ru.coon 2.8.66 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +317 -10
- package/package.json +1 -1
- package/src/Function.js +1 -1
- package/src/VisualLinker.js +610 -0
- package/src/VisualLinker.scss +219 -0
- package/src/app/Application.js +1 -0
- package/src/app/ApplicationSettings.js +49 -0
- package/src/app/Config.js +60 -0
- package/src/app/Router.js +37 -21
- package/src/app/viewPort/CVWrapperPanel.js +53 -0
- package/src/app/viewPort/CenterView.js +153 -46
- package/src/app/viewPort/CenterView.scss +151 -0
- package/src/app/viewPort/ComponentContextManager.js +24 -0
- package/src/app/viewPort/Main.js +4 -1
- package/src/app/viewPort/Routing.d2 +23 -0
- package/src/app/viewPort/TabHistory.js +81 -0
- package/src/common/ComponentFactory.js +167 -0
- package/src/common/button/DropdownContentButton.js +146 -0
- package/src/common/button/DropdownContentButton.scss +92 -0
- package/src/common/button/DropdownContentButtonController.js +60 -0
- package/src/common/component/formeditor/UiCustomFilterForm.scss +0 -1
- package/src/common/component/settings/modules/settingClosePageConfirmation.js +1 -3
- package/src/common/component/settings/modules/settingFavoritePanelShow.js +21 -0
- package/src/common/component/settings/modules/settingReportCalculator.js +22 -0
- package/src/common/component/settings/modules/settingShowNeedReloadMessage.js +1 -3
- package/src/common/component/settings/modules/settingwindowHolder.js +2 -3
- package/src/common/panel/WindowWrap.js +19 -11
- package/src/common/tree/BaseContextMenu.js +4 -3
- package/src/log.js +4 -5
- package/src/nav/AppNavCalcButton.js +23 -0
- package/src/nav/AppNavCalcButton.scss +6 -0
- package/src/nav/AppNavigationBar.js +1 -1
- package/src/nav/AppNavigationMenuController.js +2 -2
- package/src/nav/AppNavigationMenuMinimized.js +61 -0
- package/src/nav/AppNavigationPanel.js +115 -0
- package/src/nav/AppNavigationPanel.scss +178 -0
- package/src/nav/AppNavigationPanelController.js +386 -0
- package/src/nav/FavoriteCfg.js +18 -0
- package/src/nav/MenuEntity.js +23 -15
- package/src/nav/MenuFavoritesBar.js +100 -0
- package/src/nav/MenuFavoritesBar.scss +92 -0
- package/src/nav/editor/NavigateElementEditorView.js +2 -2
- package/src/nav/editor/workspace/NavWorkspaceListView.js +1 -4
- package/src/nav/menu/WorkspaceMenuViewMinimized.js +22 -0
- package/src/overrides/panel/TabPanel.js +36 -0
- package/src/overrides/panel/TabPanel.scss +65 -0
- package/src/report/component/ClearFiltersButton.js +4 -1
- package/src/report/component/CopyCellValueMenuItem.js +18 -0
- package/src/report/component/ReportFieldMap.js +274 -0
- package/src/report/component/ReportPanel.js +73 -44
- package/src/report/component/ReportPanel.scss +2 -2
- package/src/report/component/ReportTagLookup.js +59 -2
- package/src/report/component/calculator/ReportCalculatorController.js +266 -0
- package/src/report/component/calculator/ReportCalculatorField.js +47 -0
- package/src/report/component/calculator/ReportCalculatorHistoryPlugin.js +128 -0
- package/src/report/component/calculator/ReportCalculatorHistoryPlugin.scss +33 -0
- package/src/report/component/calculator/ReportCalculatorMenuItem.js +101 -0
- package/src/report/component/calculator/ReportCalculatorMenuItem.scss +41 -0
- package/src/report/component/calculator/ReportCalculatorPanel.js +363 -0
- package/src/report/component/calculator/ReportCalculatorPanel.scss +86 -0
- package/src/report/component/reportpanel/CopyReportPanelController.js +1 -1
- package/src/report/component/reportpanel/FilterPanel.js +13 -15
- package/src/report/component/reportpanel/FilterPanel.scss +5 -1
- package/src/report/component/reportpanel/FormFieldFocusPlugin.js +157 -0
- package/src/report/component/reportpanel/FormFieldFocusPlugin.scss +14 -0
- package/src/report/component/reportpanel/NorthPanel.js +16 -17
- package/src/report/component/reportpanel/NorthPanel.scss +1 -1
- package/src/report/component/reportpanel/ReportContextMenu.js +219 -0
- package/src/report/component/reportpanel/ReportGrid.js +1 -0
- package/src/report/component/reportpanel/ReportGrid.scss +4 -0
- package/src/report/component/settings/field/ReportFormFieldsGrid.js +2 -2
- package/src/report/component/settings/field/ReportFormFieldsGridController.js +2 -2
- package/src/report/component/settings/property/ReportPropertiesPanelController.js +1 -1
- package/src/report/component/settings/property/ReportPropertyDictionary.js +7 -0
- package/src/report/plugin/configPanel/AddFilterConditionPluginConfigPanel.js +34 -11
- package/src/report/plugin/configPanel/GridFiltersPluginConfigPanelFiltersGrid.js +3 -2
- package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.js +274 -255
- package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.scss +17 -0
- package/src/report/plugin/grid/AddFilterConditionPlugin.js +530 -87
- package/src/report/plugin/grid/CalculatorPlugin.js +90 -0
- package/src/report/plugin/grid/GridContextMenu.js +12 -10
- package/src/report/plugin/grid/GridRowCountPlugin.js +0 -1
- package/src/report/plugin/grid/GridToolbarButtonPlugin.js +11 -2
- package/src/report/plugin/grid/OpenCustomPanelButtonPlugin.js +126 -89
- package/src/report/plugin/grid/ReportColumnStatePlugin.js +15 -3
- package/src/report/plugin/grid/SetSingleParameterPlugin.js +1 -1
- package/src/report/plugin/grid/ToolbarButtonPlugin.js +1 -1
- package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanel.js +55 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanelController.js +226 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterConfigMixin.js +138 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterFieldFactory.js +223 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.js +164 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.scss +21 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterMenu.js +29 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanel.js +53 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanelController.js +57 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.js +111 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.scss +83 -0
- package/src/report/plugin/grid/addFilterConditionPlugin/SelectColumnPanel.js +102 -0
- package/src/report/selectionModels/MixedRowSelectionModel.js +36 -45
- package/src/report/toolbar/dropdown/ToolbarOverflowButton.js +16 -5
- package/src/report/toolbar/dropdown/ToolbarOverflowPanel.scss +26 -14
- package/src/report/toolbar/layout/ReportToolbarOverflow.js +5 -2
- package/src/ringBuffer.js +7 -3
- package/src/uielement/command/GetUIElementCommand.js +0 -1
- package/src/uielement/component/UiCPWrapper.js +26 -36
- package/src/uielement/component/UiCustomController.js +7 -0
- package/src/uielement/component/UiCustomPanel.js +46 -2
- package/src/uielement/component/settings/UiCustomPanelEditorController.js +35 -29
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.js +146 -33
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.scss +28 -0
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginGridController.js +366 -22
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginModel.js +1 -0
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanel.js +10 -4
- package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanelController.js +28 -30
- package/src/uielement/plugin/UnifiedButtonToolbarPlugin.js +203 -22
- package/src/uielement/plugin/configPanel/ExecuteFunctionPluginConfigPanelFormEditor.js +4 -36
- package/src/uielement/plugin/configPanel/FireEventPluginConfigPanelFormEditor.js +5 -36
- package/src/uielement/plugin/configPanel/MethodChainPluginConfigPanelFormEditor.js +4 -36
- package/src/uielement/plugin/configPanel/OpenPanelPluginConfigPanelFormEditor.js +2 -38
- package/src/uielement/plugin/configPanel/PrintPdfPluginConfigPanelFormEditor.js +2 -35
- package/src/uielement/plugin/configPanel/UiCPPluginFormPanel.js +54 -0
- package/src/uielement/plugin/configPanel/UnifiedButtonToolbarPluginConfigPanelFormEditor.js +28 -18
- package/src/userSettings.js +1 -0
- package/src/util/ContextManager.js +109 -0
- package/src/util.js +96 -15
- package/src/version.js +1 -1
- package/src/app/viewPort/CenterViewController.js +0 -158
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
Ext.define('Coon.util.VisualLinker', {
|
|
2
|
+
xtype: 'VisualLinker',
|
|
3
|
+
singleton: true,
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* хранилище пар соединённых компонентов и их конфиг-параметров
|
|
7
|
+
* в качестве ключей - строка leadComponent-id + secondaryComponent-id
|
|
8
|
+
*/
|
|
9
|
+
linkedElementList: new Map(),
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* CSS StyleSheet с правилами, исправляющими стили border у leadElement
|
|
13
|
+
* тэг <style#linkedStyleSheet> создаётся при первой записи в linkedElementList
|
|
14
|
+
* потом при добавлении новой пары создаются CSS правила для leadElement'a
|
|
15
|
+
* можно добавить опциональный параметр в конфиге для создания новых CSS-правил
|
|
16
|
+
*/
|
|
17
|
+
linkedStyleSheet: null,
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* регистрация новой пары
|
|
21
|
+
*/
|
|
22
|
+
createLinkedPair(leadComponent, secondaryComponent, options = {}) {
|
|
23
|
+
const parameters = this.processInputArguments(leadComponent, secondaryComponent, options);
|
|
24
|
+
|
|
25
|
+
const key = leadComponent.id + secondaryComponent.id;
|
|
26
|
+
|
|
27
|
+
if (this.linkedElementList.has(key)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Object.assign(parameters, this.getLeadStyles(leadComponent));
|
|
32
|
+
|
|
33
|
+
this.linkedElementList.set(key, parameters);
|
|
34
|
+
|
|
35
|
+
if (!this.linkedStyleSheet) {
|
|
36
|
+
this.linkedStyleSheet = this.createLinkedStyleSheet();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.setLinkedStyleSheetRules(parameters);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* принимает ключ [leadComponent, secondaryComponent] для linkedElementList
|
|
44
|
+
* получает по ключу параметры для линковки
|
|
45
|
+
* соединяет элементы
|
|
46
|
+
*/
|
|
47
|
+
link(leadComponent, secondaryComponent) {
|
|
48
|
+
const key = leadComponent.id + secondaryComponent.id;
|
|
49
|
+
const parameters = this.linkedElementList.get(key);
|
|
50
|
+
|
|
51
|
+
if (!parameters) {
|
|
52
|
+
console.error('No registred pair found');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const {
|
|
57
|
+
leadComponentClass,
|
|
58
|
+
align,
|
|
59
|
+
outerBgColor,
|
|
60
|
+
verticalOffset,
|
|
61
|
+
roundCorners,
|
|
62
|
+
leadBgColor,
|
|
63
|
+
leadBorderColor,
|
|
64
|
+
} = parameters;
|
|
65
|
+
|
|
66
|
+
const {elemLead, elemSecondary} = this.getDomElements(leadComponent, secondaryComponent);
|
|
67
|
+
|
|
68
|
+
if (!elemLead) {
|
|
69
|
+
console.error('No lead DOM element found.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (!elemSecondary) {
|
|
73
|
+
console.error('No secondary DOM element found. Make sure it is added to DOM before "link" call.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.handleLeadClassName(leadComponent, leadComponentClass, align, 'add');
|
|
78
|
+
|
|
79
|
+
this.handleSecondaryClassName(secondaryComponent, leadComponentClass, align, 'add');
|
|
80
|
+
|
|
81
|
+
this.setSecondaryCssVariables(elemSecondary, leadBgColor, leadBorderColor);
|
|
82
|
+
|
|
83
|
+
this.setPositionSecondaryElement(secondaryComponent, elemLead, align, verticalOffset);
|
|
84
|
+
|
|
85
|
+
const linkerElements = this.createLinkerElements(
|
|
86
|
+
elemLead,
|
|
87
|
+
elemSecondary,
|
|
88
|
+
verticalOffset,
|
|
89
|
+
align,
|
|
90
|
+
outerBgColor,
|
|
91
|
+
roundCorners,
|
|
92
|
+
leadBgColor,
|
|
93
|
+
leadBorderColor
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
linkerElements.forEach((el) => {
|
|
97
|
+
if (el) {
|
|
98
|
+
document.body.append(el);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
this.setLinkersRects(elemLead, elemSecondary, linkerElements, align);
|
|
103
|
+
|
|
104
|
+
const onLeadDestroyListener = leadComponent.on('beforedestroy', this.onLeadDestroy, this, {
|
|
105
|
+
args: [
|
|
106
|
+
secondaryComponent,
|
|
107
|
+
this.removeLinkers
|
|
108
|
+
],
|
|
109
|
+
destroyable: true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
this.linkedElementList.set(key, Object.assign(parameters, {onLeadDestroyListener}));
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* принимает ключ [leadComponent, secondaryComponent] для linkedElementList
|
|
117
|
+
* получает по ключу параметры для линковки
|
|
118
|
+
* разъединяет элементы
|
|
119
|
+
*/
|
|
120
|
+
unlink(leadComponent, secondaryComponent) {
|
|
121
|
+
const key = leadComponent.id + secondaryComponent.id;
|
|
122
|
+
const parameters = this.linkedElementList.get(key);
|
|
123
|
+
|
|
124
|
+
if (!parameters) {
|
|
125
|
+
console.error('No registred pair found');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const {
|
|
130
|
+
leadComponentClass,
|
|
131
|
+
align,
|
|
132
|
+
onLeadDestroyListener,
|
|
133
|
+
} = parameters;
|
|
134
|
+
|
|
135
|
+
this.handleLeadClassName(leadComponent, leadComponentClass, align, 'remove');
|
|
136
|
+
this.removeLinkers();
|
|
137
|
+
if (onLeadDestroyListener) {
|
|
138
|
+
onLeadDestroyListener.destroy();
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Before destroy event handler. Removes linkers from DOM
|
|
144
|
+
*/
|
|
145
|
+
onLeadDestroy(secondaryComponent, removeLinkers) {
|
|
146
|
+
secondaryComponent.destroy();
|
|
147
|
+
removeLinkers();
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {*} args - input arguments of createLinkedPair function
|
|
152
|
+
*/
|
|
153
|
+
processInputArguments(leadComponent, secondaryComponent, options) {
|
|
154
|
+
if (!this.validateParameters(leadComponent, secondaryComponent, options)) {
|
|
155
|
+
console.error(`Check function's input parameters!`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const newOptions = this.setDefaultParameters(leadComponent, options);
|
|
160
|
+
|
|
161
|
+
const align = this.setAlign(options.alignment);
|
|
162
|
+
|
|
163
|
+
return ({...newOptions, align});
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
validateParameters(leadComponent, secondaryComponent, options) {
|
|
167
|
+
if (leadComponent && secondaryComponent) {
|
|
168
|
+
if (!leadComponent.isComponent || !secondaryComponent.isComponent) {
|
|
169
|
+
console.error('Some of input elements are not instantiated Components');
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
console.error('Not all required input components found.');
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (options.alignment) {
|
|
178
|
+
const validAlignment = {
|
|
179
|
+
horizontal: ['t', 'b'],
|
|
180
|
+
vertical: ['l', 'r', 'f'],
|
|
181
|
+
};
|
|
182
|
+
if (
|
|
183
|
+
!validAlignment.horizontal.includes(options.alignment[0]) ||
|
|
184
|
+
!validAlignment.vertical.includes(options.alignment[1])
|
|
185
|
+
) {
|
|
186
|
+
console.error('Not valid "alignment" parameter.');
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (options.leadComponentClass && typeof options.leadComponentClass !== 'string') {
|
|
192
|
+
console.error('Class of the Lead element argument(leadComponentClass) must be of string type.');
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (options.outerBgColor && typeof options.outerBgColor !== 'string') {
|
|
197
|
+
console.error('Outer background color argument(outerBgColor) must be of string type.');
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (options.verticalOffset && !Number.isInteger(options.verticalOffset)) {
|
|
202
|
+
console.error('Vertical offset argument (verticalOffset) must be of integer type.');
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (options.roundCorners && typeof options.roundCorners !== 'boolean') {
|
|
207
|
+
console.error('Round corners argument (roundCorners) must be of boolean type.');
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return true;
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
setDefaultParameters(leadComponent, options) {
|
|
215
|
+
const leadComponentClass = options.leadComponentClass || leadComponent.cls || 'VisualLinkerLead';
|
|
216
|
+
const alignment = options.alignment || 'bl';
|
|
217
|
+
const outerBgColor = options.outerBgColor || 'white';
|
|
218
|
+
const verticalOffset = options.verticalOffset || 8;
|
|
219
|
+
const roundCorners = options.roundCorners || false;
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
leadComponentClass,
|
|
223
|
+
alignment,
|
|
224
|
+
outerBgColor,
|
|
225
|
+
verticalOffset,
|
|
226
|
+
roundCorners,
|
|
227
|
+
};
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
setAlign(alignment) {
|
|
231
|
+
const align = {
|
|
232
|
+
top: (alignment[0] === 't'),
|
|
233
|
+
bottom: (alignment[0] === 'b'),
|
|
234
|
+
left: (alignment[1] === 'l'),
|
|
235
|
+
right: (alignment[1] === 'r'),
|
|
236
|
+
full: (alignment[1] === 'f'),
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const horizontal = Object.keys(align).filter((key) => (key === 'left' || key === 'right' || key === 'full') && align[key]);
|
|
240
|
+
const vertical = Object.keys(align).filter((key) => (key === 'top' || key === 'bottom') && align[key]);
|
|
241
|
+
|
|
242
|
+
return {...align, horizontal, vertical};
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
createLinkedStyleSheet() {
|
|
246
|
+
const el = document.createElement('style');
|
|
247
|
+
el.id = 'linkedStyleSheet';
|
|
248
|
+
document.head.appendChild(el);
|
|
249
|
+
return el;
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
getLeadStyles(leadComponent) {
|
|
253
|
+
const elemLead = leadComponent.getEl().dom;
|
|
254
|
+
|
|
255
|
+
const leadStyles = getComputedStyle(elemLead);
|
|
256
|
+
const borderColor = leadStyles.borderLeftColor ||
|
|
257
|
+
leadStyles.borderRightColor;
|
|
258
|
+
const bgColor = this.getEffectiveBgColor(elemLead);
|
|
259
|
+
|
|
260
|
+
return {leadBorderColor: borderColor, leadBgColor: bgColor};
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Определяет цвет фона элемента, рекурсивно проходясь по родительским элементам, если цвет фона прозрачный.
|
|
265
|
+
* @param {DOM element} elem
|
|
266
|
+
* @returns color value
|
|
267
|
+
*/
|
|
268
|
+
getEffectiveBgColor(elem) {
|
|
269
|
+
const elemStyles = getComputedStyle(elem);
|
|
270
|
+
const bgColor = elemStyles.backgroundColor;
|
|
271
|
+
|
|
272
|
+
if (bgColor && bgColor !== 'transparent' && bgColor !== 'rgba(0, 0, 0, 0)') {
|
|
273
|
+
return bgColor;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (elem.parentElement) {
|
|
277
|
+
return this.getEffectiveBgColor(elem.parentElement);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// default white if no background found
|
|
281
|
+
return 'rgba(255, 255, 255, 1)';
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Создаёт новые CSS правила в stylesheet, созданном этим классом.
|
|
286
|
+
* Это нужно для соединения селекторов исходного класса ведущего элемента и класса активации соединения.
|
|
287
|
+
* По данному селектору изменяются стили ведущего элемента - выпрямляются скруглённые границы.
|
|
288
|
+
*/
|
|
289
|
+
setLinkedStyleSheetRules(options) {
|
|
290
|
+
const {leadComponentClass, align} = options;
|
|
291
|
+
|
|
292
|
+
const styleSheetRules = this.linkedStyleSheet.sheet.cssRules;
|
|
293
|
+
|
|
294
|
+
const leadRules = [
|
|
295
|
+
`border-${align.vertical}: none;`,
|
|
296
|
+
`border-${align.vertical}-left-radius: 0;`,
|
|
297
|
+
`border-${align.vertical}-right-radius: 0;`
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
const contentRules = [
|
|
301
|
+
'border: 1px solid var(--border-color);',
|
|
302
|
+
'backround-color: var(--bd-color);'
|
|
303
|
+
];
|
|
304
|
+
|
|
305
|
+
// Check if we already have this selector in our styleSheet
|
|
306
|
+
for (let i = 0; i < styleSheetRules.length; i++) {
|
|
307
|
+
if (styleSheetRules[i].selectorText.includes(leadComponentClass)) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this.linkedStyleSheet.sheet.insertRule(
|
|
313
|
+
`.${leadComponentClass}.${leadComponentClass}--active {${leadRules.join('')}}`
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
this.linkedStyleSheet.sheet.insertRule(
|
|
317
|
+
`.${leadComponentClass}-content {${contentRules.join('')}}`
|
|
318
|
+
);
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Добавляет или убирает активный класс у ведущего элемента при активации/деактивации модального окна
|
|
323
|
+
* @param {*} leadComponent - ведущий компонент
|
|
324
|
+
* @param {*} leadComponentClass - главный класс ведущего компонента
|
|
325
|
+
* @param {*} alignment - позиция модалки относительно ведущего элемента
|
|
326
|
+
* @param {*} method - добавить класс или удалить (add/remove)
|
|
327
|
+
*/
|
|
328
|
+
handleLeadClassName(leadComponent, leadComponentClass, align, method) {
|
|
329
|
+
const classNameActive = `${leadComponentClass}--active`;
|
|
330
|
+
const alignClassName = `${leadComponentClass}--${align.vertical}`;
|
|
331
|
+
|
|
332
|
+
if (method === 'add') {
|
|
333
|
+
leadComponent.addCls([classNameActive, alignClassName]);
|
|
334
|
+
} else if (method === 'remove') {
|
|
335
|
+
leadComponent.removeCls([classNameActive, alignClassName]);
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Добавляет или убирает класс у модального окна при активации/деактивации
|
|
341
|
+
* @param {*} elemLead - ведущий элемент
|
|
342
|
+
* @param {*} leadComponentClass - главный класс ведущего компонента
|
|
343
|
+
* @param {*} alignment - позиция модалки относительно ведущего элемента
|
|
344
|
+
* @param {*} method - добавить класс или удалить (add/remove)
|
|
345
|
+
*/
|
|
346
|
+
handleSecondaryClassName(secondaryComponent, leadComponentClass, align, method) {
|
|
347
|
+
const classNameSecondary = `${leadComponentClass}-content`;
|
|
348
|
+
const verticalAlignClassName = `${classNameSecondary}--${align.vertical}`;
|
|
349
|
+
const horizontalAlignClassName = `${classNameSecondary}--${align.horizontal}`;
|
|
350
|
+
|
|
351
|
+
if (method === 'add') {
|
|
352
|
+
secondaryComponent.addCls([classNameSecondary, verticalAlignClassName, horizontalAlignClassName]);
|
|
353
|
+
} else if (method === 'remove') {
|
|
354
|
+
secondaryComponent.removeCls([classNameSecondary, verticalAlignClassName, horizontalAlignClassName]);
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Определение CSS переменных для контент-панели
|
|
360
|
+
*/
|
|
361
|
+
setSecondaryCssVariables(elemSecondary, leadBgColor, leadBorderColor) {
|
|
362
|
+
elemSecondary.style.setProperty('--border-color', leadBorderColor);
|
|
363
|
+
// elemSecondary.style.setProperty('--bg-color', leadBgColor);
|
|
364
|
+
elemSecondary.style.setProperty('--bg-color', '#fff');
|
|
365
|
+
elemSecondary.style.setProperty('background-color', leadBgColor);
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Позиционирование модалки (secondary элемент)
|
|
370
|
+
*/
|
|
371
|
+
setPositionSecondaryElement(secondaryComponent, elemLead, align, verticalOffset) {
|
|
372
|
+
const elemLeadRect = elemLead.getBoundingClientRect();
|
|
373
|
+
const elemSecondary = secondaryComponent.getEl()?.dom;
|
|
374
|
+
if (!elemSecondary) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const elemSecondaryRect = elemSecondary.getBoundingClientRect();
|
|
378
|
+
|
|
379
|
+
if (align.full) {
|
|
380
|
+
this.setSecondaryElementRect(secondaryComponent, elemLeadRect, verticalOffset, align);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const elemSecondaryCoords = this.getElemSecondaryCoords(elemLeadRect, elemSecondaryRect, align, verticalOffset);
|
|
384
|
+
|
|
385
|
+
secondaryComponent.showAt(elemSecondaryCoords);
|
|
386
|
+
},
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Если у нас фулл-скрин alignment='bf',
|
|
390
|
+
* то определяем размеры контент-части по всей ширине окна,
|
|
391
|
+
* а также определить высоту элемента как вся высота экрана за вычетом высоты кнопки и офсета
|
|
392
|
+
*/
|
|
393
|
+
setSecondaryElementRect(secondaryComponent, elemLeadRect, verticalOffset, align) {
|
|
394
|
+
let height;
|
|
395
|
+
if (align.bottom) {
|
|
396
|
+
height = innerHeight - verticalOffset - elemLeadRect.bottom;
|
|
397
|
+
}
|
|
398
|
+
if (align.top) {
|
|
399
|
+
height = elemLeadRect.top - verticalOffset;
|
|
400
|
+
}
|
|
401
|
+
secondaryComponent.setHeight(`${height}px`);
|
|
402
|
+
secondaryComponent.setWidth('100%');
|
|
403
|
+
},
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Calculates coords for elemSecondary
|
|
407
|
+
*/
|
|
408
|
+
getElemSecondaryCoords(elemLeadRect, elemSecondaryRect, align, verticalOffset) {
|
|
409
|
+
let x = 0;
|
|
410
|
+
let y = 0;
|
|
411
|
+
if (align.bottom) {
|
|
412
|
+
y = elemLeadRect.bottom + verticalOffset;
|
|
413
|
+
} else if (align.top && !align.full) {
|
|
414
|
+
y = elemLeadRect.top - verticalOffset - elemSecondaryRect.height;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (align.right) {
|
|
418
|
+
x = elemLeadRect.right - elemSecondaryRect.width;
|
|
419
|
+
} else if (align.left) {
|
|
420
|
+
x = elemLeadRect.x;
|
|
421
|
+
} else if (align.full) {
|
|
422
|
+
x = 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return [x, y];
|
|
426
|
+
},
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Creates linker elements
|
|
430
|
+
* Sets element's classes, CSS variables and styles
|
|
431
|
+
* @param {*} elemLead - takes it's width, x/y coords and background color
|
|
432
|
+
* @param {*} elemSecondary - takes it's z-index
|
|
433
|
+
* @param {*} verticalOffset - used for sizes of linkers
|
|
434
|
+
* @param {*} alignment - alignments for linked elements
|
|
435
|
+
* @param {*} outerBgColor - outer background color around lead component
|
|
436
|
+
* @param {*} roundCorners - if we need roun corners in the connection of linkers and content element
|
|
437
|
+
* @returns array with linkers. [0] - Line Linker; [1] - Corner LInker
|
|
438
|
+
*/
|
|
439
|
+
createLinkerElements(elemLead, elemSecondary, verticalOffset, align, outerBgColor, roundCorners, leadBgColor, leadBorderColor) {
|
|
440
|
+
let linkerLine = document.querySelector('.visualLinker-linkerLine');
|
|
441
|
+
let linkerCorner = document.querySelector('.visualLinker-linkerCorner');
|
|
442
|
+
if (linkerLine || linkerCorner) {
|
|
443
|
+
this.removeLinkers();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const elemLeadRect = elemLead.getBoundingClientRect();
|
|
447
|
+
const linkerZIndex = elemSecondary.style.zIndex + 10;
|
|
448
|
+
|
|
449
|
+
linkerLine = this.createLinkerLine(elemLeadRect, verticalOffset, linkerZIndex, leadBorderColor, roundCorners, align, leadBgColor);
|
|
450
|
+
if (roundCorners) {
|
|
451
|
+
linkerCorner = this.createLinkerCorner(align, verticalOffset, linkerZIndex, leadBorderColor, outerBgColor);
|
|
452
|
+
} else {
|
|
453
|
+
linkerCorner = null;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return [linkerLine, linkerCorner];
|
|
457
|
+
},
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Creates line linker element with CSS variables and classes
|
|
461
|
+
*/
|
|
462
|
+
createLinkerLine(elemLeadRect, verticalOffset, linkerZIndex, linkerBorderColor, roundCorners, align, bgColor) {
|
|
463
|
+
const linker = document.createElement('div');
|
|
464
|
+
linker.classList.add('visualLinker-linkerLine');
|
|
465
|
+
|
|
466
|
+
linker.style.setProperty('--width', `${elemLeadRect.width}`);
|
|
467
|
+
linker.style.setProperty('--size', `${verticalOffset + 2}px`);
|
|
468
|
+
linker.style.setProperty('--z-index', linkerZIndex);
|
|
469
|
+
linker.style.setProperty('--border-color', linkerBorderColor);
|
|
470
|
+
linker.style.setProperty('--bg-color', bgColor);
|
|
471
|
+
|
|
472
|
+
linker.style.setProperty('border', 'none');
|
|
473
|
+
linker.style.setProperty('border-left', `1px solid ${linkerBorderColor}`);
|
|
474
|
+
linker.style.setProperty('border-right', `1px solid ${linkerBorderColor}`);
|
|
475
|
+
|
|
476
|
+
linker.classList.add(`linker-${align.vertical}`, `linker-${align.horizontal}`);
|
|
477
|
+
|
|
478
|
+
if (!roundCorners || align.full) {
|
|
479
|
+
linker.classList.add('linker-full');
|
|
480
|
+
} else {
|
|
481
|
+
linker.classList.add(`linker-${align.horizontal}`);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return linker;
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Creates corner linker element with CSS variables and classes
|
|
489
|
+
*/
|
|
490
|
+
createLinkerCorner(align, verticalOffset, linkerZIndex, linkerBorderColor, outerBgColor) {
|
|
491
|
+
if (align.full) {
|
|
492
|
+
return null;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const linkerCorner = document.createElement('div');
|
|
496
|
+
linkerCorner.classList.add('visualLinker-linkerCorner');
|
|
497
|
+
|
|
498
|
+
linkerCorner.style.setProperty('--size', `${verticalOffset + 4}px`);
|
|
499
|
+
linkerCorner.style.setProperty('--z-index', linkerZIndex + 1);
|
|
500
|
+
linkerCorner.style.setProperty('--border-color', linkerBorderColor);
|
|
501
|
+
linkerCorner.style.setProperty('--outer-bg-color', outerBgColor);
|
|
502
|
+
|
|
503
|
+
linkerCorner.classList.add(`linkerCorner-${align.vertical}`, `linkerCorner-${align.horizontal}`);
|
|
504
|
+
|
|
505
|
+
return linkerCorner;
|
|
506
|
+
},
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Рассчёт размеров и позиционирование линкеров
|
|
510
|
+
*/
|
|
511
|
+
setLinkersRects(elemLead, elemSecondary, linkerElements, align) {
|
|
512
|
+
this.setLinkerLineElementRect(elemLead, elemSecondary, linkerElements[0], align);
|
|
513
|
+
if (linkerElements[1]) {
|
|
514
|
+
this.setLinkerCornerElementRect(elemLead, elemSecondary, linkerElements[1], align);
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Позиционирование line linker'a
|
|
520
|
+
*/
|
|
521
|
+
setLinkerLineElementRect(elemLead, elemSecondary, linkerLineElement, align) {
|
|
522
|
+
const elemLeadRect = elemLead.getBoundingClientRect();
|
|
523
|
+
const elemSecondaryRect = elemSecondary.getBoundingClientRect();
|
|
524
|
+
const linkerLineCoords = this.getLinkerLineCoords(elemLeadRect, elemSecondaryRect, align, linkerLineElement);
|
|
525
|
+
|
|
526
|
+
linkerLineElement.style.width = `${elemLeadRect.width}px`;
|
|
527
|
+
this.positionElem(linkerLineElement, linkerLineCoords);
|
|
528
|
+
},
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Позиционирование corner linker'a
|
|
532
|
+
*/
|
|
533
|
+
setLinkerCornerElementRect(elemLead, elemSecondary, linkerCornerElement, align) {
|
|
534
|
+
const elemLeadRect = elemLead.getBoundingClientRect();
|
|
535
|
+
const elemSecondaryRect = elemSecondary.getBoundingClientRect();
|
|
536
|
+
const linkerCornerCoords = this.getLinkerCornerCoords(elemLeadRect, elemSecondaryRect, align, linkerCornerElement);
|
|
537
|
+
|
|
538
|
+
this.positionElem(linkerCornerElement, linkerCornerCoords);
|
|
539
|
+
},
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Calculates coords for line linker element
|
|
543
|
+
*/
|
|
544
|
+
getLinkerLineCoords(elemLeadRect, elemSecondaryRect, align, linkerElement) {
|
|
545
|
+
let x = 0;
|
|
546
|
+
let y = 0;
|
|
547
|
+
const linkerRect = linkerElement.getBoundingClientRect();
|
|
548
|
+
if (align.bottom) {
|
|
549
|
+
x = elemLeadRect.x;
|
|
550
|
+
y = elemSecondaryRect.top - linkerRect.height;
|
|
551
|
+
} else if (align.top) {
|
|
552
|
+
x = elemLeadRect.x;
|
|
553
|
+
y = elemSecondaryRect.bottom;
|
|
554
|
+
}
|
|
555
|
+
return [x, y];
|
|
556
|
+
},
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Calculates coords for corner linker element
|
|
560
|
+
*/
|
|
561
|
+
getLinkerCornerCoords(elemLeadRect, elemSecondaryRect, align, linkerCornerElement) {
|
|
562
|
+
let x = 0;
|
|
563
|
+
let y = 0;
|
|
564
|
+
const linkerRect = linkerCornerElement.getBoundingClientRect();
|
|
565
|
+
if (align.bottom) {
|
|
566
|
+
y = elemSecondaryRect.top - linkerRect.height;
|
|
567
|
+
} else if (align.top) {
|
|
568
|
+
y = elemSecondaryRect.bottom;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (align.left) {
|
|
572
|
+
x = elemLeadRect.right;
|
|
573
|
+
} else if (align.right) {
|
|
574
|
+
x = elemLeadRect.left - linkerRect.width;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return [x, y];
|
|
578
|
+
},
|
|
579
|
+
|
|
580
|
+
getDomElements(leadComponent, secondaryComponent) {
|
|
581
|
+
const elemLead = leadComponent?.getEl()?.dom;
|
|
582
|
+
const elemSecondary = secondaryComponent?.getEl()?.dom;
|
|
583
|
+
|
|
584
|
+
return {elemLead, elemSecondary};
|
|
585
|
+
},
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Remove linker elements from the DOM
|
|
589
|
+
*/
|
|
590
|
+
removeLinkers() {
|
|
591
|
+
const linkerElement = document.querySelector('.visualLinker-linkerLine');
|
|
592
|
+
const linkerCornerElement = document.querySelector('.visualLinker-linkerCorner');
|
|
593
|
+
if (linkerElement) {
|
|
594
|
+
linkerElement.remove();
|
|
595
|
+
}
|
|
596
|
+
if (linkerCornerElement) {
|
|
597
|
+
linkerCornerElement.remove();
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Position DOM element by coordinates
|
|
603
|
+
* @param {*} elem
|
|
604
|
+
* @param {*} coords
|
|
605
|
+
*/
|
|
606
|
+
positionElem(elem, coords) {
|
|
607
|
+
elem.style.left = `${coords[0]}px`;
|
|
608
|
+
elem.style.top = `${coords[1]}px`;
|
|
609
|
+
},
|
|
610
|
+
});
|