@componyx/ui 0.0.0-stage → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/AppSkin/AppSkin.css +1268 -0
  2. package/AppSkin/AppSkin.js +2748 -0
  3. package/AppSkin/Themes/Default.css +241 -0
  4. package/Base/Base.js +3407 -0
  5. package/Base/ComponentIcons.css +66 -0
  6. package/Base/Font/ComponentIcons.woff +0 -0
  7. package/Base/Font/UI.woff +0 -0
  8. package/Base/Library.js +8432 -0
  9. package/Base/NavigationManager.js +462 -0
  10. package/Base/ResponsiveTemplates.js +371 -0
  11. package/Base/Sanitizer.js +288 -0
  12. package/Base/Themes/Default.css +255 -0
  13. package/Base/UI.css +618 -0
  14. package/Base/UIResourcePath.js +6 -0
  15. package/Bindary/Bindary.js +2011 -0
  16. package/Bindary/Modules/Connection.js +216 -0
  17. package/Bindary/Modules/Core.js +854 -0
  18. package/Bindary/Modules/DataUpdater.js +351 -0
  19. package/Bindary/Modules/ExpressionEngine.js +347 -0
  20. package/Bindary/Modules/ProxyManager.js +482 -0
  21. package/Bindary/Modules/Renderer.js +605 -0
  22. package/Bindary/Modules/Router.js +291 -0
  23. package/Bindary/Modules/Scroller.js +89 -0
  24. package/Bindary/Modules/Template.js +1273 -0
  25. package/BookmarkSpy/BookmarkSpy.js +430 -0
  26. package/Box/Box.css +36 -0
  27. package/Box/Box.js +1685 -0
  28. package/Button/Button.css +470 -0
  29. package/Button/Button.js +1398 -0
  30. package/Button/Themes/Default.css +200 -0
  31. package/Carousel/Carousel.css +273 -0
  32. package/Carousel/Carousel.js +607 -0
  33. package/ColorButton/ColorButton.css +39 -0
  34. package/ColorButton/ColorButton.js +336 -0
  35. package/ColorPicker/ColorPicker.css +359 -0
  36. package/ColorPicker/ColorPicker.js +972 -0
  37. package/ComboBox/ComboBox.css +357 -0
  38. package/ComboBox/ComboBox.js +2342 -0
  39. package/ComboBox/Themes/Default.css +23 -0
  40. package/DataPager/DataPager.css +72 -0
  41. package/DataPager/DataPager.js +674 -0
  42. package/DatePicker/DatePicker.css +227 -0
  43. package/DatePicker/DatePicker.js +1531 -0
  44. package/DatePicker/Themes/Default.css +26 -0
  45. package/Dialog/Dialog.css +106 -0
  46. package/Dialog/Dialog.js +572 -0
  47. package/Dialog/Themes/Default.css +10 -0
  48. package/Editor/Data/Emoji.json +8285 -0
  49. package/Editor/Data/Special.json +1042 -0
  50. package/Editor/Editor.css +1562 -0
  51. package/Editor/Editor.js +4058 -0
  52. package/Editor/Font/Editor.woff +0 -0
  53. package/Editor/Modules/ComponentFactory.js +565 -0
  54. package/Editor/Modules/ContentManager.js +748 -0
  55. package/Editor/Modules/DialogManager.js +1234 -0
  56. package/Editor/Modules/EventManager.js +458 -0
  57. package/Editor/Modules/Format.js +950 -0
  58. package/Editor/Modules/History.js +191 -0
  59. package/Editor/Modules/LayoutState.js +379 -0
  60. package/Editor/Modules/ListManager.js +296 -0
  61. package/Editor/Modules/MenuManager.js +388 -0
  62. package/Editor/Modules/NodeManager.js +681 -0
  63. package/Editor/Modules/ParagraphButtons.js +122 -0
  64. package/Editor/Modules/Resizer.js +176 -0
  65. package/Editor/Modules/SelectionRange.js +564 -0
  66. package/Editor/Modules/SourceViewBuilder.js +212 -0
  67. package/Editor/Modules/SymbolPicker.js +208 -0
  68. package/Editor/Modules/Table.js +2327 -0
  69. package/Editor/Modules/TableDialog.js +757 -0
  70. package/Editor/Modules/Toolbar.js +375 -0
  71. package/Editor/Modules/TooltipMenu.js +125 -0
  72. package/Editor/Modules/Utility.js +131 -0
  73. package/Editor/Themes/Default.css +204 -0
  74. package/FileUpload/FileUpload.css +156 -0
  75. package/FileUpload/FileUpload.js +898 -0
  76. package/FileUpload/Themes/Default.css +17 -0
  77. package/Form/Form.css +1934 -0
  78. package/Form/Form.js +4943 -0
  79. package/Form/Modules/ActionManager.js +368 -0
  80. package/Form/Modules/BuildPanelManager.js +319 -0
  81. package/Form/Modules/ComponentFactory.js +468 -0
  82. package/Form/Modules/ComponentPanel.js +265 -0
  83. package/Form/Modules/ConfigPanelManager.js +685 -0
  84. package/Form/Modules/DataBinder.js +602 -0
  85. package/Form/Modules/DataObserver.js +717 -0
  86. package/Form/Modules/Draggable.js +756 -0
  87. package/Form/Modules/OptionsPanel.js +342 -0
  88. package/Form/Modules/Renderer.js +1889 -0
  89. package/Form/Modules/RuleEngine.js +585 -0
  90. package/Form/Modules/RulesPanel.js +1158 -0
  91. package/Form/Modules/Types.js +1709 -0
  92. package/Form/Modules/ValidationManager.js +194 -0
  93. package/Form/Themes/Default.css +216 -0
  94. package/FormField/FormField.css +468 -0
  95. package/FormField/FormField.js +576 -0
  96. package/FormField/Themes/Default.css +99 -0
  97. package/Grid/Grid.css +544 -0
  98. package/Grid/Grid.js +3761 -0
  99. package/Grid/Themes/Default.css +43 -0
  100. package/LICENSE +126 -0
  101. package/MaskedTextBox/MaskedTextBox.css +28 -0
  102. package/MaskedTextBox/MaskedTextBox.js +642 -0
  103. package/MaskedTextBox/Themes/Default.css +6 -0
  104. package/Menu/Menu.css +328 -0
  105. package/Menu/Menu.js +2386 -0
  106. package/Menu/Themes/Default.css +24 -0
  107. package/NumericBox/NumericBox.css +120 -0
  108. package/NumericBox/NumericBox.js +984 -0
  109. package/PanelBar/PanelBar.css +123 -0
  110. package/PanelBar/PanelBar.js +505 -0
  111. package/PanelBar/Themes/Default.css +51 -0
  112. package/PieChart/PieChart.css +95 -0
  113. package/PieChart/PieChart.js +820 -0
  114. package/PieChart/Themes/Default.css +9 -0
  115. package/README.md +178 -3
  116. package/Slider/Slider.css +348 -0
  117. package/Slider/Slider.js +1306 -0
  118. package/Slider/Themes/Default.css +44 -0
  119. package/TabStrip/TabStrip.css +52 -0
  120. package/TabStrip/TabStrip.js +362 -0
  121. package/TabStrip/Themes/Default.css +35 -0
  122. package/TimePicker/Themes/Default.css +30 -0
  123. package/TimePicker/TimePicker.css +253 -0
  124. package/TimePicker/TimePicker.js +1485 -0
  125. package/TooltipManager/Themes/Default.css +21 -0
  126. package/TooltipManager/TooltipManager.css +227 -0
  127. package/TooltipManager/TooltipManager.js +791 -0
  128. package/Validator/Validator.css +54 -0
  129. package/Validator/Validator.js +2508 -0
  130. package/componyx.html-data.json +619 -0
  131. package/index.js +27 -0
  132. package/package.json +43 -4
  133. package/types/AppSkin.d.ts +842 -0
  134. package/types/Base.d.ts +1034 -0
  135. package/types/Bindary.d.ts +1196 -0
  136. package/types/BookmarkSpy.d.ts +112 -0
  137. package/types/Box.d.ts +374 -0
  138. package/types/Button.d.ts +455 -0
  139. package/types/Carousel.d.ts +136 -0
  140. package/types/ColorButton.d.ts +120 -0
  141. package/types/ColorPicker.d.ts +225 -0
  142. package/types/ComboBox.d.ts +507 -0
  143. package/types/DataPager.d.ts +152 -0
  144. package/types/DatePicker.d.ts +354 -0
  145. package/types/Dialog.d.ts +160 -0
  146. package/types/Editor.d.ts +1289 -0
  147. package/types/FileUpload.d.ts +206 -0
  148. package/types/Form.d.ts +3078 -0
  149. package/types/FormField.d.ts +204 -0
  150. package/types/Grid.d.ts +911 -0
  151. package/types/Library.d.ts +1899 -0
  152. package/types/MaskedTextBox.d.ts +91 -0
  153. package/types/Menu.d.ts +577 -0
  154. package/types/NumericBox.d.ts +310 -0
  155. package/types/PanelBar.d.ts +223 -0
  156. package/types/PieChart.d.ts +224 -0
  157. package/types/ResponsiveTemplates.d.ts +108 -0
  158. package/types/Slider.d.ts +227 -0
  159. package/types/TabStrip.d.ts +185 -0
  160. package/types/TimePicker.d.ts +265 -0
  161. package/types/TooltipManager.d.ts +178 -0
  162. package/types/UI.d.ts +29 -0
  163. package/types/Validator.d.ts +653 -0
  164. package/types/index.d.ts +59 -0
  165. package/ui.css +11783 -0
  166. package/ui.js +79477 -0
  167. package/ui.min.css +138 -0
  168. package/ui.min.js +264 -0
  169. package/ui.min.js.map +1 -0
@@ -0,0 +1,681 @@
1
+ /*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
2
+ componyx.UI.editor_modules = componyx.UI.editor_modules || {};
3
+
4
+ /**
5
+ * NodeManager module - node manipulation and tree operations.
6
+ * @class NodeManager
7
+ * @memberof componyx.UI.editor_modules
8
+ * @ignore
9
+ */
10
+ componyx.UI.editor_modules.NodeManager = class NodeManager
11
+ {
12
+ constructor(editor)
13
+ {
14
+ this.editor = editor;
15
+ this.utility = editor.utility;
16
+ }
17
+
18
+ /**
19
+ * Returns a value indicating if the node is a bookmark node.
20
+ * @param {Node} node
21
+ */
22
+ isBookmark(node)
23
+ {
24
+ return node && node.nodeType == 1 && node.nodeName == 'A' && node.hasAttribute('id') && !node.hasAttribute('href');
25
+ }
26
+
27
+ /**
28
+ * Returns a value indicating if the node contains an image.
29
+ * @param {Node} node
30
+ */
31
+ isImage(node)
32
+ {
33
+ return node && node.nodeType == 1 && !!node.querySelector(':scope > img');
34
+ }
35
+
36
+ /**
37
+ * Returns a value indicating if the node is a media node.
38
+ * @param {Node} node
39
+ */
40
+ isMedia(node)
41
+ {
42
+ return node && node.nodeType == 1 && node.nodeName == 'FIGURE' && node.hasAttribute(this.utility.attrPrefix + 'media');
43
+ }
44
+
45
+ /**
46
+ * Returns a value indicating if the node is a link node.
47
+ * @param {Node} node
48
+ */
49
+ isLink(node)
50
+ {
51
+ return node && node.nodeType == 1 && node.nodeName == 'A' && node.href;
52
+ }
53
+
54
+ /**
55
+ * Returns a value indicating if the node matches the tag.
56
+ * @param {string[]|string} tag
57
+ * @param {Node} node
58
+ */
59
+ isTagMatch(tag, node)
60
+ {
61
+ let isMatch = false, name = node.nodeName.toLowerCase();
62
+ tag = ($lib.isArray(tag)) ? tag : [tag];
63
+
64
+ $lib.each(tag, function (t)
65
+ {
66
+ isMatch = (name == t.toLowerCase());
67
+ return !isMatch;
68
+ });
69
+
70
+ return isMatch;
71
+ }
72
+
73
+ /**
74
+ * Returns a value indicating if the node is a block node.
75
+ * @param {Node} node
76
+ */
77
+ isBlock(node, includeWrapped = false)
78
+ {
79
+ if (!node || node.nodeType != 1)
80
+ return false;
81
+
82
+ let name = node.nodeName;
83
+
84
+ if (!includeWrapped && name.match(this.utility.wrappedNodesRegEx))
85
+ return false;
86
+ else if (name.match(this.utility.blockNodeRegEx))
87
+ return true;
88
+
89
+ return window.getComputedStyle(node, null).getPropertyValue('position') == 'static' && window.getComputedStyle(node, null).getPropertyValue('display') == 'block';
90
+ }
91
+
92
+ /**
93
+ * Returns a value indicating if the node is a list node.
94
+ * @param {Node} node
95
+ */
96
+ isList(node)
97
+ {
98
+ return node.nodeType == 1 && 'UL OL'.split(' ').indexOf(node.nodeName) > -1;
99
+ }
100
+
101
+ /**
102
+ * Returns a value indicating if the node is a root node for layout elements (LI).
103
+ * @param {Node} node
104
+ */
105
+ isLayoutRoot(node)
106
+ {
107
+ return node.nodeType == 1 && 'LI'.split(' ').indexOf(node.nodeName) > -1;
108
+ }
109
+
110
+ /**
111
+ * Returns a value indicating if the node is a layout node.
112
+ * @param {Node} node
113
+ */
114
+ isLayoutNode(node)
115
+ {
116
+ return this.isTextDecorationNode(node) || this.isStyleNode(node);
117
+ }
118
+
119
+ /**
120
+ * Returns a value indicating if the node is a text decoration node.
121
+ * @param {Node} node
122
+ */
123
+ isTextDecorationNode(node)
124
+ {
125
+ return node.nodeType == 1 && $lib.isEmpty(node.id) && this.utility.layoutNodeNames.filter((val) => { return val != 'span' }).indexOf(node.nodeName.toLowerCase()) > -1;
126
+ }
127
+
128
+ /**
129
+ * Returns a value indicating if the node is a style node.
130
+ * @param {Node} node
131
+ */
132
+ isStyleNode(node)
133
+ {
134
+ return node.nodeType == 1 && node.nodeName == 'SPAN' && !$lib.isEmpty(node.style.cssText);
135
+ }
136
+
137
+ /**
138
+ * Returns a value indicating if the parent node contains the node.
139
+ * @param {Node} parent
140
+ * @param {Node} node
141
+ */
142
+ contains(parent, node)
143
+ {
144
+ return $lib.contains(parent, node);
145
+ }
146
+
147
+ /**
148
+ * Gets the image element inside the figure element.
149
+ * @param {Node} el
150
+ */
151
+ getImageFromNode(el)
152
+ {
153
+ return el.nodeName === 'IMG' ? el : el.querySelector('img');
154
+ }
155
+
156
+ /**
157
+ * Gets the node with the specified node name inside the specified element.
158
+ * @param {Node} el The root element from where to search.
159
+ * @param {String} name The name of the node to find.
160
+ */
161
+ getInnerNodeByName(el, name)
162
+ {
163
+ if (el.nodeName === name) return el;
164
+ return el.querySelector(name);
165
+ }
166
+
167
+ /**
168
+ * Gets the root node (block) for the specified node.
169
+ * @param {Node} node
170
+ * @param {boolean} [useLayoutRoot = true]
171
+ */
172
+ getRootNode(node, useLayoutRoot = true)
173
+ {
174
+ let editableElement = this.editor.getEditorElement();
175
+
176
+ if (node == editableElement)
177
+ return node.firstChild;
178
+ else if (node.parentElement == editableElement)
179
+ return node;
180
+
181
+ while (node)
182
+ {
183
+ if (node.parentElement && !this.isBlock(node) && (!useLayoutRoot || !this.isLayoutRoot(node)))
184
+ node = node.parentElement;
185
+ else
186
+ return node;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Gets the surrounding nodes for the specified element.
192
+ * @param {Node} el
193
+ * @param {Node} rootEl
194
+ */
195
+ getSurroundingNodes(el, rootEl)
196
+ {
197
+ let editableElement = this.editor.getEditorElement(),
198
+ nodes = [];
199
+
200
+ rootEl = rootEl || editableElement;
201
+
202
+ while (el && el != rootEl)
203
+ {
204
+ nodes.push(el);
205
+ el = el.parentElement;
206
+ }
207
+
208
+ return nodes;
209
+ }
210
+
211
+ /**
212
+ * Gets the previous or next sibling node.
213
+ * @param {Node} node
214
+ * @param {Node} parent
215
+ * @param {boolean} previous
216
+ * @param {number} nodeType
217
+ * @param {boolean} skipEmpty
218
+ */
219
+ sibling(node, parent, previous, nodeType, skipEmpty)
220
+ {
221
+ let fnGet = (previous) ? function (node) { return node.previousSibling; } : function (node) { return node.nextSibling; },
222
+ fnNext = function (node)
223
+ {
224
+ let next;
225
+
226
+ while (node && node != parent && !(next = fnGet(node)))
227
+ {
228
+ if (node.parentNode != parent)
229
+ node = node.parentNode;
230
+ else
231
+ node = null;
232
+ }
233
+
234
+ return next;
235
+ };
236
+
237
+ while ((node = fnNext(node)) && ((nodeType && nodeType != node.nodeType) || (skipEmpty && !node.nodeName.match(this.utility.voidNodeRegEx) && !node.textContent.length) || (node.nodeType == 1 && node.hasAttribute(this.utility.markerAttr))))
238
+ {
239
+ }
240
+
241
+ return node;
242
+ }
243
+
244
+ /**
245
+ * Gets the previous sibling nodes for the startnode and the next sibling nodes for the endnode.
246
+ * @param {Node} parent
247
+ * @param {Node} startNode
248
+ * @param {Node} endNode
249
+ */
250
+ getSiblings(parent, startNode, endNode, skipEmpty = true)
251
+ {
252
+ let node = startNode,
253
+ nodes = [];
254
+
255
+ if (node && this.contains(parent, node))
256
+ {
257
+ while ((node = this.sibling(node, parent, true, null, skipEmpty)))
258
+ {
259
+ nodes.unshift(node);
260
+ }
261
+ }
262
+
263
+ node = endNode;
264
+
265
+ if (node && this.contains(parent, node))
266
+ {
267
+ while ((node = this.sibling(node, parent, false, null, skipEmpty)))
268
+ {
269
+ nodes.push(node);
270
+ }
271
+ }
272
+
273
+ return nodes;
274
+ }
275
+
276
+ /**
277
+ * Gets the elements by tag name and returns them in a modifiable array.
278
+ * @param {Node} node
279
+ * @param {String} tagName
280
+ * @param {Boolean} filterMarkers
281
+ */
282
+ getElementsByTagName(node, tagName, filterMarkers = true)
283
+ {
284
+ let mustFilter = (tagName.split(' ').length > 1),
285
+ elements = node.getElementsByTagName((mustFilter) ? '*' : tagName),
286
+ nodes = [];
287
+
288
+ tagName = ' ' + tagName.toUpperCase() + ' ';
289
+
290
+ $lib.each(elements, (el) =>
291
+ {
292
+ if ((!mustFilter || tagName.indexOf(' ' + el.nodeName + ' ') > -1) && (!filterMarkers || !el.hasAttribute(this.utility.markerAttr)))
293
+ nodes.push(el);
294
+ });
295
+
296
+ return nodes;
297
+ }
298
+
299
+ /**
300
+ * Gets the first text node within the specified node.
301
+ * @param {Node} node
302
+ * @param {Node} parent
303
+ * @param {boolean} last
304
+ * @param {boolean} skipEmpty
305
+ */
306
+ getFirstTextNode(node, parent, last, skipEmpty)
307
+ {
308
+ if (skipEmpty == undefined)
309
+ skipEmpty = true;
310
+
311
+ while (node && (node.nodeType != 3 || (skipEmpty && !node.textContent.length)))
312
+ {
313
+ if (node.hasChildNodes())
314
+ node = (last) ? node.lastChild : node.firstChild;
315
+ else
316
+ node = this.sibling(node, parent, last, null, skipEmpty);
317
+ }
318
+
319
+ return node;
320
+ }
321
+
322
+ /**
323
+ * Gets the next sibling node
324
+ * @param {Node} node
325
+ */
326
+ nextNode(node)
327
+ {
328
+ if (!node)
329
+ return null;
330
+
331
+ if (node.hasChildNodes())
332
+ {
333
+ return node.firstChild;
334
+ }
335
+ else
336
+ {
337
+ while (node && !node.nextSibling)
338
+ {
339
+ node = node.parentNode;
340
+ }
341
+ if (!node)
342
+ {
343
+ return null;
344
+ }
345
+ return node.nextSibling;
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Returns a value indicating if the node can be removed.
351
+ * @param {Node} node
352
+ */
353
+ canRemove(node)
354
+ {
355
+ return (this.isLayoutNode(node) && (!this.nodeHasContent(node, false) || (node.firstElementChild == null && node.textContent.match(/^\uFEFF+$/g))));
356
+ }
357
+
358
+ /**
359
+ * Returns a value indicating if the node has content.
360
+ * @param {Node} node
361
+ * @param {boolean} [ignoreBR=true]
362
+ */
363
+ nodeHasContent(node, ignoreBR = true)
364
+ {
365
+ if (node.textContent.length)
366
+ return true;
367
+
368
+ node = node.firstElementChild;
369
+
370
+ while (node)
371
+ {
372
+ if ((!ignoreBR || (ignoreBR && node.nodeName != 'BR')) && !node.hasAttribute(this.utility.markerAttr))
373
+ return true;
374
+
375
+ node = node.nextElementSibling;
376
+ }
377
+
378
+ return false;
379
+ }
380
+
381
+ /**
382
+ * Creates a text node inside the node.
383
+ * @param {Node} node
384
+ * @param {Node} beforeNode
385
+ * @param {string} text
386
+ */
387
+ createTextNodePlaceHolder(node, beforeNode, text)
388
+ {
389
+ let doc = this.editor.getDoc(),
390
+ textNode = doc.createTextNode(text || '');
391
+
392
+ if (beforeNode)
393
+ beforeNode.parentNode.insertBefore(textNode, beforeNode);
394
+ else if (node.nodeName.match(this.utility.voidNodeRegEx))
395
+ node.parentNode.insertBefore(textNode, node);
396
+ else
397
+ node.appendChild(textNode);
398
+
399
+ return textNode;
400
+ }
401
+
402
+ /**
403
+ * Creates node with specified settings.
404
+ * @param {any} settings
405
+ * @returns {HTMLElement} node
406
+ */
407
+ createNode(settings)
408
+ {
409
+ let node;
410
+
411
+ if (!settings.attributes)
412
+ settings.attributes = {};
413
+
414
+ if (settings.cssClass)
415
+ settings.attributes.class = settings.cssClass;
416
+
417
+ if (settings.outerHTML)
418
+ {
419
+ let el = $lib.element();
420
+ el.innerHTML = settings.outerHTML;
421
+ node = $lib.unsurround(el); // document fragment node
422
+ }
423
+ else
424
+ node = this.editor.format.createLayoutNode(settings.tag, settings.styles, (settings.innerHTML) ? [settings.innerHTML] : settings.textContent, settings.attributes, settings.properties);
425
+
426
+ if (!$lib.isEmpty(settings.allowContent))
427
+ node.contentEditable = settings.allowContent; // FF will remove any empty nodes on delete/backspace
428
+
429
+ if (settings.selectable)
430
+ this.editor.bindNodeEvents(node);
431
+
432
+ return node;
433
+ }
434
+
435
+ /**
436
+ * Gets the text container.
437
+ * @param {Node} node
438
+ * @param {Node} parent
439
+ */
440
+ getTextContainer(node, parent)
441
+ {
442
+ while (node != parent && 'DIV TD LI'.split(' ').indexOf(node.nodeName) == -1)
443
+ {
444
+ node = node.parentNode;
445
+ }
446
+
447
+ return node;
448
+ }
449
+
450
+ /**
451
+ * Gets the nodes before the specified node.
452
+ * @param {Node} parentNode The parent node.
453
+ * @param {Node} endNode The ending node.
454
+ * @returns {DocumentFragment} A fragment containing the nodes.
455
+ */
456
+ getNodesBefore(parentNode, endNode)
457
+ {
458
+ let node = parentNode.firstChild,
459
+ fragment = document.createDocumentFragment(),
460
+ next, current = fragment;
461
+
462
+ while (node && node != endNode && node != parentNode)
463
+ {
464
+ if (!node.contains(endNode))
465
+ {
466
+ next = node.nextSibling;
467
+ current.appendChild(node);
468
+ node = next;
469
+ }
470
+ else
471
+ {
472
+ current = node.cloneNode(false);
473
+ fragment.appendChild(current);
474
+ node = node.firstChild;
475
+ }
476
+ }
477
+
478
+ return fragment;
479
+ }
480
+
481
+ /**
482
+ * Get the list (UL/OL) node.
483
+ * @param {Node} startNode
484
+ * @param {Node} rootNode
485
+ */
486
+ getListNode(startNode, rootNode)
487
+ {
488
+ return this.getMatchingNode(startNode, rootNode, (node) => { return this.utility.listFilter.indexOf(node.nodeName) > -1 });
489
+ }
490
+
491
+ /**
492
+ * Get the list-item (LI) node.
493
+ * @param {Node} startNode
494
+ * @param {Node} rootNode
495
+ */
496
+ getListItemNode(startNode, rootNode)
497
+ {
498
+ return this.getMatchingNode(startNode, rootNode, (node) => { return node.nodeName == 'LI'; });
499
+ }
500
+
501
+ /**
502
+ * Get the layout node for the startNode.
503
+ * @param {String} nodeName
504
+ * @param {Node} startNode
505
+ * @param {Node} rootNode
506
+ */
507
+ getLayoutNode(nodeName, startNode, rootNode)
508
+ {
509
+ nodeName = nodeName.toUpperCase();
510
+
511
+ let isMatch = (node) =>
512
+ {
513
+ if (node.nodeName === nodeName)
514
+ return true;
515
+
516
+ // Only match style spans if the layout operation IS a style operation
517
+ if (nodeName === 'SPAN' && this.isStyleNode(node))
518
+ return true;
519
+
520
+ return false;
521
+ };
522
+
523
+ return this.getMatchingNode(startNode, rootNode, isMatch);
524
+ }
525
+
526
+ /**
527
+ * Gets the node that matches the specified condition.
528
+ * @param {Node} startNode
529
+ * @param {Node} rootNode
530
+ * @param {Function} isMatch
531
+ */
532
+ getMatchingNode(startNode, rootNode, isMatch)
533
+ {
534
+ let node = startNode;
535
+
536
+ while (node && node != rootNode && !isMatch(node))
537
+ {
538
+ node = node.parentNode;
539
+ }
540
+
541
+ return (isMatch(node)) ? node : null;
542
+ }
543
+
544
+ /**
545
+ * Gets the layout nodes from a specific start node.
546
+ * @param {Node} startNode The node to start from.
547
+ * @param {Node} rootNode The highest node in the tree to check.
548
+ * @param {Boolean} [clone] A value indicating if a found layout-node is cloned.
549
+ * @param {Number} [type] The type of the nodes to add (1: layout-node, 2: style-node, null/undefined/0: both)
550
+ * @returns {Node[]} The list of layout-nodes.
551
+ */
552
+ getLayoutNodes(startNode, rootNode, clone, type)
553
+ {
554
+ let nodes = [], node = startNode, isLayout, isStyle;
555
+
556
+ while (node != rootNode)
557
+ {
558
+ isLayout = this.isTextDecorationNode(node);
559
+ isStyle = this.isStyleNode(node);
560
+
561
+ if ((!type && (isLayout || isStyle)) || (type == 1 && isLayout) || (type > 1 && isStyle))
562
+ nodes.push((clone) ? node.cloneNode(false) : node);
563
+
564
+ node = node.parentNode;
565
+ }
566
+
567
+ return nodes.reverse();
568
+ }
569
+
570
+ /**
571
+ * Builds the layout node tree with the specified nodes.
572
+ * @param {Node[]} nodes
573
+ */
574
+ buildLayoutTree(nodes)
575
+ {
576
+ let layoutNode;
577
+
578
+ $lib.each(nodes, (node) =>
579
+ {
580
+ let clone = node.cloneNode(false);
581
+
582
+ if (node.hasAttribute(this.utility.selAttr))
583
+ this.editor.bindNodeEvents(clone);
584
+
585
+ if (layoutNode)
586
+ layoutNode.appendChild(clone);
587
+
588
+ layoutNode = clone;
589
+ });
590
+
591
+ return layoutNode;
592
+ }
593
+
594
+ /**
595
+ * Removes the node while keeping markers.
596
+ * @param {Node} node
597
+ * @param {Object} marker
598
+ */
599
+ removeNodeAndKeepMarkers(node, marker)
600
+ {
601
+ let doc = this.editor.getDoc(),
602
+ startMarker = node.querySelector('#' + marker.startId),
603
+ endMarker = (marker.endId) ? node.querySelector('#' + marker.endId) : null;
604
+
605
+ if (startMarker || endMarker)
606
+ {
607
+ let fragment = doc.createDocumentFragment();
608
+
609
+ if (startMarker)
610
+ fragment.appendChild(startMarker);
611
+
612
+ if (endMarker)
613
+ fragment.appendChild(endMarker);
614
+
615
+ node.replaceWith(fragment);
616
+ }
617
+ else
618
+ $lib.remove(node);
619
+ }
620
+
621
+ /**
622
+ * Change node to specified block element.
623
+ * @param {Node} node
624
+ * @param {Node} blockNode
625
+ */
626
+ setBlockElement(node, blockNode)
627
+ {
628
+ let childNode = (blockNode && blockNode.firstElementChild) ? blockNode.firstElementChild : blockNode;
629
+
630
+ childNode.appendChild($lib.extract(node));
631
+
632
+ if (this.isLayoutRoot(node)) // exception for LI/TH/TD
633
+ node.appendChild(blockNode);
634
+ else
635
+ {
636
+ this.editor.format.copyStyles(node, blockNode);
637
+ node.replaceWith(blockNode);
638
+ }
639
+
640
+ if (!childNode.childNodes.length)
641
+ childNode.appendChild(this.editor.getDoc().createTextNode(this.utility.zeroWidthChar));
642
+ }
643
+
644
+ createCursorSpace(x)
645
+ {
646
+ this.editor.activateDocument();
647
+
648
+ if (!this.editor.contentManager.hasContent())
649
+ return;
650
+
651
+ let range = this.editor.selectionRange.getRange(),
652
+ rootNodes = this.editor.selectionRange.getRootNodesInRange(range),
653
+ rootNode = rootNodes[0],
654
+ firstChild = rootNode.firstChild,
655
+ lastChild = rootNode.lastChild;
656
+
657
+ if (firstChild && firstChild != rootNode && firstChild.nodeType == 1 && firstChild.hasAttribute(this.utility.selAttr) && firstChild.contentEditable == 'false')
658
+ {
659
+ let textNode = this.editor.getDoc().createTextNode(this.utility.zeroWidthChar);
660
+
661
+ if (x < $lib.getPos(firstChild).left && !firstChild?.previousSibling?.nodeValue?.match(this.utility.zeroWidthRegEx))
662
+ {
663
+ firstChild.parentNode.insertBefore(textNode, firstChild);
664
+ range.setStart(textNode, 0);
665
+ range.collapse(true);
666
+ this.editor.selectionRange.restoreRange(range);
667
+ }
668
+ else if (lastChild.nodeType == 1 && lastChild.nodeName != 'BR' && x > $lib.getPos(lastChild).right && !lastChild?.nextSibling?.nodeValue?.match(this.utility.zeroWidthRegEx))
669
+ {
670
+ lastChild.parentNode.insertBefore(textNode, lastChild.nextSibling);
671
+ range.setStart(textNode, 0);
672
+ range.collapse(true);
673
+ this.editor.selectionRange.restoreRange(range);
674
+ }
675
+ }
676
+ }
677
+ };
678
+
679
+ var NodeManager = componyx.UI.editor_modules.NodeManager;
680
+
681
+ export { NodeManager as default };