4 * Construcs a new sidebar for the given editor.
6 function Sidebar(editorUi, container) {
7 this.editorUi = editorUi;
8 this.container = container;
9 this.palettes = new Object();
10 this.showTooltips = true;
11 this.graph = new Graph(document.createElement('div'), null, null, this.editorUi
12 .editor.graph.getStylesheet());
13 this.graph.resetViewOnRootChange = false;
14 this.graph.foldingEnabled = false;
15 this.graph.setConnectable(false);
16 this.graph.autoScroll = false;
17 this.graph.setTooltips(false);
18 this.graph.setEnabled(false);
20 // Container must be in the DOM for correct HTML rendering
21 this.graph.container.style.visibility = 'hidden';
22 this.graph.container.style.position = 'absolute';
23 document.body.appendChild(this.graph.container);
25 if (!mxClient.IS_TOUCH) {
26 mxEvent.addListener(document, 'mouseup', mxUtils.bind(this, function() {
27 this.showTooltips = true;
30 // Enables tooltips after scroll
31 mxEvent.addListener(container, 'scroll', mxUtils.bind(this, function() {
32 this.showTooltips = true;
35 mxEvent.addListener(document, 'mousedown', mxUtils.bind(this, function() {
36 this.showTooltips = false;
40 mxEvent.addListener(document, 'mousemove', mxUtils.bind(this, function(evt) {
41 var src = mxEvent.getSource(evt);
44 if (src == this.currentElt) {
54 // Handles mouse leaving the window
55 mxEvent.addListener(document, 'mouseout', mxUtils.bind(this, function(evt) {
56 if (evt.toElement == null && evt.relatedTarget == null) {
64 // Pre-fetches tooltip image
65 new Image().src = IMAGE_PATH + '/tooltip.png';
69 * Adds all palettes to the sidebar.
71 Sidebar.prototype.init = function() {
72 var dir = STENCIL_PATH;
75 this.addImagePalette('entry', mxResources.get('application'), dir + '/',
76 '_128x128.png', ['start', 'question', 'input', 'end', 'email'], [mxResources.get('start'),
77 mxResources.get('question'), mxResources.get('input'), mxResources.get('end'), mxResources.get('email')
80 // this.addBpmnPalette(dir, false);
85 * Specifies if tooltips should be visible. Default is true.
87 Sidebar.prototype.enableTooltips = !mxClient.IS_TOUCH;
90 * Specifies the delay for the tooltip. Default is 16 px.
92 Sidebar.prototype.tooltipBorder = 16;
95 * Specifies the delay for the tooltip. Default is 3 px.
97 Sidebar.prototype.thumbBorder = 3;
100 * Specifies the delay for the tooltip. Default is 300 ms.
102 Sidebar.prototype.tooltipDelay = 300;
105 * Specifies if edges should be used as templates if clicked. Default is true.
107 Sidebar.prototype.installEdges = true;
110 * Specifies the URL of the gear image.
112 Sidebar.prototype.gearImage = STENCIL_PATH + '/clipart/Gear_128x128.png';
115 * Specifies the width of the thumbnails.
117 Sidebar.prototype.thumbWidth = 34;
120 * Specifies the height of the thumbnails.
122 Sidebar.prototype.thumbHeight = 34;
125 * Specifies the padding for the thumbnails. Default is 3.
127 Sidebar.prototype.thumbPadding = 2;
130 * Specifies the size of the sidebar titles.
132 Sidebar.prototype.sidebarTitleSize = 9;
135 * Specifies if titles in the sidebar should be enabled.
137 Sidebar.prototype.sidebarTitles = false;
140 * Specifies if titles in the tooltips should be enabled.
142 Sidebar.prototype.tooltipTitles = false;
145 * Adds all palettes to the sidebar.
147 Sidebar.prototype.showTooltip = function(elt, cells, title, showLabel) {
148 if (this.enableTooltips && this.showTooltips) {
149 if (this.currentElt != elt) {
150 if (this.thread != null) {
151 window.clearTimeout(this.thread);
155 var show = mxUtils.bind(this, function() {
156 // Lazy creation of the DOM nodes and graph instance
157 if (this.tooltip == null) {
158 this.tooltip = document.createElement('div');
159 this.tooltip.className = 'geSidebarTooltip';
160 document.body.appendChild(this.tooltip);
162 this.graph2 = new Graph(this.tooltip, null, null, this.editorUi.editor.graph
164 this.graph2.view.setTranslate(this.tooltipBorder, this.tooltipBorder);
165 this.graph2.resetViewOnRootChange = false;
166 this.graph2.foldingEnabled = false;
167 this.graph2.autoScroll = false;
168 this.graph2.setTooltips(false);
169 this.graph2.setConnectable(false);
170 this.graph2.setEnabled(false);
172 if (!mxClient.IS_SVG) {
173 this.graph2.view.canvas.style.position = 'relative';
176 this.tooltipImage = mxUtils.createImage(IMAGE_PATH + '/tooltip.png');
177 this.tooltipImage.style.position = 'absolute';
178 this.tooltipImage.style.width = '14px';
179 this.tooltipImage.style.height = '27px';
181 document.body.appendChild(this.tooltipImage);
184 this.tooltip.style.display = 'block';
185 this.graph2.labelsVisible = (showLabel == null || showLabel);
186 this.graph2.model.clear();
187 this.graph2.addCells(cells);
189 var bounds = this.graph2.getGraphBounds();
190 var width = bounds.width + 2 * this.tooltipBorder;
191 var height = bounds.height + 2 * this.tooltipBorder;
193 if (mxClient.IS_QUIRKS) {
196 this.tooltip.style.overflow = 'hidden';
198 this.tooltip.style.overflow = 'visible';
201 this.tooltipImage.style.visibility = 'visible';
202 this.tooltip.style.width = width + 'px';
204 // Adds title for entry
205 if (this.tooltipTitles && title != null && title.length > 0) {
206 if (this.tooltipTitle == null) {
207 this.tooltipTitle = document.createElement('div');
208 this.tooltipTitle.style.borderTop = '1px solid gray';
209 this.tooltipTitle.style.textAlign = 'center';
210 this.tooltipTitle.style.width = '100%';
212 // Oversize titles are cut-off currently. Should make tooltip wider later.
213 this.tooltipTitle.style.overflow = 'hidden';
215 if (mxClient.IS_SVG) {
216 this.tooltipTitle.style.paddingTop = '2px';
218 this.tooltipTitle.style.position = 'absolute';
219 this.tooltipTitle.style.paddingTop = '6px';
222 this.tooltip.appendChild(this.tooltipTitle);
224 this.tooltipTitle.innerHTML = '';
227 this.tooltipTitle.style.display = '';
228 mxUtils.write(this.tooltipTitle, title);
230 var dy = this.tooltipTitle.offsetHeight + 10;
233 if (mxClient.IS_SVG) {
234 this.tooltipTitle.style.marginTop = (-dy) + 'px';
237 this.tooltipTitle.style.top = (height - dy) + 'px';
239 } else if (this.tooltipTitle != null && this.tooltipTitle.parentNode !=
241 this.tooltipTitle.style.display = 'none';
244 this.tooltip.style.height = height + 'px';
245 var x0 = -Math.min(0, bounds.x - this.tooltipBorder);
246 var y0 = -Math.min(0, bounds.y - this.tooltipBorder);
248 var left = this.container.clientWidth + this.editorUi.splitSize + 3;
249 var top = Math.max(0, (this.container.offsetTop + elt.offsetTop - this.container
250 .scrollTop - height / 2 + 16));
252 if (mxClient.IS_SVG) {
253 this.graph2.view.canvas.setAttribute('transform', 'translate(' + x0 +
256 this.graph2.view.drawPane.style.left = x0 + 'px';
257 this.graph2.view.drawPane.style.top = y0 + 'px';
260 // Workaround for ignored position CSS style in IE9
261 // (changes to relative without the following line)
262 // Added width of the page-sidebar
263 // left += document.getElementById('page-sidebar').offsetWidth;
264 // Added static height of the page-navbar
267 this.tooltip.style.position = 'absolute';
268 this.tooltip.style.left = left + 'px';
269 this.tooltip.style.top = top + 'px';
270 this.tooltipImage.style.left = (left - 13) + 'px';
271 this.tooltipImage.style.top = (top + height / 2 - 13) + 'px';
274 if (this.tooltip != null && this.tooltip.style.display != 'none') {
277 this.thread = window.setTimeout(show, this.tooltipDelay);
280 this.currentElt = elt;
286 * Hides the current tooltip.
288 Sidebar.prototype.hideTooltip = function() {
289 if (this.thread != null) {
290 window.clearTimeout(this.thread);
294 if (this.tooltip != null) {
295 this.tooltip.style.display = 'none';
296 this.tooltipImage.style.visibility = 'hidden';
297 this.currentElt = null;
302 * Creates and returns the given title element.
304 Sidebar.prototype.createTitle = function(label) {
305 var elt = document.createElement('a');
306 elt.setAttribute('href', 'javascript:void(0);');
307 elt.className = 'geTitle';
308 mxUtils.write(elt, label);
314 * Creates a thumbnail for the given cells.
316 Sidebar.prototype.createThumb = function(cells, width, height, parent, title,
318 this.graph.labelsVisible = (showLabel == null || showLabel);
319 this.graph.view.scaleAndTranslate(1, 0, 0);
320 this.graph.addCells(cells);
321 var bounds = this.graph.getGraphBounds();
322 var corr = this.thumbBorder;
323 var s = Math.min((width - 2) / (bounds.width - bounds.x + corr), (height - 2) /
324 (bounds.height - bounds.y + corr));
325 var x0 = -Math.min(bounds.x, 0);
326 var y0 = -Math.min(bounds.y, 0);
327 this.graph.view.scaleAndTranslate(s, x0, y0);
329 bounds = this.graph.getGraphBounds();
330 var dx = Math.max(0, Math.floor((width - bounds.width - bounds.x) / 2));
331 var dy = Math.max(0, Math.floor((height - bounds.height - bounds.y) / 2));
335 // For supporting HTML labels in IE9 standards mode the container is cloned instead
336 if (this.graph.dialect == mxConstants.DIALECT_SVG && !mxClient.NO_FO) {
337 node = this.graph.view.getCanvas().ownerSVGElement.cloneNode(true);
339 // LATER: Check if deep clone can be used for quirks if container in DOM
341 node = this.graph.container.cloneNode(false);
342 node.innerHTML = this.graph.container.innerHTML;
345 this.graph.getModel().clear();
347 // Catch-all event handling
348 if (mxClient.IS_IE6) {
349 parent.style.backgroundImage = 'url(' + this.editorUi.editor.transparentImage +
354 node.style.position = 'relative';
355 node.style.overflow = 'hidden';
356 node.style.cursor = 'pointer';
357 node.style.left = (dx + dd) + 'px';
358 node.style.top = (dy + dd) + 'px';
359 node.style.width = width + 'px';
360 node.style.height = height + 'px';
361 node.style.visibility = '';
362 node.style.minWidth = '';
363 node.style.minHeight = '';
365 parent.appendChild(node);
367 // Adds title for sidebar entries
368 if (this.sidebarTitles && title != null) {
369 var border = (mxClient.IS_QUIRKS) ? 2 * this.thumbPadding + 2 : 0;
370 parent.style.height = (this.thumbHeight + border + this.sidebarTitleSize + 8) +
373 var div = document.createElement('div');
374 div.style.fontSize = this.sidebarTitleSize + 'px';
375 div.style.textAlign = 'center';
376 div.style.whiteSpace = 'nowrap';
378 if (mxClient.IS_IE) {
379 div.style.height = (this.sidebarTitleSize + 12) + 'px';
382 div.style.paddingTop = '4px';
383 mxUtils.write(div, title);
384 parent.appendChild(div);
389 * Creates and returns a new palette item for the given image.
391 Sidebar.prototype.createItem = function(cells, title, showLabel) {
392 var elt = document.createElement('a');
393 elt.setAttribute('href', 'javascript:void(0);');
394 elt.className = 'geItem';
395 elt.style.overflow = 'hidden';
396 var border = (mxClient.IS_QUIRKS) ? 8 + 2 * this.thumbPadding : 6;
397 elt.style.width = (this.thumbWidth + border) + 'px';
398 elt.style.height = (this.thumbHeight + border) + 'px';
399 elt.style.padding = this.thumbPadding + 'px';
401 // Blocks default click action
402 mxEvent.addListener(elt, 'click', function(evt) {
403 mxEvent.consume(evt);
406 this.createThumb(cells, this.thumbWidth, this.thumbHeight, elt, title,
414 * Creates a drop handler for inserting the given cells.
416 Sidebar.prototype.createDropHandler = function(cells, allowSplit) {
417 return function(graph, evt, target, x, y) {
418 if (graph.isEnabled()) {
419 cells = graph.getImportableCells(cells);
421 if (cells.length > 0) {
422 var validDropTarget = (target != null) ?
423 graph.isValidDropTarget(target, cells, evt) : false;
426 if (target != null && !validDropTarget) {
430 // Splits the target edge or inserts into target group
431 if (allowSplit && graph.isSplitEnabled() && graph.isSplitTarget(target,
433 graph.splitEdge(target, cells, null, x, y);
435 } else if (cells.length > 0) {
436 select = graph.importCells(cells, x, y, target);
439 if (select != null && select.length > 0) {
440 graph.scrollCellToVisible(select[0]);
441 graph.setSelectionCells(select);
449 * Creates and returns a preview element for the given width and height.
451 Sidebar.prototype.createDragPreview = function(width, height) {
452 var elt = document.createElement('div');
453 elt.style.border = '1px dashed black';
454 elt.style.width = width + 'px';
455 elt.style.height = height + 'px';
461 * Creates a drag source for the given element.
463 Sidebar.prototype.createDragSource = function(elt, dropHandler, preview) {
464 var dragSource = mxUtils.makeDraggable(elt, this.editorUi.editor.graph,
466 preview, 0, 0, this.editorUi.editor.graph.autoscroll, true, true);
470 // Allows drop into cell only if target is a valid root
471 dragSource.getDropTarget = function(graph, x, y) {
472 var target = mxDragSource.prototype.getDropTarget.apply(this, arguments);
473 if (!graph.isValidRoot(target)) {
486 * Adds a handler for inserting the cell with a single click.
488 Sidebar.prototype.addClickHandler = function(elt, ds) {
489 var graph = this.editorUi.editor.graph;
492 mxEvent.addGestureListeners(elt, function(evt) {
493 first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
496 var oldMouseUp = ds.mouseUp;
497 ds.mouseUp = function(evt) {
498 if (!mxEvent.isPopupTrigger(evt) && this.currentGraph == null && first !=
500 var tol = graph.tolerance;
502 if (Math.abs(first.x - mxEvent.getClientX(evt)) <= tol &&
503 Math.abs(first.y - mxEvent.getClientY(evt)) <= tol) {
504 var gs = graph.getGridSize();
505 ds.drop(graph, evt, null, gs, gs);
509 oldMouseUp.apply(this, arguments);
516 * Create xml document vertex
518 Sidebar.prototype.createXmlDocument = function(element, label, variables,
520 var doc = mxUtils.createXmlDocument();
521 var node = doc.createElement(element)
522 node.setAttribute('label', label);
524 variables.forEach(function(variable, index) {
525 node.setAttribute(variable, values[index] ? values[index] : '');
533 * Creates a drop handler for inserting the given cells.
535 Sidebar.prototype.createVertexTemplate = function(style, width, height, value,
543 // variables = ['Text'];
547 variables = ['question', 'other'];
548 values = ['', 'false'];
551 variables = ['question', 'Type'];
555 // variables = ['Text', 'Zendesk', 'Summary'];
559 variables = ["Host", "Username", "Password", "To", "Subject", "Body"];
568 var node = this.createXmlDocument(value, title, variables, values);
570 //var cells = [new mxCell((value != null) ? value : '', new mxGeometry(0, 0, width, height), style)];
571 var cells = [new mxCell(node, new mxGeometry(0, 0, width, height), style)];
572 cells[0].vertex = true;
574 return this.createVertexTemplateFromCells(cells, width, height, title,
581 * Creates a drop handler for inserting the given cells.
583 Sidebar.prototype.createVertexTemplateFromCells = function(cells, width, height,
585 var elt = this.createItem(cells, title, showLabel);
586 var ds = this.createDragSource(elt, this.createDropHandler(cells, true), this
587 .createDragPreview(width, height));
588 this.addClickHandler(elt, ds);
590 // Uses guides for vertices only if enabled in graph
591 ds.isGuidesEnabled = mxUtils.bind(this, function() {
592 return this.editorUi.editor.graph.graphHandler.guidesEnabled;
595 // Shows a tooltip with the rendered cell
597 mxEvent.addListener(elt, 'mousemove', mxUtils.bind(this, function(evt) {
598 this.showTooltip(elt, cells, title, showLabel);
606 * Creates a drop handler for inserting the given cells.
608 Sidebar.prototype.createEdgeTemplate = function(style, width, height, value,
610 var cells = [new mxCell((value != null) ? value : '', new mxGeometry(0, 0,
611 width, height), style)];
612 cells[0].geometry.setTerminalPoint(new mxPoint(0, height), true);
613 cells[0].geometry.setTerminalPoint(new mxPoint(width, 0), false);
614 cells[0].geometry.relative = true;
615 cells[0].edge = true;
617 return this.createEdgeTemplateFromCells(cells, width, height, title,
622 * Creates a drop handler for inserting the given cells.
624 Sidebar.prototype.createEdgeTemplateFromCells = function(cells, width, height,
626 var elt = this.createItem(cells, title, showLabel);
627 this.createDragSource(elt, this.createDropHandler(cells, false), this.createDragPreview(
630 // Installs the default edge
631 var graph = this.editorUi.editor.graph;
632 mxEvent.addListener(elt, 'click', mxUtils.bind(this, function(evt) {
633 if (this.installEdges) {
634 graph.setDefaultEdge(cells[0]);
637 // Highlights the entry for 200ms
638 elt.style.backgroundColor = '#ffffff';
640 window.setTimeout(function() {
641 elt.style.backgroundColor = '';
644 mxEvent.consume(evt);
647 // Shows a tooltip with the rendered cell
650 mxEvent.addListener(elt, 'mousemove', mxUtils.bind(this, function(evt) {
651 this.showTooltip(elt, cells, title, showLabel);
659 * Adds the given palette.
661 Sidebar.prototype.addPalette = function(id, title, expanded, onInit) {
662 var elt = this.createTitle(title);
663 this.container.appendChild(elt);
665 var div = document.createElement('div');
666 div.className = 'geSidebar';
672 div.style.display = 'none';
675 this.addFoldingHandler(elt, div, onInit);
677 var outer = document.createElement('div');
678 outer.appendChild(div);
679 this.container.appendChild(outer);
681 // Keeps references to the DOM nodes
683 this.palettes[id] = [elt, outer];
688 * Create the given title element.
690 Sidebar.prototype.addFoldingHandler = function(title, content, funct) {
691 var initialized = false;
693 title.style.backgroundImage = (content.style.display == 'none') ?
694 'url(' + IMAGE_PATH + '/collapsed.gif)' : 'url(' + IMAGE_PATH +
696 title.style.backgroundRepeat = 'no-repeat';
697 title.style.backgroundPosition = '100% 50%';
699 mxEvent.addListener(title, 'click', function(evt) {
700 if (content.style.display == 'none') {
705 title.style.cursor = 'wait';
706 window.setTimeout(function() {
708 title.style.cursor = '';
713 title.style.backgroundImage = 'url(' + IMAGE_PATH + '/expanded.gif)';
714 content.style.display = 'block';
716 title.style.backgroundImage = 'url(' + IMAGE_PATH + '/collapsed.gif)';
717 content.style.display = 'none';
720 mxEvent.consume(evt);
725 * Removes the palette for the given ID.
727 Sidebar.prototype.removePalette = function(id) {
728 var elts = this.palettes[id];
731 this.palettes[id] = null;
733 for (var i = 0; i < elts.length; i++) {
734 this.container.removeChild(elts[i]);
744 * Adds the given image palette.
746 Sidebar.prototype.addImagePalette = function(id, title, prefix, postfix, items,
749 // Expanded Sidebar only entry
750 this.addPalette(id, title, (id === 'entry'), mxUtils.bind(this, function(
752 var showTitles = titles != null;
754 for (var i = 0; i < items.length; i++) {
755 var icon = prefix + items[i] + postfix;
756 content.appendChild(this.createVertexTemplate('image;image=' + icon, 80,
757 80, items[i], (showTitles) ? titles[i] : null, showTitles));
761 // ***********modified***************
762 // Sidebar.prototype.addBpmnPalette = function(dir, expand) {
766 // this.createVertexTemplate(
767 // 'text;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;',
768 // 40, 20, 'Text', 'Text', null),
769 // //this.createVertexTemplate('shape=ext;rounded=1;whiteSpace=wrap;dashed=1;dashPattern=1 4;', 120, 80, 'Event\nSub-Process', 'Event Sub-Process', null),
770 // this.createVertexTemplate('shape=swimlane;whiteSpace=wrap;startSize=60;',
771 // 120, 160, 'Container', 'Container', null),
772 // // this.createVertexTemplate('shape=ellipse;', 120, 160, 'Ellips', 'Ellipse', null)
773 // this.createVertexTemplate(
774 // 'shape=swimlane;html=1;horizontal=0;swimlaneFillColor=white;swimlaneLine=0;fillColor=none;rounded=1;verticalAlign=middle',
775 // 300, 120, 'Lane', 'Lane', null)
779 // this.addPalette('utility', 'Utility ', false, mxUtils.bind(this, function(
781 // //var showTitles = titles != null;
782 // for (var i = 0; i < fns.length; i++) {
783 // content.appendChild(fns[i]);