luci2: add CSS for grid views + mobile improvements
[project/luci2/ui.git] / luci2 / htdocs / luci2 / rpc.js
1 Class.extend({
2 _id: 1,
3 _batch: undefined,
4 _requests: { },
5
6 _call: function(req, cb)
7 {
8 var q = '';
9
10 if ($.isArray(req))
11 for (var i = 0; i < req.length; i++)
12 q += '%s%s.%s'.format(
13 q ? ';' : '/',
14 req[i].params[1],
15 req[i].params[2]
16 );
17 else
18 q += '/%s.%s'.format(req.params[1], req.params[2]);
19
20 return $.ajax('/ubus' + q, {
21 cache: false,
22 contentType: 'application/json',
23 data: JSON.stringify(req),
24 dataType: 'json',
25 type: 'POST',
26 timeout: L.globals.timeout,
27 _rpc_req: req
28 }).then(cb, cb);
29 },
30
31 _list_cb: function(msg)
32 {
33 var list = msg.result;
34
35 /* verify message frame */
36 if (typeof(msg) != 'object' || msg.jsonrpc != '2.0' || !msg.id || !$.isArray(list))
37 list = [ ];
38
39 return $.Deferred().resolveWith(this, [ list ]);
40 },
41
42 _call_cb: function(msg)
43 {
44 var data = [ ];
45 var type = Object.prototype.toString;
46 var reqs = this._rpc_req;
47
48 if (!$.isArray(reqs))
49 {
50 msg = [ msg ];
51 reqs = [ reqs ];
52 }
53
54 for (var i = 0; i < msg.length; i++)
55 {
56 /* fetch related request info */
57 var req = L.rpc._requests[reqs[i].id];
58 if (typeof(req) != 'object')
59 throw 'No related request for JSON response';
60
61 /* fetch response attribute and verify returned type */
62 var ret = undefined;
63
64 /* verify message frame */
65 if (typeof(msg[i]) == 'object' && msg[i].jsonrpc == '2.0')
66 if ($.isArray(msg[i].result) && msg[i].result[0] == 0)
67 ret = (msg[i].result.length > 1) ? msg[i].result[1] : msg[i].result[0];
68
69 if (req.expect)
70 {
71 for (var key in req.expect)
72 {
73 if (typeof(ret) != 'undefined' && key != '')
74 ret = ret[key];
75
76 if (typeof(ret) == 'undefined' || type.call(ret) != type.call(req.expect[key]))
77 ret = req.expect[key];
78
79 break;
80 }
81 }
82
83 /* apply filter */
84 if (typeof(req.filter) == 'function')
85 {
86 req.priv[0] = ret;
87 req.priv[1] = req.params;
88 ret = req.filter.apply(L.rpc, req.priv);
89 }
90
91 /* store response data */
92 if (typeof(req.index) == 'number')
93 data[req.index] = ret;
94 else
95 data = ret;
96
97 /* delete request object */
98 delete L.rpc._requests[reqs[i].id];
99 }
100
101 return $.Deferred().resolveWith(this, [ data ]);
102 },
103
104 list: function()
105 {
106 var params = [ ];
107 for (var i = 0; i < arguments.length; i++)
108 params[i] = arguments[i];
109
110 var msg = {
111 jsonrpc: '2.0',
112 id: this._id++,
113 method: 'list',
114 params: (params.length > 0) ? params : undefined
115 };
116
117 return this._call(msg, this._list_cb);
118 },
119
120 batch: function()
121 {
122 if (!$.isArray(this._batch))
123 this._batch = [ ];
124 },
125
126 flush: function()
127 {
128 if (!$.isArray(this._batch))
129 return L.deferrable([ ]);
130
131 var req = this._batch;
132 delete this._batch;
133
134 /* call rpc */
135 return this._call(req, this._call_cb);
136 },
137
138 declare: function(options)
139 {
140 var _rpc = this;
141
142 return function() {
143 /* build parameter object */
144 var p_off = 0;
145 var params = { };
146 if ($.isArray(options.params))
147 for (p_off = 0; p_off < options.params.length; p_off++)
148 params[options.params[p_off]] = arguments[p_off];
149
150 /* all remaining arguments are private args */
151 var priv = [ undefined, undefined ];
152 for (; p_off < arguments.length; p_off++)
153 priv.push(arguments[p_off]);
154
155 /* store request info */
156 var req = _rpc._requests[_rpc._id] = {
157 expect: options.expect,
158 filter: options.filter,
159 params: params,
160 priv: priv
161 };
162
163 /* build message object */
164 var msg = {
165 jsonrpc: '2.0',
166 id: _rpc._id++,
167 method: 'call',
168 params: [
169 L.globals.sid,
170 options.object,
171 options.method,
172 params
173 ]
174 };
175
176 /* when a batch is in progress then store index in request data
177 * and push message object onto the stack */
178 if ($.isArray(_rpc._batch))
179 {
180 req.index = _rpc._batch.push(msg) - 1;
181 return L.deferrable(msg);
182 }
183
184 /* call rpc */
185 return _rpc._call(msg, _rpc._call_cb);
186 };
187 }
188 });