grapple 0.2.1 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: a00ec50832f4583379666e80a35b898efc63c066b1b19018efeccbfadefeb531
4
- data.tar.gz: fb7475bad8276a7f4867622aaf3fe47d09829853d12841795fb9ce4455697399
2
+ SHA1:
3
+ metadata.gz: 1d49408d1a5288a086cb3cb5016d2c6e68b09691
4
+ data.tar.gz: 6cbd12c3529aa3bb347771430e6bffab4926924b
5
5
  SHA512:
6
- metadata.gz: 9255cd578e733a19c272c73e47fc3fae1ac17838aa61f355a0fa150e6bd31d37ba0236a0f825cd441a9e082fb26241ddad3237bf041582ae0312275c9c8a3722
7
- data.tar.gz: 985d05b1ac0354f7ae92b5a78acf3a2236b2543bc083041009bc084539c09aa315b0f9becb1a99901944b7ece92c853f65ddb6fc6b759b3a19a04c4e4c6bd952
6
+ metadata.gz: e4fb86706c0372306b4381daa0224257b16589318d2726e9451294696e2bc5707359c29b6a2fcb907266bdca4493f7d385975b0c7e0d501cb6ec0f5cd017bb5c
7
+ data.tar.gz: 13e5c2b134d2930a836db20d3c8ea619cafccd0f69e43201171f178f1b1e3d9244468973878b8b85b4f3cd5c2d8da8cbc667df5ce9d9603ff695f612733f61f2
data/README.md CHANGED
@@ -189,7 +189,7 @@ Render the table using `table_for` in `app/views/posts/_table.html.erb`
189
189
 
190
190
  ## History w/AJAX (back button)
191
191
 
192
- Requires: https://github.com/browserstate/history.js/
192
+ Uses the native `window.history` API by default. If History.js is present it will use that instead for compatibility with older browsers (https://github.com/browserstate/history.js/).
193
193
 
194
194
  ``` javascript
195
195
  // app/assets/javascripts/application.js
@@ -4,25 +4,62 @@
4
4
  var urlQuery = Grapple.Util.urlQuery,
5
5
  parseUrlQuery = Grapple.Util.parseUrlQuery;
6
6
 
7
- var GrappleHistory = function(namespace) {
8
- this.namespace = namespace;
9
- if(History.init) {
10
- // https://github.com/browserstate/history.js/
11
- this.api = History;
7
+ // History.js for backwards compatibility with older browsers
8
+ // https://github.com/browserstate/history.js/
9
+ var LegacyHistory = function() {
10
+ var api = History;
12
11
 
13
- // Initialization of history.js can be delayed
14
- // if it was do it now
15
- if(this.api.options && this.api.options.delayInit) {
16
- this.api.options.delayInit = false;
17
- this.api.init();
18
- }
12
+ // Initialization of history.js can be delayed
13
+ // if it was do it now
14
+ if(api.options && api.options.delayInit) {
15
+ api.options.delayInit = false;
16
+ api.init();
19
17
  }
20
- else {
21
- // TODO: support native history api
22
- this.api = window.history;
18
+ this.api = api;
19
+ };
20
+
21
+ LegacyHistory.prototype = {
22
+ push: function(params) {
23
+ return this.api.pushState(null, document.title, '?' + params);
24
+ },
25
+ get: function() {
26
+ return urlQuery(this.api.getState().url);
27
+ },
28
+ bind: function(callback) {
29
+ $(window).bind('statechange', callback);
30
+ },
31
+ unbind: function(callback) {
32
+ $(window).unbind('statechange', callback);
23
33
  }
24
- this.api = History;
25
- this.changeCallback = null;
34
+ };
35
+
36
+ // Native Browser History API
37
+ var ModernHistory = function() {
38
+
39
+ };
40
+
41
+ ModernHistory.prototype = {
42
+ push: function(params) {
43
+ if(window.history && window.history.pushState) {
44
+ return window.history.pushState(params, document.title, '?' + params);
45
+ }
46
+ },
47
+ get: function() {
48
+ if(window.history) {
49
+ return window.history.state || urlQuery(document.location.toString());
50
+ }
51
+ },
52
+ bind: function(callback) {
53
+ $(window).bind('popstate', callback);
54
+ },
55
+ unbind: function(callback) {
56
+ $(window).unbind('popstate', callback);
57
+ }
58
+ };
59
+
60
+ var GrappleHistory = function(grappleTable) {
61
+ this.grappleTable = grappleTable;
62
+ this._historyChangeCallback = null;
26
63
  };
27
64
 
28
65
  // Don't clutter the url with rails form parameters
@@ -30,10 +67,20 @@ GrappleHistory.IGNORE_PARAMS = { 'utf8': true, 'authenticity_token': true };
30
67
 
31
68
  GrappleHistory.prototype = {
32
69
 
33
- add: function(params) {
34
- var namespace = this.namespace;
35
- var state = this.api.getState();
36
- var historyParams = parseUrlQuery(urlQuery(state.url));
70
+ init: function() {
71
+ // Use the History.js wrapper if History.js has been loaded
72
+ this.api = typeof History !== 'undefined' && History.init ? new LegacyHistory() : new ModernHistory();
73
+ this._subscribeToTableChange();
74
+ this._subscribeToHistoryChange();
75
+ },
76
+
77
+ /**
78
+ * Add an entry to the history
79
+ * @param {String} params
80
+ */
81
+ _addHistoryEntry: function(params) {
82
+ var namespace = this.grappleTable.namespace;
83
+ var historyParams = parseUrlQuery(this.api.get());
37
84
  var newParams = parseUrlQuery(params);
38
85
 
39
86
  // Remove any parameters from the current state
@@ -57,14 +104,45 @@ GrappleHistory.prototype = {
57
104
  historyParams[x] = newParams[x];
58
105
  }
59
106
 
60
- this.api.pushState(null, document.title, '?' + $.param(historyParams));
107
+ this.api.push($.param(historyParams));
61
108
  },
62
109
 
63
- subscribe: function(callback) {
64
- var api = this.api, namespace = this.namespace;
65
- this.changeCallback = function(event) {
66
- var state = api.getState();
67
- var params = parseUrlQuery(urlQuery(state.url));
110
+ /**
111
+ * Listen for changes to the table to add them to the history
112
+ */
113
+ _subscribeToTableChange: function() {
114
+ var self = this;
115
+ this._beforeLoadCallback = function(e, params) {
116
+ self._unsubscribeFromTableChange();
117
+ self._unsubscribeFromHistoryChange();
118
+ // Don't add params to history if this was triggered by history change
119
+ if(self._ignoreNextLoad) {
120
+ self._ignoreNextLoad = false;
121
+ }
122
+ else {
123
+ self._addHistoryEntry(params);
124
+ }
125
+ };
126
+ this.grappleTable.element.on('grapple:before_load', this._beforeLoadCallback);
127
+ },
128
+
129
+ /**
130
+ * Stop listening for changes to the table
131
+ */
132
+ _unsubscribeFromTableChange: function() {
133
+ if(this._beforeLoadCallback) {
134
+ this.grappleTable.element.unbind('grapple:before_load', this._beforeLoadCallback);
135
+ this._beforeLoadCallback = null;
136
+ }
137
+ },
138
+
139
+ /**
140
+ * Listen for changes to the history (back button clicks)
141
+ */
142
+ _subscribeToHistoryChange: function() {
143
+ var api = this.api, namespace = this.grappleTable.namespace, self = this;
144
+ this._historyChangeCallback = function(event) {
145
+ var params = parseUrlQuery(api.get());
68
146
  // Only include the parameters for this namespace
69
147
  if(namespace) {
70
148
  var r = new RegExp('^' + namespace + '\\[([^\\]]+)\\]$')
@@ -74,15 +152,19 @@ GrappleHistory.prototype = {
74
152
  }
75
153
  }
76
154
  }
77
- callback(params);
155
+ self._ignoreNextLoad = true;
156
+ self.grappleTable.loadTable($.param(params));
78
157
  };
79
- $(window).bind('statechange', this.changeCallback);
158
+ this.api.bind(this._historyChangeCallback);
80
159
  },
81
160
 
82
- unsubscribe: function() {
83
- if(this.changeCallback) {
84
- $(window).unbind('statechange', this.changeCallback);
85
- this.changeCallback = null;
161
+ /**
162
+ * Stop listening for history changes
163
+ */
164
+ _unsubscribeFromHistoryChange: function() {
165
+ if(this._historyChangeCallback) {
166
+ this.api.unbind(this._historyChangeCallback);
167
+ this._historyChangeCallback = null;
86
168
  }
87
169
  }
88
170
 
@@ -1,8 +1,5 @@
1
1
  (function(Grapple, $) {
2
2
  'use strict';
3
-
4
- var urlQuery = Grapple.Util.urlQuery,
5
- parseUrlQuery = Grapple.Util.parseUrlQuery;
6
3
 
7
4
  var overrideLink = function(clickable, anchor, callback) {
8
5
  var href = $(anchor).attr('href');
@@ -15,8 +12,8 @@ var overrideLink = function(clickable, anchor, callback) {
15
12
  /**
16
13
  * Creates a new instance of the Grapple AJAX widget.
17
14
  *
18
- * @param {String} Selector for the table container element.
19
- * @param {Object} Hash of options for the table (url, namespace, history)
15
+ * @param {String} element - Selector for the table container element.
16
+ * @param {Object} options - Hash of options for the table (url, namespace, history)
20
17
  */
21
18
  var GrappleTable = function(element, options) {
22
19
  options = options || {};
@@ -24,14 +21,12 @@ var GrappleTable = function(element, options) {
24
21
  this.url = options.url || this.element.data('grapple-ajax-url');
25
22
  this.namespace = options.namespace || this.element.data('grapple-ajax-namespace') || null;
26
23
  this.currentParams = options.params || '';
24
+ this.plugins = {};
27
25
  if(typeof options.history !== 'undefined' && options.history !== true) {
28
- this.history = options.history;
26
+ this.plugins.history = options.history;
29
27
  }
30
28
  else if(this.element.data('grapple-ajax-history') == 1 || options.history === true) {
31
- this.history = new Grapple.History(this.namespace);
32
- }
33
- else {
34
- this.history = null;
29
+ this.plugins.history = new Grapple.History(this);
35
30
  }
36
31
  this.init();
37
32
  };
@@ -44,7 +39,7 @@ GrappleTable.NON_TABLE_RESPONSE = '<!DOCTYPE html>';
44
39
  GrappleTable.prototype = {
45
40
 
46
41
  /**
47
- *
42
+ * Initialize the grapple table
48
43
  */
49
44
  init: function() {
50
45
  var self = this;
@@ -56,39 +51,29 @@ GrappleTable.prototype = {
56
51
  self.initSorting();
57
52
  self.initSearchForm();
58
53
  self.initPagination();
59
- self.initHistory();
54
+ self.initPlugins();
60
55
 
61
56
  self.element.removeClass(GrappleTable.CSS_AJAX_LOADING);
62
57
  },
63
58
 
64
- initHistory: function() {
65
- if(this.history) {
66
- var self = this;
67
- this.history.unsubscribe();
68
- this.history = new Grapple.History(this.namespace);
69
- this.history.subscribe(function(params) {
70
- self.onHistoryChange(params);
71
- });
59
+ /**
60
+ * Initialize plugins
61
+ */
62
+ initPlugins: function() {
63
+ for(var name in this.plugins) {
64
+ this.plugins[name].init();
72
65
  }
73
66
  },
74
67
 
75
- onHistoryChange: function(params) {
76
- this._showLoading();
77
- this._updateTable($.param(params));
78
- },
79
-
80
68
  /**
81
- *
69
+ * Load the table contents
70
+ * @param {String} params - Query string of parameters to load the table with
71
+ * @fires Grapple#grapple:before_load
72
+ * @fires Grapple#grapple:after_load
82
73
  */
83
74
  loadTable: function(params) {
84
- this.element.trigger('grapple:before_load');
75
+ this.element.trigger('grapple:before_load', params);
85
76
  this._showLoading();
86
-
87
- if(this.history) {
88
- this.history.unsubscribe();
89
- this.history.add(params);
90
- }
91
-
92
77
  this._updateTable(params);
93
78
  },
94
79
 
@@ -117,7 +102,7 @@ GrappleTable.prototype = {
117
102
  }
118
103
  $.ajax(url, {
119
104
  success: function(data) {
120
- // HACK
105
+ // HACK: handle full page responses
121
106
  var nonTableKeyIndex = data.indexOf(GrappleTable.NON_TABLE_RESPONSE);
122
107
  if(nonTableKeyIndex > -1 && nonTableKeyIndex < 100) {
123
108
  data = "Failed to load table";
@@ -1,9 +1,6 @@
1
1
  (function(globals) {
2
2
  'use strict';
3
3
 
4
- // Namespace
5
- var Grapple = {};
6
-
7
4
  var decodeParam = function(str) {
8
5
  return decodeURIComponent(str.replace(/\+/g, " "));
9
6
  };
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grapple
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edward Potocko
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-11-18 00:00:00.000000000 Z
13
+ date: 2020-12-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionpack
@@ -207,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
207
  version: '0'
208
208
  requirements: []
209
209
  rubyforge_project:
210
- rubygems_version: 2.7.6.2
210
+ rubygems_version: 2.6.14.1
211
211
  signing_key:
212
212
  specification_version: 4
213
213
  summary: Customizable data grid for Rails