fit-ui 2.5.1 → 2.5.2

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.js CHANGED
@@ -648,7 +648,7 @@ Fit._internal =
648
648
  {
649
649
  Core:
650
650
  {
651
- VersionInfo: { Major: 2, Minor: 5, Patch: 1 } // 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: 2 } // 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;
17204
17202
 
17205
- txtActive.value = "";
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.
17206
17207
 
17207
- Fit.Dom.Data(txtActive.parentElement, "editing", val !== "" ? "true" : null);
17208
- Fit.Dom.Data(txtActive, "editing", val !== "" ? "true" : null);
17209
- me._internal.Repaint();
17208
+ // Clear active input field in case it has a value
17209
+ txtActive.value = "";
17210
+ setInputEditing(txtActive, false);
17210
17211
 
17211
- var txt = ((focusAssigned === true) ? txtActive : txtPrimary);
17212
+ txt = txtPrimary;
17213
+ txtActive = txtPrimary;
17214
+ }
17215
+
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,25 +17446,44 @@ 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
 
@@ -17492,9 +17523,7 @@ Fit.Controls.DropDown = function(ctlId)
17492
17523
  prevValue = txt.value;
17493
17524
  var pastedValue = txt.value;
17494
17525
 
17495
- Fit.Dom.Data(txt.parentElement, "editing", "true");
17496
- Fit.Dom.Data(txt, "editing", "true");
17497
- me._internal.Repaint();
17526
+ setInputEditing(txt, true);
17498
17527
 
17499
17528
  if (fireOnPaste(txt.value) === true)
17500
17529
  {
@@ -17574,9 +17603,7 @@ Fit.Controls.DropDown = function(ctlId)
17574
17603
 
17575
17604
  if (txt.value === "")
17576
17605
  {
17577
- Fit.Dom.Data(txt.parentElement, "editing", null);
17578
- Fit.Dom.Data(txt, "editing", null);
17579
- me._internal.Repaint();
17606
+ setInputEditing(txt, false);
17580
17607
  }
17581
17608
  }
17582
17609
 
@@ -17707,6 +17734,11 @@ Fit.Controls.DropDown = function(ctlId)
17707
17734
 
17708
17735
  if (txt.value.length === 0)
17709
17736
  {
17737
+ if (txt === txtPrimary)
17738
+ {
17739
+ me._internal.UndoClearInputForSearch();
17740
+ }
17741
+
17710
17742
  if (Fit.Browser.GetInfo().Name === "MSIE")
17711
17743
  Fit.Events.PreventDefault(ev); // Do not navigate back on IE when backspace is pressed within input being removed
17712
17744
 
@@ -17776,9 +17808,7 @@ Fit.Controls.DropDown = function(ctlId)
17776
17808
  {
17777
17809
  updatePlaceholder(true, true); // Make sure placeholder is removed immediately on keystroke
17778
17810
 
17779
- Fit.Dom.Data(txt.parentElement, "editing", "true");
17780
- Fit.Dom.Data(txt, "editing", "true");
17781
- me._internal.Repaint();
17811
+ setInputEditing(txt, true);
17782
17812
  }
17783
17813
 
17784
17814
  txt.onkeyup = function(e) // Fires only once when a key is released (unless suppressed in OnKeyDown)
@@ -17895,6 +17925,44 @@ Fit.Controls.DropDown = function(ctlId)
17895
17925
  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
17926
  }
17897
17927
 
17928
+ function forceFocusInput(input)
17929
+ {
17930
+ Fit.Validation.ExpectInstance(input, HTMLInputElement);
17931
+
17932
+ // By default focus is never assigned to input on mobile if user opened the
17933
+ // DropDown by clicking the arrow icon. ForceFocusInput allows us to ignore this
17934
+ // aspect. On desktop the input field always remains focused as it automatically
17935
+ // steals back focus immediately after interacting with a picker control. See
17936
+ // picker.OnFocusIn handler registered in SetPicker(..)
17937
+ var orgFocusInputOnMobile = focusInputOnMobile;
17938
+ focusInputOnMobile = true;
17939
+ focusInput(input);
17940
+ focusInputOnMobile = orgFocusInputOnMobile;
17941
+ }
17942
+
17943
+ function setInputEditing(input, val, keepStateOnParent)
17944
+ {
17945
+ Fit.Validation.ExpectInstance(input, HTMLInputElement);
17946
+ Fit.Validation.ExpectBoolean(val);
17947
+ Fit.Validation.ExpectBoolean(keepStateOnParent, true);
17948
+
17949
+ if (keepStateOnParent !== true)
17950
+ {
17951
+ Fit.Dom.Data(input.parentElement, "editing", val === true ? "true" : null);
17952
+ }
17953
+
17954
+ Fit.Dom.Data(input, "editing", val === true ? "true" : null);
17955
+
17956
+ if (input === txtPrimary)
17957
+ {
17958
+ // DropDown's placeholder is only displayed when no items are selected.
17959
+ // Therefore, use native placeholder for input if items are selected.
17960
+ txtPrimary.placeholder = val === true && me.GetSelections().length > 0 ? me.Placeholder() : "";
17961
+ }
17962
+
17963
+ me._internal.Repaint();
17964
+ }
17965
+
17898
17966
  function clearAllInputsButActive()
17899
17967
  {
17900
17968
  var inputs = itemContainer.getElementsByTagName("input");
@@ -17904,9 +17972,16 @@ Fit.Controls.DropDown = function(ctlId)
17904
17972
  if (input === txtActive)
17905
17973
  return;
17906
17974
 
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);
17975
+ if (txtActive.parentElement === input.parentElement)
17976
+ {
17977
+ // Input is contained in a selected object whose other input is txtActive.
17978
+ // Do not remove editing state from parent element in this case - keep it!
17979
+ setInputEditing(input, false, true);
17980
+ }
17981
+ else
17982
+ {
17983
+ setInputEditing(input, false);
17984
+ }
17910
17985
 
17911
17986
  me.ClearInput(input);
17912
17987
  });
@@ -18449,7 +18524,7 @@ Fit.Controls.DropDown = function(ctlId)
18449
18524
  Fit.Dom.SetCaretPosition(txtPrimary, 0);
18450
18525
  }
18451
18526
 
18452
- // Remove placeholder in case it was added using this._internal.ClearInputAndShowPlaceholder()
18527
+ // Remove placeholder in case it was added using this._internal.ClearInputForSearch()
18453
18528
 
18454
18529
  updatePlaceholder(true);
18455
18530
 
@@ -19093,6 +19168,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19093
19168
  var hideLinesForFlatData = true;
19094
19169
  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
19170
  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()
19171
+ 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
19172
  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
19173
  var onDataLoadedCallback = [];
19098
19174
  var suppressTreeOnOpen = false;
@@ -19102,6 +19178,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19102
19178
  var autoUpdatedSelections = null; // Cached result from AutoUpdateSelected: [{ Title:string, Value:string, Exists:boolean }, ...]
19103
19179
  var useActionMenu = false;
19104
19180
  var useActionMenuForced = false;
19181
+ var useActionMenuAfterLoad = true;
19105
19182
  var translations = null;
19106
19183
 
19107
19184
  var onRequestHandlers = [];
@@ -19218,22 +19295,6 @@ Fit.Controls.WSDropDown = function(ctlId)
19218
19295
  {
19219
19296
  fireOnDataLoaded();
19220
19297
  }
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
19298
  }
19238
19299
  });
19239
19300
  tree.OnAbort(function(sender, eventArgs)
@@ -19254,6 +19315,30 @@ Fit.Controls.WSDropDown = function(ctlId)
19254
19315
  });
19255
19316
  tree.OnPopulated(function(sender, eventArgs)
19256
19317
  {
19318
+ nodesPopulated = true;
19319
+
19320
+ // If no data is returned and DropDown is in TextSelectionMode, the user will
19321
+ // not be able to remove objects from the DropDown, unless SelectionModeToggle
19322
+ // is true. Therefore we allow for items to be removed using an action menu.
19323
+ // EDIT: Now displays action menu in both Visual and Text Selection Mode for consistency.
19324
+
19325
+ if (useActionMenuForced === false)
19326
+ {
19327
+ useActionMenu = tree.GetChildren().length === 0;
19328
+ }
19329
+
19330
+ if (/*me.TextSelectionMode() === true &&*/ useActionMenu === true)
19331
+ {
19332
+ updateActionMenu();
19333
+
19334
+ if (useActionMenuAfterLoad === true || tree.GetChildren().length === 0)
19335
+ {
19336
+ me.SetPicker(actionMenu);
19337
+ }
19338
+ }
19339
+
19340
+ // Helper lines
19341
+
19257
19342
  if (hideLinesForFlatData === true && tree.Lines() === true) // Lines are off by default but might have been enabled like so: dd.GetTreeView().Lines(true)
19258
19343
  {
19259
19344
  // Disable helper lines if no children are contained
@@ -19333,11 +19418,16 @@ Fit.Controls.WSDropDown = function(ctlId)
19333
19418
  {
19334
19419
  if (item.Value === "SearchMore")
19335
19420
  {
19336
- me._internal.ClearInputAndShowPlaceholder(true); // NOTICE: TextSelectionMode only - Visual Selection Mode cannot be temporarily cleared to display the place holder
19421
+ me._internal.ClearInputForSearch();
19337
19422
  }
19338
19423
  else if (item.Value === "ShowAll")
19339
19424
  {
19425
+ me._internal.UndoClearInputForSearch(); // In case user first picked SearchMore, changed their mind, and then selected ShowAll
19426
+
19427
+ useActionMenuAfterLoad = false;
19428
+
19340
19429
  me.SetPicker(tree);
19430
+ ensureTreeViewData();
19341
19431
  }
19342
19432
  else if (item.Value === "RemoveAll")
19343
19433
  {
@@ -19430,12 +19520,22 @@ Fit.Controls.WSDropDown = function(ctlId)
19430
19520
  return;
19431
19521
  }
19432
19522
 
19433
- if (useActionMenu === true)
19523
+ // Do not show action menu if the only option available is ShowAll.
19524
+ // In this case the user will not be able to select SeachMore, and
19525
+ // there is no selected items that can be removed from the control.
19526
+ var onlyShowAllOptionDisplayedInActionMenu = actionMenu.GetItems().length === 1 && actionMenu.HasItem("ShowAll") === true;
19527
+
19528
+ if (useActionMenu === true && onlyShowAllOptionDisplayedInActionMenu === false)
19434
19529
  {
19435
19530
  me.SetPicker(actionMenu);
19436
19531
  }
19437
19532
  else
19438
19533
  {
19534
+ if (onlyShowAllOptionDisplayedInActionMenu === true)
19535
+ {
19536
+ useActionMenuAfterLoad = false;
19537
+ }
19538
+
19439
19539
  me.SetPicker(tree);
19440
19540
  ensureTreeViewData();
19441
19541
  }
@@ -19506,6 +19606,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19506
19606
  }
19507
19607
 
19508
19608
  dataLoading = true;
19609
+ nodesPopulated = false;
19509
19610
 
19510
19611
  var ensure = function()
19511
19612
  {
@@ -19651,10 +19752,6 @@ Fit.Controls.WSDropDown = function(ctlId)
19651
19752
  }
19652
19753
  }
19653
19754
 
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
19755
  this.MultiSelectionMode = Fit.Core.CreateOverride(this.MultiSelectionMode, function(val)
19659
19756
  {
19660
19757
  Fit.Validation.ExpectBoolean(val, true);
@@ -19667,6 +19764,19 @@ Fit.Controls.WSDropDown = function(ctlId)
19667
19764
  return base(val);
19668
19765
  });
19669
19766
 
19767
+ this.InputEnabled = Fit.Core.CreateOverride(this.InputEnabled, function(val)
19768
+ {
19769
+ Fit.Validation.ExpectBoolean(val, true);
19770
+
19771
+ if (Fit.Validation.IsSet(val) === true && base() !== val)
19772
+ {
19773
+ base(val);
19774
+ updateActionMenu(); // Update action menu to have SearchMore action added/removed depending on whether input is allowed or not
19775
+ }
19776
+
19777
+ return base();
19778
+ });
19779
+
19670
19780
  /// <function container="Fit.Controls.WSDropDown" name="GetListView" access="public" returns="Fit.Controls.WSListView">
19671
19781
  /// <description> Get WSListView control used to display data in a flat list view </description>
19672
19782
  /// </function>
@@ -19734,7 +19844,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19734
19844
 
19735
19845
  Fit.Internationalization.RemoveOnLocaleChanged(localize);
19736
19846
 
19737
- me = list = tree = actionMenu = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = useActionMenu = useActionMenuForced = translations = onRequestHandlers = onResponseHandlers = null;
19847
+ me = list = tree = actionMenu = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = nodesPopulated = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = useActionMenu = useActionMenuForced = useActionMenuAfterLoad = translations = onRequestHandlers = onResponseHandlers = null;
19738
19848
 
19739
19849
  base();
19740
19850
  });
@@ -19861,6 +19971,7 @@ Fit.Controls.WSDropDown = function(ctlId)
19861
19971
  if (dataRequested === false)
19862
19972
  {
19863
19973
  dataLoading = true;
19974
+ nodesPopulated = false;
19864
19975
 
19865
19976
  tree.Reload(true, function(sender)
19866
19977
  {
@@ -19941,12 +20052,19 @@ Fit.Controls.WSDropDown = function(ctlId)
19941
20052
 
19942
20053
  actionMenu.RemoveItems();
19943
20054
 
19944
- actionMenu.AddItem(searchIcon + translations.SearchMore, "SearchMore");
20055
+ if (me.InputEnabled() === true)
20056
+ {
20057
+ actionMenu.AddItem(searchIcon + translations.SearchMore, "SearchMore");
20058
+ }
19945
20059
 
19946
- if (dataRequested === false || tree.GetChildren().length > 0)
20060
+ if (nodesPopulated === false || tree.GetChildren().length > 0)
19947
20061
  {
19948
20062
  actionMenu.AddItem(showAllIcon + translations.ShowAllOptions, "ShowAll");
19949
20063
  }
20064
+ else //if (nodesPopulated === true && tree.GetChildren().length === 0)
20065
+ {
20066
+ actionMenu.AddItem(showAllIcon + "<i>" + translations.NoneAvailable + ": " + translations.ShowAllOptions + "</i>", "ShowAllNoneFound");
20067
+ }
19950
20068
 
19951
20069
  if (addRemoveAll === true)
19952
20070
  {
@@ -20054,7 +20172,8 @@ Fit.Controls.WSDropDown = function(ctlId)
20054
20172
  SearchMore : "Search for more options",
20055
20173
  ShowAllOptions : "Show all available options",
20056
20174
  RemoveAll : "Remove all selected",
20057
- Remove : "Remove"
20175
+ Remove : "Remove",
20176
+ NoneAvailable : "None available"
20058
20177
  }
20059
20178
  },
20060
20179
  "da":
@@ -20066,7 +20185,8 @@ Fit.Controls.WSDropDown = function(ctlId)
20066
20185
  SearchMore : "Søg efter flere valgmuligheder",
20067
20186
  ShowAllOptions : "Vis alle tilgængelige valgmuligheder",
20068
20187
  RemoveAll : "Fjern alle valgte",
20069
- Remove : "Fjern"
20188
+ Remove : "Fjern",
20189
+ NoneAvailable : "Ingen tilgængelige"
20070
20190
  }
20071
20191
  },
20072
20192
  "de":
@@ -20078,7 +20198,8 @@ Fit.Controls.WSDropDown = function(ctlId)
20078
20198
  SearchMore : "Nach weiteren Optionen suchen",
20079
20199
  ShowAllOptions : "Alle verfügbaren Optionen anzeigen",
20080
20200
  RemoveAll : "Alle ausgewählten entfernen",
20081
- Remove : "Entfernen"
20201
+ Remove : "Entfernen",
20202
+ NoneAvailable : "Keine verfügbar"
20082
20203
  }
20083
20204
  }
20084
20205
  }