Use a doT.js template for the serverlist
authorShadowNinja <shadowninja@minetest.net>
Sat, 2 Nov 2013 22:53:51 +0000 (18:53 -0400)
committerShadowNinja <shadowninja@minetest.net>
Sun, 3 Nov 2013 22:47:16 +0000 (17:47 -0500)
util/master/README.md [new file with mode: 0644]
util/master/index.html
util/master/list.js
util/master/servers.jst [new file with mode: 0644]
util/master/style.css

diff --git a/util/master/README.md b/util/master/README.md
new file mode 100644 (file)
index 0000000..4730dc2
--- /dev/null
@@ -0,0 +1,24 @@
+Minetest server list
+====================
+
+Setting up the webpage
+----------------------
+You will have to install node.js, doT.js and their dependencies to compile
+the serverlist webpage template.
+
+First install node.js, eg:
+    # apt-get install nodejs
+    # pacman -S nodejs
+    # emerge nodejs
+
+Then install doT.js and it's dependencies:
+    $ cd ~/code
+    $ git clone https://github.com/olado/doT.git
+    $ cd doT
+    $ npm install
+
+And finally compile the template:
+    $ cd ~/minetest/util/master
+    $ ~/code/doT/bin/dot-packer -s . -d .
+
+
index ad908fca8937559d2ce41c1245104ef750738ab0..339ebe565bc6700fc94036f2cc26fa2eb7b7a617 100644 (file)
@@ -1,12 +1,15 @@
 <!DOCTYPE html>
 <html>
-    <head>
-        <meta charset="utf-8">
-        <title>Minetest server list</title>
-        <link rel="stylesheet" href="style.css"/>
-    </head>
-    <body><div id="servers_table"></div></body>
+<head>
+       <meta charset="utf-8">
+       <title>Minetest server list</title>
+       <link rel="stylesheet" href="style.css" />
+       <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
+       <script src="servers.js"></script>
+       <script src="list.js"></script>
+</head>
+<body>
+       <div id="server_list"></div>
+</body>
 </html>
-<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
-<script>//var master = {root: 'http://servers.minetest.net/', limit:10, clients_min:1, no_flags:1, no_ping:1, no_uptime:1};</script>
-<script src="list.js"></script>
+
index 4e2104bc88a8f2567e12e030d99aa910a1a993cb..ee4568e249f1a26cffcaee70746a271d7423a250 100644 (file)
-var master_root, output_to;
 var master;
-if (!master) master = {
-    root: master_root,
-    output: output_to
-};
+if (!master) {
+       master = {
+               url: "http://servers.minetest.net/list",
+               output: "#server_list"
+       };
+}
+
+function humanTime(seconds) {
+       if (!seconds) return '?';
+       var conv = {
+               y: 31536000,
+               d: 86400,
+               h: 3600,
+               m: 60
+       }
+       for (var i in conv) {
+               if (seconds >= conv[i]) {
+                       return (seconds / conv[i]).toFixed(1) + i;
+               }
+       }
+}
 
-function e(s) {
-    if (typeof s === "undefined") s = '';
-    if (typeof s === "number") return s;
-    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); //mc"
+function escapeHTML(str) {
+       return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
 }
 
-function human_time(t, abs) {
-    var n = 's';
-    if (!t || t < 0) t = 0;
-    var f = 0;
-    var s = parseInt(abs ? (t || 0) : (new Date().getTime() / 1000 - (t || 0)));
-    if (!s || s <= 0) s = 0;
-    if (s == 0) return 'now';
-    if (s >= 60) {
-        s /= 60;
-        n = 'm';
-        if (s >= 60) {
-            s /= 60;
-            n = 'h';
-            f = 1;
-            if (s >= 24) {
-                s /= 24;
-                n = 'd';
-                f = 1;
-                if (s >= 30) {
-                    s /= 30;
-                    n = 'M';
-                    f = 1;
-                    if (s >= 12) {
-                        s /= 12;
-                        n = 'y';
-                        f = 1;
-                    }
-                }
-            }
-        }
-    }
-    return ((f ? parseFloat(s).toFixed(1) : parseInt(s)) + n);
+function addressString(server) {
+       var isIPv6 = server.address.indexOf(":") != -1;
+       var addrStr = (isIPv6 ? '[' : '') +
+               escapeHTML(server.address) +
+               (isIPv6 ? ']' : '');
+       var shortStr = addrStr;
+       addrStr += ':' + server.port;
+       var str = '<span'
+       if (shortStr.length > 25) {
+               shortStr = shortStr.substr(0, 23) + "&hellip;";
+               str += ' class="tooltip" title="' + addrStr + '"'
+       }
+       if (server.port != 30000)
+               shortStr += ':' + server.port;
+       return str + '>' + shortStr + '</span>';
 }
 
-function success(r) {
-    if (!r || !r.list) return;
-    var h = '';
-    if (!master.no_total && r.total && r.total_max)
-        h += '<div class="mts_total">Players: ' + r.total.clients + ('/' + r.total_max.clients) + ' servers: ' + r.total.servers + ('/' + r.total_max.servers) + '</div>';
-    h += '<table class="mts_table">';
-    if (r.list.length) {
-        h += '<tr class="mts_head">';
-        if (!master.no_address) h += '<th>ip[:port]</th>';
-        if (!master.no_clients) h += '<th>players/max</th>';
-        if (!master.no_version) h += '<th>version gameid mapgen</th>';
-        if (!master.no_name) h += '<th>name</th>';
-        if (!master.no_description) h += '<th>description</th>';
-        if (!master.no_flags) h += '<th>flags</th>';
-        if (!master.no_uptime) h += '<th>uptime age</th>';
-        if (!master.no_ping) h += '<th>ping</th>';
-        h += '</tr>';
-    }
-    var count = 0;
-    for (var i = 0; i < r.list.length; ++i) {
-        if (++count > master.limit && master.limit) break;
-        var s = r.list[i];
-        if (!s) continue;
-        if (master.clients_min && s.clients < master.clients_min) continue;
-        if (/:/.test(s.address)) s.address = '[' + s.address + ']';
-        h += '<tr class="mts_row">';
-        if (!master.no_address) h += '<td class="mts_address">' + e(s.address) + (s.port != 30000 ? (':' + e(s.port)) : '') + '</td>';
-        if (!master.no_clients) {
-            h += '<td class="mts_clients' + (s.clients && s.clients_list ? ' mts_is_clients' : '') + '">';
-            if (!master.no_clients_list && s.clients && s.clients_list) {
-                h += '<div class="mts_clients_list">Players (' + e(s.clients) + '):<br/>';
-                for (var ii in s.clients_list)
-                    h += e(s.clients_list[ii]) + '<br/>';
-                h += '</div>';
-            }
-            h += e(s.clients) + (s.clients_max ? '/' + e(s.clients_max) : '') + (s.clients_top ? ', ' + e(s.clients_top) : '') + '</td>';
-        }
-        var mods = 0;
-        if (s.mods && jQuery.isArray(s.mods))
-            mods = s.mods.length;
-        if (!master.no_version) {
-            h += '<td class="mts_version' + (mods ? ' mts_is_mods' : '') + '">' + e(s.version) + ' ' + e(s.gameid) + ' ' + e(s.mapgen);
-            if (!master.no_mods && mods) {
-                h += '<div class="mts_mods">Mods (' + mods + '):<br/>';
-                for (var ii in s.mods)
-                    h += e(s.mods[ii]) + '<br/>';
-                h += '</div>';
-            }
-            h += '</td>';
-        }
-        if (!master.no_name) {
-            h += '<td class="mts_url">';
-            if (s.url) h += '<a href="' + e(s.url) + '">';
-            h += e(s.name || s.url);
-            if (s.url) h += '</a>';
-            h += '</td>';
-        }
-        if (!master.no_description) h += '<td class="mts_description">' + e(s.description) + '</td>';
-        if (!master.no_flags) {
-            h += '<td class="mts_flags">' +
-                (s.password ? 'Pwd ' : '') +
-                (s.creative ? 'Cre ' : '') +
-                (s.damage ? 'Dmg ' : '') +
-                (s.pvp ? 'Pvp ' : '') +
-                (s.dedicated ? 'Ded ' : '') +
-                (s.rollback ? 'Rol ' : '') +
-                (s.liquid_finite ? 'Liq ' : '') +
-                '</td>';
-        }
-        if (!s.start || s.start < 0) s.start = 0;
-        if (!master.no_uptime) h += '<td class="mts_uptime">' + (s.uptime ? human_time(s.uptime, 1) : s.start ? human_time(s.start) : '') + (s.game_time ? ' ' + human_time(s.game_time, 1) : '') + '</td>';
-        if (!master.no_ping) h += '<td class="mts_ping">' + (s.ping ? parseFloat(s.ping).toFixed(3) * 1000 : '') + '</td>';
-        h += '</tr>';
-    }
-    h += '</table>';
-    if (master.clients_min || master.limit)
-        h += '<a href="#" onclick="delete master.limit;delete master.clients_min; get(1);">more...</a>';
-    jQuery(master.output || '#servers_table').html(h);
+function tooltipString(str, maxLen) {
+       str = escapeHTML(str);
+       var shortStr = str;
+       var ret = '<span';
+       if (shortStr.length > maxLen) {
+               shortStr = shortStr.substr(0, maxLen - 2) + "&hellip;";
+               ret += ' class="tooltip" title="' + str + '"';
+       }
+       return ret + '>' + shortStr + '</span>';
 }
 
-function get(refresh) {
-    jQuery.getJSON((master.root || '') + 'list', success);
-    if (!refresh && !master.no_refresh) setTimeout(get, 60000);
+function hoverList(name, list) {
+       if (!list || list.length == 0) return '';
+       var str = '<div class="hover_list">'
+       str += name + '(' + list.length + ')<br />';
+       for (var i in list) {
+               str += escapeHTML(list[i]) + '<br />';
+       }
+       return str + '</div>';
 }
+
+function draw(json) {
+       html = window.render.servers(json);
+       jQuery(master.output || '#server_list').html(html);
+}
+
+function get() {
+       jQuery.getJSON(master.url, draw);
+}
+
+if (!master.no_refresh) {
+       setInterval(get, 60 * 1000);
+}
+
 get();
+
diff --git a/util/master/servers.jst b/util/master/servers.jst
new file mode 100644 (file)
index 0000000..bbefe30
--- /dev/null
@@ -0,0 +1,68 @@
+{{? !master.no_total}}
+<div class="total">
+       Players: {{=it.total.clients}}/{{=it.total_max.clients}}&nbsp;
+       Servers: {{=it.total.servers}}/{{=it.total_max.servers}}
+</div>
+{{?}}
+<table>
+       <tr>
+               {{? !master.no_address}}<th>IP[:Port]</th>{{?}}
+               {{? !master.no_clients}}<th>Players/Max</th>{{?}}
+               {{? !master.no_version}}<th>Version, Gameid, MapGen</th>{{?}}
+               {{? !master.no_name}}<th>Name</th>{{?}}
+               {{? !master.no_description}}<th>Description</th>{{?}}
+               {{? !master.no_flags}}<th>Flags</th>{{?}}
+               {{? !master.no_uptime}}<th>Uptime, Age</th>{{?}}
+               {{? !master.no_ping}}<th>Ping</th>{{?}}
+       </tr>
+       {{~it.list :server:index}}
+       {{ if (master.limit && index + 1 > master.limit) break;}}
+       <tr>
+               {{? !master.no_address}}
+               <td class ="address">
+                       {{=addressString(server)}}
+               </td>{{?}}
+               {{? !master.no_clients}}
+               <td class="clients{{? server.clients_list && server.clients_list.length > 0}} hover_list_text{{?}}">
+                       {{=server.clients}}/{{=server.clients_max}} {{=server.clients_top}}
+                       {{=hoverList("Clients", server.clients_list)}}
+               </td>{{?}}
+               {{? !master.no_version}}
+               <td class="version{{? server.mods && server.mods.length > 0}} hover_list_text{{?}}">
+                       {{=escapeHTML(server.version)}}, {{=escapeHTML(server.gameid)}},&nbsp;
+                       {{=escapeHTML(server.mapgen || '?')}}
+                       {{=hoverList("Mods", server.mods)}}
+               </td>{{?}}
+               {{? !master.no_name}}
+               <td class="name">
+                       {{? server.url}}
+                               <a href="{{=escapeHTML(server.url)}}">{{=tooltipString(server.name, 25)}}</a>
+                       {{??}}
+                               {{=tooltipString(server.name, 25)}}
+                       {{?}}
+               </td>{{?}}
+               {{? !master.no_description}}
+               <td class="description">
+                       {{=tooltipString(server.description, 50)}}
+               </td>{{?}}
+               {{? !master.no_flags}}
+               <td class="flags">
+                       {{=server.creative ? 'Cre ' : ''}}
+                       {{=server.dedicated ? 'Ded ' : ''}}
+                       {{=server.damage ? 'Dmg ' : ''}}
+                       {{=server.liquid_finite ? 'Liq ' : ''}}
+                       {{=server.pvp ? 'PvP ' : ''}}
+                       {{=server.password ? 'Pwd ' : ''}}
+                       {{=server.rollback ? 'Rol ' : ''}}
+               </td>{{?}}
+               {{? !master.no_uptime}}
+               <td class="uptime">
+                       {{=humanTime(server.uptime)}}, {{=humanTime(server.game_time)}}
+               </td>{{?}}
+               {{? !master.no_ping}}
+               <td class="ping">
+                       {{=Math.floor(server.ping * 1000)}}
+               </td>{{?}}
+       </tr>
+       {{~}}
+</table>
index cff041216e4c29428832411de5d8789fed088d7a..47d58029bc89f88294ee8123cf1ab1c2fd00cf9f 100644 (file)
@@ -1,32 +1,31 @@
-table {
-  max-width: 100%;
-  background-color: transparent;
-  border-collapse: collapse;
-  border-spacing: 0;
+#server_list table {
+       max-width: 100%;
+       width: 100%;
+       background-color: transparent;
+       border-collapse: collapse;
+       border-spacing: 0;
+       font-size: small;
 }
 
-td, th {
-  border: 1px solid gray;
+#server_list td, #server_list th {
+       border: 1px solid gray;
 }
 
-div#table table {
-  width: 100%;
+.hover_list{
+       visibility: hidden;
+       border: gray solid 1px;
+       position: absolute;
+       z-index: 100;
+       background-color: white;
+       padding: 0.5em;
 }
 
-.mts_mods, .mts_clients_list {
-  visibility: hidden; 
-  border:gray solid 1px; 
-  position:absolute; 
-  z-index:100; 
-  background-color:white; 
-  padding:.5em;
+td:hover .hover_list {
+       visibility: visible;
 }
 
-.mts_version:hover .mts_mods, .mts_clients:hover .mts_clients_list {
-  visibility: visible;
+.hover_list_text, .tooltip {
+       text-decoration: underline;
+       text-decoration-style: dashed;
 }
 
-.mts_version.mts_is_mods, .mts_clients.mts_is_clients  {
-  text-decoration:underline; 
-  text-decoration-style:dashed;
-}