diff --git a/htdocs/index.html b/htdocs/index.html index f18f659..d9296c9 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -31,6 +31,7 @@ + diff --git a/htdocs/lib/FrequencyDisplay.js b/htdocs/lib/FrequencyDisplay.js new file mode 100644 index 0000000..0353fd8 --- /dev/null +++ b/htdocs/lib/FrequencyDisplay.js @@ -0,0 +1,61 @@ +function FrequencyDisplay(element) { + this.element = $(element); + this.digits = []; + this.digitContainer = $(''); + this.element.html([this.digitContainer, $(' MHz')]); + this.decimalSeparator = (0.1).toLocaleString().substring(1, 2); + this.setFrequency(0); +} + +FrequencyDisplay.prototype.setFrequency = function(freq) { + this.frequency = freq; + var formatted = (freq / 1e6).toLocaleString(undefined, {maximumFractionDigits: 4, minimumFractionDigits: 4}); + var children = this.digitContainer.children(); + for (var i = 0; i < formatted.length; i++) { + if (!this.digits[i]) { + this.digits[i] = $(''); + var before = children[i]; + if (before) { + $(before).after(this.digits[i]); + } else { + this.digitContainer.append(this.digits[i]); + } + } + this.digits[i][(isNaN(formatted[i]) ? 'remove' : 'add') + 'Class']('digit'); + this.digits[i].html(formatted[i]); + } + while (this.digits.length > formatted.length) { + this.digits.pop().remove(); + } +}; + +function TuneableFrequencyDisplay(element) { + FrequencyDisplay.call(this, element); + this.setupEvents(); +} + +TuneableFrequencyDisplay.prototype = new FrequencyDisplay(); + +TuneableFrequencyDisplay.prototype.setupEvents = function() { + var me = this; + this.element.on('wheel', function(e){ + e.preventDefault(); + e.stopPropagation(); + + var index = me.digitContainer.find('.digit').index(e.target); + if (index < 0) return; + + var delta = 10 ** (Math.floor(Math.log10(me.frequency)) - index); + if (e.originalEvent.deltaY > 0) delta *= -1; + var newFrequency = me.frequency + delta; + + me.listeners.forEach(function(l) { + l(newFrequency); + }); + }); + this.listeners = []; +}; + +TuneableFrequencyDisplay.prototype.onFrequencyChange = function(listener){ + this.listeners.push(listener); +}; \ No newline at end of file diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index e81c4c1..45112f8 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -512,7 +512,7 @@ function Demodulator_default_analog(offset_frequency, subtype) { mkenvelopes(this.visible_range); this.parent.set(); //will have to change this when changing to multi-demodulator mode: - e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", center_freq + this.parent.offset_frequency, 1e6, 4); + tunedFrequencyDisplay.setFrequency(center_freq + this.parent.offset_frequency); return true; }; @@ -565,12 +565,12 @@ function demodulator_analog_replace(subtype, for_digital) { //this function shou update_digitalvoice_panels("openwebrx-panel-metadata-" + subtype); } -function demodulator_set_offset_frequency(which, to_what) { +function demodulator_set_offset_frequency(to_what) { if (to_what > bandwidth / 2 || to_what < -bandwidth / 2) return; demodulators[0].offset_frequency = Math.round(to_what); demodulators[0].set(); mkenvelopes(get_visible_freq_range()); - $("#webrx-actual-freq").html(format_frequency("{x} MHz", center_freq + to_what, 1e6, 4)); + tunedFrequencyDisplay.setFrequency(center_freq + to_what); } function waterfallWidth() { @@ -584,9 +584,11 @@ function waterfallWidth() { var scale_ctx; var scale_canvas; +var tunedFrequencyDisplay; +var mouseFrequencyDisplay; function scale_setup() { - e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", canvas_get_frequency(window.innerWidth / 2), 1e6, 4); + tunedFrequencyDisplay.setFrequency(canvas_get_frequency(window.innerWidth / 2)); scale_canvas = e("openwebrx-scale-canvas"); scale_ctx = scale_canvas.getContext("2d"); scale_canvas.addEventListener("mousedown", scale_canvas_mousedown, false); @@ -633,14 +635,14 @@ function scale_canvas_mousemove(evt) { else if (scale_canvas_drag_params.drag) { //call the drag_move for all demodulators (and they will decide if they're dragged) for (i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_move(evt.pageX); - if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(evt.pageX)); + if (!event_handled) demodulator_set_offset_frequency(scale_offset_freq_from_px(evt.pageX)); } } function frequency_container_mousemove(evt) { var frequency = center_freq + scale_offset_freq_from_px(evt.pageX); - e("webrx-mouse-freq").innerHTML = format_frequency("{x} MHz", frequency, 1e6, 4); + mouseFrequencyDisplay.setFrequency(frequency); } function scale_canvas_end_drag(x) { @@ -649,7 +651,7 @@ function scale_canvas_end_drag(x) { scale_canvas_drag_params.mouse_down = false; var event_handled = false; for (var i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_end(); - if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(x)); + if (!event_handled) demodulator_set_offset_frequency(scale_offset_freq_from_px(x)); } function scale_canvas_mouseup(evt) { @@ -916,8 +918,9 @@ function canvas_mousemove(evt) { mkscale(); bookmarks.position(); } + } else { + mouseFrequencyDisplay.setFrequency(canvas_get_frequency(relativeX)); } - else e("webrx-mouse-freq").innerHTML = format_frequency("{x} MHz", canvas_get_frequency(relativeX), 1e6, 4); } function canvas_container_mouseleave() { @@ -929,7 +932,7 @@ function canvas_mouseup(evt) { var relativeX = get_relative_x(evt); if (!canvas_drag) { - demodulator_set_offset_frequency(0, canvas_get_freq_offset(relativeX)); + demodulator_set_offset_frequency(canvas_get_freq_offset(relativeX)); } else { canvas_end_drag(); @@ -1534,7 +1537,7 @@ function initialize_demodulator() { demodulator_analog_replace(starting_mod); if (starting_offset_frequency) { demodulators[0].offset_frequency = starting_offset_frequency; - e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", center_freq + starting_offset_frequency, 1e6, 4); + tunedFrequencyDisplay.setFrequency(center_freq + starting_offset_frequency); demodulators[0].set(); mkscale(); } @@ -1787,6 +1790,11 @@ function openwebrx_init() { secondary_demod_init(); digimodes_init(); initPanels(); + tunedFrequencyDisplay = new TuneableFrequencyDisplay($('#webrx-actual-freq')); + tunedFrequencyDisplay.onFrequencyChange(function(f) { + demodulator_set_offset_frequency(f - center_freq); + }); + mouseFrequencyDisplay = new FrequencyDisplay($('#webrx-mouse-freq')); window.addEventListener("resize", openwebrx_resize); check_top_bar_congestion(); init_header();