From 5f0b328ed6c203d4acf70086cd79ecdbff800ab9 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Wed, 19 Feb 2020 15:37:25 +0100
Subject: [PATCH] WIP: collapse preview

---
 src/core/js/new_module.js | 108 +++++++++++++++++++++++++++++++-------
 src/core/js/preview.js    |   6 ++-
 2 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/src/core/js/new_module.js b/src/core/js/new_module.js
index 0b5d231d..12a95603 100644
--- a/src/core/js/new_module.js
+++ b/src/core/js/new_module.js
@@ -23,6 +23,7 @@
 
 'use strict';
 
+
 /**
  * TODO Please adhere to JSDoc standards: https://jsdoc.app/
  *
@@ -56,10 +57,13 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
 
     ];
 
+    const previewReadyEvent = new Event("new_module.preview.ready");
+
     /**
      * TODO Please adhere to JSDoc standards: https://jsdoc.app/
      */
     const _css_class_preview_container = "caosdb-f-new_module-container";
+    const _css_class_preview_container_resolvable = "caosdb-f-new_module-container-resolvable";
 
     /**
      * TODO Please adhere to JSDoc standards: https://jsdoc.app/
@@ -74,7 +78,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      *     doesn't have any.
      */
     var get_preview_container = function (entity) {
-        return entity.getElementsByClassName(_css_class_preview_container)[0];
+        return $(entity).children(`.${_css_class_preview_container}`)[0];
     }
 
     /**
@@ -125,6 +129,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
             set_preview_container(entity, wait);
             const result = await preview;
             set_preview_container(entity, result);
+            entity.dispatchEvent(previewReadyEvent);
         } catch (err) {
             logger.error(err);
             const err_msg = "An error occured while loading this preview";
@@ -169,7 +174,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      * _css_class_preview_container}. It is intended to contain the preview
      * after it has been created.
      *
-     * The presecce of a preview container is also the marker that an entity
+     * The presence of a preview container is also the marker that an entity
      * has been visited by the root_preview_handler yet and that a preview is
      * loaded and added to the entity or on its way.
      *
@@ -178,12 +183,36 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      * purposes.
      *
      * @param {HTMLElement} entity - An entity in HTML representation.
+     * @return {HTMLElement} the newly created container.
      */
     var add_preview_container = function (entity) {
-        const style = { height: "200px" };
-        const container = $(`<div class="${_css_class_preview_container}"/>`)
+        const button_show = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-down"/> Show Preview</button>')
+            .css({width: "100%"});
+        const button_hide = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-up"/> Show Preview</button>')
+            .css({width: "100%"})
+            .hide();
+        const style = { padding: "0px 10px" };
+        const container = $(`<div class="collapse ${_css_class_preview_container}"/>`)
+            .addClass(_css_class_preview_container)
+            .addClass(_css_class_preview_container_resolvable)
             .css(style);
+        const show = function() {
+            button_show.hide();
+            button_hide.show();
+            container.collapse("show");
+        }
+        const hide = function() {
+            button_hide.hide();
+            button_show.show();
+            container.collapse("hide");
+        }
+        button_show.click(show);
+        button_hide.click(hide);
         $(entity).append(container);
+        $(entity).append(button_show);
+        $(entity).append(button_hide);
+
+        return container[0];
     }
 
     /**
@@ -198,14 +227,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      */
     var root_preview_handler = async function (entity) {
 
-        // TODO handle reference previews
-        if (get_preview_container(entity)) {
-            // preview is there
-            return;
-        }
 
-        // TODO handle reference previews
-        add_preview_container(entity);
         const preview = root_preview_creator(entity);
         if (preview) {
             set_preview(entity, preview);
@@ -217,10 +239,13 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      * changed with a delay.
      */
     var root_preview_handler_trigger = function () {
-        var entities = $(".caosdb-entity-panel");
+        var entities = $(".caosdb-entity-panel,.caosdb-entity-preview");
         for (let entity of entities) {
+            var container = $(get_preview_container(entity) || add_preview_container(entity));
             // TODO viewport + 1000 px
-            if (is_in_view_port(entity)) {
+
+            if (container.hasClass(_css_class_preview_container_resolvable) && is_in_view_port(container[0])) {
+                container.removeClass(_css_class_preview_container_resolvable);
                 root_preview_handler(entity);
             }
         }
@@ -236,14 +261,25 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
      * @param {function} trigger - the callback which is called.
      */
     var init_watcher = function (delay, trigger) {
-        // TODO handle reference previews
-        var timeout = undefined;
+        var scroll_timeout = undefined;
         $(window).scroll(() => {
-            if(!timeout) {
-                clearTimeout(timeout);
+            if (!scroll_timeout) {
+                clearTimeout(scroll_timeout);
             }
-            timeout = setTimeout(trigger, delay);
+            scroll_timeout = setTimeout(trigger, delay);
         });
+
+        var preview_timeout = undefined;
+        window.addEventListener(
+            preview.previewReadyEvent.type,
+            () => {
+                if (!preview_timeout) {
+                    clearTimeout(scroll_timeout);
+                }
+                scroll_timeout = setTimeout(trigger, 100);
+                return true;
+            },
+            true);
     };
 
     /**
@@ -300,6 +336,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
 
             // trigger the whole thing for the first time
             root_preview_handler_trigger();
+
         } catch (err) {
             logger.error(err);
         }
@@ -307,6 +344,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
     }
 
     return {
+        previewReadyEvent: previewReadyEvent,
         init: init,
         init_watcher: init_watcher,
         configure: configure,
@@ -314,9 +352,43 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
 }($, log.getLogger("new_module"), resolve_references.is_in_viewport_vertically, load_config, Plotly);
 
 
+/**
+ * Helper for plotly
+ */
+var plotly_preview = function (logger, new_module, preview, plotly) {
+
+    var create_plot = function (data) {
+        var div = $('<div/>')[0];
+        plotly.newPlot(div, data, { margin: { t: 0}, height: 200}, {responsive: true});
+        return div;
+    }
+
+    var resize_plots_event_handler = function (e) {
+        var plots = $(e.target).find(".js-plotly-plot");
+        for (let plot of plots) {
+            plotly.Plots.resize(plot);
+        }
+    }
+
+    var init = function () {
+        window.addEventListener(preview.showPreviewEvent.type,
+            resize_plots_event_handler, true);
+        window.addEventListener(new_module.previewReadyEvent.type,
+            resize_plots_event_handler, true);
+    }
+
+    return {
+        create_plot: create_plot,
+        init: init,
+    };
+
+}(log.getLogger("plotly_preview"), new_module, preview, Plotly);
+
+
 // this will be replaced by require.js in the future.
 $(document).ready(function () {
     if ("${BUILD_MODULE_NEW_MODULE}" === "ENABLED") {
+        caosdb_modules.register(plotly_preview);
         caosdb_modules.register(new_module);
     }
 });
diff --git a/src/core/js/preview.js b/src/core/js/preview.js
index 082b544c..4255b86d 100644
--- a/src/core/js/preview.js
+++ b/src/core/js/preview.js
@@ -3,7 +3,9 @@
  */
 var preview = new function() {
 
-    this.previewReadyEvent = new Event("caosdb.preview.ready")
+    this.previewReadyEvent = new Event("caosdb.preview.ready");
+    this.showPreviewEvent = new Event("caosdb.preview.show");
+    this.hidePreviewEvent = new Event("caosdb.preview.hide");
 
     this.carouselId = 0;
     this.classNameEntityPreview = "caosdb-entity-preview";
@@ -99,6 +101,7 @@ var preview = new function() {
                 $(hidePreviewButton).hide();
                 $(refLinksContainer).show();
                 $(preview.getPreviewCarousel(ref_property_elem)).hide();
+                ref_property_elem.dispatchEvent(preview.hidePreviewEvent);
             });
         };
         app.onLeaveShowLinks = function(e) {
@@ -135,6 +138,7 @@ var preview = new function() {
                 $(preview.getPreviewCarousel(ref_property_elem)).show();
                 $(hidePreviewButton).show();
                 $(refLinksContainer).hide();
+                ref_property_elem.dispatchEvent(preview.showPreviewEvent);
             });
         }
         app.onResetApp = function(e, error) {
-- 
GitLab