rails_jskit 5.0.2 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|