fit-ui 2.3.5 → 2.5.1

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: 3, Patch: 5 } // 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: 1 } // 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
 
@@ -3048,6 +3048,8 @@ Fit.Controls.Component = function(controlId)
3048
3048
  container = document.createElement("div");
3049
3049
  container.id = id;
3050
3050
  container._internal = { Instance: me };
3051
+
3052
+ Fit.Dom.Data(container, "device", ((Fit.Browser.GetInfo().IsMobile === false) ? "Desktop" : (Fit.Browser.GetInfo().IsPhone === true) ? "Phone" : "Tablet"));
3051
3053
  }
3052
3054
 
3053
3055
  /// <function container="Fit.Controls.Component" name="GetId" access="public" returns="string">
@@ -3278,8 +3280,6 @@ Fit.Controls.ControlBase = function(controlId)
3278
3280
  me._internal.Data("dirty", "false");
3279
3281
  me._internal.Data("enabled", "true");
3280
3282
 
3281
- me._internal.Data("device", ((Fit.Browser.GetInfo().IsMobile === false) ? "Desktop" : (Fit.Browser.GetInfo().IsPhone === true) ? "Phone" : "Tablet"));
3282
-
3283
3283
  // Add hidden inputs which are automatically populated with
3284
3284
  // control value and state information when control is updated.
3285
3285
 
@@ -15793,6 +15793,8 @@ Fit.Controls.DropDown = function(ctlId)
15793
15793
  var focusInputOnMobile = true; // Flag indicating whether control should focus input fields (and potentially bring up a virtual keyboard) based on configuration, platform (computer vs touch) and where user initially clicked/touched DropDown to activate it
15794
15794
  var detectBoundaries = false; // Flag indicating whether drop down menu should detect viewport collision and open upwards when needed
15795
15795
  var detectBoundariesRelToViewPort = false; // Flag indicating whether drop down menu should be positioned relative to viewport (true) or scroll parent (false)
15796
+ var persistView = false; // Flag indicating whether picker controls should remember and restore its scroll position and highlighted item when reopened
15797
+ var highlightFirst = false; // Flag indicating whether picker controls should focus its first node automatically when opened
15796
15798
 
15797
15799
  var onInputChangedHandlers = []; // Invoked when input value is changed - takes two arguments (sender (this), text value)
15798
15800
  var onPasteHandlers = []; // Invoked when a value is pasted - takes two arguments (sender (this), text value)
@@ -15922,8 +15924,15 @@ Fit.Controls.DropDown = function(ctlId)
15922
15924
  {
15923
15925
  var target = Fit.Events.GetTarget(e);
15924
15926
 
15927
+ if (target !== document.documentElement && target !== document.body && Fit.Dom.IsRooted(target) === false)
15928
+ {
15929
+ return; // Do not close DropDown if target no longer exists - this may happen if something is removed within DropDown (e.g. an item in the WSDropDown's action menu)
15930
+ }
15931
+
15925
15932
  if (me.IsDropDownOpen() === true && target !== me.GetDomElement() && Fit.Dom.Contained(me.GetDomElement(), target) === false)
15933
+ {
15926
15934
  me.CloseDropDown();
15935
+ }
15927
15936
  });
15928
15937
  Fit.Array.Add(closeHandlers, eventId);
15929
15938
  }
@@ -15940,6 +15949,11 @@ Fit.Controls.DropDown = function(ctlId)
15940
15949
 
15941
15950
  coords = null;
15942
15951
 
15952
+ if (target !== document.documentElement && target !== document.body && Fit.Dom.IsRooted(target) === false)
15953
+ {
15954
+ return; // Do not close DropDown if target no longer exists - this may happen if something is removed within DropDown (e.g. an item in the WSDropDown's action menu)
15955
+ }
15956
+
15943
15957
  if (me.IsDropDownOpen() === true && target !== me.GetDomElement() && Fit.Dom.Contained(me.GetDomElement(), target) === false)
15944
15958
  {
15945
15959
  coords = Fit.Events.GetPointerState().Coordinates.Document;
@@ -16256,7 +16270,7 @@ Fit.Controls.DropDown = function(ctlId)
16256
16270
  itemDropZones[key].Dispose();
16257
16271
  });
16258
16272
 
16259
- me = itemContainer = itemCollection = itemDropZones = arrow = txtPrimary = txtActive = txtEnabled = dropDownMenu = picker = orgSelections = invalidMessage = invalidMessageChanged = initialFocus = maxHeight = prevValue = focusAssigned = closeHandlers = dropZone = isMobile = focusInputOnMobile = detectBoundaries = onInputChangedHandlers = onPasteHandlers = onOpenHandlers = onCloseHandlers = suppressUpdateItemSelectionState = suppressOnItemSelectionChanged = clearTextSelectionOnInputChange = prevTextSelection = textSelectionCallback = cmdToggleTextMode = null;
16273
+ me = itemContainer = itemCollection = itemDropZones = arrow = txtPrimary = txtActive = txtEnabled = dropDownMenu = picker = orgSelections = invalidMessage = invalidMessageChanged = initialFocus = maxHeight = prevValue = focusAssigned = closeHandlers = dropZone = isMobile = focusInputOnMobile = detectBoundaries = detectBoundariesRelToViewPort = persistView = highlightFirst = onInputChangedHandlers = onPasteHandlers = onOpenHandlers = onCloseHandlers = suppressUpdateItemSelectionState = suppressOnItemSelectionChanged = clearTextSelectionOnInputChange = prevTextSelection = textSelectionCallback = cmdToggleTextMode = null;
16260
16274
 
16261
16275
  base();
16262
16276
  });
@@ -16468,6 +16482,11 @@ Fit.Controls.DropDown = function(ctlId)
16468
16482
  picker.MaxHeight(maxHeight.Value, maxHeight.Unit);
16469
16483
  optimizeDropDownPosition(); // In case dropdown is already open and SetPicker was called async, e.g. initiated from OnOpen event. Function may change MaxHeight on Picker.
16470
16484
 
16485
+ // Persist view and initial focus
16486
+
16487
+ picker.PersistView(persistView);
16488
+ picker.HighlightFirst(highlightFirst);
16489
+
16471
16490
  // Make sure OnItemSelectionChanged is only registered once
16472
16491
 
16473
16492
  if (!picker._internal)
@@ -16525,6 +16544,19 @@ Fit.Controls.DropDown = function(ctlId)
16525
16544
  if (txt.parentElement.parentElement === null)
16526
16545
  txt = txtPrimary;
16527
16546
  }
16547
+ else
16548
+ {
16549
+ // User selected an item which is already selected
16550
+
16551
+ if (me.TextSelectionMode() === true)
16552
+ {
16553
+ updateTextSelection(); // Make sure any search value is removed and text selection is restored
16554
+ }
16555
+ else
16556
+ {
16557
+ me.ClearInput(); // Make sure any search value is removed
16558
+ }
16559
+ }
16528
16560
 
16529
16561
  // DISABLED: Now handled using picker.OnFocus(..) handler further down - see https://github.com/Jemt/Fit.UI/issues/86 for details
16530
16562
  // if (eventArgs.ProgrammaticallyChanged === false && (isMobile === false || focusInputOnMobile === true))
@@ -16845,6 +16877,48 @@ Fit.Controls.DropDown = function(ctlId)
16845
16877
  return null;
16846
16878
  }
16847
16879
 
16880
+ /// <function container="Fit.Controls.DropDown" name="PersistView" access="public" returns="boolean">
16881
+ /// <description> Make DropDown restore scroll position and previously highlighted item when reopened </description>
16882
+ /// <param name="val" type="boolean" default="undefined"> If set, True enables feature, False disables it (default) </param>
16883
+ /// </function>
16884
+ this.PersistView = function(val)
16885
+ {
16886
+ Fit.Validation.ExpectBoolean(val, true);
16887
+
16888
+ if (Fit.Validation.IsSet(val) === true && val !== persistView)
16889
+ {
16890
+ persistView = val;
16891
+
16892
+ if (me.GetPicker() !== null)
16893
+ {
16894
+ me.GetPicker().PersistView(val);
16895
+ }
16896
+ }
16897
+
16898
+ return persistView;
16899
+ }
16900
+
16901
+ /// <function container="Fit.Controls.DropDown" name="HighlightFirst" access="public" returns="boolean">
16902
+ /// <description> Make DropDown highlight first selectable item when opened </description>
16903
+ /// <param name="val" type="boolean" default="undefined"> If set, True enables feature, False disables it (default) </param>
16904
+ /// </function>
16905
+ this.HighlightFirst = function(val)
16906
+ {
16907
+ Fit.Validation.ExpectBoolean(val, true);
16908
+
16909
+ if (Fit.Validation.IsSet(val) === true)
16910
+ {
16911
+ highlightFirst = val;
16912
+
16913
+ if (me.GetPicker() !== null)
16914
+ {
16915
+ me.GetPicker().HighlightFirst(val);
16916
+ }
16917
+ }
16918
+
16919
+ return highlightFirst;
16920
+ }
16921
+
16848
16922
  /// <function container="Fit.Controls.DropDown" name="RenameSelection" access="public">
16849
16923
  /// <description> Rename title of selected item by its value </description>
16850
16924
  /// <param name="val" type="string"> Value of selected item to rename </param>
@@ -17354,6 +17428,34 @@ Fit.Controls.DropDown = function(ctlId)
17354
17428
  Fit.Array.Add(onCloseHandlers, cb);
17355
17429
  }
17356
17430
 
17431
+ // ============================================
17432
+ // Protected
17433
+ // ============================================
17434
+
17435
+ this._internal = (this._internal ? this._internal : {});
17436
+
17437
+ // Clear input field without firing OnInputChanged, and make placeholder appear
17438
+ this._internal.ClearInputAndShowPlaceholder = function(forceFocusInput)
17439
+ {
17440
+ Fit.Validation.ExpectBoolean(forceFocusInput, true);
17441
+
17442
+ txtPrimary.value = "";
17443
+ updatePlaceholder(true);
17444
+
17445
+ if (forceFocusInput)
17446
+ {
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;
17456
+ }
17457
+ }
17458
+
17357
17459
  // ============================================
17358
17460
  // Private
17359
17461
  // ============================================
@@ -18133,7 +18235,7 @@ Fit.Controls.DropDown = function(ctlId)
18133
18235
 
18134
18236
  if (placeholder !== "" || force === true)
18135
18237
  {
18136
- var setPlaceholder = placeholder !== "" && itemCollectionOrdered.length === 0 && me.GetInputValue() === "" && willAssumeInputValue !== true;
18238
+ var setPlaceholder = placeholder !== "" && (me.TextSelectionMode() === true || itemCollectionOrdered.length === 0) && me.GetInputValue() === "" && willAssumeInputValue !== true;
18137
18239
 
18138
18240
  Fit.Dom.Data(itemContainer, "placeholder", setPlaceholder === true ? placeholder : null);
18139
18241
  Fit.Dom.Data(itemContainer, "placeholder-autoclear", setPlaceholder === true ? Fit.Browser.GetBrowser() === "MSIE" ? "true" : "false" : null);
@@ -18347,6 +18449,12 @@ Fit.Controls.DropDown = function(ctlId)
18347
18449
  Fit.Dom.SetCaretPosition(txtPrimary, 0);
18348
18450
  }
18349
18451
 
18452
+ // Remove placeholder in case it was added using this._internal.ClearInputAndShowPlaceholder()
18453
+
18454
+ updatePlaceholder(true);
18455
+
18456
+ // Have TextSelection removed when input is changed
18457
+
18350
18458
  clearTextSelectionOnInputChange = true;
18351
18459
  }
18352
18460
 
@@ -18829,6 +18937,32 @@ Fit.Controls.PickerBase = function()
18829
18937
  return null;
18830
18938
  }
18831
18939
 
18940
+ /// <function container="Fit.Controls.PickerBase" name="PersistView" access="public" returns="boolean">
18941
+ /// <description>
18942
+ /// Overridden by control developers (optional).
18943
+ /// This function can be used to tell the picker control to persist (remember) its current state between interactions.
18944
+ /// For instance a TreeView control would remembers its scroll position and highlighted node, while a calendar would
18945
+ /// remember the previously selected year and month.
18946
+ /// </description>
18947
+ /// <param name="val" type="boolean" default="undefined"> If set, True enables feature, False disables it (default) </param>
18948
+ /// </function>
18949
+ this.PersistView = function(val)
18950
+ {
18951
+ return false;
18952
+ }
18953
+
18954
+ /// <function container="Fit.Controls.PickerBase" name="HighlightFirst" access="public" returns="boolean">
18955
+ /// <description>
18956
+ /// Overridden by control developers (optional).
18957
+ /// This function can be used to make the picker control automatically highlight the first item.
18958
+ /// </description>
18959
+ /// <param name="val" type="boolean" default="undefined"> If set, True enables feature, False disables it (default) </param>
18960
+ /// </function>
18961
+ this.HighlightFirst = function()
18962
+ {
18963
+ return false;
18964
+ }
18965
+
18832
18966
  /// <function container="Fit.Controls.PickerBase" name="Destroy" access="public">
18833
18967
  /// <description>
18834
18968
  /// Overridden by control developers (required).
@@ -18952,6 +19086,7 @@ Fit.Controls.WSDropDown = function(ctlId)
18952
19086
  var me = this;
18953
19087
  var list = null;
18954
19088
  var tree = null;
19089
+ var actionMenu = null;
18955
19090
 
18956
19091
  var search = "";
18957
19092
  var forceNewSearch = false;
@@ -18965,6 +19100,9 @@ Fit.Controls.WSDropDown = function(ctlId)
18965
19100
  var currentRequest = null;
18966
19101
  var classes = null;
18967
19102
  var autoUpdatedSelections = null; // Cached result from AutoUpdateSelected: [{ Title:string, Value:string, Exists:boolean }, ...]
19103
+ var useActionMenu = false;
19104
+ var useActionMenuForced = false;
19105
+ var translations = null;
18968
19106
 
18969
19107
  var onRequestHandlers = [];
18970
19108
  var onResponseHandlers = [];
@@ -19080,6 +19218,22 @@ Fit.Controls.WSDropDown = function(ctlId)
19080
19218
  {
19081
19219
  fireOnDataLoaded();
19082
19220
  }
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
+ }
19083
19237
  }
19084
19238
  });
19085
19239
  tree.OnAbort(function(sender, eventArgs)
@@ -19170,6 +19324,104 @@ Fit.Controls.WSDropDown = function(ctlId)
19170
19324
  me.SetPicker(tree);
19171
19325
  });
19172
19326
 
19327
+ // Create action menu
19328
+
19329
+ var skipUpdateActionMenuOnChange = false;
19330
+
19331
+ actionMenu = new Fit.Controls.ListView(ctlId + "__ActionsListView");
19332
+ 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
+ {
19334
+ if (item.Value === "SearchMore")
19335
+ {
19336
+ me._internal.ClearInputAndShowPlaceholder(true); // NOTICE: TextSelectionMode only - Visual Selection Mode cannot be temporarily cleared to display the place holder
19337
+ }
19338
+ else if (item.Value === "ShowAll")
19339
+ {
19340
+ me.SetPicker(tree);
19341
+ }
19342
+ else if (item.Value === "RemoveAll")
19343
+ {
19344
+ skipUpdateActionMenuOnChange = true;
19345
+ me.ClearSelections(); // Fires OnChange
19346
+ skipUpdateActionMenuOnChange = false;
19347
+
19348
+ updateActionMenu(); // Update action menu (remove all "Remove: xyz" options)
19349
+ }
19350
+ else if (item.Value.indexOf("Remove:") === 0)
19351
+ {
19352
+ var dataValue = item.Value.replace("Remove:", "");
19353
+
19354
+ // Find item below if using keyboard to remove item
19355
+
19356
+ var above = null;
19357
+ var below = null;
19358
+
19359
+ if (Fit.Browser.GetInfo().IsMobile === false && Fit.Events.GetPointerState().Buttons.Primary === false) // Do not find and highlight item below on touch devices, or if using the mouse
19360
+ {
19361
+ var items = actionMenu.GetItems();
19362
+ var stopNext = false;
19363
+
19364
+ for (var i = 0 ; i < items.length ; i++)
19365
+ {
19366
+ if (items[i].Value.indexOf("Remove:") !== 0)
19367
+ {
19368
+ continue; // Skip items that do not remove individual selections
19369
+ }
19370
+
19371
+ if (items[i].Value.replace("Remove:", "") === dataValue)
19372
+ {
19373
+ stopNext = true;
19374
+ continue;
19375
+ }
19376
+
19377
+ if (stopNext === false)
19378
+ {
19379
+ above = items[i].Value;
19380
+ }
19381
+ else
19382
+ {
19383
+ below = items[i].Value;
19384
+ break;
19385
+ }
19386
+ }
19387
+ }
19388
+
19389
+ // Remove item
19390
+
19391
+ skipUpdateActionMenuOnChange = true;
19392
+ me.RemoveSelection(dataValue); // Fires OnChange
19393
+ skipUpdateActionMenuOnChange = false;
19394
+
19395
+ // Update list of removable items
19396
+
19397
+ actionMenu.RemoveItem(item.Value);
19398
+
19399
+ if (me.GetSelections().length === 1)
19400
+ {
19401
+ updateActionMenu(); // Update action menu to get rid of "Remove all" item when only one item is left
19402
+ }
19403
+
19404
+ // Highlight item below (or above) the item that was just removed
19405
+
19406
+ if (above !== null || below !== null)
19407
+ {
19408
+ actionMenu.RevealItemInView(below !== null ? below : above);
19409
+ }
19410
+ }
19411
+
19412
+ return false; // Prevent selection of behavioural item
19413
+ });
19414
+
19415
+ me.OnChange(function(sender)
19416
+ {
19417
+ if (skipUpdateActionMenuOnChange === false)
19418
+ {
19419
+ updateActionMenu();
19420
+ }
19421
+ });
19422
+
19423
+ // Misc
19424
+
19173
19425
  me.OnOpen(function()
19174
19426
  {
19175
19427
  if (suppressTreeOnOpen === true)
@@ -19178,9 +19430,19 @@ Fit.Controls.WSDropDown = function(ctlId)
19178
19430
  return;
19179
19431
  }
19180
19432
 
19181
- me.SetPicker(tree);
19182
- ensureTreeViewData();
19433
+ if (useActionMenu === true)
19434
+ {
19435
+ me.SetPicker(actionMenu);
19436
+ }
19437
+ else
19438
+ {
19439
+ me.SetPicker(tree);
19440
+ ensureTreeViewData();
19441
+ }
19183
19442
  });
19443
+
19444
+ Fit.Internationalization.OnLocaleChanged(localize);
19445
+ localize();
19184
19446
  }
19185
19447
 
19186
19448
  // ============================================
@@ -19405,7 +19667,6 @@ Fit.Controls.WSDropDown = function(ctlId)
19405
19667
  return base(val);
19406
19668
  });
19407
19669
 
19408
-
19409
19670
  /// <function container="Fit.Controls.WSDropDown" name="GetListView" access="public" returns="Fit.Controls.WSListView">
19410
19671
  /// <description> Get WSListView control used to display data in a flat list view </description>
19411
19672
  /// </function>
@@ -19422,6 +19683,44 @@ Fit.Controls.WSDropDown = function(ctlId)
19422
19683
  return tree;
19423
19684
  }
19424
19685
 
19686
+ /// <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>
19688
+ /// <param name="val" type="boolean" default="undefined"> If defined, True enables the action menu, False disables it </param>
19689
+ /// </function>
19690
+ this.UseActionMenu = function(val)
19691
+ {
19692
+ Fit.Validation.ExpectBoolean(val, true);
19693
+
19694
+ if (Fit.Validation.IsSet(val) === true)
19695
+ {
19696
+ useActionMenuForced = true;
19697
+
19698
+ if (val !== useActionMenu)
19699
+ {
19700
+ useActionMenu = val;
19701
+
19702
+ if (val === true)
19703
+ {
19704
+ updateActionMenu();
19705
+
19706
+ if (me.IsDropDownOpen() === true)
19707
+ {
19708
+ me.SetPicker(actionMenu);
19709
+ }
19710
+ }
19711
+ else
19712
+ {
19713
+ if (me.GetPicker() === actionMenu)
19714
+ {
19715
+ me.SetPicker(tree.GetChildren().length > 0 ? tree : list);
19716
+ }
19717
+ }
19718
+ }
19719
+ }
19720
+
19721
+ return useActionMenu;
19722
+ }
19723
+
19425
19724
  // See documentation on ControlBase
19426
19725
  this.Dispose = Fit.Core.CreateOverride(this.Dispose, function()
19427
19726
  {
@@ -19429,10 +19728,13 @@ Fit.Controls.WSDropDown = function(ctlId)
19429
19728
 
19430
19729
  list.Destroy();
19431
19730
  tree.Destroy();
19731
+ actionMenu.Destroy();
19432
19732
 
19433
19733
  cancelSearch();
19434
19734
 
19435
- me = list = tree = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = onRequestHandlers = onResponseHandlers = null;
19735
+ Fit.Internationalization.RemoveOnLocaleChanged(localize);
19736
+
19737
+ me = list = tree = actionMenu = search = forceNewSearch = hideLinesForFlatData = dataRequested = dataLoading = requestCount = onDataLoadedCallback = suppressTreeOnOpen = timeOut = currentRequest = classes = autoUpdatedSelections = useActionMenu = useActionMenuForced = translations = onRequestHandlers = onResponseHandlers = null;
19436
19738
 
19437
19739
  base();
19438
19740
  });
@@ -19623,6 +19925,48 @@ Fit.Controls.WSDropDown = function(ctlId)
19623
19925
  }
19624
19926
  }
19625
19927
 
19928
+ function updateActionMenu()
19929
+ {
19930
+ if (useActionMenu === false)
19931
+ {
19932
+ return;
19933
+ }
19934
+
19935
+ var searchIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconSearch fa fa-search'></span> ";
19936
+ var showAllIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconShowAll fa fa-sitemap'></span> ";
19937
+ var delIcon = "<span class='FitUiControlDropDownActionMenuItemIcon FitUiControlDropDownActionMenuItemIconDelete fa fa-times'></span> ";
19938
+
19939
+ var selectedItems = me.GetSelections();
19940
+ var addRemoveAll = selectedItems.length > 1;
19941
+
19942
+ actionMenu.RemoveItems();
19943
+
19944
+ actionMenu.AddItem(searchIcon + translations.SearchMore, "SearchMore");
19945
+
19946
+ if (dataRequested === false || tree.GetChildren().length > 0)
19947
+ {
19948
+ actionMenu.AddItem(showAllIcon + translations.ShowAllOptions, "ShowAll");
19949
+ }
19950
+
19951
+ if (addRemoveAll === true)
19952
+ {
19953
+ actionMenu.AddItem(delIcon + translations.RemoveAll, "RemoveAll");
19954
+ }
19955
+
19956
+ Fit.Array.ForEach(selectedItems, function(item)
19957
+ {
19958
+ actionMenu.AddItem((addRemoveAll === true ? " &nbsp; &nbsp; &nbsp; " : "") + delIcon + translations.Remove + " " + item.Title, "Remove:" + item.Value);
19959
+ });
19960
+ }
19961
+
19962
+ function localize()
19963
+ {
19964
+ var locale = Fit.Internationalization.GetLocale(me);
19965
+ translations = locale.Translations;
19966
+
19967
+ updateActionMenu();
19968
+ }
19969
+
19626
19970
  function onDataLoaded(cb)
19627
19971
  {
19628
19972
  Fit.Validation.ExpectFunction(cb);
@@ -19700,31 +20044,46 @@ Fit.Controls.WSDropDown = function(ctlId)
19700
20044
  // All locales inherit from en. All country specific overrides inherit
19701
20045
  // from their primary locale (e.g. de_AT inherits from de).
19702
20046
  // English (en) MUST be defined!
19703
-
20047
+
19704
20048
  "en": // US
19705
20049
  {
19706
20050
  Translations:
19707
20051
  {
19708
- InvalidSelection : "Invalid selection"
20052
+ InvalidSelection : "Invalid selection",
20053
+
20054
+ SearchMore : "Search for more options",
20055
+ ShowAllOptions : "Show all available options",
20056
+ RemoveAll : "Remove all selected",
20057
+ Remove : "Remove"
19709
20058
  }
19710
20059
  },
19711
20060
  "da":
19712
20061
  {
19713
20062
  Translations:
19714
20063
  {
19715
- InvalidSelection : "Ugyldigt valg"
20064
+ InvalidSelection : "Ugyldigt valg",
20065
+
20066
+ SearchMore : "Søg efter flere valgmuligheder",
20067
+ ShowAllOptions : "Vis alle tilgængelige valgmuligheder",
20068
+ RemoveAll : "Fjern alle valgte",
20069
+ Remove : "Fjern"
19716
20070
  }
19717
20071
  },
19718
20072
  "de":
19719
20073
  {
19720
20074
  Translations:
19721
20075
  {
19722
- InvalidSelection : "Ungültige Auswahl"
20076
+ InvalidSelection : "Ungültige Auswahl",
20077
+
20078
+ SearchMore : "Nach weiteren Optionen suchen",
20079
+ ShowAllOptions : "Alle verfügbaren Optionen anzeigen",
20080
+ RemoveAll : "Alle ausgewählten entfernen",
20081
+ Remove : "Entfernen"
19723
20082
  }
19724
20083
  }
19725
20084
  }
19726
20085
  Fit.Internationalization.AddLocalization(Fit.Controls.DropDown, locale);
19727
- Fit.Internationalization.AddLocalization(Fit.Controls.WSDropDown, locale);
20086
+ Fit.Internationalization.AddLocalization(Fit.Controls.WSDropDown, locale);
19728
20087
  })();
19729
20088
  /// <container name="Fit.Controls.FilePicker" extends="Fit.Controls.ControlBase">
19730
20089
  /// Control allowing for files to be selected locally and uploaded asynchronously.
@@ -22629,8 +22988,15 @@ Fit.Controls.ListView = function(controlId)
22629
22988
  var me = this;
22630
22989
  var list = me.GetDomElement();
22631
22990
  var active = null;
22991
+ var persistView = false;
22992
+ var scrollPositionTop = 0;
22993
+ var highlightFirst = false;
22994
+ var firstWasHighlighted = false;
22632
22995
  var isIe8 = (Fit.Browser.GetInfo().Name === "MSIE" && Fit.Browser.GetInfo().Version === 8);
22633
22996
 
22997
+ var onSelectHandlers = [];
22998
+ var onSelectedHandlers = [];
22999
+
22634
23000
  function init()
22635
23001
  {
22636
23002
  list.tabIndex = "0";
@@ -22638,10 +23004,37 @@ Fit.Controls.ListView = function(controlId)
22638
23004
 
22639
23005
  me.OnShow(function()
22640
23006
  {
22641
- list.scrollTop = 0;
22642
- setActive(null);
23007
+ if (persistView === false) // Reset selection and scroll position
23008
+ {
23009
+ if (highlightFirst === true)
23010
+ {
23011
+ focusFirstItem();
23012
+ }
23013
+ else
23014
+ {
23015
+ setActive(null);
23016
+ }
23017
+
23018
+ list.scrollTop = 0;
23019
+ }
23020
+ else // View persisted
23021
+ {
23022
+ if (highlightFirst === true && firstWasHighlighted === false)
23023
+ {
23024
+ focusFirstItem();
23025
+ firstWasHighlighted = true;
23026
+ }
23027
+
23028
+ list.scrollTop = scrollPositionTop;
23029
+ }
22643
23030
  });
22644
23031
 
23032
+ list.onscroll = function(e)
23033
+ {
23034
+ // Preserve scroll position which is lost if picker control is removed from DOM
23035
+ scrollPositionTop = list.scrollTop;
23036
+ };
23037
+
22645
23038
  list.onclick = function(e)
22646
23039
  {
22647
23040
  var ev = Fit.Events.GetEvent(e);
@@ -22657,12 +23050,17 @@ Fit.Controls.ListView = function(controlId)
22657
23050
 
22658
23051
  // Fire OnChanging and OnChange events
22659
23052
 
23053
+ var item = convertItemElementToObject(elm);
23054
+ var selectionCanceled = fireOnSelectHandlers(item) === false;
23055
+
22660
23056
  // Notice: We always pass False as current selection state to OnItemSelectionChanging since ListView does
22661
23057
  // not keep track of selection state. In theory item could very well already be selected in host control.
22662
23058
  // Event handlers should not trust boolean to reveal selection in host control, only in picker.
22663
- if (me._internal.FireOnItemSelectionChanging(Fit.Dom.Text(elm), decode(Fit.Dom.Data(elm, "value")), false, false) === true)
23059
+ if (selectionCanceled === false && me._internal.FireOnItemSelectionChanging(item.Title, item.Value, false, false) === true)
22664
23060
  {
22665
- me._internal.FireOnItemSelectionChanged(Fit.Dom.Text(elm), decode(Fit.Dom.Data(elm, "value")), true, false);
23061
+ fireOnSelectedHandlers(item);
23062
+
23063
+ me._internal.FireOnItemSelectionChanged(item.Title, item.Value, true, false);
22666
23064
  me._internal.FireOnItemSelectionComplete();
22667
23065
  }
22668
23066
  }
@@ -22782,6 +23180,21 @@ Fit.Controls.ListView = function(controlId)
22782
23180
  return null;
22783
23181
  }
22784
23182
 
23183
+ /// <function container="Fit.Controls.ListView" name="GetItems" access="public" returns="Fit.Controls.ListViewTypeDefs.ListViewItem[]">
23184
+ /// <description> Get all items - returns array containing objects with Title (string) and Value (string) properties </description>
23185
+ /// </function>
23186
+ this.GetItems = function()
23187
+ {
23188
+ var items = [];
23189
+
23190
+ Fit.Array.ForEach(list.children, function(child)
23191
+ {
23192
+ Fit.Array.Add(items, convertItemElementToObject(child));
23193
+ });
23194
+
23195
+ return items;
23196
+ }
23197
+
22785
23198
  /// <function container="Fit.Controls.ListView" name="HasItem" access="public" returns="boolean">
22786
23199
  /// <description> Returns value indicating whether control contains item with specified value </description>
22787
23200
  /// <param name="value" type="string"> Value of item to check for </param>
@@ -22805,6 +23218,11 @@ Fit.Controls.ListView = function(controlId)
22805
23218
  if (item !== null)
22806
23219
  {
22807
23220
  Fit.Dom.Remove(item);
23221
+
23222
+ if (item === active)
23223
+ {
23224
+ active = null;
23225
+ }
22808
23226
  }
22809
23227
  }
22810
23228
 
@@ -22868,12 +23286,17 @@ Fit.Controls.ListView = function(controlId)
22868
23286
 
22869
23287
  if (active !== null)
22870
23288
  {
23289
+ var item = convertItemElementToObject(active);
23290
+ var selectionCanceled = fireOnSelectHandlers(item) === false;
23291
+
22871
23292
  // Notice: We always pass False as current selection state to OnItemSelectionChanging since ListView does
22872
23293
  // not keep track of selection state. In theory item could very well already be selected in host control.
22873
23294
  // Event handlers should not trust boolean to reveal selection in host control, only in picker.
22874
- if (me._internal.FireOnItemSelectionChanging(Fit.Dom.Text(active), decode(Fit.Dom.Data(active, "value")), false, false) === true)
23295
+ if (selectionCanceled === false && me._internal.FireOnItemSelectionChanging(item.Title, item.Value, false, false) === true)
22875
23296
  {
22876
- me._internal.FireOnItemSelectionChanged(Fit.Dom.Text(active), decode(Fit.Dom.Data(active, "value")), true, false);
23297
+ fireOnSelectedHandlers(item);
23298
+
23299
+ me._internal.FireOnItemSelectionChanged(item.Title, item.Value, true, false);
22877
23300
  me._internal.FireOnItemSelectionComplete();
22878
23301
  }
22879
23302
  }
@@ -22894,6 +23317,85 @@ Fit.Controls.ListView = function(controlId)
22894
23317
  return null;
22895
23318
  }
22896
23319
 
23320
+ this.PersistView = function(val)
23321
+ {
23322
+ Fit.Validation.ExpectBoolean(val, true);
23323
+
23324
+ if (Fit.Validation.IsSet(val) === true && val !== persistView)
23325
+ {
23326
+ persistView = val;
23327
+ scrollPositionTop = 0;
23328
+ }
23329
+
23330
+ return persistView;
23331
+ }
23332
+
23333
+ this.HighlightFirst = function(val)
23334
+ {
23335
+ Fit.Validation.ExpectBoolean(val, true);
23336
+
23337
+ if (Fit.Validation.IsSet(val) === true)
23338
+ {
23339
+ if (val !== highlightFirst)
23340
+ {
23341
+ highlightFirst = val;
23342
+ firstWasHighlighted = false;
23343
+ }
23344
+
23345
+ // Allow external code to force focus first item if picker is visible.
23346
+ // Usually first item is automatically highlighted when the host control
23347
+ // is opened (see OnShow handler in init()).
23348
+ if (val === true && Fit.Dom.IsVisible(me.GetDomElement()) === true)
23349
+ {
23350
+ focusFirstItem();
23351
+ firstWasHighlighted = true;
23352
+ }
23353
+ }
23354
+
23355
+ return highlightFirst;
23356
+ }
23357
+
23358
+ /// <function container="Fit.Controls.ListViewTypeDefs" name="OnSelectEventHandler" returns="boolean | void">
23359
+ /// <description> OnSelect event handler </description>
23360
+ /// <param name="sender" type="$TypeOfThis"> Instance of control </param>
23361
+ /// <param name="item" type="{ Title: string, Value: string }"> Selected item </param>
23362
+ /// </function>
23363
+
23364
+ /// <function container="Fit.Controls.ListView" name="OnSelect" access="public">
23365
+ /// <description>
23366
+ /// Register event handler fired when item is being selected.
23367
+ /// Selection can be canceled by returning False.
23368
+ /// The following arguments are passed to event handler function:
23369
+ /// Sender (ListView) and Item (with Title (string) and Value (string) properties).
23370
+ /// </description>
23371
+ /// <param name="cb" type="Fit.Controls.ListViewTypeDefs.OnSelectEventHandler"> Event handler function </param>
23372
+ /// </function>
23373
+ this.OnSelect = function(cb)
23374
+ {
23375
+ Fit.Validation.ExpectFunction(cb);
23376
+ Fit.Array.Add(onSelectHandlers, cb);
23377
+ }
23378
+
23379
+ /// <function container="Fit.Controls.ListViewTypeDefs" name="OnSelectedEventHandler">
23380
+ /// <description> OnSelected event handler </description>
23381
+ /// <param name="sender" type="$TypeOfThis"> Instance of control </param>
23382
+ /// <param name="item" type="{ Title: string, Value: string }"> Selected item </param>
23383
+ /// </function>
23384
+
23385
+ /// <function container="Fit.Controls.ListView" name="OnSelected" access="public">
23386
+ /// <description>
23387
+ /// Register event handler fired when item is selected.
23388
+ /// The following arguments are passed to event handler function:
23389
+ /// Sender (ListView) and Item (with Title (string) and Value (string) properties).
23390
+ /// </description>
23391
+ /// <param name="cb" type="Fit.Controls.ListViewTypeDefs.OnSelectedEventHandler"> Event handler function </param>
23392
+ /// </function>
23393
+ this.OnSelected = function(cb)
23394
+ {
23395
+ Fit.Validation.ExpectFunction(cb);
23396
+ Fit.Array.Add(onSelectedHandlers, cb);
23397
+ }
23398
+
22897
23399
  this.Destroy = Fit.Core.CreateOverride(this.Destroy, function(calledInternally)
22898
23400
  {
22899
23401
  Fit.Validation.ExpectBoolean(calledInternally, true);
@@ -22919,9 +23421,26 @@ Fit.Controls.ListView = function(controlId)
22919
23421
  me.Destroy(true); // PickerBase.Destroy()
22920
23422
  }
22921
23423
 
22922
- me = list = active = isIe8 = null;
23424
+ me = list = active = persistView = scrollPositionTop = highlightFirst = firstWasHighlighted = isIe8 = onSelectHandlers = onSelectedHandlers = null;
22923
23425
  });
22924
23426
 
23427
+ // ============================================
23428
+ // Protected
23429
+ // ============================================
23430
+
23431
+ this._internal = (this._internal ? this._internal : {});
23432
+
23433
+ this._internal.FocusFirstItem = function() // Similar implementation in Fit.Controls.TreeView._internal.FocusFirstNode()
23434
+ {
23435
+ // If picker is still visible (it might have been hidden if user closed
23436
+ // host control while data was being loaded/populated async.) then focus first item.
23437
+ if (Fit.Dom.IsVisible(me.GetDomElement()) === true)
23438
+ {
23439
+ focusFirstItem();
23440
+ firstWasHighlighted = true;
23441
+ }
23442
+ }
23443
+
22925
23444
  // ============================================
22926
23445
  // Private
22927
23446
  // ============================================
@@ -22972,6 +23491,14 @@ Fit.Controls.ListView = function(controlId)
22972
23491
  }
22973
23492
  }
22974
23493
 
23494
+ function focusFirstItem()
23495
+ {
23496
+ if (list.children.length > 0)
23497
+ {
23498
+ setActive(list.children[0]);
23499
+ }
23500
+ }
23501
+
22975
23502
  function moveUp()
22976
23503
  {
22977
23504
  if (list.children.length === 0)
@@ -23006,6 +23533,37 @@ Fit.Controls.ListView = function(controlId)
23006
23533
  }
23007
23534
  }
23008
23535
 
23536
+ function fireOnSelectHandlers(item)
23537
+ {
23538
+ Fit.Validation.ExpectObject(item);
23539
+ Fit.Validation.ExpectString(item.Title);
23540
+ Fit.Validation.ExpectString(item.Value);
23541
+
23542
+ var selectionCanceled = false;
23543
+
23544
+ Fit.Array.ForEach(onSelectHandlers, function(handler)
23545
+ {
23546
+ if (handler(me, item) === false)
23547
+ {
23548
+ selectionCanceled = true;
23549
+ }
23550
+ });
23551
+
23552
+ return selectionCanceled === true ? false : true; // Return False if canceled
23553
+ }
23554
+
23555
+ function fireOnSelectedHandlers(item)
23556
+ {
23557
+ Fit.Validation.ExpectObject(item);
23558
+ Fit.Validation.ExpectString(item.Title);
23559
+ Fit.Validation.ExpectString(item.Value);
23560
+
23561
+ Fit.Array.ForEach(onSelectedHandlers, function(handler)
23562
+ {
23563
+ handler(me, item);
23564
+ });
23565
+ }
23566
+
23009
23567
  function repaint()
23010
23568
  {
23011
23569
  if (isIe8 === true)
@@ -23343,6 +23901,26 @@ Fit.Controls.WSListView = function(ctlId)
23343
23901
  populate(item);
23344
23902
  });
23345
23903
 
23904
+ // Highlight first item
23905
+
23906
+ if (me.PersistView() === true)
23907
+ {
23908
+ // Reset PersistView to make sure it does not reuse state
23909
+ // for newly loaded items, in case item list is changed.
23910
+ me.PersistView(false);
23911
+ me.PersistView(true);
23912
+ }
23913
+
23914
+ if (me.HighlightFirst() === true)
23915
+ {
23916
+ // Reset HighlightFirst to make sure it takes effect again
23917
+ // for newly loaded items, in case item list is changed.
23918
+ me.HighlightFirst(false);
23919
+ me.HighlightFirst(true);
23920
+
23921
+ me._internal.FocusFirstItem();
23922
+ }
23923
+
23346
23924
  // Invoke callback
23347
23925
 
23348
23926
  if (Fit.Validation.IsSet(cb) === true)
@@ -23867,6 +24445,10 @@ Fit.Controls.TreeView = function(ctlId)
23867
24445
  var showSelectAll = false; // TBD: Never implemented - can be achieved using ContextMenu. Remove or implement?
23868
24446
  var allowDeselect = true;
23869
24447
  var revealExpandedNodes = false;
24448
+ var persistView = false;
24449
+ var scrollPosition = { X: 0, Y: 0 };
24450
+ var highlightFirst = false;
24451
+ var firstWasHighlighted = false;
23870
24452
 
23871
24453
  var selected = createInternalCollection();
23872
24454
  var selectedOrg = [];
@@ -24267,6 +24849,13 @@ Fit.Controls.TreeView = function(ctlId)
24267
24849
  touchTimeout = -1;
24268
24850
  }
24269
24851
  });
24852
+
24853
+ Fit.Events.AddHandler(me.GetDomElement(), "scroll", function(e)
24854
+ {
24855
+ // Preserve scroll position which is lost if picker control is removed from DOM
24856
+ scrollPosition.X = me.GetDomElement().scrollLeft;
24857
+ scrollPosition.Y = me.GetDomElement().scrollTop;
24858
+ });
24270
24859
  }
24271
24860
 
24272
24861
  // ============================================
@@ -24865,7 +25454,7 @@ Fit.Controls.TreeView = function(ctlId)
24865
25454
  me.Destroy(true); // PickerBase.Destroy()
24866
25455
  }
24867
25456
 
24868
- me = rootContainer = rootNode = focusInEventId = keyNavigationEnabled = selectable = multiSelect = showSelectAll = allowDeselect = revealExpandedNodes = selected = selectedOrg = ctx = onSelectHandlers = onSelectedHandlers = onToggleHandlers = onToggledHandlers = onSelectAllHandlers = onSelectAllCompleteHandlers = onContextMenuHandlers = forceClear = isIe8 = isPicker = activeNode = hostFocused = null;
25457
+ me = rootContainer = rootNode = focusInEventId = keyNavigationEnabled = selectable = multiSelect = showSelectAll = allowDeselect = revealExpandedNodes = persistView = scrollPosition = highlightFirst = firstWasHighlighted = selected = selectedOrg = ctx = onSelectHandlers = onSelectedHandlers = onToggleHandlers = onToggledHandlers = onSelectAllHandlers = onSelectAllCompleteHandlers = onContextMenuHandlers = forceClear = isIe8 = isPicker = activeNode = hostFocused = null;
24869
25458
  });
24870
25459
 
24871
25460
  // ============================================
@@ -25041,10 +25630,31 @@ Fit.Controls.TreeView = function(ctlId)
25041
25630
 
25042
25631
  this.OnShow(function(sender)
25043
25632
  {
25044
- // Reset selection and scroll
25045
- unsetActiveNode();
25046
- me.GetDomElement().scrollTop = 0;
25047
- me.GetDomElement().scrollLeft = 0;
25633
+ if (persistView === false) // Reset selection and scroll position
25634
+ {
25635
+ if (highlightFirst === true)
25636
+ {
25637
+ focusFirstNode();
25638
+ }
25639
+ else
25640
+ {
25641
+ unsetActiveNode();
25642
+ }
25643
+
25644
+ me.GetDomElement().scrollTop = 0;
25645
+ me.GetDomElement().scrollLeft = 0;
25646
+ }
25647
+ else // View persisted
25648
+ {
25649
+ if (highlightFirst === true && firstWasHighlighted === false)
25650
+ {
25651
+ focusFirstNode();
25652
+ firstWasHighlighted = true;
25653
+ }
25654
+
25655
+ me.GetDomElement().scrollTop = scrollPosition.Y;
25656
+ me.GetDomElement().scrollLeft = scrollPosition.X;
25657
+ }
25048
25658
  });
25049
25659
 
25050
25660
  this.OnSelect(function(sender, node)
@@ -25173,6 +25783,45 @@ Fit.Controls.TreeView = function(ctlId)
25173
25783
  return null;
25174
25784
  }
25175
25785
 
25786
+ this.PersistView = function(val)
25787
+ {
25788
+ Fit.Validation.ExpectBoolean(val, true);
25789
+
25790
+ if (Fit.Validation.IsSet(val) === true && val !== persistView)
25791
+ {
25792
+ persistView = val;
25793
+ scrollPosition.X = 0;
25794
+ scrollPosition.Y = 0;
25795
+ }
25796
+
25797
+ return persistView;
25798
+ }
25799
+
25800
+ this.HighlightFirst = function(val)
25801
+ {
25802
+ Fit.Validation.ExpectBoolean(val, true);
25803
+
25804
+ if (Fit.Validation.IsSet(val) === true)
25805
+ {
25806
+ if (val !== highlightFirst)
25807
+ {
25808
+ highlightFirst = val;
25809
+ firstWasHighlighted = false;
25810
+ }
25811
+
25812
+ // Allow external code to force focus first item if picker is visible.
25813
+ // Usually first item is automatically highlighted when the host control
25814
+ // is opened (see OnShow handler in init()).
25815
+ if (val === true && Fit.Dom.IsVisible(me.GetDomElement()) === true)
25816
+ {
25817
+ focusFirstNode();
25818
+ firstWasHighlighted = true;
25819
+ }
25820
+ }
25821
+
25822
+ return highlightFirst;
25823
+ }
25824
+
25176
25825
  this.UpdateItemSelection = function(itemValue, selected, programmaticallyChanged)
25177
25826
  {
25178
25827
  Fit.Validation.ExpectString(itemValue);
@@ -25223,6 +25872,17 @@ Fit.Controls.TreeView = function(ctlId)
25223
25872
  fireEventHandlers(onSelectAllCompleteHandlers, { Selected: selected, Node: node || null });
25224
25873
  }
25225
25874
 
25875
+ this._internal.FocusFirstNode = function() // Similar implementation in Fit.Controls.ListView._internal.FocusFirstItem()
25876
+ {
25877
+ // If picker is still visible (it might have been hidden if user closed
25878
+ // host control while data was being loaded/populated async.) then focus first node.
25879
+ if (Fit.Dom.IsVisible(me.GetDomElement()) === true)
25880
+ {
25881
+ focusFirstNode();
25882
+ firstWasHighlighted = true;
25883
+ }
25884
+ }
25885
+
25226
25886
  this.HandleEvent = function(e)
25227
25887
  {
25228
25888
  Fit.Validation.ExpectEvent(e, true);
@@ -27450,6 +28110,29 @@ Fit.Controls.WSTreeView = function(ctlId)
27450
28110
  delete request._loadingIndicator;
27451
28111
  }
27452
28112
 
28113
+ // Highlight first node
28114
+
28115
+ if (node === null) // Only do this for root nodes
28116
+ {
28117
+ if (me.PersistView() === true)
28118
+ {
28119
+ // Reset PersistView to make sure it does not reuse state
28120
+ // for newly loaded nodes, in case node list is changed.
28121
+ me.PersistView(false);
28122
+ me.PersistView(true);
28123
+ }
28124
+
28125
+ if (me.HighlightFirst() === true)
28126
+ {
28127
+ // Reset HighlightFirst to make sure it takes effect again
28128
+ // for newly loaded nodes, in case node list is changed.
28129
+ me.HighlightFirst(false);
28130
+ me.HighlightFirst(true);
28131
+
28132
+ me._internal.FocusFirstNode();
28133
+ }
28134
+ }
28135
+
27453
28136
  // Select nodes found in preselections
27454
28137
 
27455
28138
  var hasBeenDisposedOrDetached = node !== null && nodeDisposedOrDetached(node);