UNPKG

7.4 kBJavaScriptView Raw
1'use strict';
2
3var domQuery = require('min-dom').query,
4 domClear = require('min-dom').clear,
5 domClasses = require('min-dom').classes,
6 is = require('bpmn-js/lib/util/ModelUtil').is,
7 forEach = require('lodash/forEach'),
8 domify = require('min-dom').domify,
9 Ids = require('ids').default;
10
11var SPACE_REGEX = /\s/;
12
13// for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
14var QNAME_REGEX = /^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i;
15
16// for ID validation as per BPMN Schema (QName - Namespace)
17var ID_REGEX = /^[a-z_][\w-.]*$/i;
18
19var HTML_ESCAPE_MAP = {
20 '&': '&',
21 '<': '&lt;',
22 '>': '&gt;',
23 '"': '&quot;',
24 '\'': '&#39;'
25};
26
27function selectedOption(selectBox) {
28 if (selectBox.selectedIndex >= 0) {
29 return selectBox.options[selectBox.selectedIndex].value;
30 }
31}
32
33module.exports.selectedOption = selectedOption;
34
35
36function selectedType(elementSyntax, inputNode) {
37 var typeSelect = domQuery(elementSyntax, inputNode);
38 return selectedOption(typeSelect);
39}
40
41module.exports.selectedType = selectedType;
42
43
44/**
45 * Retrieve the root element the document this
46 * business object is contained in.
47 *
48 * @return {ModdleElement}
49 */
50function getRoot(businessObject) {
51 var parent = businessObject;
52 while (parent.$parent) {
53 parent = parent.$parent;
54 }
55 return parent;
56}
57
58module.exports.getRoot = getRoot;
59
60
61/**
62 * filters all elements in the list which have a given type.
63 * removes a new list
64 */
65function filterElementsByType(objectList, type) {
66 var list = objectList || [];
67 var result = [];
68 forEach(list, function(obj) {
69 if (is(obj, type)) {
70 result.push(obj);
71 }
72 });
73 return result;
74}
75
76module.exports.filterElementsByType = filterElementsByType;
77
78
79function findRootElementsByType(businessObject, referencedType) {
80 var root = getRoot(businessObject);
81
82 return filterElementsByType(root.rootElements, referencedType);
83}
84
85module.exports.findRootElementsByType = findRootElementsByType;
86
87
88function removeAllChildren(domElement) {
89 while (domElement.firstChild) {
90 domElement.removeChild(domElement.firstChild);
91 }
92}
93
94module.exports.removeAllChildren = removeAllChildren;
95
96
97/**
98 * adds an empty option to the list
99 */
100function addEmptyParameter(list) {
101 return list.push({ 'label': '', 'value': '', 'name': '' });
102}
103
104module.exports.addEmptyParameter = addEmptyParameter;
105
106
107/**
108 * returns a list with all root elements for the given parameter 'referencedType'
109 */
110function refreshOptionsModel(businessObject, referencedType) {
111 var model = [];
112 var referableObjects = findRootElementsByType(businessObject, referencedType);
113 forEach(referableObjects, function(obj) {
114 model.push({
115 label: (obj.name || '') + ' (id='+obj.id+')',
116 value: obj.id,
117 name: obj.name
118 });
119 });
120 return model;
121}
122
123module.exports.refreshOptionsModel = refreshOptionsModel;
124
125
126/**
127 * fills the drop down with options
128 */
129function updateOptionsDropDown(domSelector, businessObject, referencedType, entryNode) {
130 var options = refreshOptionsModel(businessObject, referencedType);
131 addEmptyParameter(options);
132 var selectBox = domQuery(domSelector, entryNode);
133 domClear(selectBox);
134
135 forEach(options, function(option) {
136 var optionEntry = domify('<option value="' + escapeHTML(option.value) + '">' + escapeHTML(option.label) + '</option>');
137 selectBox.appendChild(optionEntry);
138 });
139 return options;
140}
141
142module.exports.updateOptionsDropDown = updateOptionsDropDown;
143
144
145/**
146 * checks whether the id value is valid
147 *
148 * @param {ModdleElement} bo
149 * @param {String} idValue
150 * @param {Function} translate
151 *
152 * @return {String} error message
153 */
154function isIdValid(bo, idValue, translate) {
155 var assigned = bo.$model.ids.assigned(idValue);
156
157 var idExists = assigned && assigned !== bo;
158
159 if (!idValue || idExists) {
160 return translate('Element must have an unique id.');
161 }
162
163 return validateId(idValue, translate);
164}
165
166module.exports.isIdValid = isIdValid;
167
168
169function validateId(idValue, translate) {
170
171 if (containsSpace(idValue)) {
172 return translate('Id must not contain spaces.');
173 }
174
175 if (!ID_REGEX.test(idValue)) {
176
177 if (QNAME_REGEX.test(idValue)) {
178 return translate('Id must not contain prefix.');
179 }
180
181 return translate('Id must be a valid QName.');
182 }
183}
184
185module.exports.validateId = validateId;
186
187
188function containsSpace(value) {
189 return SPACE_REGEX.test(value);
190}
191
192module.exports.containsSpace = containsSpace;
193
194/**
195 * generate a semantic id with given prefix
196 */
197function nextId(prefix) {
198 var ids = new Ids([32,32,1]);
199
200 return ids.nextPrefixed(prefix);
201}
202
203module.exports.nextId = nextId;
204
205
206function triggerClickEvent(element) {
207 var evt;
208 var eventType = 'click';
209
210 if (document.createEvent) {
211 try {
212 // Chrome, Safari, Firefox
213 evt = new MouseEvent((eventType), { view: window, bubbles: true, cancelable: true });
214 } catch (e) {
215 // IE 11, PhantomJS (wat!)
216 evt = document.createEvent('MouseEvent');
217
218 evt.initEvent((eventType), true, true);
219 }
220 return element.dispatchEvent(evt);
221 } else {
222 // Welcome IE
223 evt = document.createEventObject();
224
225 return element.fireEvent('on' + eventType, evt);
226 }
227}
228
229module.exports.triggerClickEvent = triggerClickEvent;
230
231
232function escapeHTML(str) {
233 str = '' + str;
234
235 return str && str.replace(/[&<>"']/g, function(match) {
236 return HTML_ESCAPE_MAP[match];
237 });
238}
239
240module.exports.escapeHTML = escapeHTML;
241
242function createDropdown(dropdown) {
243 var menu = dropdown.menu;
244
245 var dropdownNode = domify(
246 '<div class="group__dropdown">' +
247 '<button class="group__dropdown-button">' +
248 '<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M96 184c39.8 0 72 32.2 72 72s-32.2 72-72 72-72-32.2-72-72 32.2-72 72-72zM24 80c0 39.8 32.2 72 72 72s72-32.2 72-72S135.8 8 96 8 24 40.2 24 80zm0 352c0 39.8 32.2 72 72 72s72-32.2 72-72-32.2-72-72-72-72 32.2-72 72z"></path></svg>' +
249 '</button>' +
250 '<div class="group__dropdown-menu"></div>' +
251 '</div>'
252 );
253
254 var buttonNode = domQuery('.group__dropdown-button', dropdownNode),
255 menuNode = domQuery('.group__dropdown-menu', dropdownNode);
256
257 buttonNode.addEventListener('click', function(event) {
258 domClasses(dropdownNode).toggle('group__dropdown--open');
259
260 createOnGlobalClick(event);
261 });
262
263 forEach(menu, function(menuItem) {
264 var menuItemNode = domify('<div class="group__dropdown-menu-item" data-dropdown-action="' +
265 menuItem.id +
266 '">' + escapeHTML(menuItem.label) + '</div>');
267
268 menuItemNode.addEventListener('click', function() {
269 menuItem.onClick();
270
271 domClasses(dropdownNode).remove('group__dropdown--open');
272 });
273
274 menuNode.appendChild(menuItemNode);
275 });
276
277 var _onGlobalClick;
278
279 function createOnGlobalClick(_event) {
280 function onGlobalClick(event) {
281 if (event === _event) {
282 return;
283 }
284
285 var target = event.target;
286
287 if (menuNode !== target && !menuNode.contains(target)) {
288 domClasses(dropdownNode).remove('group__dropdown--open');
289
290 document.removeEventListener('click', onGlobalClick);
291 }
292 }
293
294 if (_onGlobalClick) {
295 document.removeEventListener('click', _onGlobalClick);
296 }
297
298 document.addEventListener('click', onGlobalClick);
299
300 _onGlobalClick = onGlobalClick;
301 }
302
303 return dropdownNode;
304}
305
306module.exports.createDropdown = createDropdown;
\No newline at end of file