@openui5/sap.f 1.119.1 → 1.120.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.
Files changed (130) hide show
  1. package/THIRDPARTY.txt +6 -6
  2. package/package.json +4 -4
  3. package/src/sap/f/.library +1 -1
  4. package/src/sap/f/Avatar.js +1 -1
  5. package/src/sap/f/AvatarGroup.js +1 -1
  6. package/src/sap/f/AvatarGroupItem.js +1 -1
  7. package/src/sap/f/CalendarAppointmentInCard.js +1 -1
  8. package/src/sap/f/CalendarInCard.js +1 -1
  9. package/src/sap/f/Card.js +1 -1
  10. package/src/sap/f/CardBase.js +1 -1
  11. package/src/sap/f/DynamicPage.js +1 -1
  12. package/src/sap/f/DynamicPageAccessibleLandmarkInfo.js +1 -1
  13. package/src/sap/f/DynamicPageHeader.js +1 -1
  14. package/src/sap/f/DynamicPageTitle.js +1 -1
  15. package/src/sap/f/FlexibleColumnLayout.js +1155 -427
  16. package/src/sap/f/FlexibleColumnLayoutAccessibleLandmarkInfo.js +1 -1
  17. package/src/sap/f/FlexibleColumnLayoutRenderer.js +64 -27
  18. package/src/sap/f/FlexibleColumnLayoutSemanticHelper.js +5 -5
  19. package/src/sap/f/GridContainer.js +2 -4
  20. package/src/sap/f/GridContainerItemLayoutData.js +1 -1
  21. package/src/sap/f/GridContainerSettings.js +2 -2
  22. package/src/sap/f/GridList.js +2 -2
  23. package/src/sap/f/GridListItem.js +1 -1
  24. package/src/sap/f/IllustratedMessage.js +1 -1
  25. package/src/sap/f/Illustration.js +1 -1
  26. package/src/sap/f/PlanningCalendarInCardLegend.js +1 -1
  27. package/src/sap/f/ProductSwitch.js +1 -1
  28. package/src/sap/f/ProductSwitchItem.js +1 -1
  29. package/src/sap/f/SearchManager.js +1 -1
  30. package/src/sap/f/ShellBar.js +1 -1
  31. package/src/sap/f/SidePanel.js +1 -1
  32. package/src/sap/f/SidePanelItem.js +1 -1
  33. package/src/sap/f/cards/BaseHeader.js +1 -1
  34. package/src/sap/f/cards/Header.js +1 -1
  35. package/src/sap/f/cards/NumericHeader.js +1 -1
  36. package/src/sap/f/cards/NumericIndicators.js +1 -1
  37. package/src/sap/f/cards/NumericSideIndicator.js +1 -1
  38. package/src/sap/f/cards/loading/AnalyticalPlaceholder.js +1 -1
  39. package/src/sap/f/cards/loading/CalendarPlaceholder.js +8 -1
  40. package/src/sap/f/cards/loading/GenericPlaceholder.js +1 -1
  41. package/src/sap/f/cards/loading/ListPlaceholder.js +33 -4
  42. package/src/sap/f/cards/loading/ListPlaceholderRenderer.js +18 -21
  43. package/src/sap/f/cards/loading/ObjectPlaceholder.js +1 -1
  44. package/src/sap/f/cards/loading/PlaceholderBase.js +1 -1
  45. package/src/sap/f/cards/loading/TablePlaceholder.js +1 -1
  46. package/src/sap/f/cards/loading/TimelinePlaceholder.js +1 -1
  47. package/src/sap/f/changeHandler/MoveDynamicPageTitleActions.js +1 -1
  48. package/src/sap/f/delegate/GridContainerItemNavigation.js +6 -1
  49. package/src/sap/f/delegate/GridItemNavigation.js +16 -19
  50. package/src/sap/f/designtime/messagebundle_mk.properties +8 -0
  51. package/src/sap/f/dnd/GridDragOver.js +1 -1
  52. package/src/sap/f/dnd/GridDropInfo.js +1 -1
  53. package/src/sap/f/library.js +2 -2
  54. package/src/sap/f/messagebundle.properties +3 -12
  55. package/src/sap/f/messagebundle_ar.properties +2 -8
  56. package/src/sap/f/messagebundle_bg.properties +2 -8
  57. package/src/sap/f/messagebundle_ca.properties +2 -8
  58. package/src/sap/f/messagebundle_cs.properties +2 -8
  59. package/src/sap/f/messagebundle_cy.properties +2 -8
  60. package/src/sap/f/messagebundle_da.properties +2 -8
  61. package/src/sap/f/messagebundle_de.properties +2 -8
  62. package/src/sap/f/messagebundle_el.properties +2 -8
  63. package/src/sap/f/messagebundle_en.properties +2 -8
  64. package/src/sap/f/messagebundle_en_GB.properties +2 -8
  65. package/src/sap/f/messagebundle_es.properties +2 -8
  66. package/src/sap/f/messagebundle_es_MX.properties +2 -8
  67. package/src/sap/f/messagebundle_et.properties +2 -8
  68. package/src/sap/f/messagebundle_fi.properties +2 -8
  69. package/src/sap/f/messagebundle_fr.properties +3 -9
  70. package/src/sap/f/messagebundle_fr_CA.properties +2 -8
  71. package/src/sap/f/messagebundle_hi.properties +2 -8
  72. package/src/sap/f/messagebundle_hr.properties +2 -8
  73. package/src/sap/f/messagebundle_hu.properties +2 -8
  74. package/src/sap/f/messagebundle_id.properties +2 -8
  75. package/src/sap/f/messagebundle_it.properties +2 -8
  76. package/src/sap/f/messagebundle_iw.properties +2 -8
  77. package/src/sap/f/messagebundle_ja.properties +2 -8
  78. package/src/sap/f/messagebundle_kk.properties +2 -8
  79. package/src/sap/f/messagebundle_ko.properties +2 -8
  80. package/src/sap/f/messagebundle_lt.properties +2 -8
  81. package/src/sap/f/messagebundle_lv.properties +2 -8
  82. package/src/sap/f/messagebundle_mk.properties +161 -0
  83. package/src/sap/f/messagebundle_ms.properties +2 -8
  84. package/src/sap/f/messagebundle_nl.properties +2 -8
  85. package/src/sap/f/messagebundle_no.properties +2 -8
  86. package/src/sap/f/messagebundle_pl.properties +2 -8
  87. package/src/sap/f/messagebundle_pt.properties +2 -8
  88. package/src/sap/f/messagebundle_pt_PT.properties +2 -8
  89. package/src/sap/f/messagebundle_ro.properties +2 -8
  90. package/src/sap/f/messagebundle_ru.properties +2 -8
  91. package/src/sap/f/messagebundle_sh.properties +10 -16
  92. package/src/sap/f/messagebundle_sk.properties +2 -8
  93. package/src/sap/f/messagebundle_sl.properties +2 -8
  94. package/src/sap/f/messagebundle_sv.properties +2 -8
  95. package/src/sap/f/messagebundle_th.properties +2 -8
  96. package/src/sap/f/messagebundle_tr.properties +2 -8
  97. package/src/sap/f/messagebundle_uk.properties +2 -8
  98. package/src/sap/f/messagebundle_vi.properties +2 -8
  99. package/src/sap/f/messagebundle_zh_CN.properties +2 -8
  100. package/src/sap/f/messagebundle_zh_TW.properties +2 -8
  101. package/src/sap/f/semantic/AddAction.js +1 -1
  102. package/src/sap/f/semantic/CloseAction.js +1 -1
  103. package/src/sap/f/semantic/CopyAction.js +1 -1
  104. package/src/sap/f/semantic/DeleteAction.js +1 -1
  105. package/src/sap/f/semantic/DiscussInJamAction.js +1 -1
  106. package/src/sap/f/semantic/EditAction.js +1 -1
  107. package/src/sap/f/semantic/ExitFullScreenAction.js +1 -1
  108. package/src/sap/f/semantic/FavoriteAction.js +1 -1
  109. package/src/sap/f/semantic/FlagAction.js +1 -1
  110. package/src/sap/f/semantic/FooterMainAction.js +1 -1
  111. package/src/sap/f/semantic/FullScreenAction.js +1 -1
  112. package/src/sap/f/semantic/MainAction.js +1 -1
  113. package/src/sap/f/semantic/MessagesIndicator.js +1 -1
  114. package/src/sap/f/semantic/NegativeAction.js +1 -1
  115. package/src/sap/f/semantic/PositiveAction.js +1 -1
  116. package/src/sap/f/semantic/PrintAction.js +1 -1
  117. package/src/sap/f/semantic/SemanticButton.js +1 -1
  118. package/src/sap/f/semantic/SemanticConfiguration.js +1 -1
  119. package/src/sap/f/semantic/SemanticControl.js +1 -1
  120. package/src/sap/f/semantic/SemanticPage.js +1 -1
  121. package/src/sap/f/semantic/SemanticToggleButton.js +1 -1
  122. package/src/sap/f/semantic/SendEmailAction.js +1 -1
  123. package/src/sap/f/semantic/SendMessageAction.js +1 -1
  124. package/src/sap/f/semantic/ShareInJamAction.js +1 -1
  125. package/src/sap/f/semantic/TitleMainAction.js +1 -1
  126. package/src/sap/f/shellBar/AdditionalContentSupport.js +1 -1
  127. package/src/sap/f/shellBar/CoPilot.js +1 -1
  128. package/src/sap/f/shellBar/ControlSpacer.js +1 -1
  129. package/src/sap/f/shellBar/Search.js +1 -1
  130. package/src/sap/f/themes/base/FlexibleColumnLayout.less +149 -38
@@ -12,8 +12,8 @@ sap.ui.define([
12
12
  "sap/ui/Device",
13
13
  "sap/ui/core/ResizeHandler",
14
14
  "sap/ui/core/Control",
15
+ "sap/ui/util/Storage",
15
16
  "sap/m/library",
16
- "sap/m/Button",
17
17
  "sap/m/NavContainer",
18
18
  "sap/ui/core/Configuration",
19
19
  'sap/ui/dom/units/Rem',
@@ -31,8 +31,8 @@ sap.ui.define([
31
31
  Device,
32
32
  ResizeHandler,
33
33
  Control,
34
+ Storage,
34
35
  mobileLibrary,
35
- Button,
36
36
  NavContainer,
37
37
  Configuration,
38
38
  DomUnitsRem,
@@ -97,7 +97,7 @@ sap.ui.define([
97
97
  *
98
98
  * @extends sap.ui.core.Control
99
99
  * @author SAP SE
100
- * @version 1.119.1
100
+ * @version 1.120.1
101
101
  *
102
102
  * @constructor
103
103
  * @public
@@ -191,12 +191,7 @@ sap.ui.define([
191
191
 
192
192
  _beginColumnNav: {type : "sap.m.NavContainer", multiple : false, visibility : "hidden"},
193
193
  _midColumnNav: {type : "sap.m.NavContainer", multiple : false, visibility : "hidden"},
194
- _endColumnNav: {type : "sap.m.NavContainer", multiple : false, visibility : "hidden"},
195
-
196
- _beginColumnBackArrow: {type: "sap.m.Button", multiple: false, visibility: "hidden"},
197
- _midColumnForwardArrow: {type: "sap.m.Button", multiple: false, visibility: "hidden"},
198
- _midColumnBackArrow: {type: "sap.m.Button", multiple: false, visibility: "hidden"},
199
- _endColumnForwardArrow: {type: "sap.m.Button", multiple: false, visibility: "hidden"}
194
+ _endColumnNav: {type : "sap.m.NavContainer", multiple : false, visibility : "hidden"}
200
195
  },
201
196
  associations : {
202
197
 
@@ -657,25 +652,12 @@ sap.ui.define([
657
652
  "LastColumn" : "FCL_END_COLUMN_REGION_TEXT"
658
653
  };
659
654
 
660
- FlexibleColumnLayout.DEFAULT_ARROW_LABELS = {
661
- "FirstColumnBackArrow" : "FCL_BEGIN_COLUMN_BACK_ARROW",
662
- "MiddleColumnForwardArrow" : "FCL_MID_COLUMN_FORWARD_ARROW",
663
- "MiddleColumnBackArrow" : "FCL_MID_COLUMN_BACK_ARROW",
664
- "LastColumnForwardArrow" : "FCL_END_COLUMN_FORWARD_ARROW"
665
- };
666
-
667
- FlexibleColumnLayout.ARROW_AGGREGATION_TO_LABEL_MAP = {
668
- "_beginColumnBackArrow" : "FirstColumnBackArrow",
669
- "_midColumnForwardArrow" : "MiddleColumnForwardArrow",
670
- "_midColumnBackArrow" : "MiddleColumnBackArrow",
671
- "_endColumnForwardArrow" : "LastColumnForwardArrow"
672
- };
673
-
674
655
  FlexibleColumnLayout.COLUMN_RESIZING_ANIMATION_DURATION = 560; // ms
675
656
  FlexibleColumnLayout.PINNED_COLUMN_CLASS_NAME = "sapFFCLPinnedColumn";
657
+ FlexibleColumnLayout.ANIMATED_COLUMN_CLASS_NAME = "sapFFCLAnimatedColumn";
676
658
  FlexibleColumnLayout.COLUMN_ORDER = ["begin", "mid", "end"]; // natural order of the columns in FCL
677
- // synced with @_sap_f_FCL_navigation_arrow_width in base less file
678
- FlexibleColumnLayout.NAVIGATION_ARROW_WIDTH = DomUnitsRem.toPx("1rem");
659
+ // synced with @_sap_f_FCL_SeparatorWidth in base less file
660
+ FlexibleColumnLayout.COLUMN_SEPARATOR_WIDTH = DomUnitsRem.toPx("1rem");
679
661
 
680
662
  FlexibleColumnLayout.prototype.init = function () {
681
663
  this._iWidth = 0;
@@ -690,9 +672,6 @@ sap.ui.define([
690
672
  // Create the 3 nav containers
691
673
  this._initNavContainers();
692
674
 
693
- // Create the expand/collapse arrows
694
- this._initButtons();
695
-
696
675
  // Holds an object, responsible for saving and searching the layout history
697
676
  this._oLayoutHistory = new LayoutHistory();
698
677
 
@@ -708,6 +687,24 @@ sap.ui.define([
708
687
  };
709
688
 
710
689
  this._oInvisibleMessage = null;
690
+ this._boundColumnSeparatorMove = this._onColumnSeparatorMove.bind(this);
691
+ this._boundColumnSeparatorMoveEnd = this._onColumnSeparatorMoveEnd.bind(this);
692
+ this._oLocalStorage = {};
693
+ this._bNeverRendered = true;
694
+ };
695
+
696
+ FlexibleColumnLayout.prototype._getLocalStorage = function (iMaxColumnsCount) {
697
+ if (!iMaxColumnsCount) {
698
+ iMaxColumnsCount = this.getMaxColumnsCount();
699
+ }
700
+ var sKey = (iMaxColumnsCount === 3) ? "desktop" : "tablet";
701
+ if (!this._oLocalStorage[sKey]) {
702
+ var sPrefix = sKey === 'desktop' ?
703
+ FlexibleColumnLayout.STORAGE_PREFIX_DESKTOP :
704
+ FlexibleColumnLayout.STORAGE_PREFIX_TABLET;
705
+ this._oLocalStorage[sKey] = new Storage(Storage.Type.local, sPrefix);
706
+ }
707
+ return this._oLocalStorage[sKey];
711
708
  };
712
709
 
713
710
  FlexibleColumnLayout.prototype._announceMessage = function (sResourceBundleKey) {
@@ -731,7 +728,7 @@ sap.ui.define([
731
728
  this._setColumnPagesRendered(oColumnNavContainer.getId(), bHasPages);
732
729
 
733
730
  if (this._hasAnyColumnPagesRendered() !== bHadAnyColumnPagesRendered) {
734
- this._hideShowArrows();
731
+ this._hideShowColumnSeparators();
735
732
  }
736
733
  };
737
734
 
@@ -787,27 +784,6 @@ sap.ui.define([
787
784
  };
788
785
  };
789
786
 
790
- /**
791
- * Formats <code>FlexibleColumnLayoutAccessibleLandmarkInfo</code> label/tooltip of the provided <code>FlexibleColumnLayout</code> arrow.
792
- *
793
- * @param {sap.f.FlexibleColumnLayoutAccessibleLandmarkInfo} oLandmarkInfo FlexibleColumnLayout LandmarkInfo
794
- * @param {string} sArrowAggregationName arrow aggregation name of the layout
795
- * @private
796
- */
797
- FlexibleColumnLayout.prototype._formatArrowLandmarkInfo = function (oLandmarkInfo, sArrowAggregationName) {
798
- var sLabel = null,
799
- sArrowName = FlexibleColumnLayout.ARROW_AGGREGATION_TO_LABEL_MAP[sArrowAggregationName];
800
-
801
- if (oLandmarkInfo) {
802
- sLabel = oLandmarkInfo["get" + sArrowName + "Label"]();
803
- }
804
-
805
- this.getAggregation(sArrowAggregationName).setTooltip(
806
- sLabel ||
807
- FlexibleColumnLayout._getResourceBundle().getText(FlexibleColumnLayout.DEFAULT_ARROW_LABELS[sArrowName]
808
- ));
809
- };
810
-
811
787
  /**
812
788
  * Proxies the navigation events from the internal nav containers to the app.
813
789
  * @param oEvent
@@ -899,7 +875,6 @@ sap.ui.define([
899
875
 
900
876
  var vResult = this.setProperty("layout", sNewLayout, true);
901
877
  this._oLayoutHistory.addEntry(sNewLayout);
902
- this._hideShowArrows();
903
878
  this._resizeColumns();
904
879
 
905
880
  return vResult;
@@ -928,6 +903,12 @@ sap.ui.define([
928
903
 
929
904
  this._deregisterResizeHandler();
930
905
  this._oAnimationEndListener.cancelAll();
906
+
907
+ if (this.$().length) {
908
+ FlexibleColumnLayout.COLUMN_ORDER.slice().forEach(function (sColumn) {
909
+ this._$columns[sColumn].removeClass(FlexibleColumnLayout.ANIMATED_COLUMN_CLASS_NAME);
910
+ }.bind(this));
911
+ }
931
912
  };
932
913
 
933
914
  FlexibleColumnLayout.prototype.onAfterRendering = function () {
@@ -937,7 +918,6 @@ sap.ui.define([
937
918
 
938
919
  this._cacheDOMElements();
939
920
 
940
- this._hideShowArrows();
941
921
  this._resizeColumns();
942
922
 
943
923
  this._flushColumnContent("begin");
@@ -945,6 +925,37 @@ sap.ui.define([
945
925
  this._flushColumnContent("end");
946
926
 
947
927
  this._fireStateChange(false, false);
928
+ this._bNeverRendered = false;
929
+ };
930
+
931
+ FlexibleColumnLayout.prototype.onmousedown = function (oEvent) {
932
+ if (this._ignoreMouse) {
933
+ return;
934
+ }
935
+ var oTarget = this._getColumnSeparator(oEvent.target);
936
+
937
+ if (!oTarget) {
938
+ return;
939
+ }
940
+ this._ignoreTouch = true;
941
+ this._onColumnSeparatorMoveStart(oEvent, oTarget);
942
+ };
943
+
944
+ FlexibleColumnLayout.prototype.ontouchstart = function (oEvent) {
945
+ if (this._ignoreTouch) {
946
+ return;
947
+ }
948
+ var oTarget = this._getColumnSeparator(oEvent.target);
949
+
950
+ if (!oTarget) {
951
+ return;
952
+ }
953
+ if (!oEvent.changedTouches || !oEvent.changedTouches[0]) {
954
+ // No touch in event
955
+ return;
956
+ }
957
+ this._ignoreMouse = true;
958
+ this._onColumnSeparatorMoveStart(oEvent.changedTouches[0], oTarget, true);
948
959
  };
949
960
 
950
961
  /**
@@ -984,11 +995,13 @@ sap.ui.define([
984
995
  * Checks whether or not the focus is in some columns that are previous to the current
985
996
  * column. For example, if the current is "end", checks if the focus is
986
997
  * in "mid" or "begin" columns.
998
+ * @param {sap.f.LayoutType} sLayout the layout to check
987
999
  * @returns {boolean} whether or not the focus is in columns that are previous to the current column
988
1000
  * @private
989
1001
  */
990
- FlexibleColumnLayout.prototype._isFocusInSomeOfThePreviousColumns = function () {
991
- var iIndex = FlexibleColumnLayout.COLUMN_ORDER.indexOf(this._sPreviuosLastVisibleColumn) - 1,
1002
+ FlexibleColumnLayout.prototype._isFocusInSomeOfThePreviousColumns = function (sLayout) {
1003
+ var sLastVisibleColumn = this._getLastVisibleColumnForLayout(sLayout),
1004
+ iIndex = FlexibleColumnLayout.COLUMN_ORDER.indexOf(sLastVisibleColumn) - 1,
992
1005
  oCurrentColumn;
993
1006
 
994
1007
  for (; iIndex >= 0; iIndex--) {
@@ -1024,6 +1037,7 @@ sap.ui.define([
1024
1037
  this._removeNavContainersFocusOutDelegate();
1025
1038
  this._oRenderedColumnPagesBoolMap = null;
1026
1039
  this._oColumnFocusInfo = null;
1040
+ this._oLocalStorage = null;
1027
1041
  this._deregisterResizeHandler();
1028
1042
  this._handleEvent(jQuery.Event("Destroy"));
1029
1043
  };
@@ -1065,52 +1079,6 @@ sap.ui.define([
1065
1079
  return [this._getBeginColumn(), this._getMidColumn(), this._getEndColumn()];
1066
1080
  };
1067
1081
 
1068
- /**
1069
- * Creates the buttons for the layout arrows, which are initially hidden and will only be shown on demand without re-rendering.
1070
- * @private
1071
- */
1072
- FlexibleColumnLayout.prototype._initButtons = function () {
1073
- var oBeginColumnBackArrow = new Button(this.getId() + "-beginBack", {
1074
- icon: "sap-icon://slim-arrow-left",
1075
- type: "Transparent",
1076
- press: function () {
1077
- this._onArrowClick("left");
1078
- this._announceMessage("FCL_MIDDLE_COLUMN_EXPANDED_MESSAGE");
1079
- }.bind(this)
1080
- }).addStyleClass("sapFFCLNavigationButton").addStyleClass("sapFFCLNavigationButtonRight");
1081
- this.setAggregation("_beginColumnBackArrow", oBeginColumnBackArrow, true);
1082
-
1083
- var oMidColumnForwardArrow = new Button(this.getId() + "-midForward", {
1084
- icon: "sap-icon://slim-arrow-right",
1085
- type: "Transparent",
1086
- press: function () {
1087
- this._onArrowClick("right");
1088
- this._announceMessage("FCL_FIRST_COLUMN_EXPANDED_MESSAGE");
1089
- }.bind(this)
1090
- }).addStyleClass("sapFFCLNavigationButton").addStyleClass("sapFFCLNavigationButtonLeft");
1091
- this.setAggregation("_midColumnForwardArrow", oMidColumnForwardArrow, true);
1092
-
1093
- var oMidColumnBackArrow = new Button(this.getId() + "-midBack", {
1094
- icon: "sap-icon://slim-arrow-left",
1095
- type: "Transparent",
1096
- press: function () {
1097
- this._onArrowClick("left");
1098
- this._announceMessage("FCL_LAST_COLUMN_EXPANDED_MESSAGE");
1099
- }.bind(this)
1100
- }).addStyleClass("sapFFCLNavigationButton").addStyleClass("sapFFCLNavigationButtonRight");
1101
- this.setAggregation("_midColumnBackArrow", oMidColumnBackArrow, true);
1102
-
1103
- var oEndColumnForwardArrow = new Button(this.getId() + "-endForward", {
1104
- icon: "sap-icon://slim-arrow-right",
1105
- type: "Transparent",
1106
- press: function () {
1107
- this._onArrowClick("right");
1108
- this._announceMessage("FCL_MIDDLE_COLUMN_EXPANDED_MESSAGE");
1109
- }.bind(this)
1110
- }).addStyleClass("sapFFCLNavigationButton").addStyleClass("sapFFCLNavigationButtonLeft");
1111
- this.setAggregation("_endColumnForwardArrow", oEndColumnForwardArrow, true);
1112
- };
1113
-
1114
1082
  /**
1115
1083
  * Saves the DOM references of the columns and layout arrows.
1116
1084
  * @private
@@ -1119,7 +1087,9 @@ sap.ui.define([
1119
1087
  this._cacheColumns();
1120
1088
 
1121
1089
  if (!Device.system.phone) {
1122
- this._cacheArrows();
1090
+ this._cacheColumnSeparators();
1091
+ this._$overlay = this.$("overlay");
1092
+ this._$overlaySeparator = this.$("overlaySeparator");
1123
1093
  }
1124
1094
  };
1125
1095
 
@@ -1131,225 +1101,370 @@ sap.ui.define([
1131
1101
  };
1132
1102
  };
1133
1103
 
1134
- FlexibleColumnLayout.prototype._cacheArrows = function () {
1135
- this._oColumnSeparatorArrows = {
1136
- beginBack: this.$("beginBack"),
1137
- midForward: this.$("midForward"),
1138
- midBack: this.$("midBack"),
1139
- endForward: this.$("endForward")
1104
+ FlexibleColumnLayout.prototype._cacheColumnSeparators = function () {
1105
+ this._oColumnSeparators = {
1106
+ begin: this.$("separator-begin"),
1107
+ end: this.$("separator-end")
1140
1108
  };
1141
1109
  };
1142
1110
 
1143
1111
  /**
1144
1112
  * Returns the number of columns that have width > 0
1145
- * @returns {Array.<string>}
1113
+ * @param {sap.f.LayoutType} sLayout the layout to check
1114
+ * @returns {number} the count
1146
1115
  * @private
1147
1116
  */
1148
- FlexibleColumnLayout.prototype._getVisibleColumnsCount = function () {
1117
+ FlexibleColumnLayout.prototype._getVisibleColumnsCount = function (sLayout) {
1118
+ return this._getVisibleColumnsForLayout(sLayout).length;
1119
+ };
1120
+
1121
+ /**
1122
+ * Returns the names of columns that have width > 0
1123
+ * @param {sap.f.LayoutType} sLayout the layout to check
1124
+ * @returns {Array.<string>} the column names
1125
+ * @private
1126
+ */
1127
+ FlexibleColumnLayout.prototype._getVisibleColumnsForLayout = function (sLayout) {
1149
1128
  return FlexibleColumnLayout.COLUMN_ORDER.filter(function (sColumn) {
1150
- return this._getColumnSize(sColumn) > 0;
1151
- }, this).length;
1129
+ return this._getColumnSizeForLayout(sColumn, sLayout) > 0;
1130
+ }, this);
1152
1131
  };
1153
1132
 
1154
1133
  /**
1155
1134
  * Returns the number of columns that have width > 0.
1156
- * @returns {number}
1135
+ * @returns {number} the count
1157
1136
  * @private
1158
1137
  */
1159
- FlexibleColumnLayout.prototype._getVisibleArrowsCount = function () {
1160
- if (!this._oColumnSeparatorArrows) {
1138
+ FlexibleColumnLayout.prototype._getVisibleColumnSeparatorsCount = function () {
1139
+ if (!this._oColumnSeparators) {
1161
1140
  return 0;
1162
1141
  }
1163
1142
 
1164
- return Object.keys(this._oColumnSeparatorArrows).filter(function (sArrow) {
1165
- return this._oColumnSeparatorArrows[sArrow].data("visible");
1143
+ return Object.keys(this._oColumnSeparators).filter(function (sName) {
1144
+ return this._oColumnSeparators[sName].data("visible");
1166
1145
  }, this).length;
1167
1146
  };
1168
1147
 
1169
1148
  /**
1170
1149
  * Returns the total width available for the columns.
1171
- * @param {boolean} bHasInsetColumn
1172
- * @returns {number}
1150
+ * @param {sap.f.LayoutType} sLayout the layout t ckeck
1151
+ * @returns {number} the width in px
1173
1152
  * @private
1174
1153
  */
1175
- FlexibleColumnLayout.prototype._getTotalColumnsWidth = function (bHasInsetColumn) {
1176
- var iSeparatorsCount = this._getVisibleArrowsCount();
1177
- if (bHasInsetColumn) { // inset column has temporarily hidden nav arrow,
1178
- // but empty space *in place of* the navigation arrows for visual consistency
1179
- iSeparatorsCount++;
1180
- }
1181
-
1182
- return this._getControlWidth() - iSeparatorsCount * FlexibleColumnLayout.NAVIGATION_ARROW_WIDTH;
1183
- };
1184
-
1185
- /**
1186
- * Changes the width
1154
+ FlexibleColumnLayout.prototype._getTotalColumnsWidth = function (sLayout) {
1155
+ var iSeparatorsCount = this._getRequiredColumnSeparatorsForLayout(sLayout).length;
1156
+ return this._getControlWidth() - iSeparatorsCount * FlexibleColumnLayout.COLUMN_SEPARATOR_WIDTH;
1157
+ };
1158
+
1159
+ /**
1160
+ * Changes the width of the columns
1161
+ * @param {object} [oOptions] custom resize options (the custom sizes on interactive resize). If not
1162
+ * provided, the default options returned from <code>_getDefaultResizeOptions</code> will be taken.
1163
+ * @param {Object<string,number>} [oOptions.columnWidths] the column widths. If not provided, the default widths
1164
+ * for the current layout will be taken
1165
+ * @param {int} [oOptions.columnWidths.begin] the width of the 'begin' column in px
1166
+ * @param {int} [oOptions.columnWidths.mid] the width of the 'mid' column in px
1167
+ * @param {int} [oOptions.columnWidths.end] the width of the 'end' column in px
1168
+ * @param {sap.f.LayoutType} [oOptions.layout] the current layout type
1169
+ * @param {sap.f.LayoutType} [oOptions.previousLayout] the current layout type. If not provided,
1170
+ * the previous entry from the <code>sap.f.FlexibleColumnLayout.LayoutHistory</code> will be taken.
1171
+ * @param {boolean} oOptions.restoreFocusOnBackNavigation if focus should be restored upon
1172
+ * resize that corresponds to back navigation
1173
+ * @param {boolean} oOptions.updateDetailedActiveClasses specifies if the CSS classes
1174
+ * 'sapFFCLColumnOnlyActive', sapFFCLColumnFirstActive, sapFFCLColumnLastActive should be updated
1175
+ * @param {boolean} oOptions.updateContextualSettings specifies if the contextual settings (for the
1176
+ * new widths) should be propagated to the controls inside the columns
1177
+ * @param {boolean} oOptions.updateMediaCSSClases specifies if the CSS classes for the media
1178
+ * corresponsing to the current columns' width should be set to the columns
1179
+ * @param {boolean} oOptions.hasAnimations specifies if animations are enabled
1187
1180
  * @private
1188
1181
  */
1189
- FlexibleColumnLayout.prototype._resizeColumns = function () {
1190
- var iPercentWidth,
1191
- iAvailableWidth,
1192
- aColumns = FlexibleColumnLayout.COLUMN_ORDER.slice(),
1193
- bRtl = Configuration.getRTL(),
1194
- sAnimationMode = Configuration.getAnimationMode(),
1195
- bHasAnimations = sAnimationMode !== Configuration.AnimationMode.none && sAnimationMode !== Configuration.AnimationMode.minimal,
1196
- aActiveColumns,
1197
- iVisibleColumnsCount,
1198
- iDefaultVisibleColumnsCount,
1182
+ FlexibleColumnLayout.prototype._resizeColumns = function (oOptions) {
1183
+ var aColumns = FlexibleColumnLayout.COLUMN_ORDER.slice(),
1184
+ bHasAnimations,
1199
1185
  sLayout,
1186
+ sPreviousLayout,
1187
+ iVisibleColumnsCount,
1188
+ oColumnWidths,
1200
1189
  sLastVisibleColumn,
1201
1190
  bInsetMidColumn,
1202
1191
  bRestoreFocusOnBackNavigation,
1203
- oPendingAnimationEnd = {};
1192
+ oPendingAnimationEnd;
1204
1193
 
1205
1194
  // Stop here if the control isn't rendered yet
1206
1195
  if (!this.isActive()) {
1207
1196
  return;
1208
1197
  }
1209
1198
 
1210
- iVisibleColumnsCount = this._getVisibleColumnsCount();
1199
+ oOptions = merge(this._getDefaultResizeOptions(), oOptions);
1200
+ sLayout = oOptions.layout;
1201
+ iVisibleColumnsCount = this._getVisibleColumnsCount(sLayout);
1202
+
1211
1203
  if (iVisibleColumnsCount === 0) {
1212
1204
  return;
1213
1205
  }
1214
1206
 
1215
- sLayout = this.getLayout();
1216
- // the default number of columns is the number at maximum control width
1217
- iDefaultVisibleColumnsCount = this._getMaxColumnsCountForLayout(sLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT);
1218
-
1219
- sLastVisibleColumn = aColumns[iDefaultVisibleColumnsCount - 1];
1220
-
1221
- bRestoreFocusOnBackNavigation = this.getRestoreFocusOnBackNavigation() &&
1222
- this._isNavigatingBackward(sLastVisibleColumn) &&
1223
- !this._isFocusInSomeOfThePreviousColumns();
1224
-
1207
+ bHasAnimations = oOptions.hasAnimations;
1208
+ sPreviousLayout = oOptions.previousLayout;
1225
1209
  bInsetMidColumn = (iVisibleColumnsCount === 3) && (sLayout === LT.ThreeColumnsEndExpanded);
1226
- // Calculate the width available for the columns
1227
- iAvailableWidth = this._getTotalColumnsWidth(bInsetMidColumn);
1228
-
1229
- // Animations on - Before resizing pin the columns that should not be animated in order to create the reveal/conceal effect
1230
- if (bHasAnimations) {
1210
+ oColumnWidths = oOptions.columnWidths || this._getAllColumnSizesForLayout(sLayout, true);
1211
+ sLastVisibleColumn = this._getLastVisibleColumnForLayout(sLayout);
1212
+ bRestoreFocusOnBackNavigation = oOptions.restoreFocusOnBackNavigation &&
1213
+ sPreviousLayout &&
1214
+ this._isNavigatingBackward(sLayout, sPreviousLayout) &&
1215
+ !this._isFocusInSomeOfThePreviousColumns(sPreviousLayout);
1216
+ oPendingAnimationEnd = (bHasAnimations && sPreviousLayout) ?
1217
+ // checks if the previous animation completed
1218
+ this._getAnimationEndStatusForColumns() : {};
1231
1219
 
1232
- aColumns.forEach(function (sColumn) {
1233
- var bShouldConcealColumn = this._shouldConcealColumn(iDefaultVisibleColumnsCount, sColumn),
1234
- bShouldRevealColumn = this._shouldRevealColumn(iDefaultVisibleColumnsCount, sColumn === sLastVisibleColumn),
1235
- oColumn = this._$columns[sColumn];
1236
1220
 
1237
- oColumn.toggleClass(FlexibleColumnLayout.PINNED_COLUMN_CLASS_NAME, bShouldConcealColumn || bShouldRevealColumn);
1238
-
1239
- }, this);
1221
+ // Animations on - Before resizing pin the columns that should not be animated in order to create the reveal/conceal effect
1222
+ if (bHasAnimations && sPreviousLayout) {
1223
+ this._pinColumnsBeforeResize(sLayout, sPreviousLayout, oColumnWidths);
1240
1224
 
1241
- // check if the previous animation completed
1242
- aColumns.forEach(function(sColumn) {
1243
- oPendingAnimationEnd[sColumn] = this._oAnimationEndListener.isWaitingForColumnResizeEnd(this._$columns[sColumn]);
1244
- }, this);
1245
1225
  // detach all listeners to any previous unfinished animation
1246
1226
  this._oAnimationEndListener.cancelAll();
1247
1227
  }
1248
1228
 
1229
+ aColumns.slice().forEach(function (sColumn) {
1230
+ this._$columns[sColumn].removeClass(FlexibleColumnLayout.ANIMATED_COLUMN_CLASS_NAME);
1231
+ }.bind(this));
1232
+
1233
+ // update separator visibility only after pinning the columns
1234
+ // to prevent unnecessary resize in the concealed column due to
1235
+ // change of its width upon hiding its preceding separator
1236
+ this._hideShowColumnSeparators();
1237
+
1249
1238
 
1250
1239
  aColumns.forEach(function (sColumn) {
1251
- var oColumn = this._$columns[sColumn],
1252
- oColumnDomRef = oColumn.get(0),
1253
- iNewWidth,
1254
- sNewWidth,
1255
- bShouldRevealColumn,
1256
- bShouldConcealColumn,
1257
- bPinned,
1258
- bCanResizeColumnWithAnimation,
1259
- oOptions;
1260
-
1261
-
1262
- // Calculate the width of the column
1263
- iPercentWidth = this._getColumnSize(sColumn);
1264
- iNewWidth = Math.round(iAvailableWidth * (iPercentWidth / 100));
1265
- if ([100, 0].indexOf(iPercentWidth) !== -1) {
1266
- sNewWidth = iPercentWidth + "%";
1267
- } else {
1268
- sNewWidth = iNewWidth + "px";
1269
- }
1270
1240
 
1241
+ var iWidth = oColumnWidths[sColumn],
1242
+ bShouldRevealColumn = bHasAnimations
1243
+ && this._shouldRevealColumn(sColumn, sLayout, sPreviousLayout),
1244
+ //&& this._$columns[sColumn].width() < FlexibleColumnLayout.COLUMN_MIN_WIDTH,
1245
+ bShouldConcealColumn = bHasAnimations
1246
+ && this._shouldConcealColumn(sColumn, sLayout, sPreviousLayout);
1271
1247
 
1272
- // set the resize options for the column:
1273
- oOptions = {
1274
- previousAnimationCompleted: !oPendingAnimationEnd[oColumn],
1275
- iNewWidth: iNewWidth,
1276
- shouldRestoreFocus: bRestoreFocusOnBackNavigation && (sColumn === sLastVisibleColumn),
1277
- hidden: iPercentWidth === 0 && this._oColumnWidthInfo[sColumn] === 0 // is hidden both before and after the resize
1278
- };
1279
- if (bHasAnimations) {
1280
- bShouldRevealColumn = this._shouldRevealColumn(iDefaultVisibleColumnsCount, sColumn === sLastVisibleColumn);
1281
- bShouldConcealColumn = this._shouldConcealColumn(iDefaultVisibleColumnsCount, sColumn);
1282
- bPinned = bShouldRevealColumn || bShouldConcealColumn;
1283
- oOptions = merge(oOptions, {
1284
- hasAnimations: true,
1285
- shouldConcealColumn: bShouldConcealColumn,
1286
- pinned: bPinned
1287
- });
1288
- bCanResizeColumnWithAnimation = this._canResizeColumnWithAnimation(sColumn, oOptions);
1289
- }
1248
+ this._resizeColumn(sColumn, {
1249
+ width: iWidth,
1290
1250
 
1251
+ shouldRestoreFocus: bRestoreFocusOnBackNavigation &&
1252
+ (sColumn === sLastVisibleColumn),
1291
1253
 
1292
- if (!bShouldConcealColumn) { // do not remove the active class of the concealed column for now (it should remain visible until the end of animations for other columns)
1293
- // Add the active class to the column if it shows something
1294
- oColumn.toggleClass("sapFFCLColumnActive", iPercentWidth > 0);
1295
- }
1254
+ shouldInsetColumn: bInsetMidColumn && (sColumn === "mid"),
1296
1255
 
1297
- oColumn.toggleClass("sapFFCLColumnInset", bInsetMidColumn && (sColumn === "mid"));
1256
+ shouldRevealColumn: bShouldRevealColumn,
1257
+ shouldConcealColumn: bShouldConcealColumn,
1298
1258
 
1299
- // Remove all the classes that are used for HCB theme borders, they will be set again later
1300
- oColumn.removeClass("sapFFCLColumnHidden");
1301
- oColumn.removeClass("sapFFCLColumnOnlyActive");
1302
- oColumn.removeClass("sapFFCLColumnLastActive");
1303
- oColumn.removeClass("sapFFCLColumnFirstActive");
1304
-
1305
-
1306
- // toggle ResizeHandler during the animation
1307
- if (bCanResizeColumnWithAnimation) {
1308
- ResizeHandler.suspend(oColumnDomRef); // Suspend ResizeHandler while animation is running
1309
- this._oAnimationEndListener.waitForColumnResizeEnd(oColumn).then(function() {
1310
- ResizeHandler.resume(oColumnDomRef); // Resume ResizeHandler once animation ended
1311
- }).catch(function() {
1312
- ResizeHandler.resume(oColumnDomRef); // Resume ResizeHandler if animation cancelled
1313
- });
1259
+ // is hidden both before and after the resize
1260
+ hidden: iWidth === 0 && this._oColumnWidthInfo[sColumn] === 0,
1261
+ autoSize: iWidth > 0 && (sColumn === "mid"),
1262
+
1263
+ hasAnimations: bHasAnimations,
1264
+ previousAnimationCompleted: !oPendingAnimationEnd[this._$columns[sColumn]],
1265
+ updateContextualSettings: oOptions.updateContextualSettings,
1266
+ updateMediaCSSClases: oOptions.updateMediaCSSClases
1267
+ });
1268
+ }, this);
1269
+
1270
+ if (oOptions.updateDetailedActiveClasses) {
1271
+ this._addDetailedActiveClasses(sLayout);
1272
+ }
1273
+ };
1274
+
1275
+ /**
1276
+ * Changes the width of the given column
1277
+ * @param {"begin" | "mid" | "end"} sColumn the column name
1278
+ * @param {object} oColumnConfig resize options
1279
+ * @param {int} oColumnConfig.width the width of the column in px
1280
+ * @param {boolean} oColumnConfig.shouldInsetColumn if CSS class "sapFFCLColumnInset"
1281
+ * should be set
1282
+ * @param {boolean} oColumnConfig.autoSize if autoSize, the it should NOT set a fixed width
1283
+ * (in px) to the column, to allow the default width of "100%" take effect. As a result,
1284
+ * the column will take the space that remains after sizing its sibling columns
1285
+ * @param {boolean} oColumnConfig.shouldRestoreFocus if focus should be restored after resize
1286
+ * @param {boolean} oColumnConfig.shouldRevealColumn if the column should be resized with
1287
+ * reveal effect
1288
+ * @param {boolean} oColumnConfig.shouldConcealColumn if the column should be resized with
1289
+ * conceal effect
1290
+ * @param {boolean} oColumnConfig.updateContextualSettings specifies if the contextual settings (for the
1291
+ * new widths) should be propagated to the controls inside the column
1292
+ * @param {boolean} oColumnConfig.updateMediaCSSClases specifies if the CSS classes for the media
1293
+ * corresponsing to the current width should be set to the column
1294
+ * @param {boolean} oColumnConfig.hasAnimations specifies if animations are enabled
1295
+ * @private
1296
+ */
1297
+ FlexibleColumnLayout.prototype._resizeColumn = function (sColumn, oColumnConfig) {
1298
+ var $column = this._$columns[sColumn],
1299
+ oColumnDomRef = $column.get(0),
1300
+ iNewWidth = oColumnConfig.width,
1301
+ sNewWidth = convertPxToCSSSizeString(iNewWidth, this._getControlWidth(), oColumnConfig.shouldInsetColumn),
1302
+ bAutoSize = oColumnConfig.autoSize,
1303
+ bAnimationsEnabled = oColumnConfig.hasAnimations,
1304
+ bPinned = oColumnConfig.shouldRevealColumn || oColumnConfig.shouldConcealColumn,
1305
+ bResizeColumnWithAnimation = this._canResizeColumnWithAnimation(sColumn, oColumnConfig),
1306
+ bSuspendResizeHandler = bAnimationsEnabled && (bResizeColumnWithAnimation || bAutoSize) && !bPinned,
1307
+ fnAfterResizeCallback = this._afterColumnResize.bind(this, sColumn, merge(oColumnConfig, {
1308
+ resumeResizeHandler: bSuspendResizeHandler // toggle back after resize
1309
+ })),
1310
+ fnResizeErrorCallback = function() {
1311
+ ResizeHandler.resume(oColumnDomRef);
1312
+ oColumnDomRef.querySelector(".sapFFCLColumnContent").style.width = "";
1313
+ };
1314
+
1315
+ if (bAutoSize) {
1316
+ // do not set a fixed size to allow the default width:100% take effect
1317
+ sNewWidth = "";
1314
1318
  }
1315
1319
 
1320
+ // Add the active class to the column if it shows something
1321
+ // the concealed column should remain visible until the end of animations for other columns
1322
+ $column.toggleClass("sapFFCLColumnActive", iNewWidth > 0 || oColumnConfig.shouldConcealColumn);
1323
+ $column.toggleClass("sapFFCLColumnInset", oColumnConfig.shouldInsetColumn);
1324
+ // Remove all the classes that are used for HCB theme borders, they will be set again later
1325
+ $column.removeClass("sapFFCLColumnHidden sapFFCLColumnOnlyActive sapFFCLColumnLastActive sapFFCLColumnFirstActive");
1316
1326
 
1317
- // Update the width of the column DOM element
1318
- if (!bShouldConcealColumn) { // regular case
1319
- oColumn.width(sNewWidth);
1320
- } else {
1321
- this._oAnimationEndListener.waitForAllColumnsResizeEnd().then(function() {
1322
- // the concealed column should be resized last (after all other columns resized)
1323
- oColumn.width(sNewWidth);
1324
- }).catch(function() {
1325
- // no action when no resize
1326
- });
1327
+ // Suspend ResizeHandler while animation is running
1328
+ if (bSuspendResizeHandler) {
1329
+ ResizeHandler.suspend(oColumnDomRef);
1327
1330
  }
1328
1331
 
1332
+ if (bResizeColumnWithAnimation) {
1333
+ $column.addClass(FlexibleColumnLayout.ANIMATED_COLUMN_CLASS_NAME);
1334
+ $column.width(sNewWidth);
1335
+ this._attachAfterColumnResizedOnce(sColumn, fnAfterResizeCallback, fnResizeErrorCallback);
1336
+
1337
+ } else if (bAutoSize && bAnimationsEnabled){
1338
+ $column.width(sNewWidth);
1339
+ this._attachAfterAllColumnsResizedOnce(fnAfterResizeCallback, fnResizeErrorCallback);
1329
1340
 
1330
- // Adjust column after resize
1331
- if (bCanResizeColumnWithAnimation || bPinned) {
1332
- this._oAnimationEndListener.waitForAllColumnsResizeEnd().then(this._afterColumnResize.bind(this, sColumn, oOptions)).catch(function() {
1333
- // no action if resize did not complete
1334
- });
1335
1341
  } else {
1336
- this._afterColumnResize(sColumn, oOptions);
1342
+ $column.width(sNewWidth);
1343
+ fnAfterResizeCallback();
1337
1344
  }
1338
1345
 
1339
-
1340
1346
  // For tablet and desktop - notify child controls to render with reduced container size, if they need to
1341
- if (!Device.system.phone) {
1347
+ if (oColumnConfig.updateContextualSettings && !Device.system.phone) {
1342
1348
  this._updateColumnContextualSettings(sColumn, iNewWidth);
1349
+ }
1350
+ if (oColumnConfig.updateMediaCSSClases && !Device.system.phone) {
1343
1351
  this._updateColumnCSSClasses(sColumn, iNewWidth);
1344
1352
  }
1353
+ };
1345
1354
 
1355
+ /**
1356
+ * Adjusts the column after resize
1357
+ *
1358
+ * @param {"begin" | "mid" | "end"} sColumn the column name
1359
+ * @param {object} oOptions the resize options
1360
+ * @param {int} oOptions.width the width of the column in px
1361
+ * @param {boolean} oOptions.shouldRestoreFocus if focus should be restored after resize
1362
+ * @param {boolean} oOptions.shouldRevealColumn if the column is being resized with reveal effect
1363
+ * @param {boolean} oOptions.shouldConcealColumn if the column is being resized with conceal effect
1364
+ * @param {boolean} oOptions.resumeResizeHandler if the <code>ResizeHandler.resume</code> should
1365
+ * be called for the column's DOM elemnt after the resize
1366
+ * @private
1367
+ */
1368
+ FlexibleColumnLayout.prototype._afterColumnResize = function (sColumn, oOptions) {
1369
+ var oColumn = this._$columns[sColumn],
1370
+ bShouldRevealColumn = oOptions.shouldRevealColumn,
1371
+ bShouldConcealColumn = oOptions.shouldConcealColumn,
1372
+ iNewWidth = oOptions.width,
1373
+ bShouldRestoreFocus = oOptions.shouldRestoreFocus;
1346
1374
 
1375
+ if (bShouldRevealColumn || bShouldConcealColumn ) {
1376
+ oColumn[0].querySelector(".sapFFCLColumnContent").style.width = "";
1377
+ }
1378
+ oColumn.toggleClass(FlexibleColumnLayout.PINNED_COLUMN_CLASS_NAME, false);
1379
+ oColumn.toggleClass(FlexibleColumnLayout.ANIMATED_COLUMN_CLASS_NAME, false);
1380
+
1381
+ if (bShouldConcealColumn) {
1382
+ // The column does not show anything anymore, so we can remove the active class
1383
+ oColumn.removeClass("sapFFCLColumnActive");
1384
+ }
1385
+
1386
+ //BCP: 1980006195
1387
+ oColumn.toggleClass("sapFFCLColumnHidden", iNewWidth === 0);
1388
+
1389
+ if (oOptions.resumeResizeHandler) {
1390
+ ResizeHandler.resume(oColumn[0]);
1391
+ }
1392
+
1393
+ this._cacheColumnWidth(sColumn, iNewWidth);
1394
+ if (bShouldRestoreFocus) {
1395
+ this._restoreFocusToColumn(sColumn);
1396
+ }
1397
+ };
1398
+
1399
+ FlexibleColumnLayout.prototype._pinColumnsBeforeResize = function (sLayout, sPreviousLayout, oColumnWidths) {
1400
+ FlexibleColumnLayout.COLUMN_ORDER.slice().forEach(function (sColumn) {
1401
+ var bShouldConcealColumn = this._shouldConcealColumn(sColumn, sLayout, sPreviousLayout),
1402
+ bShouldRevealColumn = this._shouldRevealColumn(sColumn, sLayout, sPreviousLayout),
1403
+ bShouldPin = bShouldConcealColumn || bShouldRevealColumn,
1404
+ oColumn = this._$columns[sColumn],
1405
+ oColumnDomRef = oColumn[0];
1406
+
1407
+ oColumn.toggleClass(FlexibleColumnLayout.PINNED_COLUMN_CLASS_NAME, bShouldPin);
1408
+
1409
+ if (bShouldRevealColumn) {
1410
+ oColumnDomRef.querySelector(".sapFFCLColumnContent").style.width = convertPxToCSSSizeString(oColumnWidths[sColumn], this._getControlWidth());
1411
+ } else if (bShouldConcealColumn) {
1412
+ oColumnDomRef.querySelector(".sapFFCLColumnContent").style.width = oColumnDomRef.offsetWidth + "px";
1413
+ }
1414
+
1415
+ }, this);
1416
+ };
1417
+
1418
+ FlexibleColumnLayout.prototype._getAnimationEndStatusForColumns = function () {
1419
+ var oPendingAnimationEnd = {};
1420
+ // check if the previous animation completed
1421
+ FlexibleColumnLayout.COLUMN_ORDER.slice().forEach(function(sColumn) {
1422
+ oPendingAnimationEnd[sColumn] = this._oAnimationEndListener.isWaitingForColumnResizeEnd(this._$columns[sColumn]);
1347
1423
  }, this);
1424
+ return oPendingAnimationEnd;
1425
+ };
1348
1426
 
1349
- aActiveColumns = aColumns.filter(function (sColumn) {
1350
- return this._getColumnSize(sColumn) > 0;
1427
+ FlexibleColumnLayout.prototype._getAllColumnSizesForLayout = function (sLayout, bNormalizeWidths) {
1428
+ var oSizes = {};
1429
+ FlexibleColumnLayout.COLUMN_ORDER.slice().forEach(function(sColumn) {
1430
+ var iPercentSize = this._getColumnSizeForLayout(sColumn, sLayout),
1431
+ iPxSize = this._convertColumnPercentWidthToPx(iPercentSize, sLayout);
1432
+ oSizes[sColumn] = iPxSize;
1351
1433
  }, this);
1352
1434
 
1435
+ ///needed to cover the case when the custom column sizes (in %) were saved
1436
+ // when using a *larger* screen size, to prevent too narrow columns if the same sizes (in %)
1437
+ // are applied on the smaller screen size
1438
+ if (bNormalizeWidths) {
1439
+ this._normalizeColumnWidths(oSizes, this._getVisibleColumnsForLayout(sLayout));
1440
+ }
1441
+ return oSizes;
1442
+ };
1443
+
1444
+ FlexibleColumnLayout.prototype._getDefaultResizeOptions = function () {
1445
+ var sAnimationMode = Configuration.getAnimationMode();
1446
+ return {
1447
+ layout: this.getLayout(),
1448
+ previousLayout: this._getPreviousLayout(),
1449
+ restoreFocusOnBackNavigation: this.getRestoreFocusOnBackNavigation(),
1450
+ updateDetailedActiveClasses: true,
1451
+ updateContextualSettings: true,
1452
+ updateMediaCSSClases: true,
1453
+ hasAnimations: sAnimationMode !== Configuration.AnimationMode.none && sAnimationMode !== Configuration.AnimationMode.minimal
1454
+ };
1455
+ };
1456
+
1457
+ FlexibleColumnLayout.prototype._getPreviousLayout = function () {
1458
+ return this._getLayoutHistory().getEntry(1, true /* recent first */) || LT.OneColumn;
1459
+ };
1460
+
1461
+ FlexibleColumnLayout.prototype._addDetailedActiveClasses = function (sLayout) {
1462
+ var aColumns = FlexibleColumnLayout.COLUMN_ORDER.slice(),
1463
+ bRtl = Configuration.getRTL(),
1464
+ aActiveColumns = aColumns.filter(function (sColumn) {
1465
+ return this._getColumnSizeForLayout(sColumn, sLayout) > 0;
1466
+ }, this);
1467
+
1353
1468
  if (bRtl) {
1354
1469
  aColumns.reverse();
1355
1470
  }
@@ -1362,37 +1477,569 @@ sap.ui.define([
1362
1477
  this._$columns[aActiveColumns[0]].addClass("sapFFCLColumnFirstActive");
1363
1478
  this._$columns[aActiveColumns[aActiveColumns.length - 1]].addClass("sapFFCLColumnLastActive");
1364
1479
  }
1480
+ };
1481
+
1482
+ FlexibleColumnLayout.prototype._onColumnSeparatorMoveStart = function (oEvent, oSeparator, bTouch) {
1483
+ // needed to position the separator presizely
1484
+ var bRtl = Configuration.getRTL(),
1485
+ iStartOffset = this._getDraggedSeparatorStartOffset(oSeparator, bRtl);
1486
+
1487
+ this._oDragInfo = {
1488
+ cursorStartX: oEvent.pageX,
1489
+ cursorX: oEvent.pageX, // the mouse/finger position-x
1490
+ columnWidths: {
1491
+ begin: this._$columns.begin.get(0).offsetWidth,
1492
+ mid: this._$columns.mid.get(0).offsetWidth,
1493
+ end: this._$columns.end.get(0).offsetWidth
1494
+ },
1495
+ separator: oSeparator,
1496
+ separatorPosition: {
1497
+ x: iStartOffset,
1498
+ direction: bRtl ? "right" : "left"
1499
+ },
1500
+ layout: this.getLayout(),
1501
+ rtl: bRtl
1502
+ };
1503
+
1504
+ this._enterInteractiveResizeMode(bTouch);
1505
+ };
1506
+
1507
+ FlexibleColumnLayout.prototype._getDraggedSeparatorStartOffset = function (oSeparator, bRtl) {
1508
+ if (bRtl) {
1509
+ return window.innerWidth - oSeparator.getBoundingClientRect().right;
1510
+ }
1511
+ return oSeparator.getBoundingClientRect().left;
1512
+ };
1513
+
1514
+ FlexibleColumnLayout.prototype._onColumnSeparatorMove = function (oEvent) {
1515
+ if (oEvent.preventDefault && !(oEvent.changedTouches)) {
1516
+ oEvent.preventDefault(); // Do not select text
1517
+ }
1365
1518
 
1366
- this._storePreviousResizingInfo(iDefaultVisibleColumnsCount, sLastVisibleColumn);
1519
+ var iCursonX = getCursorPositionX(oEvent);
1520
+ this._previewResizedColumnsOnDrag(iCursonX);
1521
+ };
1522
+
1523
+ FlexibleColumnLayout.prototype._onColumnSeparatorMoveEnd = function (oEvent) {
1524
+ var iCursonX = getCursorPositionX(oEvent);
1525
+ this._previewResizedColumnsOnDrag(iCursonX, true /* resize end */);
1526
+ this._saveResizedColumWidths();
1527
+
1528
+ if (this._oDragInfo.layout !== this.getLayout()) {
1529
+ this.setLayout(this._oDragInfo.layout);
1530
+ this._fireStateChange(true, false);
1531
+ }
1532
+
1533
+ this._exitInteractiveResizeMode();
1367
1534
  };
1368
1535
 
1369
1536
  /**
1370
- * Adjusts the column after resize
1537
+ * Returns the separator for the given target. If there isn't such, null is returned
1538
+ * @param {HTMLElement} oTarget The target
1539
+ * @returns {HTMLElement|null} The found bar or null
1540
+ */
1541
+ FlexibleColumnLayout.prototype._getColumnSeparator = function (oTarget) {
1542
+ var oSeparator = oTarget,
1543
+ sId = this.getId();
1544
+
1545
+ if (oSeparator.classList.contains("sapFFCLColumnSeparatorGripIcon")) {
1546
+ oSeparator = oTarget.parentElement;
1547
+ }
1548
+
1549
+ if (oSeparator.classList.contains("sapFFCLColumnSeparatorDecorationBefore")
1550
+ || oSeparator.classList.contains("sapFFCLColumnSeparatorDecorationAfter")
1551
+ || oSeparator.classList.contains("sapFFCLColumnSeparatorGrip")) {
1552
+ oSeparator = oSeparator.parentElement;
1553
+ }
1554
+
1555
+ if (!oSeparator.id || oSeparator.id.indexOf(sId + "-separator") !== 0) {
1556
+ // The clicked element was not one of my splitter bars
1557
+ return null;
1558
+ }
1559
+ return oSeparator;
1560
+ };
1561
+
1562
+ FlexibleColumnLayout.prototype._enterInteractiveResizeMode = function (bTouch) {
1563
+ var oSeparatorPosition = this._oDragInfo.separatorPosition;
1564
+
1565
+ this._$overlay.css("display", "block");
1566
+ this._$overlaySeparator.css(oSeparatorPosition.direction, oSeparatorPosition.x);
1567
+ this._oDragInfo.separator.style.visibility = "hidden";
1568
+
1569
+ if (bTouch) {
1570
+ document.addEventListener("touchend", this._boundColumnSeparatorMoveEnd);
1571
+ document.addEventListener("touchmove", this._boundColumnSeparatorMove);
1572
+ } else {
1573
+ document.addEventListener("mouseup", this._boundColumnSeparatorMoveEnd);
1574
+ document.addEventListener("mousemove", this._boundColumnSeparatorMove);
1575
+ }
1576
+ };
1577
+
1578
+ FlexibleColumnLayout.prototype._exitInteractiveResizeMode = function () {
1579
+ this._$overlay.css("display", "");
1580
+ this._oDragInfo.separator.style.visibility = "";
1581
+ this._oDragInfo.separator.focus();
1582
+ this._ignoreMouse = false;
1583
+ this._ignoreTouch = false;
1584
+ this._oDragInfo = null;
1585
+ document.removeEventListener("mouseup", this._boundColumnSeparatorMoveEnd);
1586
+ document.removeEventListener("mousemove", this._boundColumnSeparatorMove);
1587
+ document.removeEventListener("touchend", this._boundColumnSeparatorMoveEnd);
1588
+ document.removeEventListener("touchmove", this._boundColumnSeparatorMove);
1589
+ };
1590
+
1591
+ FlexibleColumnLayout.prototype._previewResizedColumnsOnDrag = function (cursorX, bIsResizeEnd) {
1592
+ var getPositionOffset = function (iOldCursorX) {
1593
+ var iOffset = cursorX - iOldCursorX;
1594
+ return this._oDragInfo.rtl ? -iOffset : iOffset;
1595
+ }.bind(this);
1596
+
1597
+ this._oDragInfo.offsetFromPreviousPosition = getPositionOffset(this._oDragInfo.cursorX);
1598
+ this._oDragInfo.offsetFromStartPosition = getPositionOffset(this._oDragInfo.cursorStartX);
1599
+ this._oDragInfo.cursorX = cursorX;
1600
+
1601
+ if (!this._oDragInfo.offsetFromStartPosition) {
1602
+ return;
1603
+ }
1604
+
1605
+ if (!this._oDragInfo.offsetFromPreviousPosition && !bIsResizeEnd) {
1606
+ return;
1607
+ }
1608
+
1609
+ var aResizedColumns = getInteractivelyResizedColumns(this._oDragInfo.separator, this._oDragInfo.layout, this.getMaxColumnsCount()),
1610
+ sSeparator = getSeparatorName(this._oDragInfo.separator),
1611
+ bForwardResizeDirection = this._oDragInfo.offsetFromStartPosition > 0,
1612
+ sColumnEnlargedByDragging = aResizedColumns[bForwardResizeDirection ? 0 : 1],
1613
+ iSeparatorsCount = this._getVisibleColumnSeparatorsCount(),
1614
+ iSeparatorsCountDiff = 0,
1615
+ iOffsetOnSeparatorsCountChange = 0,
1616
+ iOffsetOnColumnWidthNormalization,
1617
+ sPreviousLayout = this._oDragInfo.layout,
1618
+ sLayout,
1619
+ bLayoutChange,
1620
+ oNewColumnWidths,
1621
+ bResizeWithPinning;
1622
+
1623
+ this._oDragInfo.columnWidths[aResizedColumns[0]] += this._oDragInfo.offsetFromPreviousPosition;
1624
+ this._oDragInfo.columnWidths[aResizedColumns[1]] -= this._oDragInfo.offsetFromPreviousPosition;
1625
+ this._oDragInfo.columnEnlargedByDragging = sColumnEnlargedByDragging;
1626
+
1627
+ oNewColumnWidths = merge({}, this._oDragInfo.columnWidths);
1628
+
1629
+ // if some column is below min allowed width => expand it
1630
+ this._normalizeColumnWidths(oNewColumnWidths, aResizedColumns);
1631
+
1632
+ // if normalization led to width change of some column => the column separator will be offset
1633
+ iOffsetOnColumnWidthNormalization = this._oDragInfo.columnWidths[aResizedColumns[1]] - oNewColumnWidths[aResizedColumns[1]];
1634
+
1635
+ // update the dragged separator to match the new mouse/touch position
1636
+ this._offsetDraggedColumnSeparator(this._oDragInfo.offsetFromPreviousPosition + iOffsetOnColumnWidthNormalization);
1637
+
1638
+ // if the user drags to expand a hidden column, show its content
1639
+ this._toggleColumnVisibility(sColumnEnlargedByDragging, true);
1640
+
1641
+ sLayout = this._getNextLayoutOnResizeByDrag(oNewColumnWidths, sPreviousLayout, sSeparator, bForwardResizeDirection, bIsResizeEnd);
1642
+ bLayoutChange = sLayout !== sPreviousLayout;
1643
+
1644
+ if (bLayoutChange) {
1645
+ this._hideShowColumnSeparators(sLayout);
1646
+ iSeparatorsCountDiff = iSeparatorsCount - this._getRequiredColumnSeparatorsForLayout(sLayout).length;
1647
+ if (iSeparatorsCountDiff) {
1648
+ iOffsetOnSeparatorsCountChange = FlexibleColumnLayout.COLUMN_SEPARATOR_WIDTH * iSeparatorsCountDiff;
1649
+ oNewColumnWidths.mid += iOffsetOnSeparatorsCountChange;
1650
+ }
1651
+
1652
+ bResizeWithPinning = FlexibleColumnLayout.COLUMN_ORDER.some(function(sColumnName) {
1653
+ return this._shouldRevealColumn(sColumnName, sLayout, sPreviousLayout)
1654
+ || this._shouldConcealColumn(sColumnName, sLayout, sPreviousLayout);
1655
+ }, this);
1656
+
1657
+ oNewColumnWidths = this._mergeColumnWidthsOnInteractiveLayoutChange({
1658
+ oldWidths: this._getAllColumnSizesForLayout(sLayout, true),
1659
+ newWidths: {
1660
+ [aResizedColumns[0]]: oNewColumnWidths[aResizedColumns[0]],
1661
+ [aResizedColumns[1]]: oNewColumnWidths[aResizedColumns[1]]
1662
+ },
1663
+ layout: sLayout,
1664
+ columnEnlargedByDragging: sColumnEnlargedByDragging
1665
+ });
1666
+
1667
+ this._oDragInfo.layout = sLayout;
1668
+ // allow compute dragging direction relative to the last layout
1669
+ this._oDragInfo.cursorStartX = cursorX;
1670
+ }
1671
+
1672
+ this._oDragInfo.columnWidths = oNewColumnWidths;
1673
+
1674
+ if (bResizeWithPinning) {
1675
+ // call the dedicated function in order to resize with reveal/conceal effect
1676
+ this._resizeColumns({
1677
+ columnWidths: oNewColumnWidths,
1678
+ layout: sLayout,
1679
+ previousLayout: sPreviousLayout,
1680
+ updateContextualSettings: false,
1681
+ updateMediaCSSClases: false,
1682
+ updateDetailedActiveClasses: false,
1683
+ restoreFocusOnBackNavigation: false
1684
+ });
1685
+ } else {
1686
+ // only offset the rendered columns
1687
+ // skip mid column as it has width: 100% by default (to allow the mid column
1688
+ // take the space that remains after sizing its sibling columns)
1689
+ this._$columns.begin.css("width", this._oDragInfo.columnWidths.begin + "px");
1690
+ this._$columns.end.css("width", this._oDragInfo.columnWidths.end + "px");
1691
+ }
1692
+ };
1693
+
1694
+ /**
1695
+ * Merges the default (or previously saved) column widths [for the given layout]
1696
+ * with the updated column widths upon interactive resize [when the user dragged
1697
+ * the column separators]
1698
+ * @param {object} oOptions the oprions
1699
+ * @param {Object<string,number>} oOptions.oldWidths the default (or previously saved) column widths
1700
+ * for the given layout
1701
+ * @param {Object<string,number>} oOptions.newWidths the new column widths produced
1702
+ * upon interactive resize, when the user dragged the column separators
1703
+ * @param {sap.f.LayoutType} oOptions.sLayout the layout
1704
+ * @param {"begin"|"mid"|"end"} oOptions.columnEnlargedByDragging the name of the column
1705
+ * enlarged during interactive resize
1706
+ * @returns {Object<string,number>} the merged widths
1707
+ */
1708
+ FlexibleColumnLayout.prototype._mergeColumnWidthsOnInteractiveLayoutChange = function (oOptions) {
1709
+ var oOldWidths = oOptions.oldWidths,
1710
+ oNewWidths = oOptions.newWidths,
1711
+ sLayout = oOptions.layout,
1712
+ sColumnEnlargedByDragging = oOptions.columnEnlargedByDragging,
1713
+ aResizedColumnNames = Object.keys(oNewWidths),
1714
+ iAvailableWidth = this._getTotalColumnsWidth(sLayout),
1715
+ isFullyVisible = function(sColumn) {
1716
+ return oNewWidths[sColumn] >= FlexibleColumnLayout.COLUMN_MIN_WIDTH;
1717
+ },
1718
+ autosizeMid = function(oColumnWidths) {
1719
+ // the mid column takes the remaining space after begin and end are sized
1720
+ oColumnWidths.mid = iAvailableWidth - oColumnWidths.begin - oColumnWidths.end;
1721
+ return oColumnWidths;
1722
+ },
1723
+ sColumnToUpdate;
1724
+
1725
+ if (aResizedColumnNames.indexOf("mid") > -1) {
1726
+ // the other resized column is either 'begin' or 'end' =>
1727
+ // to reflect the update in the widths, it is enough to
1728
+ // merge the width of the column closer to the edge ('begin' or 'end')
1729
+ // and allow the size of the 'mid' column be the space that is left by the other two columns
1730
+ sColumnToUpdate = aResizedColumnNames.find((sColumn) => sColumn !== "mid");
1731
+ } else {
1732
+ sColumnToUpdate = sColumnEnlargedByDragging; // covers the known cases
1733
+ }
1734
+
1735
+ if (!isFullyVisible(sColumnToUpdate)) {
1736
+ // this is the case where the user is revealing a column by dragging,
1737
+ // but stopped dragging before the full size of the column was reached
1738
+ // => complete the user action => render that column in its required width
1739
+ // using its previously saved width
1740
+ return oOldWidths;
1741
+ }
1742
+
1743
+ return autosizeMid(merge(oOldWidths, {
1744
+ [sColumnToUpdate]: oNewWidths[sColumnToUpdate]
1745
+ }));
1746
+ };
1747
+
1748
+ FlexibleColumnLayout.prototype._offsetDraggedColumnSeparator = function (iOffset) {
1749
+ this._oDragInfo.separatorPosition.x += iOffset;
1750
+ this._$overlaySeparator.css(this._oDragInfo.separatorPosition.direction,
1751
+ this._oDragInfo.separatorPosition.x);
1752
+ };
1753
+
1754
+ FlexibleColumnLayout.prototype._toggleColumnVisibility = function (sColumn, bShow) {
1755
+ this._$columns[sColumn].toggleClass("sapFFCLColumnHidden", !bShow);
1756
+ this._$columns[sColumn].toggleClass("sapFFCLColumnActive", bShow);
1757
+ };
1758
+
1759
+ /**
1760
+ * Applies predefined contraints to the column widths.
1761
+ * Currently checks if the <code>FlexibleColumnLayout.COLUMN_MIN_WIDTH</code>
1762
+ * constraint is satisfied and corrects the width if not satisfied.
1763
+ * @param {Object<string,number>} oColumnWidths the column widths
1764
+ * @param {array} aVisibleColumns the names of the visible columns
1765
+ */
1766
+ FlexibleColumnLayout.prototype._normalizeColumnWidths = function (oColumnWidths, aVisibleColumns) {
1767
+ var iVisibleColumnsCount = aVisibleColumns.length;
1768
+ if (iVisibleColumnsCount < 2) { // fullscreen case
1769
+ return;
1770
+ }
1771
+
1772
+ var fnNormalizeColumnWidth = function (sColumn) {
1773
+ if (this._isColumnAllowedToHaveBelowMinWidth(sColumn)) {
1774
+ return;
1775
+ }
1776
+
1777
+ var iOffset = oColumnWidths[sColumn] - FlexibleColumnLayout.COLUMN_MIN_WIDTH,
1778
+ sSiblingColumn,
1779
+ iSiblingColumnWidth;
1780
+ if (iOffset < 0) { // column is smaller than min-width
1781
+ oColumnWidths[sColumn] = FlexibleColumnLayout.COLUMN_MIN_WIDTH;
1782
+ sSiblingColumn = getSiblingColumn(sColumn);
1783
+ iSiblingColumnWidth = oColumnWidths[sSiblingColumn];
1784
+ oColumnWidths[sSiblingColumn] = iSiblingColumnWidth - Math.abs(iOffset);
1785
+ }
1786
+ }.bind(this);
1787
+
1788
+ function getSiblingColumn(sColumn) {
1789
+ if (iVisibleColumnsCount === 2) {
1790
+ return aVisibleColumns.find(function(sNextColumn) {
1791
+ return sNextColumn !== sColumn;
1792
+ });
1793
+ }
1794
+ // all three columns are visible
1795
+ if (["begin", "end"].indexOf(sColumn) > -1) {
1796
+ return "mid";
1797
+ }
1798
+ // get sibling for 'mid'
1799
+ return (oColumnWidths.begin > oColumnWidths.end) ? "begin" : "end";
1800
+ }
1801
+
1802
+ aVisibleColumns.forEach(fnNormalizeColumnWidth);
1803
+ };
1804
+
1805
+ /**
1806
+ * Checks if the column is allowed to be displayed with a width smaller then
1807
+ * the minimal required by <code>FlexibleColumnLayout.COLUMN_MIN_WIDTH</code>.
1371
1808
  *
1372
- * @param {string} sColumn the column name
1373
- * @param {object} oOptions the resize options
1374
- * @private
1809
+ * This is needed only during interactive resize, when a column can temporarily
1810
+ * have a smaller width while the user drags and before the user releases the mouse.
1811
+ * @param {"begin"|"mid"|"end"} sColumn the column name
1812
+ * @returns {boolean} the flag
1375
1813
  */
1376
- FlexibleColumnLayout.prototype._afterColumnResize = function (sColumn, oOptions) {
1377
- var oColumn = this._$columns[sColumn],
1378
- bShouldConcealColumn = oOptions.shouldConcealColumn,
1379
- iNewWidth = oOptions.iNewWidth,
1380
- bShouldRestoreFocus = oOptions.shouldRestoreFocus;
1814
+ FlexibleColumnLayout.prototype._isColumnAllowedToHaveBelowMinWidth = function (sColumn) {
1815
+ if (!this._oDragInfo) {
1816
+ // outside interactive resize the min-width restriction should always be valid
1817
+ return false;
1818
+ }
1381
1819
 
1382
- oColumn.toggleClass(FlexibleColumnLayout.PINNED_COLUMN_CLASS_NAME, false);
1820
+ if (sColumn === this._oDragInfo.columnEnlargedByDragging) {
1821
+ // the user us revealing a hidden column by dragging
1822
+ // its ajacent separator => do not yet expand the column to min-width
1823
+ // untill the user stops dragging, to prevent undesired visual jump
1824
+ return true;
1825
+ }
1383
1826
 
1384
- if (bShouldConcealColumn) {
1385
- // The column does not show anything anymore, so we can remove the active class
1386
- oColumn.removeClass("sapFFCLColumnActive");
1827
+ // allow a column NOT adjacent to the dragged column-separator
1828
+ // to be indirectly shrinked (needed on tablet upon shifts
1829
+ // between ThreeColumnsMidExpanded and ThreeColumnsEndExpanded)
1830
+ return !this._isColumnAdjacentToDraggedSeparator(sColumn);
1831
+ };
1832
+
1833
+ FlexibleColumnLayout.prototype._convertColumnPercentWidthToPx = function (iPercentWidth, sLayout) {
1834
+ if (!iPercentWidth) {
1835
+ return 0;
1387
1836
  }
1388
1837
 
1389
- //BCP: 1980006195
1390
- oColumn.toggleClass("sapFFCLColumnHidden", iNewWidth === 0);
1838
+ // Calculate the width available for the columns
1839
+ var iAvailableWidth = this._getTotalColumnsWidth(sLayout);
1391
1840
 
1392
- this._cacheColumnWidth(sColumn, iNewWidth);
1393
- if (bShouldRestoreFocus) {
1394
- this._restoreFocusToColumn(sColumn);
1841
+ return Math.round(iAvailableWidth * iPercentWidth / 100);
1842
+ };
1843
+
1844
+ FlexibleColumnLayout.prototype._convertColumnPxWidthToPercent = function (vPx, sLayout) {
1845
+ if (!vPx) {
1846
+ return 0;
1847
+ }
1848
+
1849
+ var iAvailableWidth = this._getTotalColumnsWidth(sLayout),
1850
+ fnConvert = function(vPx) {
1851
+ return vPx / iAvailableWidth * 100;
1852
+ };
1853
+
1854
+ if (typeof vPx === "number") {
1855
+ return fnConvert(vPx);
1856
+ }
1857
+
1858
+ if (typeof vPx === "object") {
1859
+ var oColumnPercentWidths = Object.assign({}, vPx);
1860
+ Object.keys(oColumnPercentWidths).forEach(function(sColumnName) {
1861
+ var iColumnWidth = oColumnPercentWidths[sColumnName];
1862
+ if (iColumnWidth) {
1863
+ oColumnPercentWidths[sColumnName] = fnConvert(iColumnWidth);
1864
+ }
1865
+ }, this);
1866
+ return oColumnPercentWidths;
1395
1867
  }
1868
+ return null;
1869
+ };
1870
+
1871
+ FlexibleColumnLayout.prototype._isValidWidthDistributionForLayout = function(sNewWidthsDistribution, sLayout) {
1872
+ var aPercentWidths = sNewWidthsDistribution.split("/").map((x) => parseFloat(x)),
1873
+ iSum = aPercentWidths.reduce(function(i, sum) {
1874
+ return parseFloat(i) + sum;
1875
+ }),
1876
+ aPxWidths;
1877
+
1878
+ if (Math.round(iSum) !== 100) {
1879
+ return false;
1880
+ }
1881
+
1882
+ aPxWidths = aPercentWidths.map(function(iPercentWidth) {
1883
+ return this._convertColumnPercentWidthToPx(iPercentWidth, sLayout);
1884
+ }, this);
1885
+
1886
+ if (aPxWidths.some(function(iPxWidth) {
1887
+ return (iPxWidth > 0) && (iPxWidth < FlexibleColumnLayout.COLUMN_MIN_WIDTH);
1888
+ })) {
1889
+ return false;
1890
+ }
1891
+
1892
+ return this._verifyColumnWidthsMatchLayout({
1893
+ begin: aPxWidths[0],
1894
+ mid: aPxWidths[1],
1895
+ end: aPxWidths[2]
1896
+ }, sLayout);
1897
+ };
1898
+
1899
+ FlexibleColumnLayout.prototype._saveResizedColumWidths = function() {
1900
+ var sNewLayout = this._oDragInfo.layout,
1901
+ oColumnPercentWidths = this._convertColumnPxWidthToPercent(this._oDragInfo.columnWidths, sNewLayout),
1902
+ sNewWidthsDistribution = Object.values(oColumnPercentWidths).join("/");
1903
+
1904
+ if (this._isValidWidthDistributionForLayout(sNewWidthsDistribution, sNewLayout)) {
1905
+ this._getLocalStorage().put(sNewLayout, sNewWidthsDistribution);
1906
+ }
1907
+ };
1908
+
1909
+ FlexibleColumnLayout.prototype._getNextLayoutOnResizeByDrag = function (oColumnWidths,
1910
+ sPreviousLayout, sSeparator, bForwardDirection, bResizeEnd) {
1911
+ function dragged(oOptions) {
1912
+ return oOptions.from === sPreviousLayout &&
1913
+ oOptions.separator === sSeparator &&
1914
+ oOptions.forward === bForwardDirection;
1915
+ }
1916
+
1917
+ var iBeginWidth = oColumnWidths.begin,
1918
+ iBeginPercentWidth = Math.ceil(this._convertColumnPxWidthToPercent(iBeginWidth, sPreviousLayout)),
1919
+ iMaxColumnsCount = this.getMaxColumnsCount(),
1920
+ bTablet = iMaxColumnsCount === 2;
1921
+
1922
+ if (dragged({
1923
+ from: LT.TwoColumnsMidExpanded,
1924
+ separator: "begin",
1925
+ forward: true
1926
+ }) && (oColumnWidths.begin >= oColumnWidths.mid)) {
1927
+ return LT.TwoColumnsBeginExpanded;
1928
+ }
1929
+
1930
+ if (dragged({
1931
+ from: LT.TwoColumnsBeginExpanded,
1932
+ separator: "begin",
1933
+ forward: false
1934
+ }) && (oColumnWidths.begin < oColumnWidths.mid)) {
1935
+ return LT.TwoColumnsMidExpanded;
1936
+ }
1937
+
1938
+ if (dragged({
1939
+ from: LT.ThreeColumnsMidExpanded,
1940
+ separator: "begin",
1941
+ forward: true
1942
+ }) && iBeginPercentWidth >= 33) {
1943
+ return LT.ThreeColumnsMidExpandedEndHidden;
1944
+ }
1945
+
1946
+ if (dragged({
1947
+ from: LT.ThreeColumnsMidExpandedEndHidden,
1948
+ separator: "begin",
1949
+ forward: false
1950
+ }) && iBeginPercentWidth < 33) {
1951
+ return LT.ThreeColumnsMidExpanded;
1952
+ }
1953
+
1954
+ if (dragged({
1955
+ from: LT.ThreeColumnsMidExpandedEndHidden,
1956
+ separator: "end",
1957
+ forward: false
1958
+ }) && ((oColumnWidths.end >= FlexibleColumnLayout.COLUMN_MIN_WIDTH) || bResizeEnd)) {
1959
+ return LT.ThreeColumnsMidExpanded;
1960
+ }
1961
+
1962
+ if (dragged({
1963
+ from: LT.ThreeColumnsMidExpanded,
1964
+ separator: "end",
1965
+ forward: false
1966
+ }) && oColumnWidths.mid < oColumnWidths.end) {
1967
+ return LT.ThreeColumnsEndExpanded;
1968
+ }
1969
+
1970
+ if (dragged({
1971
+ from: LT.ThreeColumnsEndExpanded,
1972
+ separator: "end",
1973
+ forward: true
1974
+ }) && oColumnWidths.mid >= oColumnWidths.end) {
1975
+ return LT.ThreeColumnsMidExpanded;
1976
+ }
1977
+
1978
+ if (dragged({
1979
+ from: LT.ThreeColumnsMidExpandedEndHidden,
1980
+ separator: "begin",
1981
+ forward: true
1982
+ }) && oColumnWidths.begin >= oColumnWidths.mid) {
1983
+ return LT.ThreeColumnsBeginExpandedEndHidden;
1984
+ }
1985
+
1986
+ if (dragged({
1987
+ from: LT.ThreeColumnsBeginExpandedEndHidden,
1988
+ separator: "begin",
1989
+ forward: false
1990
+ }) && oColumnWidths.begin < oColumnWidths.mid) {
1991
+ return LT.ThreeColumnsMidExpandedEndHidden;
1992
+ }
1993
+
1994
+ if (dragged({
1995
+ from: LT.ThreeColumnsMidExpanded,
1996
+ separator: "begin",
1997
+ forward: true
1998
+ }) && bTablet && ((iBeginWidth >= FlexibleColumnLayout.COLUMN_MIN_WIDTH) || bResizeEnd)) {
1999
+ return LT.ThreeColumnsMidExpandedEndHidden;
2000
+ }
2001
+
2002
+ if (dragged({
2003
+ from: LT.TwoColumnsMidExpandedEndHidden,
2004
+ separator: "end",
2005
+ forward: false
2006
+ }) && bTablet && ((oColumnWidths.end >= FlexibleColumnLayout.COLUMN_MIN_WIDTH) || bResizeEnd)) {
2007
+ return LT.ThreeColumnsMidExpanded;
2008
+ }
2009
+
2010
+ return sPreviousLayout; // no layout change
2011
+ };
2012
+
2013
+ FlexibleColumnLayout.prototype._verifyColumnWidthsMatchLayout = function (oColumnWidths, sLayout) {
2014
+ var iMaxColumnsCount = this.getMaxColumnsCount(),
2015
+ iBeginWidth = oColumnWidths.begin,
2016
+ iBeginPercentWidth = Math.ceil(this._convertColumnPxWidthToPercent(iBeginWidth, sLayout)),
2017
+ oLayoutMatchers = {
2018
+ [LT.TwoColumnsBeginExpanded]: function() {
2019
+ return oColumnWidths.begin >= oColumnWidths.mid;
2020
+ },
2021
+ [LT.TwoColumnsMidExpanded]: function() {
2022
+ return oColumnWidths.mid > oColumnWidths.begin;
2023
+ },
2024
+ [LT.ThreeColumnsEndExpanded]: function() {
2025
+ return (oColumnWidths.end > oColumnWidths.mid) && (iBeginPercentWidth < 33);
2026
+ },
2027
+ [LT.ThreeColumnsBeginExpandedEndHidden]: function() {
2028
+ return (oColumnWidths.begin >= oColumnWidths.mid) && oColumnWidths.end === 0;
2029
+ },
2030
+ [LT.ThreeColumnsMidExpanded]: function() {
2031
+ return (oColumnWidths.mid >= oColumnWidths.end) &&
2032
+ (((iMaxColumnsCount === 3) && iBeginPercentWidth < 33) // desktop
2033
+ || ((iMaxColumnsCount === 2) && iBeginPercentWidth === 0)); // tablet
2034
+ },
2035
+ [LT.ThreeColumnsMidExpandedEndHidden]: function() {
2036
+ return (oColumnWidths.mid > oColumnWidths.begin) &&
2037
+ oColumnWidths.end === 0 &&
2038
+ ((iMaxColumnsCount === 3 && iBeginPercentWidth >= 33)
2039
+ || (iMaxColumnsCount === 2 && iBeginWidth >= FlexibleColumnLayout.COLUMN_MIN_WIDTH));
2040
+ }
2041
+ };
2042
+ return oLayoutMatchers[sLayout]();
1396
2043
  };
1397
2044
 
1398
2045
  /**
@@ -1447,68 +2094,112 @@ sap.ui.define([
1447
2094
  };
1448
2095
 
1449
2096
  /**
1450
- * Stores information from the last columns' resizing.
1451
- *
1452
- * @param iVisibleColumnsCount
1453
- * @param sLastVisibleColumn
1454
- * @private
2097
+ * Returns the name of the last visible column for the given layout
2098
+ * @param {sap.f.LayoutType} sLayout the layout
2099
+ * @returns {string} the column name
1455
2100
  */
1456
- FlexibleColumnLayout.prototype._storePreviousResizingInfo = function (iVisibleColumnsCount, sLastVisibleColumn) {
1457
- var oCurrentLayout = this.getLayout();
1458
-
1459
- this._iPreviousVisibleColumnsCount = iVisibleColumnsCount;
1460
- this._bWasFullScreen = oCurrentLayout === LT.MidColumnFullScreen || oCurrentLayout === LT.EndColumnFullScreen;
1461
- this._sPreviuosLastVisibleColumn = sLastVisibleColumn;
2101
+ FlexibleColumnLayout.prototype._getLastVisibleColumnForLayout = function (sLayout) {
2102
+ var aColumns = FlexibleColumnLayout.COLUMN_ORDER.slice(),
2103
+ iVisibleColumnsCount = this._getMaxColumnsCountForLayout(sLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT);
2104
+ if (iVisibleColumnsCount > 1) {
2105
+ return aColumns[iVisibleColumnsCount - 1];
2106
+ }
2107
+ if (sLayout === LT.OneColumn) {
2108
+ return "begin";
2109
+ }
2110
+ if (sLayout === LT.MidColumnFullScreen) {
2111
+ return "mid";
2112
+ }
2113
+ if (sLayout === LT.EndColumnFullScreen) {
2114
+ return "end";
2115
+ }
1462
2116
  };
1463
2117
 
1464
- FlexibleColumnLayout.prototype._isNavigatingBackward = function (sLastVisibleColumn) {
1465
- return this._bWasFullScreen ||
1466
- FlexibleColumnLayout.COLUMN_ORDER.indexOf(this._sPreviuosLastVisibleColumn) >
1467
- FlexibleColumnLayout.COLUMN_ORDER.indexOf(sLastVisibleColumn);
2118
+ FlexibleColumnLayout.prototype._isNavigatingBackward = function (sLayout, sPreviousLayout) {
2119
+ return ([LT.MidColumnFullScreen, LT.EndColumnFullScreen].indexOf(sPreviousLayout) > -1) ||
2120
+ FlexibleColumnLayout.COLUMN_ORDER.indexOf(this._getLastVisibleColumnForLayout(sPreviousLayout)) >
2121
+ FlexibleColumnLayout.COLUMN_ORDER.indexOf(this._getLastVisibleColumnForLayout(sLayout));
1468
2122
  };
1469
2123
 
1470
2124
  /**
1471
2125
  * Decides whether or not a given column should be revealed - another column slide out on top of it).
1472
2126
  *
1473
- * @param iVisibleColumnsCount
1474
- * @param bIsLastColumn
1475
- * @returns {boolean|*}
2127
+ * @param {"begin"|"mid"|"end"} sColumn the column name
2128
+ * @param {sap.f.LayoutType} sLayout the new layout
2129
+ * @param {sap.f.LayoutType} sPreviousLayout the previous layout
2130
+ * @returns {boolean} the flag
1476
2131
  * @private
1477
2132
  */
1478
- FlexibleColumnLayout.prototype._shouldRevealColumn = function (iVisibleColumnsCount, bIsLastColumn) {
1479
- return (iVisibleColumnsCount > this._iPreviousVisibleColumnsCount) && !this._bWasFullScreen && bIsLastColumn;
2133
+ FlexibleColumnLayout.prototype._shouldRevealColumn = function (sColumn, sLayout, sPreviousLayout) {
2134
+ var iVisibleColumnsCount = this._getMaxColumnsCountForLayout(sLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT),
2135
+ sLastVisibleColumn = this._getLastVisibleColumnForLayout(sLayout),
2136
+ bIsLastColumn = sColumn === sLastVisibleColumn,
2137
+ iPreviousVisibleColumnsCount = this._getMaxColumnsCountForLayout(sPreviousLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT),
2138
+ bWasFullScreen = (sPreviousLayout === LT.MidColumnFullScreen || sPreviousLayout === LT.EndColumnFullScreen);
2139
+
2140
+ return (iVisibleColumnsCount > iPreviousVisibleColumnsCount) &&
2141
+ !bWasFullScreen &&
2142
+ bIsLastColumn;
2143
+ };
2144
+
2145
+ FlexibleColumnLayout.prototype._isInteractivelyResizedColumn = function (sColumn) {
2146
+ return this._oDragInfo && this._isColumnAdjacentToDraggedSeparator(sColumn);
2147
+ };
2148
+
2149
+ FlexibleColumnLayout.prototype._isColumnAdjacentToDraggedSeparator = function (sColumn) {
2150
+ return this._oDragInfo &&
2151
+ this._oDragInfo.separator &&
2152
+ (this._$columns[sColumn][0] === this._oDragInfo.separator.previousElementSibling ||
2153
+ this._$columns[sColumn][0] === this._oDragInfo.separator.nextElementSibling);
1480
2154
  };
1481
2155
 
1482
2156
  /**
1483
2157
  * Decides whether or not a given column should be concealed - another column should slide in on top of it.
1484
2158
  *
1485
- * @param iVisibleColumnsCount
1486
- * @param sColumn
1487
- * @returns {boolean|*}
2159
+ * @param {"begin"|"mid"|"end"} sColumn the column name
2160
+ * @param {sap.f.LayoutType} sLayout the new layout
2161
+ * @param {sap.f.LayoutType} sPreviousLayout the previous layout
2162
+ * @returns {boolean} the flag
1488
2163
  * @private
1489
2164
  */
1490
- FlexibleColumnLayout.prototype._shouldConcealColumn = function(iVisibleColumnsCount, sColumn) {
1491
- return (iVisibleColumnsCount < this._iPreviousVisibleColumnsCount && sColumn === this._sPreviuosLastVisibleColumn
1492
- && !this._bWasFullScreen && this._getColumnSize(sColumn) === 0);
2165
+ FlexibleColumnLayout.prototype._shouldConcealColumn = function (sColumn, sLayout, sPreviousLayout) {
2166
+ var iVisibleColumnsCount = this._getMaxColumnsCountForLayout(sLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT),
2167
+ iPreviousVisibleColumnsCount = this._getMaxColumnsCountForLayout(sPreviousLayout, FlexibleColumnLayout.DESKTOP_BREAKPOINT),
2168
+ sPreviousLastVisibleColumn = this._getLastVisibleColumnForLayout(sPreviousLayout),
2169
+ bWasFullScreen = (sPreviousLayout === LT.MidColumnFullScreen || sPreviousLayout === LT.EndColumnFullScreen);
2170
+
2171
+ return (iVisibleColumnsCount < iPreviousVisibleColumnsCount
2172
+ && sColumn === sPreviousLastVisibleColumn
2173
+ && !bWasFullScreen
2174
+ && this._getColumnSizeForLayout(sColumn, sLayout) === 0);
1493
2175
  };
1494
2176
 
1495
2177
  /**
1496
2178
  * Checks if a column can be resized with an animation
1497
2179
  *
1498
- * @param {string} sColumn the column name
2180
+ * @param {"begin"|"mid"|"end"} sColumn the column name
1499
2181
  * @param {object} oOptions the column resize options
1500
- * @returns {boolean|*}
2182
+ * @param {number} oOptions.width the column width in px
2183
+ * @param {boolean} oOptions.hasAnimations if animations are enabled
2184
+ * @param {boolean} oOptions.hidden if the column has 0 width (as it is not required
2185
+ * to be shown by the current layout)
2186
+ * @param {boolean} oOptions.previousAnimationCompleted if the previous resize animation
2187
+ * fuly completed before staring the current one
2188
+ * @returns {boolean} the flag
1501
2189
  * @private
1502
2190
  */
1503
2191
  FlexibleColumnLayout.prototype._canResizeColumnWithAnimation = function(sColumn, oOptions) {
1504
- var oColumn, bFirstRendering,
1505
- iNewWidth = oOptions.iNewWidth,
2192
+ var oColumn,
2193
+ iNewWidth = oOptions.width,
1506
2194
  bHasAnimations = oOptions.hasAnimations,
1507
- bPinned = oOptions.pinned,
1508
2195
  bHidden = oOptions.hidden,
1509
2196
  bWasPartiallyResized = !oOptions.previousAnimationCompleted;
1510
2197
 
1511
- if (!bHasAnimations || bPinned || bHidden) {
2198
+ if (!bHasAnimations || bHidden) {
2199
+ return false;
2200
+ }
2201
+
2202
+ if (this._isInteractivelyResizedColumn(sColumn)) { // user is dragging to resize it
1512
2203
  return false;
1513
2204
  }
1514
2205
 
@@ -1517,9 +2208,8 @@ sap.ui.define([
1517
2208
  return oColumn.width() !== iNewWidth;
1518
2209
  }
1519
2210
 
1520
- bFirstRendering = !oColumn.get(0).style.width;
1521
- if (bFirstRendering) {
1522
- return false; // no animation on initial rendering of the column
2211
+ if (this._bNeverRendered || oOptions.autoSize) {
2212
+ return false; // initial rendering or autosized
1523
2213
  }
1524
2214
 
1525
2215
  return this._getColumnWidth(sColumn) !== iNewWidth;
@@ -1569,13 +2259,13 @@ sap.ui.define([
1569
2259
 
1570
2260
  /**
1571
2261
  * Gets the size (in %) of a column based on the current layout
1572
- * @param {string} sColumn - string: begin/mid/end
1573
- * @returns {*}
2262
+ * @param {"begin"|"mid"|"end"} sColumn - string: begin/mid/end
2263
+ * @param {sap.f.LayoutType} sLayout the layout
2264
+ * @returns {number} the size
1574
2265
  * @private
1575
2266
  */
1576
- FlexibleColumnLayout.prototype._getColumnSize = function (sColumn) {
1577
- var sLayout = this.getLayout(),
1578
- sColumnWidthDistribution = this._getColumnWidthDistributionForLayout(sLayout),
2267
+ FlexibleColumnLayout.prototype._getColumnSizeForLayout = function (sColumn, sLayout) {
2268
+ var sColumnWidthDistribution = this._getColumnWidthDistributionForLayout(sLayout),
1579
2269
  aSizes = sColumnWidthDistribution.split("/"),
1580
2270
  aMap = {
1581
2271
  begin: 0,
@@ -1584,7 +2274,7 @@ sap.ui.define([
1584
2274
  },
1585
2275
  sSize = aSizes[aMap[sColumn]];
1586
2276
 
1587
- return parseInt(sSize);
2277
+ return parseFloat(sSize);
1588
2278
  };
1589
2279
 
1590
2280
 
@@ -1622,9 +2312,9 @@ sap.ui.define([
1622
2312
 
1623
2313
  /**
1624
2314
  * Returns the maximum number of columns that can be displayed for given layout and control width.
1625
- * @param {string} sLayout the layout
1626
- * @param {int} iWidth
1627
- * @returns {number}
2315
+ * @param {sap.f.LayoutType} sLayout the layout
2316
+ * @param {int} iWidth the <code>sap.f.FlexibleColumnLayout</code> control width
2317
+ * @returns {number} the count
1628
2318
  * @private
1629
2319
  */
1630
2320
  FlexibleColumnLayout.prototype._getMaxColumnsCountForLayout = function (sLayout, iWidth) {
@@ -1672,7 +2362,6 @@ sap.ui.define([
1672
2362
 
1673
2363
  // Only update the arrows and fire the event if the maximum number of columns that can be shown has changed
1674
2364
  if (iMaxColumnsCount !== iOldMaxColumnsCount) {
1675
- this._hideShowArrows();
1676
2365
  this._fireStateChange(false, true);
1677
2366
  }
1678
2367
  };
@@ -1699,38 +2388,46 @@ sap.ui.define([
1699
2388
  };
1700
2389
 
1701
2390
  /**
1702
- * Called when the layout arrows were clicked.
1703
- * @param {string} sShiftDirection - left/right (direction of the arrow)
2391
+ * Obtains the names of the required column separators for the given layout.
2392
+ * @param {string} sLayout the layout
2393
+ * @returns {array} the names of the required separators
1704
2394
  * @private
1705
2395
  */
1706
- FlexibleColumnLayout.prototype._onArrowClick = function (sShiftDirection) {
1707
- var sCurrentLayout = this.getLayout(),
1708
- bIsLayoutValid = typeof FlexibleColumnLayout.SHIFT_TARGETS[sCurrentLayout] !== "undefined" && typeof FlexibleColumnLayout.SHIFT_TARGETS[sCurrentLayout][sShiftDirection] !== "undefined",
1709
- sNewLayout;
2396
+ FlexibleColumnLayout.prototype._getRequiredColumnSeparatorsForLayout = function (sLayout) {
2397
+ var oMap = {},
2398
+ aNeededSeparators = [],
2399
+ iMaxColumnsCount;
1710
2400
 
1711
- assert(bIsLayoutValid, "An invalid layout was used for determining arrow behavior");
1712
- sNewLayout = bIsLayoutValid ? FlexibleColumnLayout.SHIFT_TARGETS[sCurrentLayout][sShiftDirection] : LT.OneColumn;
2401
+ if (Device.system.phone) {
2402
+ return [];
2403
+ }
1713
2404
 
1714
- this.setLayout(sNewLayout);
2405
+ iMaxColumnsCount = this.getMaxColumnsCount();
1715
2406
 
1716
- // If the same arrow is hidden in the new layout, focus on the opposite one in it
1717
- if (FlexibleColumnLayout.ARROWS_NAMES[sNewLayout][sShiftDirection] !== FlexibleColumnLayout.ARROWS_NAMES[sCurrentLayout][sShiftDirection] && bIsLayoutValid) {
1718
- var sOppositeShiftDirection = sShiftDirection === 'right' ? 'left' : 'right';
2407
+ // Only show arrows if 2 or 3 columns can be displayed at a time
2408
+ if (iMaxColumnsCount > 1) {
2409
+ oMap[LT.TwoColumnsBeginExpanded] = ["begin"];
2410
+ oMap[LT.TwoColumnsMidExpanded] = ["begin"];
2411
+ oMap[LT.ThreeColumnsMidExpanded] = ["begin", "end"];
2412
+ oMap[LT.ThreeColumnsEndExpanded] = ["end"];
2413
+ oMap[LT.ThreeColumnsMidExpandedEndHidden] = ["begin", "end"];
2414
+ oMap[LT.ThreeColumnsBeginExpandedEndHidden] = ["begin"];
1719
2415
 
1720
- this._oColumnSeparatorArrows[FlexibleColumnLayout.ARROWS_NAMES[sNewLayout][sOppositeShiftDirection]].trigger("focus");
2416
+ if (typeof oMap[sLayout] === "object") {
2417
+ aNeededSeparators = oMap[sLayout];
2418
+ }
1721
2419
  }
1722
- this._fireStateChange(true, false);
2420
+
2421
+ return aNeededSeparators;
1723
2422
  };
1724
2423
 
1725
2424
  /**
1726
- * Updates the visibility of the layout arrows according to the current layout.
2425
+ * Updates the visibility of the column separators according to the given layout.
2426
+ * @param {string} [sLayout] the layout. If not provided, the current layout is taken
1727
2427
  * @private
1728
2428
  */
1729
- FlexibleColumnLayout.prototype._hideShowArrows = function () {
1730
- var sLayout = this.getLayout(),
1731
- oMap = {},
1732
- aNeededArrows = [],
1733
- iMaxColumnsCount,
2429
+ FlexibleColumnLayout.prototype._hideShowColumnSeparators = function (sLayout) {
2430
+ var aNeededSeparators = [],
1734
2431
  bIsNavContainersContentRendered;
1735
2432
 
1736
2433
  // Stop here if the control isn't rendered yet or in phone mode, where arrows aren't necessary
@@ -1738,42 +2435,29 @@ sap.ui.define([
1738
2435
  return;
1739
2436
  }
1740
2437
 
1741
- iMaxColumnsCount = this.getMaxColumnsCount();
2438
+ sLayout || (sLayout = this.getLayout());
1742
2439
 
1743
- // Only show arrows if 2 or 3 columns can be displayed at a time
1744
- if (iMaxColumnsCount > 1) {
1745
- oMap[LT.TwoColumnsBeginExpanded] = ["beginBack"];
1746
- oMap[LT.TwoColumnsMidExpanded] = ["midForward"];
1747
- oMap[LT.ThreeColumnsMidExpanded] = ["midForward", "midBack"];
1748
- oMap[LT.ThreeColumnsEndExpanded] = ["endForward"];
1749
- oMap[LT.ThreeColumnsMidExpandedEndHidden] = ["midForward", "midBack"];
1750
- oMap[LT.ThreeColumnsBeginExpandedEndHidden] = ["beginBack"];
1751
-
1752
- if (typeof oMap[sLayout] === "object") {
1753
- aNeededArrows = oMap[sLayout];
1754
- }
1755
- }
2440
+ aNeededSeparators = this._getRequiredColumnSeparatorsForLayout(sLayout);
1756
2441
 
1757
2442
  bIsNavContainersContentRendered = this._hasAnyColumnPagesRendered();
1758
2443
 
1759
- Object.keys(this._oColumnSeparatorArrows).forEach(function (key) {
1760
- this._toggleButton(key, aNeededArrows.indexOf(key) !== -1, bIsNavContainersContentRendered);
2444
+ Object.keys(this._oColumnSeparators).forEach(function (key) {
2445
+ this._toggleSeparator(key, aNeededSeparators.indexOf(key) !== -1, bIsNavContainersContentRendered);
1761
2446
  }, this);
1762
2447
  };
1763
2448
 
1764
2449
  /**
1765
- * Changes the visibility of a navigation button.
1766
- * @param {string} sButton
2450
+ * Changes the visibility of a separator.
2451
+ * @param {string} sKey, the separator name
1767
2452
  * @param {boolean} bShow
2453
+ * @param {boolean} bReveal
1768
2454
  * @private
1769
2455
  */
1770
- FlexibleColumnLayout.prototype._toggleButton = function (sButton, bShow, bReveal) {
1771
-
1772
- this._oColumnSeparatorArrows[sButton].toggle(bShow && bReveal);
1773
- this._oColumnSeparatorArrows[sButton].data("visible", bShow);
2456
+ FlexibleColumnLayout.prototype._toggleSeparator = function (sKey, bShow, bReveal) {
2457
+ this._oColumnSeparators[sKey].toggle(bShow && bReveal);
2458
+ this._oColumnSeparators[sKey].data("visible", bShow);
1774
2459
  };
1775
2460
 
1776
-
1777
2461
  FlexibleColumnLayout.prototype._fireStateChange = function (bIsNavigationArrow, bIsResize) {
1778
2462
 
1779
2463
  // The event should not be fired if the control has zero width as all relevant layout calculations are size-based
@@ -2179,12 +2863,14 @@ sap.ui.define([
2179
2863
  * Returns a string, representing the relative percentage sizes of the columns for the given layout in the format "begin/mid/end" (f.e. "33/67/0")
2180
2864
  * @param {string} sLayout - the layout
2181
2865
  * @param {boolean} bAsArray - return an array in the format [33, 67, 0] instead of a string "33/67/0"
2866
+ * @param {number} [iMaxColumnsCount] the maximun number of columns. If not provided, the result of
2867
+ * <code>getMaxColumnsCount</code> will be taken
2182
2868
  * @returns {string|array}
2183
2869
  * @private
2184
2870
  * @ui5-restricted sap.f.FlexibleColumnLayoutSemanticHelper
2185
2871
  */
2186
2872
  FlexibleColumnLayout.prototype._getColumnWidthDistributionForLayout = function (sLayout, bAsArray, iMaxColumnsCount) {
2187
- var oMap = {},
2873
+ var sColumnWidthDistribution = this._getLocalStorage(iMaxColumnsCount).get(sLayout),
2188
2874
  vResult;
2189
2875
 
2190
2876
  iMaxColumnsCount || (iMaxColumnsCount = this.getMaxColumnsCount());
@@ -2193,44 +2879,74 @@ sap.ui.define([
2193
2879
 
2194
2880
  vResult = "0/0/0";
2195
2881
 
2882
+ } else if (iMaxColumnsCount > 1
2883
+ && sColumnWidthDistribution) {
2884
+ vResult = sColumnWidthDistribution;
2196
2885
  } else {
2886
+ vResult = this._getDefaultColumnWidthDistributionForLayout(sLayout, iMaxColumnsCount);
2887
+ }
2888
+
2889
+ if (bAsArray) {
2890
+ vResult = vResult.split("/").map(function (sColumnWidth) {
2891
+ return parseInt(sColumnWidth);
2892
+ });
2893
+ }
2197
2894
 
2198
- // Layouts with the same distribution for all cases
2199
- oMap[LT.OneColumn] = "100/0/0";
2200
- oMap[LT.MidColumnFullScreen] = "0/100/0";
2201
- oMap[LT.EndColumnFullScreen] = "0/0/100";
2895
+ return vResult;
2896
+ };
2202
2897
 
2203
- if (iMaxColumnsCount === 1) {
2898
+ /**
2899
+ * Returns a string, representing the default relative percentage sizes of the columns
2900
+ * for the given layout
2901
+ * @param {sap.f.LayoutType} sLayout the layout
2902
+ * @param {number} iMaxColumnsCount the maximun available number of columns
2903
+ * @returns {string} a representation in the format "begin/mid/end" (f.e. "33/67/0")
2904
+ */
2905
+ FlexibleColumnLayout.prototype._getDefaultColumnWidthDistributionForLayout = function (sLayout, iMaxColumnsCount) {
2906
+ var oMap = {};
2907
+ // Layouts with the same distribution for all cases
2908
+ oMap[LT.OneColumn] = "100/0/0";
2909
+ oMap[LT.MidColumnFullScreen] = "0/100/0";
2910
+ oMap[LT.EndColumnFullScreen] = "0/0/100";
2204
2911
 
2205
- // On 1 column, all have fullscreen mapping
2206
- oMap[LT.TwoColumnsBeginExpanded] = "0/100/0";
2207
- oMap[LT.TwoColumnsMidExpanded] = "0/100/0";
2208
- oMap[LT.ThreeColumnsMidExpanded] = "0/0/100";
2209
- oMap[LT.ThreeColumnsEndExpanded] = "0/0/100";
2210
- oMap[LT.ThreeColumnsMidExpandedEndHidden] = "0/0/100";
2211
- oMap[LT.ThreeColumnsBeginExpandedEndHidden] = "0/0/100";
2912
+ if (iMaxColumnsCount === 1) {
2212
2913
 
2213
- } else {
2914
+ // On 1 column, all have fullscreen mapping
2915
+ oMap[LT.TwoColumnsBeginExpanded] = "0/100/0";
2916
+ oMap[LT.TwoColumnsMidExpanded] = "0/100/0";
2917
+ oMap[LT.ThreeColumnsMidExpanded] = "0/0/100";
2918
+ oMap[LT.ThreeColumnsEndExpanded] = "0/0/100";
2919
+ oMap[LT.ThreeColumnsMidExpandedEndHidden] = "0/0/100";
2920
+ oMap[LT.ThreeColumnsBeginExpandedEndHidden] = "0/0/100";
2214
2921
 
2215
- // On 2 and 3 columns, the only difference is in the modes where all 3 columns are visible
2216
- oMap[LT.TwoColumnsBeginExpanded] = "67/33/0";
2217
- oMap[LT.TwoColumnsMidExpanded] = "33/67/0";
2218
- oMap[LT.ThreeColumnsMidExpanded] = iMaxColumnsCount === 2 ? "0/67/33" : "25/50/25";
2219
- oMap[LT.ThreeColumnsEndExpanded] = iMaxColumnsCount === 2 ? "0/33/67" : "25/25/50";
2220
- oMap[LT.ThreeColumnsMidExpandedEndHidden] = "33/67/0";
2221
- oMap[LT.ThreeColumnsBeginExpandedEndHidden] = "67/33/0";
2222
- }
2922
+ } else {
2223
2923
 
2224
- vResult = oMap[sLayout];
2924
+ // On 2 and 3 columns, the only difference is in the modes where all 3 columns are visible
2925
+ oMap[LT.TwoColumnsBeginExpanded] = "67/33/0";
2926
+ oMap[LT.TwoColumnsMidExpanded] = "33/67/0";
2927
+ oMap[LT.ThreeColumnsMidExpanded] = iMaxColumnsCount === 2 ? "0/67/33" : "25/50/25";
2928
+ oMap[LT.ThreeColumnsEndExpanded] = iMaxColumnsCount === 2 ? "0/33/67" : "25/25/50";
2929
+ oMap[LT.ThreeColumnsMidExpandedEndHidden] = "33/67/0";
2930
+ oMap[LT.ThreeColumnsBeginExpandedEndHidden] = "67/33/0";
2225
2931
  }
2226
2932
 
2227
- if (bAsArray) {
2228
- vResult = vResult.split("/").map(function (sColumnWidth) {
2229
- return parseInt(sColumnWidth);
2933
+ return oMap[sLayout];
2934
+ };
2935
+
2936
+ FlexibleColumnLayout.prototype._attachAfterColumnResizedOnce = function (sColumn, fnSuccessCallback, fnErrorCallback) {
2937
+ this._oAnimationEndListener.waitForColumnResizeEnd(this._$columns[sColumn])
2938
+ .then(fnSuccessCallback)
2939
+ .catch(function() {
2940
+ fnErrorCallback && fnErrorCallback();
2230
2941
  });
2231
- }
2942
+ };
2232
2943
 
2233
- return vResult;
2944
+ FlexibleColumnLayout.prototype._attachAfterAllColumnsResizedOnce = function (fnSuccessCallback, fnErrorCallback) {
2945
+ this._oAnimationEndListener.waitForAllColumnsResizeEnd()
2946
+ .then(fnSuccessCallback)
2947
+ .catch(function() {
2948
+ fnErrorCallback && fnErrorCallback();
2949
+ });
2234
2950
  };
2235
2951
 
2236
2952
 
@@ -2242,29 +2958,10 @@ sap.ui.define([
2242
2958
  // The width above which (inclusive) we are in tablet mode
2243
2959
  FlexibleColumnLayout.TABLET_BREAKPOINT = 960;
2244
2960
 
2245
- // Arrows names for each shift position in a given layout
2246
- FlexibleColumnLayout.ARROWS_NAMES = {
2247
- TwoColumnsBeginExpanded: {
2248
- "left": "beginBack"
2249
- },
2250
- TwoColumnsMidExpanded: {
2251
- "right": "midForward"
2252
- },
2253
- ThreeColumnsMidExpanded: {
2254
- "left": "midBack",
2255
- "right": "midForward"
2256
- },
2257
- ThreeColumnsEndExpanded: {
2258
- "right": "endForward"
2259
- },
2260
- ThreeColumnsMidExpandedEndHidden: {
2261
- "left": "midBack",
2262
- "right": "midForward"
2263
- },
2264
- ThreeColumnsBeginExpandedEndHidden: {
2265
- "left": "beginBack"
2266
- }
2267
- };
2961
+ FlexibleColumnLayout.COLUMN_MIN_WIDTH = 312; // px, obtained as 25% of (DESKTOP_BREAKPOINT - 2 * COLUMN_SEPARATOR_WIDTH)
2962
+
2963
+ FlexibleColumnLayout.STORAGE_PREFIX_TABLET = "sap-f-fcl-tablet-column-width-distributions";
2964
+ FlexibleColumnLayout.STORAGE_PREFIX_DESKTOP = "sap-f-fcl-desktop-column-width-distributions";
2268
2965
 
2269
2966
  /**
2270
2967
  * Retrieves the resource bundle for the <code>sap.f</code> library.
@@ -2276,29 +2973,6 @@ sap.ui.define([
2276
2973
  return sap.ui.getCore().getLibraryResourceBundle("sap.f");
2277
2974
  };
2278
2975
 
2279
- // Resulting layouts, after shifting in a given direction from a specific layout
2280
- FlexibleColumnLayout.SHIFT_TARGETS = {
2281
- TwoColumnsBeginExpanded: {
2282
- "left": LT.TwoColumnsMidExpanded
2283
- },
2284
- TwoColumnsMidExpanded: {
2285
- "right": LT.TwoColumnsBeginExpanded
2286
- },
2287
- ThreeColumnsMidExpanded: {
2288
- "left": LT.ThreeColumnsEndExpanded,
2289
- "right": LT.ThreeColumnsMidExpandedEndHidden
2290
- },
2291
- ThreeColumnsEndExpanded: {
2292
- "right": LT.ThreeColumnsMidExpanded
2293
- },
2294
- ThreeColumnsMidExpandedEndHidden: {
2295
- "left": LT.ThreeColumnsMidExpanded,
2296
- "right": LT.ThreeColumnsBeginExpandedEndHidden
2297
- },
2298
- ThreeColumnsBeginExpandedEndHidden: {
2299
- "left": LT.ThreeColumnsMidExpandedEndHidden
2300
- }
2301
- };
2302
2976
 
2303
2977
  /**
2304
2978
  * Shows the placeholder on the corresponding column for the provided aggregation name.
@@ -2310,7 +2984,9 @@ sap.ui.define([
2310
2984
  * @since 1.91
2311
2985
  */
2312
2986
  FlexibleColumnLayout.prototype.showPlaceholder = function(mSettings) {
2313
- if (!Configuration.getPlaceholder()) {
2987
+ var Placeholder = sap.ui.require("sap/ui/core/Placeholder");
2988
+
2989
+ if (!Placeholder || !Placeholder.isEnabled()) {
2314
2990
  return;
2315
2991
  }
2316
2992
 
@@ -2395,6 +3071,20 @@ sap.ui.define([
2395
3071
  }
2396
3072
  };
2397
3073
 
3074
+ /**
3075
+ * Retrieves the etry at the given index
3076
+ * @param {*} iIndex ihe index
3077
+ * @param {*} bRecentFirst if the history should be ordered from the most recent to the most old
3078
+ * @returns {string} the entry at the given index
3079
+ */
3080
+ LayoutHistory.prototype.getEntry = function (iIndex, bRecentFirst) {
3081
+ var aHistory = this._aLayoutHistory;
3082
+ if (bRecentFirst) {
3083
+ aHistory = this._aLayoutHistory.toReversed();
3084
+ }
3085
+ return aHistory[iIndex];
3086
+ };
3087
+
2398
3088
  /**
2399
3089
  * Searches the history for the most recent layout that matches any of the aLayouts entries
2400
3090
  * @param aLayouts - a list of layouts
@@ -2517,6 +3207,7 @@ sap.ui.define([
2517
3207
  this._aPendingPromises = [];
2518
3208
  this._oCancelPromises = {};
2519
3209
  this._oPendingPromiseAll = null;
3210
+ this._oListeners = {};
2520
3211
  if (this.iTimer) {
2521
3212
  clearTimeout(this.iTimer);
2522
3213
  this.iTimer = null;
@@ -2549,6 +3240,43 @@ sap.ui.define([
2549
3240
  }
2550
3241
  };
2551
3242
 
3243
+ //utils
3244
+ function convertPxToCSSSizeString(iPxSize, iTotalPzSize, bIsInsetColumn) {
3245
+ var iContentSize;
3246
+ if (iPxSize === iTotalPzSize) {
3247
+ return "100%";
3248
+ }
3249
+ iContentSize = bIsInsetColumn ? (iPxSize - FlexibleColumnLayout.COLUMN_SEPARATOR_WIDTH) : iPxSize;
3250
+
3251
+ return iContentSize + "px";
3252
+ }
3253
+
3254
+ function getSeparatorName(oColumnSeparator) {
3255
+ return oColumnSeparator.classList.contains("sapFFCLColumnSeparatorBegin") ?
3256
+ "begin" : "end";
3257
+ }
3258
+
3259
+ function getInteractivelyResizedColumns(oColumnSeparator, sLayout, iMaxColumnsCount) {
3260
+ var bIsBeginSeparator = oColumnSeparator.classList.contains("sapFFCLColumnSeparatorBegin");
3261
+
3262
+ if (iMaxColumnsCount === 2 && sLayout == LT.ThreeColumnsMidExpandedEndHidden) {
3263
+ return (bIsBeginSeparator) ? ["begin", "mid"] : ["begin", "end"];
3264
+ }
3265
+
3266
+ if (iMaxColumnsCount === 2 && sLayout == LT.ThreeColumnsMidExpanded) {
3267
+ return (bIsBeginSeparator) ? ["begin", "end"] : ["mid", "end"];
3268
+ }
3269
+ return (bIsBeginSeparator) ? ["begin", "mid"] : ["mid", "end"];
3270
+ }
3271
+
3272
+ function getCursorPositionX (oEvent) {
3273
+ var oConfig = oEvent;
3274
+ if (oEvent.changedTouches && oEvent.changedTouches[0]) {
3275
+ oConfig = oConfig.changedTouches[0];
3276
+ }
3277
+ return oConfig.pageX;
3278
+ }
3279
+
2552
3280
  return FlexibleColumnLayout;
2553
3281
 
2554
3282
  });