Select to view content in your preferred language

DevEdition Wab - Search Widget JS Highlight Symbol: Changes from 2.7 through 2.11

5371
24
Jump to solution
11-29-2017 02:00 PM
DavidColey
Honored Contributor

Hi all - this is in reference to the earlier post dealing with the same issue at 1.3 and 2.3:

Web AppBuilder 1.2 Search/Geocoder widget color/style question 

but thought I'd start a new thread because the changes in the Search widget's Widget.js code at 2.6 have rendered the earlier fix (that worked up through 2.5) when starting a new app in the 2.6 Developer edition

As in earlier 2.x versions, to change the default highlight symbol I add in the jsonUtils to the define function and alias:

define([
 'dojo/_base/declare',
 'dojo/_base/lang',
 'dojo/_base/array',
 'dojo/_base/html',
 'dojo/when',
 'dojo/on',
 'dojo/aspect',
 'dojo/query',
 'dojo/keys',
 'dojo/Deferred',
 'dojo/promise/all',
 'jimu/BaseWidget',
 'jimu/LayerInfos/LayerInfos',
 'jimu/utils',
 'esri/dijit/Search',
 'esri/tasks/locator',
 'esri/layers/FeatureLayer',
 'esri/InfoTemplate',
 'esri/lang',
 './utils',
 'esri/symbols/jsonUtils', //for highlight change
 'dojo/NodeList-dom'
 ],
 function(declare, lang, array, html, when, on, aspect, query, keys, Deferred, all,
 BaseWidget, LayerInfos, jimuUtils, Search, Locator,
 FeatureLayer, InfoTemplate, esriLang, utils, jsonUtils)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

On about line 330 in the code, I add the highlight symbol property to the convertedSource var inside the _convertConfig function:

var convertedSource = {
 featureLayer: flayer,
 outFields: ["*"],
 searchFields: fNames,
 displayField: source.displayField || "",
 exactMatch: !!source.exactMatch,
 name: jimuUtils.stripHTML(source.name || ""),
 placeholder: jimuUtils.stripHTML(source.placeholder || ""),
 maxSuggestions: source.maxSuggestions || 6,
 maxResults: source.maxResults || 6,
 zoomScale: source.zoomScale || 50000,
 infoTemplate: template,
 useMapExtent: !!source.searchInCurrentMapExtent,
 _featureLayerId: source.layerId,
 highlightSymbol: jsonUtils.fromJson(source.highlightSymbol) //to add highlight symbol from json
 };‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

the highlightSymbol is set for each of the layers in the config.json:

"highlightSymbol": {
 "color": [100,100,100,25],
    "outline": {
       "color": [102,0,204],
          "width": 5,"type": "esriSLS" , "style", "esriSLSSolid"
    },"type": "esriSFS" ,"style": "esriSFSSolid"}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

and returns my settings to me in the console.log, but still reverts to the default highlight color and thickness, regardless:

So what should be a thick purple outline comes back in the default setting.  I've gone through the code to try to find what would be preventing the earlier method from working but have not had success.  Here are the changes, the comments here are the esri developer's comments:

On about line 137, a new promise(?) and handler for the infoWindow is added, not present in earlier 2.x:

// attatch original feature layer's id.
 this.own(
 aspect.before(this.map.infoWindow, 'setFeatures', lang.hitch(this, '_attatchOriLayerId'))
 );
 // this.map.infoWindow has two different implementations (esri/dijit/Popup and esri/dijit/PopupMobile)
 // after screen size changed. map switch it automatically.
 // here make sure fun:setFeatures be binded
 this._mapInfoWindow_ = this.map.infoWindow;
 var _winResizeHandler = on(window, 'resize', lang.hitch(this, function() {
 if (this._mapInfoWindow_ !== this.map.infoWindow) {
 this.own(
 aspect.before(this.map.infoWindow, 'setFeatures', lang.hitch(this, '_attatchOriLayerId'))
 );
 _winResizeHandler.remove();
 }
 }));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

at about line 182, a 'show,hide' on event that I previously used to persist a graphic on-screen after the infoWindow closes has been commented out (a separate behavior):

// this.own(
 // on(this.map.infoWindow, 'show,hide', lang.hitch(this, function() {
 // if (this.searchDijit &&
 // this.map.infoWindow.getSelectedFeature() ===
 // this.searchDijit.highlightGraphic) {
 // this.searchDijit.clearGraphics();
 // query('li', this.searchResultsNode).removeClass('result-item-selected');
 // }
 // }))
 // );‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The next changes begin on about line 677 as part of the _onSelectedSeachResult function:

// clear before select.
 this.searchDijit.clearGraphics();‍‍‍‍‍‍‍‍

Then more commented code as part of the _onSelectResult function at line 683:

_onSelectResult: function(e) {
 var result = e.result;
 if (!(result && result.name)) {
 return;
 }
 var dataSourceIndex = e.sourceIndex;
 var sourceResults = this.searchResults[dataSourceIndex];
 var dataIndex = 0;
 // var that = this;
// var getGraphics = function(layer, fid) {
 // var graphics = layer.graphics;
 // var gs = array.filter(graphics, function(g) {
 // return g.attributes[layer.objectIdField] === fid;
 // });
 // return gs;
 // };
 // var showPopupByFeatures = function(features) {
 // var location = null;
 // that.map.infoWindow.setFeatures(features);
 // if (features[0].geometry.type === "point") {
 // location = features[0].geometry;
 // } else {
 // location = features[0].geometry.getExtent().getCenter();
 // }
 // that.map.infoWindow.show(location, {
 // closetFirst: true
 // });
 // };‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

and again beginning at line 733:

// var layer = this.map.getLayer(e.source._featureLayerId);
// if (layer && this.config.showInfoWindowOnSelect) {
 // var gs = getGraphics(layer, e.result.feature.__attributes[layer.objectIdField]);
 // if (gs.length > 0) {
 // showPopupByFeatures(gs);
 // } else {
 // var handle = on(layer, 'update-end', lang.hitch(this, function() {
 // if (this.domNode) {
 // var gs = getGraphics(layer, e.result.feature.__attributes[layer.objectIdField]);
 // if (gs.length > 0) {
 // showPopupByFeatures(gs);
 // }
 // }
// if (handle && handle.remove) {
 // handle.remove();
 // }
 // }));
 // this.own(handle);
 // }
 // }
 // publish select result to other widgets‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Finally, I believe this new code at line 760 may be where the highlightSymbol graphic may be NOT drawing, but I can't be certain:

// hide the graphic in map's default graphiclayer.
 var _searchGL = this.searchDijit.graphicsLayer || this.map.graphics;
 _searchGL.graphics.forEach(lang.hitch(this,function(item) {
 if (item && lang.getObject("_wabProperties.referToFeatureLayerId", false, item)) {
 // this.searchDijit.clearGraphics();
 _searchGL.remove(item);
 }
 }));
 },
_attatchOriLayerId: function(fs) {
 // Summary: attatchOriLayerId _attatch original featureLayer's ID.
 // Condition:
 // 1. Search dijit of JSAPI create new graphic and add it to map's default graphicslayer
 // if no graphicslayer configured, map contains two same graphic at the same time.
 // 2. Attach original flayer's id as a property to graphic(map's default featurelayer),
 // WAB can create related records with .
// fs is an array, it's item could be 'esri.Graphic' or 'dojo.deferred'
if (fs && fs.length && fs[0].declaredClass === "esri.Graphic" &&
 esriLang.isDefined(this._currentSelectSourceIdx)) {
 // iterator every item
 fs.forEach(lang.hitch(this, function(item) {
 // only type 'esri.Graphic'
 if (item.declaredClass === "esri.Graphic") {
 // original featurelayer id
 var _featureLayerId = this.searchDijit.sources[this._currentSelectSourceIdx]._featureLayerId;
 // get original featurelayer if exists.
 var layer = _featureLayerId && this.layerInfosObj.getLayerInfoById(_featureLayerId);
 // if original featurelayer added to map
 if (layer && this.config.showInfoWindowOnSelect) {
 // attatch original featurelayer's ID to this feature
 lang.setObject("_wabProperties.referToFeatureLayerId", _featureLayerId, item);
 }
 }
 }));
 }
 },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So if anyone has any suggestions as to where I can add/remove or otherwise comment code in order to be able to draw a custom highlight upon a result selection that would certainly help, because I just can't see it. 

As an fyi I did not see any other changes to any other js or json files contained with the Search.  The only changes appear to be in the Widget.js

Thanks,

David

Tags (1)
0 Kudos
24 Replies
RobertScheitlin__GISP
MVP Emeritus

Andrew,

   What version of WAB are you using?

0 Kudos
by Anonymous User
Not applicable

2.8 -- the latest and 'greatest!'

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Andrew,

  Actually 2.9 is out. In 2.9 I don't get an orange graphic.

0 Kudos
by Anonymous User
Not applicable

Well that's exciting -- just the normal highlight (cyan) graphic when you search directly against a feature service? I'll download 2.9 and see if the app plays nice there

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Correct

0 Kudos
KyleSchwizer
Occasional Contributor

Has anyone made the jump to 2.10 and gotten this functionality to work? I had it working on 2.7 but as I have made the jump to the most recent version i cant seem to recreate it. I can see the changes start to work on initial search but then they disappear and get over taken by the default highlight and popup window. When I disable the highlight in the Widget.js I get the same result. Initial search will show the change briefly but then it will disappear. 

0 Kudos
KyleSchwizer
Occasional Contributor

Got it figured out. Please see the below code changes to both the Search Widget.js and the Search config.json.

Search Widget.js changes:

//Place after var convertedSource around line 376
var convertedSource = {
                featureLayer: flayer,
                outFields: ["*"],
                searchFields: fNames,
                autoNavigate: false,
                displayField: source.displayField || "",
                exactMatch: !!source.exactMatch,
                name: jimuUtils.stripHTML(source.name || ""),
                placeholder: jimuUtils.stripHTML(source.placeholder || ""),
                maxSuggestions: source.maxSuggestions || 6,
                maxResults: source.maxResults || 6,
                zoomScale: source.zoomScale || 50000,
                //infoTemplate: lang.clone(template),
                useMapExtent: !!source.searchInCurrentMapExtent,
                showInfoWindowOnSelect: showInfoWindowOnSelect,
                enableInfoWindow: enableInfoWindow,
                _featureLayerId: source.layerId,
                _zoomScaleOfConfigSource: source.zoomScale,
                _panToScale: source.panToScale,
              
              };
//Insert below lines
              if (source.highlightSymbol) {
                convertedSource.highlightSymbol = jsonUtils.fromJson(source.highlightSymbol);
                this.map.infoWindow.fillSymbol = jsonUtils.fromJson(source.highlightSymbol);
              }
//Comment out this.searchDijit.clearGraphics() to get symbology to persist
_loadInfoTemplateAndShowPopup: function (layerInfo, selectedFeature, selectEvent) {
        if (layerInfo) {
          //this.searchDijit.clearGraphics();
          var layerObjectInMap = this.map.getLayer(layerInfo.id);
          if (layerInfo.isPopupEnabled() && layerObjectInMap) {
            this._showPopupByFeatures(layerInfo, [selectedFeature], selectEvent);
          } else {
            layerInfo.loadInfoTemplate().then(lang.hitch(this, function (infoTemplate) {
              //temporary set infoTemplate to selectedFeature.
              selectedFeature.setInfoTemplate(lang.clone(infoTemplate));
              this._showPopupByFeatures(layerInfo, [selectedFeature], selectEvent);
              // clear infoTemplate for selectedFeature;
              var handle = aspect.before(this.map, 'onClick', lang.hitch(this, function () {
                selectedFeature.setInfoTemplate(null);
                handle.remove();
              }));
            }));
          }
        }
      },

 Search config.js additions: 

// Add at end of config. Need to be sure that showInfoWindowOnSelect is true     
 "highlightSymbol": {
        "color": [
          0,
          0,
          0,
          0
        ],
        "outline": {
          "color": [
            0,
            0,
            0,
            128
          ],
          "width": 3.5,
          "type": "esriSLS",
          "style": "esriSLSSolid"
        },
        "type": "esriSFS",
        "style": "esriSFSSolid"
      }
DavidColey
Honored Contributor

Thanks for doing this Kyle, usually I keep up with this particular little change from version to version but in this case I had not yet done so as I've been standing up Enterprise at 10.6 then to 10.6.1 for the last 4 months.  Actually, in looking at your change and what I have at 2.8, looks the same.  But I hadn't moved to 2.10 since Portal at 10.6.1 uses wab 2.8, I now want to keep my wab dev and portal wab at the same release level. 

DavidColey
Honored Contributor

Hi Kyle -  I have an update to this for wab 2.11.  There is an updated code section in the widget.js on or about line 330 that needs to be commented out as well as the above changes you put up on Oct 31 if you want the graphic to persist:

/* if(sourceLayerInfo) {
 if(searchLayer.geometryType === "esriGeometryPoint") {
 convertedSource.highlightSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,
 10,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255, 0.0]),
 2),
 new Color([0, 0, 0, 0.0]));
 } else if(searchLayer.geometryType === "esriGeometryPolyline") {
 convertedSource.highlightSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255, 0.0]),
 2);
 } else if(searchLayer.geometryType === "esriGeometryPolygon") {
 convertedSource.highlightSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255, 0.0]),
 2));
 }
 } else {
 if(searchLayer.geometryType === "esriGeometryPoint") {
 convertedSource.highlightSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,
 10,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255]),
 2),
 new Color([0, 0, 0]));
 } else if(searchLayer.geometryType === "esriGeometryPolyline") {
 convertedSource.highlightSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255]),
 2);
 } else if(searchLayer.geometryType === "esriGeometryPolygon") {
 convertedSource.highlightSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([0, 255, 255]),
 2));
 }
 } */‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I'm not really sure what this section is doing now, I guess it's just the way the developers are handling highlighting....

0 Kudos
DavidColey
Honored Contributor

Actually I can see a little more of what this is doing.  When browsing/clicking a feature layer in the map, by commenting out this entire section the popup highlight will return the same as what you have set in the search config and not the default light-blue highlight symbol, for polygon layers at least.  I'll do more work..... 

0 Kudos