From 3a5c862fa18d5f221e8b117289add36a65e4726e Mon Sep 17 00:00:00 2001 From: Ivo Sonderegger Date: Wed, 16 Sep 2020 14:17:18 +0200 Subject: [PATCH] Release 1.9.0 --- CHANGELOG.md | 7 + doc/Modelviewer.js.html | 291 ++++ doc/RepetitiveRequests.js.html | 2 +- doc/Sounding.js.html | 2 +- doc/Synview.js.html | 2 +- doc/ThermodynamicDiagram.js.html | 2 +- doc/ThermodynamicDiagramPluggable.js.html | 2 +- doc/Timeline.js.html | 2 +- doc/Tooltip.js.html | 2 +- doc/base_Collection.js.html | 2 +- doc/base_Named.js.html | 2 +- doc/base_NamedCollection.js.html | 2 +- doc/base_Unique.js.html | 2 +- doc/base_UniqueNamed.js.html | 2 +- doc/calc.js.html | 2 +- doc/events.js.html | 2 +- doc/external-Event.html | 2 +- doc/external-HTMLElement.html | 2 +- doc/external-SVG.html | 2 +- doc/external-XMLHttpRequest.html | 2 +- doc/external-jQuery.html | 2 +- doc/index.html | 1327 ++++++++++++++++- doc/index.js.html | 40 +- doc/modelviewer_Container.js.html | 707 +++++++++ doc/modelviewer_Display.js.html | 383 +++++ doc/modelviewer_NWPResources.js.html | 197 +++ doc/modelviewer_Node.js.html | 256 ++++ doc/modelviewer_OffsetVariable.js.html | 140 ++ doc/modelviewer_Resource.js.html | 236 +++ doc/modelviewer_Resources.js.html | 549 +++++++ doc/modelviewer_TimeVariable.js.html | 115 ++ doc/modelviewer_Variable.js.html | 106 ++ doc/modelviewer_VariableCollection.js.html | 178 +++ ...delviewer_display_SelectNavigation.js.html | 157 ++ doc/modelviewer_display_Simple.js.html | 147 ++ doc/modelviewer_resource_Image.js.html | 104 ++ doc/modelviewer_resource_Sounding.js.html | 108 ++ doc/module-meteoJS.html | 2 +- ...le-meteoJS_base_collection.Collection.html | 2 +- doc/module-meteoJS_base_collection.html | 2 +- doc/module-meteoJS_base_named.Named.html | 2 +- doc/module-meteoJS_base_named.html | 2 +- ..._base_namedCollection.NamedCollection.html | 2 +- doc/module-meteoJS_base_namedCollection.html | 2 +- doc/module-meteoJS_base_unique.Unique.html | 2 +- doc/module-meteoJS_base_unique.html | 2 +- ...-meteoJS_base_uniquenamed.UniqueNamed.html | 2 +- doc/module-meteoJS_base_uniquenamed.html | 2 +- doc/module-meteoJS_calc.html | 2 +- doc/module-meteoJS_events.html | 2 +- ...odule-meteoJS_modelviewer.Modelviewer.html | 225 +++ doc/module-meteoJS_modelviewer.html | 253 ++++ ...teoJS_modelviewer_container.Container.html | 310 ++++ doc/module-meteoJS_modelviewer_container.html | 554 +++++++ ...e-meteoJS_modelviewer_display.Display.html | 171 +++ doc/module-meteoJS_modelviewer_display.html | 294 ++++ ...lay_selectNavigation.SelectNavigation.html | 84 ++ ..._modelviewer_display_selectNavigation.html | 79 + ...oJS_modelviewer_display_simple.Simple.html | 121 ++ ...le-meteoJS_modelviewer_display_simple.html | 79 + doc/module-meteoJS_modelviewer_node.Node.html | 396 +++++ doc/module-meteoJS_modelviewer_node.html | 131 ++ ...modelviewer_nwpResources.NWPResources.html | 302 ++++ ...dule-meteoJS_modelviewer_nwpResources.html | 79 + ...lviewer_offsetVariable.OffsetVariable.html | 143 ++ ...le-meteoJS_modelviewer_offsetVariable.html | 147 ++ ...meteoJS_modelviewer_resource.Resource.html | 325 ++++ doc/module-meteoJS_modelviewer_resource.html | 175 +++ ...eoJS_modelviewer_resource_image.Image.html | 118 ++ ...le-meteoJS_modelviewer_resource_image.html | 133 ++ ...odelviewer_resource_sounding.Sounding.html | 118 ++ ...meteoJS_modelviewer_resource_sounding.html | 133 ++ ...teoJS_modelviewer_resources.Resources.html | 531 +++++++ doc/module-meteoJS_modelviewer_resources.html | 216 +++ ...modelviewer_timeVariable.TimeVariable.html | 139 ++ ...dule-meteoJS_modelviewer_timeVariable.html | 133 ++ ...meteoJS_modelviewer_variable.Variable.html | 118 ++ doc/module-meteoJS_modelviewer_variable.html | 133 ++ ...variableCollection.VariableCollection.html | 213 +++ ...eteoJS_modelviewer_variableCollection.html | 194 +++ ...repetitiveRequests.RepetitiveRequests.html | 2 +- doc/module-meteoJS_repetitiveRequests.html | 2 +- doc/module-meteoJS_sounding.Sounding.html | 2 +- doc/module-meteoJS_sounding.html | 2 +- ...module-meteoJS_sounding_parcel.Parcel.html | 2 +- doc/module-meteoJS_sounding_parcel.html | 2 +- doc/module-meteoJS_synview.html | 2 +- ...meteoJS_synview_collection.Collection.html | 2 +- doc/module-meteoJS_synview_collection.html | 2 +- ...module-meteoJS_synview_map.SynviewMap.html | 2 +- doc/module-meteoJS_synview_map.html | 2 +- doc/module-meteoJS_synview_map_ll.MapLL.html | 2 +- doc/module-meteoJS_synview_map_ll.html | 2 +- doc/module-meteoJS_synview_map_ol.MapOL.html | 2 +- doc/module-meteoJS_synview_map_ol.html | 2 +- ...ule-meteoJS_synview_resource.Resource.html | 2 +- doc/module-meteoJS_synview_resource.html | 2 +- ...resourceCollection.ResourceCollection.html | 2 +- ...le-meteoJS_synview_resourceCollection.html | 2 +- ...eoJS_synview_resource_GeoJSON.GeoJSON.html | 2 +- ...dule-meteoJS_synview_resource_GeoJSON.html | 2 +- ...view_resource_GeoJSONTile.GeoJSONTile.html | 2 +- ...-meteoJS_synview_resource_GeoJSONTile.html | 2 +- ...JS_synview_resource_Image.ImageStatic.html | 2 +- ...module-meteoJS_synview_resource_Image.html | 2 +- ...dule-meteoJS_synview_resource_OSM.OSM.html | 2 +- doc/module-meteoJS_synview_resource_OSM.html | 2 +- ...eteoJS_synview_resource_Vector.Vector.html | 2 +- ...odule-meteoJS_synview_resource_Vector.html | 2 +- ...ynview_resource_VectorTile.VectorTile.html | 2 +- ...e-meteoJS_synview_resource_VectorTile.html | 2 +- ...odule-meteoJS_synview_tooltip.Tooltip.html | 2 +- doc/module-meteoJS_synview_tooltip.html | 2 +- doc/module-meteoJS_synview_type.Type.html | 2 +- doc/module-meteoJS_synview_type.html | 2 +- ...synview_typeCollection.TypeCollection.html | 2 +- ...module-meteoJS_synview_typeCollection.html | 2 +- ...modynamicDiagram.ThermodynamicDiagram.html | 2 +- doc/module-meteoJS_thermodynamicDiagram.html | 2 +- ...uggable.ThermodynamicDiagramPluggable.html | 2 +- ...meteoJS_thermodynamicDiagramPluggable.html | 2 +- ...modynamicDiagram_axes_axes_axisLabels.html | 2 +- ...teoJS_thermodynamicDiagram_axes_xAxis.html | 2 +- ...thermodynamicDiagram_axes_xAxis.xAxis.html | 2 +- ...teoJS_thermodynamicDiagram_axes_yAxis.html | 2 +- ...thermodynamicDiagram_axes_yAxis.yAxis.html | 2 +- ...ram_coordinateSystem.CoordinateSystem.html | 2 +- ...thermodynamicDiagram_coordinateSystem.html | 2 +- ...gram_coordinateSystem_emagram.Emagram.html | 2 +- ...namicDiagram_coordinateSystem_emagram.html | 2 +- ...tem_skewTlogPDiagram.SkewTlogPDiagram.html | 2 +- ...ram_coordinateSystem_skewTlogPDiagram.html | 2 +- ...ateSystem_stueveDiagram.StueveDiagram.html | 2 +- ...iagram_coordinateSystem_stueveDiagram.html | 2 +- ...agram_diagramSounding.DiagramSounding.html | 2 +- ..._thermodynamicDiagram_diagramSounding.html | 2 +- ...eteoJS_thermodynamicDiagram_functions.html | 2 +- ...rmodynamicDiagram_hodograph.Hodograph.html | 2 +- ...eteoJS_thermodynamicDiagram_hodograph.html | 2 +- ...AltitudeDataArea.PlotAltitudeDataArea.html | 2 +- ...modynamicDiagram_plotAltitudeDataArea.html | 2 +- ...hermodynamicDiagram_plotArea.PlotArea.html | 2 +- ...meteoJS_thermodynamicDiagram_plotArea.html | 2 +- ...amicDiagram_plotDataArea.PlotDataArea.html | 2 +- ...oJS_thermodynamicDiagram_plotDataArea.html | 2 +- ...rmodynamicDiagram_tdDiagram.TDDiagram.html | 2 +- ...eteoJS_thermodynamicDiagram_tdDiagram.html | 2 +- ...ram_windbarbsProfile.WindbarbsProfile.html | 2 +- ...thermodynamicDiagram_windbarbsProfile.html | 2 +- ...ram_windspeedProfile.WindspeedProfile.html | 2 +- ...thermodynamicDiagram_windspeedProfile.html | 2 +- doc/module-meteoJS_timeline.Timeline.html | 2 +- doc/module-meteoJS_timeline.html | 2 +- ...-meteoJS_timeline_animation.Animation.html | 2 +- doc/module-meteoJS_timeline_animation.html | 2 +- ...e_animation_togglebutton.ToggleButton.html | 2 +- ...teoJS_timeline_animation_togglebutton.html | 2 +- ...e_navigationButtons.NavigationButtons.html | 2 +- ...le-meteoJS_timeline_navigationButtons.html | 2 +- ..._timeline_visualisation.Visualisation.html | 2 +- ...module-meteoJS_timeline_visualisation.html | 2 +- ...ine_visualisation_bsButtons.bsButtons.html | 2 +- ...eoJS_timeline_visualisation_bsButtons.html | 2 +- ...e_visualisation_bsDropdown.bsDropdown.html | 2 +- ...oJS_timeline_visualisation_bsDropdown.html | 2 +- ..._timeline_visualisation_slider.Slider.html | 2 +- ...meteoJS_timeline_visualisation_slider.html | 2 +- ...eoJS_timeline_visualisation_text.Text.html | 2 +- ...e-meteoJS_timeline_visualisation_text.html | 2 +- doc/module-meteoJS_tooltip.Tooltip.html | 2 +- doc/module-meteoJS_tooltip.html | 2 +- ...tip_bootstrapTooltip.BootstrapTooltip.html | 2 +- ...dule-meteoJS_tooltip_bootstrapTooltip.html | 2 +- doc/scripts/jsdoc-toc.js | 2 +- doc/sounding_Parcel.js.html | 2 +- doc/synview_Collection.js.html | 2 +- doc/synview_Resource.js.html | 2 +- doc/synview_ResourceCollection.js.html | 2 +- doc/synview_SynviewMap.js.html | 2 +- doc/synview_Tooltip.js.html | 2 +- doc/synview_Type.js.html | 2 +- doc/synview_TypeCollection.js.html | 2 +- doc/synview_map_MapLL.js.html | 2 +- doc/synview_map_MapOL.js.html | 2 +- doc/synview_resource_GeoJSON.js.html | 2 +- doc/synview_resource_GeoJSONTile.js.html | 2 +- doc/synview_resource_Image.js.html | 2 +- doc/synview_resource_OSM.js.html | 2 +- doc/synview_resource_Vector.js.html | 2 +- doc/synview_resource_VectorTile.js.html | 2 +- ...rmodynamicDiagram_CoordinateSystem.js.html | 2 +- ...ermodynamicDiagram_DiagramSounding.js.html | 2 +- doc/thermodynamicDiagram_Functions.js.html | 2 +- doc/thermodynamicDiagram_Hodograph.js.html | 2 +- ...ynamicDiagram_PlotAltitudeDataArea.js.html | 2 +- doc/thermodynamicDiagram_TDDiagram.js.html | 2 +- ...rmodynamicDiagram_WindbarbsProfile.js.html | 2 +- ...rmodynamicDiagram_WindspeedProfile.js.html | 2 +- ...ermodynamicDiagram_axes_axisLabels.js.html | 2 +- doc/thermodynamicDiagram_axes_xAxis.js.html | 2 +- doc/thermodynamicDiagram_axes_yAxis.js.html | 2 +- ...icDiagram_coordinateSystem_Emagram.js.html | 2 +- ..._coordinateSystem_SkewTlogPDiagram.js.html | 2 +- ...ram_coordinateSystem_StueveDiagram.js.html | 2 +- doc/thermodynamicDiagram_plotArea.js.html | 2 +- doc/thermodynamicDiagram_plotDataArea.js.html | 2 +- doc/timeline_Animation.js.html | 2 +- doc/timeline_NavigationButtons.js.html | 2 +- doc/timeline_Visualisation.js.html | 2 +- doc/timeline_animation_ToggleButton.js.html | 2 +- doc/timeline_visualisation_Slider.js.html | 2 +- doc/timeline_visualisation_Text.js.html | 2 +- doc/timeline_visualisation_bsButtons.js.html | 2 +- doc/timeline_visualisation_bsDropdown.js.html | 2 +- doc/tooltip_BootstrapTooltip.js.html | 2 +- meteoJS.min.js | 4 +- meteoJS.min.js.map | 2 +- package.json | 2 +- 218 files changed, 11262 insertions(+), 175 deletions(-) create mode 100644 doc/Modelviewer.js.html create mode 100644 doc/modelviewer_Container.js.html create mode 100644 doc/modelviewer_Display.js.html create mode 100644 doc/modelviewer_NWPResources.js.html create mode 100644 doc/modelviewer_Node.js.html create mode 100644 doc/modelviewer_OffsetVariable.js.html create mode 100644 doc/modelviewer_Resource.js.html create mode 100644 doc/modelviewer_Resources.js.html create mode 100644 doc/modelviewer_TimeVariable.js.html create mode 100644 doc/modelviewer_Variable.js.html create mode 100644 doc/modelviewer_VariableCollection.js.html create mode 100644 doc/modelviewer_display_SelectNavigation.js.html create mode 100644 doc/modelviewer_display_Simple.js.html create mode 100644 doc/modelviewer_resource_Image.js.html create mode 100644 doc/modelviewer_resource_Sounding.js.html create mode 100644 doc/module-meteoJS_modelviewer.Modelviewer.html create mode 100644 doc/module-meteoJS_modelviewer.html create mode 100644 doc/module-meteoJS_modelviewer_container.Container.html create mode 100644 doc/module-meteoJS_modelviewer_container.html create mode 100644 doc/module-meteoJS_modelviewer_display.Display.html create mode 100644 doc/module-meteoJS_modelviewer_display.html create mode 100644 doc/module-meteoJS_modelviewer_display_selectNavigation.SelectNavigation.html create mode 100644 doc/module-meteoJS_modelviewer_display_selectNavigation.html create mode 100644 doc/module-meteoJS_modelviewer_display_simple.Simple.html create mode 100644 doc/module-meteoJS_modelviewer_display_simple.html create mode 100644 doc/module-meteoJS_modelviewer_node.Node.html create mode 100644 doc/module-meteoJS_modelviewer_node.html create mode 100644 doc/module-meteoJS_modelviewer_nwpResources.NWPResources.html create mode 100644 doc/module-meteoJS_modelviewer_nwpResources.html create mode 100644 doc/module-meteoJS_modelviewer_offsetVariable.OffsetVariable.html create mode 100644 doc/module-meteoJS_modelviewer_offsetVariable.html create mode 100644 doc/module-meteoJS_modelviewer_resource.Resource.html create mode 100644 doc/module-meteoJS_modelviewer_resource.html create mode 100644 doc/module-meteoJS_modelviewer_resource_image.Image.html create mode 100644 doc/module-meteoJS_modelviewer_resource_image.html create mode 100644 doc/module-meteoJS_modelviewer_resource_sounding.Sounding.html create mode 100644 doc/module-meteoJS_modelviewer_resource_sounding.html create mode 100644 doc/module-meteoJS_modelviewer_resources.Resources.html create mode 100644 doc/module-meteoJS_modelviewer_resources.html create mode 100644 doc/module-meteoJS_modelviewer_timeVariable.TimeVariable.html create mode 100644 doc/module-meteoJS_modelviewer_timeVariable.html create mode 100644 doc/module-meteoJS_modelviewer_variable.Variable.html create mode 100644 doc/module-meteoJS_modelviewer_variable.html create mode 100644 doc/module-meteoJS_modelviewer_variableCollection.VariableCollection.html create mode 100644 doc/module-meteoJS_modelviewer_variableCollection.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd4bfe9..a73e9e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +## [1.9.0] - 2020-09-16 +### Added +- Modelviewer classes. Used to build an application to view different resources. + These resources belong to certain variables (like model run, displayed region, + etc.). Currently not every feature is implemented. + ## [1.8.1] - 2020-08-10 ### Added - Github workflows. @@ -72,6 +78,7 @@ will not work anymore, until you pass a callback to `getTimeText`. - Some tests with DOM usage. [Unreleased]: https://github.com/chird/meteoJS/compare/v1.8.1...HEAD +[1.9.0]: https://github.com/chird/meteoJS/compare/v1.8.1...v1.9.0 [1.8.1]: https://github.com/chird/meteoJS/compare/v1.8.0...v1.8.1 [1.8.0]: https://github.com/chird/meteoJS/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/chird/meteoJS/compare/v1.6.0...v1.7.0 diff --git a/doc/Modelviewer.js.html b/doc/Modelviewer.js.html new file mode 100644 index 00000000..0b556e99 --- /dev/null +++ b/doc/Modelviewer.js.html @@ -0,0 +1,291 @@ + + + + + + + Source: Modelviewer.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer
+ */
+import Collection from './base/Collection.js';
+import Timeline from './Timeline.js';
+
+/**
+ * Creates and returns a HTMLElement or jQuery object for a container. The
+ * content of the container is appended to this element. This function has to
+ * append the element to the modelviewer's containersNode.
+ * 
+ * @typedef {Function} module:meteoJS/modelviewer~makeContainerNode
+ * @param {module:meteoJS/modelviewer/container.Container} container
+ *   Container to append.
+ * @this module:meteoJS/modelviewer~Modelviewer
+ * @returns {HTMLElement|jQuery} Top node of the appended container.
+ */
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {Object} module:meteoJS/modelviewer~options
+ * @param {module:meteoJS/modelviewer/resources.Resources} resources
+ *   Available resources.
+ * @param {HTMLElement|jQuery} containersNode Node to append the containers.
+ * @param {module:meteoJS/timeline.Timeline} [timeline]
+ *   Shared Timeline between containers.
+ * @param {module:meteoJS/modelviewer~makeContainerNode} [makeContainerNode]
+ *   Function to create the top node of each container.
+ * @param {boolean} [firstTimeOnInit=true] - Selects the first time in timeline
+ *   once for the first time times are added to the timeline.
+ * @param {boolean} [lastTimeOnInit=false] - Selects the last time in timeline
+ *   once for the first time times are added to the timeline.
+ *   Ignored if firstTimeOnInit is true.
+ */
+
+/**
+ * @classdesc
+ 
+ * Entscheidet über das Design der Container (auch Darstellungsbreite -> entsprechend welche Navigation)
+ * Wie kann der User die Anordnung der Container ändern?
+   * Dies soll für Bootstrap aber auch allg. funktionieren
+   * Wie soll dazu die Navigation angepasst werden können
+ * Handelt wahrscheinlich die Darstellung der Container (irgendwie…)
+ * Eigentlich wäre gut, wenn auch keine Abhängikeit von jQuery… (geht das?)
+ * Output Container -> Modelviewer
+   * Kann entweder nur ein Bild/Sounding/etc. anzeigen
+   * Kann je nach dem auch noch Navigation(en) ausgeben
+   * Je nach Output unterschiedlicher Aufbau des Container-div's
+   * Wie übergibt man diesem Objekt die Darstellung (z.B. der Navigation)
+   * Navigation muss sich anpassen (Änderung einer Collection, Änderung der Resource, …)
+ * Wie löst man das Vererben der Anzeige des vorangegangenen Containers -> Modelviewer
+ * Wie löst man, dass öffnen eines nächsten Runs vom vorangegangenen Container -> Modelviewer
+ * Bei Image -> hover funktion -> Modelviewer
+ * Bei Image -> Überblenden von Punkten für z.B. Ensembles -> Modelviewer
+ * Default-Navigation mit <select>-Nodes. -> Modelviewer
+ * 2te Default-Navigation mit vertikal angeordneten Listen -> Modelviewer
+ * 
+ * ToDo:
+ * * Alle Zeitpunkte für Modell/Run
+ * * Alle Zeitpunkte für eine gewählte Resource (oder mind. displayVariables)
+ *   -> dabei sollten keine Unter-Nodes berücksichtigt werden.
+ * * Auswahl der DisplayVariable entweder nur per 1:1 Übereinstimmung oder aber
+ *   durch Best-Match (wie soll dies gelöst werden).
+ * Aktuell befindet sich ziemlicher Rubbish-Code in den Klassen.
+ * collectTimesVariableCollections in Resources ist nicht die Lösung
+ */
+export class Modelviewer extends Collection {
+  
+  /**
+   * @param {module:meteoJS/modelviewer~options} options - Options.
+   */
+  constructor({ resources,
+    containersNode,
+    timeline = undefined,
+    makeContainerNode = undefined,
+    firstTimeOnInit = true,
+    lastTimeOnInit = false } = {}) {
+    super({
+      fireReplace: false,
+      fireAddRemoveOnReplace: true
+    });
+    
+    /**
+     * @type module:meteoJS/modelviewer/resources.Resources
+     * @private
+     */
+    this._resources = resources;
+    
+    /**
+     * @type HTMLElement
+     * @private
+     */
+    this._containersNode =
+      (typeof containersNode == 'object' && containersNode.jquery)
+        ? containersNode[0] : containersNode;
+    
+    /**
+     * @type module:meteoJS/timeline.Timeline
+     * @private
+     */
+    this._timeline = (timeline === undefined) ? new Timeline() : timeline;
+    
+    /**
+     * @type undefined|Function
+     * @private
+     */
+    this._makeContainerNode = makeContainerNode;
+    
+    /**
+     * @type Map<module:meteoJS/modelviewer/container.Container,mixed>
+     * @private
+     */
+    let listenerKeys = new Map();
+    
+    this.on('add:item', container => {
+      container.modelviewer = this;
+      container.containerNode =
+        this._getContainerNode(container);
+      if (!isNaN(this.timeline.getSelectedTime().valueOf()) ||
+          !firstTimeOnInit && !lastTimeOnInit)
+        return;
+      
+      listenerKeys
+        .set(container, container.on('change:selectedVariables', ()  => {
+          if (isNaN(this._timeline.getSelectedTime().valueOf())) {
+            if (firstTimeOnInit)
+              this._timeline.first();
+            else if (lastTimeOnInit)
+              this._timeline.last();
+            if (!isNaN(this._timeline.getSelectedTime().valueOf()))
+              for (let c of listenerKeys.keys()) {
+                c.un('change:selectedVariables', listenerKeys.get(c));
+                listenerKeys.delete(c);
+              }
+          }
+        }));
+    });
+    
+    this.on('remove:item', container => {
+      if (container.containerNode !== undefined &&
+          container.containerNode.parentNode != null)
+        container.containerNode.parentNode.removeChild(container.containerNode);
+      container.modelviewer = undefined;
+      container.containerNode = undefined;
+      if (listenerKeys.has(container)) {
+        container.un('change:selectedVariables', listenerKeys.get(container));
+        listenerKeys.delete(container);
+      }
+    });
+  }
+  
+  /**
+   * Resources.
+   * 
+   * @type module:meteoJS/modelviewer/resources.Resources
+   * @readonly
+   */
+  get resources() {
+    return this._resources;
+  }
+  
+  /**
+   * Node to append the container's node into.
+   * 
+   * @type HTMLElement
+   * @readonly
+   */
+  get containersNode() {
+    return this._containersNode;
+  }
+  
+  /**
+   * Timeline.
+   * 
+   * @type module:meteoJS/timeline.Timeline
+   * @readonly
+   */
+  get timeline() {
+    return this._timeline;
+  }
+  
+  /**
+   * Appends container(s).
+   * 
+   * @param {...module:meteoJS/modelviewer/container.Container} containers
+   *   New containers.
+   * @returns {module:meteoJS/modelviewer.Modelviewer} This.
+   * @override
+   */
+  append(...containers) {
+    let ids = [...this.itemIds];
+    containers
+      .filter(container => container.id !== undefined)
+      .forEach(container => ids.push(container.id));
+    containers
+      .filter(container => container.id === undefined)
+      .forEach(container => {
+        let i = 1;
+        let id = `container${i}`;
+        while (ids.indexOf(id) > -1) {
+          i++;
+          id = `container${i}`;
+        }
+        container.id = id;
+        ids.push(id);
+      });
+    super.append(...containers);
+    return this;
+  }
+  
+  /**
+   * Creates a HTMLElement to append the container content into it. This
+   * element is appended to the containersNode.
+   * 
+   * @param {module:meteoJS/modelviewer/container.Container} container
+   *   Create Node for this container.
+   * @returns {HTMLElement} Node.
+   * @private
+   */
+  _getContainerNode(container) {
+    if (this._makeContainerNode !== undefined) {
+      let result =
+        this._makeContainerNode.call(this, this.containersNode, container);
+      return (typeof result == 'object' && result.jquery) ? result[0] : result;
+    }
+    else {
+      let containerNode =
+        (container.containerNode !== undefined)
+          ? container.containerNode
+          : document.createElement('div');
+      if (this.containersNode !== undefined)
+        this.containersNode.appendChild(containerNode);
+      return containerNode;
+    }
+  }
+}
+export default Modelviewer;
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/doc/RepetitiveRequests.js.html b/doc/RepetitiveRequests.js.html index 16d7e6a0..dedb70d6 100644 --- a/doc/RepetitiveRequests.js.html +++ b/doc/RepetitiveRequests.js.html @@ -356,7 +356,7 @@

Source: RepetitiveRequests.js

diff --git a/doc/Sounding.js.html b/doc/Sounding.js.html index 388879ea..4bfe472c 100644 --- a/doc/Sounding.js.html +++ b/doc/Sounding.js.html @@ -277,7 +277,7 @@

Source: Sounding.js

diff --git a/doc/Synview.js.html b/doc/Synview.js.html index 8cfa1a48..12a88c99 100644 --- a/doc/Synview.js.html +++ b/doc/Synview.js.html @@ -201,7 +201,7 @@

Source: Synview.js

diff --git a/doc/ThermodynamicDiagram.js.html b/doc/ThermodynamicDiagram.js.html index 90c70383..457848d8 100644 --- a/doc/ThermodynamicDiagram.js.html +++ b/doc/ThermodynamicDiagram.js.html @@ -300,7 +300,7 @@

Source: ThermodynamicDiagram.js

diff --git a/doc/ThermodynamicDiagramPluggable.js.html b/doc/ThermodynamicDiagramPluggable.js.html index 26cfc2ce..81ca2cf2 100644 --- a/doc/ThermodynamicDiagramPluggable.js.html +++ b/doc/ThermodynamicDiagramPluggable.js.html @@ -231,7 +231,7 @@

Source: ThermodynamicDiagramPluggable.js

diff --git a/doc/Timeline.js.html b/doc/Timeline.js.html index fca610a6..5ab0b463 100644 --- a/doc/Timeline.js.html +++ b/doc/Timeline.js.html @@ -843,7 +843,7 @@

Source: Timeline.js

diff --git a/doc/Tooltip.js.html b/doc/Tooltip.js.html index 7bbb172b..67fe9a9e 100644 --- a/doc/Tooltip.js.html +++ b/doc/Tooltip.js.html @@ -155,7 +155,7 @@

Source: Tooltip.js

diff --git a/doc/base_Collection.js.html b/doc/base_Collection.js.html index 27429087..b6d82c12 100644 --- a/doc/base_Collection.js.html +++ b/doc/base_Collection.js.html @@ -300,7 +300,7 @@

Source: base/Collection.js

diff --git a/doc/base_Named.js.html b/doc/base_Named.js.html index 29e9b6dd..eabb27c7 100644 --- a/doc/base_Named.js.html +++ b/doc/base_Named.js.html @@ -161,7 +161,7 @@

Source: base/Named.js

diff --git a/doc/base_NamedCollection.js.html b/doc/base_NamedCollection.js.html index 66f699a5..a2ebe092 100644 --- a/doc/base_NamedCollection.js.html +++ b/doc/base_NamedCollection.js.html @@ -106,7 +106,7 @@

Source: base/NamedCollection.js

diff --git a/doc/base_Unique.js.html b/doc/base_Unique.js.html index 38ef4e5c..1ed57549 100644 --- a/doc/base_Unique.js.html +++ b/doc/base_Unique.js.html @@ -81,7 +81,7 @@

Source: base/Unique.js

diff --git a/doc/base_UniqueNamed.js.html b/doc/base_UniqueNamed.js.html index 92c13e41..ae9c4392 100644 --- a/doc/base_UniqueNamed.js.html +++ b/doc/base_UniqueNamed.js.html @@ -93,7 +93,7 @@

Source: base/UniqueNamed.js

diff --git a/doc/calc.js.html b/doc/calc.js.html index 5b2f6d8e..faf921fa 100644 --- a/doc/calc.js.html +++ b/doc/calc.js.html @@ -523,7 +523,7 @@

Source: calc.js

diff --git a/doc/events.js.html b/doc/events.js.html index ca74542b..1de14a8f 100644 --- a/doc/events.js.html +++ b/doc/events.js.html @@ -165,7 +165,7 @@

Source: Events.js

diff --git a/doc/external-Event.html b/doc/external-Event.html index 93e0eb34..fe953768 100644 --- a/doc/external-Event.html +++ b/doc/external-Event.html @@ -51,7 +51,7 @@

Event

diff --git a/doc/external-HTMLElement.html b/doc/external-HTMLElement.html index be618048..7147635d 100644 --- a/doc/external-HTMLElement.html +++ b/doc/external-HTMLElement.html @@ -51,7 +51,7 @@

HTMLElement

diff --git a/doc/external-SVG.html b/doc/external-SVG.html index eed79a9e..cd70f262 100644 --- a/doc/external-SVG.html +++ b/doc/external-SVG.html @@ -51,7 +51,7 @@

SVG

diff --git a/doc/external-XMLHttpRequest.html b/doc/external-XMLHttpRequest.html index 70a6a6f0..160cd179 100644 --- a/doc/external-XMLHttpRequest.html +++ b/doc/external-XMLHttpRequest.html @@ -51,7 +51,7 @@

XMLHttpRequest

diff --git a/doc/external-jQuery.html b/doc/external-jQuery.html index 6f061020..3ee2a2b4 100644 --- a/doc/external-jQuery.html +++ b/doc/external-jQuery.html @@ -51,7 +51,7 @@

jQuery

diff --git a/doc/index.html b/doc/index.html index faeb23c8..c4ea5be7 100644 --- a/doc/index.html +++ b/doc/index.html @@ -857,6 +857,1331 @@

meteoJS/events

+
+
+

meteoJS/modelviewer

+
+
+
+
+ meteoJS/modelviewer +
+
+
+
+
+ + + + + +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+

meteoJS/modelviewer/display/selectNavigation

+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+

meteoJS/modelviewer/display/selectNavigation.SelectNavigation

+ +
+
+
+
+

meteoJS/modelviewer/display/simple

+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+

meteoJS/modelviewer/node

+
+
+
+
+ meteoJS/modelviewer/node +
+
+
+
+
+ + + +
+
+
+
+ +
+
+
+
+ +
+
+
+

meteoJS/modelviewer/nwpResources

+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+

meteoJS/modelviewer/offsetVariable

+
+ + + + +
+
+
+
+ +
+
+
+
+ +
+
+
+

meteoJS/modelviewer/resource

+
+ + + + +
+
+
+
+ +
+
+
+
+ +
+
+
+

meteoJS/modelviewer/resource/image

+
+ + + + +
+
+
+
+ +
+
+
+
+
+

meteoJS/modelviewer/resource/image.Image

+ +
+
+
+
+

meteoJS/modelviewer/resource/sounding

+
+ + + + +
+
+
+
+ +
+
+
+
+
+

meteoJS/modelviewer/resource/sounding.Sounding

+ +
+
+
+
+

meteoJS/modelviewer/resources

+ +
+
+
+ +
+
+
+

meteoJS/modelviewer/timeVariable

+
+ + + + +
+
+
+
+ +
+
+
+
+
+

meteoJS/modelviewer/timeVariable.TimeVariable

+ +
+
+
+
+

meteoJS/modelviewer/variable

+
+ + + + +
+
+
+
+ +
+
+
+
+
+

meteoJS/modelviewer/variable.Variable

+ +
+
+
+ +
+
+ +

meteoJS/repetitiveRequests

@@ -7560,7 +8885,7 @@

meteoJS/tooltip/boots
diff --git a/doc/index.js.html b/doc/index.js.html index b1793fd5..c216a40d 100644 --- a/doc/index.js.html +++ b/doc/index.js.html @@ -119,7 +119,7 @@

Source: index.js

}; export { default as Synview } from './Synview.js'; -import { default as Collection } from './synview/Collection.js'; +import { default as SynviewCollection } from './synview/Collection.js'; import { default as Map } from './synview/SynviewMap.js'; import { default as MapOL } from './synview/map/MapOL.js'; import { default as MapLL } from './synview/map/MapLL.js'; @@ -135,7 +135,7 @@

Source: index.js

import { default as Type } from './synview/Type.js'; import { default as TypeCollection } from './synview/TypeCollection.js'; export const synview = { - Collection, + Collection: SynviewCollection, Map, map: { MapOL, @@ -162,6 +162,40 @@

Source: index.js

BootstrapTooltip }; +export { default as Modelviewer } from './Modelviewer.js'; +import Variable from './modelviewer/Variable.js'; +import TimeVariable from './modelviewer/TimeVariable.js'; +import VariableCollection from './modelviewer/VariableCollection.js'; +import Node from './modelviewer/Node.js'; +import ModelviewerResource from './modelviewer/Resource.js'; +import ModelviewerImage from './modelviewer/resource/Image.js'; +import ModelviewerSounding from './modelviewer/resource/Sounding.js'; +import Resources from './modelviewer/Resources.js'; +import NWPResources from './modelviewer/NWPResources.js'; +import Container from './modelviewer/Container.js'; +import Display from './modelviewer/Display.js'; +import Simple from './modelviewer/display/Simple.js'; +import SelectNavigation from './modelviewer/display/SelectNavigation.js'; +export const modelviewer = { + Variable, + TimeVariable, + VariableCollection, + Node, + Resource: ModelviewerResource, + resource: { + Image: ModelviewerImage, + Sounding: ModelviewerSounding + }, + Resources, + NWPResources, + Container, + Display, + display: { + Simple, + SelectNavigation + } +} + export { default as Sounding } from './Sounding.js'; import { default as Parcel } from './sounding/Parcel.js'; export const sounding = { @@ -211,7 +245,7 @@

Source: index.js

diff --git a/doc/modelviewer_Container.js.html b/doc/modelviewer_Container.js.html new file mode 100644 index 00000000..268d722d --- /dev/null +++ b/doc/modelviewer_Container.js.html @@ -0,0 +1,707 @@ + + + + + + + Source: modelviewer/Container.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/container
+ */
+import Unique from '../base/Unique.js';
+import addEventFunctions from '../Events.js';
+import Resource from './Resource.js';
+import Node from './Node.js';
+import Display from './Display.js';
+import VariableCollection from './VariableCollection.js';
+
+/**
+ * Triggered, when visible Resource changes.
+ * 
+ * @event module:meteoJS/modelviewer/container#change:enabledResources
+ * @type {Object}
+ * @property {Map<integer,module:meteoJS/modelviewer/resource.Resource>}
+ *   [enabledResources] - Enabled resources, selected by selectedVariables.
+ */
+
+/**
+ * Triggered, when visible Resource changes.
+ * 
+ * @event module:meteoJS/modelviewer/container#change:visibleResource
+ */
+
+/**
+ * Triggered, when displayVariables is changed.
+ * 
+ * @event module:meteoJS/modelviewer/container#change:displayVariables
+ * @type {Object}
+ * @property {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   [addedVariables] - Added variables to displayVariables.
+ * @property {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   [removedVariables] - Removed variables to displayVariables.
+ */
+
+/**
+ * Triggered, when selectedVariables is changed.
+ * 
+ * @event module:meteoJS/modelviewer/container#change:selectedVariables
+ * @type {Object}
+ * @property {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   [addedVariables] - Added variables to selectedVariables.
+ * @property {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   [removedVariables] - Removed variables to selectedVariables.
+ */
+
+/**
+ * If a suitable resource is searched, this method will be called several times.
+ * The first argument ist a list of variables. These variables are collected of
+ * one hierarchy level, defined by the
+ * {@link module:meteoJS/modelviewer/resources.Resources|resources object}.
+ * The method returns an ordered list of these passed variables (or a subset).
+ * For these variables, further down in the hierarchy, a possible resource is
+ * searched. If one is found, this variable will be used for selectedVariables.
+ * Method is only used if adaptSuitableResource is enabled. Default algorythm is
+ * to return the list in the order of the Iterator.
+ * 
+ * @typedef {Function} module:meteoJS/modelviewer/container~getPossibleVariables
+ * @param {module:meteoJS/modelviewer/variable.Variable[]}
+ *   possibleSelectedVariables - Variables to return an ordered list.
+ * @param {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   selectedVariables - Already selected variables so far, top-down in
+ *   hierarchy.
+ * @returns {module:meteoJS/modelviewer/variable.Variable[]} - Ordered list.
+ */
+
+/**
+ * With the passed selectedVariables, the method determines if already a
+ * suitable resource should be selected. If method returns true, the property
+ * selectedVariables will be set by the passed Set.
+ * Method used if adaptSuitableResource is enabled. Default algorythm is to
+ * return true if the Node of the lastAddedVariable contains resources.
+ * 
+ * @typedef {Function} module:meteoJS/modelviewer/container~isResourceSelected
+ * @param {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   selectedVariables - Selected variables so far.
+ * @param {undefined|module:meteoJS/modelviewer/variable.Variable}
+ *   lastAddedVariable - Last added variable to selectedVariables.
+ * @returns {boolean} - True if a suitable resource should be selected with the
+ *   current state of selectedVariables.
+ */
+
+/**
+ * Options to adapt a suitable resource to display.
+ * 
+ * @typedef {Object}
+ *   module:meteoJS/modelviewer/container~adaptSuitableResource
+ * @param {boolean} enabled - Enabled adapt suitable resource.
+ * @param {module:meteoJS/modelviewer/container~getPossibleVariables}
+ *   getPossibleVariables - Determines order of variables of a hierarchy level.
+ * @param {module:meteoJS/modelviewer/container~isResourceSelected}
+ *   isResourceSelected - Is selectedVariables complete.
+ */
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {module:meteoJS/base/unique~options}
+ *   module:meteoJS/modelviewer/container~options
+ * @param {module:meteoJS/modelviewer/display.Display} [display]
+ *   Display object to output the container content to DOM.
+ * @param {module:meteoJS/modelviewer/container~adaptSuitableResource}
+ *   [adaptSuitableResource] - Options for adapt suitable resource.
+ */
+
+/**
+ * @classdesc This object represents a container, that displays one resource.
+ * Via displayVariables the appropriate resource is chosen.
+ * 
+ * @fires module:meteoJS/modelviewer/container#change:visibleResource
+ * @fires module:meteoJS/modelviewer/container#change:enabledResources
+ * @fires module:meteoJS/modelviewer/container#change:displayVariables
+ * @fires module:meteoJS/modelviewer/container#change:selectedVariables
+ */
+export class Container extends Unique {
+
+  /**
+   * @param {module:meteoJS/modelviewer/container~options} [options] - Options.
+   */
+  constructor({ id,
+    display = undefined,
+    adaptSuitableResource = {} } = {}) {
+    super({
+      id
+    });
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer/display.Display
+     * @private
+     */
+    this._display = (display === undefined) ? new Display() : display;
+    this._display.modelviewer = this.modelviewer;
+    this._display.container = this;
+    this._display.parentNode = this._containerNode;
+    
+    /**
+     * @type module:meteoJS/modelviewer/container~adaptSuitableResource
+     * @private
+     */
+    this._adaptSuitableResource = {};
+    this._initAdaptSuitableResource(adaptSuitableResource);
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer.Modelviewer
+     * @private
+     */
+    this._modelviewer = undefined;
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer/resource.Resource
+     * @private
+     */
+    this._visibleResource;
+    
+    /**
+     * @type Set<module:meteoJS/modelviewer/variable.Variable>
+     * @private
+     */
+    this._displayVariables = new Set();
+    
+    /**
+     * @type Set<module:meteoJS/modelviewer/variable.Variable>
+     * @private
+     */
+    this._selectedVariables = new Set();
+    
+    /**
+     * @type module:meteoJS/modelviewer/node.Node|undefined
+     * @private
+     */
+    this._selectedNode = undefined;
+    
+    /**
+     * @type Map<integer,module:meteoJS/modelviewer/resource.Resource>
+     * @private
+     */
+    this._enabledResources = new Map();
+    
+    /**
+     * @type undefined|HTMLElement
+     * @private
+     */
+    this._containerNode = undefined;
+    
+    /**
+     * @type Object<string,Object<string,mixed>>
+     * @private
+     */
+    this._listeners = {
+      mirror: {
+        container: undefined,
+        listenerKey: undefined
+      },
+      timeline: {
+        timeline: undefined,
+        listenerKey: undefined
+      },
+      resources: {
+        resources: undefined,
+        listenerKey: undefined
+      }
+    };
+  }
+  
+  /**
+   * Display object to generate dom output.
+   * 
+   * @type undefined|module:meteoJS/modelviewer/display.Display
+   * @readonly
+   */
+  get display() {
+    return this._display;
+  }
+  
+  /**
+   * This container belongs to this modelviewer object.
+   * 
+   * @type undefined|module:meteoJS/modelviewer.Modelviewer
+   * @package
+   */
+  get modelviewer() {
+    return this._modelviewer;
+  }
+  set modelviewer(modelviewer) {
+    this._modelviewer = modelviewer;
+    if (this._modelviewer === undefined) {
+      if (this._listeners.timeline.listenerKey !== undefined)
+        this._listeners.timeline.timeline
+          .un('change:time', this._listeners.timeline.listenerKey);
+      if (this._listeners.resources.listenerKey !== undefined)
+        this._listeners.resources.resources
+          .un('change:resources', this._listeners.resources.listenerKey);
+      return;
+    }
+    this._display.modelviewer = modelviewer;
+    
+    this._listeners.timeline.timeline = this._modelviewer.timeline;
+    this._listeners.timeline.listenerKey = this._modelviewer.timeline
+      .on('change:time', () => this._setVisibleResource());
+    this._listeners.resources.resources = this._modelviewer.resources;
+    this._listeners.resources.listenerKey = this._modelviewer.resources
+      .on('change:resources', () => {
+        this._setTimes();
+        this._setEnabledResources();
+        this._updateSelectedVariables();
+      });
+    this._setTimes();
+  }
+  
+  /**
+   * DOM node to append container's output.
+   * 
+   * @type undefined|HTMLElement
+   * @package
+   */
+  get containerNode() {
+    return this._containerNode;
+  }
+  set containerNode(containerNode) {
+    this._containerNode = containerNode;
+    if (this._containerNode === undefined)
+      return;
+    this._display.parentNode = this._containerNode;
+  }
+  
+  /**
+   * Currently visible resource. Could be an empty resource.
+   * 
+   * @type module:meteoJS/modelviewer/resource.Resource
+   * @readonly
+   */
+  get visibleResource() {
+    return (this._visibleResource === undefined) ?
+      new Resource() : this._visibleResource;
+  }
+  
+  /**
+   * These variables define, which resource is displayed.
+   * If adaptSuitableResource is not enabled, then the displayed resource is
+   * exactly defined by these variables (and additionally the datetime selected
+   * by the timeline object). If adaptSuitableResource is enabled, then a
+   * resource is displayed, that matches the variables but can be defined by
+   * additional variables.
+   * Setter allows Set or Array. Getter returns always Set.
+   * 
+   * @type Set<module:meteoJS/modelviewer/variable.Variable>
+   */
+  get displayVariables() {
+    return this._displayVariables;
+  }
+  set displayVariables(variables) {
+    let addedVariables = new Set();
+    variables = new Set(variables);
+    for (let variable of variables)
+      if (!this._displayVariables.has(variable))
+        addedVariables.add(variable);
+    let removedVariables = new Set();
+    for (let displayVariable of this.displayVariables)
+      if (!variables.has(displayVariable))
+        removedVariables.add(displayVariable);
+    if (
+      addedVariables.size > 0 ||
+      removedVariables.size > 0
+    ) {
+      this._displayVariables = variables;
+      this._updateSelectedVariables();
+      this.trigger(
+        'change:displayVariables',
+        { addedVariables, removedVariables }
+      );
+    }
+  }
+  
+  /**
+   * These variables define excactly, which resource will be displayed. These
+   * variables are retrieved from the available resources and displayVariables.
+   * Together with the selected time in the timeline, the resource to display
+   * is uniquely defined.
+   * If adaptSuitableResource is not enabled, selectedVariables is equal to
+   * displayVariables.
+   * 
+   * @type Set<module:meteoJS/modelviewer/variable.Variable>
+   * @readonly
+   */
+  get selectedVariables() {
+    return this._selectedVariables;
+  }
+  
+  /**
+   * Returns an array of times (for the timeline). For all of these times, there
+   * exists resources which match with the current displayVariables.
+   * 
+   * @type Date[]
+   * @readonly
+   */
+  get enabledTimes() {
+    return [...this._enabledResources.keys()]
+      .filter(datetime => !isNaN(datetime))
+      .map(datetime => new Date(datetime));
+  }
+  
+  /**
+   * Exchanges variables in displayVariables. The variable with the same
+   * Collection will be exchanged. If none is found, the variable will be added.
+   * 
+   * @param {Set<module:meteoJS/modelviewer/variable.Variable>} variables
+   *   Add these variables to the set of displayVariables.
+   * @returns {module:meteoJS/modelviewer/container.Container} - This.
+   * @fires module:meteoJS/modelviewer/container#change:displayVariables
+   */
+  exchangeDisplayVariable(variables) {
+    let displayVariables = new Set(this.displayVariables);
+    for (let variable of variables)
+      for (let displayVariable of this.displayVariables)
+        if (displayVariable.variableCollection ===
+            variable.variableCollection) {
+          displayVariables.delete(displayVariable);
+          displayVariables.add(variable);
+        }
+    for (let variable of variables)
+      if (!displayVariables.has(variable))
+        displayVariables.add(variable);
+    this.displayVariables = displayVariables;
+    return this;
+  }
+  
+  /**
+   * Mirrors (parts of) the displayVariables form another container. With this
+   * feature, e.g. in different containers can be viewed plots of different
+   * models. If you change e.g. the field in the first container, all other
+   * containers, that mirrors form this container, will also change the viewed
+   * content.
+   * 
+   * @param {module:meteoJS/modelviewer/container.Container} [container]
+   *   Mirrors from this container.
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection[]}
+   *   [variableCollections] - The displayVariables of these VariableCollections
+   *   are mirrored.
+   */
+  mirrorsFrom(container = undefined, variableCollections = undefined) {
+    if (this._listeners.mirror.listenerKey !== undefined)
+      this._listeners.mirror.container
+        .un('change:displayVariables', this._listeners.mirror.listenerKey);
+    if (container === undefined)
+      return;
+    if (variableCollections === undefined)
+      variableCollections = this.modelviewer.resources.variableCollections;
+    this._listeners.mirror.container = container;
+    let onChangeDisplayVariables = () => {
+      let newDisplayVariables = new Set();
+      for (let variable of container.displayVariables)
+        variableCollections.forEach(collection => {
+          if (variable.variableCollection === collection)
+            newDisplayVariables.add(variable);
+        });
+      this.exchangeDisplayVariable(newDisplayVariables);
+    };
+    this._listeners.mirror.listenerKey =
+      container.on('change:displayVariables', onChangeDisplayVariables);
+    onChangeDisplayVariables();
+  }
+  
+  /**
+   * Sets all available times in the timeline object for this container.
+   * 
+   * @private
+   */
+  _setTimes() {
+    let [selectedVariables] =
+      this._getSelectedVariablesWithResources(
+        [this.modelviewer.resources.topNode],
+        new Set(),
+        undefined,
+        selectedVariables => {
+          let result = true;
+          this.modelviewer.resources._timesVariableCollections.forEach(collection => {
+            let contained = false;
+            for (let selectedVariable of selectedVariables) {
+              if (collection.contains(selectedVariable))
+                contained = true;
+            }
+            if (!contained)
+              result = false;
+          });
+          return result;
+        }
+      );
+    
+    if (selectedVariables === undefined)
+      selectedVariables = new Set();
+    
+    this.modelviewer.timeline
+      .setTimesBySetID(
+        this.id,
+        this.modelviewer
+          .resources.getTimesByVariables(...selectedVariables)
+      );
+  }
+  
+  /**
+   * Updates the selected variables, according to displayVariables.
+   * 
+   * @private
+   */
+  _updateSelectedVariables() {
+    let [selectedVariables, lastSelectedVariable] =
+      this._getSelectedVariablesWithResources(
+        [this.modelviewer.resources.topNode],
+        new Set(),
+        undefined
+      );
+    
+    let node;
+    if (selectedVariables === undefined) {
+      selectedVariables = new Set();
+      node = new Node({ variableCollection: new VariableCollection() });
+    }
+    else
+      node = lastSelectedVariable.variableCollection.node;
+    this._setSelectedVariables(selectedVariables, node);
+  }
+  
+  /**
+   * @typedef result_getSelectedVariablesWithResources
+   * @type {Array}
+   * @property {undefined|Set<module:meteoJS/modelviewer/variable.Variable>} 0
+   * @property {undefined|module:meteoJS/modelviewer/variable.Variable} 1
+   */
+  
+  /**
+   * 
+   * 
+   * @param {Set<module:meteoJS/modelviewer/node.Node>} nodes - Nodes to check.
+   * @param {Set<module:meteoJS/modelviewer/variable.Variable>}
+   *   selectedVariables - Selected Variables from top until this node.
+   * @returns {result_getSelectedVariablesWithResources}
+   *   Array with first element the SelectedVariables, second element the last
+   *   selectedVariable (node most down in the tree).
+   * @private
+   */
+  _getSelectedVariablesWithResources(
+    nodes,
+    selectedVariables,
+    lastSelectedVariable,
+    isResourceSelected = this._adaptSuitableResource.isResourceSelected
+  ) {
+    if (isResourceSelected.call(this, selectedVariables, lastSelectedVariable))
+      return [selectedVariables, lastSelectedVariable];
+    
+    let possibleSelectedVariables = [];
+    let availableSelectedVariables = [];
+    for (let childNode of nodes) {
+      if (this.modelviewer.resources.availableVariablesMap.has(childNode) &&
+          this.modelviewer.resources.availableVariablesMap.get(childNode).size)
+        for (let availableVariable
+          of this.modelviewer.resources.availableVariablesMap.get(childNode)) {
+          if (this.displayVariables.has(availableVariable))
+            possibleSelectedVariables.push(availableVariable);
+          else if (this._adaptSuitableResource.enabled)
+            availableSelectedVariables.push(availableVariable);
+        }
+    }
+    
+    [].push.call(
+      possibleSelectedVariables,
+      ...this._adaptSuitableResource
+        .getPossibleVariables
+        .call(this, availableSelectedVariables, selectedVariables)
+    );
+    
+    let result = [undefined, undefined];
+    possibleSelectedVariables.forEach(possibleSelectedVariable => {
+      if (result[0] !== undefined)
+        return;
+      
+      let tempSelectedVariables = new Set(selectedVariables);
+      tempSelectedVariables.add(possibleSelectedVariable);
+      let [resultSelectedVariables, resultLastSelectedVariable] =
+        this
+          ._getSelectedVariablesWithResources(
+            possibleSelectedVariable.variableCollection.node.children,
+            tempSelectedVariables,
+            possibleSelectedVariable,
+            isResourceSelected
+          );
+      if (resultSelectedVariables !== undefined) {
+        result[0] = resultSelectedVariables;
+        result[1] = resultLastSelectedVariable;
+        return;
+      }
+      
+      let isOnlyTimesVariables = true;
+      for (let selectedVariable of tempSelectedVariables) {
+        let contained = false;
+        this.modelviewer.resources._timesVariableCollections.forEach(collection => {
+          if (collection.contains(selectedVariable))
+            contained = true;
+        });
+        if (!contained)
+          isOnlyTimesVariables = false;
+      }
+      if (isOnlyTimesVariables &&
+          tempSelectedVariables.size == this.modelviewer.resources._timesVariableCollections.size) {
+        result[0] = tempSelectedVariables;
+        result[1] = possibleSelectedVariable;
+      }
+    });
+    
+    return result;
+  }
+  
+  /**
+   * @param {Set<module:meteoJS/modelviewer/variable.Variable>}
+   *   selectedVariables - New selectedVariables.
+   * @param {module:meteoJS/modelviewer/node.Node} selectedNode
+   *   Selectes resources from this Node.
+   * @private
+   */
+  _setSelectedVariables(selectedVariables, selectedNode) {
+    let addedVariables = new Set();
+    selectedVariables = new Set(selectedVariables);
+    for (let variable of selectedVariables)
+      if (!this.selectedVariables.has(variable))
+        addedVariables.add(variable);
+    let removedVariables = new Set();
+    for (let selectedVariable of this.selectedVariables)
+      if (!selectedVariables.has(selectedVariable))
+        removedVariables.add(selectedVariable);
+    if (
+      addedVariables.size > 0 ||
+      removedVariables.size > 0
+    ) {
+      this._selectedVariables = selectedVariables;
+      this._selectedNode = selectedNode;
+      this._setTimes();
+      this._setEnabledResources();
+      this.trigger(
+        'change:selectedVariables',
+        { addedVariables, removedVariables }
+      );
+    }
+  }
+  
+  /**
+   * Sets internally _enabledResources. These resources are selected by
+   * selectedVariable. The visibleResource is determined from this resources.
+   * 
+   * @private
+   */
+  _setEnabledResources() {
+    this._enabledResources.clear();
+    if (this._selectedNode === undefined)
+      return;
+    this._selectedNode
+      .getResourcesByVariables(true, ...this.selectedVariables)
+      .filter(r => r.datetime && !isNaN(r.datetime.valueOf()))
+      .forEach(r => this._enabledResources.set(r.datetime.valueOf(), r));
+    this.modelviewer.timeline
+      .setEnabledTimesBySetID(this.id, this.enabledTimes);
+    this.trigger('change:enabledResources', this._enabledResources);
+    this._setVisibleResource();
+  }
+  
+  /**
+   * Sets visible resource.
+   * 
+   * @private
+   */
+  _setVisibleResource() {
+    let oldVisibleResource = this._visibleResource;
+    let datetime = this.modelviewer.timeline.getSelectedTime().valueOf();
+    if (this._enabledResources.has(datetime))
+      this._visibleResource = this._enabledResources.get(datetime);
+    else
+      this._visibleResource = undefined;
+    if (this._visibleResource !== oldVisibleResource)
+      this.trigger('change:visibleResource');
+  }
+  
+  /**
+   * Inits private property _adaptSuitableResource.
+   * 
+   * @param {module:meteoJS/modelviewer/container~adaptSuitableResource}
+   *   [adaptSuitableResource] - Adapt suitable resource.
+   * @private
+   */
+  _initAdaptSuitableResource({ enabled = true,
+    getPossibleVariables = undefined,
+    isResourceSelected = undefined,
+    //excludeVariableCollectionFromSimiliarDisplay = []
+  } = {}) {
+    this._adaptSuitableResource = {
+      enabled,
+      getPossibleVariables,
+      isResourceSelected
+    };
+    
+    if (this._adaptSuitableResource.getPossibleVariables === undefined)
+      this._adaptSuitableResource.getPossibleVariables =
+        availableSV => availableSV;
+    if (this._adaptSuitableResource.isResourceSelected === undefined)
+      this._adaptSuitableResource.isResourceSelected =
+      (selectedVariables, lastAddedVariable) => {
+        if (lastAddedVariable === undefined)
+          return false;
+        let resources = lastAddedVariable.variableCollection
+          .node.getResourcesByVariables(true, ...selectedVariables);
+        return resources.length > 0;
+      };
+  }
+}
+addEventFunctions(Container.prototype);
+export default Container;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_Display.js.html b/doc/modelviewer_Display.js.html new file mode 100644 index 00000000..6de31fc6 --- /dev/null +++ b/doc/modelviewer_Display.js.html @@ -0,0 +1,383 @@ + + + + + + + Source: modelviewer/Display.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/display
+ */
+import $ from 'jquery';
+import addEventFunctions from '../Events.js';
+
+/**
+ * Display initalisation event.
+ * 
+ * @event module:meteoJS/modelviewer/display#init:display
+ */
+
+/**
+ * VariableCollection add event. Also fired, once the object is assigned to
+ * a Container object.
+ * 
+ * @event module:meteoJS/modelviewer/display#add:variableCollection
+ * @type {Object}
+ * @property {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+ *   variableCollection - The added variableCollection.
+ */
+
+/**
+ * Adding a variable to a variableCollection event. Also fired for each variable
+ * in the available variableCollections, once the object is assigned to a
+ * Container object.
+ * 
+ * @event module:meteoJS/modelviewer/display#add:variable
+ * @type {Object}
+ * @property {module:meteoJS/modelviewer/variable.Variable} variable
+ *   The added variable.
+ */
+
+/**
+ * Change available variables event.
+ * 
+ * @event module:meteoJS/modelviewer/display#change:availableVariables
+ * @type {Object}
+ * @property {Set<module:meteoJS/modelviewer/variable.Variable>}
+ *   availableVariables - Set of the available variables of a collection.
+ * @property {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+ *   variableCollection - The collection all the variables belong to.
+ */
+
+/**
+ * Change selected variable event.
+ * 
+ * @event module:meteoJS/modelviewer/display#change:selectedVariable
+ * @type {Object}
+ * @property {module:meteoJS/modelviewer/variable.Variable} variable
+ *   The currently selected variable of the variableCollection. Could also be a
+ *   empty variable with no id.
+ * @property {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+ *   variableCollection - VariableCollection.
+ */
+
+/**
+ * Change visible resource event.
+ * 
+ * @event module:meteoJS/modelviewer/display#change:visibleResource
+ * @type {Object}
+ */
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {Object}
+ * @param
+ *   {Iterable.<module:meteoJS/modelviewer/variableCollection.VariableCollection>}
+ *   [alwaysAvailableCollections]
+ *   Variables from these variableCollections are always available.
+ */
+
+/**
+ * @classdesc
+ * 
+ * @fires module:meteoJS/modelviewer/display#init:display
+ * @fires module:meteoJS/modelviewer/display#add:variableCollection
+ * @fires module:meteoJS/modelviewer/display#add:variable
+ * @fires module:meteoJS/modelviewer/display#change:availableVariables
+ * @fires module:meteoJS/modelviewer/display#change:selectedVariable
+ * @fires module:meteoJS/modelviewer/display#change:visibleResource
+ */
+export class Display {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/display~options} [options] - Options.
+   */
+  constructor({
+    alwaysAvailableCollections = []
+  } = {}) {
+    
+    /**
+     * @type Set<module:meteoJS/modelviewer/variableCollection.VariableCollection>
+     * @private
+     */
+    this._alwaysAvailableCollections = new Set(alwaysAvailableCollections);
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer.Modelviewer
+     * @private
+     */
+    this._modelviewer = undefined;
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer/container.Container
+     * @private
+     */
+    this._container = undefined;
+    
+    /**
+     * @type undefined|HTMLElement|jQuery
+     * @private
+     */
+    this._parentNode = undefined;
+    
+    /**
+     * @type undefined|HTMLElement|jQuery
+     * @private
+     */
+    this._resourceNode = undefined;
+    
+    this._resourceOutput = {
+      image: undefined,
+      thermodynamicDiagram: undefined
+    };
+  }
+  
+  /**
+   * @type undefined|module:meteoJS/modelviewer.Modelviewer
+   * @package
+   */
+  get modelviewer() {
+    return this._modelviewer;
+  }
+  set modelviewer(modelviewer) {
+    this._modelviewer = modelviewer;
+    if (this._modelviewer === undefined)
+      return;
+    
+    this._modelviewer.resources.variableCollections.forEach(collection => {
+      collection.on('add:variable', variable => {
+        this.trigger('add:variable', { variable });
+      });
+    });
+    this._modelviewer.resources
+      .on('change:resources', () => this._changeResources());
+  }
+  
+  /**
+   * @type undefined|module:meteoJS/modelviewer/container.Container
+   * @package
+   */
+  get container() {
+    return this._container;
+  }
+  set container(container) {
+    this._container = container;
+    if (this._container === undefined)
+      return;
+    
+    this._container.on('change:selectedVariables',
+      ({ addedVariables }) => {
+        this._onChangeSelectedVariables(addedVariables);
+      });
+    this._onChangeSelectedVariables();
+    this._container.on('change:visibleResource', () => {
+      this._onChangeVisibleResource();
+    });
+  }
+  
+  /**
+   * @type HTMLElement|jQuery
+   * @package
+   */
+  get parentNode() {
+    return this._parentNode;
+  }
+  set parentNode(parentNode) {
+    this._parentNode = parentNode;
+    this.onInit();
+  }
+  
+  /**
+   * @type undefined|HTMLElement|jQuery
+   * @package
+   */
+  get resourceNode() {
+    return this._resourceNode;
+  }
+  set resourceNode(resourceNode) {
+    this._resourceNode = resourceNode;
+    this._onChangeVisibleResource();
+  }
+  
+  /**
+   * Re-Render this display.
+   */
+  render() {
+    this.onInit();
+    this.onChangeVisibleResource();
+  }
+  
+  /**
+   * @private
+   */
+  onInit() {
+    if (this.parentNode === undefined)
+      return;
+    
+    $(this.parentNode).empty();
+    this.trigger('init:display');
+    if (this._modelviewer === undefined)
+      return;
+    
+    this._modelviewer.resources.variableCollections
+      .forEach(variableCollection => {
+        this.trigger('add:variableCollection', { variableCollection });
+        for (let variable of variableCollection)
+          this.trigger('add:variable', { variable });
+      });
+    this._onChangeSelectedVariables();
+  }
+  
+  /**
+   * @private
+   */
+  _onChangeSelectedVariables(addedVariables = undefined) {
+    this._changeResources();
+    
+    if (this._modelviewer === undefined)
+      return;
+    
+    let selectedVariables = (addedVariables === undefined)
+      ? this._container.selectedVariables
+      : addedVariables;
+    this._modelviewer.resources.variableCollections
+      .forEach(variableCollection => {
+        [...selectedVariables].forEach(variable => {
+          if (variableCollection.contains(variable))
+            this.trigger('change:selectedVariable',
+              { variable, variableCollection });
+        });
+      });
+  }
+  
+  /**
+   * @private
+   */
+  _changeResources() {
+    if (this._modelviewer === undefined ||
+        this._container === undefined)
+      return;
+    
+    for (let variableCollection of this._modelviewer.resources.variableCollections) {
+      let availableVariables =
+      (variableCollection
+         === this._modelviewer.resources.topNode.variableCollection
+       || this._alwaysAvailableCollections.has(variableCollection))
+        ? new Set(variableCollection.variables)
+        : this._modelviewer.resources
+          .getAvailableVariables(
+            variableCollection,
+            { variables: [...this._container.selectedVariables] }
+          );
+      
+      this.trigger('change:availableVariables',
+        { availableVariables, variableCollection });
+    }
+  }
+  
+  /**
+   * @private
+   */
+  _onChangeVisibleResource() {
+    if (this._resourceNode === undefined) {
+      this.trigger('change:visibleResource');
+      return;
+    }
+    if (this._container === undefined)
+      return;
+    
+    let visibleResource = this._container.visibleResource;
+    if ('url' in visibleResource) {
+      if (this.thermodynamicDiagram !== undefined) {
+        this.thermodynamicDiagram = undefined;
+        $(this._resourceNode).empty();
+      }
+      if (this._resourceOutput.image === undefined) {
+        $(this._resourceNode).empty();
+        this._resourceOutput.image = $('<img>').css({ 'max-width': '100%' });
+        $(this._resourceNode).append(this._resourceOutput.image);
+      }
+      this._resourceOutput.image.attr('src', visibleResource.url);
+    }
+    else if ('sounding' in visibleResource) {
+      if (this._resourceOutput.image !== undefined) {
+        this._resourceOutput.image = undefined;
+        $(this._resourceNode).empty();
+      }
+      /*if (this._resourceOutput.thermodynamicDiagram === undefined)
+        this._resourceOutput.thermodynamicDiagram = new ThermodynamicDiagram({
+          renderTo: $(this._resourceNode)
+        });*/
+      let isAppended = false;
+      this._resourceOutput.thermodynamicDiagram.soundings.forEach(sounding => {
+        if (sounding.getSounding() === visibleResource.sounding) {
+          isAppended = true;
+          sounding.visible(true);
+        }
+        else
+          sounding.visible(false);
+      });
+      if (!isAppended)
+        this._resourceOutput.thermodynamicDiagram
+          .addSounding(visibleResource.sounding);
+    }
+    else {
+      if (this._resourceOutput.image !== undefined) {
+        this._resourceOutput.image = undefined;
+        $(this._resourceNode).empty();
+      }
+      if (this._resourceOutput.thermodynamicDiagram !== undefined)
+        this._resourceOutput.thermodynamicDiagram.soundings
+          .forEach(sounding => sounding.visible(false));
+    }
+  }
+}
+addEventFunctions(Display.prototype);
+export default Display;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_NWPResources.js.html b/doc/modelviewer_NWPResources.js.html new file mode 100644 index 00000000..5bfec273 --- /dev/null +++ b/doc/modelviewer_NWPResources.js.html @@ -0,0 +1,197 @@ + + + + + + + Source: modelviewer/NWPResources.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/nwpResources
+ */
+import Resources from './Resources.js';
+import VariableCollection from './VariableCollection.js';
+import Node from './Node.js';
+import Variable from './Variable.js';
+import TimeVariable from './TimeVariable.js';
+
+/**
+ * @classdesc For usage of NWP (numerical weather prediction). This class is
+ *   designed to use the modelviewer for NWP.
+ */
+export class NWPResources extends Resources {
+  
+  constructor() {
+    let collections = new Set();
+    ['models', 'runs', 'regions', 'fields', 'levels', 'accumulations', 'thresholds']
+      .forEach(id => collections.add(new VariableCollection({ id })));
+    let nodes = {};
+    for (let collection of collections)
+      nodes[collection.id] = new Node(collection);
+    // build hierarchy
+    nodes.models.appendChild(nodes.runs);
+    nodes.runs.appendChild(nodes.regions);
+    nodes.regions.appendChild(nodes.fields);
+    nodes.fields.appendChild(nodes.levels, nodes.accumulations);
+    nodes.accumulations.appendChild(nodes.thresholds);
+    
+    super({
+      topNode: nodes.models,
+      timesVariableCollections: new Set([nodes.models.variableCollection, nodes.runs.variableCollection])
+    });
+  }
+  
+  /**
+   * Creates a Variable-Object and adds it to the VariableCollection.
+   * 
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+   *   variableCollection - VariableCollection.
+   * @param {Object} [options] - Variable options.
+   * @param {mixed} [options.id] - Variable id.
+   * @param {string} [options.name] - Default name.
+   * @param {Object.<string,string>} [options.names] - Names.
+   * @param {string[]} [options.langSortation] - Priority of language codes.
+   * @param {Date|undefined} [option.sdatetime] - Datetime.
+   * @returns {module:meteoJS/modelviewer/nwpResources.NWPResources} This.
+   */
+  addVariable(variableCollection,
+    { id,
+      name = undefined,
+      names = {},
+      langSortation = [],
+      datetime = undefined } = {}) {
+    let variable =
+      (datetime === undefined)
+        ? new Variable({
+          id,
+          name,
+          names,
+          langSortation
+        })
+        : new TimeVariable({
+          id,
+          name,
+          names,
+          langSortation,
+          datetime
+        });
+    variableCollection.append(variable);
+    return this;
+  }
+  
+  /**
+   * Collection of all defined models.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get models() {
+    return this.getNodeByVariableCollectionId('models').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined runs.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get runs() {
+    return this.getNodeByVariableCollectionId('runs').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined regions.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get regions() {
+    return this.getNodeByVariableCollectionId('regions').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined fields.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get fields() {
+    return this.getNodeByVariableCollectionId('fields').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined levels.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get levels() {
+    return this.getNodeByVariableCollectionId('levels').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined accumulations.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get accumulations() {
+    return this.getNodeByVariableCollectionId('accumulations').variableCollection;
+  }
+  
+  /**
+   * Collection of all defined thresholds.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get thresholds() {
+    return this.getNodeByVariableCollectionId('thresholds').variableCollection;
+  }
+}
+export default NWPResources;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_Node.js.html b/doc/modelviewer_Node.js.html new file mode 100644 index 00000000..c3ac871b --- /dev/null +++ b/doc/modelviewer_Node.js.html @@ -0,0 +1,256 @@ + + + + + + + Source: modelviewer/Node.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/node
+ */
+import addEventFunctions from '../Events.js';
+
+/**
+ * Triggered on append of a child node.
+ * 
+ * @event module:meteoJS/modelviewer/node#append:child
+ * @param {module:meteoJS/modelviewer/node.Node} node - Appended child node.
+ */
+
+/**
+ * A node has always a correspondent VariableCollection. With the node objects
+ * a hierarchy of the collections is build up. This hierarchy is mainly used
+ * to achieve a good user experience. This way, the menus in the
+ * {@link module:meteoJS/modelviewer/container.Container|modelviewer-container}
+ * could be setup to present the user only available fields or levels or only
+ * activate buttons which are available for a certain model and run.
+ * Additionally a node contains a list of resources, this is used internally
+ * in {@link module:meteoJS/modelviewer/resources.Resources}.
+ * 
+ * @fires module:meteoJS/modelviewer/node#append:child
+ */
+export class Node {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+   *   variableCollection
+   *   This node belongs to this collection.
+   */
+  constructor(variableCollection) {
+    
+    /**
+     * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+     * @private
+     */
+    this._variableCollection = variableCollection;
+    variableCollection.node = this;
+    
+    /**
+     * @type module:meteoJS/modelviewer/node.Node[]
+     * @private
+     */
+    this._parents = [];
+    
+    /**
+     * @type module:meteoJS/modelviewer/node.Node[]
+     * @private
+     */
+    this._children = [];
+    
+    /**
+     * @type Map<module:meteoJS/modelviewer/variableCollection.VariableCollection,
+     *           Set<module:meteoJS/modelviewer/resource.Resource>>
+     * @private
+     */
+    this._resources = new Map();
+  }
+  
+  /**
+   * VariableCollection correspondent to this node.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   */
+  get variableCollection() {
+    return this._variableCollection;
+  }
+  
+  /**
+   * Parent nodes.
+   * 
+   * @type module:meteoJS/modelviewer/node.Node[]
+   */
+  get parents() {
+    return this._parents;
+  }
+  
+  /**
+   * Child nodes.
+   * 
+   * @type module:meteoJS/modelviewer/node.Node[]
+   */
+  get children() {
+    return this._children;
+  }
+  
+  /**
+   * Appends a node as a child.
+   * 
+   * @param {...module:meteoJS/modelviewer/node.Node} nodes - Node to append.
+   * @returns {module:meteoJS/modelviewer/node.Node} This.
+   * @fires module:meteoJS/modelviewer/node#append:child
+   */
+  appendChild(...nodes) {
+    nodes.forEach(node => {
+      this._children.push(node);
+      node._addParent(this);
+      this.trigger('append:child', node);
+    });
+    return this;
+  }
+  
+  /**
+   * Adds a parent node.
+   * 
+   * @param {module:meteoJS/modelviewer/node.Node} node - Node to add.
+   * @package
+   */
+  _addParent(node) {
+    this._parents.push(node);
+  }
+  
+  /**
+   * All contained resources.
+   * 
+   * @type module:meteoJS/modelviewer/resource.Resource[]
+   * @package
+   */
+  get resources() {
+    let result = new Set();
+    for (let resources of this._resources.values()) {
+      for (let r of resources.values())
+        result.add(r);
+    }
+    return [...result];
+  }
+  
+  /**
+   * Append resources.
+   * 
+   * @param {...module:meteoJS/modelviewer/resource.Resource} resources
+   *   Resources.
+   * @returns {integer} Count of really added resources.
+   * @package
+   */
+  append(...resources) {
+    let addedCount = 0;
+    resources.forEach(resource => {
+      let variable =
+        resource.getVariableByVariableCollection(this.variableCollection);
+      /* Only append resources, that have variables which belongs to node's
+       * collection.
+       */
+      if (variable.id === undefined)
+        return;
+      resource.variables.forEach(variable => {
+        if (!this._resources.has(variable.variableCollection))
+          this._resources.set(variable.variableCollection, new Set());
+        if (!this._resources.get(variable.variableCollection).has(resource))
+          addedCount++;
+        this._resources.get(variable.variableCollection).add(resource);
+      });
+    });
+    return addedCount;
+  }
+  
+  /**
+   * Removes resources.
+   * 
+   * @param {...module:meteoJS/modelviewer/resource.Resource} resources
+   *   Resources.
+   * @returns {integer} Count of really removed resources.
+   * @package
+   */
+  remove(...resources) {
+    let removedCount = 0;
+    resources.forEach(resource => {
+      resource.variables.forEach(variable => {
+        if (this._resources.has(variable.variableCollection))
+          if (this._resources.get(variable.variableCollection).delete(resource))
+            removedCount++;
+      });
+    });
+    return removedCount;
+  }
+  
+  /**
+   * Returns all or a part of the resources contained in this node. The returned
+   * resources are defined by all of the passed variables.
+   * 
+   * @param {boolean} [exactlyMatch=false] - Only return resources, which are
+   *   defined exactly by the passed variables.
+   * @param {...module:meteoJS/modelviewer/variable.Variable} variables
+   *   Variables.
+   * @returns {module:meteoJS/modelviewer/resource.Resource[]} Resources.
+   */
+  getResourcesByVariables(...variables) {
+    let exactlyMatch = false;
+    if (variables.length &&
+        typeof variables[0] === 'boolean')
+      exactlyMatch = variables.shift();
+    
+    if (variables.length == 0)
+      return [];
+    
+    return this.resources.filter(resource => {
+      return resource.isDefinedBy(exactlyMatch, ...variables);
+    });
+  }
+}
+addEventFunctions(Node.prototype);
+export default Node;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_OffsetVariable.js.html b/doc/modelviewer_OffsetVariable.js.html new file mode 100644 index 00000000..54a083c3 --- /dev/null +++ b/doc/modelviewer_OffsetVariable.js.html @@ -0,0 +1,140 @@ + + + + + + + Source: modelviewer/OffsetVariable.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/offsetVariable
+ */
+import TimeVariable from './TimeVariable.js';
+
+/**
+ * Options for OffsetVariable constructor
+ * 
+ * @typedef {module:meteoJS/base/timeVariable~options}
+ *   module:meteoJS/modelviewer/offsetVariable~options
+ * @param {undefined|Date} [run] - Runtime.
+ * @param {undefined|integer} [offset] - Offset in seconds.
+ */
+
+/**
+ * @classdesc Class for something representing a time. The constructor supports
+ *   passing a runtime and an offset from this runtime.
+ */
+export class OffsetVariable extends TimeVariable {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/offsetVariable~options} options - Options.
+   */
+  constructor({ id,
+    name = undefined,
+    names = {},
+    langSortation = [],
+    datetime = undefined,
+    run = undefined,
+    offset = undefined } = {}) {
+    super({
+      id,
+      name,
+      names,
+      langSortation,
+      datetime
+    });
+    
+    /**
+     * @type undefined|Date
+     */
+    this._run = run;
+    /**
+     * @type undefined|integer
+     */
+    this._offset = offset;
+    
+    this._updateDatetime();
+  }
+  
+  /**
+   * Runtime.
+   * 
+   * @type Date|undefined
+   */
+  get run() {
+    return this._run;
+  }
+  set run(run) {
+    this._run = run;
+    this._updateDatetime();
+  }
+  
+  /**
+   * Offset.
+   * 
+   * @type integer|undefined
+   */
+  get offset() {
+    return this._offset;
+  }
+  set offset(offset) {
+    this._offset = offset;
+    this._updateDatetime();
+  }
+  
+  /**
+   * Sets datetime according to run and offset.
+   * @private
+   */
+  _updateDatetime() {
+    if (this._run !== undefined &&
+        this._offset !== undefined)
+      this.datetime = new Date(this._run.valueOf() + this._offset * 1000);
+  }
+}
+export default OffsetVariable;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_Resource.js.html b/doc/modelviewer_Resource.js.html new file mode 100644 index 00000000..d7dafddb --- /dev/null +++ b/doc/modelviewer_Resource.js.html @@ -0,0 +1,236 @@ + + + + + + + Source: modelviewer/Resource.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/resource
+ */
+import Variable from './Variable.js';
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {Object} module:meteoJS/modelviewer/resource~options
+ * @param {module:meteoJS/modelviewer/variable.Variable[]} [variables] -
+ *   Variables, which define this resource uniquely.
+ * @param {Date} [datetime] - Datetime, ignored if run and offset are defined.
+ * @param {Date} [run] - Runtime.
+ * @param {integer} [offset] - Offset in seconds.
+ */
+
+/**
+ * @classdesc Class to describe a data resource like a modelplot or a
+ *   sounding data. The resource must be defined uniquely by several variables
+ *   (like model, runtime, …). You should not define the resource by
+ *   several variables of the same collection.
+ * @abstract
+ */
+export class Resource {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/resource~options} [options] - Options.
+   */
+  constructor({ variables = [],
+    datetime = undefined,
+    run = undefined,
+    offset = undefined } = {}) {
+    /**
+     * @type Set<module:meteoJS/modelviewer/variable.Variable>
+     * @private
+     */
+    this._variables = new Set;
+    variables.forEach(variable => this._variables.add(variable));
+    
+    /**
+     * @type Date|undefined
+     * @private
+     */
+    this._datetime = datetime;
+    
+    /**
+     * @type undefined|Date
+     */
+    this._run = run;
+    
+    /**
+     * @type undefined|integer
+     */
+    this._offset = offset;
+    
+    this._updateDatetime();
+  }
+  
+  /**
+   * Variable objects, which define this resource. Like model, run, offset,…
+   * 
+   * @type module:meteoJS/modelviewer/variable.Variable[]
+   * @readonly
+   */
+  get variables() {
+    return [...this._variables];
+  }
+  
+  /**
+   * Resource is valid for this datetime. If undefined, than the resource is
+   * not only valid at one datetime.
+   * 
+   * @type Date|undefined
+   */
+  get datetime() {
+    return this._datetime;
+  }
+  set datetime(datetime) {
+    this._datetime = datetime;
+  }
+  
+  /**
+   * Runtime.
+   * 
+   * @type Date|undefined
+   */
+  get run() {
+    return this._run;
+  }
+  set run(run) {
+    this._run = run;
+    this._updateDatetime();
+  }
+  
+  /**
+   * Offset.
+   * 
+   * @type integer|undefined
+   */
+  get offset() {
+    return this._offset;
+  }
+  set offset(offset) {
+    this._offset = offset;
+    this._updateDatetime();
+  }
+  
+  /**
+   * Returns the variable-object that is part of the definition of this resource
+   * and contains to the passed collection. If you define the resource by
+   * several variables of the same variable collection, it is not defined
+   * which variable is returned.
+   * 
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+   *   variableCollection - VariableCollection.
+   * @returns {module:meteoJS/modelviewer/variable.Variable}
+   */
+  getVariableByVariableCollection(variableCollection) {
+    let result = undefined;
+    this.variables.forEach(variable => {
+      if (variable.variableCollection === variableCollection)
+        result = variable;
+    });
+    return (result === undefined) ? new Variable() : result;
+  }
+  
+  /**
+   * Returns if the passed Variable-objects all define this resource.
+   * 
+   * @param {boolean} [exactlyMatch] - Only return true, if the passed
+   *   variables exactly define the resource.
+   * @param {...module:meteoJS/modelviewer/variable.Variable} variables
+   *   Variables.
+   * @returns {boolean} All passed variables defines the resource.
+   */
+  isDefinedBy(...variables) {
+    let exactlyMatch = false;
+    if (variables.length &&
+        typeof variables[0] === 'boolean')
+      exactlyMatch = variables.shift();
+    if (!exactlyMatch)
+      return variables.filter(v => !this._variables.has(v)).length == 0;
+    
+    let result = true;
+    let variablesSet = new Set(variables);
+    for (let variable of variablesSet)
+      if (!this._variables.has(variable))
+        result = false;
+    for (let variable of this._variables)
+      if (!variablesSet.has(variable))
+        result = false;
+    return result;
+  }
+  
+  /**
+   * Returns if a Variable-object of the passed collection defines this
+   * resource.
+   * 
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+   *   variableCollection - VariableCollection.
+   * @returns {boolean} A variable of the collection defines the resource.
+   */
+  isDefinedByVariableOf(variableCollection) {
+    let result = false;
+    variableCollection.variables.forEach(variable => {
+      if (this.isDefinedBy(variable))
+        result = true;
+    });
+    return result;
+  }
+  
+  /**
+   * Sets datetime according to run and offset.
+   * 
+   * @private
+   */
+  _updateDatetime() {
+    if (this._run !== undefined &&
+        this._offset !== undefined)
+      this.datetime = new Date(this._run.valueOf() + this._offset * 1000);
+  }
+}
+export default Resource;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_Resources.js.html b/doc/modelviewer_Resources.js.html new file mode 100644 index 00000000..e97d3e29 --- /dev/null +++ b/doc/modelviewer_Resources.js.html @@ -0,0 +1,549 @@ + + + + + + + Source: modelviewer/Resources.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/resources
+ */
+import addEventFunctions from '../Events.js';
+import Image from './resource/Image.js';
+import VariableCollection from './VariableCollection.js';
+import Node from './Node.js';
+
+/**
+ * Triggered on adding and removing Resource-Objects.
+ * 
+ * @event module:meteoJS/modelviewer/resources#change:resources
+ * @type {Object}
+ * @property {module:meteoJS/modelviewer/resource.Resource} [addedResources] -
+ *   Added resources.
+ * @property {module:meteoJS/modelviewer/resource.Resource} [removedResources] -
+ *   Removed resources.
+ */
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {Object} module:meteoJS/modelviewer/resources~options
+ * @param {module:meteoJS/modelviewer/node.Node} topNode - Top level node.
+ * @param {Set<module:meteoJS/modelviewer/variableCollection.VariableCollection>}
+ *   timesVariableCollections - These collections group the top part of the
+ *   hierarchy. For NWP, this contains  typically the model and the run
+ *   collection.
+ */
+
+/**
+ * @classdesc Linchpin of the modelviewer. In this class every available
+ *   resource is registered. Additionally requests about data per Variable can
+ *   be performed, like all available run times of a model or all available
+ *   fields of model, etc. The hierarchy via
+ *   {@link module:meteoJS/modelviewer/node.Node|Node}
+ *   has to be defined before the construction of Resources.
+ * 
+ * @fires module:meteoJS/modelviewer/resources#change:resources
+ */
+export class Resources {
+  
+  constructor({ topNode,
+    timesVariableCollections = [] } = {}) {
+    
+    /**
+     * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+     * @private
+     */
+    this._topNode = topNode;
+    
+    /**
+     * @type Map<module:meteoJS/modelviewer/node.Node,
+     *           Set<module:meteoJS/modelviewer/variable.Variable>>
+     * @private
+     */
+    this._availableVariablesMap = new Map();
+    
+    /**
+     * @type Set<module:meteoJS/modelviewer/variableCollection.VariableCollection>
+     * @private
+     */
+    this._timesVariableCollections = timesVariableCollections;
+  }
+  
+  /**
+   * VariableCollectionNode that stand on the top of the hierarchy.
+   * 
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+   * @readonly
+   */
+  get topNode() {
+    return this._topNode;
+  }
+  
+  /**
+   * @type module:meteoJS/modelviewer/variableCollection.VariableCollection[]
+   * @readonly
+   */
+  get variableCollections() {
+    let pushChildCollections;
+    pushChildCollections = node => {
+      node.children.forEach(n => {
+        result.push(n.variableCollection);
+        pushChildCollections(n);
+      });
+    };
+    let result = [this.topNode.variableCollection];
+    pushChildCollections(this.topNode);
+    return result;
+  }
+  
+  /**
+   * Map of nodes and their variables (contained in the variableCollection of
+   * the node). For each variable exists at least one resource in this
+   * Resources-object that is defined by this variable.
+   * 
+   * @type Map<module:meteoJS/modelviewer/node.Node,
+   *           Set<module:meteoJS/modelviewer/variable.Variable>>
+   * @readonly
+   */
+  get availableVariablesMap() {
+    return this._availableVariablesMap;
+  }
+  
+  /**
+   * Append resources.
+   * 
+   * @param {...module:meteoJS/modelviewer/resource.Resource} resources
+   *   Available resources.
+   * @returns {module:meteoJS/modelviewer/resources.Resources} This.
+   * @fires module:meteoJS/modelviewer/resources#change:resources
+   */
+  append(...resources) {
+    let addedResources = [];
+    resources.forEach(resource => {
+      let topNode = this._getTopNodeOfResourceDefinition(resource, this.topNode);
+      if (topNode !== undefined) {
+        let node = this._getTopMostChildWithAllVariables(new Set(resource.variables), topNode, true);
+        if (node !== undefined) {
+          let addedCount = node.append(resource);
+          if (addedCount > 0) {
+            addedResources.push(resource);
+            this._addAvailableVariablesMapByResource(resource);
+          }
+        }
+      }
+    });
+    if (addedResources.length > 0) {
+      // Debounce firing
+      if (INTERNAL_CHANGE_RESOURCES.timeoutId)
+        clearTimeout(INTERNAL_CHANGE_RESOURCES.timeoutId);
+      INTERNAL_CHANGE_RESOURCES.addedResources.push(...addedResources);
+      INTERNAL_CHANGE_RESOURCES.timeoutId = setTimeout(() => {
+        this.trigger('change:resources', {
+          addedResources: INTERNAL_CHANGE_RESOURCES.addedResources
+        });
+        INTERNAL_CHANGE_RESOURCES.addedResources = [];
+      }, 100);
+    }
+    return this;
+  }
+  
+  /**
+   * Adds variables of a resource to _availableVariablesMap.
+   * 
+   * @param {module:meteoJS/modelviewer/resource.Resource} resource - Resource.
+   * @private
+   */
+  _addAvailableVariablesMapByResource(resource) {
+    resource.variables.forEach(variable => {
+      if (variable.variableCollection.node === undefined)
+        return;
+      if (!this._availableVariablesMap.has(variable.variableCollection.node))
+        this._availableVariablesMap.set(variable.variableCollection.node, new Set());
+      this._availableVariablesMap.get(variable.variableCollection.node).add(variable);
+    });
+  }
+  
+  /**
+   * Removes resources.
+   * 
+   * @param {...module:meteoJS/modelviewer/resource.Resource} resources
+   *   Resources.
+   * @returns {module:meteoJS/modelviewer/resources.Resources} This.
+   * @fires module:meteoJS/modelviewer/resources#change:resources
+   */
+  remove(...resources) {
+    let removedResources = [];
+    let removedNodeResourcesMap = new Map();
+    resources.forEach(resource => {
+      let topNode = this._getTopNodeOfResourceDefinition(resource, this.topNode);
+      if (topNode !== undefined) {
+        let node = this._getTopMostChildWithAllVariables(new Set(resource.variables), topNode, true);
+        if (node !== undefined) {
+          let removedCount = node.remove(resource);
+          if (removedCount > 0) {
+            removedResources.push(resource);
+            if (!removedNodeResourcesMap.has(node))
+              removedNodeResourcesMap.set(node, new Set());
+            removedNodeResourcesMap.get(node).add(resource);
+          }
+        }
+      }
+    });
+    if (removedNodeResourcesMap.size > 0)
+      this._removeAvailableVariablesMapByResources(removedNodeResourcesMap);
+    if (removedResources.length > 0)
+      this.trigger('change:resources', { removedResources });
+    return this;
+  }
+  
+  /**
+   * Removes variables from _availableVariablesMap.
+   * Prerequisite: The resources have already to be removed of the nodes.
+   * 
+   * @param {Map<module:meteoJS/modelviewer/node.Node,
+   *         Set<module:meteoJS/modelviewer/resource.Resource>>}
+   *   removedNodeResourcesMap - Map of Nodes with their removed Resources.
+   * @private
+   */
+  _removeAvailableVariablesMapByResources(removedNodeResourcesMap) {
+    let fullCheckVariables = new Set();
+    for (let [node, resourcesSet] of removedNodeResourcesMap.entries()) {
+      let variables = new Set();
+      for (let resource of resourcesSet)
+        resource.variables.forEach(variable => variables.add(variable));
+      for (let variable of variables)
+        if (node.getResourcesByVariables(variable).length == 0)
+          fullCheckVariables.add(variable);
+    }
+    for (let variable of fullCheckVariables) {
+      let node = this.getNodeByVariableCollection(variable.variableCollection);
+      if (this._getResourcesOf(node, 'children', [ variable ]).length == 0)
+        if (this._availableVariablesMap.has(node))
+          this._availableVariablesMap.get(node).delete(variable);
+    }
+  }
+  
+  /**
+   * Returns a node of the hierarchy, so that all parents and itself contain
+   * all the passed variables. The returned node is the most top in hierarchy
+   * as possible. If no node is found, an empty node object is returned.
+   * 
+   * @param {...module:meteoJS/modelviewer/variable.Variable} variables
+   *   Variables.
+   * @returns {module:meteoJS/modelviewer/node.Node} - Node.
+   */
+  getTopMostNodeWithAllVariables(...variables) {
+    let result =
+      this._getTopMostChildWithAllVariables(new Set(variables), this.topNode, true);
+    return (result === undefined) ? new Node(new VariableCollection()) : result;
+  }
+  
+  /**
+   * Returns first node in hierarchy that contains a VariableCollection which
+   * is part of the definition of the passed resource.
+   * 
+   * @param {module:meteoJS/modelviewer/resource.Resource} resource
+   *   Resource.
+   * @param {module:meteoJS/modelviewer/node.Node} node
+   *   Search from 'node' and all the children.
+   * @returns {undefined|module:meteoJS/modelviewer/node.Node}
+   *   Node or undefined if no node is found.
+   * @private
+   */
+  _getTopNodeOfResourceDefinition(resource, node) {
+    if (resource.isDefinedByVariableOf(node.variableCollection))
+      return node;
+    let result = undefined;
+    node.children.forEach(childNode => {
+      if (result !== undefined)
+        result = this._getTopNodeOfResourceDefinition(resource, childNode);
+    });
+    return result;
+  }
+  
+  /**
+   * Returns top most node for which on the way down (beginning from node)
+   * all variables are contained by the VariableCollections of the travelled
+   * nodes.
+   * 
+   * @param {Set<module:meteoJS/modelviewer/variable.Variable>} variables
+   *   Variables which have still to be found.
+   * @param {module:meteoJS/modelviewer/node.Node} node - Node.
+   * @param {boolean} bubbleDown - .
+   * @returns {undefined|module:meteoJS/modelviewer/node.Node} Child node.
+   */
+  _getTopMostChildWithAllVariables(variables, node, bubbleDown) {
+    let isVariableContained = false;
+    node.variableCollection.variables.forEach(variable => {
+      if (variables.has(variable)) {
+        isVariableContained = true;
+        variables.delete(variable);
+      }
+    });
+    if (variables.size == 0)
+      return node;
+    else if (node.children.length == 0)
+      return undefined;
+    else if (!isVariableContained &&
+             !bubbleDown)
+      return undefined;
+    let result = undefined;
+    node.children.forEach(childNode => {
+      if (result === undefined)
+        result = this._getTopMostChildWithAllVariables(variables, childNode, bubbleDown);
+    });
+    return result;
+  }
+  
+  /**
+   * Returns node which contains the passed variableCollection
+   * 
+   * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+   *   variableCollection
+   *   VariableCollection.
+   * @returns {module:meteoJS/modelviewer/node.Node} Node.
+   */
+  getNodeByVariableCollection(variableCollection) {
+    return (variableCollection.node === undefined)
+      ? new Node(new VariableCollection())
+      : variableCollection.node;
+  }
+  
+  /**
+   * Returns node which contains the variableCollection with the passed Id.
+   * 
+   * @param {mixed} id - Id.
+   * @returns {module:meteoJS/modelviewer/node.Node} Node.
+   */
+  getNodeByVariableCollectionId(id) {
+    let result = this._getNodeByVariableCollection(a => id == a.id);
+    return (result === undefined) ? new Node(new VariableCollection()) : result;
+  }
+  
+  /**
+   * Returns node which contains the passed variableCollection.
+   * 
+   * @param {Function} compareFunc - Argument is a VariableCollection-object.
+   * @returns {undefined|module:meteoJS/modelviewer/node.Node} Node.
+   * @private
+   */
+  _getNodeByVariableCollection(compareFunc) {
+    return (compareFunc(this.topNode.variableCollection))
+      ? this.topNode
+      : this._findChildNodeByVariableCollection(compareFunc, this.topNode);
+  }
+  
+  /**
+   * Returns a VariableCollection with passed variableCollection of
+   * node's children.
+   * 
+   * @param {Function} compareFunc - Argument is a VariableCollection-object.
+   * @param {module:meteoJS/modelviewer/node.Node} parentNode
+   *   Search recursively in this node's children.
+   * @returns {undefined|module:meteoJS/modelviewer/node.Node} Node.
+   * @private
+   */
+  _findChildNodeByVariableCollection(compareFunc, parentNode) {
+    let result;
+    parentNode.children.forEach(n => {
+      if (result === undefined &&
+          compareFunc(n.variableCollection)) {
+        result = n;
+        return;
+      }
+      if (result === undefined &&
+          n.children.length > 0)
+        result = this._findChildNodeByVariableCollection(compareFunc, n);
+    });
+    return result;
+  }
+  
+  /**
+   * Appends an Image-resource. Alias for append(new Image(…)).
+   * 
+   * @see module:meteoJS/modelviewer/resource/image.Image
+   * @returns {module:meteoJS/modelviewer/resources.Resources} This.
+   */
+  appendImage({ variables, datetime, run, offset, url }) {
+    this.append(new Image({
+      variables,
+      datetime,
+      run,
+      offset,
+      url
+    }));
+    return this;
+  }
+  
+  /**
+   * Returns an Set of available Variable-Objects from a VariableCollection.
+   * For this objects at least one resource is contained in this Resources-
+   * Object. With 'variables' the resources will be limited in which only
+   * variables will be considered from parents collections. Only resources
+   * which are assigned to these variables will be accounted.
+   * 
+   * @param {module:meteoJS/modelviewer/VariableCollection.VariableCollection}
+   *   variableCollection
+   *   Return Variables of this VariableCollection.
+   * @param {module:meteoJS/modelviewer/Variable.Variable[]}
+   *   Only 
+   * @returns {Set<module:meteoJS/modelviewer/Variable.Variable>}
+   *   Available variables.
+   */
+  getAvailableVariables(variableCollection, { variables = [] } = {}) {
+    variables = new Set(variables);
+    let node = variableCollection.node;
+    let parentsVariables = this._getVariablesOfParents(node, variables);
+    let resources = node.getResourcesByVariables(...parentsVariables);
+    [].push
+      .apply(resources, this._getResourcesOf(node, 'children', parentsVariables));
+    [].push
+      .apply(resources, this._getResourcesOf(node, 'parents', parentsVariables));
+    let result = new Set();
+    resources.forEach(resource => {
+      for (let variable of variableCollection)
+        if (resource.isDefinedBy(variable, ...parentsVariables))
+          result.add(variable);
+    });
+    return result;
+  }
+  
+  /**
+   * @param {module:meteoJS/modelviewer/node.Node} node
+   * @param {Set<module:meteoJS/modelviewer/Variable.Variable>} variables
+   * @returns {Set<module:meteoJS/modelviewer/Variable.Variable>}
+   * @private
+   */
+  _getVariablesOfParents(node, variables) {
+    let newVariables = new Set();
+    node.parents.forEach(n => {
+      n.variableCollection.variables.map(variable => {
+        if (variables.has(variable))
+          newVariables.add(variable);
+      });
+      let nV = this._getVariablesOfParents(n, variables);
+      for (let v of nV)
+        newVariables.add(v);
+    });
+    return newVariables;
+  }
+  
+  /**
+   * Traverses all children respectively parents of the passed node. Collects
+   * all resources in this traversed nodes, which are defined by all of the
+   * passed variables. Returns this collected resources.
+   * 
+   * @param {module:meteoJS/modelviewer/node.Node} node - Node.
+   * @param {string} key - 'children' or 'parents'.
+   * @returns {module:meteoJS/modelviewer/resource.Resource[]} Resources.
+   * @private
+   */
+  _getResourcesOf(node, key, variables) {
+    let result = [];
+    node[key].forEach(n => {
+      [].push.apply(result, n.getResourcesByVariables(...variables));
+      [].push.apply(result, this._getResourcesOf(n, key, variables));
+    });
+    return result;
+  }
+  
+  /**
+   * Returns all times, that are contains in the times group, defined by
+   * the option timesVariableCollections.
+   * 
+   * @param {...module:meteoJS/modelviewer/variable.Variable} variables
+   *   Variables.
+   * @returns {Date[]} - Sorted upwardly.
+   */
+  getTimesByVariables(...variables) {
+    let collectVariables = variables
+      .filter(variable => {
+        let result = false;
+        this._timesVariableCollections.forEach(collection => {
+          if (collection.contains(variable))
+            result = true;
+        });
+        return result;
+      });
+    if (collectVariables.length != this._timesVariableCollections.size)
+      return [];
+    
+    let node =
+      this._getTopMostChildWithAllVariables(
+        new Set(collectVariables),
+        this.topNode,
+        true
+      );
+    if (node === undefined)
+      return [];
+    
+    let times = new Set();
+    let collectTimes = node => {
+      node.getResourcesByVariables(...collectVariables).forEach(resource => {
+        if (resource.datetime !== undefined)
+          times.add(resource.datetime.valueOf());
+      });
+      node.children.forEach(n => collectTimes(n));
+    };
+    collectTimes(node);
+    return [...times].sort().map(t => new Date(t));
+  }
+}
+addEventFunctions(Resources.prototype);
+export default Resources;
+
+/**
+ * @private
+ */
+const INTERNAL_CHANGE_RESOURCES = {
+  timeoutId: undefined,
+  addedResources: []
+};
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_TimeVariable.js.html b/doc/modelviewer_TimeVariable.js.html new file mode 100644 index 00000000..bc7bbd94 --- /dev/null +++ b/doc/modelviewer_TimeVariable.js.html @@ -0,0 +1,115 @@ + + + + + + + Source: modelviewer/TimeVariable.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/timeVariable
+ */
+import Variable from './Variable.js';
+
+/**
+ * Options for TimeVariable constructor
+ * 
+ * @typedef {module:meteoJS/base/uniquenamed~options}
+ *   module:meteoJS/modelviewer/timeVariable~options
+ * @param {Date|undefined} [datetime] - Datetime.
+ */
+
+/**
+ * @classdesc Class for something representing a time, e.g. runtime or offset.
+ */
+export class TimeVariable extends Variable {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/timeVariable~options} options - Options.
+   */
+  constructor({ id,
+    name = undefined,
+    names = {},
+    langSortation = [],
+    datetime = undefined } = {}) {
+    super({
+      id,
+      name,
+      names,
+      langSortation
+    });
+    
+    /**
+     * @type Date|undefined
+     * @private
+     */
+    this._datetime = (this.id === undefined) ? undefined : new Date(this.id);
+    
+    if (datetime !== undefined)
+      this.datetime = datetime;
+  }
+  
+  /**
+   * @override
+   */
+  setId(id) {
+    this._datetime = (id === undefined) ? undefined : new Date(id);
+  }
+  
+  /**
+   * @type Date|undefined
+   */
+  get datetime() {
+    return this._datetime;
+  }
+  set datetime(datetime) {
+    this._datetime = datetime;
+    this._id = (datetime !== undefined) ? datetime.valueOf() : undefined;
+  }
+}
+export default TimeVariable;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_Variable.js.html b/doc/modelviewer_Variable.js.html new file mode 100644 index 00000000..6a942379 --- /dev/null +++ b/doc/modelviewer_Variable.js.html @@ -0,0 +1,106 @@ + + + + + + + Source: modelviewer/Variable.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/variable
+ */
+import UniqueNamed from '../base/UniqueNamed.js';
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {module:meteoJS/base/uniquenamed~options}
+ *   module:meteoJS/modelviewer/variable~options
+ * @param {module:meteoJS/modelviewer/variableCollection.VariableCollection}
+ *   [variableCollection] - Belongs to this VariableCollection.
+ */
+
+/**
+ * @classdesc Object for e.g. a model, a runtime or a field.
+ */
+export class Variable extends UniqueNamed {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/variable~options} [options] - Options.
+   */
+  constructor({ id,
+    name = undefined,
+    names = {},
+    langSortation = [],
+    variableCollection } = {}) {
+    super({
+      id,
+      name,
+      names,
+      langSortation
+    });
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer/variableCollection.VariableCollection
+     * @private
+     */
+    this._variableCollection = variableCollection;
+  }
+  
+  /**
+   * This Variable belongs to this VariableCollection.
+   * @type undefined|module:meteoJS/modelviewer/variableCollection.VariableCollection
+   */
+  get variableCollection() {
+    return this._variableCollection;
+  }
+  set variableCollection(variableCollection) {
+    this._variableCollection = variableCollection;
+  }
+}
+export default Variable;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_VariableCollection.js.html b/doc/modelviewer_VariableCollection.js.html new file mode 100644 index 00000000..062ec8c4 --- /dev/null +++ b/doc/modelviewer_VariableCollection.js.html @@ -0,0 +1,178 @@ + + + + + + + Source: modelviewer/VariableCollection.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/variableCollection
+ */
+import Variable from './Variable.js';
+import Unique from '../base/Unique.js';
+import UniqueNamed from '../base/UniqueNamed.js';
+import NamedCollection from '../base/NamedCollection.js';
+
+/**
+ * Triggered on adding a Variable to collection.
+ * 
+ * @event module:meteoJS/modelviewer/variableCollection#add:variable
+ * @param {module:meteoJS/modelviewer/variable.Variable} variable -
+ *   Added variable.
+ */
+
+/**
+ * Triggered on removing a Variable from collection.
+ * 
+ * @event module:meteoJS/modelviewer/variableCollection#remove:variable
+ * @param {module:meteoJS/modelviewer/variable.Variable} variable -
+ *   Removed variable.
+ */
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {module:meteoJS/base/namedCollection~options}
+ *   module:meteoJS/modelviewer/variableCollection~options
+ */
+
+/**
+ * @classdesc A collection of Variable-objects. It also defines a hierarchy
+ *   of the collections. So a VariableCollection could have children and
+ *   parents. A variable object can only belong to one collection.
+ * @augments module:meteoJS/base/unique.Unique
+ * @fires module:meteoJS/modelviewer/variableCollection#add:variable
+ * @fires module:meteoJS/modelviewer/variableCollection#remove:variable
+ */
+export class VariableCollection extends NamedCollection {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/variableCollection~options} options
+   *   - Options.
+   */
+  constructor({ id,
+    fireReplace=true,
+    fireAddRemoveOnReplace=false,
+    appendOnReplace=true,
+    sortFunction,
+    names,
+    langSortation } = {}) {
+    super({
+      emptyObjectMaker: () => { return new Variable(); },
+      fireReplace,
+      fireAddRemoveOnReplace,
+      appendOnReplace,
+      sortFunction,
+      names,
+      langSortation
+    });
+    
+    Object.defineProperty(this, 'id',
+      Object.getOwnPropertyDescriptor(Unique.prototype, 'id'));
+    // constructor code of Unique
+    this._id = id;
+    
+    // ID as name
+    Object.defineProperty(this, 'getDefaultName',
+      Object.getOwnPropertyDescriptor(UniqueNamed.prototype, 'getDefaultName'));
+    
+    /**
+     * @type undefined|module:meteoJS/modelviewer/node.Node
+     * @private
+     */
+    this._node = undefined;
+    
+    this.on('add:item', item => {
+      if (item.variableCollection !== undefined)
+        item.variableCollection.remove(item);
+      item.variableCollection = this;
+      this.trigger('add:variable', item);
+    });
+    this.on('remove:item', item => this.trigger('remove:variable', item));
+  }
+  
+  /**
+   * @override
+   */
+  setId(id) {
+    Unique.prototype.setId.call(this, id);
+  }
+  
+  /**
+   * Variables contained by this collection.
+   * 
+   * @type module:meteoJS/modelviewer/variable.Variable[]
+   */
+  get variables() {
+    return this.items;
+  }
+  
+  /**
+   * Alias of getItemById.
+   * 
+   * @param {mixed} id ID.
+   * @returns {module:meteoJS/modelviewer/variable.Variable} Variable.
+   */
+  getVariableById(id) {
+    return this.getItemById(id);
+  }
+  
+  /**
+   * If defined, this VariableCollection belongs to this node.
+   * 
+   * @type undefined|module:meteoJS/modelviewer/node.Node
+   */
+  get node() {
+    return this._node;
+  }
+  set node(node) {
+    this._node = node;
+  }
+}
+export default VariableCollection;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_display_SelectNavigation.js.html b/doc/modelviewer_display_SelectNavigation.js.html new file mode 100644 index 00000000..39c544c4 --- /dev/null +++ b/doc/modelviewer_display_SelectNavigation.js.html @@ -0,0 +1,157 @@ + + + + + + + Source: modelviewer/display/SelectNavigation.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/display/selectNavigation
+ */
+import $ from 'jquery';
+import Simple from './Simple.js';
+
+/**
+ * @classdesc 
+ */
+export class SelectNavigation extends Simple {
+  
+  constructor({ ignoreVariableCollections = [],
+    selectCaption = false,
+    navigationClass = undefined,
+    selectDivClass = undefined,
+    selectClass = undefined } = {}) {
+    super();
+    
+    this.options = {
+      ignoreVariableCollections: new Set(ignoreVariableCollections),
+      selectCaption,
+      navigationClass,
+      selectDivClass,
+      selectClass
+    };
+    
+    /**
+     * @type undefined|jQuery
+     * @private
+     */
+    this.navigationNode = undefined;
+    
+    /**
+     * @type Map<module:meteoJS/modelviewer/variableCollection.variableCollection,jQuery>
+     * @private
+     */
+    this.selectNodes = new Map();
+  }
+  
+  /**
+   * @override
+   */
+  onInit() {
+    if (this.parentNode === undefined)
+      return;
+    this.navigationNode = $('<div>').addClass(this.options.navigationClass);
+    this.resourceNode = $('<div>');
+    $(this.parentNode).empty().append(this.navigationNode, this.resourceNode);
+    if (this.modelviewer !== undefined)
+      this.modelviewer.resources.variableCollections
+        .filter(collection => !this.options.ignoreVariableCollections.has(collection) && collection.count > 0)
+        .forEach(collection => this._appendSelectNode(collection));
+    this._changeSelected();
+  }
+  
+  onChangeVisibleResource({ variable } = {}) {
+    super.onChangeVisibleResource({ variable });
+    this._changeSelected();
+  }
+  
+  onAppendVariable(variable) {
+    if (this.selectNodes.has(variable.variableCollection))
+      this._appendOptionNode(this.selectNodes.get(variable.variableCollection), variable);
+    else
+      this._appendSelectNode(variable.variableCollection);
+    this._changeSelected();
+  }
+  
+  _appendSelectNode(variableCollection) {
+    let selectNode = $('<select>').addClass(this.options.selectClass);
+    selectNode.on('change', () => {
+      let variable = variableCollection.getItemById(selectNode.val());
+      this.container.exchangeDisplayVariable = [ variable ];
+    });
+    if (this.options.selectCaption) {
+      let captionOption = $('<option>').text(variableCollection.name).attr('disabled', 'disabled').prop('selected', 'selected');
+      selectNode.append(captionOption);
+    }
+    variableCollection.variables.forEach(variable => {
+      this._appendOptionNode(selectNode, variable);
+    });
+    this.navigationNode.append($('<div>').addClass(this.options.selectDivClass).append(selectNode));
+    this.selectNodes.set(variableCollection, selectNode);
+  }
+  
+  _appendOptionNode(selectNode, variable) {
+    let option =
+      $('<option>')
+        .attr('value', variable.id)
+        .text(variable.name)
+        .addClass(this.options.optionsClass);
+    selectNode.append(option);
+  }
+  
+  _changeSelected() {
+    for (let variableCollection of this.selectNodes.keys()) {
+      if (!this.selectNodes.has(variableCollection))
+        continue;
+      let variable = this.container.visibleResource.getVariableByVariableCollection(variableCollection);
+      this.selectNodes.get(variableCollection).val(variable.id);
+    }
+  }
+}
+export default SelectNavigation;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_display_Simple.js.html b/doc/modelviewer_display_Simple.js.html new file mode 100644 index 00000000..9b38ffd1 --- /dev/null +++ b/doc/modelviewer_display_Simple.js.html @@ -0,0 +1,147 @@ + + + + + + + Source: modelviewer/display/Simple.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/display/simple
+ */
+import $ from 'jquery';
+import ThermodynamicDiagram from '../../ThermodynamicDiagram.js';
+import Display from '../Display.js';
+
+/**
+ * @classdesc Displays a modelviewer container with a navigation on top of the
+ *   resource. The navigation contains of several select-Nodes (each for a
+ *   VariableCollection).
+ */
+export class Simple extends Display {
+  
+  constructor() {
+    super();
+    
+    /**
+     * @type undefined|jQuery
+     * @private
+     */
+    this.imgNode = undefined;
+    
+    /**
+     * @type undefined|meteoJS/thermodynamicDiagram.ThermodynamicDiagram
+     * @private
+     */
+    this.thermodynamicDiagram = undefined;
+    
+    /**
+     * @type undefined|jQuery
+     * @protected
+     */
+    this.resourceNode = undefined;
+  }
+  
+  /**
+   * @override
+   */
+  onInit() {
+    if (this.parentNode !== undefined) {
+      this.resourceNode = $(this.parentNode);
+      this.resourceNode.empty();
+    }
+  }
+  
+  /**
+   * @override
+   */
+  onChangeVisibleResource() {
+    if (this.resourceNode === undefined)
+      return;
+    let visibleResource = this.container.visibleResource;
+    if ('url' in visibleResource) {
+      if (this.thermodynamicDiagram !== undefined) {
+        this.thermodynamicDiagram = undefined;
+        this.resourceNode.empty();
+      }
+      if (this.imgNode === undefined) {
+        this.resourceNode.empty();
+        this.imgNode = $('<img>');
+        this.resourceNode.append(this.imgNode);
+      }
+      this.imgNode.attr('src', visibleResource.url);
+      this.imgNode.css({ 'max-width': '100%' });
+    }
+    else if ('sounding' in visibleResource) {
+      if (this.imgNode !== undefined) {
+        this.imgNode = undefined;
+        this.resourceNode.empty();
+      }
+      if (this.thermodynamicDiagram === undefined)
+        this.thermodynamicDiagram = new ThermodynamicDiagram({
+          renderTo: this.resourceNode
+        });
+      let isAppended = false;
+      this.thermodynamicDiagram.soundings.forEach(sounding => {
+        if (sounding.getSounding() === visibleResource.sounding) {
+          isAppended = true;
+          sounding.visible(true);
+        }
+        else
+          sounding.visible(false);
+      });
+      if (!isAppended)
+        this.thermodynamicDiagram.addSounding(visibleResource.sounding);
+    }
+    else {
+      this.imgNode = undefined;
+      this.resourceNode.empty();
+    }
+  }
+}
+export default Simple;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_resource_Image.js.html b/doc/modelviewer_resource_Image.js.html new file mode 100644 index 00000000..90db1a2c --- /dev/null +++ b/doc/modelviewer_resource_Image.js.html @@ -0,0 +1,104 @@ + + + + + + + Source: modelviewer/resource/Image.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/resource/image
+ */
+import Resource from '../Resource.js';
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {module:meteoJS/modelviewer/resource~options}
+ *   module:meteoJS/modelviewer/resource/image~options
+ * @param {string} [url] - URL to the Image.
+ */
+
+/**
+ * @classdesc Class to describe an image resource.
+ */
+export class Image extends Resource {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/resource/image~options} [options]
+   *   Options.
+   */
+  constructor({ variables = [],
+    datetime = undefined,
+    run = undefined,
+    offset = undefined,
+    url = undefined /*, mimetype, ...*/ } = {}) {
+    super({
+      variables,
+      datetime,
+      run,
+      offset
+    });
+    
+    /**
+     * @type string
+     * @private
+     */
+    this._url = url;
+  }
+  
+  /**
+   * URL to the Image.
+   * 
+   * @type string
+   */
+  get url() {
+    return this._url;
+  }
+}
+export default Image;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/modelviewer_resource_Sounding.js.html b/doc/modelviewer_resource_Sounding.js.html new file mode 100644 index 00000000..2d46bcea --- /dev/null +++ b/doc/modelviewer_resource_Sounding.js.html @@ -0,0 +1,108 @@ + + + + + + + Source: modelviewer/resource/Sounding.js + + + + + + + + +
+
+
+ +
+ +
+
/**
+ * @module meteoJS/modelviewer/resource/sounding
+ */
+import Resource from '../Resource.js';
+import SoundingData from '../../Sounding.js';
+
+/**
+ * Options for constructor.
+ * 
+ * @typedef {module:meteoJS/modelviewer/resource~options}
+ *   module:meteoJS/modelviewer/resource/sounding~options
+ * @param {module:meteoJS/sounding.Sounding} [sounding] - Sounding data.
+ */
+
+/**
+ * @classdesc Class to describe an sounding resource.
+ */
+export class Sounding extends Resource {
+  
+  /**
+   * @param {module:meteoJS/modelviewer/resource/sounding~options} [options]
+   *   Options.
+   */
+  constructor({ variables = [],
+    datetime = undefined,
+    run = undefined,
+    offset = undefined,
+    sounding = undefined } = {}) {
+    super({
+      variables,
+      datetime,
+      run,
+      offset
+    });
+    
+    /**
+     * @type undefined|module:meteoJS/sounding.Sounding
+     * @private
+     */
+    this._sounding = sounding;
+  }
+  
+  /**
+   * Sounding data.
+   * 
+   * @type module:meteoJS/sounding.Sounding
+   */
+  get sounding() {
+    return (this._sounding === undefined) ? new SoundingData() : this._sounding;
+  }
+  set sounding(sounding) {
+    this._sounding = sounding;
+  }
+}
+export default Sounding;
+
+
+
+ +
+
+
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/module-meteoJS.html b/doc/module-meteoJS.html index a8a3946a..00f066dd 100644 --- a/doc/module-meteoJS.html +++ b/doc/module-meteoJS.html @@ -44,7 +44,7 @@

meteoJS

diff --git a/doc/module-meteoJS_base_collection.Collection.html b/doc/module-meteoJS_base_collection.Collection.html index ad25defd..04cb0f1a 100644 --- a/doc/module-meteoJS_base_collection.Collection.html +++ b/doc/module-meteoJS_base_collection.Collection.html @@ -416,7 +416,7 @@

Parameter

diff --git a/doc/module-meteoJS_base_collection.html b/doc/module-meteoJS_base_collection.html index cd78ed80..b1db368d 100644 --- a/doc/module-meteoJS_base_collection.html +++ b/doc/module-meteoJS_base_collection.html @@ -64,7 +64,7 @@

Collection

diff --git a/doc/module-meteoJS_base_named.Named.html b/doc/module-meteoJS_base_named.Named.html index bf8b4d50..3155f5f0 100644 --- a/doc/module-meteoJS_base_named.Named.html +++ b/doc/module-meteoJS_base_named.Named.html @@ -305,7 +305,7 @@

Parameters

diff --git a/doc/module-meteoJS_base_named.html b/doc/module-meteoJS_base_named.html index c20cf01b..a94c962e 100644 --- a/doc/module-meteoJS_base_named.html +++ b/doc/module-meteoJS_base_named.html @@ -146,7 +146,7 @@

Parameters

diff --git a/doc/module-meteoJS_base_namedCollection.NamedCollection.html b/doc/module-meteoJS_base_namedCollection.NamedCollection.html index fe0ce7fb..119f680c 100644 --- a/doc/module-meteoJS_base_namedCollection.NamedCollection.html +++ b/doc/module-meteoJS_base_namedCollection.NamedCollection.html @@ -79,7 +79,7 @@

Parameter

diff --git a/doc/module-meteoJS_base_namedCollection.html b/doc/module-meteoJS_base_namedCollection.html index 7ab2ae35..6e83a53d 100644 --- a/doc/module-meteoJS_base_namedCollection.html +++ b/doc/module-meteoJS_base_namedCollection.html @@ -146,7 +146,7 @@

Parameters

diff --git a/doc/module-meteoJS_base_unique.Unique.html b/doc/module-meteoJS_base_unique.Unique.html index 72c02dfd..87e468c5 100644 --- a/doc/module-meteoJS_base_unique.Unique.html +++ b/doc/module-meteoJS_base_unique.Unique.html @@ -156,7 +156,7 @@

Parameter

diff --git a/doc/module-meteoJS_base_unique.html b/doc/module-meteoJS_base_unique.html index 6a5a10da..4b637e48 100644 --- a/doc/module-meteoJS_base_unique.html +++ b/doc/module-meteoJS_base_unique.html @@ -118,7 +118,7 @@

Parameter

diff --git a/doc/module-meteoJS_base_uniquenamed.UniqueNamed.html b/doc/module-meteoJS_base_uniquenamed.UniqueNamed.html index 526880af..78352a10 100644 --- a/doc/module-meteoJS_base_uniquenamed.UniqueNamed.html +++ b/doc/module-meteoJS_base_uniquenamed.UniqueNamed.html @@ -137,7 +137,7 @@

setId diff --git a/doc/module-meteoJS_base_uniquenamed.html b/doc/module-meteoJS_base_uniquenamed.html index 0993faec..4c8e1f03 100644 --- a/doc/module-meteoJS_base_uniquenamed.html +++ b/doc/module-meteoJS_base_uniquenamed.html @@ -118,7 +118,7 @@

Parameter

diff --git a/doc/module-meteoJS_calc.html b/doc/module-meteoJS_calc.html index d35c154e..b3c04e1b 100644 --- a/doc/module-meteoJS_calc.html +++ b/doc/module-meteoJS_calc.html @@ -1319,7 +1319,7 @@

Parameter

diff --git a/doc/module-meteoJS_events.html b/doc/module-meteoJS_events.html index c368c36a..cf6d9c66 100644 --- a/doc/module-meteoJS_events.html +++ b/doc/module-meteoJS_events.html @@ -363,7 +363,7 @@

Parameters

diff --git a/doc/module-meteoJS_modelviewer.Modelviewer.html b/doc/module-meteoJS_modelviewer.Modelviewer.html new file mode 100644 index 00000000..4f9c2b85 --- /dev/null +++ b/doc/module-meteoJS_modelviewer.Modelviewer.html @@ -0,0 +1,225 @@ + + + + + + + Class: Modelviewer + + + + + + + + +
+
+
+
+