WAB Dev Edition 2.7: How can I add a dropdown menu to header widget controller?

1785
7
Jump to solution
04-20-2018 08:14 AM
FrancescoTonini2
Occasional Contributor II

I am using WAB2.7 Dev Edition as a template, and am trying to add a dropdown menu item to the header widget controller element, where all the links are listed. For example (see image below), I would like users to click on the "sample data" link and have a list of N items in a drop-down menu fashion.

Sample Data

|

|

Sample Data1  (link)

Sample Data2  (link)

...

For CSS, I can probably re=use some of the jimu.css style (which one?) but for the functionality, I am looking inside the \themes\FoldableTheme\widgets\HeaderController\Widget.js file:

array.forEach(links, function(link) {

   if (link.label.toUpperCase() === 'SAMPLE DATA'){
      html.create('a', {
         href: link.url,
         rel: 'noopener noreferrer',
         innerHTML: utils.sanitizeHTML(link.label),
         'class': "jimu-link jimu-align-leading jimu-leading-margin1",
         style: {
            lineHeight: this.height + 'px'
         }
      }, this.dynamicLinksNode);

   }

}, this);

I am aware the customization has to happen here, but I am not sure how to go about it...I would normally add a <div> if I was writing it from scratch, but within the Widget.js, I want to make sure I can do this using the appropriate tags and functions.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Francesco,

   This should get you started:

      //New function
      getMenuPosition: function(myLink){
        var position = {
          relativeTo: 'map'
        };
        var pbox = html.getMarginBox(myLink);
        var sbox = {
          h: 300,
          w: 220
        };
        var containerBox = html.getMarginBox(this.map.id);
        var top = pbox.t + pbox.h + 16;//put under icon by default
        if(top + sbox.h > containerBox.h){
          position.bottom = containerBox.h - pbox.t + 1;
        }else{
          position.top = top;
        }
        if(pbox.l + sbox.w > containerBox.w){
          position.right = 0;
        }else{
          position.left = pbox.l + 12;
        }
        return position;
      },

      // modified function
      _createDynamicLinks: function(links) {
        if (window.isRTL) {
          var _links = [];
          array.forEach(links, function(link) {
            _links.unshift(link);
          });
          links = _links;
        }
        html.empty(this.dynamicLinksNode);
        array.forEach(links, function(link) {
          if (link.label.toUpperCase() === 'BLAH BLAH'){
            var myLink = html.create('span', {
              innerHTML: utils.sanitizeHTML(link.label),
              'class': "jimu-link jimu-align-leading jimu-leading-margin1",
              style: {
                lineHeight: this.height + 'px',
                cursor: 'pointer'
              }
            }, this.dynamicLinksNode);
            setTimeout(lang.hitch(this, function(){
              var style = utils.getPositionStyle(this.getMenuPosition(myLink));
              style.height = 'auto';
              style.width = 'auto';
              style.display = 'none';
              style['padding-right'] = '12px';
              style.position = 'absolute';
              style['padding-right'] = '12px';
              style['border-radius'] = '2px';
              style['z-index'] = '111';
              var menu = html.create('div', {
                'class': "myMenu jimu-main-background",
                style: style
              }, this.dynamicLinksNode);
              html.create('a', {
                href: link.url,
                target: '_blank',
                rel: 'noopener noreferrer',
                innerHTML: utils.sanitizeHTML('Sample Data 1'),
                'class': "jimu-link jimu-align-leading jimu-leading-margin1",
                style: {
                  lineHeight: this.height + 'px',
                  float: 'left',
                  clear: 'both'
                }
              }, menu);
              html.create('a', {
                href: link.url,
                target: '_blank',
                rel: 'noopener noreferrer',
                innerHTML: utils.sanitizeHTML('Sample Data 2'),
                'class': "jimu-link jimu-align-leading jimu-leading-margin1",
                style: {
                  lineHeight: this.height + 'px',
                  float: 'left',
                  clear: 'both'
                }
              }, menu);

              on(myLink, 'click', lang.hitch(this, function(){
                if(html.getStyle(menu, 'display') === 'block'){
                  html.setStyle(menu, 'display', 'none');
                }else{
                  html.setStyle(menu, 'display', 'block');
                }
              }));
            }), 200);

            return;
          }

          html.create('a', {
            href: link.url,
            target: '_blank',
            rel: 'noopener noreferrer',
            innerHTML: utils.sanitizeHTML(link.label),
            'class': "jimu-link jimu-align-leading jimu-leading-margin1",
            style: {
              lineHeight: this.height + 'px'
            }
          }, this.dynamicLinksNode);
        }, this);
      },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

7 Replies
RobertScheitlin__GISP
MVP Emeritus

Francesco,

   This should get you started:

      //New function
      getMenuPosition: function(myLink){
        var position = {
          relativeTo: 'map'
        };
        var pbox = html.getMarginBox(myLink);
        var sbox = {
          h: 300,
          w: 220
        };
        var containerBox = html.getMarginBox(this.map.id);
        var top = pbox.t + pbox.h + 16;//put under icon by default
        if(top + sbox.h > containerBox.h){
          position.bottom = containerBox.h - pbox.t + 1;
        }else{
          position.top = top;
        }
        if(pbox.l + sbox.w > containerBox.w){
          position.right = 0;
        }else{
          position.left = pbox.l + 12;
        }
        return position;
      },

      // modified function
      _createDynamicLinks: function(links) {
        if (window.isRTL) {
          var _links = [];
          array.forEach(links, function(link) {
            _links.unshift(link);
          });
          links = _links;
        }
        html.empty(this.dynamicLinksNode);
        array.forEach(links, function(link) {
          if (link.label.toUpperCase() === 'BLAH BLAH'){
            var myLink = html.create('span', {
              innerHTML: utils.sanitizeHTML(link.label),
              'class': "jimu-link jimu-align-leading jimu-leading-margin1",
              style: {
                lineHeight: this.height + 'px',
                cursor: 'pointer'
              }
            }, this.dynamicLinksNode);
            setTimeout(lang.hitch(this, function(){
              var style = utils.getPositionStyle(this.getMenuPosition(myLink));
              style.height = 'auto';
              style.width = 'auto';
              style.display = 'none';
              style['padding-right'] = '12px';
              style.position = 'absolute';
              style['padding-right'] = '12px';
              style['border-radius'] = '2px';
              style['z-index'] = '111';
              var menu = html.create('div', {
                'class': "myMenu jimu-main-background",
                style: style
              }, this.dynamicLinksNode);
              html.create('a', {
                href: link.url,
                target: '_blank',
                rel: 'noopener noreferrer',
                innerHTML: utils.sanitizeHTML('Sample Data 1'),
                'class': "jimu-link jimu-align-leading jimu-leading-margin1",
                style: {
                  lineHeight: this.height + 'px',
                  float: 'left',
                  clear: 'both'
                }
              }, menu);
              html.create('a', {
                href: link.url,
                target: '_blank',
                rel: 'noopener noreferrer',
                innerHTML: utils.sanitizeHTML('Sample Data 2'),
                'class': "jimu-link jimu-align-leading jimu-leading-margin1",
                style: {
                  lineHeight: this.height + 'px',
                  float: 'left',
                  clear: 'both'
                }
              }, menu);

              on(myLink, 'click', lang.hitch(this, function(){
                if(html.getStyle(menu, 'display') === 'block'){
                  html.setStyle(menu, 'display', 'none');
                }else{
                  html.setStyle(menu, 'display', 'block');
                }
              }));
            }), 200);

            return;
          }

          html.create('a', {
            href: link.url,
            target: '_blank',
            rel: 'noopener noreferrer',
            innerHTML: utils.sanitizeHTML(link.label),
            'class': "jimu-link jimu-align-leading jimu-leading-margin1",
            style: {
              lineHeight: this.height + 'px'
            }
          }, this.dynamicLinksNode);
        }, this);
      },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

FrancescoTonini2
Occasional Contributor II

Thanks a lot Rob! Would your chunk of code above replace any existing one in the Widget.js or it should be added to it?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Francesco,

  If you look at the comments in my code I tell you that.

0 Kudos
FrancescoTonini2
Occasional Contributor II

I see, so the CSS class 'myMenu' you added along with jimu in case I wanted to add a specific custom style to that element?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Correct

0 Kudos
FrancescoTonini2
Occasional Contributor II

I have noticed you also used a single link.url as href parameter in both Sample Data 1 and Sample Data 2 <a> link tags...These links will have different URLs to point to, so what do you think is the best way to accommodate that in the config.json file? Would something like this work?

"links": [
 {
 "label": "BLAH BLAH",
 "url": [url1, url2]
 }]

then called in the Widget.js as

...

href: link.url[0]

...

...

href: link.url[1]

...

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

That should work.