/* * Control.ContextMenu */ /* global $ map _ */ L.Control.ContextMenu = L.Control.extend({ options: { SEPARATOR: '---------', /* * Enter UNO commands that should appear in the context menu. * Entering a UNO command under `general' would enable it for all types * of documents. If you do not want that, whitelist it in document specific filter. */ whitelist: { /* * UNO commands for menus are not available sometimes. Presence of Menu commands * in following list is just for reference and ease of locating uno command * from context menu structure. */ general: ['Cut', 'Copy', 'Paste', 'PasteSpecialMenu', 'PasteUnformatted', 'NumberingStart', 'ContinueNumbering', 'IncrementLevel', 'DecrementLevel', 'OpenHyperlinkOnCursor', 'CopyHyperlinkLocation', 'RemoveHyperlink', 'AnchorMenu', 'SetAnchorToPage', 'SetAnchorToPara', 'SetAnchorAtChar', 'SetAnchorToChar', 'SetAnchorToFrame', 'WrapMenu', 'WrapOff', 'WrapOn', 'WrapIdeal', 'WrapLeft', 'WrapRight', 'WrapThrough', 'WrapThroughTransparent', 'WrapContour', 'WrapAnchorOnly', 'ArrangeFrameMenu', 'ArrangeMenu', 'BringToFront', 'ObjectForwardOne', 'ObjectBackOne', 'SendToBack', 'RotateMenu', 'RotateLeft', 'RotateRight'], text: ['TableInsertMenu', 'InsertRowsBefore', 'InsertRowsAfter', 'InsertColumnsBefore', 'InsertColumnsAfter', 'TableDeleteMenu', 'DeleteRows', 'DeleteColumns', 'DeleteTable', 'MergeCells', 'SetOptimalColumnWidth', 'SetOptimalRowWidth', 'UpdateCurIndex','RemoveTableOf', 'ReplyComment', 'DeleteComment', 'DeleteAuthor', 'DeleteAllNotes'], spreadsheet: ['MergeCells', 'SplitCells', 'InsertAnnotation', 'EditAnnotation', 'DeleteNote', 'ShowNote', 'HideNote', 'RecalcPivotTable'], presentation: [], drawing: [] } }, onAdd: function (map) { this._prevMousePos = null; map.on('locontextmenu', this._onContextMenu, this); map.on('mousedown', this._onMouseDown, this); map.on('keydown', this._onKeyDown, this); }, _onMouseDown: function(e) { this._prevMousePos = {x: e.originalEvent.pageX, y: e.originalEvent.pageY}; $.contextMenu('destroy', '.leaflet-layer'); }, _onKeyDown: function(e) { if (e.originalEvent.keyCode === 27 /* ESC */) { $.contextMenu('destroy', '.leaflet-layer'); } }, _onContextMenu: function(obj) { if (map._permission !== 'edit') { return; } var contextMenu = this._createContextMenuStructure(obj); $.contextMenu({ selector: '.leaflet-layer', className: 'loleaflet-font', trigger: 'none', build: function() { return { callback: function(key) { map.sendUnoCommand(key); // Give the stolen focus back to map map.focus(); }, items: contextMenu }; } }); $('.leaflet-layer').contextMenu(this._prevMousePos); }, _createContextMenuStructure: function(obj) { var docType = map.getDocType(); var contextMenu = {}; var sepIdx = 1, itemName; var isLastItemText = false; for (var idx in obj.menu) { var item = obj.menu[idx]; if (item.enabled === 'false') { continue; } if (item.type === 'separator') { if (isLastItemText) { contextMenu['sep' + sepIdx++] = this.options.SEPARATOR; } isLastItemText = false; } else if (item.type === 'command') { // Only show whitelisted items // Command name (excluding '.uno:') starts from index = 5 var commandName = item.command.substring(5); if (this.options.whitelist.general.indexOf(commandName) === -1 && !(docType === 'text' && this.options.whitelist.text.indexOf(commandName) !== -1) && !(docType === 'spreadsheet' && this.options.whitelist.spreadsheet.indexOf(commandName) !== -1) && !(docType === 'presentation' && this.options.whitelist.presentation.indexOf(commandName) !== -1) && !(docType === 'drawing' && this.options.whitelist.drawing.indexOf(commandName) !== -1)) { continue; } itemName = item.text.replace('~', ''); itemName = itemName.replace('°', '°'); // bccu#1813 double encoding in cp-5.0 branch only if (commandName === 'DeleteAuthor') { // In some versions of libreoffice, context menu callback returns 'Delete All Comments by $1' // while in some it returns the actual username replacing $1. // Also, the translations in LO core are for 'Delete All Comments by This Author' // Lets use the later for simplicity and to leverage the core translations in online itemName = itemName.replace(itemName.substring('Delete All Comments by '.length), 'This Author'); } contextMenu[item.command] = { name: _(itemName) }; if (item.checktype === 'checkmark') { if (item.checked === 'true') { contextMenu[item.command]['icon'] = 'lo-checkmark'; } } else if (item.checktype === 'radio') { if (item.checked === 'true') { contextMenu[item.command]['icon'] = 'radio'; } } isLastItemText = true; } else if (item.type === 'menu') { itemName = item.text.replace('~', ''); var submenu = this._createContextMenuStructure(item); // ignore submenus with all items disabled if (Object.keys(submenu).length === 0) { continue; } contextMenu[item.command] = { name: _(itemName), items: submenu }; isLastItemText = true; } } // Remove separator, if present, at the end var lastItem = Object.keys(contextMenu)[Object.keys(contextMenu).length - 1]; if (lastItem !== undefined && lastItem.startsWith('sep')) { delete contextMenu[lastItem]; } return contextMenu; } }); L.control.contextMenu = function (options) { return new L.Control.ContextMenu(options); };