提交 | 用户 | 时间
|
71e81e
|
1 |
/* |
懒 |
2 |
* Activiti Modeler component part of the Activiti project |
|
3 |
* Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. |
|
4 |
|
|
5 |
* This library is free software; you can redistribute it and/or |
|
6 |
* modify it under the terms of the GNU Lesser General Public |
|
7 |
* License as published by the Free Software Foundation; either |
|
8 |
* version 2.1 of the License, or (at your option) any later version. |
|
9 |
* |
|
10 |
* This library is distributed in the hope that it will be useful, |
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
* Lesser General Public License for more details. |
|
14 |
|
|
15 |
* You should have received a copy of the GNU Lesser General Public |
|
16 |
* License along with this library; if not, write to the Free Software |
|
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
*/ |
|
19 |
'use strict'; |
|
20 |
|
|
21 |
var activitiModeler = angular.module('activitiModeler', [ |
|
22 |
'ngCookies', |
|
23 |
'ngResource', |
|
24 |
'ngSanitize', |
|
25 |
'ngRoute', |
|
26 |
'ngDragDrop', |
|
27 |
'mgcrea.ngStrap', |
|
28 |
'ngGrid', |
|
29 |
'ngAnimate', |
|
30 |
'pascalprecht.translate', |
|
31 |
'duScroll' |
|
32 |
]); |
|
33 |
|
|
34 |
var activitiModule = activitiModeler; |
|
35 |
|
|
36 |
activitiModeler |
|
37 |
// Initialize routes |
|
38 |
.config(['$selectProvider', '$translateProvider', function ($selectProvider, $translateProvider) { |
|
39 |
|
|
40 |
// Override caret for bs-select directive |
|
41 |
angular.extend($selectProvider.defaults, { |
|
42 |
caretHtml: ' <i class="icon icon-caret-down"></i>' |
|
43 |
}); |
|
44 |
|
|
45 |
// Initialize angular-translate |
|
46 |
$translateProvider.useStaticFilesLoader({ |
|
47 |
prefix: './editor-app/i18n/', |
|
48 |
suffix: '.json' |
|
49 |
}); |
|
50 |
|
|
51 |
$translateProvider.preferredLanguage('en'); |
|
52 |
|
|
53 |
// remember language |
|
54 |
$translateProvider.useCookieStorage(); |
|
55 |
|
|
56 |
}]) |
|
57 |
.run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$window', '$http', '$q', |
|
58 |
function($rootScope, $timeout, $modal, $translate, $location, $window, $http, $q) { |
|
59 |
|
|
60 |
$rootScope.config = ACTIVITI.CONFIG; |
|
61 |
|
|
62 |
$rootScope.editorInitialized = false; |
|
63 |
|
|
64 |
$rootScope.editorFactory = $q.defer(); |
|
65 |
|
|
66 |
$rootScope.forceSelectionRefresh = false; |
|
67 |
|
|
68 |
$rootScope.ignoreChanges = false; // by default never ignore changes |
|
69 |
|
|
70 |
$rootScope.validationErrors = []; |
|
71 |
|
|
72 |
$rootScope.staticIncludeVersion = Date.now(); |
|
73 |
|
|
74 |
/** |
|
75 |
* A 'safer' apply that avoids concurrent updates (which $apply allows). |
|
76 |
*/ |
|
77 |
$rootScope.safeApply = function(fn) { |
|
78 |
var phase = this.$root.$$phase; |
|
79 |
if(phase == '$apply' || phase == '$digest') { |
|
80 |
if(fn && (typeof(fn) === 'function')) { |
|
81 |
fn(); |
|
82 |
} |
|
83 |
} else { |
|
84 |
this.$apply(fn); |
|
85 |
} |
|
86 |
}; |
|
87 |
|
|
88 |
|
|
89 |
/** |
|
90 |
* Initialize the event bus: couple all Oryx events with a dispatch of the |
|
91 |
* event of the event bus. This way, it gets much easier to attach custom logic |
|
92 |
* to any event. |
|
93 |
*/ |
|
94 |
|
|
95 |
/* Helper method to fetch model from server (always needed) */ |
|
96 |
function fetchModel(modelId) { |
|
97 |
|
|
98 |
var modelUrl = KISBPM.URL.getModel(modelId); |
|
99 |
|
|
100 |
console.log(modelUrl); |
|
101 |
|
|
102 |
$http({method: 'GET', url: modelUrl}). |
|
103 |
success(function (data, status, headers, config) { |
|
104 |
$rootScope.editor = new ORYX.Editor(data); |
|
105 |
$rootScope.modelData = angular.fromJson(data); |
|
106 |
$rootScope.editorFactory.resolve(); |
|
107 |
}). |
|
108 |
error(function (data, status, headers, config) { |
|
109 |
console.log('Error loading model with id ' + modelId + ' ' + data); |
|
110 |
}); |
|
111 |
} |
|
112 |
|
|
113 |
|
|
114 |
function initScrollHandling() { |
|
115 |
var canvasSection = jQuery('#canvasSection'); |
|
116 |
canvasSection.scroll(function() { |
|
117 |
|
|
118 |
// Hides the resizer and quick menu items during scrolling |
|
119 |
|
|
120 |
var selectedElements = $rootScope.editor.selection; |
|
121 |
var subSelectionElements = $rootScope.editor._subSelection; |
|
122 |
|
|
123 |
$rootScope.selectedElements = selectedElements; |
|
124 |
$rootScope.subSelectionElements = subSelectionElements; |
|
125 |
if (selectedElements && selectedElements.length > 0) { |
|
126 |
$rootScope.selectedElementBeforeScrolling = selectedElements[0]; |
|
127 |
} |
|
128 |
|
|
129 |
jQuery('.Oryx_button').each(function(i, obj) { |
|
130 |
$rootScope.orginalOryxButtonStyle = obj.style.display; |
|
131 |
obj.style.display = 'none'; |
|
132 |
}); |
|
133 |
|
|
134 |
jQuery('.resizer_southeast').each(function(i, obj) { |
|
135 |
$rootScope.orginalResizerSEStyle = obj.style.display; |
|
136 |
obj.style.display = 'none'; |
|
137 |
}); |
|
138 |
jQuery('.resizer_northwest').each(function(i, obj) { |
|
139 |
$rootScope.orginalResizerNWStyle = obj.style.display; |
|
140 |
obj.style.display = 'none'; |
|
141 |
}); |
|
142 |
$rootScope.editor.handleEvents({type:ORYX.CONFIG.EVENT_CANVAS_SCROLL}); |
|
143 |
}); |
|
144 |
|
|
145 |
canvasSection.scrollStopped(function(){ |
|
146 |
|
|
147 |
// Puts the quick menu items and resizer back when scroll is stopped. |
|
148 |
|
|
149 |
$rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same |
|
150 |
$rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements); |
|
151 |
$rootScope.selectedElements = undefined; |
|
152 |
$rootScope.subSelectionElements = undefined; |
|
153 |
|
|
154 |
function handleDisplayProperty(obj) { |
|
155 |
if (jQuery(obj).position().top > 0) { |
|
156 |
obj.style.display = 'block'; |
|
157 |
} else { |
|
158 |
obj.style.display = 'none'; |
|
159 |
} |
|
160 |
} |
|
161 |
|
|
162 |
jQuery('.Oryx_button').each(function(i, obj) { |
|
163 |
handleDisplayProperty(obj); |
|
164 |
}); |
|
165 |
|
|
166 |
jQuery('.resizer_southeast').each(function(i, obj) { |
|
167 |
handleDisplayProperty(obj); |
|
168 |
}); |
|
169 |
jQuery('.resizer_northwest').each(function(i, obj) { |
|
170 |
handleDisplayProperty(obj); |
|
171 |
}); |
|
172 |
|
|
173 |
}); |
|
174 |
} |
|
175 |
|
|
176 |
/** |
|
177 |
* Initialize the Oryx Editor when the content has been loaded |
|
178 |
*/ |
|
179 |
$rootScope.$on('$includeContentLoaded', function (event) { |
|
180 |
if (!$rootScope.editorInitialized) { |
|
181 |
|
|
182 |
ORYX._loadPlugins(); |
|
183 |
|
|
184 |
var modelId = EDITOR.UTIL.getParameterByName('modelId'); |
|
185 |
fetchModel(modelId); |
|
186 |
|
|
187 |
$rootScope.window = {}; |
|
188 |
var updateWindowSize = function() { |
|
189 |
$rootScope.window.width = $window.innerWidth; |
|
190 |
$rootScope.window.height = $window.innerHeight; |
|
191 |
}; |
|
192 |
|
|
193 |
// Window resize hook |
|
194 |
angular.element($window).bind('resize', function() { |
|
195 |
$rootScope.safeApply(updateWindowSize()); |
|
196 |
}); |
|
197 |
|
|
198 |
$rootScope.$watch('window.forceRefresh', function(newValue) { |
|
199 |
if(newValue) { |
|
200 |
$timeout(function() { |
|
201 |
updateWindowSize(); |
|
202 |
$rootScope.window.forceRefresh = false; |
|
203 |
}); |
|
204 |
} |
|
205 |
}); |
|
206 |
|
|
207 |
updateWindowSize(); |
|
208 |
|
|
209 |
// Hook in resizing of main panels when window resizes |
|
210 |
// TODO: perhaps move to a separate JS-file? |
|
211 |
jQuery(window).resize(function () { |
|
212 |
|
|
213 |
// Calculate the offset based on the bottom of the module header |
|
214 |
var offset = jQuery("#editor-header").offset(); |
|
215 |
var propSectionHeight = jQuery('#propertySection').height(); |
|
216 |
var canvas = jQuery('#canvasSection'); |
|
217 |
var mainHeader = jQuery('#main-header'); |
|
218 |
|
|
219 |
if (offset == undefined || offset === null |
|
220 |
|| propSectionHeight === undefined || propSectionHeight === null |
|
221 |
|| canvas === undefined || canvas === null || mainHeader === null) { |
|
222 |
return; |
|
223 |
} |
|
224 |
|
|
225 |
if ($rootScope.editor) |
|
226 |
{ |
|
227 |
var selectedElements = $rootScope.editor.selection; |
|
228 |
var subSelectionElements = $rootScope.editor._subSelection; |
|
229 |
|
|
230 |
$rootScope.selectedElements = selectedElements; |
|
231 |
$rootScope.subSelectionElements = subSelectionElements; |
|
232 |
if (selectedElements && selectedElements.length > 0) |
|
233 |
{ |
|
234 |
$rootScope.selectedElementBeforeScrolling = selectedElements[0]; |
|
235 |
|
|
236 |
$rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same |
|
237 |
$rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements); |
|
238 |
$rootScope.selectedElements = undefined; |
|
239 |
$rootScope.subSelectionElements = undefined; |
|
240 |
} |
|
241 |
} |
|
242 |
|
|
243 |
var totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21; |
|
244 |
canvas.height(totalAvailable - propSectionHeight); |
|
245 |
jQuery('#paletteSection').height(totalAvailable); |
|
246 |
|
|
247 |
// Update positions of the resize-markers, according to the canvas |
|
248 |
|
|
249 |
var actualCanvas = null; |
|
250 |
if (canvas && canvas[0].children[1]) { |
|
251 |
actualCanvas = canvas[0].children[1]; |
|
252 |
} |
|
253 |
|
|
254 |
var canvasTop = canvas.position().top; |
|
255 |
var canvasLeft = canvas.position().left; |
|
256 |
var canvasHeight = canvas[0].clientHeight; |
|
257 |
var canvasWidth = canvas[0].clientWidth; |
|
258 |
var iconCenterOffset = 8; |
|
259 |
var widthDiff = 0; |
|
260 |
|
|
261 |
var actualWidth = 0; |
|
262 |
if(actualCanvas) { |
|
263 |
// In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent |
|
264 |
actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth; |
|
265 |
} |
|
266 |
|
|
267 |
|
|
268 |
if(actualWidth < canvas[0].clientWidth) { |
|
269 |
widthDiff = actualWidth - canvas[0].clientWidth; |
|
270 |
// In case the canvas is smaller than the actual viewport, the resizers should be moved |
|
271 |
canvasLeft -= widthDiff / 2; |
|
272 |
canvasWidth += widthDiff; |
|
273 |
} |
|
274 |
|
|
275 |
var iconWidth = 17; |
|
276 |
var iconOffset = 20; |
|
277 |
|
|
278 |
var north = jQuery('#canvas-grow-N'); |
|
279 |
north.css('top', canvasTop + iconOffset + 'px'); |
|
280 |
north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); |
|
281 |
|
|
282 |
var south = jQuery('#canvas-grow-S'); |
|
283 |
south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); |
|
284 |
south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); |
|
285 |
|
|
286 |
var east = jQuery('#canvas-grow-E'); |
|
287 |
east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px'); |
|
288 |
east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); |
|
289 |
|
|
290 |
var west = jQuery('#canvas-grow-W'); |
|
291 |
west.css('top', canvasTop -10 + (canvasHeight - iconWidth) / 2 + 'px'); |
|
292 |
west.css('left', canvasLeft + iconOffset + 'px'); |
|
293 |
|
|
294 |
north = jQuery('#canvas-shrink-N'); |
|
295 |
north.css('top', canvasTop + iconOffset + 'px'); |
|
296 |
north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px'); |
|
297 |
|
|
298 |
south = jQuery('#canvas-shrink-S'); |
|
299 |
south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); |
|
300 |
south.css('left', canvasLeft +10 + (canvasWidth - iconWidth) / 2 + 'px'); |
|
301 |
|
|
302 |
east = jQuery('#canvas-shrink-E'); |
|
303 |
east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); |
|
304 |
east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); |
|
305 |
|
|
306 |
west = jQuery('#canvas-shrink-W'); |
|
307 |
west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); |
|
308 |
west.css('left', canvasLeft + iconOffset + 'px'); |
|
309 |
}); |
|
310 |
|
|
311 |
jQuery(window).trigger('resize'); |
|
312 |
|
|
313 |
jQuery.fn.scrollStopped = function(callback) { |
|
314 |
jQuery(this).scroll(function(){ |
|
315 |
var self = this, $this = jQuery(self); |
|
316 |
if ($this.data('scrollTimeout')) { |
|
317 |
clearTimeout($this.data('scrollTimeout')); |
|
318 |
} |
|
319 |
$this.data('scrollTimeout', setTimeout(callback,50,self)); |
|
320 |
}); |
|
321 |
}; |
|
322 |
|
|
323 |
// Always needed, cause the DOM element on which the scroll event listeners are attached are changed for every new model |
|
324 |
initScrollHandling(); |
|
325 |
|
|
326 |
$rootScope.editorInitialized = true; |
|
327 |
} |
|
328 |
}); |
|
329 |
|
|
330 |
/** |
|
331 |
* Initialize the event bus: couple all Oryx events with a dispatch of the |
|
332 |
* event of the event bus. This way, it gets much easier to attach custom logic |
|
333 |
* to any event. |
|
334 |
*/ |
|
335 |
|
|
336 |
$rootScope.editorFactory.promise.then(function() { |
|
337 |
|
|
338 |
KISBPM.eventBus.editor = $rootScope.editor; |
|
339 |
|
|
340 |
var eventMappings = [ |
|
341 |
{ oryxType : ORYX.CONFIG.EVENT_SELECTION_CHANGED, kisBpmType : KISBPM.eventBus.EVENT_TYPE_SELECTION_CHANGE }, |
|
342 |
{ oryxType : ORYX.CONFIG.EVENT_DBLCLICK, kisBpmType : KISBPM.eventBus.EVENT_TYPE_DOUBLE_CLICK }, |
|
343 |
{ oryxType : ORYX.CONFIG.EVENT_MOUSEOUT, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OUT }, |
|
344 |
{ oryxType : ORYX.CONFIG.EVENT_MOUSEOVER, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OVER } |
|
345 |
|
|
346 |
]; |
|
347 |
|
|
348 |
eventMappings.forEach(function(eventMapping) { |
|
349 |
$rootScope.editor.registerOnEvent(eventMapping.oryxType, function(event) { |
|
350 |
KISBPM.eventBus.dispatch(eventMapping.kisBpmType, event); |
|
351 |
}); |
|
352 |
}); |
|
353 |
|
|
354 |
$rootScope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, function (event) { |
|
355 |
var validateButton = document.getElementById(event.shape.resourceId + "-validate-button"); |
|
356 |
if (validateButton) |
|
357 |
{ |
|
358 |
validateButton.style.display = 'none'; |
|
359 |
} |
|
360 |
}); |
|
361 |
|
|
362 |
// The Oryx canvas is ready (we know since we're in this promise callback) and the |
|
363 |
// event bus is ready. The editor is now ready for use |
|
364 |
KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_EDITOR_READY, {type : KISBPM.eventBus.EVENT_TYPE_EDITOR_READY}); |
|
365 |
|
|
366 |
}); |
|
367 |
|
|
368 |
// Alerts |
|
369 |
$rootScope.alerts = { |
|
370 |
queue: [] |
|
371 |
}; |
|
372 |
|
|
373 |
$rootScope.showAlert = function(alert) { |
|
374 |
if(alert.queue.length > 0) { |
|
375 |
alert.current = alert.queue.shift(); |
|
376 |
// Start timout for message-pruning |
|
377 |
alert.timeout = $timeout(function() { |
|
378 |
if (alert.queue.length == 0) { |
|
379 |
alert.current = undefined; |
|
380 |
alert.timeout = undefined; |
|
381 |
} else { |
|
382 |
$rootScope.showAlert(alert); |
|
383 |
} |
|
384 |
}, (alert.current.type == 'error' ? 5000 : 1000)); |
|
385 |
} else { |
|
386 |
$rootScope.alerts.current = undefined; |
|
387 |
} |
|
388 |
}; |
|
389 |
|
|
390 |
$rootScope.addAlert = function(message, type) { |
|
391 |
var newAlert = {message: message, type: type}; |
|
392 |
if (!$rootScope.alerts.timeout) { |
|
393 |
// Timeout for message queue is not running, start one |
|
394 |
$rootScope.alerts.queue.push(newAlert); |
|
395 |
$rootScope.showAlert($rootScope.alerts); |
|
396 |
} else { |
|
397 |
$rootScope.alerts.queue.push(newAlert); |
|
398 |
} |
|
399 |
}; |
|
400 |
|
|
401 |
$rootScope.dismissAlert = function() { |
|
402 |
if (!$rootScope.alerts.timeout) { |
|
403 |
$rootScope.alerts.current = undefined; |
|
404 |
} else { |
|
405 |
$timeout.cancel($rootScope.alerts.timeout); |
|
406 |
$rootScope.alerts.timeout = undefined; |
|
407 |
$rootScope.showAlert($rootScope.alerts); |
|
408 |
} |
|
409 |
}; |
|
410 |
|
|
411 |
$rootScope.addAlertPromise = function(promise, type) { |
|
412 |
if (promise) { |
|
413 |
promise.then(function(data) { |
|
414 |
$rootScope.addAlert(data, type); |
|
415 |
}); |
|
416 |
} |
|
417 |
}; |
|
418 |
|
|
419 |
} |
|
420 |
]) |
|
421 |
|
|
422 |
// Moment-JS date-formatting filter |
|
423 |
.filter('dateformat', function() { |
|
424 |
return function(date, format) { |
|
425 |
if (date) { |
|
426 |
if (format) { |
|
427 |
return moment(date).format(format); |
|
428 |
} else { |
|
429 |
return moment(date).calendar(); |
|
430 |
} |
|
431 |
} |
|
432 |
return ''; |
|
433 |
}; |
|
434 |
}); |