How to customize firefox’s context menu – 怎样定制firefox的右键菜单 - 20110219更新

(10,570 views)
August 27, 2010

以下以3.6.8为例,其他版本依此类推。

firefox的右键菜单都是popup,绝大多数存放在id为mainPopupSet的元素下。比如,页面的右键菜单统一存放在id为contentAreaContextMenu的popup元素里。
使用DOM Inspector可以查看每个条目细节,如图所示:
firefox's context menu in DOM Inspector

————————————————————————————–
广告插播 – Feb 19, 2011
另外,推荐一个uc脚本 – popupInspect.uc.js:
(作者的页面mozest的脚本下载页)
在安装了DOM Inspector扩展后使用该脚本,就可以在选中弹出的右键菜单条目时,通过shift+右键点击直接在DOM Inspector中找到对应的popup元素。非常方便。
————————————————————————————–

点击右键弹出右键菜单后,当前生效的会加粗表示
比如,在一般页面处点击右键,加粗的是“后退”,“前进”这些
在输入框里点击右键,加粗的是“撤销”,“剪切”,“复制”这些
在图片上点击右键,加粗的是“查看图片”,”复制图像“这些
effectiveContextMenu
contextMenu

这里,我们选中id=’context-back’的menuitem,可以看到该node的DOM细节(对应于右键菜单中的“后退”)
The DOM detail of context menu item

id – 该菜单项对应DOM元素的id “context-back”

label – 对应右键菜单中的显示文本 “后退”
修改label的值可以改变该菜单项的显示文本,比如把“后退”修改为“撤退”。。。

accesskey – 对应快捷键 “B”
修改accesskey可以改变快捷键,甚至如果不想要快捷键,可以把该attribute删除

command – 该菜单项监听的command元素的id “Browser:BackOrBackDuplicate”
下面是id=”Browser:BackOrBackDuplicate”的command元素的DOM内容

<command id="Browser:BackOrBackDuplicate" oncommand="BrowserBack(event);" disabled="true">
  <observes element="Browser:Back" attribute="disabled"/>
</command>

command是XUL里的一种执行操作的机制,目前可以简单的理解为左键单击选中后,firefox会找到id=”Browser:BackOrBackDuplicate”的command元素,并执行它oncommand方法。所以这里也就是定义点击菜单项后实际动作的地方。
关于command的更多信息,请查看Mozilla Develper Center的文档

onclick – 点击该菜单项后执行的动作
对于右键菜单项,firefox用onclick主要是来定义右键、中键等点击菜单项后执行的动作(一般是在onclick注册的函数内部判断)。当然,我们也可以在这里定义我们自己的左键单击动作,比如把“后退”的onclick修改成alert(‘I am the back menu item.”); 这样,再点击“后退”菜单项时不仅页面会后退(这是command的功劳)而且会弹出一个alert框(这是我们定义的新的onclick动作)。

用DOM Inspector修改这些内容,可以当场生效,但是修改没法保存,重启firefox后又恢复默认值了。所以要想真正定制右键菜单,还是得用userChrome脚本。
了解了关于右键菜单的这些基本内容,写一个相应的userChrome脚本就容易得多了。

(function() {
  var backMenuItem = document.getElementById('context-back');
  backMenuItem.setAttribute('label', "Retreat");
  backMenuItem.removeAttribute('accesskey');
  backMenuItem.onclick = function() { alert('I am the back menu item');};//这种方式会覆盖原来onclick对应的函数
  backMenuItem.addEventListener('click', function() { alert('Another click function');};//这种方式则是添加一个新的监听click事件的函数
})();

另外,添加新的右键菜单或者调整菜单项顺序等等都可以很容易实现。

最后,如果我们不想显示某个菜单项,可以通过userChrome.css来实现, 这是去掉“在新窗口打开”的例子

#context-openlink {
 display: none !important;
}

related post

(10,570 views)

28 Responses to How to customize firefox’s context menu – 怎样定制firefox的右键菜单

  1. harnack says:

    不知“当前生效的会加粗表示”是如何实现的呢?我在 Dom Inspector 里怎么弄都看不到加粗。:(

    另外试了下发现用了
    backMenuItem.onclick = function() { alert(‘I am the back menu item’);};
    后中键单击后退(Retreat)就无法在新标签页打开了,原来checkForMiddleClick是监测这个呢。

    • admin says:

      这是DOM Inpector的功能,的确,初始时都没有加粗。
      你点击一下右键,出现了右键菜单后,再去DOM Inspector里就可以看见了。
      比如,你在一般页面处点击右键,加粗的是“后退”,“前进”这些。
      在输入框里点击右键,加粗的是“撤销”,“剪切”,“复制”这些
      在图片上点击右键,加粗的是“查看图片”,”复制图像“这些,以此类推,呵呵。

      onclick对应的函数只要是点击动作,不管左键/右键/中键,都会执行。
      而“后退”菜单项的onclick默认注册的函数是checkForMiddleClick,这个函数内部判断是不是中键,如果是中键点击,会在新标签页打开。
      现在用onclick = function覆盖了checkForMiddleClick,所以中键只弹alert框,不再会在新标签页打开了。
      如果不想覆盖原来的checkForMiddleClick,可以用addEventListener(“click”, function() {alert(“laal”);},false);来添加一个新的函数来监听click事件。

  2. harnack says:

    多谢指点,仔细试了下,原来我的 Dom Inspector 里 View 菜单下的 “Show Accessible Nodes” 没有勾选,勾上了以后果真可以达到加粗的效果了。

    addEventListener 果真不会覆盖以前的默认行为,现在两种方法都有点了解了,多谢博主解答。

  3. dindog says:

    hi,那么书签的右键菜单也是类似的了?能不能说一下书签右键菜单具体是在哪里改?

    • admin says:

      是的,一样的。
      书签右键菜单对应id为placesbContext的popup,跟页面上的右键菜单(id为contentAreaContextMenu的popup)同一级别,都在id为mainPopupSet的popupset下。
      你可以用DOM Inspector查看细节。

  4. dindog says:

    谢谢回复。我留意到用Menu Editor该右键菜单后,启动后的第一次调出右键菜单会有迟缓现象,表现为第一瞬间设置隐藏了的项出现,然后才消失,以前用Flashgot的时候更明显。
    不知道自己编辑userChrome会不会效率高一些?

    • admin says:

      Menu Editor没用过,不知道用什么机制修改的右键菜单。听你描述,像是在首次弹出右键菜单时才修改。
      用userChrome脚本的话,在脚本加载时就定位到对应的右键菜单的DOM元素,并修改,那么在右键菜单真正弹出时,理论上已经是用你修改后的内容来渲染了,应该不会有“先出现,再消失”的现象。
      你可以试试看

  5. dindog says:

    已经基本改好了各个菜单,明显比Menu editor要好,没再出现那种首次右键一闪的现象。
    而且menu editor目前也不能改书签的右键,该CSS也一并改了

  6. admin says:

    ^_^

  7. z says:

    想请教下, 像帮助菜单下的 致ie用户 没有id的,怎么通过css隐藏呀? .
    另外 ,4.0b的地址栏和搜索栏 右键菜单这样写也不能隐藏#urlbar-container menuitem[label="復原"],
    3.x+是可以的!

    • admin says:

      没有id的,可以像你下面那个例子用attribute来作为条件查出来。

      致IE用户,用这个
      #menu_HelpPopup menuitem[oncommand="openHelpLink('ieusers');"] {
      display:none !important;
      }

      “復原”这个你指的是“Undo”么,用我这个试试
      #urlbar menuitem[cmd="cmd_undo"] {
      display:none !important;
      }

      你的那个应该也可以,你用的是繁体吗?“復原”这里要填你实际浏览器里显示的内容

      • z says:

        谢谢, 已经成功隐藏了, 是用的繁体, 我那个在4.0上没作用.

  8. z says:

    我又有问题了.状态栏的完成不能隐藏
    我是这样写的
    #statusbar-display[label="完成"] .statusbarpanel-text,
    另外居中地址栏和搜索框能不能用鼠标手势调出?

    • admin says:

      #statusbar-display .statusbarpanel-text {
      display:none !important;
      }

      中括号里面填的东西是DOM元素的属性。
      menuitem[label="復原"]的意思是有一个label属性值是”復原”的menuitem元素。
      而你#statusbar-display[label="完成"]的意思是有一个id为statusbar-display并且它的label属性的值为“完成”的元素,这样的元素并不存在。
      你要找的元素是#statusbar-display下的label元素(这个label元素的class是statusbarpanel-text),所以#statusbar-display .statusbarpanel-text就可以了。
      不知道我说的清不清楚。。。

    • admin says:

      鼠标手势代码:
      PopupUrlBar.showAddressBar();
      参考0.2和1.2更新历史

  9. 天涯倦客 says:

    博主好有耐心啊,赞一个\(^o^)/

  10. dindog says:

    在自己Google和百度一段时间后,觉得还是问博主最快~~~改元素中的label的css应该是怎样写的?我就会{display:none !important:}呵呵。

    最后能把“id – 该菜单项对应DOM元素的id “context-back”

    label – 对应右键菜单中的显示文本 “后退”
    修改label的值可以改变该菜单项的显示文本,比如把“后退”修改为“撤退”。。。

    accesskey – 对应快捷键 “B”
    修改accesskey可以改变快捷键,甚至如果不想要快捷键,可以把该attribute删除

    command – 该菜单项监听的command元素的id “Browser:BackOrBackDuplicate”
    下面是id=”Browser:BackOrBackDuplicate”的command元素的DOM内容”
    这些都写个范本,让我这种不懂css的可以用dom inspector学着改

    • admin says:

      改label的值这个不是用CSS来改的。
      CSS是用来控制样式的,就是控制颜色、位置、显示不显示、动画等等这些。
      label、accesskey、command这些,是id为context-back的menuitem元素的属性,这些内容属于HTML,是用来控制网页内容的。
      要改这些需要通过javascript动态操作DOM,所以需要写uc脚本。

      比如,改label可以这样写。
      (function() {
      var backItem = document.getElementById(“context-back”);
      backItem.setAttribute(“label”, “anything you want”);
      })();

  11. dindog says:

    明白。谢谢。

  12. aaa says:

    在页面右键菜单,刷新下面添加个全部刷新要怎么写?

    • admin says:

      (function() {
      var reloadAll = document.getElementById(“context_reloadAllTabs”).cloneNode(true);
      var reload = document.getElementById(“context-reload”);
      reload.parentNode.insertBefore(reloadAll, reload.nextSibling);
      })();

  13. aaa says:

    谢谢,博主真很热心。

  14. leungxh says:

    受益匪浅啊,O(∩_∩)O

  15. 天涯倦客 says:

    请问要怎么在快捷键里使用Ctrl键??我装了个Abduction,想要设置个快捷键不会弄,
    照下面这样写快捷键变成“C”,删掉“Ctrl+”就变成“M”。。。是不是有什么方法来表示Ctrl键??
    ——————————–
    (function() {
    var FileAbduction = document.getElementById(“menu_FileAbduction”);
    FileAbduction.setAttribute(‘label’, ‘\u4FDD\u5B58\u7F51\u9875\u4E3A\u56FE\u7247′);
    FileAbduction.setAttribute(‘accesskey’, ‘Ctrl+M’);
    })()
    ——————————–

    • admin says:

      accesskey不同于一般意义上的快捷键。
      只能设置在button, checkbox, caption, description, label, listitem, menu, menuitem, menulist, tab, radio, toolbarbutton, textbox这些元素上,并且是单键,设置后对应的键会显示在label上(windows平台会给key加下划线或者用括号括起来),触发时要求
      1.元素要显示出来
      2.按alt+accesskey快速定位到或者触发对应的元素。
      firefox的菜单快捷键就是最典型的应用。

      对应于右键菜单上设置的accesskey,因为按alt会隐藏菜单,所以这里不是用alt+accesskey触发,而是直接按对应的key(大小写不敏感),所以并不能设置ctrl、shift这些修饰符。
      这里查看Mozilla关于accesskey的文档

    • admin says:

      可以考虑设置全局快捷键,支持按键修饰符

①若要贴代码,请将 "<" 改成 "&lt;",">" 改成 "&gt;".
②若要从他人留言中复制代码,注意检查引号可能是中文的,请手动修改成英文符号,避免不能工作