-
Notifications
You must be signed in to change notification settings - Fork 643
Expand file tree
/
Copy pathAposAreas.js
More file actions
148 lines (125 loc) · 4.16 KB
/
Copy pathAposAreas.js
File metadata and controls
148 lines (125 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* eslint-disable vue/one-component-per-file */
import createApp from 'Modules/@apostrophecms/ui/lib/vue';
export default function() {
let widgetsRendering = 0;
apos.area.widgetOptions = [];
createWidgetClipboardApp();
createAreaApps();
document.documentElement.style.setProperty('--a-widget-margin', apos.ui.widgetMargin);
apos.bus.$on('widget-rendering', function() {
widgetsRendering++;
});
apos.bus.$on('widget-rendered', options => {
widgetsRendering--;
createAreaAppsAndRunPlayersIfDone(options);
});
apos.bus.$on('refreshed', function() {
createAreaAppsAndRunPlayersIfDone();
});
function createAreaAppsAndRunPlayersIfDone({ edit = true } = {}) {
if (edit) {
createAreaApps();
}
if (widgetsRendering === 0) {
apos.util.runPlayers();
}
}
function createAreaApps() {
// Sort the areas by DOM depth to ensure parents light up before children
const els = Array.from(document.querySelectorAll('[data-apos-area-newly-editable]'));
els.sort((a, b) => {
const da = depth(a);
const db = depth(b);
if (da < db) {
return -1;
} else if (db > da) {
return 1;
} else {
return 0;
}
});
for (const el of els) {
createAreaApp(el);
}
}
function depth(el) {
let depth = 0;
while (el) {
el = el.parentNode;
depth++;
}
return depth;
}
function createAreaApp(el) {
const options = JSON.parse(el.getAttribute('data-options')) || {};
const data = JSON.parse(el.getAttribute('data')) || {};
const fieldId = el.getAttribute('data-field-id');
const moduleName = el.getAttribute('data-module');
const choices = JSON.parse(el.getAttribute('data-choices'));
const renderings = {};
const _docId = data._docId;
const parentOptionsStr = el.getAttribute('data-parent-options');
const parentOptions = parentOptionsStr ? JSON.parse(parentOptionsStr) : null;
let componentName = options.editorComponent || 'AposAreaEditor';
if (!apos.vueComponents[componentName]) {
// eslint-disable-next-line no-console
console.error(`Area Editor component "${componentName}" not found. Switching to default.`);
componentName = 'AposAreaEditor';
}
const component = apos.vueComponents[componentName];
for (const widgetEl of el.querySelectorAll('[data-apos-widget]')) {
const _id = widgetEl.getAttribute('data-apos-widget');
const item = data.items.find(item => _id === item._id);
// This will only match our own widgets, leaving the nested matches alone,
// another area app will handle them when the time comes
if (item) {
renderings[_id] = {
html: widgetEl.innerHTML,
parameters: {
_docId,
widget: item,
areaFieldId: fieldId,
type: item.type
}
};
widgetEl.remove();
}
}
el.removeAttribute('data-apos-area-newly-editable');
if (apos.area.activeEditor && (apos.area.activeEditor.id === data._id)) {
// Editing a piece causes a refresh of the main content area,
// but this may contain the area we originally intended to add
// a widget to when we created a piece for that purpose. Preserve
// the editing experience by restoring that widget's editor to the DOM
// rather than creating a new one.
el.parentNode.replaceChild(apos.area.activeEditor.$el, el);
} else {
const app = createApp(component, {
options,
id: data._id,
items: data.items,
choices,
docId: _docId,
fieldId,
moduleName,
parentOptions,
renderings
});
app.mount(el);
}
}
function createWidgetClipboardApp() {
// Simpler and more reliable to just talk to localStorage always and avoid the
// storage event handle
class Clipboard {
set(widget) {
localStorage.setItem('aposWidgetClipboard', JSON.stringify(widget));
}
get() {
const existing = window.localStorage.getItem('aposWidgetClipboard');
return existing ? JSON.parse(existing) : null;
}
}
apos.area.widgetClipboard = new Clipboard();
}
}