| /** |
| * $Id: Toolbar.js,v 1.10 2014/01/16 12:08:57 gaudenz Exp $ |
| * Copyright (c) 2006-2012, JGraph Ltd |
| */ |
| /** |
| * Construcs a new toolbar for the given editor. |
| */ |
| function Toolbar(editorUi, container) |
| { |
| this.editorUi = editorUi; |
| this.container = container; |
| this.init(); |
| |
| // Global handler to hide the current menu |
| mxEvent.addGestureListeners(document, mxUtils.bind(this, function(evt) |
| { |
| this.hideMenu(); |
| })); |
| }; |
| |
| /** |
| * Adds the toolbar elements. |
| */ |
| Toolbar.prototype.init = function() |
| { |
| this.addItems(['undo', 'redo', 'delete', '-', 'actualSize', 'zoomIn', 'zoomOut', '-']); |
| var fontElt = this.addMenu('Helvetica', mxResources.get('fontFamily'), true, 'fontFamily'); |
| fontElt.style.whiteSpace = 'nowrap'; |
| fontElt.style.overflow = 'hidden'; |
| fontElt.style.width = '56px'; |
| this.addSeparator(); |
| var sizeElt = this.addMenu('12', mxResources.get('fontSize'), true, 'fontSize'); |
| sizeElt.style.whiteSpace = 'nowrap'; |
| sizeElt.style.overflow = 'hidden'; |
| sizeElt.style.width = '22px'; |
| |
| this.addItems(['-', 'bold', 'italic', 'underline']); |
| var align = this.addMenuFunction('geSprite-left', mxResources.get('align'), false, mxUtils.bind(this, function(menu) |
| { |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_LEFT], 'geIcon geSprite geSprite-left', null, |
| function() { document.execCommand('justifyleft'); }).setAttribute('title', mxResources.get('left')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_CENTER], 'geIcon geSprite geSprite-center', null, |
| function() { document.execCommand('justifycenter'); }).setAttribute('title', mxResources.get('center')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_RIGHT], 'geIcon geSprite geSprite-right', null, |
| function() { document.execCommand('justifyright'); }).setAttribute('title', mxResources.get('right')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_TOP], 'geIcon geSprite geSprite-top', null).setAttribute('title', mxResources.get('top')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_MIDDLE], 'geIcon geSprite geSprite-middle', null).setAttribute('title', mxResources.get('middle')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_BOTTOM], 'geIcon geSprite geSprite-bottom', null).setAttribute('title', mxResources.get('bottom')); |
| })); |
| this.addItems(['fontColor', '-']); |
| var line = this.addMenuFunction('geSprite-straight', mxResources.get('line'), false, mxUtils.bind(this, function(menu) |
| { |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE], [null], 'geIcon geSprite geSprite-straight', null).setAttribute('title', mxResources.get('straight')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE], ['entityRelationEdgeStyle'], 'geIcon geSprite geSprite-entity', null).setAttribute('title', mxResources.get('entityRelation')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW], ['elbowEdgeStyle', 'horizontal'], 'geIcon geSprite geSprite-helbow', null).setAttribute('title', mxResources.get('horizontal')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW], ['elbowEdgeStyle', 'vertical'], 'geIcon geSprite geSprite-velbow', null).setAttribute('title', mxResources.get('vertical')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE], ['segmentEdgeStyle'], 'geIcon geSprite geSprite-segment', null).setAttribute('title', mxResources.get('manual')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_EDGE], ['orthogonalEdgeStyle'], 'geIcon geSprite geSprite-orthogonal', null).setAttribute('title', mxResources.get('automatic')); |
| })); |
| var linestart = this.addMenuFunction('geSprite-startclassic', mxResources.get('lineend'), false, mxUtils.bind(this, function(menu) |
| { |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null).setAttribute('title', mxResources.get('none')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-startclassic', null).setAttribute('title', mxResources.get('classic')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OPEN, 1], 'geIcon geSprite geSprite-startopen', null).setAttribute('title', mxResources.get('openArrow')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-startblock', null).setAttribute('title', mxResources.get('block')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-startoval', null).setAttribute('title', mxResources.get('oval')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-startdiamond', null).setAttribute('title', mxResources.get('diamond')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-startthindiamond', null).setAttribute('title', mxResources.get('diamondThin')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-startclassictrans', null).setAttribute('title', mxResources.get('classic')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-startblocktrans', null).setAttribute('title', mxResources.get('block')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-startovaltrans', null).setAttribute('title', mxResources.get('oval')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-startdiamondtrans', null).setAttribute('title', mxResources.get('diamond')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-startthindiamondtrans', null).setAttribute('title', mxResources.get('diamondThin')); |
| })); |
| var lineend = this.addMenuFunction('geSprite-endclassic', mxResources.get('lineend'), false, mxUtils.bind(this, function(menu) |
| { |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null).setAttribute('title', mxResources.get('none')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-endclassic', null).setAttribute('title', mxResources.get('classic')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OPEN, 1], 'geIcon geSprite geSprite-endopen', null).setAttribute('title', mxResources.get('openArrow')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-endblock', null).setAttribute('title', mxResources.get('block')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-endoval', null).setAttribute('title', mxResources.get('oval')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-enddiamond', null).setAttribute('title', mxResources.get('diamond')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-endthindiamond', null).setAttribute('title', mxResources.get('diamondThin')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-endclassictrans', null).setAttribute('title', mxResources.get('classic')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-endblocktrans', null).setAttribute('title', mxResources.get('block')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-endovaltrans', null).setAttribute('title', mxResources.get('oval')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-enddiamondtrans', null).setAttribute('title', mxResources.get('diamond')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-endthindiamondtrans', null).setAttribute('title', mxResources.get('diamondThin')); |
| })); |
| this.addItems(['-', 'strokeColor', 'image', 'fillColor']); |
| this.addItem('geSprite-gradientcolor', 'gradientColor').setAttribute('title', mxResources.get('gradient')); |
| this.addItems(['shadow']); |
| |
| var graph = this.editorUi.editor.graph; |
| |
| // Update font size and font family labels |
| var update = mxUtils.bind(this, function() |
| { |
| var ff = 'Helvetica'; |
| var fs = '12'; |
| var state = graph.getView().getState(graph.getSelectionCell()); |
| |
| if (state != null) |
| { |
| ff = state.style[mxConstants.STYLE_FONTFAMILY] || ff; |
| fs = state.style[mxConstants.STYLE_FONTSIZE] || fs; |
| |
| if (ff.length > 10) |
| { |
| ff = ff.substring(0, 8) + '...'; |
| } |
| |
| fontElt.innerHTML = ff; |
| sizeElt.innerHTML = fs; |
| } |
| }); |
| |
| graph.getSelectionModel().addListener(mxEvent.CHANGE, update); |
| graph.getModel().addListener(mxEvent.CHANGE, update); |
| |
| // Updates button states |
| this.addEdgeSelectionHandler([line, linestart, lineend]); |
| this.addSelectionHandler([align]); |
| }; |
| |
| /** |
| * Hides the current menu. |
| */ |
| Toolbar.prototype.createTextToolbar = function() |
| { |
| var graph = this.editorUi.editor.graph; |
| this.addItems(['undo', 'redo', '-']); |
| |
| var fontElt = this.addMenu(mxResources.get('style'), mxResources.get('style'), true, 'formatBlock'); |
| fontElt.style.whiteSpace = 'nowrap'; |
| fontElt.style.overflow = 'hidden'; |
| |
| var fontElt = this.addMenu('Helvetica', mxResources.get('fontFamily'), true, 'fontFamily'); |
| fontElt.style.whiteSpace = 'nowrap'; |
| fontElt.style.overflow = 'hidden'; |
| fontElt.style.width = '56px'; |
| |
| this.addSeparator(); |
| |
| var sizeElt = this.addMenu('12', mxResources.get('fontSize'), true, 'fontSize'); |
| sizeElt.style.whiteSpace = 'nowrap'; |
| sizeElt.style.overflow = 'hidden'; |
| sizeElt.style.width = '22px'; |
| |
| this.addItems(['-', 'bold', 'italic', 'underline']); |
| |
| // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems |
| // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text). |
| this.addMenuFunction('geSprite-left', mxResources.get('align'), false, mxUtils.bind(this, function(menu) |
| { |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_LEFT], 'geIcon geSprite geSprite-left', null, |
| function() { document.execCommand('justifyleft'); }).setAttribute('title', mxResources.get('left')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_CENTER], 'geIcon geSprite geSprite-center', null, |
| function() { document.execCommand('justifycenter'); }).setAttribute('title', mxResources.get('center')); |
| this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_RIGHT], 'geIcon geSprite geSprite-right', null, |
| function() { document.execCommand('justifyright'); }).setAttribute('title', mxResources.get('right')); |
| })); |
| |
| this.addMenuFunction('geSprite-fontcolor', mxResources.get('more') + '...', false, mxUtils.bind(this, function(menu) |
| { |
| // KNOWN: IE+FF don't return keyboard focus after color dialog (calling focus doesn't help) |
| elt = menu.addItem('', null, this.editorUi.actions.get('fontColor').funct, null, 'geIcon geSprite geSprite-fontcolor'); |
| elt.setAttribute('title', mxResources.get('fontColor')); |
| |
| elt = menu.addItem('', null, this.editorUi.actions.get('backgroundColor').funct, null, 'geIcon geSprite geSprite-fontbackground'); |
| elt.setAttribute('title', mxResources.get('backgroundColor')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| document.execCommand('superscript'); |
| }), null, 'geIcon geSprite geSprite-superscript'); |
| elt.setAttribute('title', mxResources.get('superscript')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| document.execCommand('subscript'); |
| }), null, 'geIcon geSprite geSprite-subscript'); |
| elt.setAttribute('title', mxResources.get('subscript')); |
| })); |
| |
| this.addSeparator(); |
| |
| this.addButton('geIcon geSprite geSprite-orderedlist', mxResources.get('numberedList'), function() |
| { |
| document.execCommand('insertorderedlist'); |
| }); |
| |
| this.addButton('geIcon geSprite geSprite-unorderedlist', mxResources.get('bulletedList'), function() |
| { |
| document.execCommand('insertunorderedlist'); |
| }); |
| |
| this.addButton('geIcon geSprite geSprite-outdent', mxResources.get('decreaseIndent'), function() |
| { |
| document.execCommand('outdent'); |
| }); |
| |
| this.addButton('geIcon geSprite geSprite-indent', mxResources.get('increaseIndent'), function() |
| { |
| document.execCommand('indent'); |
| }); |
| |
| this.addSeparator(); |
| |
| function getSelectedElement(name) |
| { |
| var node = null; |
| |
| if (window.getSelection) |
| { |
| var sel = window.getSelection(); |
| |
| if (sel.getRangeAt && sel.rangeCount) |
| { |
| var range = sel.getRangeAt(0); |
| node = range.commonAncestorContainer; |
| } |
| } |
| else if (document.selection) |
| { |
| node = document.selection.createRange().parentElement(); |
| } |
| |
| while (node != null) |
| { |
| if (node.nodeName == name) |
| { |
| return node; |
| } |
| |
| node = node.parentNode; |
| } |
| |
| return node; |
| }; |
| |
| function getParentElement(node, name) |
| { |
| var result = node; |
| |
| while (result != null) |
| { |
| if (result.nodeName == name) |
| { |
| break; |
| } |
| |
| result = result.parentNode; |
| } |
| |
| return result; |
| }; |
| |
| function getSelectedCell() |
| { |
| return getSelectedElement('TD'); |
| }; |
| |
| function getSelectedRow() |
| { |
| return getSelectedElement('TR'); |
| }; |
| |
| function getParentTable(node) |
| { |
| return getParentElement(node, 'TABLE'); |
| }; |
| |
| function selectNode(node) |
| { |
| var sel = null; |
| |
| // IE9 and non-IE |
| if (window.getSelection) |
| { |
| sel = window.getSelection(); |
| |
| if (sel.getRangeAt && sel.rangeCount) |
| { |
| var range = document.createRange(); |
| range.selectNode(node); |
| sel.removeAllRanges(); |
| sel.addRange(range); |
| } |
| } |
| // IE < 9 |
| else if ((sel = document.selection) && sel.type != 'Control') |
| { |
| var originalRange = sel.createRange(); |
| originalRange.collapse(true); |
| range = sel.createRange(); |
| range.setEndPoint('StartToStart', originalRange); |
| range.select(); |
| } |
| }; |
| |
| function pasteHtmlAtCaret(html) |
| { |
| var sel, range; |
| |
| // IE9 and non-IE |
| if (window.getSelection) |
| { |
| sel = window.getSelection(); |
| |
| if (sel.getRangeAt && sel.rangeCount) |
| { |
| range = sel.getRangeAt(0); |
| range.deleteContents(); |
| |
| // Range.createContextualFragment() would be useful here but is |
| // only relatively recently standardized and is not supported in |
| // some browsers (IE9, for one) |
| var el = document.createElement("div"); |
| el.innerHTML = html; |
| var frag = document.createDocumentFragment(), node; |
| |
| while ((node = el.firstChild)) |
| { |
| lastNode = frag.appendChild(node); |
| } |
| |
| range.insertNode(frag); |
| } |
| } |
| // IE < 9 |
| else if ((sel = document.selection) && sel.type != "Control") |
| { |
| // FIXME: Does not work if selection is empty |
| sel.createRange().pasteHTML(html); |
| } |
| }; |
| |
| // TODO: Disable toolbar button for HTML code view |
| this.addButton('geIcon geSprite geSprite-link', mxResources.get('insertLink'), mxUtils.bind(this, function() |
| { |
| if (graph.cellEditor.isContentEditing()) |
| { |
| var link = getSelectedElement('A'); |
| var oldValue = ''; |
| |
| if (link != null) |
| { |
| oldValue = link.getAttribute('href'); |
| } |
| |
| var selState = graph.cellEditor.saveSelection(); |
| |
| var dlg = new TextareaDialog(this.editorUi, mxResources.get('enterValue') + ' (' + mxResources.get('url') + '):', oldValue, mxUtils.bind(this, function(value) |
| { |
| graph.cellEditor.restoreSelection(selState); |
| |
| // To find the new link, we create a list of all existing links first |
| // LATER: Refactor for reuse with code for finding inserted image below |
| var tmp = graph.cellEditor.text2.getElementsByTagName('a'); |
| var oldLinks = []; |
| |
| for (var i = 0; i < tmp.length; i++) |
| { |
| oldLinks.push(tmp[i]); |
| } |
| |
| if (value != null && value.length > 0) |
| { |
| document.execCommand('createlink', false, mxUtils.trim(value)); |
| |
| // Adds target="_blank" for the new link |
| var newLinks = graph.cellEditor.text2.getElementsByTagName('a'); |
| |
| if (newLinks.length == oldLinks.length + 1) |
| { |
| // Inverse order in favor of appended links |
| for (var i = newLinks.length - 1; i >= 0; i--) |
| { |
| if (i == 0 || newLinks[i] != oldLinks[i - 1]) |
| { |
| newLinks[i].setAttribute('target', '_blank'); |
| break; |
| } |
| } |
| } |
| } |
| }), mxUtils.bind(this, function() |
| { |
| graph.cellEditor.restoreSelection(selState); |
| })); |
| |
| this.editorUi.showDialog(dlg.container, 320, 200, true, false); |
| dlg.init(); |
| } |
| })); |
| |
| // TODO: Disable toolbar button for HTML code view |
| this.addButton('geIcon geSprite geSprite-image', mxResources.get('insertImage'), mxUtils.bind(this, function() |
| { |
| if (graph.cellEditor.isContentEditing()) |
| { |
| var selState = graph.cellEditor.saveSelection(); |
| |
| this.showInsertImage(mxUtils.bind(this, function(value, w, h) |
| { |
| graph.cellEditor.restoreSelection(selState); |
| |
| // To find the new image, we create a list of all existing links first |
| var tmp = graph.cellEditor.text2.getElementsByTagName('img'); |
| var oldImages = []; |
| |
| for (var i = 0; i < tmp.length; i++) |
| { |
| oldImages.push(tmp[i]); |
| } |
| |
| if (value != null && value.length > 0) |
| { |
| document.execCommand('insertimage', false, value); |
| |
| // Adds target="_blank" for the new link |
| var newImages = graph.cellEditor.text2.getElementsByTagName('img'); |
| |
| if (newImages.length == oldImages.length + 1) |
| { |
| // Inverse order in favor of appended images |
| for (var i = newImages.length - 1; i >= 0; i--) |
| { |
| if (i == 0 || newImages[i] != oldImages[i - 1]) |
| { |
| // LATER: Add dialog for image size |
| newImages[i].style.width = w + 'px'; |
| newImages[i].style.height = h + 'px'; |
| |
| break; |
| } |
| } |
| } |
| } |
| })); |
| } |
| }), mxUtils.bind(this, function() |
| { |
| graph.cellEditor.restoreSelection(selState); |
| })); |
| |
| this.addButton('geIcon geSprite geSprite-horizontalrule', mxResources.get('insertHorizontalRule'), function() |
| { |
| document.execCommand('inserthorizontalrule'); |
| }); |
| |
| // KNOWN: All table stuff does not work with undo/redo |
| // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems |
| // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text). |
| var elt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu) |
| { |
| var cell = getSelectedCell(); |
| var row = getSelectedRow(); |
| |
| if (row == null) |
| { |
| function createTable(rows, cols) |
| { |
| var html = ['<table>']; |
| |
| for (var i = 0; i < rows; i++) |
| { |
| html.push('<tr>'); |
| |
| for (var j = 0; j < cols; j++) |
| { |
| html.push('<td><br></td>'); |
| } |
| |
| html.push('</tr>'); |
| } |
| |
| html.push('</table>'); |
| |
| return html.join(''); |
| }; |
| |
| // Show table size dialog |
| var elt2 = menu.addItem('', null, mxUtils.bind(this, function(evt) |
| { |
| var td = getParentElement(mxEvent.getSource(evt), 'TD'); |
| |
| if (td != null) |
| { |
| var row2 = getParentElement(td, 'TR'); |
| |
| // To find the new link, we create a list of all existing links first |
| // LATER: Refactor for reuse with code for finding inserted image below |
| var tmp = graph.cellEditor.text2.getElementsByTagName('table'); |
| var oldTables = []; |
| |
| for (var i = 0; i < tmp.length; i++) |
| { |
| oldTables.push(tmp[i]); |
| } |
| |
| // Finding the new table will work with insertHTML, but IE does not support that |
| pasteHtmlAtCaret(createTable(row2.sectionRowIndex + 1, td.cellIndex + 1)); |
| |
| // Moves cursor to first table cell |
| var newTables = graph.cellEditor.text2.getElementsByTagName('table'); |
| |
| if (newTables.length == oldTables.length + 1) |
| { |
| // Inverse order in favor of appended tables |
| for (var i = newTables.length - 1; i >= 0; i--) |
| { |
| if (i == 0 || newTables[i] != oldTables[i - 1]) |
| { |
| selectNode(newTables[i].rows[0].cells[0]); |
| break; |
| } |
| } |
| } |
| } |
| })); |
| |
| // Quirks mode does not add cell padding if cell is empty, needs good old spacer solution |
| var quirksCellHtml = '<img src="' + mxClient.imageBasePath + '/transparent.gif' + '" width="16" height="16"/>'; |
| |
| function createPicker(rows, cols) |
| { |
| var table2 = document.createElement('table'); |
| table2.setAttribute('border', '1'); |
| table2.style.borderCollapse = 'collapse'; |
| |
| if (!mxClient.IS_QUIRKS) |
| { |
| table2.setAttribute('cellPadding', '8'); |
| } |
| |
| for (var i = 0; i < rows; i++) |
| { |
| var row = table2.insertRow(i); |
| |
| for (var j = 0; j < cols; j++) |
| { |
| var cell = row.insertCell(-1); |
| |
| if (mxClient.IS_QUIRKS) |
| { |
| cell.innerHTML = quirksCellHtml; |
| } |
| } |
| } |
| |
| return table2; |
| }; |
| |
| function extendPicker(picker, rows, cols) |
| { |
| for (var i = picker.rows.length; i < rows; i++) |
| { |
| var row = picker.insertRow(i); |
| |
| for (var j = 0; j < picker.rows[0].cells.length; j++) |
| { |
| var cell = row.insertCell(-1); |
| |
| if (mxClient.IS_QUIRKS) |
| { |
| cell.innerHTML = quirksCellHtml; |
| } |
| } |
| } |
| |
| for (var i = 0; i < picker.rows.length; i++) |
| { |
| var row = picker.rows[i]; |
| |
| for (var j = row.cells.length; j < cols; j++) |
| { |
| var cell = row.insertCell(-1); |
| |
| if (mxClient.IS_QUIRKS) |
| { |
| cell.innerHTML = quirksCellHtml; |
| } |
| } |
| } |
| }; |
| |
| elt2.firstChild.innerHTML = ''; |
| var picker = createPicker(5, 5); |
| elt2.firstChild.appendChild(picker); |
| |
| var label = document.createElement('div'); |
| label.style.padding = '4px'; |
| label.style.fontSize = '12px'; |
| label.innerHTML = '1x1'; |
| elt2.firstChild.appendChild(label); |
| |
| mxEvent.addListener(picker, 'mouseover', function(e) |
| { |
| var td = getParentElement(mxEvent.getSource(e), 'TD'); |
| |
| if (td != null) |
| { |
| var row2 = getParentElement(td, 'TR'); |
| extendPicker(picker, Math.min(20, row2.sectionRowIndex + 2), Math.min(20, td.cellIndex + 2)); |
| label.innerHTML = (td.cellIndex + 1) + 'x' + (row2.sectionRowIndex + 1); |
| |
| for (var i = 0; i < picker.rows.length; i++) |
| { |
| var r = picker.rows[i]; |
| |
| for (var j = 0; j < r.cells.length; j++) |
| { |
| var cell = r.cells[j]; |
| |
| if (i <= row2.sectionRowIndex && j <= td.cellIndex) |
| { |
| cell.style.backgroundColor = 'blue'; |
| } |
| else |
| { |
| cell.style.backgroundColor = 'white'; |
| } |
| } |
| } |
| |
| mxEvent.consume(e); |
| } |
| }); |
| } |
| else |
| { |
| var table = getParentTable(row); |
| |
| function insertRow(index) |
| { |
| var tblBodyObj = table.tBodies[0]; |
| var colCount = (tblBodyObj.rows.length > 0) ? tblBodyObj.rows[0].cells.length : 1; |
| var newRow = tblBodyObj.insertRow(index); |
| |
| for (var i = 0; i < colCount; i++) |
| { |
| var newCell = newRow.insertCell(-1); |
| mxUtils.br(newCell); |
| } |
| |
| selectNode(newRow.cells[0]); |
| } |
| |
| function deleteColumn(index) |
| { |
| var tblBodyObj = table.tBodies[0]; |
| var allRows = tblBodyObj.rows; |
| |
| for (var i = 0; i < allRows.length; i++) |
| { |
| if (allRows[i].cells.length > index) |
| { |
| allRows[i].deleteCell(index); |
| } |
| } |
| }; |
| |
| function insertColumn(index) |
| { |
| var tblHeadObj = table.tHead; |
| |
| if (tblHeadObj != null) |
| { |
| // TODO: use colIndex |
| for (var h = 0; h < tblHeadObj.rows.length; h++) |
| { |
| var newTH = document.createElement('th'); |
| tblHeadObj.rows[h].appendChild(newTH); |
| mxUtils.br(newTH); |
| } |
| } |
| |
| var tblBodyObj = table.tBodies[0]; |
| |
| for (var i = 0; i < tblBodyObj.rows.length; i++) |
| { |
| var newCell = tblBodyObj.rows[i].insertCell(index); |
| mxUtils.br(newCell); |
| } |
| |
| selectNode(tblBodyObj.rows[0].cells[(index >= 0) ? index : tblBodyObj.rows[0].cells.length - 1]); |
| }; |
| |
| var elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| insertColumn((cell != null) ? cell.cellIndex : 0); |
| }), null, 'geIcon geSprite geSprite-insertcolumnbefore'); |
| elt.setAttribute('title', mxResources.get('insertColumnBefore')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| insertColumn((cell != null) ? cell.cellIndex + 1 : -1); |
| }), null, 'geIcon geSprite geSprite-insertcolumnafter'); |
| elt.setAttribute('title', mxResources.get('insertColumnAfter')); |
| |
| elt = menu.addItem('Delete column', null, mxUtils.bind(this, function() |
| { |
| if (cell != null) |
| { |
| deleteColumn(cell.cellIndex); |
| } |
| }), null, 'geIcon geSprite geSprite-deletecolumn'); |
| elt.setAttribute('title', mxResources.get('deleteColumn')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| insertRow(row.sectionRowIndex); |
| }), null, 'geIcon geSprite geSprite-insertrowbefore'); |
| elt.setAttribute('title', mxResources.get('insertRowBefore')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| insertRow(row.sectionRowIndex + 1); |
| }), null, 'geIcon geSprite geSprite-insertrowafter'); |
| elt.setAttribute('title', mxResources.get('insertRowAfter')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| var tblBodyObj = table.tBodies[0]; |
| tblBodyObj.deleteRow(row.sectionRowIndex); |
| }), null, 'geIcon geSprite geSprite-deleterow'); |
| elt.setAttribute('title', mxResources.get('deleteRow')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| var colorValue = table.style.borderColor.replace( |
| /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, |
| function($0, $1, $2, $3) { |
| return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); |
| }); |
| |
| var selState = graph.cellEditor.saveSelection(); |
| |
| var dlg = new ColorDialog(this.editorUi, colorValue || 'none', mxUtils.bind(this, function(color) |
| { |
| graph.cellEditor.restoreSelection(selState); |
| |
| if (color == null || color == mxConstants.NONE) |
| { |
| table.removeAttribute('border'); |
| table.style.border = ''; |
| table.style.borderCollapse = ''; |
| } |
| else |
| { |
| table.setAttribute('border', '1'); |
| table.style.border = '1px solid ' + color; |
| table.style.borderCollapse = 'collapse'; |
| } |
| }), function() |
| { |
| graph.cellEditor.restoreSelection(selState); |
| }); |
| this.editorUi.showDialog(dlg.container, 220, 400, true, false); |
| dlg.init(); |
| }), null, 'geIcon geSprite geSprite-strokecolor'); |
| elt.setAttribute('title', mxResources.get('borderColor')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| // Converts rgb(r,g,b) values |
| var colorValue = table.style.backgroundColor.replace( |
| /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, |
| function($0, $1, $2, $3) { |
| return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); |
| }); |
| |
| var selState = graph.cellEditor.saveSelection(); |
| |
| var dlg = new ColorDialog(this.editorUi, colorValue || 'none', mxUtils.bind(this, function(color) |
| { |
| graph.cellEditor.restoreSelection(selState); |
| |
| if (color == null || color == mxConstants.NONE) |
| { |
| table.style.backgroundColor = ''; |
| } |
| else |
| { |
| table.style.backgroundColor = color; |
| } |
| }), function() |
| { |
| graph.cellEditor.restoreSelection(selState); |
| }); |
| this.editorUi.showDialog(dlg.container, 220, 400, true, false); |
| dlg.init(); |
| }), null, 'geIcon geSprite geSprite-fillcolor'); |
| elt.setAttribute('title', mxResources.get('backgroundColor')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| var value = table.getAttribute('cellPadding') || 0; |
| |
| var dlg = new FilenameDialog(this.editorUi, value, mxResources.get('apply'), mxUtils.bind(this, function(newValue) |
| { |
| if (newValue != null && newValue.length > 0) |
| { |
| table.setAttribute('cellPadding', newValue); |
| } |
| else |
| { |
| table.removeAttribute('cellPadding'); |
| } |
| }), mxResources.get('spacing')); |
| this.editorUi.showDialog(dlg.container, 300, 80, true, true); |
| dlg.init(); |
| }), null, 'geIcon geSprite geSprite-fit'); |
| elt.setAttribute('title', mxResources.get('spacing')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| table.setAttribute('align', 'left'); |
| }), null, 'geIcon geSprite geSprite-left'); |
| elt.setAttribute('title', mxResources.get('left')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| table.setAttribute('align', 'center'); |
| }), null, 'geIcon geSprite geSprite-center'); |
| elt.setAttribute('title', mxResources.get('center')); |
| |
| elt = menu.addItem('', null, mxUtils.bind(this, function() |
| { |
| table.setAttribute('align', 'right'); |
| }), null, 'geIcon geSprite geSprite-right'); |
| elt.setAttribute('title', mxResources.get('right')); |
| |
| } |
| })); |
| elt.style.width = '16px'; |
| elt.style.paddingTop = '0px'; |
| elt.style.paddingLeft = '4px'; |
| |
| this.addSeparator(); |
| |
| this.addButton('geIcon geSprite geSprite-removeformat', mxResources.get('removeFormat'), function() |
| { |
| document.execCommand('removeformat'); |
| }); |
| |
| this.addButton('geIcon geSprite geSprite-code', mxResources.get('html'), function() |
| { |
| graph.cellEditor.toggleViewMode(); |
| }); |
| }; |
| |
| /** |
| * Hides the current menu. |
| */ |
| Toolbar.prototype.showInsertImage = function(applyFn) |
| { |
| var value = mxUtils.prompt(mxResources.get('enterValue') + ' (' + mxResources.get('url') + ')'); |
| |
| if (value != null && value.length > 0) |
| { |
| var img = new Image(); |
| |
| img.onload = function() |
| { |
| applyFn(value, img.width, img.height); |
| }; |
| img.onerror = function() |
| { |
| mxUtils.alert(mxResources.get('fileNotFound')); |
| }; |
| |
| img.src = value; |
| } |
| }; |
| |
| /** |
| * Hides the current menu. |
| */ |
| Toolbar.prototype.hideMenu = function() |
| { |
| if (this.currentMenu != null) |
| { |
| this.currentMenu.hideMenu(); |
| this.currentMenu.destroy(); |
| this.currentMenu = null; |
| } |
| }; |
| |
| /** |
| * Adds a label to the toolbar. |
| */ |
| Toolbar.prototype.addMenu = function(label, tooltip, showLabels, name) |
| { |
| var menu = this.editorUi.menus.get(name); |
| var elt = this.addMenuFunction(label, tooltip, showLabels, menu.funct); |
| |
| menu.addListener('stateChanged', function() |
| { |
| elt.setEnabled(menu.enabled); |
| }); |
| |
| return elt; |
| }; |
| |
| /** |
| * Adds a label to the toolbar. |
| */ |
| Toolbar.prototype.addMenuFunction = function(label, tooltip, showLabels, funct) |
| { |
| var elt = (showLabels) ? this.createLabel(label) : this.createButton(label); |
| this.initElement(elt, tooltip); |
| this.addMenuHandler(elt, showLabels, funct); |
| this.container.appendChild(elt); |
| |
| return elt; |
| }; |
| |
| /** |
| * Adds a separator to the separator. |
| */ |
| Toolbar.prototype.addSeparator = function() |
| { |
| var elt = document.createElement('div'); |
| elt.className = 'geSeparator'; |
| this.container.appendChild(elt); |
| |
| return elt; |
| }; |
| |
| /** |
| * Adds given action item |
| */ |
| Toolbar.prototype.addItems = function(keys) |
| { |
| for (var i = 0; i < keys.length; i++) |
| { |
| var key = keys[i]; |
| |
| if (key == '-') |
| { |
| this.addSeparator(); |
| } |
| else |
| { |
| this.addItem('geSprite-' + key.toLowerCase(), key); |
| } |
| } |
| }; |
| |
| /** |
| * Adds given action item |
| */ |
| Toolbar.prototype.addItem = function(sprite, key) |
| { |
| var action = this.editorUi.actions.get(key); |
| var elt = null; |
| |
| if (action != null) |
| { |
| elt = this.addButton(sprite, action.label, action.funct); |
| elt.setEnabled(action.enabled); |
| |
| action.addListener('stateChanged', function() |
| { |
| elt.setEnabled(action.enabled); |
| }); |
| } |
| |
| return elt; |
| }; |
| |
| /** |
| * Adds a button to the toolbar. |
| */ |
| Toolbar.prototype.addButton = function(classname, tooltip, funct) |
| { |
| var elt = this.createButton(classname); |
| |
| this.initElement(elt, tooltip); |
| this.addClickHandler(elt, funct); |
| this.container.appendChild(elt); |
| |
| return elt; |
| }; |
| |
| /** |
| * Updates the states of the given toolbar items based on the selection. |
| */ |
| Toolbar.prototype.addSelectionHandler = function(items) |
| { |
| var graph = this.editorUi.editor.graph; |
| |
| var selectionListener = function() |
| { |
| var selected = !graph.isSelectionEmpty(); |
| |
| for (var i = 0; i < items.length; i++) |
| { |
| items[i].setEnabled(selected); |
| } |
| }; |
| |
| graph.getSelectionModel().addListener(mxEvent.CHANGE, selectionListener); |
| selectionListener(); |
| }; |
| |
| /** |
| * Updates the states of the given toolbar items based on the selection. |
| */ |
| Toolbar.prototype.addEdgeSelectionHandler = function(items) |
| { |
| var graph = this.editorUi.editor.graph; |
| |
| var selectionListener = function() |
| { |
| var edgeSelected = false; |
| |
| if (!graph.isSelectionEmpty()) |
| { |
| var cells = graph.getSelectionCells(); |
| |
| for (var i = 0; i < cells.length; i++) |
| { |
| if (graph.getModel().isEdge(cells[i])) |
| { |
| edgeSelected = true; |
| break; |
| } |
| } |
| } |
| |
| for (var i = 0; i < items.length; i++) |
| { |
| items[i].setEnabled(edgeSelected); |
| } |
| }; |
| |
| graph.getSelectionModel().addListener(mxEvent.CHANGE, selectionListener); |
| selectionListener(); |
| }; |
| |
| /** |
| * Initializes the given toolbar element. |
| */ |
| Toolbar.prototype.initElement = function(elt, tooltip) |
| { |
| // Adds tooltip |
| if (tooltip != null) |
| { |
| elt.setAttribute('title', tooltip); |
| } |
| |
| this.addEnabledState(elt); |
| }; |
| |
| /** |
| * Adds enabled state with setter to DOM node (avoids JS wrapper). |
| */ |
| Toolbar.prototype.addEnabledState = function(elt) |
| { |
| var classname = elt.className; |
| |
| elt.setEnabled = function(value) |
| { |
| elt.enabled = value; |
| |
| if (value) |
| { |
| elt.className = classname; |
| } |
| else |
| { |
| elt.className = classname + ' mxDisabled'; |
| } |
| }; |
| |
| elt.setEnabled(true); |
| }; |
| |
| /** |
| * Adds enabled state with setter to DOM node (avoids JS wrapper). |
| */ |
| Toolbar.prototype.addClickHandler = function(elt, funct) |
| { |
| if (funct != null) |
| { |
| mxEvent.addListener(elt, 'click', function(evt) |
| { |
| if (elt.enabled) |
| { |
| funct(evt); |
| } |
| |
| mxEvent.consume(evt); |
| }); |
| |
| if (document.documentMode != null && document.documentMode >= 9) |
| { |
| // Prevents focus |
| mxEvent.addListener(elt, 'mousedown', function(evt) |
| { |
| evt.preventDefault(); |
| }); |
| } |
| } |
| }; |
| |
| /** |
| * Creates and returns a new button. |
| */ |
| Toolbar.prototype.createButton = function(classname) |
| { |
| var elt = document.createElement('a'); |
| elt.setAttribute('href', 'javascript:void(0);'); |
| elt.className = 'geButton'; |
| |
| var inner = document.createElement('div'); |
| |
| if (classname != null) |
| { |
| inner.className = 'geSprite ' + classname; |
| } |
| |
| elt.appendChild(inner); |
| |
| return elt; |
| }; |
| |
| /** |
| * Creates and returns a new button. |
| */ |
| Toolbar.prototype.createLabel = function(label, tooltip) |
| { |
| var elt = document.createElement('a'); |
| elt.setAttribute('href', 'javascript:void(0);'); |
| elt.className = 'geLabel'; |
| mxUtils.write(elt, label); |
| |
| return elt; |
| }; |
| |
| /** |
| * Adds a handler for showing a menu in the given element. |
| */ |
| Toolbar.prototype.addMenuHandler = function(elt, showLabels, funct, showAll) |
| { |
| if (funct != null) |
| { |
| var graph = this.editorUi.editor.graph; |
| var menu = null; |
| |
| mxEvent.addListener(elt, 'click', mxUtils.bind(this, function(evt) |
| { |
| if (elt.enabled == null || elt.enabled) |
| { |
| graph.popupMenuHandler.hideMenu(); |
| menu = new mxPopupMenu(funct); |
| menu.div.className += ' geToolbarMenu'; |
| menu.showDisabled = showAll; |
| menu.labels = showLabels; |
| menu.autoExpand = true; |
| |
| var offset = mxUtils.getOffset(elt); |
| menu.popup(offset.x, offset.y + elt.offsetHeight, null, evt); |
| this.currentMenu = menu; |
| } |
| |
| mxEvent.consume(evt); |
| })); |
| |
| if (document.documentMode != null && document.documentMode >= 9) |
| { |
| // Prevents focus |
| mxEvent.addListener(elt, 'mousedown', function(evt) |
| { |
| evt.preventDefault(); |
| }); |
| } |
| } |
| }; |