rails_jskit 5.0.2 → 5.1.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 +4 -4
- data/README.md +2 -2
- data/app/assets/javascripts/jskit.js +172 -246
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 240307149b562d4e71edf1aefeafcb18dcffd2f9
|
4
|
+
data.tar.gz: 5db7168702b8598eed85b76d16cd4fe7d57cf781
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2de89050713116fbaad34b612b5193b810944c758a6fb9b14664da23e251a029e5238e5a12709d2c5a005902aa43714be804eccbd215d81949a9400ebf361ff
|
7
|
+
data.tar.gz: 94f6f5ddf9910a6a8632bb10ae9fb93963cc6807b236258f64b62db454105ab4f04dc457d604d079a57a4cae3d520b0f8e6d6b672658f70fc99de2c91339f68e
|
data/README.md
CHANGED
@@ -107,7 +107,7 @@ Documentation
|
|
107
107
|
|
108
108
|
### Application Object
|
109
109
|
|
110
|
-
RailsJskit will automatically create a JSkit application object for you, using the configured `app_namespace` for the global variable name _(defaults to "App")_. This global namespace provides you a way to interact with your JSkit application. You can
|
110
|
+
RailsJskit will automatically create a JSkit application object for you, using the configured `app_namespace` for the global variable name _(defaults to "App")_. This global namespace provides you a way to interact with your JSkit application. You can [configure](#configuration) this setting in your initializer `(config/initializers/rails_jskit.rb)`.
|
111
111
|
|
112
112
|
#### Dispatcher
|
113
113
|
|
@@ -472,7 +472,7 @@ Testing
|
|
472
472
|
|
473
473
|
One of the main advantages of RailsJSkit is that it provides a simple structure that's easily tested. There are however, a few things you need to keep in mind while testing JSkit controllers.
|
474
474
|
|
475
|
-
When testing, it's important to use the
|
475
|
+
When testing, it's important to use the [Controller Factories](#controller-factories) to create your test subjects. This ensures that you always have a fresh version of the controller that has not been mutated by previous tests. A basic jasmine/mocha style JSkit controller test looks something like this:
|
476
476
|
|
477
477
|
```js
|
478
478
|
// spec/javscripts/controllers/posts_controller_spec.js
|
@@ -6,7 +6,6 @@
|
|
6
6
|
*/
|
7
7
|
var JSkit = (function() {
|
8
8
|
if (!_) throw new Error("JSkit: lodash or underscore is required");
|
9
|
-
if (!$) throw new Error("JSkit: jQuery or equivalent is required");
|
10
9
|
|
11
10
|
return {
|
12
11
|
/**
|
@@ -27,8 +26,8 @@ var JSkit = (function() {
|
|
27
26
|
* @class Dispatcher
|
28
27
|
*/
|
29
28
|
JSkit.Dispatcher = (function() {
|
30
|
-
var
|
31
|
-
var
|
29
|
+
var any = _.any;
|
30
|
+
var each = _.each;
|
32
31
|
|
33
32
|
/**
|
34
33
|
Get all handler functions for a given dispatcher and event.
|
@@ -69,7 +68,7 @@ JSkit.Dispatcher = (function() {
|
|
69
68
|
*/
|
70
69
|
function registerHandler(registeredHandlers, eventHandler, method) {
|
71
70
|
method = method || "push";
|
72
|
-
if (!
|
71
|
+
if (!any(registeredHandlers, eventHandler)) {
|
73
72
|
registeredHandlers[method](eventHandler);
|
74
73
|
}
|
75
74
|
}
|
@@ -146,7 +145,7 @@ JSkit.Dispatcher = (function() {
|
|
146
145
|
var eventHhandlers = this.__events__[eventName] || [];
|
147
146
|
var args = _.rest(arguments);
|
148
147
|
|
149
|
-
|
148
|
+
each(eventHhandlers, function(eventHandler) {
|
150
149
|
var handler = eventHandler.handler;
|
151
150
|
var context = eventHandler.context;
|
152
151
|
handler.apply(context, args);
|
@@ -157,301 +156,228 @@ JSkit.Dispatcher = (function() {
|
|
157
156
|
};
|
158
157
|
})();
|
159
158
|
|
160
|
-
/**
|
161
|
-
* @module JSkit
|
162
|
-
* @class Controller
|
163
|
-
*/
|
164
159
|
JSkit.Controller = (function() {
|
160
|
+
var bind = _.bind;
|
165
161
|
var bindAll = _.bindAll;
|
162
|
+
var cloneDeep = _.cloneDeep;
|
166
163
|
var compact = _.compact;
|
167
164
|
var defaults = _.defaults;
|
168
165
|
var each = _.each;
|
166
|
+
var extend = _.extend;
|
169
167
|
var first = _.first;
|
170
168
|
var flatten = _.flatten;
|
171
|
-
var
|
172
|
-
var
|
169
|
+
var includes = _.includes;
|
170
|
+
var isArray = _.isArray;
|
171
|
+
var isFunction = _.isFunction;
|
173
172
|
var isObject = _.isObject;
|
174
173
|
var keys = _.keys;
|
175
174
|
var last = _.last;
|
176
175
|
var map = _.map;
|
177
|
-
var pairs = _.pairs;
|
178
176
|
var reduce = _.reduce;
|
179
|
-
var
|
180
|
-
|
177
|
+
var underscore = _.snakeCase;
|
178
|
+
|
179
|
+
function restrictKeywords(attrs) {
|
180
|
+
var keywords = [
|
181
|
+
"registerEvents",
|
182
|
+
"registerActions",
|
183
|
+
"cacheElements",
|
184
|
+
"eventNameForAction"
|
185
|
+
];
|
186
|
+
|
187
|
+
each(keys(attrs), function(keyword) {
|
188
|
+
if (includes(keywords, keyword)) {
|
189
|
+
throw new Error("JSkit.Controller.create: " + keyword + " is a restricted keyword");
|
190
|
+
}
|
191
|
+
});
|
192
|
+
}
|
181
193
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
*/
|
190
|
-
function underscore(string) {
|
191
|
-
string = string || "";
|
192
|
-
return string.replace(/([A-Z])/g, " $1").replace(/^\s?/, "").replace(/-|\s/g, "_").toLowerCase();
|
194
|
+
function eventNameForAction(controller, action) {
|
195
|
+
return compact([
|
196
|
+
controller.namespace,
|
197
|
+
controller.channel,
|
198
|
+
controller.controllerEventName,
|
199
|
+
action
|
200
|
+
]).join(controller.eventSeparator);
|
193
201
|
}
|
194
202
|
|
195
|
-
|
196
|
-
|
197
|
-
*
|
198
|
-
* @private
|
199
|
-
* @method registerActions
|
200
|
-
* @param {Controller} controller
|
201
|
-
*/
|
202
|
-
function registerActions(controller) {
|
203
|
-
each(controller.actions, function(action) {
|
204
|
-
each(mapAction(action), function(actionMap) {
|
205
|
-
ensureActionIsDefined(controller, actionMap);
|
206
|
-
controller.dispatcher.on(actionEventName(controller, actionMap.name), controller[actionMap.method], controller);
|
207
|
-
}, controller);
|
208
|
-
}, controller);
|
203
|
+
function registerAllAction(controller) {
|
204
|
+
if (!includes(controller.actions, "all")) controller.actions.unshift("all");
|
209
205
|
}
|
210
206
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
* @private
|
216
|
-
* @method mapAction
|
217
|
-
* @param {String,Object} action/mappedAction
|
218
|
-
* @return {Array} action/event maps
|
219
|
-
*/
|
220
|
-
function mapAction(action) {
|
221
|
-
return isObject(action) ? map(action, createActionMap) : [createActionMap(action, action)];
|
207
|
+
function normalizeActions(controller) {
|
208
|
+
controller.__actions__ = flatten(map(controller.actions, function(action) {
|
209
|
+
return normalizeAction(action);
|
210
|
+
}));
|
222
211
|
}
|
223
212
|
|
224
|
-
|
225
|
-
|
226
|
-
*
|
227
|
-
* @private
|
228
|
-
* @method createActionMap
|
229
|
-
* @param {String} method to map to action
|
230
|
-
* @param {String} action to map to method
|
231
|
-
*/
|
232
|
-
function createActionMap(method, action) {
|
233
|
-
return { name: action, method: method };
|
213
|
+
function normalizeAction(action) {
|
214
|
+
return isObject(action) ? map(action, createActionObject) : [createActionObject(action, action)];
|
234
215
|
}
|
235
216
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
* @param {Controller} controller
|
244
|
-
* @param {Object} actionMap
|
245
|
-
*/
|
246
|
-
function ensureActionIsDefined(controller, actionMap) {
|
247
|
-
if (!isFunc(controller[actionMap.method])) {
|
248
|
-
throw new Error(controller.name + ' action "' + actionMap.name + ":" + actionMap.method + '" method is undefined');
|
217
|
+
function createActionObject(method, name) {
|
218
|
+
return { name: name, method: method };
|
219
|
+
}
|
220
|
+
|
221
|
+
function ensureActionIsDefined(controller, action) {
|
222
|
+
if (!isFunction(controller[action.method])) {
|
223
|
+
throw new Error(controller.name + ' action "' + action.name + ":" + action.method + '" method is undefined');
|
249
224
|
}
|
250
225
|
}
|
251
226
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
227
|
+
function registerActions(controller) {
|
228
|
+
each(controller.__actions__, function(action) {
|
229
|
+
ensureActionIsDefined(controller, action);
|
230
|
+
controller.dispatcher.on(eventNameForAction(controller, action.name), controller[action.method], controller);
|
231
|
+
});
|
232
|
+
}
|
233
|
+
|
234
|
+
function normalizeControllerElements(controller) {
|
235
|
+
controller.__elements__ = reduce(controller.elements, function(memo, elements, action) {
|
236
|
+
memo[action] = normalizeElements(elements);
|
237
|
+
return memo;
|
238
|
+
}, {});
|
239
|
+
}
|
240
|
+
|
241
|
+
function normalizeElements(elements) {
|
242
|
+
return reduce(elements, function(memo, selector, name) {
|
243
|
+
if (_.isArray(selector)) selector = first(selector);
|
244
|
+
memo[name] = selector;
|
245
|
+
return memo;
|
246
|
+
}, {});
|
247
|
+
}
|
248
|
+
|
249
|
+
function normalizeControllerEvents(controller) {
|
250
|
+
controller.__events__ = reduce(controller.elements, function(memo, elements, action) {
|
251
|
+
memo[action] = normalizeEvents(elements);
|
252
|
+
return memo;
|
253
|
+
}, {});
|
254
|
+
}
|
255
|
+
|
256
|
+
function normalizeEvents(elements) {
|
257
|
+
return reduce(elements, function(memo, selector, name) {
|
258
|
+
if (_.isArray(selector)) memo["$" + name] = last(selector);
|
259
|
+
|
260
|
+
return memo;
|
261
|
+
}, {});
|
262
|
+
}
|
263
|
+
|
264
|
+
function isMappedAction(action) {
|
265
|
+
return action.name != action.method;
|
266
|
+
}
|
267
|
+
|
268
|
+
function nativeFind(selector) {
|
269
|
+
return document.querySelectorAll(selector);
|
270
|
+
}
|
271
|
+
|
272
|
+
function findInDOM(selector) {
|
273
|
+
var finder = $ ? $ : nativeFind;
|
274
|
+
return finder(selector);
|
269
275
|
}
|
270
276
|
|
271
|
-
/**
|
272
|
-
* Iterate over the given controller's elements object
|
273
|
-
* and cache a reference to each selected element.
|
274
|
-
*
|
275
|
-
* @private
|
276
|
-
* @method cacheElements
|
277
|
-
* @param {Controller} controller
|
278
|
-
* @param {String} action
|
279
|
-
*/
|
280
277
|
function cacheElements(controller, action) {
|
281
|
-
if (
|
282
|
-
|
283
|
-
|
284
|
-
|
278
|
+
if (!action) throw new Error("JSkit.Controller.cacheElements: action is undefined");
|
279
|
+
|
280
|
+
var actionElements = controller.__elements__[action];
|
281
|
+
|
282
|
+
if (actionElements) {
|
283
|
+
each(actionElements, function(selector, name) {
|
284
|
+
var element = controller["$" + name] = findInDOM(selector);
|
285
|
+
|
286
|
+
if (!element.length) {
|
287
|
+
throw new Error("JSkit.Controller.cacheElements: " + selector + " is not in the DOM");
|
288
|
+
}
|
289
|
+
});
|
285
290
|
}
|
286
291
|
}
|
287
292
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
* @private
|
293
|
-
* @method registerEvents
|
294
|
-
* @param {Controller} controller
|
295
|
-
* @param {String} action
|
296
|
-
*/
|
297
|
-
function registerEvents(controller, action) {
|
298
|
-
if (reduceElements(controller.elements, last)[action]) {
|
299
|
-
each(reduceElements(controller.elements, last)[action], function(eventMap, element) {
|
300
|
-
each(eventMap, function(method, evnt) {
|
301
|
-
var handler = controller[method];
|
302
|
-
var $element = controller["$" + element];
|
303
|
-
$element.on(evnt, handler);
|
304
|
-
}, controller);
|
305
|
-
}, controller);
|
306
|
-
}
|
293
|
+
function decorateCacheElements(controller) {
|
294
|
+
controller.cacheElements = function(action) {
|
295
|
+
return cacheElements(controller, action);
|
296
|
+
};
|
307
297
|
}
|
308
298
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
* @method registerElementCaching
|
315
|
-
* @param {Controller} controller
|
316
|
-
*/
|
317
|
-
function registerElementCaching(controller) {
|
318
|
-
each(reduceElements(controller.elements, first), function(elements, action) {
|
319
|
-
controller.dispatcher.before(actionEventName(controller, action), function() {
|
320
|
-
cacheElements(controller, action);
|
321
|
-
}, controller);
|
322
|
-
}, controller);
|
299
|
+
function registerActionEvents(controller, action) {
|
300
|
+
each(controller.__events__[action], function(events, element) {
|
301
|
+
if (!controller[element]) cacheElements(controller, action);
|
302
|
+
registerElementEvents(controller, element, events);
|
303
|
+
});
|
323
304
|
}
|
324
305
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
* @private
|
330
|
-
* @method registerControllerEvents
|
331
|
-
* @param {Controller} controller
|
332
|
-
*/
|
333
|
-
function registerControllerEvents(controller) {
|
334
|
-
each(reduceElements(controller.elements, last), function(eventMap, action) {
|
335
|
-
controller.dispatcher.on(actionEventName(controller, action), function() {
|
336
|
-
registerEvents(controller, action);
|
337
|
-
}, controller);
|
338
|
-
}, controller);
|
306
|
+
function registerElementEvents(controller, element, events) {
|
307
|
+
var eventsBinder = bind(eventsBinderFor(events), controller);
|
308
|
+
var on = bind($.prototype.on, controller[element]);
|
309
|
+
eventsBinder(on);
|
339
310
|
}
|
340
311
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
* @param {Function} function to grab either head or tail (first, last)
|
351
|
-
* @return {Object}
|
352
|
-
*/
|
353
|
-
function reduceElements(elements, accessMethod) {
|
354
|
-
return reduce(elements, function(memo, value, key) {
|
355
|
-
memo[key] = {};
|
356
|
-
each(value, function(v, k) {
|
357
|
-
memo[key][k] = accessMethod(flatten([v]));
|
312
|
+
function eventsBinderFor(events) {
|
313
|
+
if(events instanceof Function) {
|
314
|
+
return events;
|
315
|
+
}
|
316
|
+
|
317
|
+
return function(on) {
|
318
|
+
var controller = this;
|
319
|
+
each(events, function(handler, evnt) {
|
320
|
+
on(evnt, controller[handler]);
|
358
321
|
});
|
359
|
-
|
360
|
-
|
322
|
+
};
|
323
|
+
}
|
324
|
+
|
325
|
+
function decorateRegisterEvents(controller) {
|
326
|
+
controller.registerEvents = function(action) {
|
327
|
+
return registerActionEvents(controller, action);
|
328
|
+
};
|
329
|
+
}
|
330
|
+
|
331
|
+
function registerCacheElementsForActions(controller) {
|
332
|
+
each(controller.__actions__, function(action) {
|
333
|
+
var eventName = eventNameForAction(controller, action.name);
|
334
|
+
controller.dispatcher.before(eventName, function() {
|
335
|
+
return cacheElements(controller, action.name);
|
336
|
+
})
|
337
|
+
});
|
338
|
+
}
|
339
|
+
|
340
|
+
function registerControllerElementEvents(controller) {
|
341
|
+
each(controller.__actions__, function(action) {
|
342
|
+
registerActionEvents(controller, action.name);
|
343
|
+
});
|
361
344
|
}
|
362
345
|
|
363
346
|
return {
|
364
|
-
/**
|
365
|
-
* Factory function to create fresh controller objects
|
366
|
-
* with the given attributes.
|
367
|
-
*
|
368
|
-
* @method create
|
369
|
-
* @static
|
370
|
-
* @param {Object} [attrs={}]
|
371
|
-
*
|
372
|
-
* @return {Controller}
|
373
|
-
*/
|
374
347
|
create: function(attrs) {
|
375
|
-
attrs =
|
376
|
-
if (!attrs.name) throw new Error("Controller
|
377
|
-
|
348
|
+
attrs = extend({}, attrs);
|
349
|
+
if (!attrs.name) throw new Error("JSkit.Controller: name is undefined");
|
350
|
+
restrictKeywords(attrs);
|
378
351
|
var controller = defaults(attrs, {
|
379
|
-
/**
|
380
|
-
* Array of actions to be wired up.
|
381
|
-
*
|
382
|
-
* @property actions
|
383
|
-
* @type Array
|
384
|
-
* @default []
|
385
|
-
*/
|
386
352
|
actions: [],
|
387
|
-
/**
|
388
|
-
* Namespace that controller events are namespaced under.
|
389
|
-
*
|
390
|
-
* @property namespace
|
391
|
-
* @type String
|
392
|
-
* @default ""
|
393
|
-
*/
|
394
|
-
namespace: "",
|
395
|
-
/**
|
396
|
-
* Channel that controller events use under namespace.
|
397
|
-
*
|
398
|
-
* @property channel
|
399
|
-
* @type String
|
400
|
-
* @default "controller"
|
401
|
-
*/
|
402
353
|
channel: "controller",
|
403
|
-
/**
|
404
|
-
* Underscored name of controller for use in events.
|
405
|
-
*
|
406
|
-
* @property controllerEventName
|
407
|
-
* @type String
|
408
|
-
* @default "controller"
|
409
|
-
*/
|
410
354
|
controllerEventName: underscore(attrs.name),
|
411
|
-
/**
|
412
|
-
* Event dispatcher for registering events.
|
413
|
-
*
|
414
|
-
* @property dispatcher
|
415
|
-
* @type Dispatcher
|
416
|
-
* @default JSkit.Dispatcher.create()
|
417
|
-
*/
|
418
355
|
dispatcher: JSkit.Dispatcher.create(),
|
419
|
-
/**
|
420
|
-
* Object of element names/selectors to
|
421
|
-
* cache per action.
|
422
|
-
*
|
423
|
-
* @property elements
|
424
|
-
* @type Object
|
425
|
-
* @default {}
|
426
|
-
*/
|
427
356
|
elements: {},
|
428
|
-
/**
|
429
|
-
* Object of events for each action to
|
430
|
-
* register on given elements.
|
431
|
-
*
|
432
|
-
* @property events
|
433
|
-
* @type Object
|
434
|
-
* @default {}
|
435
|
-
*/
|
436
357
|
eventSeparator: ":",
|
437
|
-
|
438
|
-
|
439
|
-
* @method all
|
440
|
-
*/
|
358
|
+
namespace: "",
|
359
|
+
initialize: function() {},
|
441
360
|
all: function() {},
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
*/
|
446
|
-
initialize: function() {}
|
361
|
+
eventNameForAction: function(action) {
|
362
|
+
return eventNameForAction(this, action);
|
363
|
+
}
|
447
364
|
});
|
365
|
+
|
448
366
|
bindAll(controller);
|
449
|
-
controller.actions.unshift("all");
|
450
367
|
|
451
|
-
|
452
|
-
|
368
|
+
registerAllAction(controller);
|
369
|
+
normalizeActions(controller);
|
453
370
|
registerActions(controller);
|
454
371
|
|
372
|
+
normalizeControllerElements(controller);
|
373
|
+
normalizeControllerEvents(controller);
|
374
|
+
|
375
|
+
registerCacheElementsForActions(controller);
|
376
|
+
registerControllerElementEvents(controller);
|
377
|
+
|
378
|
+
decorateCacheElements(controller);
|
379
|
+
decorateRegisterEvents(controller);
|
380
|
+
|
455
381
|
controller.initialize();
|
456
382
|
|
457
383
|
return controller;
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_jskit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dayton Nolan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -170,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
170
|
version: '0'
|
171
171
|
requirements: []
|
172
172
|
rubyforge_project:
|
173
|
-
rubygems_version: 2.
|
173
|
+
rubygems_version: 2.4.5.1
|
174
174
|
signing_key:
|
175
175
|
specification_version: 4
|
176
176
|
summary: Gem that provides Rails integration for jskit
|