X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=luci2%2Fhtdocs%2Fluci2%2Fluci2.js;h=2b13604497f90f21e51ee9a560bf6bd8c17f3abf;hb=7887ec7cd3897733129a4aa649d4c544418faeea;hp=7c099018aef80c076254df3025344a79a28d7cf4;hpb=ad4689b7aed8a254410e626b50a9483899cdb59e;p=project%2Fluci2%2Fui.git diff --git a/luci2/htdocs/luci2/luci2.js b/luci2/htdocs/luci2/luci2.js index 7c09901..2b13604 100644 --- a/luci2/htdocs/luci2/luci2.js +++ b/luci2/htdocs/luci2/luci2.js @@ -485,6 +485,152 @@ function LuCI2() return n; }; + this.toColor = function(str) + { + if (typeof(str) != 'string' || str.length == 0) + return '#CCCCCC'; + + if (str == 'wan') + return '#F09090'; + else if (str == 'lan') + return '#90F090'; + + var i = 0, hash = 0; + + while (i < str.length) + hash = str.charCodeAt(i++) + ((hash << 5) - hash); + + var r = (hash & 0xFF) % 128; + var g = ((hash >> 8) & 0xFF) % 128; + + var min = 0; + var max = 128; + + if ((r + g) < 128) + min = 128 - r - g; + else + max = 255 - r - g; + + var b = min + (((hash >> 16) & 0xFF) % (max - min)); + + return '#%02X%02X%02X'.format(0xFF - r, 0xFF - g, 0xFF - b); + }; + + this.parseIPv4 = function(str) + { + if ((typeof(str) != 'string' && !(str instanceof String)) || + !str.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) + return undefined; + + var num = [ ]; + var parts = str.split(/\./); + + for (var i = 0; i < parts.length; i++) + { + var n = parseInt(parts[i], 10); + if (isNaN(n) || n > 255) + return undefined; + + num.push(n); + } + + return num; + }; + + this.parseIPv6 = function(str) + { + if ((typeof(str) != 'string' && !(str instanceof String)) || + !str.match(/^[a-fA-F0-9:]+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/)) + return undefined; + + var parts = str.split(/::/); + if (parts.length == 0 || parts.length > 2) + return undefined; + + var lnum = [ ]; + if (parts[0].length > 0) + { + var left = parts[0].split(/:/); + for (var i = 0; i < left.length; i++) + { + var n = parseInt(left[i], 16); + if (isNaN(n)) + return undefined; + + lnum.push((n / 256) >> 0); + lnum.push(n % 256); + } + } + + var rnum = [ ]; + if (parts.length > 1 && parts[1].length > 0) + { + var right = parts[1].split(/:/); + + for (var i = 0; i < right.length; i++) + { + if (right[i].indexOf('.') > 0) + { + var addr = L.parseIPv4(right[i]); + if (!addr) + return undefined; + + rnum.push.apply(rnum, addr); + continue; + } + + var n = parseInt(right[i], 16); + if (isNaN(n)) + return undefined; + + rnum.push((n / 256) >> 0); + rnum.push(n % 256); + } + } + + if (rnum.length > 0 && (lnum.length + rnum.length) > 15) + return undefined; + + var num = [ ]; + + num.push.apply(num, lnum); + + for (var i = 0; i < (16 - lnum.length - rnum.length); i++) + num.push(0); + + num.push.apply(num, rnum); + + if (num.length > 16) + return undefined; + + return num; + }; + + this.isNetmask = function(addr) + { + if (!$.isArray(addr)) + return false; + + var c; + + for (c = 0; (c < addr.length) && (addr[c] == 255); c++); + + if (c == addr.length) + return true; + + if ((addr[c] == 254) || (addr[c] == 252) || (addr[c] == 248) || + (addr[c] == 240) || (addr[c] == 224) || (addr[c] == 192) || + (addr[c] == 128) || (addr[c] == 0)) + { + for (c++; (c < addr.length) && (addr[c] == 0); c++); + + if (c == addr.length) + return true; + } + + return false; + }; + this.globals = { timeout: 15000, resource: '/luci2', @@ -963,6 +1109,35 @@ function LuCI2() return this.set(conf, sid, opt, undefined); }, + get_first: function(conf, type, opt) + { + var sid = undefined; + + L.uci.sections(conf, type, function(s) { + if (typeof(sid) != 'string') + sid = s['.name']; + }); + + return this.get(conf, sid, opt); + }, + + set_first: function(conf, type, opt, val) + { + var sid = undefined; + + L.uci.sections(conf, type, function(s) { + if (typeof(sid) != 'string') + sid = s['.name']; + }); + + return this.set(conf, sid, opt, val); + }, + + unset_first: function(conf, type, opt) + { + return this.set_first(conf, type, opt, undefined); + }, + _reload: function() { var pkgs = [ ]; @@ -2562,6 +2737,30 @@ function LuCI2() return dev.getTrafficHistory(); }, + renderBadge: function() + { + var badge = $('') + .addClass('badge') + .text('%s: '.format(this.name())); + + var dev = this.getDevice(); + var subdevs = this.getSubdevices(); + + if (subdevs.length) + for (var j = 0; j < subdevs.length; j++) + badge.append($('') + .attr('src', subdevs[j].icon()) + .attr('title', '%s (%s)'.format(subdevs[j].description(), subdevs[j].name() || '?'))); + else if (dev) + badge.append($('') + .attr('src', dev.icon()) + .attr('title', '%s (%s)'.format(dev.description(), dev.name() || '?'))); + else + badge.append($('').text(L.tr('(No devices attached)'))); + + return badge; + }, + setDevices: function(devs) { var dev = this.getPhysdev(); @@ -4412,8 +4611,7 @@ function LuCI2() 'ipaddr': function() { - if (validation.types['ip4addr'].apply(this) || - validation.types['ip6addr'].apply(this)) + if (L.parseIPv4(this) || L.parseIPv6(this)) return true; validation.i18n('Must be a valid IP address'); @@ -4422,17 +4620,8 @@ function LuCI2() 'ip4addr': function() { - if (this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\S+))?$/)) - { - if ((RegExp.$1 >= 0) && (RegExp.$1 <= 255) && - (RegExp.$2 >= 0) && (RegExp.$2 <= 255) && - (RegExp.$3 >= 0) && (RegExp.$3 <= 255) && - (RegExp.$4 >= 0) && (RegExp.$4 <= 255) && - ((RegExp.$6.indexOf('.') < 0) - ? ((RegExp.$6 >= 0) && (RegExp.$6 <= 32)) - : (validation.types['ip4addr'].apply(RegExp.$6)))) - return true; - } + if (L.parseIPv4(this)) + return true; validation.i18n('Must be a valid IPv4 address'); return false; @@ -4440,62 +4629,74 @@ function LuCI2() 'ip6addr': function() { - if (this.match(/^([a-fA-F0-9:.]+)(\/(\d+))?$/)) - { - if (!RegExp.$2 || ((RegExp.$3 >= 0) && (RegExp.$3 <= 128))) - { - var addr = RegExp.$1; + if (L.parseIPv6(this)) + return true; - if (addr == '::') - { - return true; - } + validation.i18n('Must be a valid IPv6 address'); + return false; + }, - if (addr.indexOf('.') > 0) - { - var off = addr.lastIndexOf(':'); + 'netmask4': function() + { + if (L.isNetmask(L.parseIPv4(this))) + return true; - if (!(off && validation.types['ip4addr'].apply(addr.substr(off+1)))) - { - validation.i18n('Must be a valid IPv6 address'); - return false; - } + validation.i18n('Must be a valid IPv4 netmask'); + return false; + }, - addr = addr.substr(0, off) + ':0:0'; - } + 'netmask6': function() + { + if (L.isNetmask(L.parseIPv6(this))) + return true; - if (addr.indexOf('::') >= 0) - { - var colons = 0; - var fill = '0'; + validation.i18n('Must be a valid IPv6 netmask6'); + return false; + }, - for (var i = 1; i < (addr.length-1); i++) - if (addr.charAt(i) == ':') - colons++; + 'cidr4': function() + { + if (this.match(/^([0-9.]+)\/(\d{1,2})$/)) + if (RegExp.$2 <= 32 && L.parseIPv4(RegExp.$1)) + return true; - if (colons > 7) - { - validation.i18n('Must be a valid IPv6 address'); - return false; - } + validation.i18n('Must be a valid IPv4 prefix'); + return false; + }, - for (var i = 0; i < (7 - colons); i++) - fill += ':0'; + 'cidr6': function() + { + if (this.match(/^([a-fA-F0-9:.]+)\/(\d{1,3})$/)) + if (RegExp.$2 <= 128 && L.parseIPv6(RegExp.$1)) + return true; - if (addr.match(/^(.*?)::(.*?)$/)) - addr = (RegExp.$1 ? RegExp.$1 + ':' : '') + fill + - (RegExp.$2 ? ':' + RegExp.$2 : ''); - } + validation.i18n('Must be a valid IPv6 prefix'); + return false; + }, - if (addr.match(/^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/) != null) - return true; + 'ipmask4': function() + { + if (this.match(/^([0-9.]+)\/([0-9.]+)$/)) + { + var addr = RegExp.$1, mask = RegExp.$2; + if (L.parseIPv4(addr) && L.isNetmask(L.parseIPv4(mask))) + return true; + } - validation.i18n('Must be a valid IPv6 address'); - return false; - } + validation.i18n('Must be a valid IPv4 address/netmask pair'); + return false; + }, + + 'ipmask6': function() + { + if (this.match(/^([a-fA-F0-9:.]+)\/([a-fA-F0-9:.]+)$/)) + { + var addr = RegExp.$1, mask = RegExp.$2; + if (L.parseIPv6(addr) && L.isNetmask(L.parseIPv6(mask))) + return true; } - validation.i18n('Must be a valid IPv6 address'); + validation.i18n('Must be a valid IPv6 address/netmask pair'); return false; }, @@ -4898,7 +5099,7 @@ function LuCI2() if (typeof(a) != typeof(b)) return true; - if (typeof(a) == 'object') + if ($.isArray(a)) { if (a.length != b.length) return true; @@ -4909,6 +5110,18 @@ function LuCI2() return false; } + else if ($.isPlainObject(a)) + { + for (var k in a) + if (!(k in b)) + return true; + + for (var k in b) + if (!(k in a) || a[k] !== b[k]) + return true; + + return false; + } return (a != b); }, @@ -5776,7 +5989,7 @@ function LuCI2() return $('
') .addClass('form-control-static') .attr('id', this.id(sid)) - .html(this.ucivalue(sid)); + .html(this.ucivalue(sid) || this.label('placeholder')); }, formvalue: function(sid) @@ -5835,30 +6048,16 @@ function LuCI2() for (var i = 0; i < interfaces.length; i++) { var iface = interfaces[i]; - var badge = $('') - .addClass('badge') - .text('%s: '.format(iface.name())); - - var dev = iface.getDevice(); - var subdevs = iface.getSubdevices(); - - if (subdevs.length) - for (var j = 0; j < subdevs.length; j++) - badge.append(this._device_icon(subdevs[j])); - else if (dev) - badge.append(this._device_icon(dev)); - else - badge.append($('').text(L.tr('(No devices attached)'))); $('') .append($('') .addClass(itype + ' inline') - .append($('') + .append(this.validator(sid, $('') .attr('name', itype + id) .attr('type', itype) .attr('value', iface.name()) - .prop('checked', !!check[iface.name()])) - .append(badge)) + .prop('checked', !!check[iface.name()]), true)) + .append(iface.renderBadge())) .appendTo(ul); } @@ -5867,11 +6066,11 @@ function LuCI2() $('') .append($('') .addClass(itype + ' inline text-muted') - .append($('') + .append(this.validator(sid, $('') .attr('name', itype + id) .attr('type', itype) .attr('value', '') - .prop('checked', $.isEmptyObject(check))) + .prop('checked', $.isEmptyObject(check)), true)) .append(L.tr('unspecified'))) .appendTo(ul); } @@ -6283,6 +6482,11 @@ function LuCI2() return true; }, + sort: function(section1, section2) + { + return 0; + }, + sections: function(cb) { var s1 = L.uci.sections(this.map.uci_package); @@ -6293,6 +6497,8 @@ function LuCI2() if (this.filter(s1[i])) s2.push(s1[i]); + s2.sort(this.sort); + if (typeof(cb) == 'function') for (var i = 0; i < s2.length; i++) cb.call(this, s2[i]); @@ -7012,7 +7218,9 @@ function LuCI2() { var self = ev.data.self; - self.trigger('save', ev); + self.send().then(function() { + self.trigger('save', ev); + }); }, _ev_reset: function(ev) @@ -7271,9 +7479,8 @@ function LuCI2() }); }, - reset: function() + revert: function() { - var self = this; var packages = { }; for (var i = 0; i < this.sections.length; i++) @@ -7282,6 +7489,13 @@ function LuCI2() packages[this.uci_package] = true; L.uci.unload(L.toArray(packages)); + }, + + reset: function() + { + var self = this; + + self.revert(); return self.insertInto(self.target); }, @@ -7327,6 +7541,7 @@ function LuCI2() var self = ev.data.self; self.trigger('close', ev); + self.revert(); self.close(); },