Commit | Line | Data |
---|---|---|
67341f3c CW |
1 | (function(angular, $, _) { |
2 | angular.module('crmRouteBinder', CRM.angRequires('crmRouteBinder')); | |
3 | ||
4 | // While processing a change from the $watch()'d data, we set the "pendingUpdates" flag | |
5 | // so that automated URL changes don't cause a reload. | |
6 | var pendingUpdates = null, activeTimer = null, registered = false, ignorable = {}; | |
7 | ||
8 | function registerGlobalListener($injector) { | |
9 | if (registered) return; | |
10 | registered = true; | |
11 | ||
12 | $injector.get('$rootScope').$on('$routeUpdate', function () { | |
13 | // Only reload if someone else -- like the user or an <a href> -- changed URL. | |
14 | if (null === pendingUpdates) { | |
15 | $injector.get('$route').reload(); | |
16 | } | |
17 | }); | |
18 | } | |
19 | ||
20 | var formats = { | |
21 | json: { | |
22 | watcher: '$watchCollection', | |
23 | decode: angular.fromJson, | |
24 | encode: angular.toJson, | |
25 | default: {} | |
26 | }, | |
27 | raw: { | |
28 | watcher: '$watch', | |
29 | decode: function(v) { return v; }, | |
30 | encode: function(v) { return v; }, | |
31 | default: '' | |
32 | }, | |
33 | int: { | |
34 | watcher: '$watch', | |
35 | decode: function(v) { return parseInt(v); }, | |
36 | encode: function(v) { return v; }, | |
37 | default: 0 | |
38 | }, | |
39 | bool: { | |
40 | watcher: '$watch', | |
41 | decode: function(v) { return v === '1'; }, | |
42 | encode: function(v) { return v ? '1' : '0'; }, | |
43 | default: false | |
44 | } | |
45 | }; | |
46 | ||
47 | angular.module('crmRouteBinder').config(function ($provide) { | |
48 | $provide.decorator('$rootScope', function ($delegate, $injector, $parse) { | |
49 | Object.getPrototypeOf($delegate).$bindToRoute = function (options) { | |
50 | registerGlobalListener($injector); | |
51 | ||
52 | options.format = options.format || 'json'; | |
4581ff3f | 53 | var fmt = _.clone(formats[options.format]); |
284ed4f0 CW |
54 | if (options.deep) { |
55 | fmt.watcher = '$watch'; | |
56 | } | |
67341f3c CW |
57 | if (options.default === undefined) { |
58 | options.default = fmt.default; | |
59 | } | |
4581ff3f CW |
60 | var value, |
61 | _scope = this, | |
62 | $route = $injector.get('$route'), | |
63 | $timeout = $injector.get('$timeout'); | |
67341f3c | 64 | |
67341f3c CW |
65 | if (options.param in $route.current.params) { |
66 | value = fmt.decode($route.current.params[options.param]); | |
67 | } | |
68 | else { | |
b3dcd750 | 69 | value = _.cloneDeep(options.default); |
67341f3c CW |
70 | ignorable[options.param] = fmt.encode(options.default); |
71 | } | |
72 | $parse(options.expr).assign(_scope, value); | |
73 | ||
74 | // Keep the URL bar up-to-date. | |
75 | _scope[fmt.watcher](options.expr, function (newValue) { | |
76 | var encValue = fmt.encode(newValue); | |
4581ff3f CW |
77 | if (!_.isEqual(newValue, options.default) && $route.current.params[options.param] === encValue) { |
78 | return; | |
79 | } | |
67341f3c CW |
80 | |
81 | pendingUpdates = pendingUpdates || {}; | |
82 | pendingUpdates[options.param] = encValue; | |
83 | var p = angular.extend({}, $route.current.params, pendingUpdates); | |
4581ff3f CW |
84 | |
85 | angular.forEach(ignorable, function(v, k) { | |
86 | if (p[k] === v) { | |
87 | delete p[k]; | |
88 | } | |
89 | }); | |
90 | ||
91 | // Remove params from url if they equal their defaults | |
92 | if (_.isEqual(newValue, options.default)) { | |
93 | p[options.param] = null; | |
94 | } | |
95 | ||
67341f3c CW |
96 | $route.updateParams(p); |
97 | ||
98 | if (activeTimer) $timeout.cancel(activeTimer); | |
99 | activeTimer = $timeout(function () { | |
100 | pendingUpdates = null; | |
101 | activeTimer = null; | |
102 | ignorable = {}; | |
103 | }, 50); | |
284ed4f0 | 104 | }, options.deep); |
67341f3c CW |
105 | }; |
106 | ||
107 | return $delegate; | |
108 | }); | |
109 | }); | |
110 | ||
111 | })(angular, CRM.$, CRM._); |