diff --git a/src/atom.coffee b/src/atom.coffee index 422949da5..cab272df9 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -10,12 +10,14 @@ dialog = remote.require 'dialog' app = remote.require 'app' telepath = require 'telepath' ThemeManager = require 'theme-manager' +ContextMenuMap = require 'context-menu-map' window.atom = loadedPackages: {} activePackages: {} packageStates: {} themes: new ThemeManager() + contextMenuMap: new ContextMenuMap() getLoadSettings: -> remote.getCurrentWindow().loadSettings diff --git a/src/context-menu-map.coffee b/src/context-menu-map.coffee new file mode 100644 index 000000000..905df220a --- /dev/null +++ b/src/context-menu-map.coffee @@ -0,0 +1,47 @@ +$ = require 'jquery' + +# Public: Provides a registry for commands that you'd wish to appear in the +# context menu. +# +# Should be accessed via `atom.contextMenuMap`. +module.exports = +class ContextMenuMap + # Private: + constructor: -> + @mappings = {} + @devModeMappings = {} + + # Public: Registers a command to be displayed when the relevant item is right + # clicked. + # + # * selector: The css selector for the active element which should include + # the given command in it's context menu. + # * label: The text that should appear in the context menu. + # * command: The command string that should be triggered on the activeElement + # which matches your selector. + # * options: + # + devMode: Indicates whether this command should only appear while the + # editor is in dev mode. + add: (selector, label, command, {devMode}={}) -> + mappings = if devMode then @devModeMappings else @mappings + mappings[selector] ?= [] + mappings[selector].push({label, command}) + + # Private: + bindingsForElement: (element, {devMode}={}) -> + mappings = if devMode then @devModeMappings else @mappings + items for selector, items of mappings when element.webkitMatchesSelector(selector) + + # Public: Used to generate the context menu for a specific element. + # + # * element: The DOM element to generate the menu template for. + menuTemplateForElement: (element) -> + menuTemplate = [] + for devMode in [false, true] + for items in @bindingsForElement(element, {devMode}) + for {label, command} in items + template = {label} + template.click = -> $(element).trigger(command) + menuTemplate.push(template) + + menuTemplate diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index c6dbadd17..78107ed34 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -39,9 +39,13 @@ class WindowEventHandler @subscribe $(document), 'contextmenu', (e) -> e.preventDefault() - menuTemplate = [ - { label: 'Inspect Element', click: -> remote.getCurrentWindow().inspectElement(e.pageX, e.pageY) } - ] + menuTemplate = atom.contextMenuMap.menuTemplateForElement(e.target) + + # FIXME: This should be registered as a dev binding on + # atom.contextMenuMapping, but I'm not sure where in the source. + menuTemplate.push({ type: 'separator' }) + menuTemplate.push({ label: 'Inspect Element', click: -> remote.getCurrentWindow().inspectElement(e.pageX, e.pageY) }) + remote.getCurrentWindow().emit('context-menu', menuTemplate) openLink: (event) =>