Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Refactor project page to use Backbone.js.

  • Loading branch information...
commit dae8e0946d1114c14d561c7c7971473b13ec4108 1 parent ce332a2
Karthik Viswanathan authored September 04, 2012

Showing 36 changed files with 639 additions and 3,625 deletions. Show diff stats Hide diff stats

  1. 15  public/javascripts/collections/extended.js
  2. 15  public/javascripts/collections/project.js
  3. 17  public/javascripts/collections/screen.js
  4. 38  public/javascripts/controllers/extended.js
  5. 35  public/javascripts/controllers/project-list.js
  6. 127  public/javascripts/controllers/project.js
  7. 95  public/javascripts/controllers/screen-list.js
  8. 54  public/javascripts/controllers/screen.js
  9. 2  public/javascripts/helpers/errors.js
  10. 39  public/javascripts/lib/backbone.min.js
  11. 42  public/javascripts/lib/can.construct.super.js
  12. 2,994  public/javascripts/lib/can.jquery.js
  13. 1  public/javascripts/lib/can.jquery.min.js
  14. 181  public/javascripts/lib/can.observe.list.sort.js
  15. 32  public/javascripts/lib/underscore.min.js
  16. 17  public/javascripts/models/project.js
  17. 17  public/javascripts/models/screen.js
  18. 12  public/javascripts/routers/project-page.js
  19. 14  public/javascripts/scripts/index.js
  20. 0  public/javascripts/{controllers → views}/component-list.js
  21. 0  public/javascripts/{controllers → views}/component.js
  22. 0  public/javascripts/{controllers → views}/element-list.js
  23. 0  public/javascripts/{controllers → views}/element.js
  24. 113  public/javascripts/views/extended.js
  25. 0  public/javascripts/{controllers → views}/layout-modification.js
  26. 54  public/javascripts/views/project-list.js
  27. 143  public/javascripts/views/project.js
  28. 0  public/javascripts/{controllers → views}/screen-actions.js
  29. 0  public/javascripts/{controllers → views}/screen-layout.js
  30. 93  public/javascripts/views/screen-list.js
  31. 71  public/javascripts/views/screen.js
  32. 0  public/javascripts/{controllers → views}/switch.js
  33. 0  public/javascripts/{controllers → views}/window.js
  34. 5  todo.txt
  35. 7  views/templates/collections/project.jade
  36. 31  views/templates/collections/screen.jade
15  public/javascripts/collections/extended.js
... ...
@@ -0,0 +1,15 @@
  1
+define(['jquery', 'backbone'],
  2
+  function($, Backbone) {
  3
+    var ExtendedCollection = Backbone.Collection.extend({
  4
+      initialize: function(models, options) {
  5
+        this.options = options;
  6
+      },
  7
+
  8
+      constructParent: function(args) {
  9
+        args = Array.prototype.slice.call(args, 0);
  10
+        ExtendedCollection.prototype.initialize.apply(this, args);
  11
+      }
  12
+    });
  13
+
  14
+    return ExtendedCollection;
  15
+  });
15  public/javascripts/collections/project.js
... ...
@@ -0,0 +1,15 @@
  1
+define(['jquery', 'backbone', './extended', 'models/project'],
  2
+  function($, Backbone, ExtendedCollection, ProjectModel) {
  3
+    return ExtendedCollection.extend({
  4
+      url: 'projects',
  5
+      model: ProjectModel,
  6
+
  7
+      initialize: function(models, options) {
  8
+        this.constructParent(arguments);
  9
+      },
  10
+
  11
+      comparator: function(project) {
  12
+        return project.get('id');
  13
+      }
  14
+    });
  15
+  });
17  public/javascripts/collections/screen.js
... ...
@@ -0,0 +1,17 @@
  1
+define(['jquery', 'backbone', './extended', 'models/screen'],
  2
+  function($, Backbone, ExtendedCollection, ScreenModel) {
  3
+    return ExtendedCollection.extend({
  4
+      url: function() {
  5
+        return '/projects/' + this.options.projectId + '/screens';
  6
+      },
  7
+
  8
+      initialize: function(models, options) {
  9
+        this.constructParent(arguments);
  10
+      },
  11
+
  12
+      model: ScreenModel,
  13
+      comparator: function(screen) {
  14
+        return screen.get('id');
  15
+      }
  16
+    });
  17
+  });
38  public/javascripts/controllers/extended.js
... ...
@@ -1,38 +0,0 @@
1  
-define(['can', 'helpers/utils', 'helpers/screen-utils'],
2  
-  function(can, utils, screenUtils) {
3  
-  return can.Control({
4  
-    init: function($element, options) {
5  
-      this.$ = utils.bind($element.find, $element);
6  
-
7  
-      if (screenUtils.isSharePage()) {
8  
-        // no event handlers on share page
9  
-        this.off();
10  
-      }
11  
-    },
12  
-
13  
-    setElement: function($element) {
14  
-      var curControls = this.element.data('controls');
15  
-      var newControls = $element.data('controls');
16  
-
17  
-      this.off();
18  
-
19  
-      // can uses the element's controls data internally to tell what
20  
-      // controllers are attached
21  
-      if (newControls) {
22  
-        newControls.push(this);
23  
-      } else {
24  
-        $element.data('controls', [ this ]);
25  
-      }
26  
-      curControls.splice(can.inArray(this, curControls), 1);
27  
-
28  
-      // reset the element and re-bind handlers
29  
-      this.element = $element;
30  
-      if (!screenUtils.isSharePage()) {
31  
-        this.on();
32  
-      }
33  
-
34  
-      // re-add the shortcut find function
35  
-      this.$ = utils.bind($element.find, $element);
36  
-    }
37  
-  });
38  
-});
35  public/javascripts/controllers/project-list.js
... ...
@@ -1,35 +0,0 @@
1  
-define(['jquery', 'can', './extended', 'models/project', './project',
2  
-        'helpers/errors', 'can.super'],
3  
-  function($, can, ExtendedControl, ProjectModel, ProjectControl, errors) {
4  
-    can.route.ready(false);
5  
-
6  
-    return ExtendedControl({
7  
-      init: function($element, options) {
8  
-        this._super($element, options);
9  
-        var $projects = $('#projects');
10  
-
11  
-        // create a ProjectControl for each project
12  
-        ProjectModel.findAll()
13  
-          .then(function(projects) {
14  
-            can.each(projects, function(project, index) {
15  
-              new ProjectControl($projects, { project: project });
16  
-            });
17  
-
18  
-            can.route.ready(true);
19  
-          });
20  
-      },
21  
-
22  
-      // to add a project
23  
-      '#add-project-form submit': function($element, event) {
24  
-        event.preventDefault();
25  
-        var $input = $('#project-title');
26  
-
27  
-        var project = new ProjectModel({ title: $input.val() });
28  
-        project.save()
29  
-          .then(function(project) {
30  
-            new ProjectControl('#projects', { project: project });
31  
-            $input.val('');
32  
-          }, errors.tooltipHandler($input));
33  
-      }
34  
-    });
35  
-  });
127  public/javascripts/controllers/project.js
... ...
@@ -1,127 +0,0 @@
1  
-define(['can', './extended', 'helpers/errors', 'can.super'], function(can, ExtendedControl, errors) {
2  
-  return ExtendedControl({
3  
-    init: function($element, options) {
4  
-      this._super($element, options);
5  
-      this.viewData = new can.Observe(options);
6  
-      this.project = this.viewData.project;
7  
-
8  
-      $element.append(can.view('project-template', this.viewData));
9  
-      this.setElement($element.children().last());
10  
-      this.$('i').tooltip({ placement: 'bottom' });
11  
-      
12  
-      // for event handlers
13  
-      this.off();
14  
-      this.options.$sidebar = $('#sidebar');
15  
-      this.on();
16  
-    },
17  
-
18  
-    'project/:projectId route': function(data) {
19  
-      var projectId = parseInt(data.projectId, 10);
20  
-      if (this.project.attr('id') === projectId) {
21  
-        this.viewData.attr('active', 'active');
22  
-      } else {
23  
-        this.viewData.removeAttr('active');
24  
-      }
25  
-    },
26  
-
27  
-    // to begin editing a project
28  
-    '.icon-pencil click': function($element, event) {
29  
-      event.preventDefault();
30  
-      this.viewData.attr('editing', 'editing');
31  
-      
32  
-      var $edit = this.$('.edit');
33  
-      $edit.focus();
34  
-      $edit.select();
35  
-    },
36  
-
37  
-    // to edit a project
38  
-    '.edit keypress': function($element, event) {
39  
-      var self = this;
40  
-
41  
-      // enter key pressed
42  
-      if (event.which === 13) {
43  
-        self.project.attr('title', $element.val());
44  
-        self.project.save()
45  
-          .then(function(project) {
46  
-            self.viewData.removeAttr('editing');
47  
-          }, errors.tooltipHandler($element));
48  
-      }
49  
-    },
50  
-
51  
-    // to stop editing a project
52  
-    '.icon-remove click': function($element, event) {
53  
-      event.preventDefault();
54  
-      if (this.viewData.attr('editing')) {
55  
-        this.viewData.removeAttr('editing');
56  
-        this.$('.edit').val(this.project.attr('title'));
57  
-      }
58  
-    },
59  
-
60  
-    // to export a project
61  
-    '.icon-inbox click': function($element, event) {
62  
-      event.preventDefault();
63  
-      window.location.href = '/export/project/' + this.project.attr('id');
64  
-    },
65  
-
66  
-    // to delete a project
67  
-    '{$sidebar} .icon-trash click': function($element, event) {
68  
-      event.preventDefault();
69  
-      event.stopPropagation();
70  
-
71  
-      var $li = $element.closest('li');
72  
-      if ($li.is(this.element)) {
73  
-        // if this project's trash icon was clicked, open up a popover
74  
-        // confirmation dialog
75  
-        var self = this;
76  
-
77  
-        if (!this.element.data('popover')) {
78  
-          this.element.popover({
79  
-            title: 'Delete Project',
80  
-            trigger: 'manual',
81  
-            placement: 'bottom',
82  
-            content: can.view.render('#project-deletion-template', {})
83  
-          });
84  
-        }
85  
-
86  
-        this.element.popover('show');
87  
-        this.element.addClass('popover-active');
88  
-      } else if (this.element.hasClass('popover-active')) {
89  
-        // otherwise, if this project's trash icon was not clicked and it has
90  
-        // a popover currently active, hide it
91  
-        this.element.popover('hide');
92  
-        this.element.removeClass('popover-active');
93  
-      }
94  
-    },
95  
-
96  
-    '{window} .popover-content .btn-danger click': function($element, event) {
97  
-      if (this.element.hasClass('popover-active')) {
98  
-        var self = this;
99  
-
100  
-        // user has confirmed they want to delete this project
101  
-        self.project.destroy()
102  
-          .then(function(project) {
103  
-            self.element.popover('hide');
104  
-            self.element.remove();
105  
-          }, errors.tooltipHandler($element));
106  
-      }
107  
-    },
108  
-
109  
-    '{window} .close-popover click': function($element, event) {
110  
-      if (this.element.hasClass('popover-active')) {
111  
-        event.preventDefault();
112  
-        this.element.popover('hide');
113  
-      }
114  
-    },
115  
-
116  
-    '{window} click': function($element, event) {
117  
-      if (this.element.hasClass('popover-active')) {
118  
-        var $target = $(event.target);
119  
-        
120  
-        // if the click occurred outside the popover hide it
121  
-        if ($target.closest('.popover').length === 0) {
122  
-          this.element.popover('hide');
123  
-        }
124  
-      }
125  
-    }
126  
-  });
127  
-});
95  public/javascripts/controllers/screen-list.js
... ...
@@ -1,95 +0,0 @@
1  
-define(['can', './extended', 'models/screen', './screen', 'helpers/errors', 'can.super'],
2  
-  function(can, ExtendedControl, ScreenModel, ScreenControl, errors) {
3  
-    return ExtendedControl({
4  
-      init: function($element, options) {
5  
-        this._super($element, options);
6  
-        this.element.hide();
7  
-      },
8  
-
9  
-      'project/:projectId route': function(data) {
10  
-        this.element.show();
11  
-        this.projectId = data.projectId;
12  
-        this.renderAllScreens();
13  
-      },
14  
-      
15  
-      'route': function(data) {
16  
-        // revert to hidden state when empty route is triggered
17  
-        this.element.hide();
18  
-        this.projectId = null;
19  
-      },
20  
-
21  
-      numScreens: 0,
22  
-      renderAllScreens: function() {
23  
-        var self = this;
24  
-
25  
-        // create a ScreenControl for each project
26  
-        ScreenModel.findAll({ projectId: self.projectId })
27  
-          .then(function(screens) {
28  
-            self.cachedScreens = screens;
29  
-            self.clearScreens();
30  
-            self.renderEachScreen();
31  
-            self.bindListChangeEvents();
32  
-          });
33  
-      },
34  
-
35  
-      // when the screen list changes, automatically re-render display
36  
-      bindListChangeEvents: function() {
37  
-        var self = this;
38  
-        var screens = self.cachedScreens;
39  
-
40  
-        screens.bind('change', function(event, what, how, data) {
41  
-          if (how === 'remove') {
42  
-            self.clearScreens();
43  
-            self.renderEachScreen();
44  
-          }
45  
-        });
46  
-      },
47  
-
48  
-      clearScreens: function() {
49  
-        this.numScreens = 0;
50  
-        this.element.children('.screen-row').remove();
51  
-      },
52  
-
53  
-      renderEachScreen: function() {
54  
-        var self = this;
55  
-        self.cachedScreens.each(function(screen) {
56  
-          self.renderScreen(screen);
57  
-        });
58  
-      },
59  
-
60  
-      renderScreen: function(screen) {
61  
-        var self = this;
62  
-        var $screenRow;
63  
-
64  
-        // insert a new row for every four screens
65  
-        if (self.numScreens % 4 === 0) {
66  
-          self.element.append(can.view('screen-row-template'), {});
67  
-        }
68  
-
69  
-        $screenRow = self.element.children().last();
70  
-        new ScreenControl($screenRow,
71  
-          { screen: screen, projectId: self.projectId });
72  
-
73  
-        self.numScreens++;
74  
-      },
75  
-
76  
-      // to add a screen
77  
-      '#add-screen form submit': function($element, event) {
78  
-        event.preventDefault();
79  
-        var self = this;
80  
-
81  
-        var $input = $('#screen-title');
82  
-        var screen = new ScreenModel({
83  
-          projectId: self.projectId,
84  
-          title: $input.val()
85  
-        });
86  
-
87  
-        screen.save()
88  
-          .then(function(screen) {
89  
-            self.cachedScreens.push(screen);
90  
-            self.renderScreen(screen);
91  
-            $input.val('');
92  
-          }, errors.tooltipHandler($input));
93  
-      }
94  
-    });
95  
-  });
54  public/javascripts/controllers/screen.js
... ...
@@ -1,54 +0,0 @@
1  
-define(['can', './extended', 'helpers/errors', 'can.super'], function(can, ExtendedControl, errors) {
2  
-  return ExtendedControl({
3  
-    init: function($element, options) {
4  
-      this._super($element, options);
5  
-      this.viewData = new can.Observe(options);
6  
-      this.screen = this.viewData.screen;
7  
-      this.screen.attr('projectId', this.options.projectId);
8  
-
9  
-      $element.append(can.view('screen-template', this.viewData));
10  
-      this.setElement($element.find('.screen').last());
11  
-    },
12  
-
13  
-    // to begin editing a project
14  
-    '.icon-pencil click': function($element, event) {
15  
-      event.preventDefault();
16  
-      this.viewData.attr('editing', 'editing');
17  
-
18  
-      var $edit = this.$('.edit');
19  
-      $edit.focus();
20  
-      $edit.select();
21  
-    },
22  
-
23  
-    // to edit a screen
24  
-    '.edit keypress': function($element, event) {
25  
-      var self = this;
26  
-
27  
-      // enter key pressed
28  
-      if (event.which === 13) {
29  
-        self.screen.attr('title', $element.val());
30  
-        self.screen.save({ projectId: this.projectId })
31  
-          .then(function(screen) {
32  
-            self.viewData.removeAttr('editing');
33  
-          }, errors.tooltipHandler($element));
34  
-      }
35  
-    },
36  
-
37  
-    // to stop editing a screen
38  
-    '.icon-remove click': function($element, event) {
39  
-      event.preventDefault();
40  
-      if (this.viewData.attr('editing')) {
41  
-        this.viewData.removeAttr('editing');
42  
-        this.$('.edit').val(this.screen.attr('title'));
43  
-      }
44  
-    },
45  
-
46  
-    // to delete a screen
47  
-    '.icon-trash click': function($element, event) {
48  
-      event.preventDefault();
49  
-      this.screen.destroy()
50  
-        .then(function(screen) {
51  
-        }, errors.tooltipHandler($element));
52  
-    }
53  
-  });
54  
-});
2  public/javascripts/helpers/errors.js
@@ -6,7 +6,7 @@ define(['lib/bootstrap.min'], function() {
6 6
      */
7 7
     tooltipHandler: function($element, placement, howLong) {
8 8
       var self = this;
9  
-      return function(xhr) {
  9
+      return function(model, xhr) {
10 10
         self.displayTooltip($element, xhr.responseText, placement, howLong);
11 11
         $element.focus();
12 12
       };
39  public/javascripts/lib/backbone.min.js
... ...
@@ -0,0 +1,39 @@
  1
+// Backbone.js 0.9.2
  2
+
  3
+// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
  4
+// Backbone may be freely distributed under the MIT license.
  5
+// For all details and documentation:
  6
+// http://backbonejs.org
  7
+(function(h,g){typeof exports!=="undefined"?g(h,exports,require("underscore")):typeof define==="function"&&define.amd?define(["underscore","jquery","exports"],function(f,i,p){h.Backbone=g(h,p,f,i)}):h.Backbone=g(h,{},h._,h.jQuery||h.Zepto||h.ender)})(this,function(h,g,f,i){var p=h.Backbone,y=Array.prototype.slice,z=Array.prototype.splice;g.VERSION="0.9.2";g.setDomLibrary=function(a){i=a};g.noConflict=function(){h.Backbone=p;return g};g.emulateHTTP=false;g.emulateJSON=false;var q=/\s+/,l=g.Events=
  8
+{on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(q);for(d=this._callbacks||(this._callbacks={});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,k,g,j,h;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(q):f.keys(e);d=a.shift();)if(k=e[d],delete e[d],k&&(b||c))for(g=k.tail;(k=k.next)!==g;)if(j=k.callback,h=k.context,b&&j!==b||c&&h!==c)this.on(d,j,h);return this}},
  9
+trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(q);for(g=y.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};l.bind=l.on;l.unbind=l.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);if(b&&b.collection)this.collection=b.collection;
  10
+this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent={};this._pending={};this.set(a,{silent:true});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,l,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;
  11
+if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(b==null?"":""+b)},has:function(a){return this.get(a)!=null},set:function(a,b,c){var d,e;f.isObject(a)||a==null?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;if(d instanceof o)d=d.attributes;if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return false;if(this.idAttribute in d)this.id=d[this.idAttribute];var b=c.changes={},g=this.attributes,h=this._escapedAttributes,j=this._previousAttributes||
  12
+{};for(e in d){a=d[e];if(!f.isEqual(g[e],a)||c.unset&&f.has(g,e))delete h[e],(c.silent?this._silent:b)[e]=true;c.unset?delete g[e]:g[e]=a;!f.isEqual(j[e],a)||f.has(g,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=true)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=true;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=true;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=
  13
+a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return false;c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||a==null?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return false;e=f.clone(this.attributes)}a=f.extend({},c,{silent:true});if(d&&!this.set(d,c.wait?a:c))return false;var k=this,h=c.success;c.success=function(a,b,e){b=k.parse(a,e);
  14
+c.wait&&(delete c.wait,b=f.extend(d||{},b));if(!k.set(b,c))return false;h?h(k,a):k.trigger("sync",k,a,c)};c.error=g.wrapError(c.error,k,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),false;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||
  15
+g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();return this.isNew()?a:a+(a.charAt(a.length-1)=="/"?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return this.id==null},change:function(a){a||(a={});var b=this._changing;this._changing=true;for(var c in this._silent)this._pending[c]=true;var d=f.extend({},a.changes,this._silent);
  16
+this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending={};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=false;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):
  17
+false;var b,c=false,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return true;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return true;b&&b.error?
  18
+b.error(this,c,b):this.trigger("error",this,c,b);return false}});var r=g.Collection=function(a,b){b||(b={});if(b.model)this.model=b.model;if(b.comparator)this.comparator=b.comparator;this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:true,parse:b.parse})};f.extend(r.prototype,l,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,h,j={},i={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];for(c=0,d=
  19
+a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error("Can't add an invalid model to a collection");g=e.cid;h=e.id;j[g]||this._byCid[g]||h!=null&&(i[h]||this._byId[h])?l.push(c):j[g]=i[h]=e}for(c=l.length;c--;)a.splice(l[c],1);for(c=0,d=a.length;c<d;c++)(e=a[c]).on("all",this._onModelEvent,this),this._byCid[e.cid]=e,e.id!=null&&(this._byId[e.id]=e);this.length+=d;z.apply(this.models,[b.at!=null?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:true});if(b.silent)return this;
  20
+for(c=0,d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger("add",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?a.slice():[a];for(c=0,d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c])){delete this._byId[g.id];delete this._byCid[g.cid];e=this.indexOf(g);this.models.splice(e,1);this.length--;if(!b.silent)b.index=e,g.trigger("remove",g,this,b);this._removeReference(g)}return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,
  21
+b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},shift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return a==null?void 0:this._byId[a.id!=null?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return false;
  22
+return true})},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");var b=f.bind(this.comparator,this);this.comparator.length==1?this.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:true},
  23
+b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?f.clone(a):{};if(a.parse===void 0)a.parse=true;var b=this,c=a.success;a.success=function(d,e,f){b[a.add?"add":"reset"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return false;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger("sync",
  24
+a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId={};this._byCid={}},_prepareModel:function(a,b){b||(b={});if(a instanceof o){if(!a.collection)a.collection=this}else{var c;b.collection=this;a=new this.model(a,b);a._validate(a.attributes,b)||(a=false)}return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,
  25
+b,c,d){(a=="add"||a=="remove")&&c!=this||(a=="destroy"&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,arguments))}});f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","),function(a){r.prototype[a]=function(){return f[a].apply(f,
  26
+[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});if(a.routes)this.routes=a.routes;this._bindRoutes();this.initialize.apply(this,arguments)},A=/:\w+/g,B=/\*\w+/g,C=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(u.prototype,l,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+
  27
+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(C,"\\$&").replace(A,"([^/]+)").replace(B,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=
  28
+[];f.bindAll(this,"checkUrl")},s=/^[#\/]/,D=/msie [\w.]+/;m.started=false;f.extend(m.prototype,l,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:""},getFragment:function(a,b){if(a==null)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,"")},start:function(a){if(m.started)throw Error("Backbone.history has already been started");
  29
+m.started=true;this.options=f.extend({},{root:"/"},this.options,a);this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=D.exec(navigator.userAgent.toLowerCase())&&(!b||b<=7))this.iframe=i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);if(this._hasPushState)i(window).bind("popstate",
  30
+this.checkUrl);else if(this._wantsHashChange&&"onhashchange"in window&&!b)i(window).bind("hashchange",this.checkUrl);else if(this._wantsHashChange)this._checkUrlInterval=setInterval(this.checkUrl,this.interval);this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,true),window.location.replace(this.options.root+"#"+this.fragment),true;else if(this._wantsPushState&&this._hasPushState&&
  31
+b&&a.hash)this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment);if(!this.options.silent)return this.loadUrl()},stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=false},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));
  32
+if(a==this.fragment)return false;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),true})},navigate:function(a,b){if(!m.started)return false;if(!b||b===true)b={trigger:b};var c=(a||"").replace(s,"");if(this.fragment!=c)this._hasPushState?(c.indexOf(this.options.root)!=0&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?
  33
+"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a)},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid=
  34
+f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},E=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");f.extend(v.prototype,l,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c!=null&&i(a).html(c);return a},setElement:function(a,
  35
+b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];b!==false&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(E),e=d[1],d=d[2],c=f.bind(c,this);e+=".delegateEvents"+this.cid;d===""?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+
  36
+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,false);else{var a=n(this,"attributes")||{};if(this.id)a.id=this.id;if(this.className)a["class"]=this.className;this.setElement(this.make(this.tagName,a),false)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=F(this,a,b);c.extend=this.extend;return c};var G={create:"POST",
  37
+update:"PUT","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=G[a];c||(c={});var e={type:d,dataType:"json"};if(!c.url)e.url=n(b,"url")||t();if(!c.data&&b&&(a=="create"||a=="update"))e.contentType="application/json",e.data=JSON.stringify(b.toJSON());if(g.emulateJSON)e.contentType="application/x-www-form-urlencoded",e.data=e.data?{model:e.data}:{};if(g.emulateHTTP&&(d==="PUT"||d==="DELETE")){if(g.emulateJSON)e.data._method=d;e.type="POST";e.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",
  38
+d)}}if(e.type!=="GET"&&!g.emulateJSON)e.processData=false;return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger("error",b,e,c)}};var x=function(){},F=function(a,b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||
  39
+!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A "url" property or function must be specified');};return g});
42  public/javascripts/lib/can.construct.super.js
... ...
@@ -1,42 +0,0 @@
1  
-define(['can'], function(can) {
2  
-  // tests if we can get super in .toString()
3  
-	var isFunction = can.isFunction,
4  
-		
5  
-		fnTest = /xyz/.test(function() {
6  
-			xyz;
7  
-		}) ? /\b_super\b/ : /.*/;
8  
-		
9  
-		// overwrites a single property so it can still call super
10  
-		can.Construct._overwrite = function(addTo, base, name, val){
11  
-			// Check if we're overwriting an existing function
12  
-			addTo[name] = isFunction(val) && 
13  
-						isFunction(base[name]) && 
14  
-						fnTest.test(val) ? (function( name, fn ) {
15  
-					return function() {
16  
-						var tmp = this._super,
17  
-							ret;
18  
-
19  
-						// Add a new ._super() method that is the same method
20  
-						// but on the super-class
21  
-						this._super = base[name];
22  
-
23  
-						// The method only need to be bound temporarily, so we
24  
-						// remove it when we're done executing
25  
-						ret = fn.apply(this, arguments);
26  
-						this._super = tmp;
27  
-						return ret;
28  
-					};
29  
-				})(name, val) : val;
30  
-		};
31  
-
32  
-		// overwrites an object with methods, sets up _super
33  
-		//   newProps - new properties
34  
-		//   oldProps - where the old properties might be
35  
-		//   addTo - what we are adding to
36  
-		can.Construct._inherit = function( newProps, oldProps, addTo ) {
37  
-			addTo = addTo || newProps;
38  
-			for ( var name in newProps ) {
39  
-				can.Construct._overwrite(addTo, oldProps, name, newProps[name]);
40  
-			}
41  
-		};
42  
-});
2,994  public/javascripts/lib/can.jquery.js
... ...
@@ -1,2994 +0,0 @@
1  
-define(['jquery'], function(jQuery) {
2  
-// # CanJS v1.0.7
3  
-
4  
-// (c) 2012 Bitovi  
5  
-// MIT license  
6  
-// [http://canjs.us/](http://canjs.us/)
7  
-  window.can = {};
8  
-
9  
-	// jquery.js
10  
-	// ---------
11  
-	// _jQuery node list._
12  
-	$.extend( can, jQuery, {
13  
-		trigger: function( obj, event, args ) {
14  
-			obj.trigger ?
15  
-				obj.trigger( event, args ) :
16  
-				$.event.trigger( event, args, obj, true );
17  
-		},
18  
-		addEvent: function(ev, cb){
19  
-			$([this]).bind(ev, cb)
20  
-			return this;
21  
-		},
22  
-		removeEvent: function(ev, cb){
23  
-			$([this]).unbind(ev, cb)
24  
-			return this;
25  
-		},
26  
-		// jquery caches fragments, we always needs a new one
27  
-		buildFragment : function(result, element){
28  
-			var ret = $.buildFragment([result],[element]);
29  
-			return ret.cacheable ? $.clone(ret.fragment) : ret.fragment
30  
-		},
31  
-		$: jQuery
32  
-	});
33  
-
34  
-	// Wrap binding functions.
35  
-	$.each(['bind','unbind','undelegate','delegate'],function(i,func){
36  
-		can[func] = function(){
37  
-			var t = this[func] ? this : $([this])
38  
-			t[func].apply(t, arguments)
39  
-			return this;
40  
-		}
41  
-	})
42  
-
43  
-	// Wrap modifier functions.
44  
-	$.each(["append","filter","addClass","remove","data","get"], function(i,name){
45  
-		can[name] = function(wrapped){
46  
-			return wrapped[name].apply(wrapped, can.makeArray(arguments).slice(1))
47  
-		}
48  
-	})
49  
-
50  
-	// Memory safe destruction.
51  
-	var oldClean = $.cleanData;
52  
-
53  
-	$.cleanData = function( elems ) {
54  
-		$.each( elems, function( i, elem ) {
55  
-			can.trigger(elem,"destroyed",[],false)
56  
-		});
57  
-		oldClean(elems);
58  
-	};
59  
-
60  
-	can.each = function (elements, callback, context) {
61  
-		var i = 0,
62  
-		    key;
63  
-		if (elements) {
64  
-			if (typeof elements.length == 'number' && elements.pop) {
65  
-				elements.attr && elements.attr('length');
66  
-				for (var len = elements.length; i < len; i++) {
67  
-					if (callback.call(context || elements[i], elements[i], i, elements) === false) {
68  
-						break;
69  
-					}
70  
-				}
71  
-			} else {
72  
-				for (key in elements) {
73  
-					if (callback.call(context || elements[i], elements[key], key, elements) === false) {
74  
-						break;
75  
-					}
76  
-				}
77  
-			}
78  
-		}
79  
-		return elements;
80  
-	}
81  
-;
82  
-
83  
-	// ##string.js
84  
-	// _Miscellaneous string utility functions._  
85  
-	
86  
-	// Several of the methods in this plugin use code adapated from Prototype
87  
-	// Prototype JavaScript framework, version 1.6.0.1.
88  
-	// © 2005-2007 Sam Stephenson
89  
-	var undHash     = /_|-/,
90  
-		colons      = /==/,
91  
-		words       = /([A-Z]+)([A-Z][a-z])/g,
92  
-		lowUp       = /([a-z\d])([A-Z])/g,
93  
-		dash        = /([a-z\d])([A-Z])/g,
94  
-		replacer    = /\{([^\}]+)\}/g,
95  
-		quote       = /"/g,
96  
-		singleQuote = /'/g,
97  
-
98  
-		// Returns the `prop` property from `obj`.
99  
-		// If `add` is true and `prop` doesn't exist in `obj`, create it as an 
100  
-		// empty object.
101  
-		getNext = function( obj, prop, add ) {
102  
-			return prop in obj ?
103  
-				obj[ prop ] : 
104  
-				( add && ( obj[ prop ] = {} ));
105  
-		},
106  
-
107  
-		// Returns `true` if the object can have properties (no `null`s).
108  
-		isContainer = function( current ) {
109  
-			return /^f|^o/.test( typeof current );
110  
-		};
111  
-
112  
-		can.extend(can, {
113  
-			// Escapes strings for HTML.
114  
-						esc : function( content ) {
115  
-				return ( "" + content )
116  
-					.replace(/&/g, '&amp;')
117  
-					.replace(/</g, '&lt;')
118  
-					.replace(/>/g, '&gt;')
119  
-					.replace(quote, '&#34;')
120  
-					.replace(singleQuote, "&#39;");
121  
-			},
122  
-			
123  
-						getObject : function( name, roots, add ) {
124  
-			
125  
-				// The parts of the name we are looking up  
126  
-				// `['App','Models','Recipe']`
127  
-				var parts = name ? name.split('.') : [],
128  
-					length =  parts.length,
129  
-					current,
130  
-					r = 0,
131  
-					ret, i;
132  
-				
133  
-				// Make sure roots is an `array`.
134  
-				roots = can.isArray(roots) ? roots : [roots || window];
135  
-				
136  
-				if ( ! length ) {
137  
-					return roots[0];
138  
-				}
139  
-
140  
-				// For each root, mark it as current.
141  
-				while( current = roots[r++] ) {
142  
-
143  
-					// Walk current to the 2nd to last object or until there 
144  
-					// is not a container.
145  
-					for (i =0; i < length - 1 && isContainer( current ); i++ ) {
146  
-						current = getNext( current, parts[i], add );
147  
-					}
148  
-
149  
-					// If we can get a property from the 2nd to last object...
150  
-					if( isContainer(current) ) {
151  
-						
152  
-						// Get (and possibly set) the property.
153  
-						ret = getNext(current, parts[i], add); 
154  
-						
155  
-						// If there is a value, we exit.
156  
-						if ( ret !== undefined ) {
157  
-							// If `add` is `false`, delete the property
158  
-							if ( add === false ) {
159  
-								delete current[parts[i]];
160  
-							}
161  
-							return ret;
162  
-							
163  
-						}
164  
-					}
165  
-				}
166  
-			},
167  
-			// Capitalizes a string.
168  
-						capitalize: function( s, cache ) {
169  
-				// Used to make newId.
170  
-				return s.charAt(0).toUpperCase() + s.slice(1);
171  
-			},
172  
-			
173  
-			// Underscores a string.
174  
-						underscore: function( s ) {
175  
-				return s
176  
-					.replace(colons, '/')
177  
-					.replace(words, '$1_$2')
178  
-					.replace(lowUp, '$1_$2')
179  
-					.replace(dash, '_')
180  
-					.toLowerCase();
181  
-			},
182  
-			// Micro-templating.
183  
-						sub: function( str, data, remove ) {
184  
-
185  
-				var obs = [];
186  
-
187  
-				obs.push( str.replace( replacer, function( whole, inside ) {
188  
-
189  
-					// Convert inside to type.
190  
-					var ob = can.getObject( inside, data, remove === undefined? remove : !remove );
191  
-					
192  
-					// If a container, push into objs (which will return objects found).
193  
-					if ( isContainer( ob ) ) {
194  
-						obs.push( ob );
195  
-						return "";
196  
-					} else {
197  
-						return "" + ob;
198  
-					}
199  
-				}));
200  
-				
201  
-				return obs.length <= 1 ? obs[0] : obs;
202  
-			},
203  
-
204  
-			// These regex's are used throughout the rest of can, so let's make
205  
-			// them available.
206  
-			replacer : replacer,
207  
-			undHash : undHash
208  
-		});
209  
-
210  
-	// ## construct.js
211  
-	// `can.Construct`  
212  
-	// _This is a modified version of
213  
-	// [John Resig's class](http://ejohn.org/blog/simple-javascript-inheritance/).  
214  
-	// It provides class level inheritance and callbacks._
215  
-	
216  
-	// A private flag used to initialize a new class instance without
217  
-	// initializing it's bindings.
218  
-	var initializing = 0;
219  
-
220  
-		can.Construct = function() {
221  
-		if (arguments.length) {
222  
-			return can.Construct.extend.apply(can.Construct, arguments);
223  
-		}
224  
-	};
225  
-
226  
-		can.extend(can.Construct, {
227  
-				newInstance: function() {
228  
-			// Get a raw instance object (`init` is not called).
229  
-			var inst = this.instance(),
230  
-				arg = arguments,
231  
-				args;
232  
-				
233  
-			// Call `setup` if there is a `setup`
234  
-			if ( inst.setup ) {
235  
-				args = inst.setup.apply(inst, arguments);
236  
-			}
237  
-
238  
-			// Call `init` if there is an `init`  
239  
-			// If `setup` returned `args`, use those as the arguments
240  
-			if ( inst.init ) {
241  
-				inst.init.apply(inst, args || arguments);
242  
-			}
243  
-
244  
-			return inst;
245  
-		},
246  
-		// Overwrites an object with methods. Used in the `super` plugin.
247  
-		// `newProps` - New properties to add.  
248  
-		// `oldProps` - Where the old properties might be (used with `super`).  
249  
-		// `addTo` - What we are adding to.
250  
-		_inherit: function( newProps, oldProps, addTo ) {
251  
-			can.extend(addTo || newProps, newProps || {})
252  
-		},
253  
-		// used for overwriting a single property.
254  
-		// this should be used for patching other objects
255  
-		// the super plugin overwrites this
256  
-		_overwrite : function(what, oldProps, propName, val){
257  
-			what[propName] = val;
258  
-		},
259  
-		// Set `defaults` as the merger of the parent `defaults` and this 
260  
-		// object's `defaults`. If you overwrite this method, make sure to
261  
-		// include option merging logic.
262  
-				setup: function( base, fullName ) {
263  
-			this.defaults = can.extend(true,{}, base.defaults, this.defaults);
264  
-		},
265  
-		// Create's a new `class` instance without initializing by setting the
266  
-		// `initializing` flag.
267  
-		instance: function() {
268  
-
269  
-			// Prevents running `init`.
270  
-			initializing = 1;
271  
-
272  
-			var inst = new this();
273  
-
274  
-			// Allow running `init`.
275  
-			initializing = 0;
276  
-
277  
-			return inst;
278  
-		},
279  
-		// Extends classes.
280  
-				extend: function( fullName, klass, proto ) {
281  
-			// Figure out what was passed and normalize it.
282  
-			if ( typeof fullName != 'string' ) {
283  
-				proto = klass;
284  
-				klass = fullName;
285  
-				fullName = null;
286  
-			}
287  
-
288  
-			if ( ! proto ) {
289  
-				proto = klass;
290  
-				klass = null;
291  
-			}
292  
-			proto = proto || {};
293  
-
294  
-			var _super_class = this,
295  
-				_super = this.prototype,
296  
-				name, shortName, namespace, prototype;
297  
-
298  
-			// Instantiate a base class (but only create the instance,
299  
-			// don't run the init constructor).
300  
-			prototype = this.instance();
301  
-			
302  
-			// Copy the properties over onto the new prototype.
303  
-			can.Construct._inherit(proto, _super, prototype);
304  
-
305  
-			// The dummy class constructor.
306  
-			function Constructor() {
307  
-				// All construction is actually done in the init method.
308  
-				if ( ! initializing ) {
309  
-					return this.constructor !== Constructor && arguments.length ?
310  
-						// We are being called without `new` or we are extending.
311  
-						arguments.callee.extend.apply(arguments.callee, arguments) :
312  
-						// We are being called with `new`.
313  
-						this.constructor.newInstance.apply(this.constructor, arguments);
314  
-				}
315  
-			}
316  
-
317  
-			// Copy old stuff onto class (can probably be merged w/ inherit)
318  
-			for ( name in _super_class ) {
319  
-				if ( _super_class.hasOwnProperty(name) ) {
320  
-					Constructor[name] = _super_class[name];
321  
-				}
322  
-			}
323  
-
324  
-			// Copy new static properties on class.
325  
-			can.Construct._inherit(klass, _super_class, Constructor);
326  
-
327  
-			// Setup namespaces.
328  
-			if ( fullName ) {
329  
-
330  
-				var parts = fullName.split('.'),
331  
-					shortName = parts.pop(),
332  
-					current = can.getObject(parts.join('.'), window, true),
333  
-					namespace = current,
334  
-					_fullName = can.underscore(fullName.replace(/\./g, "_")),
335  
-					_shortName = can.underscore(shortName);
336  
-
337  
-				//@steal-remove-start
338  
-				if(current[shortName]){
339  
-					
340  
-				}
341  
-				//@steal-remove-end
342  
-				
343  
-				current[shortName] = Constructor;
344  
-			}
345  
-
346  
-			// Set things that shouldn't be overwritten.
347  
-			can.extend(Constructor, {
348  
-				constructor: Constructor,
349  
-				prototype: prototype,
350  
-								namespace: namespace,
351  
-								shortName: shortName,
352  
-				_shortName : _shortName,
353  
-								fullName: fullName,
354  
-				_fullName: _fullName
355  
-			});
356  
-
357  
-			// Make sure our prototype looks nice.
358  
-			Constructor.prototype.constructor = Constructor;
359  
-
360  
-			
361  
-			// Call the class `setup` and `init`
362  
-			var t = [_super_class].concat(can.makeArray(arguments)),
363  
-				args = Constructor.setup.apply(Constructor, t );
364  
-			
365  
-			if ( Constructor.init ) {
366  
-				Constructor.init.apply(Constructor, args || t );
367  
-			}
368  
-
369  
-						return Constructor;
370  
-						//  
371  
-						//  
372  
-					}
373  
-
374  
-	});
375  
-
376  
-	// ## observe.js  
377  
-	// `can.Observe`  
378  
-	// _Provides the observable pattern for JavaScript Objects._  
379  
-	//  
380  
-	// Returns `true` if something is an object with properties of its own.
381  
-	var canMakeObserve = function( obj ) {
382  
-			return obj && typeof obj === 'object' && !(obj instanceof Date);
383  
-		},
384  
-
385  
-		// Removes all listeners.
386  
-		unhookup = function(items, namespace){
387  
-			return can.each(items, function(item){
388  
-				if(item && item.unbind){
389  
-					item.unbind("change" + namespace);
390  
-				}
391  
-			});
392  
-		},
393  
-		// Listens to changes on `val` and "bubbles" the event up.  
394  
-		// `val` - The object to listen for changes on.  
395  
-		// `prop` - The property name is at on.  
396  
-		// `parent` - The parent object of prop.  
397  
-		hookupBubble = function( val, prop, parent ) {
398  
-			// If it's an `array` make a list, otherwise a val.
399  
-			if (val instanceof Observe){
400  
-				// We have an `observe` already...
401  
-				// Make sure it is not listening to this already
402  
-				unhookup([val], parent._namespace);
403  
-			} else if ( can.isArray(val) ) {
404  
-				val = new Observe.List(val);
405  
-			} else {
406  
-				val = new Observe(val);
407  
-			}
408  
-			
409  
-			// Listen to all changes and `batchTrigger` upwards.
410  
-			val.bind("change" + parent._namespace, function( ev, attr ) {
411  
-				// `batchTrigger` the type on this...
412  
-				var args = can.makeArray(arguments),
413  
-					ev = args.shift();
414  
-					args[0] = prop === "*" ? 
415  
-						parent.indexOf(val)+"." + args[0] :
416  
-						prop +  "." + args[0];
417  
-				// track objects dispatched on this observe		
418  
-				ev.triggeredNS = ev.triggeredNS || {};
419  
-				// if it has already been dispatched exit
420  
-				if (ev.triggeredNS[parent._namespace]) {
421  
-					return;
422  
-				}
423  
-				ev.triggeredNS[parent._namespace] = true;
424  
-						
425  
-				can.trigger(parent, ev, args);
426  
-				can.trigger(parent,args[0],args);
427  
-			});
428  
-
429  
-			return val;
430  
-		},
431  
-		
432  
-		// An `id` to track events for a given observe.
433  
-		observeId = 0,
434  
-		// A reference to an `array` of events that will be dispatched.
435  
-		collecting = undefined,
436  
-		// Call to start collecting events (`Observe` sends all events at
437  
-		// once).
438  
-		collect = function() {
439  
-			if (!collecting ) {
440  
-				collecting = [];
441  
-				return true;
442  
-			}
443  
-		},
444  
-		// Creates an event on item, but will not send immediately 
445  
-		// if collecting events.  
446  
-		// `item` - The item the event should happen on.  
447  
-		// `event` - The event name, ex: `change`.  
448  
-		// `args` - Tn array of arguments.
449  
-		batchTrigger = function( item, event, args ) {
450  
-			// Don't send events if initalizing.
451  
-			if ( ! item._init) {
452  
-				if (!collecting ) {
453  
-					return can.trigger(item, event, args);
454  
-				} else {
455  
-					collecting.push([
456  
-					item,
457  
-					{
458  
-						type: event,
459  
-						batchNum : batchNum
460  
-					}, 
461  
-					args ] );
462  
-				}
463  
-			}
464  
-		},
465  
-		// Which batch of events this is for -- might not want to send multiple
466  
-		// messages on the same batch.  This is mostly for event delegation.
467  
-		batchNum = 1,
468  
-		// Sends all pending events.
469  
-		sendCollection = function() {
470  
-			var items = collecting.slice(0);
471  
-			collecting = undefined;
472  
-			batchNum++;
473  
-			can.each(items, function( item ) {
474  
-				can.trigger.apply(can, item)
475  
-			})
476  
-			
477  
-		},
478  
-		// A helper used to serialize an `Observe` or `Observe.List`.  
479  
-		// `observe` - The observable.  
480  
-		// `how` - To serialize with `attr` or `serialize`.  
481  
-		// `where` - To put properties, in an `{}` or `[]`.
482  
-		serialize = function( observe, how, where ) {
483  
-			// Go through each property.
484  
-			observe.each(function( val, name ) {
485  
-				// If the value is an `object`, and has an `attrs` or `serialize` function.
486  
-				where[name] = canMakeObserve(val) && can.isFunction( val[how] ) ?
487  
-				// Call `attrs` or `serialize` to get the original data back.
488  
-				val[how]() :
489  
-				// Otherwise return the value.
490  
-				val
491  
-			})
492  
-			return where;
493  
-		},
494  
-		$method = function( name ) {
495  
-			return function() {
496  
-				return can[name].apply(this, arguments );
497  
-			}
498  
-		},
499  
-		bind = $method('addEvent'),
500  
-		unbind = $method('removeEvent'),
501  
-		attrParts = function(attr){
502  
-			return can.isArray(attr) ? attr : (""+attr).split(".")
503  
-		};
504  
-		var Observe = can.Construct('can.Observe', {
505  
-		// keep so it can be overwritten
506  
-		setup : function(){
507  
-			can.Construct.setup.apply(this, arguments)
508  
-		},
509  
-		bind : bind,
510  
-		unbind: unbind,
511  
-		id: "id"
512  
-	},
513  
-		{
514  
-		setup: function( obj ) {
515  
-			// `_data` is where we keep the properties.
516  
-			this._data = {};
517  
-			// The namespace this `object` uses to listen to events.
518  
-			this._namespace = ".observe" + (++observeId);
519  
-			// Sets all `attrs`.
520  
-			this._init = 1;
521  
-			this.attr(obj);
522  
-			delete this._init;
523  
-		},
524  
-				attr: function( attr, val ) {
525  
-			// This is super obfuscated for space -- basically, we're checking
526  
-			// if the type of the attribute is not a `number` or a `string`.
527  
-			if ( !~ "ns".indexOf((typeof attr).charAt(0))) {
528  
-				return this._attrs(attr, val)
529  
-			} else if ( val === undefined ) {// If we are getting a value.
530  
-				// Let people know we are reading.
531  
-				Observe.__reading && Observe.__reading(this, attr)
532  
-				return this._get(attr)
533  
-			} else {
534  
-				// Otherwise we are setting.
535  
-				this._set(attr, val);
536  
-				return this;
537  
-			}
538  
-		},
539  
-				each: function() {
540  
-			return can.each.apply(undefined, [this.__get()].concat(can.makeArray(arguments)))
541  
-		},
542  
-				removeAttr: function( attr ) {
543  
-			// Convert the `attr` into parts (if nested).
544  
-			var parts = attrParts(attr),
545  
-				// The actual property to remove.
546  
-				prop = parts.shift(),
547  
-				// The current value.
548  
-				current = this._data[prop];
549  
-
550  
-			// If we have more parts, call `removeAttr` on that part.
551  
-			if ( parts.length ) {
552  
-				return current.removeAttr(parts)
553  
-			} else {
554  
-				// Otherwise, `delete`.
555  
-				delete this._data[prop];
556  
-				// Create the event.
557  
-				if (!(prop in this.constructor.prototype)) {
558  
-					delete this[prop]
559  
-				}
560  
-				batchTrigger(this, "change", [prop, "remove", undefined, current]);
561  
-				batchTrigger(this, prop, [undefined, current]);
562  
-				return current;
563  
-			}
564  
-		},
565  
-		// Reads a property from the `object`.
566  
-		_get: function( attr ) {
567  
-			var parts = attrParts(attr),
568  
-				current = this.__get(parts.shift());
569  
-			return parts.length ? current ? current._get(parts) : undefined : current;
570  
-		},
571  
-		// Reads a property directly if an `attr` is provided, otherwise
572  
-		// returns the "real" data object itself.
573  
-		__get: function( attr ) {
574  
-			return attr ? this._data[attr] : this._data;
575  
-		},
576  
-		// Sets `attr` prop as value on this object where.
577  
-		// `attr` - Is a string of properties or an array  of property values.
578  
-		// `value` - The raw value to set.
579  
-		_set: function( attr, value ) {
580  
-			// Convert `attr` to attr parts (if it isn't already).
581  
-			var parts = attrParts(attr),
582  
-				// The immediate prop we are setting.
583  
-				prop = parts.shift(),
584  
-				// The current value.
585  
-				current = this.__get(prop);
586  
-