fit-ui 2.5.0 → 2.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Fit.UI.css CHANGED
@@ -3854,7 +3854,7 @@ div.FitUiControlDropDown[data-selectionmodetoggle="true"]
3854
3854
 
3855
3855
  /* WSDropDown: Action Menu (ListView) */
3856
3856
 
3857
- div.FitUiControlDropDown span.FitUiControlDropDownActionMenuItemDelete
3857
+ div.FitUiControlDropDown span.FitUiControlDropDownActionMenuItemIconDelete
3858
3858
  {
3859
3859
  color: #DB1E1E;
3860
3860
  }
package/dist/Fit.UI.js CHANGED
@@ -648,7 +648,7 @@ Fit._internal =
648
648
  {
649
649
  Core:
650
650
  {
651
- VersionInfo: { Major: 2, Minor: 5, Patch: 0 } // Do NOT modify format - version numbers are programmatically changed when releasing new versions - MUST be on a separate line!
651
+ VersionInfo: { Major: 2, Minor: 5, Patch: 4 } // Do NOT modify format - version numbers are programmatically changed when releasing new versions - MUST be on a separate line!
652
652
  }
653
653
  };
654
654
 
@@ -17177,9 +17177,7 @@ Fit.Controls.DropDown = function(ctlId)
17177
17177
 
17178
17178
  inp.value = "";
17179
17179
 
17180
- Fit.Dom.Data(inp.parentElement, "editing", null);
17181
- Fit.Dom.Data(inp, "editing", null);
17182
- me._internal.Repaint();
17180
+ setInputEditing(inp, false);
17183
17181
 
17184
17182
  if (inp === txtActive)
17185
17183
  prevValue = "";
@@ -17199,22 +17197,31 @@ Fit.Controls.DropDown = function(ctlId)
17199
17197
  {
17200
17198
  Fit.Validation.ExpectString(val);
17201
17199
 
17202
- if (txtActive.value === val)
17203
- return;
17200
+ var txt = txtActive;
17201
+ var fireOnChange = txt.value !== val;
17202
+
17203
+ if (focusAssigned === false && txt !== txtPrimary)
17204
+ {
17205
+ // DropDown does not have focus, and the currently active input field
17206
+ // is not the primary one. Change it to the primary input field instead.
17204
17207
 
17205
- txtActive.value = "";
17208
+ // Clear active input field in case it has a value
17209
+ txtActive.value = "";
17210
+ setInputEditing(txtActive, false);
17206
17211
 
17207
- Fit.Dom.Data(txtActive.parentElement, "editing", val !== "" ? "true" : null);
17208
- Fit.Dom.Data(txtActive, "editing", val !== "" ? "true" : null);
17209
- me._internal.Repaint();
17212
+ txt = txtPrimary;
17213
+ txtActive = txtPrimary;
17214
+ }
17210
17215
 
17211
- var txt = ((focusAssigned === true) ? txtActive : txtPrimary);
17216
+ setInputEditing(txt, val !== "");
17212
17217
 
17213
17218
  txt.value = val;
17214
17219
  prevValue = val;
17215
- txtActive = txt;
17216
17220
 
17217
- fireOnInputChanged(txt.value);
17221
+ if (fireOnChange === true)
17222
+ {
17223
+ fireOnInputChanged(txt.value);
17224
+ }
17218
17225
  }
17219
17226
 
17220
17227
  /// <function container="Fit.Controls.DropDown" name="GetInputValue" access="public" returns="string">
@@ -17254,6 +17261,11 @@ Fit.Controls.DropDown = function(ctlId)
17254
17261
  if (Fit._internal.DropDown.Current !== null && Fit._internal.DropDown.Current !== me)
17255
17262
  Fit._internal.DropDown.Current.CloseDropDown();
17256
17263
 
17264
+ if (txtActive === txtPrimary && me.GetInputValue() === "")
17265
+ {
17266
+ me._internal.UndoClearInputForSearch();
17267
+ }
17268
+
17257
17269
  // Do this before displaying drop down to prevent dropdown with position:absolute
17258
17270
  // from changing height of document which may cause page to temporarily scroll, hence
17259
17271
  // result in incorrect measurement of control position in optimizeDropDownPosition().
@@ -17434,28 +17446,54 @@ Fit.Controls.DropDown = function(ctlId)
17434
17446
 
17435
17447
  this._internal = (this._internal ? this._internal : {});
17436
17448
 
17437
- // Clear input field without firing OnInputChanged, and make placeholder appear
17438
- this._internal.ClearInputAndShowPlaceholder = function(forceFocusInput)
17449
+ this._internal.ClearInputForSearch = function()
17439
17450
  {
17440
- Fit.Validation.ExpectBoolean(forceFocusInput, true);
17451
+ if (me.TextSelectionMode() === true)
17452
+ {
17453
+ forceFocusInput(txtPrimary);
17454
+ txtPrimary.value = "";
17455
+ updatePlaceholder(true);
17456
+ }
17457
+ else
17458
+ {
17459
+ forceFocusInput(txtPrimary);
17460
+ me.ClearInput();
17461
+ setInputEditing(txtPrimary, true);
17462
+ }
17441
17463
 
17442
- txtPrimary.value = "";
17443
- updatePlaceholder(true);
17464
+ // If DropDown is in Visual Selection Mode, the search field is now displayed
17465
+ // on a separate "line" (see code above where setInputEditing(..) is called).
17466
+ // When that input field lose focus, it will immediately return to its normal
17467
+ // state. This results in the control's height changing which in turn results
17468
+ // in the pulldown menu moving up. So if a user clicks an item in the pulldown
17469
+ // menu, the input lose focus, the position of the pulldown menu changes, and
17470
+ // nothing happens from the click because the picker uses a traditional onclick
17471
+ // event to register interactions, which doesn't fire unless the mouse button is released
17472
+ // on the same object it was pressed down on. We avoid this by closing the control.
17473
+ // We close it in both Text Selection Mode and Visual Selection Mode for consistency.
17474
+ me.CloseDropDown();
17475
+ }
17444
17476
 
17445
- if (forceFocusInput)
17477
+ this._internal.UndoClearInputForSearch = function()
17478
+ {
17479
+ if (me.TextSelectionMode() === true)
17446
17480
  {
17447
- // By default focus is never assigned to input on mobile if user opened the
17448
- // DropDown by clicking the arrow icon. ForceFocusInput allows us to ignore this
17449
- // aspect. On desktop the input field always remains focused as it automatically
17450
- // steals back focus immediately after interacting with a picker control. See
17451
- // picker.OnFocusIn handler registered in SetPicker(..)
17452
- var orgFocusInputOnMobile = focusInputOnMobile;
17453
- focusInputOnMobile = true;
17454
- focusInput(txtActive);
17455
- focusInputOnMobile = orgFocusInputOnMobile;
17481
+ updateTextSelection(); // Also removes placeholder by calling updatePlaceholder(true)
17482
+ }
17483
+ else
17484
+ {
17485
+ me.ClearInput();
17486
+ setInputEditing(txtPrimary, false);
17456
17487
  }
17457
17488
  }
17458
17489
 
17490
+ // Focus input field on mobile and keep it focused, even if DropDown was opened using arrow icon
17491
+ this._internal.ForceFocusMobile = function()
17492
+ {
17493
+ focusInputOnMobile = true;
17494
+ focusInput(txtPrimary);
17495
+ }
17496
+
17459
17497
  // ============================================
17460
17498
  // Private
17461
17499
  // ============================================
@@ -17492,9 +17530,7 @@ Fit.Controls.DropDown = function(ctlId)
17492
17530
  prevValue = txt.value;
17493
17531
  var pastedValue = txt.value;
17494
17532
 
17495
- Fit.Dom.Data(txt.parentElement, "editing", "true");
17496
- Fit.Dom.Data(txt, "editing", "true");
17497
- me._internal.Repaint();
17533
+ setInputEditing(txt, true);
17498
17534
 
17499
17535
  if (fireOnPaste(txt.value) === true)
17500
17536
  {
@@ -17574,9 +17610,7 @@ Fit.Controls.DropDown = function(ctlId)
17574
17610
 
17575
17611
  if (txt.value === "")
17576
17612
  {
17577
- Fit.Dom.Data(txt.parentElement, "editing", null);
17578
- Fit.Dom.Data(txt, "editing", null);
17579
- me._internal.Repaint();
17613
+ setInputEditing(txt, false);
17580
17614
  }
17581
17615
  }
17582
17616
 
@@ -17707,6 +17741,11 @@ Fit.Controls.DropDown = function(ctlId)
17707
17741
 
17708
17742
  if (txt.value.length === 0)
17709
17743
  {
17744
+ if (txt === txtPrimary)
17745
+ {
17746
+ me._internal.UndoClearInputForSearch();
17747
+ }
17748
+
17710
17749
  if (Fit.Browser.GetInfo().Name === "MSIE")
17711
17750
  Fit.Events.PreventDefault(ev); // Do not navigate back on IE when backspace is pressed within input being removed
17712
17751
 
@@ -17776,9 +17815,7 @@ Fit.Controls.DropDown = function(ctlId)
17776
17815
  {
17777
17816
  updatePlaceholder(true, true); // Make sure placeholder is removed immediately on keystroke
17778
17817
 
17779
- Fit.Dom.Data(txt.parentElement, "editing", "true");
17780
- Fit.Dom.Data(txt, "editing", "true");
17781
- me._internal.Repaint();
17818
+ setInputEditing(txt, true);
17782
17819
  }
17783
17820
 
17784
17821
  txt.onkeyup = function(e) // Fires only once when a key is released (unless suppressed in OnKeyDown)
@@ -17895,6 +17932,44 @@ Fit.Controls.DropDown = function(ctlId)
17895
17932
  txtActive.focus(); // Notice: Input field's onfocus handler will move focus to txtPrimary if this is the last selection's right side input field - on mobile it might redirect focus to the arrow icon to avoid bringing up the virtual keyboard
17896
17933
  }
17897
17934
 
17935
+ function forceFocusInput(input)
17936
+ {
17937
+ Fit.Validation.ExpectInstance(input, HTMLInputElement);
17938
+
17939
+ // By default focus is never assigned to input on mobile if user opened the
17940
+ // DropDown by clicking the arrow icon. ForceFocusInput allows us to ignore this
17941
+ // aspect. On desktop the input field always remains focused as it automatically
17942
+ // steals back focus immediately after interacting with a picker control. See
17943
+ // picker.OnFocusIn handler registered in SetPicker(..)
17944
+ var orgFocusInputOnMobile = focusInputOnMobile;
17945
+ focusInputOnMobile = true;
17946
+ focusInput(input);
17947
+ focusInputOnMobile = orgFocusInputOnMobile;
17948
+ }
17949
+
17950
+ function setInputEditing(input, val, keepStateOnParent)
17951
+ {
17952
+ Fit.Validation.ExpectInstance(input, HTMLInputElement);
17953
+ Fit.Validation.ExpectBoolean(val);
17954
+ Fit.Validation.ExpectBoolean(keepStateOnParent, true);
17955
+
17956
+ if (keepStateOnParent !== true)
17957
+ {
17958
+ Fit.Dom.Data(input.parentElement, "editing", val === true ? "true" : null);
17959
+ }
17960
+
17961
+ Fit.Dom.Data(input, "editing", val === true ? "true" : null);
17962
+
17963
+ if (input === txtPrimary)
17964
+ {
17965
+ // DropDown's placeholder is only displayed when no items are selected.
17966
+ // Therefore, use native placeholder for input if items are selected.
17967
+ txtPrimary.placeholder = val === true && me.GetSelections().length > 0 ? me.Placeholder() : "";
17968
+ }
17969
+
17970
+ me._internal.Repaint();
17971
+ }
17972
+
17898
17973
  function clearAllInputsButActive()
17899
17974
  {
17900
17975
  var inputs = itemContainer.getElementsByTagName("input");
@@ -17904,9 +17979,16 @@ Fit.Controls.DropDown = function(ctlId)
17904
17979
  if (input === txtActive)
17905
17980
  return;
17906
17981
 
17907
- if ((txtActive.parentElement === itemContainer && input === txtPrimary) || (txtActive.parentElement !== itemContainer && Fit.Dom.Contained(txtActive.parentElement, input) === false))
17908
- Fit.Dom.Data(input.parentElement, "editing", null);
17909
- Fit.Dom.Data(input, "editing", null);
17982
+ if (txtActive.parentElement === input.parentElement)
17983
+ {
17984
+ // Input is contained in a selected object whose other input is txtActive.
17985
+ // Do not remove editing state from parent element in this case - keep it!
17986
+ setInputEditing(input, false, true);
17987
+ }
17988
+ else
17989
+ {
17990
+ setInputEditing(input, false);
17991
+ }
17910
17992
 
17911
17993
  me.ClearInput(input);
17912
17994
  });
@@ -18449,7 +18531,7 @@ Fit.Controls.DropDown = function(ctlId)
18449
18531
  Fit.Dom.SetCaretPosition(txtPrimary, 0);
18450
18532
  }
18451
18533
 
18452
- // Remove placeholder in case it was added using this._internal.ClearInputAndShowPlaceholder()
18534
+ // Remove placeholder in case it was added using this._internal.ClearInputForSearch()
18453
18535
 
18454
18536
  updatePlaceholder(true);
18455
18537
 
@@ -19093,6 +19175,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19093
19175
  var hideLinesForFlatData = true;
19094
19176
  var dataRequested = false; // Flag indicating whether TreeView data has been requested or not - determines whether a call to ensureTreeViewData() actually loads data or not
19095
19177
  var dataLoading = false; // Flag indicating whether TreeView data is currently being loaded by WSDropDown internals (awaiting response) - will not be True when user expand nodes to load children, or when invoking e.g. dd.GetTreeView.Reload()
19178
+ var nodesPopulated = false; // Flag indicating whether TreeView root nodes have been populated - contrary to dataLoading this flag is set when a potentially partial portion of the data has been loaded
19096
19179
  var requestCount = 0; // Counter to keep track of nodes for which data is currently being loaded, no matter how it was being loaded (via WSDropDown internals, programmatically on WSTreeView from external code, or by user expanding nodes)
19097
19180
  var onDataLoadedCallback = [];
19098
19181
  var suppressTreeOnOpen = false;
@@ -19102,6 +19185,10 @@ Fit.Controls.WSDropDown = function(ctlId)
19102
19185
  var autoUpdatedSelections = null; // Cached result from AutoUpdateSelected: [{ Title:string, Value:string, Exists:boolean }, ...]
19103
19186
  var useActionMenu = false;
19104
19187
  var useActionMenuForced = false;
19188
+ var useActionMenuAfterLoad = true;
19189
+ var treeViewEnabled = true;
19190
+ var orgPlaceholder = this.Placeholder;
19191
+ var customPlaceholderSet = false;
19105
19192
  var translations = null;
19106
19193
 
19107
19194
  var onRequestHandlers = [];
@@ -19126,7 +19213,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19126
19213
 
19127
19214
  // Create ListView
19128
19215
 
19129
- list = new Fit.Controls.WSListView(ctlId + "__WSListView");
19216
+ list = new Fit.Controls.WSListView(me.GetId() + "__WSListView");
19130
19217
  list.OnRequest(function(sender, eventArgs)
19131
19218
  {
19132
19219
  if (fireEventHandlers(onRequestHandlers, list, eventArgs) === false)
@@ -19178,7 +19265,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19178
19265
 
19179
19266
  // Create TreeView
19180
19267
 
19181
- tree = new Fit.Controls.WSTreeView(ctlId + "__WSTreeView");
19268
+ tree = new Fit.Controls.WSTreeView(me.GetId() + "__WSTreeView");
19182
19269
  tree.Selectable(true); // Make nodes selectable by default when added
19183
19270
  tree.Width(100, "%");
19184
19271
  //tree.Lines(true); // DISABLED - lines do not scale with font size
@@ -19218,22 +19305,6 @@ Fit.Controls.WSDropDown = function(ctlId)
19218
19305
  {
19219
19306
  fireOnDataLoaded();
19220
19307
  }
19221
-
19222
- // If no data is returned and DropDown is in TextSelectionMode, the user will
19223
- // not have an easy way to remove objects from the DropDown, unless SelectionModeToggle
19224
- // is true. Therefore we allow for items to be removed using an action menu.
19225
- // EDIT: Now displays action menu in both Visual and Text Selection Mode for consistency.
19226
-
19227
- if (useActionMenuForced === false)
19228
- {
19229
- useActionMenu = eventArgs.Children.length === 0;
19230
- }
19231
-
19232
- if (/*me.TextSelectionMode() === true &&*/ useActionMenu === true)
19233
- {
19234
- updateActionMenu();
19235
- me.SetPicker(actionMenu);
19236
- }
19237
19308
  }
19238
19309
  });
19239
19310
  tree.OnAbort(function(sender, eventArgs)
@@ -19254,6 +19325,30 @@ Fit.Controls.WSDropDown = function(ctlId)
19254
19325
  });
19255
19326
  tree.OnPopulated(function(sender, eventArgs)
19256
19327
  {
19328
+ nodesPopulated = true;
19329
+
19330
+ // If no data is returned and DropDown is in TextSelectionMode, the user will
19331
+ // not be able to remove objects from the DropDown, unless SelectionModeToggle
19332
+ // is true. Therefore we allow for items to be removed using an action menu.
19333
+ // EDIT: Now displays action menu in both Visual and Text Selection Mode for consistency.
19334
+
19335
+ if (useActionMenuForced === false)
19336
+ {
19337
+ useActionMenu = tree.GetChildren().length === 0;
19338
+ }
19339
+
19340
+ if (/*me.TextSelectionMode() === true &&*/ useActionMenu === true)
19341
+ {
19342
+ updateActionMenu();
19343
+
19344
+ if (useActionMenuAfterLoad === true || tree.GetChildren().length === 0)
19345
+ {
19346
+ me.SetPicker(actionMenu);
19347
+ }
19348
+ }
19349
+
19350
+ // Helper lines
19351
+
19257
19352
  if (hideLinesForFlatData === true && tree.Lines() === true) // Lines are off by default but might have been enabled like so: dd.GetTreeView().Lines(true)
19258
19353
  {
19259
19354
  // Disable helper lines if no children are contained
@@ -19328,16 +19423,21 @@ Fit.Controls.WSDropDown = function(ctlId)
19328
19423
 
19329
19424
  var skipUpdateActionMenuOnChange = false;
19330
19425
 
19331
- actionMenu = new Fit.Controls.ListView(ctlId + "__ActionsListView");
19426
+ actionMenu = new Fit.Controls.ListView(me.GetId() + "__ActionsListView");
19332
19427
  actionMenu.OnSelect(function(sender, item) // Using OnSelect instead of OnItemSelectionChanging since DropDown fires OnItemSelectionChanging when selection is changed, which would result in OnItemSelectionChanging being executed multiple times
19333
19428
  {
19334
19429
  if (item.Value === "SearchMore")
19335
19430
  {
19336
- me._internal.ClearInputAndShowPlaceholder(true); // NOTICE: TextSelectionMode only - Visual Selection Mode cannot be temporarily cleared to display the place holder
19431
+ me._internal.ClearInputForSearch();
19337
19432
  }
19338
19433
  else if (item.Value === "ShowAll")
19339
19434
  {
19435
+ me._internal.UndoClearInputForSearch(); // In case user first picked SearchMore, changed their mind, and then selected ShowAll
19436
+
19437
+ useActionMenuAfterLoad = false;
19438
+
19340
19439
  me.SetPicker(tree);
19440
+ ensureTreeViewData();
19341
19441
  }
19342
19442
  else if (item.Value === "RemoveAll")
19343
19443
  {
@@ -19430,14 +19530,32 @@ Fit.Controls.WSDropDown = function(ctlId)
19430
19530
  return;
19431
19531
  }
19432
19532
 
19433
- if (useActionMenu === true)
19533
+ // Do not show action menu if the only option available is ShowAll.
19534
+ // In this case the user will not be able to select SeachMore, and
19535
+ // there is no selected items that can be removed from the control.
19536
+ // In this case we ignore useActionMenu === true, even when useActionMenuForced is true.
19537
+ var onlyTheShowAllOptionIsDisplayedInActionMenu = actionMenu.GetItems().length === 1 && actionMenu.HasItem("ShowAll") === true;
19538
+
19539
+ if (useActionMenu === true && onlyTheShowAllOptionIsDisplayedInActionMenu === false)
19434
19540
  {
19435
19541
  me.SetPicker(actionMenu);
19436
19542
  }
19437
19543
  else
19438
19544
  {
19439
- me.SetPicker(tree);
19440
- ensureTreeViewData();
19545
+ if (onlyTheShowAllOptionIsDisplayedInActionMenu === true)
19546
+ {
19547
+ useActionMenuAfterLoad = false;
19548
+ }
19549
+
19550
+ if (treeViewEnabled === true)
19551
+ {
19552
+ me.SetPicker(tree);
19553
+ ensureTreeViewData();
19554
+ }
19555
+ else
19556
+ {
19557
+ list.RemoveItems(); // Do not show previous search results again
19558
+ }
19441
19559
  }
19442
19560
  });
19443
19561
 
@@ -19506,6 +19624,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19506
19624
  }
19507
19625
 
19508
19626
  dataLoading = true;
19627
+ nodesPopulated = false;
19509
19628
 
19510
19629
  var ensure = function()
19511
19630
  {
@@ -19651,10 +19770,6 @@ Fit.Controls.WSDropDown = function(ctlId)
19651
19770
  }
19652
19771
  }
19653
19772
 
19654
- /// <function container="Fit.Controls.WSDropDown" name="MultiSelectionMode" access="public" returns="boolean">
19655
- /// <description> Get/set value indicating whether control allows for multiple selections simultaneously </description>
19656
- /// <param name="val" type="boolean" default="undefined"> If defined, True enables support for multiple selections, False disables it </param>
19657
- /// </function>
19658
19773
  this.MultiSelectionMode = Fit.Core.CreateOverride(this.MultiSelectionMode, function(val)
19659
19774
  {
19660
19775
  Fit.Validation.ExpectBoolean(val, true);
@@ -19667,6 +19782,105 @@ Fit.Controls.WSDropDown = function(ctlId)
19667
19782
  return base(val);
19668
19783
  });
19669
19784
 
19785
+ this.InputEnabled = Fit.Core.CreateOverride(this.InputEnabled, function(val)
19786
+ {
19787
+ Fit.Validation.ExpectBoolean(val, true);
19788
+
19789
+ if (Fit.Validation.IsSet(val) === true && base() !== val)
19790
+ {
19791
+ base(val);
19792
+ localize(); // Add/remove placeholder depending on whether input is enabled or not - also calls updateActionMenu() which will make sure SearchMore action is added/removed depending on whether input is enabled or not
19793
+
19794
+ if (val === false && me.GetPicker() === list)
19795
+ {
19796
+ me.SetPicker(null); // Which picker to use is decided in the OnOpen handler
19797
+ }
19798
+ }
19799
+
19800
+ return base();
19801
+ });
19802
+
19803
+ /// <function container="Fit.Controls.WSDropDown" name="TreeViewEnabled" access="public" returns="boolean">
19804
+ /// <description> Get/set value indicating whether TreeView control is enabled or not </description>
19805
+ /// <param name="val" type="boolean" default="undefined"> If defined, True enables TreeView (default), False disables it </param>
19806
+ /// </function>
19807
+ this.TreeViewEnabled = function(val)
19808
+ {
19809
+ Fit.Validation.ExpectBoolean(val, true);
19810
+
19811
+ if (Fit.Validation.IsSet(val) === true && val !== treeViewEnabled)
19812
+ {
19813
+ treeViewEnabled = val;
19814
+
19815
+ if (useActionMenuForced === false)
19816
+ {
19817
+ // Use action menu if there is no data to display
19818
+
19819
+ if (val === true)
19820
+ {
19821
+ useActionMenu = nodesPopulated === false || tree.GetChildren().length === 0;
19822
+ }
19823
+ else
19824
+ {
19825
+ useActionMenu = true; // User must search to retrieve available options
19826
+ }
19827
+ }
19828
+
19829
+ if (val === false && me.GetPicker() === tree)
19830
+ {
19831
+ me.SetPicker(null); // Which picker to use is decided in the OnOpen handler
19832
+ }
19833
+
19834
+ updateActionMenu(); // Update action menu to have ShowAll action added/removed depending on whether TreeView is enabled or not
19835
+ }
19836
+
19837
+ return treeViewEnabled;
19838
+ }
19839
+
19840
+ /// <function container="Fit.Controls.WSDropDown" name="ListViewEnabled" access="public" returns="boolean">
19841
+ /// <description>
19842
+ /// Get/set flag indicating whether searchable ListView is enabled or not.
19843
+ /// The value provided also determines the value for InputEnabled and vice versa.
19844
+ /// </description>
19845
+ /// <param name="val" type="boolean" default="undefined"> If defined, True enables ListView and search capability (default), False disables it </param>
19846
+ /// </function>
19847
+ this.ListViewEnabled = function(val)
19848
+ {
19849
+ Fit.Validation.ExpectBoolean(val, true);
19850
+ return me.InputEnabled(val);
19851
+ }
19852
+
19853
+ this.Placeholder = function(val)
19854
+ {
19855
+ Fit.Validation.ExpectString(val, true);
19856
+
19857
+ customPlaceholderSet = true;
19858
+ return orgPlaceholder(val);
19859
+ }
19860
+
19861
+ this.OpenDropDown = Fit.Core.CreateOverride(this.OpenDropDown, function()
19862
+ {
19863
+ if (me.InputEnabled() === true && me.GetInputValue() === "" && me.GetSelections().length === 0 && treeViewEnabled === false)
19864
+ {
19865
+ // Do not open DropDown - it will only contain "Search for more options"
19866
+ // when no items are currently selected and TreeView is disabled, and no
19867
+ // search value has been entered yet.
19868
+ // The control will display "Search.." (or a custom placeholder), making it
19869
+ // obvious what the user need to do to get data - no need to display the action menu.
19870
+
19871
+ if (Fit.Browser.GetInfo().IsMobile === true)
19872
+ {
19873
+ // Focus input on mobile, even if DropDown was opened using
19874
+ // the arrow icon - this will bring up the virtual keyboard.
19875
+ this._internal.ForceFocusMobile();
19876
+ }
19877
+
19878
+ return;
19879
+ }
19880
+
19881
+ base();
19882
+ });
19883
+
19670
19884
  /// <function container="Fit.Controls.WSDropDown" name="GetListView" access="public" returns="Fit.Controls.WSListView">
19671
19885
  /// <description> Get WSListView control used to display data in a flat list view </description>
19672
19886
  /// </function>
@@ -19684,7 +19898,21 @@ Fit.Controls.WSDropDown = function(ctlId)
19684
19898
  }
19685
19899
 
19686
19900
  /// <function container="Fit.Controls.WSDropDown" name="UseActionMenu" access="public">
19687
- /// <description> Get/set value indicating whether control uses the built-in action menu to ease addition and removal of items </description>
19901
+ /// <description>
19902
+ /// Get/set value indicating whether control uses the built-in action menu to ease addition and removal of items.
19903
+ /// If this property is not explicitly set, it will automatically be changed by the control depending on data and other settings.
19904
+ /// The action menu will be enabled if TreeViewEnabled is set to False, as it would otherwise not show anything unless the user
19905
+ /// enters a search value. If TreeViewEnabled is True but no data is provided to the TreeView control upon request, the action menu
19906
+ /// is also enabled.
19907
+ /// If the control does not have any selections, InputEnabled (or its alias ListViewEnabled) is True, and TreeViewEnabled is False,
19908
+ /// no picker will be displayed since the action menu would only display the &quot;Search for options&quot; item - but it should already
19909
+ /// be obvious to the user that searching is required due to the placeholder displaying &quot;Search..&quot; by default.
19910
+ /// Likewise, if TreeViewEnabled is True and InputEnabled (or its alias ListViewEnabled) is False, and no selections are made,
19911
+ /// the action menu would only display &quot;Show available options&quot;. In this case the TreeView will be displayed instead,
19912
+ /// even if UseActionMenu has explicitely been set to True.
19913
+ /// The behaviour described is in place to make sure the action menu is only displayed when it makes sense, since it introduces
19914
+ /// and extra step (click) required by the user to access data.
19915
+ /// </description>
19688
19916
  /// <param name="val" type="boolean" default="undefined"> If defined, True enables the action menu, False disables it </param>
19689
19917
  /// </function>
19690
19918
  this.UseActionMenu = function(val)
@@ -19734,7 +19962,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19734
19962
 
19735
19963
  Fit.Internationalization.RemoveOnLocaleChanged(localize);
19736
19964
 
19737
- me = list = tree = actionMenu = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = useActionMenu = useActionMenuForced = translations = onRequestHandlers = onResponseHandlers = null;
19965
+ me = list = tree = actionMenu = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = nodesPopulated = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = useActionMenu = useActionMenuForced = useActionMenuAfterLoad = treeViewEnabled = orgPlaceholder = customPlaceholderSet = translations = onRequestHandlers = onResponseHandlers = null;
19738
19966
 
19739
19967
  base();
19740
19968
  });
@@ -19861,6 +20089,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19861
20089
  if (dataRequested === false)
19862
20090
  {
19863
20091
  dataLoading = true;
20092
+ nodesPopulated = false;
19864
20093
 
19865
20094
  tree.Reload(true, function(sender)
19866
20095
  {
@@ -19932,20 +20161,30 @@ Fit.Controls.WSDropDown = function(ctlId)
19932
20161
  return;
19933
20162
  }
19934
20163
 
19935
- var searchIcon = "<span class='FitUiControlDropDownActionMenuItem FitUiControlDropDownActionMenuItemSearch fa fa-search'></span> ";
19936
- var showAllIcon = "<span class='FitUiControlDropDownActionMenuItem FitUiControlDropDownActionMenuItemShowAll fa fa-sitemap'></span> ";
19937
- var delIcon = "<span class='FitUiControlDropDownActionMenuItem FitUiControlDropDownActionMenuItemDelete fa fa-times'></span> ";
20164
+ var searchIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconSearch fa fa-search'></span> ";
20165
+ var showAllIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconShowAll fa fa-sitemap'></span> ";
20166
+ var delIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconDelete fa fa-times'></span> ";
19938
20167
 
19939
20168
  var selectedItems = me.GetSelections();
19940
20169
  var addRemoveAll = selectedItems.length > 1;
19941
20170
 
19942
20171
  actionMenu.RemoveItems();
19943
20172
 
19944
- actionMenu.AddItem(searchIcon + translations.SearchMore, "SearchMore");
20173
+ if (me.InputEnabled() === true)
20174
+ {
20175
+ actionMenu.AddItem(searchIcon + translations.SearchMore, "SearchMore");
20176
+ }
19945
20177
 
19946
- if (dataRequested === false || tree.GetChildren().length > 0)
20178
+ if (treeViewEnabled === true)
19947
20179
  {
19948
- actionMenu.AddItem(showAllIcon + translations.ShowAllOptions, "ShowAll");
20180
+ if (nodesPopulated === false || tree.GetChildren().length > 0)
20181
+ {
20182
+ actionMenu.AddItem(showAllIcon + translations.ShowAllOptions, "ShowAll");
20183
+ }
20184
+ else //if (nodesPopulated === true && tree.GetChildren().length === 0)
20185
+ {
20186
+ actionMenu.AddItem(showAllIcon + "<i>" + translations.NoneAvailable + ": " + translations.ShowAllOptions + "</i>", "ShowAllNoneFound");
20187
+ }
19949
20188
  }
19950
20189
 
19951
20190
  if (addRemoveAll === true)
@@ -19965,6 +20204,11 @@ Fit.Controls.WSDropDown = function(ctlId)
19965
20204
  translations = locale.Translations;
19966
20205
 
19967
20206
  updateActionMenu();
20207
+
20208
+ if (customPlaceholderSet === false)
20209
+ {
20210
+ orgPlaceholder(me.InputEnabled() === true ? translations.Search : "");
20211
+ }
19968
20212
  }
19969
20213
 
19970
20214
  function onDataLoaded(cb)
@@ -20051,10 +20295,13 @@ Fit.Controls.WSDropDown = function(ctlId)
20051
20295
  {
20052
20296
  InvalidSelection : "Invalid selection",
20053
20297
 
20054
- SearchMore : "Search for more options",
20055
- ShowAllOptions : "Show all available options",
20298
+ // WSDropDown
20299
+ Search : "Search..",
20300
+ SearchMore : "Search for options",
20301
+ ShowAllOptions : "Show available options",
20056
20302
  RemoveAll : "Remove all selected",
20057
- Remove : "Remove"
20303
+ Remove : "Remove",
20304
+ NoneAvailable : "The list is empty"
20058
20305
  }
20059
20306
  },
20060
20307
  "da":
@@ -20063,10 +20310,13 @@ Fit.Controls.WSDropDown = function(ctlId)
20063
20310
  {
20064
20311
  InvalidSelection : "Ugyldigt valg",
20065
20312
 
20066
- SearchMore : "Søg efter flere valgmuligheder",
20067
- ShowAllOptions : "Vis alle tilgængelige valgmuligheder",
20313
+ // WSDropDown
20314
+ Search : "Søg..",
20315
+ SearchMore : "Søg efter valgmuligheder",
20316
+ ShowAllOptions : "Vis tilgængelige valgmuligheder",
20068
20317
  RemoveAll : "Fjern alle valgte",
20069
- Remove : "Fjern"
20318
+ Remove : "Fjern",
20319
+ NoneAvailable : "Listen er tom"
20070
20320
  }
20071
20321
  },
20072
20322
  "de":
@@ -20075,10 +20325,13 @@ Fit.Controls.WSDropDown = function(ctlId)
20075
20325
  {
20076
20326
  InvalidSelection : "Ungültige Auswahl",
20077
20327
 
20078
- SearchMore : "Nach weiteren Optionen suchen",
20079
- ShowAllOptions : "Alle verfügbaren Optionen anzeigen",
20328
+ // WSDropDown
20329
+ Search : "Suchen..",
20330
+ SearchMore : "Nach Optionen suchen",
20331
+ ShowAllOptions : "Verfügbare Optionen anzeigen",
20080
20332
  RemoveAll : "Alle ausgewählten entfernen",
20081
- Remove : "Entfernen"
20333
+ Remove : "Entfernen",
20334
+ NoneAvailable : "Die Liste ist leer"
20082
20335
  }
20083
20336
  }
20084
20337
  }