diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js
index b98044b..aed1b17 100644
--- a/htdocs/lib/DemodulatorPanel.js
+++ b/htdocs/lib/DemodulatorPanel.js
@@ -165,10 +165,13 @@ DemodulatorPanel.prototype.updatePanels = function() {
modulation = this.getDemodulator().get_modulation();
var showing = 'openwebrx-panel-metadata-' + modulation;
- $(".openwebrx-meta-panel").each(function (_, p) {
+ var metaPanels = $(".openwebrx-meta-panel");
+ metaPanels.each(function (_, p) {
toggle_panel(p.id, p.id === showing);
});
- clear_metadata();
+ metaPanels.metaPanel().each(function() {
+ this.clear();
+ });
};
DemodulatorPanel.prototype.getDemodulator = function() {
diff --git a/htdocs/lib/MetaPanel.js b/htdocs/lib/MetaPanel.js
new file mode 100644
index 0000000..3be5529
--- /dev/null
+++ b/htdocs/lib/MetaPanel.js
@@ -0,0 +1,119 @@
+function MetaPanel(el) {
+ this.el = el;
+ this.modes = [];
+}
+
+MetaPanel.prototype.update = function(data) {
+};
+
+MetaPanel.prototype.isSupported = function(data) {
+ return this.modes.includes(data.protocol);
+};
+
+MetaPanel.prototype.clear = function() {
+ this.el.find(".openwebrx-meta-autoclear").text("");
+ this.el.find(".openwebrx-meta-slot").removeClass("active").removeClass("sync");
+};
+
+function DmrMetaSlot(el) {
+ this.el = $(el);
+}
+
+DmrMetaSlot.prototype.update = function(data) {
+ var id = "";
+ var name = "";
+ var target = "";
+ var group = false;
+ this.el[data['sync'] ? "addClass" : "removeClass"]("sync");
+ if (data['sync'] && data['sync'] === "voice") {
+ id = (data['additional'] && data['additional']['callsign']) || data['source'] || "";
+ name = (data['additional'] && data['additional']['fname']) || "";
+ if (data['type'] === "group") {
+ target = "Talkgroup: ";
+ group = true;
+ }
+ if (data['type'] === "direct") target = "Direct: ";
+ target += data['target'] || "";
+ this.el.addClass("active");
+ } else {
+ this.el.removeClass("active");
+ }
+ this.el.find(".openwebrx-dmr-id").text(id);
+ this.el.find(".openwebrx-dmr-name").text(name);
+ this.el.find(".openwebrx-dmr-target").text(target);
+ this.el.find(".openwebrx-meta-user-image")[group ? "addClass" : "removeClass"]("group");
+}
+
+function DmrMetaPanel(el) {
+ MetaPanel.call(this, el);
+ this.modes = ['DMR'];
+ this.slots = this.el.find('.openwebrx-meta-slot').toArray().map(function(el){
+ return new DmrMetaSlot(el);
+ });
+}
+
+DmrMetaPanel.prototype = new MetaPanel();
+
+DmrMetaPanel.prototype.update = function(data) {
+ if (!this.isSupported(data)) return;
+ if (data['slot']) {
+ var slot = this.slots[data['slot']];
+ slot.update(data);
+ } else {
+ this.clear();
+ }
+}
+
+DmrMetaPanel.prototype.clear = function() {
+ MetaPanel.prototype.clear.call(this);
+ this.el.find(".openwebrx-dmr-timeslot-panel").removeClass("muted");
+};
+
+function YsfMetaPanel(el) {
+ MetaPanel.call(this, el);
+ this.modes = ['YSF'];
+}
+
+YsfMetaPanel.prototype = new MetaPanel();
+
+YsfMetaPanel.prototype.update = function(data) {
+ if (!this.isSupported(data)) return;
+
+ var mode = " ";
+ var source = "";
+ var up = "";
+ var down = "";
+ if (data['mode'] && data['mode'] !== "") {
+ mode = "Mode: " + data['mode'];
+ source = data['source'] || "";
+ if (data['lat'] && data['lon'] && data['source']) {
+ source = "
" + source;
+ }
+ up = data['up'] ? "Up: " + data['up'] : "";
+ down = data['down'] ? "Down: " + data['down'] : "";
+ this.el.find(".openwebrx-meta-slot").addClass("active");
+ } else {
+ this.el.find(".openwebrx-meta-slot").removeClass("active");
+ }
+ this.el.find(".openwebrx-ysf-mode").text(mode);
+ this.el.find(".openwebrx-ysf-source").html(source);
+ this.el.find(".openwebrx-ysf-up").text(up);
+ this.el.find(".openwebrx-ysf-down").text(down);
+}
+
+MetaPanel.types = {
+ dmr: DmrMetaPanel,
+ ysf: YsfMetaPanel
+};
+
+$.fn.metaPanel = function() {
+ return this.map(function() {
+ var $self = $(this);
+ if (!$self.data('metapanel')) {
+ var matches = /^openwebrx-panel-metadata-([a-z]+)$/.exec($self.prop('id'));
+ var constructor = matches && MetaPanel.types[matches[1]] || MetaPanel;
+ $self.data('metapanel', new constructor($self));
+ }
+ return $self.data('metapanel');
+ });
+};
\ No newline at end of file
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js
index cbef892..e7d5303 100644
--- a/htdocs/openwebrx.js
+++ b/htdocs/openwebrx.js
@@ -790,7 +790,9 @@ function on_ws_recv(evt) {
Modes.setFeatures(json['value']);
break;
case "metadata":
- update_metadata(json['value']);
+ $('.openwebrx-meta-panel').metaPanel().each(function(){
+ this.update(json['value']);
+ });
break;
case "js8_message":
$("#openwebrx-panel-js8-message").js8().pushMessage(json['value']);
@@ -900,75 +902,6 @@ function on_ws_recv(evt) {
}
}
-function update_metadata(meta) {
- var el;
- if (meta['protocol']) switch (meta['protocol']) {
- case 'DMR':
- if (meta['slot']) {
- el = $("#openwebrx-panel-metadata-dmr").find(".openwebrx-dmr-timeslot-panel").get(meta['slot']);
- var id = "";
- var name = "";
- var target = "";
- var group = false;
- $(el)[meta['sync'] ? "addClass" : "removeClass"]("sync");
- if (meta['sync'] && meta['sync'] === "voice") {
- id = (meta['additional'] && meta['additional']['callsign']) || meta['source'] || "";
- name = (meta['additional'] && meta['additional']['fname']) || "";
- if (meta['type'] === "group") {
- target = "Talkgroup: ";
- group = true;
- }
- if (meta['type'] === "direct") target = "Direct: ";
- target += meta['target'] || "";
- $(el).addClass("active");
- } else {
- $(el).removeClass("active");
- }
- $(el).find(".openwebrx-dmr-id").text(id);
- $(el).find(".openwebrx-dmr-name").text(name);
- $(el).find(".openwebrx-dmr-target").text(target);
- $(el).find(".openwebrx-meta-user-image")[group ? "addClass" : "removeClass"]("group");
- } else {
- clear_metadata();
- }
- break;
- case 'YSF':
- el = $("#openwebrx-panel-metadata-ysf");
-
- var mode = " ";
- var source = "";
- var up = "";
- var down = "";
- if (meta['mode'] && meta['mode'] !== "") {
- mode = "Mode: " + meta['mode'];
- source = meta['source'] || "";
- if (meta['lat'] && meta['lon'] && meta['source']) {
- source = "
" + source;
- }
- up = meta['up'] ? "Up: " + meta['up'] : "";
- down = meta['down'] ? "Down: " + meta['down'] : "";
- $(el).find(".openwebrx-meta-slot").addClass("active");
- } else {
- $(el).find(".openwebrx-meta-slot").removeClass("active");
- }
- $(el).find(".openwebrx-ysf-mode").text(mode);
- $(el).find(".openwebrx-ysf-source").html(source);
- $(el).find(".openwebrx-ysf-up").text(up);
- $(el).find(".openwebrx-ysf-down").text(down);
-
- break;
- } else {
- clear_metadata();
- }
-
-}
-
-function clear_metadata() {
- $(".openwebrx-meta-panel .openwebrx-meta-autoclear").text("");
- $(".openwebrx-meta-slot").removeClass("active").removeClass("sync");
- $(".openwebrx-dmr-timeslot-panel").removeClass("muted");
-}
-
var waterfall_measure_minmax_now = false;
var waterfall_measure_minmax_continuous = false;
@@ -1301,6 +1234,8 @@ function digimodes_init() {
$(e.currentTarget).toggleClass("muted");
update_dmr_timeslot_filtering();
});
+
+ $('.openwebrx-meta-panel').metaPanel();
}
function update_dmr_timeslot_filtering() {
@@ -1348,7 +1283,7 @@ function toggle_panel(what, on) {
item.style.transitionProperty = 'transform';
} else {
item.movement = 'expand';
- item.style.display = 'block';
+ item.style.display = null;
setTimeout(function(){
item.style.transitionProperty = 'transform';
item.style.transform = 'perspective(600px) rotateX(0deg)';
diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py
index bac09e6..7563325 100644
--- a/owrx/controllers/assets.py
+++ b/owrx/controllers/assets.py
@@ -129,6 +129,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController):
"lib/MessagePanel.js",
"lib/Js8Threads.js",
"lib/Modes.js",
+ "lib/MetaPanel.js",
],
"map.js": [
"lib/jquery-3.2.1.min.js",