PageSourceSearch

https://serviciiharta.brasovcity.ro/portal/js/_xportalTemplate/wg2.SearchPanel.js

js brasovcity.ro collected 2026-10-02 06:55:30 UTC 52,602 bytes, 1,166 lines download raw bytes

1WebGis.SearchPanel = OpenLayers.Class(
2{
3    /********************************************************************************************/
4    /********************************* Variables ************************************************/
5    /********************************************************************************************/
6
7    Config: null,
8    MapControl: null,
9    TabSettings: [],
10
11    TabPanelID: "advSearchTabPanel",
12
13    TabBar_Class: "wgTabBar",
14    TabPanel_Class: "wgTabPanel",
15    TabPanelBody_Class: "wgTabPanelBody",
16    TabHeaderS_Class: "wgTabHeader_S",
17    TabHeaderM_Class: "wgTabHeader_M",
18    TabBody_Class: "wgTabBody",
19    TabBtns_Class: "wgContainerBtns",
20    Button_Class: "wgTabPnlBtn",
21
22    GridSelectedItem_Class: "wgResultGrid_SelectedItem",
23    Grid_Class: "wgResultGridPanel",
24    GridBody_Class: "wgResultGridPanelBody",
25    GridColumn_Class: "wgResultColumn",
26    GridCell_Class: "wgResultCell",
27    GridPagingToolbar_Class: "wgPagingtoolbar",
28
29    Msg_NoSearchPerformed: properties.menu.AdvSearch_NoSearchPerformed,
30    Msg_NoResultFound: properties.menu.AdvSearch_NoResultFound,
31
32    BtnShowFeature_Text: properties.menu.AdvSearch_BtnShowFeature_Text,
33    BtnShowFeature_IconCls: "icon-sagetele",
34
35    Feature_Tooltip: properties.menu.AdvSearch_Feature_Tooltip,
36
37    SearchUtil: null,
38
39    EM_FEATURE_NOT_FOUND: properties.menu.AdvSearch_EM_FeatureNotFound,
40    EM_FEATURE_GEOMETRY_NOT_FOUND: properties.menu.AdvSearch_EM_FeatureGeometryNotFound,
41    EM_RELATED_FEATURE_NOT_FOUND: properties.menu.AdvSearch_EM_RelatedGeometryNotFound,
42
43    /********************************************************************************************/
44
45    /********************************************************************************************/
46    /********************************* Constructor **********************************************/
47    /********************************************************************************************/
48
49    initialize: function (mapControl) {
50
51        meAdvSearch = this;
52        this.events = new OpenLayers.Events(this);
53        this.MapControl = mapControl;
54        this.SearchUtil = new WebGis.Search.Util();
55    },
56
57    /********************************************************************************************/
58
59    /********************************************************************************************/
60    /*******************************  Main functions used outside the class *********************/
61    /********************************************************************************************/
62
63    init: function (_config) {
64
65        this.Config = _config.map.advancedSearches;
66        this.ExtractTabsSettigs();
67    },
68
69    //Create advanced search control and render it to the div received as parameter
70    CreateControl: function (divID) {
71
72        this.DefineControl();
73        Ext.create('WebGis2.view.SearchCtrl', { renderTo: divID });
74
75        $(window).resize(function () {
76            Ext.getCmp(meAdvSearch.TabPanelID).doLayout();
77        });
78    },
79
80    //Cancel drawing - used when onother btn from othet panel gets focus
81    CancelDrawing: function () {
82        for (var i = 0; i < this.TabSettings.length; i++) {
83            this.TabSettings[i].FilterDrawing.disableDrawing();
84        }
85    },
86
87    /********************************************************************************************/
88
89    /********************************************************************************************/
90    /****************************  Main functions used to extract settings **********************/
91    /********************************************************************************************/
92
93    //Extract tabs' settings used to create the search tabs and to display results
94    ExtractTabsSettigs: function () {
95
96        this.TabSettings = [];
97        for (var i = 0; i < this.Config.length; i++) {
98            this.TabSettings.push(
99                this.ExtractTabSettings(this.Config[i], i));
100        }
101    },
102
103    //Extract tab settings used to create the search tabs and to display results
104    ExtractTabSettings: function (advSearch, tabIndex) {
105
106        var tabSetting = {};
107        tabSetting.GUID = advSearch.Guid;
108        tabSetting.Title = advSearch.Name;
109
110        tabSetting.FilterDrawing = new WebGis.Drawing(_mapControl.map, "FilterLayer_" + tabIndex.toString(),null, null)
111
112        //Filter settings
113        tabSetting.Filters = [];
114        for (var i = 0; i < advSearch.Filters.length; i++) {
115
116            if (!advSearch.Filters[i].ForDesktopTemplate) {
117                continue;
118            }
119
120            var filterSettings = {
121                fieldName: advSearch.Filters[i].Field,
122                label: advSearch.Filters[i].Label,
123                fieldType: this.getType(advSearch.Filters[i].FieldType),
124                filterType: this.getFilterCtrlType(advSearch.Filters[i].FieldInterpretationType, advSearch.Filters[i].IsDropDownList,
125                    this.getOpType(advSearch.Filters[i].FilterOpType)),
126                filterOp: this.getOpType(advSearch.Filters[i].FilterOpType),
127                filterSettings: this.getFilterCtrlSettings(advSearch.Filters[i], tabIndex, tabSetting.FilterDrawing),
128                validationFunction: advSearch.Filters[i].ValidationFunction
129            }
130
131            if (filterSettings.fieldType != null && filterSettings.filterType != null) {
132                tabSetting.Filters.push(filterSettings);
133            }
134        }
135
136        //Result settings
137        tabSetting.Results = {};
138        tabSetting.Results.LoadByDefault = advSearch.LoadByDefault;
139        tabSetting.Results.Template = advSearch.ResultItemTemplate;
140        tabSetting.Results.Fields = this.SearchUtil.getResultFields(advSearch);
141        tabSetting.Results.RelatedFeature = this.SearchUtil.getResult_RelatedFeature(advSearch);
142        tabSetting.Results.IsMapRealated = advSearch.ShowResultsByDefault && tabSetting.Results.RelatedFeature != null;
143
144        //The Guid for the layers related to a certain search (one layer for default Search, two layers for Map Related Search- main layer 
145        //& layer for other related features)
146        tabSetting.RelatedLayerGUID = advSearch.Guid;
147        if (tabSetting.Results.IsMapRealated) {
148            tabSetting.MainLayerGUID = "Main_" + advSearch.Guid;
149        }
150
151        tabSetting.Results.StoreName = this.SearchUtil.getStore(tabSetting.Results.IsMapRealated, advSearch, tabSetting.MainLayerGUID);
152        return tabSetting;
153    },
154
155    /********************************************************************************************/
156
157    /********************************************************************************************/
158    /*******************  Main functions used to define the Search Control **********************/
159    /********************************************************************************************/
160
161    //Define the search panel control - a TabPanel with a tab for each advanced search 
162    DefineControl: function () {
163
164        Ext.define('WebGis2.view.SearchCtrl', {
165            extend: 'Ext.tab.Panel',
166            id: this.TabPanelID,
167            cls: this.TabPanel_Class,
168            bodyCls: this.TabPanelBody_Class,
169            width: "100%",
170            height: "100%",
171            items: this.GetTabItems(),
172            tabBar: {
173                cls: this.TabBar_Class,
174            },
175            config: {
176                //Deactivate the tab related to a certain search
177                deactivateTab: function (ctrl, advSearchGUID) {
178                    var tabs = ctrl.items.items;
179                    for (var i = 0; i < tabs.length; i++) {
180                        if (tabs[i].advSerachGuid == advSearchGUID) {
181                            tabs[i].config.deactivate(tabs[i]);
182                            break;
183                        }
184                    }
185                },
186                //Activate the tab related to a certain search
187                activateTab: function (ctrl, advSearchGUID) {
188                    var tabs = ctrl.items.items;
189                    for (var i = 0; i < tabs.length; i++) {
190                        if (tabs[i].advSerachGuid == advSearchGUID) {
191                            tabs[i].config.activate(tabs[i]);
192                            break;
193                        }
194                    }
195                },
196            },
197            listeners: {
198                beforetabchange: function (tabPanel, newCard, oldCard, opts) {
199                 
200                    $event.notify("advancedSearch_BeforeTabChange", {
201                        newTab_advSearchGUID: newCard.advSerachGuid,
202                        oldTab_advSearchGUID: oldCard.advSerachGuid,
203                    }, this);
204                    if(this.cancelEvent) {
205	                    this.cancelEvent = false;
206	                    return false;
207	                }
208                    return true;
209                },
210                tabchange: function (tabPanel, newCard, oldCard, eOpts) {
211
212                    //Disable drawing for the old tab and hide the filter layer
213                    var tabSettings = meAdvSearch.getTabSettings_ByGuid(oldCard.advSerachGuid);
214                    meAdvSearch.destroyLayer(tabSettings.RelatedLayerGUID);
215                    if (tabSettings.MainLayerGUID != null && _mapControl.GetLayerByGuid(tabSettings.MainLayerGUID) != null) {
216                        _mapControl.GetLayerByGuid(tabSettings.MainLayerGUID).setVisibility(false);
217                    }
218                    tabSettings.FilterDrawing.disableDrawing();
219                    tabSettings.FilterDrawing.setLayerVisibility(false);
220
221                    //Show the filter layer for the new tab
222                    tabSettings = meAdvSearch.getTabSettings_ByGuid(newCard.advSerachGuid);
223                    tabSettings.FilterDrawing.setLayerVisibility(true);
224                    if (tabSettings.MainLayerGUID != null && _mapControl.GetLayerByGuid(tabSettings.MainLayerGUID)) {
225                        _mapControl.GetLayerByGuid(tabSettings.MainLayerGUID).setVisibility(true);
226                    }
227                }
228            }
229        });
230    },
231
232    //Get the tab items that should be added to the search panel 
233    GetTabItems: function () {
234
235        var tabItems = [];
236        for (var i = 0; i < this.TabSettings.length; i++) {
237            tabItems.push(this.GetTabItem(this.TabSettings[i]));
238        }
239
240        return tabItems;
241    },
242
243    //Create a tab item according to the settings received as parameter
244    //It contains 3 sections: the filter section (controls for each filters), 
245    //the button section (search and clear section), the result section (a list with the search results)
246    GetTabItem: function (tabSetting) {
247
248        var tabItem = {
249            xtype: "panel",
250            layout: "fit",
251            hideMode: 'offsets',
252            advSerachGuid: tabSetting.GUID,
253            title: tabSetting.Title,
254            tabConfig: {
255                cls: this.TabHeaderS_Class, 
256            },
257            cls: this.TabBody_Class,
258            padding: "10 10 10 10",
259            layout: {
260                type: 'vbox'
261            },
262            config: {
263
264                //Deactivate the items from the current tab
265                deactivate: function (ctrl) {
266
267                    var tabItems = ctrl.items.items;
268                    for (var i = 0; i < tabItems.length - 1; i++) {
269                        var tabContainerItems = tabItems[i];
270                        for (var j = 0; j < tabContainerItems.items.items.length; j++) {
271                            tabContainerItems.items.items[j].setDisabled(true);
272                        }
273                    }
274                    tabItems[tabItems.length - 1].setDisabled(true);
275                },
276
277                //Reactivate the items for the current tab
278                activate: function (ctrl) {
279
280                    var tabItems = ctrl.items.items;
281                    for (var i = 0; i < tabItems.length - 1; i++) {
282                        var tabContainerItems = tabItems[i];
283                        for (var j = 0; j < tabContainerItems.items.items.length; j++) {
284                            tabContainerItems.items.items[j].setDisabled(false);
285                        }
286                    }
287                    tabItems[tabItems.length - 1].setDisabled(false);
288                },
289
290            },
291            items: [
292                //Filter Section
293                {
294                    xtype: 'container',
295                    items: this.GetFilterItems(tabSetting),
296                    width: "100%",
297                },
298                //Clear and Search ButtonsSection
299                {
300                    xtype: 'container',
301                    width: "100%",
302                    layout: {
303                        type: 'hbox',
304                        pack: 'end',
305                        padding: "10 0 10 0",
306                    },
307                    itemCls: this.TabBtns_Class,
308                    items: [
309                          {
310                              xtype: 'button',
311                              text: properties.menu.AdvSearch_BtnClear_Text,
312                              store_name: tabSetting.Results.StoreName,
313                              advSerachGuid: tabSetting.GUID,
314                              cls: this.Button_Class,
315                              listeners: {
316                                  click: {
317                                      scope: this,
318                                      fn: function (button, e, eOpts) {
319
320                                          $event.notify("advancedSearch_CleanBtn_OnClick", { advSearchGUID: button.advSerachGuid }, this);
321                                          if (this.cancelEvent) {
322                                              this.cancelEvent = false;
323                                              return false;
324                                          }
325                                        
326                                          var panelItem = button.up("container").up("panel");
327
328                                          //Clear filters
329                                          var filtersContainer = panelItem.items.items[0];
330                                          var filterItems = filtersContainer.items.items;
331                                          for (var i = 0; i < filterItems.length; i++) {
332                                              filterItems[i].clearField();
333                                          }
334
335                                          //Change the empty msg and clear the grid                                          
336                                          var grid = panelItem.down("grid");
337                                          grid.getView().emptyText = "<div class='x-grid-empty'>" + meAdvSearch.Msg_NoSearchPerformed + "</div>";
338                                          var store = Ext.StoreManager.getByKey(button.store_name);
339                                          store.loadPage(0);
340
341                                          //Destroy the layer for the related features (the main layer for map related search 
342                                          //is destroyed when the grid is cleared)
343                                          var tabSettings = meAdvSearch.getTabSettings_ByGuid(button.advSerachGuid);
344                                          meAdvSearch.destroyLayer(tabSettings.RelatedLayerGUID);
345                                      }
346                                  }
347                              }
348                          },
349                         {
350                             xtype: 'button',
351                             text: properties.menu.AdvSearch_BtnSearch_Text,
352                             store_name: tabSetting.Results.StoreName,
353                             cls: this.Button_Class,
354                             advSerachGuid: tabSetting.GUID,
355                             listeners: {
356                                 click: {
357                                     scope: this,
358                                     fn: function (button, e, eOpts) {
359
360                                         $event.notify("advancedSearch_SearchBtn_OnClick", { advSearchGUID: button.advSerachGuid }, this);
361                                         if (this.cancelEvent) {
362                                             this.cancelEvent = false;
363                                             return false;
364                                         }
365
366                                         var panelItem = button.up("container").up("panel");
367
368                                         //Use filters to create the store query
369                                         var query = "";
370                                         var filtersContainer = panelItem.items.items[0];
371                                         var filterItems = filtersContainer.items.items;
372                                         var errorList = [];
373                                         for (var i = 0; i < filterItems.length; i++) {
374                                             var filterItem = filterItems[i];
375
376                                             //check the filter value 
377                                             if (typeof window[filterItem.validationFunction] === "function") {
378                                                 var response = null;
379                                                 if (filterItem.filterOp == "Between") {
380                                                     response = window[filterItem.validationFunction](filterItem.getValue_From(),
381                                                         filterItem.getValue_To());
382                                                 }
383                                                 else {
384                                                     response = window[filterItem.validationFunction](filterItem.getValue());
385                                                 }
386                                                 if (response.error && response.errorMsg != null && response.errorMsg != "") {
387                                                     errorList.push(response.errorMsg);
388                                                 }
389                                             }
390
391                                             var filterQuery = filterItem.getSearchQuery();
392                                             if (filterQuery != null && filterQuery != "") {
393                                                 query += (query == "" ? "" : "&") + filterQuery;
394                                             }
395                                         }
396
397                                         //if there are invalid filters, don't perfom the search
398                                         if (errorList.length > 0) {
399                                             var msg = "";
400                                             for (var i = 0; i < errorList.length; i++) {
401                                                 msg += errorList[i] + "<br>";
402                                             }
403
404                                             Ext.Msg.alert('', msg, Ext.emptyFn);
405                                             return;
406                                         }
407
408                                         //Change the empty msg and load the grid     
409                                         var grid = panelItem.down("grid");
410                                         grid.getView().emptyText = "<div class='x-grid-empty'>" + meAdvSearch.Msg_NoResultFound + "</div>";
411
412                                         var store = Ext.StoreManager.getByKey(button.store_name);
413                                         store.proxy.url = store.proxy.backupUrl + "&" + query;
414                                         store.loadPage(1);
415
416                                         //Destroy the layer for the related features (the main layer for map related search 
417                                         //is recreated when the grid is loaded)
418                                         var tabSettings = meAdvSearch.getTabSettings_ByGuid(button.advSerachGuid);
419                                         tabSettings.FilterDrawing.disableDrawing();
420                                         meAdvSearch.destroyLayer(tabSettings.RelatedLayerGUID);
421                                     }
422                                 }
423                             }
424                         }
425                    ]
426                },
427
428             //The Grid for results
429             this.GetResultItem(tabSetting)
430            ],
431
432        };
433        return tabItem;
434    },
435
436    //Get tab filter items
437    GetFilterItems: function (tabSettings) {
438
439        var filterItems = [];
440        for (var i = 0; i < tabSettings.Filters.length; i++) {
441            filterItems.push({
442                xtype: tabSettings.Filters[i].filterType,
443                fieldLabel: tabSettings.Filters[i].label,
444                fieldName: tabSettings.Filters[i].fieldName,
445                type: tabSettings.Filters[i].fieldType,
446                filterOp: tabSettings.Filters[i].filterOp,
447                filterSettings: tabSettings.Filters[i].filterSettings,
448                validationFunction: tabSettings.Filters[i].validationFunction
449            });
450        }
451        return filterItems;
452    },
453
454    //Get the item used to show the search results inside a tab 
455    GetResultItem: function (tabSettings) {
456
457        if (tabSettings.Results.IsMapRealated) {
458            return this.GetResultItem_MapRelated(tabSettings);
459        }
460        else {
461            return this.GetResultItem_Default(tabSettings);
462        }
463    },
464
465    //The Grid Panel for the default search (the results are not displayed into the map)
466    GetResultItem_Default: function (tabSettings) {
467
468        var item = {
469            xtype: 'gridpanel',
470            disableSelection: true,
471            header: false,
472            store: tabSettings.Results.StoreName,
473            cls: this.Grid_Class,
474            flex: 1,
475            bodyCls: this.GridBody_Class,
476            autoScroll: true,
477            width: "100%",
478            viewConfig: {
479                deferEmptyText: false,
480                emptyText: this.Msg_NoSearchPerformed,
481                selectedItemCls: this.GridSelectedItem_Class,
482                loadMask: false,
483            },
484            loadByDefault: tabSettings.Results.LoadByDefault,
485
486            columns: [
487                 {
488                     xtype: 'templatecolumn',
489                     text: properties.menu.AdvSearch_ResultGrid_Header,
490                     menuDisabled: true,
491                     sortable: false,
492                     tpl: tabSettings.Results.Template,
493                     advSerachGUID: tabSettings.GUID,
494                     flex: 1,
495                     cls: this.GridColumn_Class,
496                     tdCls: this.GridCell_Class,
497   
497                  renderer: function (value, metaData, record, row, col, store, gridView) {
498
499                         var template = this.columns[0].tpl.html;
500                         var tabSettings = meAdvSearch.getTabSettings_ByGuid(this.columns[0].advSerachGUID);
501                         var resultFields = tabSettings.Results.Fields;
502                         var relatedFeature = tabSettings.Results.RelatedFeature;
503
504                         //Use the results to create the template
505                         for (var i = 0; i < resultFields.length; i++) {
506                             var text = meAdvSearch.getResultField_Text(record.data[resultFields[i].Field], resultFields[i], record,
507                                 tabSettings.RelatedLayerGUID, this.columns[0].advSerachGUID);
508                             template = template.replaceAll("{" + resultFields[i].Field + "}", text);
509                         }
510
511                         //Add btn to show related feature if any
512                         if (relatedFeature != null && record.data[relatedFeature.FeatureID] != null && record.data[relatedFeature.FeatureID] != ""
513                             && record.data[relatedFeature.FeatureID] != 0) {
514                             var colNr = meAdvSearch.getColumnCount($(template));
515                             var btnHtml = "<a title='" + meAdvSearch.Feature_Tooltip + "' class='" + meAdvSearch.BtnShowFeature_IconCls + "' href='javascript:meAdvSearch.showFeatures(\""
516                                 + this.columns[0].advSerachGUID + "\",\"" + tabSettings.RelatedLayerGUID + "\",null,\""
517                                 + record.data[relatedFeature.FeatureID].toString() + "\", true);'> "
518                                 + meAdvSearch.BtnShowFeature_Text + " </a>";
519                             var rowHtml = "<tr><td align='right' style='padding-bottom:5px;' colspan='" + colNr.toString() + "'>" + btnHtml + "</td></tr>";
520                             template = $(template).last().append(rowHtml)[0].outerHTML;
521                         }
522
523
524                         //Correct the templet html- remove links with href='-'
525                         if ($(template).find("a[href=-]").length > 0) {
526
527                             var emptyLinks = $(template).find("a[href=-]");
528                             for (var i = 0; i < emptyLinks.length; i++) {
529                                 template = template.replaceAll(emptyLinks[i].outerHTML, "-");
530                             }
531
532
533                         }
534
535                         //Correct the templet html- remove imgs with src='-'
536                         if ($(template).find("img[src=-]").length > 0) {
537                             var emptyImages = $(template).find("img[src=-]");
538                             for (var i = 0; i < emptyImages.length; i++) {
539                                 template = template.replaceAll(emptyImages[i].outerHTML, "-");
540                                 template = template.replaceAll(emptyImages[i].outerHTML.replaceAll("\"", "'"), "-");
541                                 template = template.replaceAll(emptyImages[i].outerHTML.replaceAll("'", "\""), "-");
542                             }
543                         }
544
545                         return template;
546                     }
547                 },
548            ],
549            dockedItems: [
550                {
551                    xtype: 'pagingtoolbar',
552                    dock: 'bottom',
553                    width: "100%",
554                    displayInfo: false,
555                    store: tabSettings.Results.StoreName,
556                    cls: this.GridPagingToolbar_Class
557                }
558            ],
559            listeners: {
560                afterrender: function (ctrl, eOpts) {
561                    ctrl.getStore().gridID = ctrl.getId();
562                    //perform default search if the grid should be loaded by default
563                    if (this.loadByDefault) {
564                        ctrl.getStore().loadPage(1);
565                    }
566                },
567                beginDrag: function () {
568                    if (this.floatingDescendants) {
569                        this.floatingDescendants.hide();
570                    }
571                },
572
573                endDrag: function () {
574                    if (this.floatingDescendants) {
575                        this.floatingDescendants.show();
576                    }
577                },
578
579            },
580            config: {
581
582                //Apply custom scrollbar inside the grid
583                applyCustomScrollBar: function (ctrl) {
584
585                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").css("overflow-y", "auto");
586                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").mCustomScrollbar();
587                },
588
589                //Remove custom scrollbar from the grid
590                removeCustomScrollBar: function (ctrl) {
591
592                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").css("overflow-y", "hidden");
593                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").mCustomScrollbar("destroy");
594                }
595            }
596        };
597
598        return item;
599    },
600
601    //The Grid Panel for the map related search (the grid results' features are displayed into the map)
602    GetResultItem_MapRelated: function (tabSettings) {
603
604        var item = {
605            xtype: 'gridpanel',
606            disableSelection: false,
607            header: false,
608            store: tabSettings.Results.StoreName,
609            cls: this.Grid_Class,
610            flex: 1,
611            bodyCls: this.GridBody_Class,
612            autoScroll: true,
613            width: "100%",
614            viewConfig: {
615                deferEmptyText: false,
616                emptyText: this.Msg_NoSearchPerformed,
617                selectedItemCls: this.GridSelectedItem_Class,
618                loadMask: false,
619            },
620            loadByDefault: tabSettings.Results.LoadByDefault,
621
622            columns: [
623                 {
624                     xtype: 'templatecolumn',
625                     text: properties.menu.AdvSearch_ResultGrid_Header,
626                     menuDisabled: true,
627                     sortable: false,
628                     tpl: tabSettings.Results.Template,
629                     advSerachGUID: tabSettings.GUID,
630                     flex: 1,
631                     cls: this.GridColumn_Class,
632                     tdCls: this.GridCell_Class,
633                     renderer: function (value, metaData, record, row, c
633ol, store, gridView) {
634
635                         var template = this.columns[0].tpl.html;
636                         var tabSettings = meAdvSearch.getTabSettings_ByGuid(this.columns[0].advSerachGUID);
637                         var resultFields = tabSettings.Results.Fields;
638
639                         //Use the results to create the template
640                         for (var i = 0; i < resultFields.length; i++) {
641                             var text = meAdvSearch.getResultField_Text(record.data[resultFields[i].Field], resultFields[i], record,
642                                 tabSettings.RelatedLayerGUID, this.columns[0].advSerachGUID);
643                             template = template.replaceAll("{" + resultFields[i].Field + "}", text);
644                         }
645
646                         //Correct the templet html- remove links with href='-'
647                         if ($(template).find("a[href=-]").length > 0) {
648
649                             var emptyLinks = $(template).find("a[href=-]");
650                             for (var i = 0; i < emptyLinks.length; i++) {
651                                 template = template.replaceAll(emptyLinks[i].outerHTML, "-");
652                             }
653                         }
654
655                         //Correct the templet html- remove imgs with src='-'
656                         if ($(template).find("img[src=-]").length > 0) {
657                             var emptyImages = $(template).find("img[src=-]");
658                             for (var i = 0; i < emptyImages.length; i++) {
659                                 template = template.replaceAll(emptyImages[i].outerHTML, "-");
660                                 template = template.replaceAll(emptyImages[i].outerHTML.replaceAll("\"", "'"), "-");
661                                 template = template.replaceAll(emptyImages[i].outerHTML.replaceAll("'", "\""), "-");
662                             }
663                         }
664
665                         return template;
666                     }
667                 },
668            ],
669            dockedItems: [
670                {
671                    xtype: 'pagingtoolbar',
672                    dock: 'bottom',
673                    width: "100%",
674                    displayInfo: false,
675                    store: tabSettings.Results.StoreName,
676                    cls: this.GridPagingToolbar_Class
677                }
678            ],
679            listeners: {
680                afterrender: function (ctrl, eOpts) {
681                    ctrl.getStore().gridID = ctrl.getId();
682                    //Perform default search if the grid must be loaded by default
683                    if (this.loadByDefault) {
684                        ctrl.getStore().loadPage(1);
685                    }
686                },
687                beforecellclick: function (ctrl, td, cellIndex, record, tr, rowIndex, e, eOpts) {
688
689                    //if the user perform the click on a link - avoid item selection
690                    if (e.target.href != null) {
691                        this.getSelectionModel().deselectAll();
692                        this.getSelectionModel().clearSelections();
693                        return false;
694                    }
695                },
696
697                //On click on the result item
698                cellclick: function (ctrl, td, cellIndex, record, tr, rowIndex, e, eOpts) {
699
700                    //if the user perform the click on a link - avoid item selection
701                    if (e.target.href != null) {
702                        this.getSelectionModel().deselectAll();
703                        this.getSelectionModel().clearSelections();
704                        return;
705                    }
706
707                    $event.notify("advancedSearch_BeforeShowFeature", { advSearchGUID: this.columns[0].advSerachGUID }, this);
708                    if (this.cancelEvent) {
709                        this.getSelectionModel().deselectAll();
710                        this.getSelectionModel().clearSelections();
711                        this.cancelEvent = false;
712                        return;
713                    }
714                
715                    //Clear feature selection
716                    _mapControl.featureSelection.ClearSelection();
717
718                    //Find the feature related to the selected result item and select it
719                    var tabSettings = meAdvSearch.getTabSettings_ByGuid(this.columns[0].advSerachGUID);
720                    var layer = _mapControl.GetLayerByGuid(tabSettings.MainLayerGUID);
721                    var relatedFeature = tabSettings.Results.RelatedFeature;
722
723                    var featureID_Field = relatedFeature.FeatureID;
724                    var featureID = record.data[featureID_Field];
725
726                    //If the result has no related feature - inform the user
727                    if (featureID == null) {
728                        Ext.Msg.alert('', meAdvSearch.EM_RELATED_FEATURE_NOT_FOUND, Ext.emptyFn);
729                        return;
730                    }
731
732                    //Try to find and select the feature
733                    for (var i = 0; i < layer.features.length; i++) {
734
735                        if (featureID == layer.features[i].data[featureID_Field]) {
736
737                            _mapControl.FitFeatures([layer.features[i]], 1.1, layer.zoomLevel, false);
738                            _mapControl.featureSelection.SelectFeature(layer.features[i]);
739                            return;
740                        }
741
742                    }
743
744                    //If the result has no related feature - inform the user
745                    Ext.Msg.alert('', meAdvSearch.EM_RELATED_FEATURE_NOT_FOUND, Ext.emptyFn);
746
747                }
748            },
749            config: {
750                //Apply custom scrollbar inside the grid
751                applyCustomScrollBar: function (ctrl) {
752
753                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").css("overflow-y", "auto");
754                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").mCustomScrollbar();
755                },
756                //Remove custom scrollbar from the grid
757                removeCustomScrollBar: function (ctrl) {
758
759                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").css("overflow-y", "hidden");
760                    $("#" + ctrl.getId() + " .wgResultGridPanelBody .x-grid-view").mCustomScrollbar("destroy");
761                }
762            }
763        };
764
765        return item;
766    },
767
768    /********************************************************************************************/
769
770    /********************************************************************************************/
771    /*******************  Main functions used to define the Search Control **********************/
772    /********************************************************************************************/
773
774    //Get column type
775    getType: function (type) {
776
777        switch (type) {
778            case 1:
779                return "Boolean";
780            case 2:
781                return "Int";
782            case 3:
783                return "Double";
784            case 4:
785                return "String";
786            case 5:
787                return "Date";
788            case 6:
789                return "Time";
790            case 7:
791                return "DateTime";
792            case 8:
793                return "Geometry";
794        }
795    },
796
797    //Get column type
798    getFilterCtrlType: function (type, isDDL, op) {
799
800        if (isDDL) {
801            return "wgListOfValuesFilter";
802        }
803
804        switch (type) {
805            case 1:
806                return "wgBooleanFilter";
807            case 2:
808                return op == "Between" ? "wgIntIntervalFilter" : "wgIntFilter";
809            case 3:
810                return op == "Between" ? "wgDoubleIntervalFilter" : "wgDoubleFilter";
811            case 4:
812                return "wgStringFilter";
813            case 5:
814                return op == "Between" ? "wgDateIntervalFilter" : "wgDateFilter";
815            case 6:
816                return op == "Between" ? "wgTimeIntervalFilter" : "wgTimeFilter";
817            case 7:
818                return "wgDateTimeFilter";
819            case 8:
820                return "wgGeometryFilter";
821        }
822    },
823
824    //Get the settings according to the filter ctrl type
825    getFilterCtrlSettings: function (filterSettings, tabIndex, FilterDrawing) {
826
827        if (filterSettings.IsDropDownList) {
828            return { ListOfValues: filterSettings.ListOfValues };
829
830        }
831
832        switch (filterSettings.FieldInterpretationType) {
833            case 4:
834                return { RemoveDiacritics: filterSettings.RemoveDiacritics };
835            case 2:
836                return { AllowNumberFormat: filterSettings.AllowNumberFormat };
837            case 3:
838                return { NumberOfDecimals: filterSettings.NumberOfDecimals };
839            case 8:
840                return { ButtonGroup: "Tab_" + tabIndex.toString(), FilterDrawing: FilterDrawing};
841        }
842
843        return null;
844    },
845
846    //Get filter item type
847    getOpType: function (type) {
848
849        switch (type) {
850            case 1:
851                return "Equals";
852            case 2:
853                return "SP_Intersect";
854            case 3:
855                return "SP_Contains";
856            case 4:
857                return "Contains";
858            case 5:
859                return "StartsWith";
860            case 6:
861                return "EndsWith";
862            case 7:
863                return "SmallerThan";
864            case 8:
865                return "SmallerOrEqualThan";
866            case 9:
867                return "GreaterThan";
868            case 10:
869                return "GreaterOrEqualThan";
870            case 11:
871                return "NotNull";
872            case 12:
873                return "Between";
874        }
875    },
876
877    //Get field 
878    getResultField_Text: function (value, settings, record, layerGUID, advancedSearchGUID) {
879
880        var result = "-";
881
882        if (value != null && value.toString() != "") {
883            switch (settings.FieldInterpretationType) {
884                case "Boolean":
885                    result = (value == true || value == 1) ? "Da" : "Nu";
886                    break;
887                case "Int":
888                    result = (settings.AllowNumberFormat) ? this.formatNumber(value, 0) : value.toString();
889                    break;
890                case "Double":
891                    result = this.formatNumber(value, settings.NumberOfDecimals);
892                    break;
893                case "String":
894                    result = value;
895                    break;
896                case "Date":
897                    result = moment(value).format("DD.MM.YYYY");
898                    break;
899                case "Time":
900                    result = value.length==20?moment(value.replace("Z","")).format("H:mm"): moment("1990-01-01T" + value).format("H:mm");
901                    break;
902                case "DateTime":
903                    result = moment(value).format("DD.MM.YYYY H:mm");
904                    break;
905            }
906
907            if (settings.RelatedFeature != null && record.data[settings.RelatedFeature.FeatureID] != null &&
908                record.data[settings.RelatedFeature.FeatureID] != "" && record.data[settings.RelatedFeature.FeatureID] != 0) {
909                result = "<a title='" + meAdvSearch.Feature_Tooltip
910                    + "' href='javascript:meAdvSearch.showFeatures(\"" + advancedSearchGUID + "\",\"" + layerGUID + "\",\"" +
911                    settings.Field + "\",\"" + record.data[settings.RelatedFeature.FeatureID].toString()
912                    + "\", true);'>"
913                    + "  <img src='img/pinRed.png' style='width:15px;' />  " + result
914                    + "</a>";
915            }
916        }
917        return result;
918    },
919
920    /********************************************************************************************/
921
922    /********************************************************************************************/
923    /*******************  Main functions used to show Map Features ******************************/
924    /********************************************************************************************/
925
926    //Show related feature inside the map
927    showFeatures: function (advSearchGuid, layerGUID, relatedField, featureID, selectResults) {
928
929        $event.notify("advancedSearch_BeforeShowFeature", { advSearchGUID: advSearchGuid }, this);
930        if (this.cancelEvent) {
931            this.cancelEvent = false;
932            return;
933        }
934
935        var tabSettings = this.getTabSettings_ByGuid(advSearchGuid);
936        var relatedFeatureSettings = this.getRelatedFeature_Details(tabSettings, relatedField);
937
938        //Create the layer related to the current avd search (set the cql filter in order to show only the needed features)
939        //and add it to the map 
940        //set the load end event in order to fit the search results  
941        this.createLayer(layerGUID, advSearchGuid, relatedField, relatedFeatureSettings, featureID, selectResults);
942    },
943
944    //Create layer used to show the advSearchFeatures
945    createLayer: function (layerGUID, advSearchGuid, relatedField, relatedFeatureSettings, featureID, selectResults) {
946
947        //Deactivate current tab (will be reactivated when the feature is retrieved)
948        var tabPnl = Ext.getCmp(this.TabPanelID);
949        tabPnl.config.deactivateTab(tabPnl, advSearchGuid);
950
951        //Destroy the layer related to the current Adv Search
952        this.destroyLayer(layerGUID);
953
954        //Get CQL Filter Expression - used to retrieve only one feature (the needed one)
955        var format_filter = new OpenLayers.Format.CQL();
956        var filterExp = "";
957        if (!$.isArray(featureID)) {
958            filterExp = relatedFeatureSettings.Layer_featureID + "='" + featureID.toString() + "'";
959        }
960        else {
961            for (var i = 0; i < featureID.length; i++) {
962                filterExp += (i > 0 ? " OR " : "") + relatedFeatureSettings.Layer_featureID + "='" + featureID[i].toString() + "'";
963            }
964        }
965        var filter_compute = format_filter.read(filterExp);
966
967        //Create and add layer to the map 
968        //It is used OpenLayers.Strategy.Fixed because the layer should be loaded only once and it should not depend 
969        //on the map bounding box 
970        var layerConfig = relatedFeatureSettings.Layer;
971        var url = _mapControl.main.configUrl(_mapControl.main.url.proxy) + "&_layerGuid=" + layerConfig.GUID;
972        var layer = new OpenLayers.Layer.Vector(layerGUID, {
973            strategies: [new OpenLayers.Strategy.Fixed()],
974            protocol: new OpenLayers.Protocol.WFS({
975                version: "1.1.0",
976                srsName: layerConfig.projection,
977                url: url,
978                featurePrefix: layerConfig.namespace,
979                featureType: layerConfig.tableName,
980                features: layerConfig.geometryName,
981                featureNS: layerConfig.namespace,
982                outputFormat: "JSON",
983                readFormat: new OpenLayers.Format.GeoJSON(),
984                geometryName: layerConfig.geometryFieldName
985            }),
986            filter: filter_compute,
987            projection: new OpenLayers.Projection(layerConfig.projection),
988            attribution: "",
989        });
990        layer.visibility = true;
991        layer.setOpacity(1);
992        layer.GUID = layerGUID;
993        layer.advancedSearchGUID = advSearchGuid;
994        layer.tooltip = layerConfig.tooltip;
995        layer.relatedLayers = [];
996        layer.idFieldName = layerConfig.idFieldName;
997        layer.mobileTooltip = layerConfig.mobileTooltip;
998        layer.zoomLevel = relatedFeatureSettings.Zoom;
999        layer.AdvSearch_RelatedField = relatedField == null ? "" : relatedField;
1000        layer.RelatedToAdvSearch = true;
1001        layer.selectResults = selectResults;
1002
1003        _mapControl.SetLayerStyles(layerConfig, layer);
1004
1005        //When the layer is loaded => show the form
1006        layer.events.register("loadend", layer, function (evt) {
1007
1008            //used to check if the feature has an empty geometry
1009            if (this.features.length == 1 && this.features[0].geometry != null) {
1010                this.features[0].geometry.calculateBounds()
1011            }
1012
1013            if (this.features.length == 0 || (this.features.length == 1 && (this.features[0].geometry == null
1014                || this.features[0].geometry.bounds == null))) {
1015                Ext.Msg.alert('', (this.features.length==1 && (this.features[0].geometry ==null ||this.features[0].geometry.bounds == null))? meAdvSearch.EM_FEATURE_GEOMETRY_NOT_FOUND :
1016                    meAdvSearch.EM_FEATURE_NOT_FOUND, Ext.emptyFn);
1017            }
1018            else {
1019
1020                for (var i = 0; i < this.features.length; i++) {
1021                    this.features[i].isAdvSearchResult = true;
1022                    this.features[i].advSearchResult_RelatedField = this.AdvSearch_RelatedField;
1023                    this.features[i].advancedSearchGUID = this.advancedSearchGUID;
1024                }
1025
1026                _mapControl.FitFeatures(this.features, 1.2, this.zoomLevel, false);
1027                _mapControl.featureSelection.ClearSelection();
1028
1029                if (this.selectResults) {
1030                    _mapControl.featureSelection.SelectFeature(this.features[0]);
1031                }
1032            }
1033
1034            //Reactivate current tab
1035            var tabPnl = Ext.getCmp(meAdvSearch.TabPanelID);
1036            tabPnl.config.activateTab(tabPnl, this.advancedSearchGUID);
1037
1038        });
1039
1040        // Add layer to the map and set its right index
1041        _mapControl.map.addLayers([layer]);
1042        var layerIndex = this.getLayerIndex(relatedFeatureSettings.AddAfterMapLayer);
1043        if (layerIndex != null) {
1044            _mapControl.map.setLayerIndex(layer, layerIndex);
1045        }
1046
1047        //Add the temporary layer to the highlight control
1048        if (_mapControl.featureHighlight) {
1049            _mapControl.featureHighlight.AddLayer(layer);
1050        }
1051
1052        //Add the temporary layer to the tooltip control
1053        if (_mapControl.tooltip) {
1054            _mapControl.tooltip.AddLayer(layer);
1055        }
1056
1057        //Add the temporary layer from the featureSelection control
1058        if (_mapControl.featureSelection) {
1059            _mapControl.featureSelection.AddLayer(layer);
1060        }
1061
1062
1063    },
1064
1065    //Destroy layer related to a certain adv search
1066    destroyLayer: function (layerGUID) {
1067
1068        var layer = _mapControl.GetLayerByGuid(layerGUID);
1069        if (layer) {
1070
1071            _mapControl.featureSelection.ClearSelectionByLayer(layerGUID);
1072
1073            //Remove the temporary layer from the highlight control
1074            if (_mapControl.featureHighlight) {
1075                _mapControl.featureHighlight.RemoveLayer(layer);
1076            }
1077
1078            //Remove the temporary layer from the tooltip control
1079            if (_mapControl.tooltip) {
1080                _mapControl.tooltip.RemoveLayer(layer);
1081            }
1082
1083            //Remove the temporary layer from the featureSelection control
1084            if (_mapControl.featureSelection) {
1085                _mapControl.featureSelection.RemoveLayer(layer);
1086            }
1087
1088            //Remove the temporarylayer from the map and destroy it
1089            _mapControl.map.removeLayer(layer);
1090
1091        }
1092    },
1093
1094    //Get layer Index
1095    getLayerIndex: function (relatedLayerGUID) {
1096
1097        //if the "related layer" was not added to the map, then the result layer should remain 
1098        //the last layer
1099        var relatedLayer = _mapControl.GetLayerByGuid(relatedLayerGUID)
1100        if (relatedLayer == null || relatedLayerGUID == null || relatedLayerGUID == "") {
1101            return null;
1102        }
1103        //The layer must be added after the related layer and other layers related to adv searches
1104        var layerIndex = _mapControl.map.getLayerIndex(relatedLayer);
1105        for (var i = layerIndex + 1; i < _mapControl.map.layers.length; i++) {
1106            if (_mapControl.map.layers[i].RelatedToAdvSearch == null ||
1107                !_mapControl.map.layers[i].RelatedToAdvSearch) {
1108                return i;
1109            }
1110        }
1111
1112        return layerIndex + 1;
1113    },
1114
1115    /********************************************************************************************/
1116    /*******************  Main functions used to define the Search Control **********************/
1117    /********************************************************************************************/
1118
1119    //Get tab settings by tab guid (advSearch guis)
1120    getTabSettings_ByGuid: function (guid) {
1121
1122        for (var i = 0; i < this.TabSettings.length; i++) {
1123            if (this.TabSettings[i].GUID == guid) {
1124                return this.TabSettings[i];
1125            }
1126        }
1127
1128        return null;
1129    },
1130
1131    //Get related feature details
1132    getRelatedFeature_Details: function (tabSettings, relatedField) {
1133
1134        if (relatedField == null || relatedField == "") {
1135            return tabSettings.Results.RelatedFeature;
1136        }
1137
1138        for (var i = 0; i < tabSettings.Results.Fields.length; i++) {
1139            if (tabSettings.Results.Fields[i].Field == relatedField) {
1140                return tabSettings.Results.Fields[i].RelatedFeature;
1141            }
1142        }
1143    },
1144
1145    //Get the number of columns inside a table
1146    getColumnCount: function (table) {
1147        var ColCount = 0;
1148        table.find("tr").eq(0).find("th,td").each(function () {
1149            ColCount += $(this).attr("colspan") ? parseInt($(this).attr("colspan")) : 1;
1150        });
1151
1152        return ColCount;
1153    },
1154
1155    //Return numbers as formated strings
1156    formatNumber: function (x, nrDigits) {
1157        x = Math.floor(x * Math.pow(10, nrDigits)) / Math.pow(10, nrDigits);
1158        var parts = x.toString().split(".");
1159        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1160        return parts.join(".");
1161    },
1162
1163    /********************************************************************************************/
1164
1165});
1166

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.