cmv / cmv-app

CMV - The Configurable Map Viewer - A community supported open source mapping framework built with the Esri JavaScript API and the Dojo Toolkit
https://demo.cmv.io/
MIT License
325 stars 278 forks source link

Floating Pane - Created Floating Pane instead of sidebar #678

Open mayur9785 opened 7 years ago

mayur9785 commented 7 years ago

Hi, I am working on create dynamic toolbar toggle button widgets that configured in viewer.js file. The button is linked with Floating pane widgets open/close, expand/collapse & movable. Instead of sidebar I try to load Draw widgets in floating panel and it's loading and working fine. The same way I am trying to load LayerControl widgets in Floating pane but unable to load.

I am able to load Draw widgets, and I want to have LayerControl in my Floating Pane and later I have plan to use other widgets.

Any idea how to load LayerControl in floating panel. There is something I am missing, I tried to find but not getting exact point where to do and what parameter to pass?

Here is my steps to get it done for Draw widgets and same way I am trying for LayerControl.

  1. In Viewe.js - in return statement
         "theme": "black",
        "toolbarEnabled": true,
        "extentWidgetEnabled": false,
        "searchWidgetEnabled": true,
        "graphicsWidgetEnabled": true,
        "layerControlWidgetEnabled": true,
  2. Then I have the widgets list in viewer.js
        toolbarwidgets: {
           //This toolbar is for Toolbar button - Create Menu widgets configured in viewer and display Icon 
            toolbar:
            {
                showCount: 2,
             },
         // this is search widget
            search:
            {
            },
         // this is Draw widgets - This one is working and able to load in Floating Pane widgets
            graphics:
            {

            },
            layerControl:
            {
                map: map,
                separated: true,
                vectorReorder: true,
                overlayReorder: true,
                layerInfos:layerInfos,
                layerInfos: [{
                    layer: new ArcGISDynamicMapServiceLayer("http://myserverurl/arcgis/rest/services/UAT/ROADS/MapServer", {
                        "opacity": 1,
                        visible: false,
                        id: 'mymap'
                    }),
                    type: 'dynamic',
                    title: 'Roads',
                    controlOptions: {
                        swipe: true,
                        metadataUrl: true,
                        expanded: true
                        // see Control Options
                    }
                }],
            }
  1. Then in Controller.js file - I am calling this this.loadtoolbarWidgets() in initWidgets functions

    this.loadtoolbarWidgets();
  2. This function is below how I call the widgets, create menu, floating pane etc..

    loadtoolbarWidgets: function (widgetConfig, position) {
            debugger;
            var toolbarWidgetList = []; // array to store widgets list
            var tabWidgetIndex = 1;
            var toolbarEnabled = this.config.toolbarEnabled;
            //  Check here if widgets enabled true/false and  how I call the widgets
            //this is the Draw widgets and its working and loading in floating pane
            if (this.config.graphicsWidgetEnabled == true) {
                var container = domConstruct.create('div', { id: "graphicsWidgetDiv", class: "toolbarButton" });
                domConstruct.place(container, this.map.container);
                this.graphicsWidget = new GraphicsWidget({
                    map: this.map,
                    theme: this.config.theme,
                    config: this.config.toolbarwidgets.graphics
                }, container);
                this.graphicsWidget.startup();
                toolbarWidgetList.push(this.graphicsWidget);
            }
            // LayerControl widget - This is what I am calling and trying to load in Floating Pane Widgets
            if (this.config.layerControlWidgetEnabled == true)
            {
                var container = domConstruct.create('div', { id: "layerControlWidgetDiv", class: "toolbarButton" });
                domConstruct.place(container, this.map.container);
                this.layerControlWidget = new LayerControl({
                    map: this.map,
                    theme: this.config.theme,
                    config: this.config.toolbarwidgets.layerControl
                    // see LayerInfos
                }, container);
                this.layerControlWidget.startup();
                toolbarWidgetList.push(this.layerControlWidget);
            }
           // this is for create toolbar - Menubar with icons.
            if (toolbarEnabled == true) {
                this.toolbar = new ToolbarWidget({
                    map: this.map,
                    widgets: toolbarWidgetList,
                    showCount: this.config.toolbarwidgets.toolbar.showCount
                }, "toolbarWidgetDiv");
                this.toolbar.startup();
            }
        }
  3. Here is the LayerControl.js file - I have added 2 more functions to linked the widgets with toggle menu button and create Floating pane widgets - below is the changes in LayerControl.js file

define([
    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/_base/lang',
    'dojo/topic',
    'dojo/dom-attr',
    'dojo/dom-construct',
    "dojo/dom-class",
    "gis/dijit/floatWidgetBase",
    'dijit/_WidgetBase',
    "dijit/_TemplatedMixin",
    "dijit/_WidgetsInTemplateMixin",
    'dijit/_Container',
    'dijit/layout/ContentPane',
    'dijit/form/Button',
    "dojo/text!./LayerControl/templates/button.html",
    'esri/tasks/ProjectParameters',
    'esri/config',
    'require',
    'xstyle/css!./LayerControl/css/LayerControl.css'
], function (
    declare,
    array,
    lang,
    topic,
    domAttr,
    domConst,
    domClass,
    floatWidgetBase,
    _WidgetBase,
    _TemplatedMixin, 
    _WidgetsInTemplateMixin,
    Container,
    ContentPane,
    Button,
    buttonTemplate,
    ProjectParameters,
    esriConfig,
    require

) {

    (function () {
        var css = [require.toUrl("gis/dijit/Graphics/css/graphics.css")];
        var head = document.getElementsByTagName("head").item(0),
            link;
        for (var i = 0, il = css.length; i < il; i++) {
            link = document.createElement("link");
            link.type = "text/css";
            link.rel = "stylesheet";
            link.href = css[i].toString();
            head.appendChild(link);
        }
    }());
   // Create button in Toolbar
    var layerControlButton = declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin],
    {
        widgetsInTemplate: true,
        templateString: buttonTemplate,
        baseClass: 'widget_LayerControl',
        buttonClass: 'toolbarButton',
        postCreate: function () {
            debugger;
            //initialize the widget
            this.inherited(arguments);
            domClass.add(this.toolbarButton.domNode);//, "toolbarButtonIcon "+this.theme);
            var props = {
                map: this.map, theme: this.theme,config:this.config, //layerInfos: this.config.layerInfos,
                //separated: this.config.separated, vectorReorder: this.config.vectorReorder,
                //overlayReorder: this.config.overlayReorder
            };
            this.widget = new floatWidget(props);
            this.widget.startup();
        },
        toggleWidget: function () {
            //debugger;
            if (this.widget.visible)
                this.widget.close();
            else
                this.widget.show();
        }
    });
   // this is for create floating pane widgets
    var floatWidget = declare([floatWidgetBase],
        {
            widgetsInTemplate: false,
            baseClass: 'widget_LayerControl',
            title: 'Layers',
            postCreate: function () {
                debugger;
                this.inherited(arguments);
                //debugger;
                console.log("LayerControl");
                this.floatIconStyle += " " + this.theme;
                this.resizable = true,
                this.top = 100;
                this.left = 100;
                this.contentHeight = 150;
                this.contentWidth = 500;
                this.initFloat();
                this.initUI();
            },
            initUI: function () {
                var props = {
                    parentContainer: this.floatingPane.containerNode, map: this.map,
                    layerInfos: this.config.layerInfos, separated: this.config.separated,
                    vectorReorder: this.config.vectorReorder,
                    overlayReorder: this.config.overlayReorder
                };
                debugger;
                this.ui = new LayerControl(props);
                this.ui.startup();
            }
        });
    // Here is Our LayerControl actual code goes 
   var LayerControl = declare([_WidgetBase, Container], {
..... 
....
});
    return LayerControl, layerControlButton;
});
  1. This is floatWidgetBase.js file - create Floating pane Dynamically
    
    define(["dojo/_base/declare",
    "dijit/_WidgetBase",
    "dojo/dom-construct",
    "dojo/query",
    "dojo/on",
    'dojo/dom',
    "dojo/_base/lang",
    "dojo/dom-style",
    "dojo/dom-class",
    "dojox/layout/FloatingPane",
    "dijit/layout/ContentPane",
     "dojo/dnd/move",

], function (declare, _WidgetBase, domConstruct, query, on, dom, lang, domStyle, domClass, FloatingPane, ContentPane, dndMove) {

var ConstrainedFloatingPane = dojo.declare(dojox.layout.FloatingPane, {
    postCreate: function () {
        this.inherited(arguments);
        this.moveable = new dojo.dnd.move.constrainedMoveable(
            this.domNode, {
                handle: this.focusNode,
                constraints: function () {
                    var coordsBody = dojo.coords(dojo.body());
                    // or
                    var coordsWindow = {
                        l: 0,
                        t: 0,
                        w: window.innerWidth,
                        h: window.innerHeight
                    };
                    return coordsWindow;
                },
                within: true
            }
        );
    }
});

return declare([_WidgetBase], {
    //id:"floatWidget",
    parentId:null,
    baseContainer:null,
    title:"Floating Widget",
    floatIconStyle:"floatingPaneIcon",
    minimizeBtn:null,
    maximizeBtn:null,
    closeBtn:null,
    floatingPane:null,
    visible:false,
    minimized:false,
    top:100,
    left:10,
    contentWidth:330,
    contentHeight:400,
    maxWidth:999999,
    postCreate: function () {
        //debugger;

        this.parentId = dijit.getEnclosingWidget(this.domNode).id;
        this.baseContainer = domConstruct.create('div', {
            class : "float",
            id : this.id+"fPanefloatWidget",
            style : ""
        });
        domConstruct.place(this.baseContainer, this.map.container, 'first');    
    },
    initFloat:function()
    {
        debugger;
        this.floatingPane = new ConstrainedFloatingPane({
        title: "<span class='paneTitleText'>"+this.title+"</span>",
        resizable: this.resizable,//true,
        dockable: false,
        closable: false,
        style: "position:absolute;z-index:1000;top:"+this.top+"px;left:"+this.left+"px;width:"+this.contentWidth+"px;height:"+this.contentHeight+"px;overflow: hidden;visibility:hidden;",
        id: this.id+"_fPane",
        'class': "floatingPane "+this.baseClass}, this.baseContainer);
        this.floatingPane.hide();
        this.floatingPane.startup();

        var lTitlePane = query("#"+this.id+"_fPane"+' .dojoxFloatingPaneTitle')[0];

        this.closeBtn= domConstruct.create("div", {
            class:"closeBtn",
            style : "width:20px;height:20px;overflow: hidden;"
        });
        on(this.closeBtn,"click",lang.hitch(this,"close"));

        this.minimizeBtn = domConstruct.create("div", {
            class:"minimizeBtn",
            style : "width:20px;height:20px;overflow: hidden;"
         });
        on(this.minimizeBtn,"click",lang.hitch(this,"minimize"));

        this.maximizeBtn= domConstruct.create("div", {
            class:"maximizeBtn",
            style : "width:20px;height:20px;overflow: hidden;visibility:hidden;"           
        });
        on(this.maximizeBtn,"click",lang.hitch(this,"maximize"));

        domConstruct.place(this.closeBtn, lTitlePane, "after");
        domConstruct.place(this.minimizeBtn, lTitlePane, "after");
        domConstruct.place(this.maximizeBtn, lTitlePane, "after");
        var lIconPane = query("#"+this.id+"_fPane")[0];
        //var logoDiv = domConstruct.create('div',{class:this.floatIconStyle},lIconPane);
        var logoDiv = domConstruct.create('div',{class:this.floatIconStyle},lIconPane);

        var self = this;

    },
    show:function()
    {       
        this.floatingPane.bringToTop();
        this.maximize();
        this.floatingPane.show();
        this.visible = true;
    },
    close:function()
    {
        this.floatingPane.hide();
        this.visible = false;
        if (!this.minimized)
        {
            this.contentWidth = this.floatingPane.domNode.style.width;
            this.contentHeight = this.floatingPane.domNode.style.height;
        }
    },
    minimize:function()
    {
        //store current sizing
        this.contentWidth = this.floatingPane.domNode.style.width;
        this.contentHeight = this.floatingPane.domNode.style.height;
        this.minimized = true;
        //minmize control
        domStyle.set(this.floatingPane.domNode, "height", "25px");
        domStyle.set(this.floatingPane.domNode, "width", "180px");
        //remove resize control
        domStyle.set(this.floatingPane.canvas.children[1],"visibility","hidden");
        //swap buttons
        domStyle.set(this.minimizeBtn,'visibility', 'hidden');
        domStyle.set(this.maximizeBtn,'visibility', 'visible');
    },
    maximize:function()
    {
        //restore control
        domStyle.set(this.floatingPane.domNode, "height", this.contentHeight);
        domStyle.set(this.floatingPane.domNode, "width", this.contentWidth);
        this.minimized = false;
        //domStyle.set(this.floatingPane.canvas.children[0],'height', this.contentHeight);
        //add resize control
        domStyle.set(this.floatingPane.canvas.children[1],"visibility","visible");
        //swap buttons
        domStyle.set(this.minimizeBtn,'visibility', 'visible');
        domStyle.set(this.maximizeBtn,'visibility', 'hidden');
    }
});

});

7. finally toolbarwidgets.js file for Create Dynamic toolbar menu Button
```javascript
define(["dojo/_base/declare",
        "dojo/_base/html",
        "dojo/on",
        "dijit/_WidgetBase",
        "dijit/_TemplatedMixin",
        "dijit/_WidgetsInTemplateMixin",
        "dojo/text!./Toolbar/templates/buttons.html",
        "dijit/form/Button",
        "dojo/dom-construct",
        "dojo/dom-class",
        "dojo/dom-style",
        'xstyle/css!./Toolbar/css/toolbar.css']
,function(declare, html, on, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, extentTemplate, Button,domConstruct,domClass,domStyle)
{
     //function to load CSS files required for this module
    (function () {
        var css = [require.toUrl("gis/dijit/Toolbar/css/toolbar.css")];
        var head = document.getElementsByTagName("head").item(0),
            link;
        for (var i = 0, il = css.length; i < il; i++) {
            link = document.createElement("link");
            link.type = "text/css";
            link.rel = "stylesheet";
            link.href = css[i].toString();
            head.appendChild(link);
        }
    }());

    return declare("toolbarWidget", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin],
    {
        widgetsInTemplate: true,
        templateString: extentTemplate,
        baseClass: 'widgets_Toolbar',
        buttonClass: 'extentButton',
        leftButtonClass: 'slideLeftButton',
        rightButtonClass: 'slideRightButton',
        //mobileHelper: new MobileHelper(),
        postCreate: function () {
            debugger;
            //initialize the widget
            this.inherited(arguments);
            //this.mobileHelper.collectInfo();
            var availableWidth = this.getLayoutWidth();
            var widgetDisplayWidth = 33 * this.widgets.length;

            if ((this.widgets) && (this.widgets.length > 0)) {
                for (var i in this.widgets)
                { 
                    var w = this.widgets[i];
                    var li = domConstruct.create("li");
                    domConstruct.place(w.domNode,li,'first');
                    this.toolList.appendChild(li);
                }
            }

            this.setLayout();
            var self = this;
            //on(this.mobileHelper, "orientationChange", function (e) {
            //    self.setLayout();
            //});
        },
        setLayout: function () {
            if ((this.widgets) && (this.widgets.length > 0) && (this.widgets.length > this.showCount)) {
                var availableWidth = this.getLayoutWidth();
                var widgetDisplayWidth = 33 * this.widgets.length;

                if (availableWidth < widgetDisplayWidth) {
                    domStyle.set(this.mask, "width", (33 * this.showCount) + "px");
                    domStyle.set(this.toolList, "width", (widgetDisplayWidth) + "px");
                    this.createKeyFramesRulesLeftRight((-34.5 * (this.widgets.length - this.showCount)));
                    domClass.replace(this.btnScrollRight, "scrollButton", "scrollButton hidden");
                    domClass.replace(this.btnScrollLeft, "scrollButton", "scrollButton hidden");
                } else {
                    domStyle.set(this.mask, "width", (widgetDisplayWidth) + "px");
                    this.moveLeft();
                    domClass.replace(this.btnScrollRight, "scrollButton hidden", "scrollButton");
                    domClass.replace(this.btnScrollLeft, "scrollButton hidden", "scrollButton");
                }
            }
        },
        getLayoutWidth: function () {
            //debugger;
            var layoutBox = html.getMarginBox(this.map.id);
            return layoutBox.w - 280;
        },
        moveLeft: function () {
            var node = this.toolList;
            domStyle.set(node, "MozAnimation", "cssAnimationLeft 1s  1 linear forwards");
            domStyle.set(node, "WebkitAnimation", "cssAnimationLeft 1s  1 linear forwards");
            domStyle.set(node, "OAnimation", "cssAnimationLeft 1s  1 linear forwards");
            domStyle.set(node, "animation", "cssAnimationLeft 1s  1 linear forwards");
            domStyle.set(node, "MozAnimationPlayState", "running");
            domStyle.set(node, "WebkitAnimationPlayState", "running");
            domStyle.set(node, "OAnimationPlayState", "running");
            domStyle.set(node, "AnimationPlayState", "running");

        },
        stopMove: function () {
            var node = this.toolList;
            domStyle.set(node, "MozAnimationPlayState", "paused");
            domStyle.set(node, "WebkitAnimationPlayState", "paused");
            domStyle.set(node, "OAnimationPlayState", "paused");
            domStyle.set(node, "AnimationPlayState", "paused");
        },
        moveRight: function () {
            var node = this.toolList;
            domStyle.set(node, "MozAnimation", "cssAnimationRight 1s  1 linear forwards");
            domStyle.set(node, "WebkitAnimation", "cssAnimationRight 1s  1 linear forwards");
            domStyle.set(node, "OAnimation", "cssAnimationRight 1s  1 linear forwards");
            domStyle.set(node, "animation", "cssAnimationRight 1s  1 linear forwards");
            domStyle.set(node, "MozAnimationPlayState", "running");
            domStyle.set(node, "WebkitAnimationPlayState", "running");
            domStyle.set(node, "OAnimationPlayState", "running");
            domStyle.set(node, "AnimationPlayState", "running");
        },
        createKeyFramesRulesLeftRight: function (val) {
            console.log(val);
            // gather all stylesheets into an array
            var head = document.getElementsByTagName("head").item(0);

            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-moz-keyframes cssAnimationLeft{' +
            '0%   { left: ' + val + 'px}' +
            '100% { left: 0px; }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-webkit-keyframes cssAnimationLeft{' +
            '0%   { left: ' + val + 'px}' +
            '100% { left: 0px; }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@keyframes cssAnimationLeft{' +
            '0%   { left: ' + val + 'px}' +
            '100% { left: 0px; }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);

            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-moz-keyframes cssAnimationRight{' +
            '0%   { left: 0px}' +
            '100% { left: ' + val + 'px }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode(' @-webkit-keyframes cssAnimationRight{' +
            '0%   { left: 0px}' +
            '100% { left: ' + val + 'px }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode(' @keyframes cssAnimationRight{' +
            '0%   { left: 0px}' +
            '100% { left: ' + val + 'px }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
        },
        createKeyFramesRulesUpDown: function (val) {
            console.log(val);
            // gather all stylesheets into an array
            var head = document.getElementsByTagName("head").item(0);

            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-moz-keyframes cssAnimationUp{' +
            '0%   { top: ' + val + 'px}' +
            '100% { top: 0px; }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-webkit-keyframes cssAnimationUp{' +
            '0%   { top: ' + val + 'px}' +
            '100% { top: 0px; }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);

            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode('@-moz-keyframes cssAnimationDown{' +
            '0%   { top: 0px}' +
            '100% { top: ' + val + 'px }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
            var cssAnimation = document.createElement('style');
            cssAnimation.type = 'text/css';
            var rules = document.createTextNode(' @-webkit-keyframes cssAnimationDown{' +
            '0%   { top: 0px}' +
            '100% { top: ' + val + 'px }' +
            '}');
            cssAnimation.appendChild(rules);
            head.appendChild(cssAnimation);
        }
    });
});

floating_pane_widgets

tmcgee commented 7 years ago

@mayur9785 Looks like a lot of interesting work.

It would be much easier to visualize this (and possibly contribute) if you provided a working example with demo in a github repo.

Also: check out my cmv-calcite-maps repo. All of the cmv core widgets are there in floating windows. They are not draggable windows since the calcite maps template doesn't currently support that. There were no modifications to titlePane widgets required to include them in the floating window. There were no modifications to core CMV required. Only a few methods were overridden in the _CalciteMixin I recommend you follow a similar methodology in your approach to keep modifications to the core CMV to a minimum (or none, if possible). This allows for easier upgrades in the future.

I look forward to see your toolbar/window approach in action!

mayur9785 commented 7 years ago

@tmcgee I have created repo CMVFloatingPane here to download the file. As of now it is working for Draw widget only and my priority is for LayerControl now, but its not loading into the Floating pane. Later I have plan to use other CMV widgets and WAB widgets in my app with the same Floating pane created dynamically and load the actual widgets in it.

tmcgee commented 7 years ago

Hi @mayur9785 please add all the individual files in the repo instead of a single rar file. That would greatly help myself and others that may want to contribute. :) Thanks.

mayur9785 commented 7 years ago

Hi @tmcgee I have added the all files in repo CMV Floating Pane. Please have a look into that and help how other cmv widgets and WAB widgets we can load in Floating pane.

:) Thank you very much your support.