2 * Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI
5 * Copyright 2015 Lutty Yang <lutty@wcan.in>
7 * Have a bug? Please create an issue here on GitHub!
8 * https://github.com/LuttyYang/luci-theme-material/issues
10 * luci-theme-bootstrap:
11 * Copyright 2008 Steven Barth <steven@midlink.org>
12 * Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
13 * Copyright 2012 David Menting <david@nut-bolt.nl>
16 * https://github.com/muicss/mui
18 * Licensed to the public under the Apache License 2.0
21 var b64
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
28 * Encode multi-byte Unicode string into utf-8 multiple single-byte characters
29 * (BMP / basic multilingual plane only)
31 * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
33 * @param {String} strUni Unicode string to be encoded as UTF-8
34 * @returns {String} encoded string
36 encode: function (strUni
) {
37 // use regular expressions & String.replace callback function for better efficiency
38 // than procedural approaches
39 var strUtf
= strUni
.replace(/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
41 var cc
= c
.charCodeAt(0);
42 return String
.fromCharCode(0xc0 | cc
>> 6, 0x80 | cc
& 0x3f);
44 .replace(/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
46 var cc
= c
.charCodeAt(0);
47 return String
.fromCharCode(0xe0 | cc
>> 12, 0x80 | cc
>> 6 & 0x3F, 0x80 | cc
& 0x3f);
52 * Decode utf-8 encoded string back into multi-byte Unicode characters
54 * @param {String} strUtf UTF-8 string to be decoded back to Unicode
55 * @returns {String} decoded string
57 decode: function (strUtf
) {
58 // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
59 var strUni
= strUtf
.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
60 function (c
) { // (note parentheses for precence)
61 var cc
= ((c
.charCodeAt(0) & 0x0f) << 12) | ((c
.charCodeAt(1) & 0x3f) << 6) | (c
.charCodeAt(2) & 0x3f);
62 return String
.fromCharCode(cc
);
64 .replace(/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
65 function (c
) { // (note parentheses for precence)
66 var cc
= (c
.charCodeAt(0) & 0x1f) << 6 | c
.charCodeAt(1) & 0x3f;
67 return String
.fromCharCode(cc
);
73 var c
= String
.fromCharCode(i
);
76 r64
[i
] = b64
.indexOf(c
);
79 function code(s
, discard
, alpha
, beta
, w1
, w2
) {
87 var c
= s
.charCodeAt(i
);
88 c
= c
< 256 ? alpha
[c
] : -1;
89 buffer
= (buffer
<< w1
) + c
;
91 while (bitsInBuffer
>= w2
) {
93 var tmp
= buffer
>> bitsInBuffer
;
94 result
+= beta
.charAt(tmp
);
95 buffer
^= tmp
<< bitsInBuffer
;
99 if (!discard
&& bitsInBuffer
> 0) result
+= beta
.charAt(buffer
<< (w2
- bitsInBuffer
));
103 var Plugin
= $.base64 = function (dir
, input
, encode
) {
104 return input
? Plugin
[dir
](input
, encode
) : dir
? null : this;
106 Plugin
.btoa
= Plugin
.encode = function (plain
, utf8encode
) {
107 plain
= Plugin
.raw
=== false || Plugin
.utf8encode
|| utf8encode
? UTF8
.encode(plain
) : plain
;
108 plain
= code(plain
, false, r256
, b64
, 8, 6);
109 return plain
+ '===='.slice((plain
.length
% 4) || 4);
111 Plugin
.atob
= Plugin
.decode = function (coded
, utf8decode
) {
112 coded
= String(coded
).split('=');
113 var i
= coded
.length
;
116 coded
[i
] = code(coded
[i
], true, r64
, a256
, 6, 8);
118 coded
= coded
.join('');
119 return Plugin
.raw
=== false || Plugin
.utf8decode
|| utf8decode
? UTF8
.decode(coded
) : coded
;
124 $(".main > .loading").fadeOut();
127 * trim text, Remove spaces, wrap
131 function trimText(text
) {
132 return text
.replace(/[ \t\n\r]+/g, " ");
136 var tree
= undefined;
137 var lastNode
= undefined;
138 var mainNodeName
= undefined;
141 * get the current node by Burl (primary)
142 * @returns {boolean} success?
144 function getCurrentNodeByUrl() {
146 var getUrlNode = function (href
){
147 if (!$('body').hasClass('logged-in')){
150 if (href
== "/cgi-bin/luci/"){
153 var link
= href
.substr(href
.indexOf("admin/"));
162 var currentNode
= getUrlNode(window
.location
.pathname
);
164 if (currentNode
== "login"){
165 tree
= ["Main", "Login"];
167 }else if(currentNode
== "overview"){
168 tree
= ["Status", "Overview"];
169 lastNode
= $($($(".main > .main-left > .nav > .slide > .menu")[0]).next().find("a")[0]).parent();
173 $(".main > .main-left > .nav > .slide > .menu").each(function () {
174 var ulNode
= $(this);
175 ulNode
.next().find("a").each(function () {
177 var href
= that
.attr("href");
179 if (currentNode
.indexOf(getUrlNode(href
)) != -1){
181 ulNode
.next(".slide-menu").stop(true,true);
182 lastNode
= that
.parent();
183 tree
= [trimText(ulNode
.data("title")), trimText(that
.data("title"))];
184 lastNode
.addClass("active");
196 $(".main > .main-left > .nav > .slide > .menu").click(function () {
197 var ul
= $(this).next(".slide-menu");
199 if (!ul
.is(":visible")) {
200 menu
.addClass("active");
201 ul
.addClass("active");
202 ul
.stop(true).slideDown("fast");
204 ul
.stop(true).slideUp("fast", function () {
205 menu
.removeClass("active");
206 ul
.removeClass("active");
212 * hook menu click and add the hash
214 $(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
215 if (lastNode
!= undefined) lastNode
.removeClass("active");
216 $(this).parent().addClass("active");
217 $(".main > .loading").fadeIn("fast");
224 $(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
225 if (lastNode
!= undefined) lastNode
.removeClass("active");
226 $(this).addClass("active");
227 $(".main > .loading").fadeIn("fast");
228 window
.location
= $($(this).find("a")[0]).attr("href");
233 * get current node and open it
235 if (!getCurrentNodeByUrl()){
236 if (tree
!= undefined && tree
[0] == "Status" && tree
[1] == "Overview"){
238 lastNode
.addClass("active");
239 $($(".main > .main-left > .nav > .slide > .menu")[0]).click();
242 if (tree
!= undefined){
243 mainNodeName
= "node-"+ tree
[0] + "-" + tree
[1];
244 mainNodeName
= mainNodeName
.replace(/[ \t\n\r\/]+/g,"_").toLowerCase();
245 $("body").addClass(mainNodeName
);
248 $(".cbi-button-up").val("");
249 $(".cbi-button-down").val("");
253 * hook other "A Label" and add hash to it.
255 $("#maincontent > .container").find("a").each(function () {
257 var onclick
= that
.attr("onclick");
258 if (onclick
== undefined || onclick
== ""){
259 that
.click(function () {
260 var href
= that
.attr("href");
261 if (href
.indexOf("#") == -1){
262 $(".main > .loading").fadeIn("fast");
272 var showSide
= false;
273 $(".showSide").click(function () {
275 $(".darkMask").stop(true).fadeOut("fast");
276 $(".main-left").stop(true).animate({
279 $(".main-right").css("overflow-y", "auto");
282 $(".darkMask").stop(true).fadeIn("fast");
283 $(".main-left").stop(true).animate({
286 $(".main-right").css("overflow-y", "hidden");
292 $(".darkMask").click(function () {
295 $(".darkMask").stop(true).fadeOut("fast");
296 $(".main-left").stop(true).animate({
299 $(".main-right").css("overflow-y", "auto");
303 $(window
).resize(function() {
304 if ($(window
).width() > 921) {
305 $(".main-left").css("width", "");
306 $(".darkMask").stop(true);
307 $(".darkMask").css("display", "none");
313 * fix legend position
315 $("legend").each(function () {
317 that
.after("<span class='panel-title'>" + that
.text() + "</span>");
321 $(".main-right").focus();
322 $(".main-right").blur();
323 $("input").attr("size", "0");
325 if (mainNodeName
!= undefined){
326 console
.log(mainNodeName
);
327 switch (mainNodeName
){
328 case "node-status-system_log":
329 case "node-status-kernel_log":
330 $("#syslog").focus(function () {
332 $(".main-right").focus();
333 $(".main-right").blur();
336 case "node-status-firewall":
337 var button
= $(".node-status-firewall > .main fieldset li > a");
338 button
.addClass("cbi-button cbi-button-reset a-to-btn");
340 case "node-system-reboot":
341 var button
= $(".node-system-reboot > .main > .main-right p > a");
342 button
.addClass("cbi-button cbi-input-reset a-to-btn");