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 var linkPos
= href
.indexOf(";");
151 linkPos
= href
.indexOf("/", linkPos
);
155 var link
= href
.substr(linkPos
);
164 var currentNode
= getUrlNode(window
.location
.pathname
);
166 if (currentNode
== "login"){
167 tree
= ["Main", "Login"];
169 }else if(currentNode
== "overview"){
170 tree
= ["Status", "Overview"];
171 lastNode
= $($($(".main > .main-left > .nav > .slide > .menu")[0]).next().find("a")[0]).parent();
175 $(".main > .main-left > .nav > .slide > .menu").each(function () {
176 var ulNode
= $(this);
177 ulNode
.next().find("a").each(function () {
179 var href
= that
.attr("href");
181 if (currentNode
.indexOf(getUrlNode(href
)) != -1){
183 ulNode
.next(".slide-menu").stop(true,true);
184 lastNode
= that
.parent();
185 tree
= [trimText(ulNode
.data("title")), trimText(that
.data("title"))];
186 lastNode
.addClass("active");
198 $(".main > .main-left > .nav > .slide > .menu").click(function () {
199 var ul
= $(this).next(".slide-menu");
201 if (!ul
.is(":visible")) {
202 menu
.addClass("active");
203 ul
.addClass("active");
204 ul
.stop(true).slideDown();
206 ul
.slideUp(function () {
207 menu
.removeClass("active");
208 ul
.removeClass("active");
214 * hook menu click and add the hash
216 $(".main > .main-left > .nav > .slide > .slide-menu > li > a").click(function () {
217 if (lastNode
!= undefined) lastNode
.removeClass("active");
218 $(this).parent().addClass("active");
219 $(".main > .loading").fadeIn("fast");
226 $(".main > .main-left > .nav > .slide > .slide-menu > li").click(function () {
227 if (lastNode
!= undefined) lastNode
.removeClass("active");
228 $(this).addClass("active");
229 $(".main > .loading").fadeIn("fast");
230 window
.location
= $($(this).find("a")[0]).attr("href");
235 * get current node and open it
237 if (!getCurrentNodeByUrl()){
238 if (tree
!= undefined && tree
[0] == "Status" && tree
[1] == "Overview"){
240 lastNode
.addClass("active");
241 $($(".main > .main-left > .nav > .slide > .menu")[0]).click();
244 if (tree
!= undefined){
245 mainNodeName
= "node-"+ tree
[0] + "-" + tree
[1];
246 mainNodeName
= mainNodeName
.replace(/[ \t\n\r\/]+/g,"_").toLowerCase();
247 $("body").addClass(mainNodeName
);
250 $(".cbi-button-up").val("");
251 $(".cbi-button-down").val("");
255 * hook other "A Label" and add hash to it.
257 $("#maincontent > .container").find("a").each(function () {
259 var onclick
= that
.attr("onclick");
260 if (onclick
== undefined || onclick
== ""){
261 that
.click(function () {
262 var href
= that
.attr("href");
263 if (href
.indexOf("#") == -1){
264 $(".main > .loading").fadeIn("fast");
274 var showSide
= false;
275 $(".showSide").click(function () {
277 $(".darkMask").stop(true).fadeOut();
278 $(".main-left").stop(true).animate({
283 $(".darkMask").stop(true).fadeIn();
284 $(".main-left").stop(true).animate({
292 $(".darkMask").click(function () {
295 $(".darkMask").stop(true).fadeOut();
296 $(".main-left").stop(true).animate({
302 $(window
).resize(function() {
303 if ($(window
).width() > 921) {
304 $(".main-left").css("width", "");
305 $(".darkMask").stop(true);
306 $(".darkMask").css("display", "none");
312 * fix legend position
314 $("legend").each(function () {
316 that
.after("<span class='panel-title'>" + that
.text() + "</span>");
320 $(".main-right").focus();
321 $(".main-right").blur();
322 $("input").attr("size", "0");
324 if (mainNodeName
!= undefined){
325 console
.log(mainNodeName
);
326 switch (mainNodeName
){
327 case "node-status-system_log":
328 case "node-status-kernel_log":
329 $("#syslog").focus(function () {
331 $(".main-right").focus();
332 $(".main-right").blur();
335 case "node-status-firewall":
336 var button
= $(".node-status-firewall > .main fieldset li > a");
337 button
.addClass("cbi-button cbi-button-reset a-to-btn");
339 case "node-system-reboot":
340 var button
= $(".node-system-reboot > .main > .main-right p > a");
341 button
.addClass("cbi-button cbi-input-reset a-to-btn");