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