tableling-rails 0.0.18 → 0.0.19

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.
@@ -2,11 +2,12 @@
2
2
  module Tableling
3
3
 
4
4
  class Field
5
- attr_reader :name
5
+ attr_accessor :name, :alias
6
6
 
7
7
  def initialize name, view, options = {}, &block
8
8
 
9
9
  @name, @view = name.to_s, view
10
+ @alias = options[:as].try :to_s
10
11
  @value_column = options[:value].try :to_s
11
12
  @includes = options[:includes]
12
13
 
@@ -19,6 +20,14 @@ module Tableling
19
20
  instance_eval &block if block
20
21
  end
21
22
 
23
+ def working_name
24
+ @alias || @name
25
+ end
26
+
27
+ def as name
28
+ @alias = name.to_s
29
+ end
30
+
22
31
  def order &block
23
32
  @order_block = block
24
33
  end
@@ -1,3 +1,3 @@
1
1
  module Tableling
2
- VERSION = "0.0.18"
2
+ VERSION = "0.0.19"
3
3
  end
@@ -42,22 +42,34 @@ module Tableling
42
42
  if options[:sort].present?
43
43
  options[:sort].select{ |item| item.match /\A([^ ]+)* (asc|desc)\Z/i }.each do |item|
44
44
  parts = item.split ' '
45
- f = field parts[0]
45
+ # TODO: handle unknown fields
46
+ f = @fields.find{ |f| f.working_name.to_s == parts[0] }
46
47
  q = f.with_order q, parts[1].downcase.to_sym if f
47
48
  end
48
49
  end
49
50
 
50
51
  @fields.each{ |f| q = f.with_includes q }
51
52
 
52
- limit = options[:pageSize].to_i
53
- limit = 10 if limit <= 0
54
- q = q.limit limit
53
+ response_options = {
54
+ total: total
55
+ }
56
+
57
+ page_size = options[:pageSize].to_i
58
+ page_size = 10 if page_size <= 0
59
+ q = q.limit page_size
60
+
61
+ max_page = (total.to_f / page_size).ceil
62
+ page = options[:page].to_i
55
63
 
56
- offset = options[:page].to_i - 1
57
- offset = 0 if offset < 0
58
- q = q.offset offset * limit
64
+ # TODO: allow this to be disabled
65
+ if page < 1 or page > max_page
66
+ page = 1
67
+ response_options[:page] = 1
68
+ end
69
+
70
+ q = q.offset (page - 1) * page_size
59
71
 
60
- serialize_response total, q
72
+ serialize_response q, response_options
61
73
  end
62
74
 
63
75
  class DSL
@@ -86,12 +98,9 @@ module Tableling
86
98
 
87
99
  private
88
100
 
89
- def serialize_response total, query
101
+ def serialize_response query, response_options = {}
90
102
 
91
- res = {
92
- total: total,
93
- data: query.all
94
- }
103
+ res = response_options.merge data: query.all
95
104
 
96
105
  if @serialize_response_block
97
106
  @serialize_response_block.call res
@@ -1572,7 +1572,7 @@
1572
1572
 
1573
1573
  // Backbone.BabySitter
1574
1574
  // -------------------
1575
- // v0.0.5
1575
+ // v0.0.6
1576
1576
  //
1577
1577
  // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
1578
1578
  // Distributed under MIT license
@@ -1590,14 +1590,13 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1590
1590
  // Container Constructor
1591
1591
  // ---------------------
1592
1592
 
1593
- var Container = function(initialViews){
1593
+ var Container = function(views){
1594
1594
  this._views = {};
1595
1595
  this._indexByModel = {};
1596
- this._indexByCollection = {};
1597
1596
  this._indexByCustom = {};
1598
1597
  this._updateLength();
1599
1598
 
1600
- this._addInitialViews(initialViews);
1599
+ _.each(views, this.add, this);
1601
1600
  };
1602
1601
 
1603
1602
  // Container Methods
@@ -1607,7 +1606,7 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1607
1606
 
1608
1607
  // Add a view to this container. Stores the view
1609
1608
  // by `cid` and makes it searchable by the model
1610
- // and/or collection of the view. Optionally specify
1609
+ // cid (and model itself). Optionally specify
1611
1610
  // a custom key to store an retrieve the view.
1612
1611
  add: function(view, customIndex){
1613
1612
  var viewCid = view.cid;
@@ -1620,11 +1619,6 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1620
1619
  this._indexByModel[view.model.cid] = viewCid;
1621
1620
  }
1622
1621
 
1623
- // index it by collection
1624
- if (view.collection){
1625
- this._indexByCollection[view.collection.cid] = viewCid;
1626
- }
1627
-
1628
1622
  // index by custom
1629
1623
  if (customIndex){
1630
1624
  this._indexByCustom[customIndex] = viewCid;
@@ -1634,18 +1628,16 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1634
1628
  },
1635
1629
 
1636
1630
  // Find a view by the model that was attached to
1637
- // it. Uses the model's `cid` to find it, and
1638
- // retrieves the view by it's `cid` from the result
1631
+ // it. Uses the model's `cid` to find it.
1639
1632
  findByModel: function(model){
1640
- var viewCid = this._indexByModel[model.cid];
1641
- return this.findByCid(viewCid);
1633
+ return this.findByModelCid(model.cid);
1642
1634
  },
1643
1635
 
1644
- // Find a view by the collection that was attached to
1645
- // it. Uses the collection's `cid` to find it, and
1646
- // retrieves the view by it's `cid` from the result
1647
- findByCollection: function(col){
1648
- var viewCid = this._indexByCollection[col.cid];
1636
+ // Find a view by the `cid` of the model that was attached to
1637
+ // it. Uses the model's `cid` to find the view `cid` and
1638
+ // retrieve the view using it.
1639
+ findByModelCid: function(modelCid){
1640
+ var viewCid = this._indexByModel[modelCid];
1649
1641
  return this.findByCid(viewCid);
1650
1642
  },
1651
1643
 
@@ -1675,26 +1667,13 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1675
1667
  delete this._indexByModel[view.model.cid];
1676
1668
  }
1677
1669
 
1678
- // delete collection index
1679
- if (view.collection){
1680
- delete this._indexByCollection[view.collection.cid];
1681
- }
1682
-
1683
1670
  // delete custom index
1684
- var cust;
1685
-
1686
- for (var key in this._indexByCustom){
1687
- if (this._indexByCustom.hasOwnProperty(key)){
1688
- if (this._indexByCustom[key] === viewCid){
1689
- cust = key;
1690
- break;
1691
- }
1671
+ _.any(this._indexByCustom, function(cid, key) {
1672
+ if (cid === viewCid) {
1673
+ delete this._indexByCustom[key];
1674
+ return true;
1692
1675
  }
1693
- }
1694
-
1695
- if (cust){
1696
- delete this._indexByCustom[cust];
1697
- }
1676
+ }, this);
1698
1677
 
1699
1678
  // remove the view from the container
1700
1679
  delete this._views[viewCid];
@@ -1706,44 +1685,24 @@ Backbone.ChildViewContainer = (function(Backbone, _){
1706
1685
  // Call a method on every view in the container,
1707
1686
  // passing parameters to the call method one at a
1708
1687
  // time, like `function.call`.
1709
- call: function(method, args){
1710
- args = Array.prototype.slice.call(arguments, 1);
1711
- this.apply(method, args);
1688
+ call: function(method){
1689
+ this.apply(method, _.tail(arguments));
1712
1690
  },
1713
1691
 
1714
1692
  // Apply a method on every view in the container,
1715
1693
  // passing parameters to the call method one at a
1716
1694
  // time, like `function.apply`.
1717
1695
  apply: function(method, args){
1718
- var view;
1719
-
1720
- // fix for IE < 9
1721
- args = args || [];
1722
-
1723
- _.each(this._views, function(view, key){
1696
+ _.each(this._views, function(view){
1724
1697
  if (_.isFunction(view[method])){
1725
- view[method].apply(view, args);
1698
+ view[method].apply(view, args || []);
1726
1699
  }
1727
1700
  });
1728
-
1729
1701
  },
1730
1702
 
1731
1703
  // Update the `.length` attribute on this container
1732
1704
  _updateLength: function(){
1733
1705
  this.length = _.size(this._views);
1734
- },
1735
-
1736
- // set up an initial list of views
1737
- _addInitialViews: function(views){
1738
- if (!views){ return; }
1739
-
1740
- var view, i,
1741
- length = views.length;
1742
-
1743
- for (i=0; i<length; i++){
1744
- view = views[i];
1745
- this.add(view);
1746
- }
1747
1706
  }
1748
1707
  });
1749
1708
 
@@ -2071,7 +2030,7 @@ Marionette.extend = Backbone.Model.extend;
2071
2030
  // --------------------
2072
2031
 
2073
2032
  // Retrieve an object, function or other value from a target
2074
- // object or it's `options`, with `options` taking precedence.
2033
+ // object or its `options`, with `options` taking precedence.
2075
2034
  Marionette.getOption = function(target, optionName){
2076
2035
  if (!target || !optionName){ return; }
2077
2036
  var value;
@@ -2211,7 +2170,7 @@ Marionette.MonitorDOMRefresh = (function(){
2211
2170
  var methodNames = methods.split(/\s+/);
2212
2171
 
2213
2172
  _.each(methodNames,function(methodName) {
2214
- var method = target[method];
2173
+ var method = target[methodName];
2215
2174
  target.stopListening(entity, evt, method, target);
2216
2175
  });
2217
2176
  }
@@ -2452,18 +2411,24 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
2452
2411
 
2453
2412
  this.ensureEl();
2454
2413
 
2455
- if (view !== this.currentView) {
2414
+ var isViewClosed = view.isClosed || _.isUndefined(view.$el);
2415
+
2416
+ var isDifferentView = view !== this.currentView;
2417
+
2418
+ if (isDifferentView) {
2456
2419
  this.close();
2457
- view.render();
2458
- this.open(view);
2459
- } else {
2460
- view.render();
2461
2420
  }
2462
2421
 
2463
- Marionette.triggerMethod.call(view, "show");
2464
- Marionette.triggerMethod.call(this, "show", view);
2422
+ view.render();
2465
2423
 
2424
+ if (isDifferentView || isViewClosed) {
2425
+ this.open(view);
2426
+ }
2427
+
2466
2428
  this.currentView = view;
2429
+
2430
+ Marionette.triggerMethod.call(this, "show", view);
2431
+ Marionette.triggerMethod.call(view, "show");
2467
2432
  },
2468
2433
 
2469
2434
  ensureEl: function(){
@@ -2614,14 +2579,20 @@ Marionette.RegionManager = (function(Marionette){
2614
2579
  // internal method to store regions
2615
2580
  _store: function(name, region){
2616
2581
  this._regions[name] = region;
2617
- this.length = _.size(this._regions);
2582
+ this._setLength();
2618
2583
  },
2619
2584
 
2620
2585
  // internal method to remove a region
2621
2586
  _remove: function(name, region){
2622
2587
  region.close();
2623
2588
  delete this._regions[name];
2589
+ this._setLength();
2624
2590
  this.triggerMethod("region:remove", name, region);
2591
+ },
2592
+
2593
+ // set the number of regions current held
2594
+ _setLength: function(){
2595
+ this.length = _.size(this._regions);
2625
2596
  }
2626
2597
 
2627
2598
  });
@@ -2700,7 +2671,7 @@ _.extend(Marionette.TemplateCache, {
2700
2671
  });
2701
2672
 
2702
2673
  // TemplateCache instance methods, allowing each
2703
- // template cache object to manage it's own state
2674
+ // template cache object to manage its own state
2704
2675
  // and know whether or not it has been loaded
2705
2676
  _.extend(Marionette.TemplateCache.prototype, {
2706
2677
 
@@ -2755,7 +2726,20 @@ Marionette.Renderer = {
2755
2726
  // template function. Override this method to provide your own
2756
2727
  // custom rendering and template handling for all of Marionette.
2757
2728
  render: function(template, data){
2758
- var templateFunc = typeof template === 'function' ? template : Marionette.TemplateCache.get(template);
2729
+
2730
+ if (!template) {
2731
+ var error = new Error("Cannot render the template since it's false, null or undefined.");
2732
+ error.name = "TemplateNotFoundError";
2733
+ throw error;
2734
+ }
2735
+
2736
+ var templateFunc;
2737
+ if (typeof template === "function"){
2738
+ templateFunc = template;
2739
+ } else {
2740
+ templateFunc = Marionette.TemplateCache.get(template);
2741
+ }
2742
+
2759
2743
  return templateFunc(data);
2760
2744
  }
2761
2745
  };
@@ -2821,7 +2805,7 @@ Marionette.View = Backbone.View.extend({
2821
2805
  // build the event handler function for the DOM event
2822
2806
  triggerEvents[key] = function(e){
2823
2807
 
2824
- // stop the event in it's tracks
2808
+ // stop the event in its tracks
2825
2809
  if (e && e.preventDefault){ e.preventDefault(); }
2826
2810
  if (e && e.stopPropagation){ e.stopPropagation(); }
2827
2811
 
@@ -2946,7 +2930,10 @@ Marionette.View = Backbone.View.extend({
2946
2930
  // A single item view implementation that contains code for rendering
2947
2931
  // with underscore.js templates, serializing the view's model or collection,
2948
2932
  // and calling several methods on extended views, such as `onRender`.
2949
- Marionette.ItemView = Marionette.View.extend({
2933
+ Marionette.ItemView = Marionette.View.extend({
2934
+
2935
+ // Setting up the inheritance chain which allows changes to
2936
+ // Marionette.View.prototype.constructor which allows overriding
2950
2937
  constructor: function(){
2951
2938
  Marionette.View.prototype.constructor.apply(this, slice(arguments));
2952
2939
  },
@@ -2986,6 +2973,7 @@ Marionette.ItemView = Marionette.View.extend({
2986
2973
 
2987
2974
  var template = this.getTemplate();
2988
2975
  var html = Marionette.Renderer.render(template, data);
2976
+
2989
2977
  this.$el.html(html);
2990
2978
  this.bindUIElements();
2991
2979
 
@@ -3279,10 +3267,11 @@ Marionette.CollectionView = Marionette.View.extend({
3279
3267
  // Extends directly from CollectionView and also renders an
3280
3268
  // an item view as `modelView`, for the top leaf
3281
3269
  Marionette.CompositeView = Marionette.CollectionView.extend({
3282
- constructor: function(options){
3283
- Marionette.CollectionView.apply(this, slice(arguments));
3284
-
3285
- this.itemView = this.getItemView();
3270
+
3271
+ // Setting up the inheritance chain which allows changes to
3272
+ // Marionette.CollectionView.prototype.constructor which allows overriding
3273
+ constructor: function(){
3274
+ Marionette.CollectionView.prototype.constructor.apply(this, slice(arguments));
3286
3275
  },
3287
3276
 
3288
3277
  // Configured the initial events that the composite view
@@ -3370,7 +3359,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
3370
3359
  // `itemViewContainer` (a jQuery selector). Override this method to
3371
3360
  // provide custom logic of how the child item view instances have their
3372
3361
  // HTML appended to the composite view instance.
3373
- appendHtml: function(cv, iv){
3362
+ appendHtml: function(cv, iv, index){
3374
3363
  var $container = this.getItemViewContainer(cv);
3375
3364
  $container.append(iv.el);
3376
3365
  },
@@ -3428,7 +3417,7 @@ Marionette.Layout = Marionette.ItemView.extend({
3428
3417
  this._firstRender = true;
3429
3418
  this._initializeRegions(options);
3430
3419
 
3431
- Marionette.ItemView.call(this, options);
3420
+ Marionette.ItemView.prototype.constructor.call(this, options);
3432
3421
  },
3433
3422
 
3434
3423
  // Layout's render will use the existing region objects the
@@ -3893,7 +3882,7 @@ _.extend(Marionette.Module, {
3893
3882
  })(this, Backbone, _);
3894
3883
 
3895
3884
  /*!
3896
- * Tableling v0.0.20
3885
+ * Tableling v0.0.21
3897
3886
  * Copyright (c) 2012-2013 Simon Oulevay (Alpha Hydrae) <hydrae.alpha@gmail.com>
3898
3887
  * Distributed under MIT license
3899
3888
  * https://github.com/AlphaHydrae/tableling
@@ -3901,7 +3890,7 @@ _.extend(Marionette.Module, {
3901
3890
  Backbone.Tableling = Tableling = (function(Backbone, _, $){
3902
3891
 
3903
3892
  var Tableling = {
3904
- version : "0.0.20"
3893
+ version : "0.0.21"
3905
3894
  };
3906
3895
 
3907
3896
  // Tableling
@@ -3921,6 +3910,8 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
3921
3910
  initialize : function(options) {
3922
3911
  options = options || {};
3923
3912
 
3913
+ this.collection = options.collection;
3914
+
3924
3915
  // Table options can also be overriden for each instance at construction.
3925
3916
  this.config = _.extend(_.clone(this.config || {}), _.result(options, 'config') || {});
3926
3917
 
@@ -3933,7 +3924,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
3933
3924
 
3934
3925
  // Components should trigger the `table:update` event to update
3935
3926
  // the table (e.g. change page size, sort) and fetch the new data.
3936
- this.vent.on('table:update', this.update, this);
3927
+ this.vent.on('table:update', this.onUpdate, this);
3937
3928
 
3938
3929
  this.on('item:rendered', this.setup, this);
3939
3930
  },
@@ -3948,11 +3939,15 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
3948
3939
 
3949
3940
  // Subclasses must return the Backbone.Collection used to fetch data.
3950
3941
  getCollection : function() {
3951
- throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
3942
+ return this.collection;
3952
3943
  },
3953
3944
 
3954
3945
  // ### Refreshing the table
3955
3946
  update : function(config, options) {
3947
+ this.ventTrigger('table:update', config, options);
3948
+ },
3949
+
3950
+ onUpdate : function(config, options) {
3956
3951
 
3957
3952
  _.each(config || {}, _.bind(this.updateValue, this));
3958
3953
 
@@ -4014,6 +4009,12 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
4014
4009
  // which is the total number of items (not just in the current page).
4015
4010
  this.config.total = response.total;
4016
4011
 
4012
+ // The server may override the `page` property, for example if the
4013
+ // requested page was outside the range of available pages.
4014
+ if (response.page) {
4015
+ this.config.page = response.page;
4016
+ }
4017
+
4017
4018
  // `tableling:refreshed` is triggered after every refresh. The first argument
4018
4019
  // is the current table configuration with the following additional meta data:
4019
4020
  //
@@ -4107,18 +4108,20 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
4107
4108
  return view;
4108
4109
  },
4109
4110
 
4110
- // By default, a modular table expects a `table` module which
4111
+ // By default the collection is the one given at construction.
4112
+ // Otherwise, a modular table expects a `table` module which
4111
4113
  // should have a collection (e.g. a Marionette CompositeView or
4112
- // CollectionView). If your subclass does not have that, it
4114
+ // CollectionView). If your subclass does not have either, it
4113
4115
  // should override this method to return the Backbone.Collection
4114
4116
  // used to fetch table data.
4115
4117
  getCollection : function() {
4116
- return this.moduleViews.table.collection;
4118
+ return this.collection || (this.moduleViews && this.moduleViews.table ? this.moduleViews.table.collection : undefined);
4117
4119
  },
4118
4120
 
4119
4121
  getModuleOptions : function(name) {
4120
4122
  var options = this[name + 'ViewOptions'] || {};
4121
- return typeof(options) == 'function' ? options.call(this) : options;
4123
+ options = typeof(options) == 'function' ? options.call(this) : options;
4124
+ return name == 'table' ? _.defaults(options, { collection : this.collection }) : options;
4122
4125
  }
4123
4126
  });
4124
4127
 
@@ -4269,6 +4272,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
4269
4272
  this.vent = options.vent;
4270
4273
  this.sort = [];
4271
4274
  this.vent.on('table:setup', this.setSort, this);
4275
+ this.vent.on('table:refreshed', this.setSort, this);
4272
4276
  },
4273
4277
 
4274
4278
  updateSort : function(ev) {
@@ -4521,23 +4525,28 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
4521
4525
  return Math.ceil(this.data.total / this.data.pageSize);
4522
4526
  },
4523
4527
 
4524
- goToFirstPage : function() {
4528
+ goToFirstPage : function(e) {
4529
+ e.preventDefault();
4525
4530
  this.goToPageNumber(1);
4526
4531
  },
4527
4532
 
4528
- goToPreviousPage : function() {
4533
+ goToPreviousPage : function(e) {
4534
+ e.preventDefault();
4529
4535
  this.goToPageNumber(this.getPage(this.data) - 1);
4530
4536
  },
4531
4537
 
4532
4538
  goToPage : function(e) {
4539
+ e.preventDefault();
4533
4540
  this.goToPageNumber(parseInt($(e.target).text(), 10));
4534
4541
  },
4535
4542
 
4536
- goToNextPage : function() {
4543
+ goToNextPage : function(e) {
4544
+ e.preventDefault();
4537
4545
  this.goToPageNumber(this.getPage(this.data) + 1);
4538
4546
  },
4539
4547
 
4540
- goToLastPage : function() {
4548
+ goToLastPage : function(e) {
4549
+ e.preventDefault();
4541
4550
  this.goToPageNumber(this.numberOfPages());
4542
4551
  },
4543
4552
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Tableling v0.0.20
2
+ * Tableling v0.0.21
3
3
  * Copyright (c) 2012-2013 Simon Oulevay (Alpha Hydrae) <hydrae.alpha@gmail.com>
4
4
  * Distributed under MIT license
5
5
  * https://github.com/AlphaHydrae/tableling
@@ -7,7 +7,7 @@
7
7
  Backbone.Tableling = Tableling = (function(Backbone, _, $){
8
8
 
9
9
  var Tableling = {
10
- version : "0.0.20"
10
+ version : "0.0.21"
11
11
  };
12
12
 
13
13
  // Tableling
@@ -27,6 +27,8 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
27
27
  initialize : function(options) {
28
28
  options = options || {};
29
29
 
30
+ this.collection = options.collection;
31
+
30
32
  // Table options can also be overriden for each instance at construction.
31
33
  this.config = _.extend(_.clone(this.config || {}), _.result(options, 'config') || {});
32
34
 
@@ -39,7 +41,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
39
41
 
40
42
  // Components should trigger the `table:update` event to update
41
43
  // the table (e.g. change page size, sort) and fetch the new data.
42
- this.vent.on('table:update', this.update, this);
44
+ this.vent.on('table:update', this.onUpdate, this);
43
45
 
44
46
  this.on('item:rendered', this.setup, this);
45
47
  },
@@ -54,11 +56,15 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
54
56
 
55
57
  // Subclasses must return the Backbone.Collection used to fetch data.
56
58
  getCollection : function() {
57
- throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
59
+ return this.collection;
58
60
  },
59
61
 
60
62
  // ### Refreshing the table
61
63
  update : function(config, options) {
64
+ this.ventTrigger('table:update', config, options);
65
+ },
66
+
67
+ onUpdate : function(config, options) {
62
68
 
63
69
  _.each(config || {}, _.bind(this.updateValue, this));
64
70
 
@@ -120,6 +126,12 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
120
126
  // which is the total number of items (not just in the current page).
121
127
  this.config.total = response.total;
122
128
 
129
+ // The server may override the `page` property, for example if the
130
+ // requested page was outside the range of available pages.
131
+ if (response.page) {
132
+ this.config.page = response.page;
133
+ }
134
+
123
135
  // `tableling:refreshed` is triggered after every refresh. The first argument
124
136
  // is the current table configuration with the following additional meta data:
125
137
  //
@@ -213,18 +225,20 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
213
225
  return view;
214
226
  },
215
227
 
216
- // By default, a modular table expects a `table` module which
228
+ // By default the collection is the one given at construction.
229
+ // Otherwise, a modular table expects a `table` module which
217
230
  // should have a collection (e.g. a Marionette CompositeView or
218
- // CollectionView). If your subclass does not have that, it
231
+ // CollectionView). If your subclass does not have either, it
219
232
  // should override this method to return the Backbone.Collection
220
233
  // used to fetch table data.
221
234
  getCollection : function() {
222
- return this.moduleViews.table.collection;
235
+ return this.collection || (this.moduleViews && this.moduleViews.table ? this.moduleViews.table.collection : undefined);
223
236
  },
224
237
 
225
238
  getModuleOptions : function(name) {
226
239
  var options = this[name + 'ViewOptions'] || {};
227
- return typeof(options) == 'function' ? options.call(this) : options;
240
+ options = typeof(options) == 'function' ? options.call(this) : options;
241
+ return name == 'table' ? _.defaults(options, { collection : this.collection }) : options;
228
242
  }
229
243
  });
230
244
 
@@ -375,6 +389,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
375
389
  this.vent = options.vent;
376
390
  this.sort = [];
377
391
  this.vent.on('table:setup', this.setSort, this);
392
+ this.vent.on('table:refreshed', this.setSort, this);
378
393
  },
379
394
 
380
395
  updateSort : function(ev) {
@@ -627,23 +642,28 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
627
642
  return Math.ceil(this.data.total / this.data.pageSize);
628
643
  },
629
644
 
630
- goToFirstPage : function() {
645
+ goToFirstPage : function(e) {
646
+ e.preventDefault();
631
647
  this.goToPageNumber(1);
632
648
  },
633
649
 
634
- goToPreviousPage : function() {
650
+ goToPreviousPage : function(e) {
651
+ e.preventDefault();
635
652
  this.goToPageNumber(this.getPage(this.data) - 1);
636
653
  },
637
654
 
638
655
  goToPage : function(e) {
656
+ e.preventDefault();
639
657
  this.goToPageNumber(parseInt($(e.target).text(), 10));
640
658
  },
641
659
 
642
- goToNextPage : function() {
660
+ goToNextPage : function(e) {
661
+ e.preventDefault();
643
662
  this.goToPageNumber(this.getPage(this.data) + 1);
644
663
  },
645
664
 
646
- goToLastPage : function() {
665
+ goToLastPage : function(e) {
666
+ e.preventDefault();
647
667
  this.goToPageNumber(this.numberOfPages());
648
668
  },
649
669
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  json2.js
3
- 2012-10-08
3
+ 2013-05-26
4
4
 
5
5
  Public Domain.
6
6
 
@@ -173,7 +173,7 @@ if (typeof JSON !== 'object') {
173
173
 
174
174
  if (typeof Date.prototype.toJSON !== 'function') {
175
175
 
176
- Date.prototype.toJSON = function (key) {
176
+ Date.prototype.toJSON = function () {
177
177
 
178
178
  return isFinite(this.valueOf())
179
179
  ? this.getUTCFullYear() + '-' +
@@ -187,7 +187,7 @@ if (typeof JSON !== 'object') {
187
187
 
188
188
  String.prototype.toJSON =
189
189
  Number.prototype.toJSON =
190
- Boolean.prototype.toJSON = function (key) {
190
+ Boolean.prototype.toJSON = function () {
191
191
  return this.valueOf();
192
192
  };
193
193
  }
@@ -12885,7 +12885,7 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
12885
12885
 
12886
12886
  // Backbone.BabySitter
12887
12887
  // -------------------
12888
- // v0.0.5
12888
+ // v0.0.6
12889
12889
  //
12890
12890
  // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
12891
12891
  // Distributed under MIT license
@@ -12903,14 +12903,13 @@ Backbone.ChildViewContainer = (function(Backbone, _){
12903
12903
  // Container Constructor
12904
12904
  // ---------------------
12905
12905
 
12906
- var Container = function(initialViews){
12906
+ var Container = function(views){
12907
12907
  this._views = {};
12908
12908
  this._indexByModel = {};
12909
- this._indexByCollection = {};
12910
12909
  this._indexByCustom = {};
12911
12910
  this._updateLength();
12912
12911
 
12913
- this._addInitialViews(initialViews);
12912
+ _.each(views, this.add, this);
12914
12913
  };
12915
12914
 
12916
12915
  // Container Methods
@@ -12920,7 +12919,7 @@ Backbone.ChildViewContainer = (function(Backbone, _){
12920
12919
 
12921
12920
  // Add a view to this container. Stores the view
12922
12921
  // by `cid` and makes it searchable by the model
12923
- // and/or collection of the view. Optionally specify
12922
+ // cid (and model itself). Optionally specify
12924
12923
  // a custom key to store an retrieve the view.
12925
12924
  add: function(view, customIndex){
12926
12925
  var viewCid = view.cid;
@@ -12933,11 +12932,6 @@ Backbone.ChildViewContainer = (function(Backbone, _){
12933
12932
  this._indexByModel[view.model.cid] = viewCid;
12934
12933
  }
12935
12934
 
12936
- // index it by collection
12937
- if (view.collection){
12938
- this._indexByCollection[view.collection.cid] = viewCid;
12939
- }
12940
-
12941
12935
  // index by custom
12942
12936
  if (customIndex){
12943
12937
  this._indexByCustom[customIndex] = viewCid;
@@ -12947,18 +12941,16 @@ Backbone.ChildViewContainer = (function(Backbone, _){
12947
12941
  },
12948
12942
 
12949
12943
  // Find a view by the model that was attached to
12950
- // it. Uses the model's `cid` to find it, and
12951
- // retrieves the view by it's `cid` from the result
12944
+ // it. Uses the model's `cid` to find it.
12952
12945
  findByModel: function(model){
12953
- var viewCid = this._indexByModel[model.cid];
12954
- return this.findByCid(viewCid);
12946
+ return this.findByModelCid(model.cid);
12955
12947
  },
12956
12948
 
12957
- // Find a view by the collection that was attached to
12958
- // it. Uses the collection's `cid` to find it, and
12959
- // retrieves the view by it's `cid` from the result
12960
- findByCollection: function(col){
12961
- var viewCid = this._indexByCollection[col.cid];
12949
+ // Find a view by the `cid` of the model that was attached to
12950
+ // it. Uses the model's `cid` to find the view `cid` and
12951
+ // retrieve the view using it.
12952
+ findByModelCid: function(modelCid){
12953
+ var viewCid = this._indexByModel[modelCid];
12962
12954
  return this.findByCid(viewCid);
12963
12955
  },
12964
12956
 
@@ -12988,26 +12980,13 @@ Backbone.ChildViewContainer = (function(Backbone, _){
12988
12980
  delete this._indexByModel[view.model.cid];
12989
12981
  }
12990
12982
 
12991
- // delete collection index
12992
- if (view.collection){
12993
- delete this._indexByCollection[view.collection.cid];
12994
- }
12995
-
12996
12983
  // delete custom index
12997
- var cust;
12998
-
12999
- for (var key in this._indexByCustom){
13000
- if (this._indexByCustom.hasOwnProperty(key)){
13001
- if (this._indexByCustom[key] === viewCid){
13002
- cust = key;
13003
- break;
13004
- }
12984
+ _.any(this._indexByCustom, function(cid, key) {
12985
+ if (cid === viewCid) {
12986
+ delete this._indexByCustom[key];
12987
+ return true;
13005
12988
  }
13006
- }
13007
-
13008
- if (cust){
13009
- delete this._indexByCustom[cust];
13010
- }
12989
+ }, this);
13011
12990
 
13012
12991
  // remove the view from the container
13013
12992
  delete this._views[viewCid];
@@ -13019,44 +12998,24 @@ Backbone.ChildViewContainer = (function(Backbone, _){
13019
12998
  // Call a method on every view in the container,
13020
12999
  // passing parameters to the call method one at a
13021
13000
  // time, like `function.call`.
13022
- call: function(method, args){
13023
- args = Array.prototype.slice.call(arguments, 1);
13024
- this.apply(method, args);
13001
+ call: function(method){
13002
+ this.apply(method, _.tail(arguments));
13025
13003
  },
13026
13004
 
13027
13005
  // Apply a method on every view in the container,
13028
13006
  // passing parameters to the call method one at a
13029
13007
  // time, like `function.apply`.
13030
13008
  apply: function(method, args){
13031
- var view;
13032
-
13033
- // fix for IE < 9
13034
- args = args || [];
13035
-
13036
- _.each(this._views, function(view, key){
13009
+ _.each(this._views, function(view){
13037
13010
  if (_.isFunction(view[method])){
13038
- view[method].apply(view, args);
13011
+ view[method].apply(view, args || []);
13039
13012
  }
13040
13013
  });
13041
-
13042
13014
  },
13043
13015
 
13044
13016
  // Update the `.length` attribute on this container
13045
13017
  _updateLength: function(){
13046
13018
  this.length = _.size(this._views);
13047
- },
13048
-
13049
- // set up an initial list of views
13050
- _addInitialViews: function(views){
13051
- if (!views){ return; }
13052
-
13053
- var view, i,
13054
- length = views.length;
13055
-
13056
- for (i=0; i<length; i++){
13057
- view = views[i];
13058
- this.add(view);
13059
- }
13060
13019
  }
13061
13020
  });
13062
13021
 
@@ -13384,7 +13343,7 @@ Marionette.extend = Backbone.Model.extend;
13384
13343
  // --------------------
13385
13344
 
13386
13345
  // Retrieve an object, function or other value from a target
13387
- // object or it's `options`, with `options` taking precedence.
13346
+ // object or its `options`, with `options` taking precedence.
13388
13347
  Marionette.getOption = function(target, optionName){
13389
13348
  if (!target || !optionName){ return; }
13390
13349
  var value;
@@ -13524,7 +13483,7 @@ Marionette.MonitorDOMRefresh = (function(){
13524
13483
  var methodNames = methods.split(/\s+/);
13525
13484
 
13526
13485
  _.each(methodNames,function(methodName) {
13527
- var method = target[method];
13486
+ var method = target[methodName];
13528
13487
  target.stopListening(entity, evt, method, target);
13529
13488
  });
13530
13489
  }
@@ -13765,18 +13724,24 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
13765
13724
 
13766
13725
  this.ensureEl();
13767
13726
 
13768
- if (view !== this.currentView) {
13727
+ var isViewClosed = view.isClosed || _.isUndefined(view.$el);
13728
+
13729
+ var isDifferentView = view !== this.currentView;
13730
+
13731
+ if (isDifferentView) {
13769
13732
  this.close();
13770
- view.render();
13771
- this.open(view);
13772
- } else {
13773
- view.render();
13774
13733
  }
13775
13734
 
13776
- Marionette.triggerMethod.call(view, "show");
13777
- Marionette.triggerMethod.call(this, "show", view);
13735
+ view.render();
13778
13736
 
13737
+ if (isDifferentView || isViewClosed) {
13738
+ this.open(view);
13739
+ }
13740
+
13779
13741
  this.currentView = view;
13742
+
13743
+ Marionette.triggerMethod.call(this, "show", view);
13744
+ Marionette.triggerMethod.call(view, "show");
13780
13745
  },
13781
13746
 
13782
13747
  ensureEl: function(){
@@ -13927,14 +13892,20 @@ Marionette.RegionManager = (function(Marionette){
13927
13892
  // internal method to store regions
13928
13893
  _store: function(name, region){
13929
13894
  this._regions[name] = region;
13930
- this.length = _.size(this._regions);
13895
+ this._setLength();
13931
13896
  },
13932
13897
 
13933
13898
  // internal method to remove a region
13934
13899
  _remove: function(name, region){
13935
13900
  region.close();
13936
13901
  delete this._regions[name];
13902
+ this._setLength();
13937
13903
  this.triggerMethod("region:remove", name, region);
13904
+ },
13905
+
13906
+ // set the number of regions current held
13907
+ _setLength: function(){
13908
+ this.length = _.size(this._regions);
13938
13909
  }
13939
13910
 
13940
13911
  });
@@ -14013,7 +13984,7 @@ _.extend(Marionette.TemplateCache, {
14013
13984
  });
14014
13985
 
14015
13986
  // TemplateCache instance methods, allowing each
14016
- // template cache object to manage it's own state
13987
+ // template cache object to manage its own state
14017
13988
  // and know whether or not it has been loaded
14018
13989
  _.extend(Marionette.TemplateCache.prototype, {
14019
13990
 
@@ -14068,7 +14039,20 @@ Marionette.Renderer = {
14068
14039
  // template function. Override this method to provide your own
14069
14040
  // custom rendering and template handling for all of Marionette.
14070
14041
  render: function(template, data){
14071
- var templateFunc = typeof template === 'function' ? template : Marionette.TemplateCache.get(template);
14042
+
14043
+ if (!template) {
14044
+ var error = new Error("Cannot render the template since it's false, null or undefined.");
14045
+ error.name = "TemplateNotFoundError";
14046
+ throw error;
14047
+ }
14048
+
14049
+ var templateFunc;
14050
+ if (typeof template === "function"){
14051
+ templateFunc = template;
14052
+ } else {
14053
+ templateFunc = Marionette.TemplateCache.get(template);
14054
+ }
14055
+
14072
14056
  return templateFunc(data);
14073
14057
  }
14074
14058
  };
@@ -14134,7 +14118,7 @@ Marionette.View = Backbone.View.extend({
14134
14118
  // build the event handler function for the DOM event
14135
14119
  triggerEvents[key] = function(e){
14136
14120
 
14137
- // stop the event in it's tracks
14121
+ // stop the event in its tracks
14138
14122
  if (e && e.preventDefault){ e.preventDefault(); }
14139
14123
  if (e && e.stopPropagation){ e.stopPropagation(); }
14140
14124
 
@@ -14259,7 +14243,10 @@ Marionette.View = Backbone.View.extend({
14259
14243
  // A single item view implementation that contains code for rendering
14260
14244
  // with underscore.js templates, serializing the view's model or collection,
14261
14245
  // and calling several methods on extended views, such as `onRender`.
14262
- Marionette.ItemView = Marionette.View.extend({
14246
+ Marionette.ItemView = Marionette.View.extend({
14247
+
14248
+ // Setting up the inheritance chain which allows changes to
14249
+ // Marionette.View.prototype.constructor which allows overriding
14263
14250
  constructor: function(){
14264
14251
  Marionette.View.prototype.constructor.apply(this, slice(arguments));
14265
14252
  },
@@ -14299,6 +14286,7 @@ Marionette.ItemView = Marionette.View.extend({
14299
14286
 
14300
14287
  var template = this.getTemplate();
14301
14288
  var html = Marionette.Renderer.render(template, data);
14289
+
14302
14290
  this.$el.html(html);
14303
14291
  this.bindUIElements();
14304
14292
 
@@ -14592,10 +14580,11 @@ Marionette.CollectionView = Marionette.View.extend({
14592
14580
  // Extends directly from CollectionView and also renders an
14593
14581
  // an item view as `modelView`, for the top leaf
14594
14582
  Marionette.CompositeView = Marionette.CollectionView.extend({
14595
- constructor: function(options){
14596
- Marionette.CollectionView.apply(this, slice(arguments));
14597
-
14598
- this.itemView = this.getItemView();
14583
+
14584
+ // Setting up the inheritance chain which allows changes to
14585
+ // Marionette.CollectionView.prototype.constructor which allows overriding
14586
+ constructor: function(){
14587
+ Marionette.CollectionView.prototype.constructor.apply(this, slice(arguments));
14599
14588
  },
14600
14589
 
14601
14590
  // Configured the initial events that the composite view
@@ -14683,7 +14672,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
14683
14672
  // `itemViewContainer` (a jQuery selector). Override this method to
14684
14673
  // provide custom logic of how the child item view instances have their
14685
14674
  // HTML appended to the composite view instance.
14686
- appendHtml: function(cv, iv){
14675
+ appendHtml: function(cv, iv, index){
14687
14676
  var $container = this.getItemViewContainer(cv);
14688
14677
  $container.append(iv.el);
14689
14678
  },
@@ -14741,7 +14730,7 @@ Marionette.Layout = Marionette.ItemView.extend({
14741
14730
  this._firstRender = true;
14742
14731
  this._initializeRegions(options);
14743
14732
 
14744
- Marionette.ItemView.call(this, options);
14733
+ Marionette.ItemView.prototype.constructor.call(this, options);
14745
14734
  },
14746
14735
 
14747
14736
  // Layout's render will use the existing region objects the
@@ -15206,7 +15195,7 @@ _.extend(Marionette.Module, {
15206
15195
  })(this, Backbone, _);
15207
15196
 
15208
15197
  /*!
15209
- * Tableling v0.0.20
15198
+ * Tableling v0.0.21
15210
15199
  * Copyright (c) 2012-2013 Simon Oulevay (Alpha Hydrae) <hydrae.alpha@gmail.com>
15211
15200
  * Distributed under MIT license
15212
15201
  * https://github.com/AlphaHydrae/tableling
@@ -15214,7 +15203,7 @@ _.extend(Marionette.Module, {
15214
15203
  Backbone.Tableling = Tableling = (function(Backbone, _, $){
15215
15204
 
15216
15205
  var Tableling = {
15217
- version : "0.0.20"
15206
+ version : "0.0.21"
15218
15207
  };
15219
15208
 
15220
15209
  // Tableling
@@ -15234,6 +15223,8 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15234
15223
  initialize : function(options) {
15235
15224
  options = options || {};
15236
15225
 
15226
+ this.collection = options.collection;
15227
+
15237
15228
  // Table options can also be overriden for each instance at construction.
15238
15229
  this.config = _.extend(_.clone(this.config || {}), _.result(options, 'config') || {});
15239
15230
 
@@ -15246,7 +15237,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15246
15237
 
15247
15238
  // Components should trigger the `table:update` event to update
15248
15239
  // the table (e.g. change page size, sort) and fetch the new data.
15249
- this.vent.on('table:update', this.update, this);
15240
+ this.vent.on('table:update', this.onUpdate, this);
15250
15241
 
15251
15242
  this.on('item:rendered', this.setup, this);
15252
15243
  },
@@ -15261,11 +15252,15 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15261
15252
 
15262
15253
  // Subclasses must return the Backbone.Collection used to fetch data.
15263
15254
  getCollection : function() {
15264
- throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
15255
+ return this.collection;
15265
15256
  },
15266
15257
 
15267
15258
  // ### Refreshing the table
15268
15259
  update : function(config, options) {
15260
+ this.ventTrigger('table:update', config, options);
15261
+ },
15262
+
15263
+ onUpdate : function(config, options) {
15269
15264
 
15270
15265
  _.each(config || {}, _.bind(this.updateValue, this));
15271
15266
 
@@ -15327,6 +15322,12 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15327
15322
  // which is the total number of items (not just in the current page).
15328
15323
  this.config.total = response.total;
15329
15324
 
15325
+ // The server may override the `page` property, for example if the
15326
+ // requested page was outside the range of available pages.
15327
+ if (response.page) {
15328
+ this.config.page = response.page;
15329
+ }
15330
+
15330
15331
  // `tableling:refreshed` is triggered after every refresh. The first argument
15331
15332
  // is the current table configuration with the following additional meta data:
15332
15333
  //
@@ -15420,18 +15421,20 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15420
15421
  return view;
15421
15422
  },
15422
15423
 
15423
- // By default, a modular table expects a `table` module which
15424
+ // By default the collection is the one given at construction.
15425
+ // Otherwise, a modular table expects a `table` module which
15424
15426
  // should have a collection (e.g. a Marionette CompositeView or
15425
- // CollectionView). If your subclass does not have that, it
15427
+ // CollectionView). If your subclass does not have either, it
15426
15428
  // should override this method to return the Backbone.Collection
15427
15429
  // used to fetch table data.
15428
15430
  getCollection : function() {
15429
- return this.moduleViews.table.collection;
15431
+ return this.collection || (this.moduleViews && this.moduleViews.table ? this.moduleViews.table.collection : undefined);
15430
15432
  },
15431
15433
 
15432
15434
  getModuleOptions : function(name) {
15433
15435
  var options = this[name + 'ViewOptions'] || {};
15434
- return typeof(options) == 'function' ? options.call(this) : options;
15436
+ options = typeof(options) == 'function' ? options.call(this) : options;
15437
+ return name == 'table' ? _.defaults(options, { collection : this.collection }) : options;
15435
15438
  }
15436
15439
  });
15437
15440
 
@@ -15582,6 +15585,7 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15582
15585
  this.vent = options.vent;
15583
15586
  this.sort = [];
15584
15587
  this.vent.on('table:setup', this.setSort, this);
15588
+ this.vent.on('table:refreshed', this.setSort, this);
15585
15589
  },
15586
15590
 
15587
15591
  updateSort : function(ev) {
@@ -15834,23 +15838,28 @@ Backbone.Tableling = Tableling = (function(Backbone, _, $){
15834
15838
  return Math.ceil(this.data.total / this.data.pageSize);
15835
15839
  },
15836
15840
 
15837
- goToFirstPage : function() {
15841
+ goToFirstPage : function(e) {
15842
+ e.preventDefault();
15838
15843
  this.goToPageNumber(1);
15839
15844
  },
15840
15845
 
15841
- goToPreviousPage : function() {
15846
+ goToPreviousPage : function(e) {
15847
+ e.preventDefault();
15842
15848
  this.goToPageNumber(this.getPage(this.data) - 1);
15843
15849
  },
15844
15850
 
15845
15851
  goToPage : function(e) {
15852
+ e.preventDefault();
15846
15853
  this.goToPageNumber(parseInt($(e.target).text(), 10));
15847
15854
  },
15848
15855
 
15849
- goToNextPage : function() {
15856
+ goToNextPage : function(e) {
15857
+ e.preventDefault();
15850
15858
  this.goToPageNumber(this.getPage(this.data) + 1);
15851
15859
  },
15852
15860
 
15853
- goToLastPage : function() {
15861
+ goToLastPage : function(e) {
15862
+ e.preventDefault();
15854
15863
  this.goToPageNumber(this.numberOfPages());
15855
15864
  },
15856
15865
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tableling-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.18
4
+ version: 0.0.19
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-16 00:00:00.000000000 Z
12
+ date: 2013-07-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -125,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
125
  version: '0'
126
126
  segments:
127
127
  - 0
128
- hash: -4338373402448950759
128
+ hash: -4441844229467767142
129
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  none: false
131
131
  requirements:
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  version: '0'
135
135
  segments:
136
136
  - 0
137
- hash: -4338373402448950759
137
+ hash: -4441844229467767142
138
138
  requirements: []
139
139
  rubyforge_project:
140
140
  rubygems_version: 1.8.25