diff --git a/.eslintrc b/.eslintrc index 64cc9da..35fcf81 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,3 +10,4 @@ rules: "guard-for-in": 0 "no-undefined": 0 "no-nested-ternary": 0 + "no-extend-native": ["error", { "exceptions": ["String"] }] diff --git a/README.md b/README.md index 0e89f18..83857c3 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ - Add modes - For example add a night layer and style - Updates selected node or list (incl. image stats cache-breaker) - not only overview tables +- Node filter is implemented - Zoom level if you click a node (`nodeZoom`) - Zoom level 22 available, but it is to close for a click - Formatted Code - Translation support - https://crowdin.com/project/meshviewer diff --git a/app.js b/app.js index 6e8875f..0401293 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,10 @@ 'use strict'; +// Node search polyfill for mobile browsers and IE +if (!String.prototype.includes) { + String.prototype.includes = function () { + return String.prototype.indexOf.apply(this, arguments) !== -1; + }; +} require.config({ baseUrl: 'lib', diff --git a/assets/icons/fonts/icon.ttf b/assets/icons/fonts/icon.ttf index 8b8d822..bf938cc 100644 Binary files a/assets/icons/fonts/icon.ttf and b/assets/icons/fonts/icon.ttf differ diff --git a/assets/icons/fonts/icon.woff b/assets/icons/fonts/icon.woff index 7cc19f4..ef0bc9e 100644 Binary files a/assets/icons/fonts/icon.woff and b/assets/icons/fonts/icon.woff differ diff --git a/assets/icons/fonts/icon.woff2 b/assets/icons/fonts/icon.woff2 index 0377338..6d92253 100644 Binary files a/assets/icons/fonts/icon.woff2 and b/assets/icons/fonts/icon.woff2 differ diff --git a/assets/icons/icon.scss b/assets/icons/icon.scss index d589691..89ca76a 100644 --- a/assets/icons/icon.scss +++ b/assets/icons/icon.scss @@ -43,3 +43,4 @@ @include icon('android-remove', '\f2f4'); @include icon('ios-person', '\f47e'); @include icon('layer', '\f229'); +@include icon('filter', '\f38B'); diff --git a/lib/filters/hostname.js b/lib/filters/hostname.js new file mode 100644 index 0000000..b311c07 --- /dev/null +++ b/lib/filters/hostname.js @@ -0,0 +1,41 @@ +define(function () { + 'use strict'; + + return function () { + var refreshFunctions = []; + var timer; + var input = document.createElement('input'); + + function refresh() { + clearTimeout(timer); + timer = setTimeout(function () { + refreshFunctions.forEach(function (f) { + f(); + }); + }, 250); + } + + function run(d) { + return (d.nodeinfo !== undefined ? d.nodeinfo.hostname.toLowerCase().includes(input.value.toLowerCase()) : ''); + } + + function setRefresh(f) { + refreshFunctions.push(f); + } + + function render(el) { + input.type = 'search'; + input.placeholder = _.t('sidebar.nodeFilter'); + input.addEventListener('input', refresh); + el.classList.add('filter-node'); + el.classList.add('ion-filter'); + el.appendChild(input); + } + + return { + run: run, + setRefresh: setRefresh, + render: render + }; + }; +}); diff --git a/lib/gui.js b/lib/gui.js index 815a839..b195a75 100644 --- a/lib/gui.js +++ b/lib/gui.js @@ -1,10 +1,10 @@ define(['chroma-js', 'map', 'sidebar', 'tabs', 'container', 'legend', 'linklist', 'nodelist', 'simplenodelist', 'infobox/main', 'proportions', 'forcegraph', 'title', 'about', 'datadistributor', - 'filters/filtergui'], + 'filters/filtergui', 'filters/hostname'], function (chroma, Map, Sidebar, Tabs, Container, Legend, Linklist, Nodelist, SimpleNodelist, Infobox, Proportions, ForceGraph, - Title, About, DataDistributor, FilterGUI) { + Title, About, DataDistributor, FilterGUI, HostnameFilter) { 'use strict'; return function (config, router) { @@ -105,6 +105,9 @@ define(['chroma-js', 'map', 'sidebar', 'tabs', 'container', 'legend', fanout.watchFilters(filterGUI); header.add(filterGUI); + var hostnameFilter = new HostnameFilter(); + fanout.addFilter(hostnameFilter); + sidebar.add(tabs); tabs.add('sidebar.actual', overview); tabs.add('node.nodes', nodelist); diff --git a/locale/de.json b/locale/de.json index 9034e42..0eadaa6 100644 --- a/locale/de.json +++ b/locale/de.json @@ -39,6 +39,7 @@ "copy":"Kopieren" }, "sidebar":{ + "nodeFilter": "Knotenfilter", "nodes":"%{total} Knoten, davon %{online} Knoten online", "clients":"mit %{smart_count} Nutzer |||| mit %{smart_count} Nutzern", "gateway":"auf %{smart_count} Gateway |||| auf %{smart_count} Gateways", diff --git a/locale/en.json b/locale/en.json index 1b4ec56..e3ec0ac 100644 --- a/locale/en.json +++ b/locale/en.json @@ -39,6 +39,7 @@ "copy": "Copy" }, "sidebar": { + "nodeFilter": "Node filter", "nodes": "%{total} nodes, including %{online} nodes online", "clients": "with %{smart_count} client |||| with %{smart_count} clients", "gateway": "on %{smart_count} gateway |||| on %{smart_count} gateways", diff --git a/scss/modules/_filter.scss b/scss/modules/_filter.scss index 4e690dc..8e209b0 100644 --- a/scss/modules/_filter.scss +++ b/scss/modules/_filter.scss @@ -37,4 +37,30 @@ } } } + + .filter-node { + border: 0; + padding: 0 5px; + width: 100%; + + &::before { + font-size: 1.8em; + } + + input { + background: transparent; + border: 0; + border-bottom: 1px solid $color-primary; + font-family: $font-family; + font-size: $font-size; + margin: 0 15px 0 3px; + outline: none; + padding: 0 2px; + width: 100%; + } + + button { + display: none; + } + } } diff --git a/scss/night.scss b/scss/night.scss index ddaa1ce..a7c8bf3 100644 --- a/scss/night.scss +++ b/scss/night.scss @@ -35,6 +35,13 @@ html { } } + //@import 'modules/filter'; + .filter-node { + input { + color: $color-black; + } + } + //@import 'modules/sidebar'; .sidebar { .infobox, .container {