Commit | Line | Data |
---|---|---|
a2dc0f82 TO |
1 | // crmResource: Given a templateUrl "~/mymodule/myfile.html", load the matching HTML. |
2 | // This implementation loads partials and strings in per-module batches. | |
3 | // FIXME: handling of CRM.strings not well tested; may be racy | |
4 | (function(angular, $, _) { | |
5 | angular.module('crmResource', []); | |
6 | ||
7 | angular.module('crmResource').factory('crmResource', function($q, $http) { | |
8 | var modules = {}; // moduleQueue[module] = 'loading'|Object; | |
9 | var templates = {}; // templates[url] = HTML; | |
10 | ||
11 | function CrmResourceModule(name) { | |
12 | this.name = name; | |
13 | this.status = 'new'; // loading|loaded|error | |
14 | this.data = null; | |
15 | this.deferreds = []; | |
16 | } | |
17 | ||
18 | angular.extend(CrmResourceModule.prototype, { | |
19 | createDeferred: function createDeferred() { | |
20 | var deferred = $q.defer(); | |
21 | switch (this.status) { | |
22 | case 'new': | |
23 | case 'loading': | |
24 | this.deferreds.push(deferred); | |
25 | break; | |
26 | case 'loaded': | |
27 | deferred.resolve(this.data); | |
28 | break; | |
29 | case 'error': | |
30 | deferred.reject(); | |
31 | break; | |
32 | default: | |
33 | throw 'Unknown status: ' + this.status; | |
34 | } | |
35 | return deferred.promise; | |
36 | }, | |
37 | load: function load() { | |
38 | var module = this; | |
39 | this.status = 'loading'; | |
578d3d13 | 40 | var moduleUrl = CRM.url('civicrm/ajax/angular-modules', {modules: module.name, l: CRM.config.lcMessages, r: CRM.angular.cacheCode}); |
a2dc0f82 TO |
41 | $http.get(moduleUrl) |
42 | .success(function httpSuccess(data) { | |
43 | if (data[module.name]) { | |
44 | module.onSuccess(data[module.name]); | |
45 | } | |
46 | else { | |
47 | module.onError(); | |
48 | } | |
49 | }) | |
50 | .error(function httpError() { | |
51 | module.onError(); | |
52 | }); | |
53 | }, | |
54 | onSuccess: function onSuccess(data) { | |
55 | var module = this; | |
56 | this.data = data; | |
57 | this.status = 'loaded'; | |
58 | if (this.data.partials) { | |
59 | angular.extend(templates, this.data.partials); | |
60 | } | |
61 | if (this.data.strings) { | |
e3d90d6c | 62 | CRM.addStrings(this.data.domain, this.data.strings); |
a2dc0f82 TO |
63 | } |
64 | angular.forEach(this.deferreds, function(deferred) { | |
65 | deferred.resolve(module.data); | |
66 | }); | |
67 | delete this.deferreds; | |
68 | }, | |
69 | onError: function onError() { | |
70 | this.status = 'error'; | |
71 | angular.forEach(this.deferreds, function(deferred) { | |
72 | deferred.reject(); | |
73 | }); | |
74 | delete this.deferreds; | |
75 | } | |
76 | }); | |
77 | ||
78 | return { | |
79 | // @return Promise<ModuleData> | |
80 | getModule: function getModule(name) { | |
81 | if (!modules[name]) { | |
82 | modules[name] = new CrmResourceModule(name); | |
83 | modules[name].load(); | |
84 | } | |
85 | return modules[name].createDeferred(); | |
86 | }, | |
87 | // @return string|Promise<string> | |
88 | getUrl: function getUrl(url) { | |
89 | if (templates[url]) { | |
90 | return templates[url]; | |
91 | } | |
92 | ||
93 | var parts = url.split('/'); | |
94 | var deferred = $q.defer(); | |
95 | this.getModule(parts[1]).then( | |
96 | function() { | |
97 | if (templates[url]) { | |
98 | deferred.resolve({ | |
99 | status: 200, | |
100 | headers: function(name) { | |
101 | var headers = {'Content-type': 'text/html'}; | |
102 | return name ? headers[name] : headers; | |
103 | }, | |
104 | data: templates[url] | |
105 | }); | |
106 | } | |
107 | else { | |
108 | deferred.reject({status: 500}); // FIXME | |
109 | } | |
110 | }, | |
111 | function() { | |
112 | deferred.reject({status: 500}); // FIXME | |
113 | } | |
114 | ); | |
115 | ||
116 | return deferred.promise; | |
117 | } | |
118 | }; | |
119 | }); | |
120 | ||
121 | angular.module('crmResource').config(function($provide) { | |
122 | $provide.decorator('$templateCache', function($delegate, $http, $q, crmResource) { | |
123 | var origGet = $delegate.get; | |
124 | var urlPat = /^~\//; | |
125 | $delegate.get = function(url) { | |
126 | if (urlPat.test(url)) { | |
127 | return crmResource.getUrl(url); | |
128 | } | |
129 | else { | |
130 | return origGet.call(this, url); | |
131 | } | |
132 | }; | |
133 | return $delegate; | |
134 | }); | |
135 | }); | |
136 | ||
137 | })(angular, CRM.$, CRM._); |