2 LuCI2 - OpenWrt Web Interface
4 Copyright 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
13 String
.prototype.format = function()
15 var html_esc
= [/&/g, '&', /"/g, '"', /'/g, ''', /</g, '<', />/g, '>'];
16 var quot_esc = [/"/g
, '"', /'/g, '''];
19 for( var i = 0; i < r.length; i += 2 )
20 s = s.replace(r[i], r[i+1]);
26 var re = /^(([^%]*)%('.|0|\x20)?(-)?(\d
+)?(\.\d
+)?(%|b
|c
|d
|u
|f
|o
|s
|x
|X
|q
|h
|j
|t
|m
))/;
27 var a
= b
= [], numSubstitutions
= 0, numMatches
= 0;
29 while ((a
= re
.exec(str
)) != null)
32 var leftpart
= a
[2], pPad
= a
[3], pJustify
= a
[4], pMinLength
= a
[5];
33 var pPrecision
= a
[6], pType
= a
[7];
43 if (numSubstitutions
< arguments
.length
)
45 var param
= arguments
[numSubstitutions
++];
48 if (pPad
&& pPad
.substr(0,1) == "'")
49 pad
= leftpart
.substr(1,1);
53 var justifyRight
= true;
54 if (pJustify
&& pJustify
=== "-")
59 minLength
= parseInt(pMinLength
);
62 if (pPrecision
&& pType
== 'f')
63 precision
= parseInt(pPrecision
.substring(1));
70 subst
= (parseInt(param
) || 0).toString(2);
74 subst
= String
.fromCharCode(parseInt(param
) || 0);
78 subst
= (parseInt(param
) || 0);
82 subst
= Math
.abs(parseInt(param
) || 0);
86 subst
= (precision
> -1)
87 ? ((parseFloat(param
) || 0.0)).toFixed(precision
)
88 : (parseFloat(param
) || 0.0);
92 subst
= (parseInt(param
) || 0).toString(8);
100 subst
= ('' + (parseInt(param
) || 0).toString(16)).toLowerCase();
104 subst
= ('' + (parseInt(param
) || 0).toString(16)).toUpperCase();
108 subst
= esc(param
, html_esc
);
112 subst
= esc(param
, quot_esc
);
116 subst
= String
.serialize(param
);
123 var ts
= (param
|| 0);
126 tm
= Math
.floor(ts
/ 60);
131 th
= Math
.floor(tm
/ 60);
136 td
= Math
.floor(th
/ 24);
141 ? '%dd %dh %dm %ds'.format(td
, th
, tm
, ts
)
142 : '%dh %dm %ds'.format(th
, tm
, ts
);
147 var mf
= pMinLength
? parseInt(pMinLength
) : 1000;
148 var pr
= pPrecision
? Math
.floor(10*parseFloat('0'+pPrecision
)) : 2;
151 var val
= parseFloat(param
|| 0);
152 var units
= [ '', 'K', 'M', 'G', 'T', 'P', 'E' ];
154 for (i
= 0; (i
< units
.length
) && (val
> mf
); i
++)
157 subst
= val
.toFixed(pr
) + ' ' + units
[i
];
161 subst
= (typeof(subst
) == 'undefined') ? '' : subst
.toString();
163 if (minLength
> 0 && pad
.length
> 0)
164 for (var i
= 0; i
< (minLength
- subst
.length
); i
++)
165 subst
= justifyRight
? (pad
+ subst
) : (subst
+ pad
);
169 out
+= leftpart
+ subst
;
170 str
= str
.substr(m
.length
);
176 if (!window
.location
.origin
)
177 window
.location
.origin
= '%s//%s%s'.format(
178 window
.location
.protocol
,
179 window
.location
.hostname
,
180 (window
.location
.port
? ':' + window
.location
.port
: '')
187 var Class = function() { };
189 Class
.extend = function(properties
)
191 Class
.initializing
= true;
193 var prototype = new this();
194 var superprot
= this.prototype;
196 Class
.initializing
= false;
198 $.extend(prototype, properties
, {
199 callSuper: function() {
201 var meth
= arguments
[0];
203 if (typeof(superprot
[meth
]) != 'function')
206 for (var i
= 1; i
< arguments
.length
; i
++)
207 args
.push(arguments
[i
]);
209 return superprot
[meth
].apply(this, args
);
215 this.options
= arguments
[0] || { };
217 if (!Class
.initializing
&& typeof(this.init
) == 'function')
218 this.init
.apply(this, arguments
);
221 _class
.prototype = prototype;
222 _class
.prototype.constructor = _class
;
224 _class
.extend
= Class
.extend
;
229 Class
.require = function(name
)
231 var path
= '/' + name
.replace(/\./g, '/') + '.js
';
233 return $.ajax(path, {
238 }).then(function(text) {
239 var code = '%s
\n\n//@ sourceURL=%s/%s'.format(text, window.location.origin, path);
240 var construct
= eval(code
);
242 var parts
= name
.split(/\./);
243 var cparent
= L
.Class
|| (L
.Class
= { });
245 for (var i
= 1; i
< parts
.length
- 1; i
++)
247 cparent
= cparent
[parts
[i
]];
250 throw "Missing parent class";
253 cparent
[parts
[i
]] = construct
;
257 Class
.instantiate = function(name
)
259 Class
.require(name
).then(function() {
260 var parts
= name
.split(/\./);
262 var construct
= L
.Class
;
264 for (var i
= 1; i
< parts
.length
- 1; i
++)
266 iparent
= iparent
[parts
[i
]];
267 construct
= construct
[parts
[i
]];
270 throw "Missing parent class";
273 if (construct
[parts
[i
]])
274 iparent
[parts
[i
]] = new construct
[parts
[i
]]();
278 this.defaults = function(obj
, def
)
281 if (typeof(obj
[key
]) == 'undefined')
287 this.isDeferred = function(x
)
289 return (typeof(x
) == 'object' &&
290 typeof(x
.then
) == 'function' &&
291 typeof(x
.promise
) == 'function');
294 this.deferrable = function()
296 if (this.isDeferred(arguments
[0]))
299 var d
= $.Deferred();
300 d
.resolve
.apply(d
, arguments
);
309 plural: function(n
) { return 0 + (n
!= 1) },
315 var lang
= (navigator
.userLanguage
|| navigator
.language
|| 'en').toLowerCase();
316 var langs
= (lang
.indexOf('-') > -1) ? [ lang
, lang
.split(/-/)[0] ] : [ lang
];
318 for (var i
= 0; i
< langs
.length
; i
++)
319 $.ajax('%s/i18n/base.%s.json'.format(L
.globals
.resource
, langs
[i
]), {
323 success: function(data
) {
324 $.extend(L
.i18n
.catalog
, data
);
326 var pe
= L
.i18n
.catalog
[''];
329 delete L
.i18n
.catalog
[''];
331 var pf
= new Function('n', 'return 0 + (' + pe
+ ')');
338 L
.i18n
.loaded
= true;
343 this.tr = function(msgid
)
347 var msgstr
= L
.i18n
.catalog
[msgid
];
349 if (typeof(msgstr
) == 'undefined')
351 else if (typeof(msgstr
) == 'string')
357 this.trp = function(msgid
, msgid_plural
, count
)
361 var msgstr
= L
.i18n
.catalog
[msgid
];
363 if (typeof(msgstr
) == 'undefined')
364 return (count
== 1) ? msgid
: msgid_plural
;
365 else if (typeof(msgstr
) == 'string')
368 return msgstr
[L
.i18n
.plural(count
)];
371 this.trc = function(msgctx
, msgid
)
375 var msgstr
= L
.i18n
.catalog
[msgid
+ '\u0004' + msgctx
];
377 if (typeof(msgstr
) == 'undefined')
379 else if (typeof(msgstr
) == 'string')
385 this.trcp = function(msgctx
, msgid
, msgid_plural
, count
)
389 var msgstr
= L
.i18n
.catalog
[msgid
+ '\u0004' + msgctx
];
391 if (typeof(msgstr
) == 'undefined')
392 return (count
== 1) ? msgid
: msgid_plural
;
393 else if (typeof(msgstr
) == 'string')
396 return msgstr
[L
.i18n
.plural(count
)];
399 this.setHash = function(key
, value
)
402 var data
= this.getHash(undefined);
404 if (typeof(value
) == 'undefined')
415 for (var i
= 0; i
< keys
.length
; i
++)
420 h
+= keys
[i
] + ':' + data
[keys
[i
]];
424 location
.hash
= '#' + h
;
429 this.getHash = function(key
)
432 var tuples
= (location
.hash
|| '#').substring(1).split(/,/);
434 for (var i
= 0; i
< tuples
.length
; i
++)
436 var tuple
= tuples
[i
].split(/:/);
437 if (tuple
.length
== 2)
438 data
[tuple
[0]] = tuple
[1];
441 if (typeof(key
) != 'undefined')
447 this.toArray = function(x
)
457 var l
= x
.split(/\s+/);
458 for (var i
= 0; i
< l
.length
; i
++)
467 for (var i
= 0; i
< x
.length
; i
++)
471 else if ($.isPlainObject(x
))
475 if (x
.hasOwnProperty(k
))
484 this.toObject = function(x
)
494 var l
= x
.split(/\x+/);
495 for (var i
= 0; i
< l
.length
; i
++)
504 for (var i
= 0; i
< x
.length
; i
++)
508 else if ($.isPlainObject(x
))
517 this.filterArray = function(array
, item
)
519 if (!$.isArray(array
))
522 for (var i
= 0; i
< array
.length
; i
++)
523 if (array
[i
] === item
)
524 array
.splice(i
--, 1);
529 this.toClassName = function(str
, suffix
)
532 var l
= str
.split(/[\/.]/);
534 for (var i
= 0; i
< l
.length
; i
++)
536 n
+= l
[i
].charAt(0).toUpperCase() + l
[i
].substr(1).toLowerCase();
538 if (typeof(suffix
) == 'string')
544 this.toColor = function(str
)
546 if (typeof(str
) != 'string' || str
.length
== 0)
551 else if (str
== 'lan')
556 while (i
< str
.length
)
557 hash
= str
.charCodeAt(i
++) + ((hash
<< 5) - hash
);
559 var r
= (hash
& 0xFF) % 128;
560 var g
= ((hash
>> 8) & 0xFF) % 128;
570 var b
= min
+ (((hash
>> 16) & 0xFF) % (max
- min
));
572 return '#%02X%02X%02X'.format(0xFF - r
, 0xFF - g
, 0xFF - b
);
575 this.parseIPv4 = function(str
)
577 if ((typeof(str
) != 'string' && !(str
instanceof String
)) ||
578 !str
.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/))
582 var parts
= str
.split(/\./);
584 for (var i
= 0; i
< parts
.length
; i
++)
586 var n
= parseInt(parts
[i
], 10);
587 if (isNaN(n
) || n
> 255)
596 this.parseIPv6 = function(str
)
598 if ((typeof(str
) != 'string' && !(str
instanceof String
)) ||
599 !str
.match(/^[a-fA-F0-9:]+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/))
602 var parts
= str
.split(/::/);
603 if (parts
.length
== 0 || parts
.length
> 2)
607 if (parts
[0].length
> 0)
609 var left
= parts
[0].split(/:/);
610 for (var i
= 0; i
< left
.length
; i
++)
612 var n
= parseInt(left
[i
], 16);
616 lnum
.push((n
/ 256) >> 0);
622 if (parts
.length
> 1 && parts
[1].length
> 0)
624 var right
= parts
[1].split(/:/);
626 for (var i
= 0; i
< right
.length
; i
++)
628 if (right
[i
].indexOf('.') > 0)
630 var addr
= L
.parseIPv4(right
[i
]);
634 rnum
.push
.apply(rnum
, addr
);
638 var n
= parseInt(right
[i
], 16);
642 rnum
.push((n
/ 256) >> 0);
647 if (rnum
.length
> 0 && (lnum
.length
+ rnum
.length
) > 15)
652 num
.push
.apply(num
, lnum
);
654 for (var i
= 0; i
< (16 - lnum
.length
- rnum
.length
); i
++)
657 num
.push
.apply(num
, rnum
);
665 this.isNetmask = function(addr
)
667 if (!$.isArray(addr
))
672 for (c
= 0; (c
< addr
.length
) && (addr
[c
] == 255); c
++);
674 if (c
== addr
.length
)
677 if ((addr
[c
] == 254) || (addr
[c
] == 252) || (addr
[c
] == 248) ||
678 (addr
[c
] == 240) || (addr
[c
] == 224) || (addr
[c
] == 192) ||
679 (addr
[c
] == 128) || (addr
[c
] == 0))
681 for (c
++; (c
< addr
.length
) && (addr
[c
] == 0); c
++);
683 if (c
== addr
.length
)
693 sid
: '00000000000000000000000000000000'
696 Class
.instantiate('luci2.rpc');
697 Class
.instantiate('luci2.uci');
698 Class
.instantiate('luci2.network');
699 Class
.instantiate('luci2.wireless');
700 Class
.instantiate('luci2.firewall');
701 Class
.instantiate('luci2.system');
702 Class
.instantiate('luci2.session');
703 Class
.instantiate('luci2.ui');
704 Class
.instantiate('luci2.cbi');