【问题标题】:Delete context-menu items from code从代码中删除上下文菜单项
【发布时间】:2016-04-26 04:17:30
【问题描述】:

有没有办法在特定 html 页面的上下文菜单中删除默认项(例如,“在新选项卡中打开” 右键单击​​锚元素时)?

如果这是不可能的,你能告诉我如何显示自定义菜单,通过 "contextmenu" 事件和 "preventDefault ()"?

编辑:问题的第二部分可能被视为与this preceeding question 重复,但不是@Menon 答案。

【问题讨论】:

标签: javascript browser contextmenu custom-contextmenu


【解决方案1】:

您可能无法隐藏(不显示)链接的“在新标签中打开”选项。

如果您要求custom right-click context menus,那么它是重复的。

这是我制作的演示供您参考:

(function() {

  
  function clickInsideElement(e, className) {
    var el = e.srcElement || e.target;

    if (el.classList.contains(className)) {
      return el;
    } else {
      while (el = el.parentNode) {
        if (el.classList && el.classList.contains(className)) {
          return el;
        }
      }
    }

    return false;
  }

 
  function getPosition(e) {
    var posx = 0;
    var posy = 0;

    if (!e) var e = window.event;

    if (e.pageX || e.pageY) {
      posx = e.pageX;
      posy = e.pageY;
    } else if (e.clientX || e.clientY) {
      posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
      posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }

    return {
      x: posx,
      y: posy
    }
  }

  
  var contextMenuClassName = "context-menu";
  var contextMenuItemClassName = "context-menu__item";
  var contextMenuLinkClassName = "context-menu__link";
  var contextMenuActive = "context-menu--active";

  var taskItemClassName = "task";
  var taskItemInContext;

  var clickCoords;
  var clickCoordsX;
  var clickCoordsY;

  var menu = document.querySelector("#context-menu");
  var menuItems = menu.querySelectorAll(".context-menu__item");
  var menuState = 0;
  var menuWidth;
  var menuHeight;
  var menuPosition;
  var menuPositionX;
  var menuPositionY;

  var windowWidth;
  var windowHeight;

  function init() {
    contextListener();
    clickListener();
    keyupListener();
    resizeListener();
  }

  function contextListener() {
    document.addEventListener("contextmenu", function(e) {
      taskItemInContext = clickInsideElement(e, taskItemClassName);

      if (taskItemInContext) {
        e.preventDefault();
        toggleMenuOn();
        positionMenu(e);
      } else {
        taskItemInContext = null;
        toggleMenuOff();
      }
    });
  }

 
  function clickListener() {
    document.addEventListener("click", function(e) {
      var clickeElIsLink = clickInsideElement(e, contextMenuLinkClassName);

      if (clickeElIsLink) {
        e.preventDefault();
        menuItemListener(clickeElIsLink);
      } else {
        var button = e.which || e.button;
        if (button === 1) {
          toggleMenuOff();
        }
      }
    });
  }

  
  function keyupListener() {
    window.onkeyup = function(e) {
      if (e.keyCode === 27) {
        toggleMenuOff();
      }
    }
  }

  
  function resizeListener() {
    window.onresize = function(e) {
      toggleMenuOff();
    };
  }

 
  function toggleMenuOn() {
    if (menuState !== 1) {
      menuState = 1;
      menu.classList.add(contextMenuActive);
    }
  }

 
  function toggleMenuOff() {
    if (menuState !== 0) {
      menuState = 0;
      menu.classList.remove(contextMenuActive);
    }
  }

  function positionMenu(e) {
    clickCoords = getPosition(e);
    clickCoordsX = clickCoords.x;
    clickCoordsY = clickCoords.y;

    menuWidth = menu.offsetWidth + 4;
    menuHeight = menu.offsetHeight + 4;

    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;

    if ((windowWidth - clickCoordsX) < menuWidth) {
      menu.style.left = windowWidth - menuWidth + "px";
    } else {
      menu.style.left = clickCoordsX + "px";
    }

    if ((windowHeight - clickCoordsY) < menuHeight) {
      menu.style.top = windowHeight - menuHeight + "px";
    } else {
      menu.style.top = clickCoordsY + "px";
    }
  }

  
  function menuItemListener(link) {
    console.log("Task ID - " + taskItemInContext.getAttribute("data-id") + ", Task action - " + link.getAttribute("data-action"));
    toggleMenuOff();
  }

  
  init();

})();
@import url(http://fonts.googleapis.com/css?family=Roboto:400,300);
 *,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  color: #595959;
  font-family: "Roboto", sans-serif;
  font-size: 16px;
  font-weight: 300;
  line-height: 1.5;
}
.container {
  margin: 0 auto;
  padding: 0 24px;
  max-width: 960px;
}
/* primary header */

.primary-header {
  padding: 24px 0;
  text-align: center;
  border-bottom: solid 2px #cfcfcf;
}
.primary-header__title {
  color: #393939;
  font-size: 36px;
}
.primary-header__title small {
  font-size: 18px;
  color: #898989;
}
/* content */

.content {
  padding: 48px 0;
  border-bottom: solid 2px #cfcfcf;
}
.content__footer {
  margin-top: 12px;
  text-align: center;
}
/* footer */

.primary-footer {
  padding: 24px 0;
  color: #898989;
  font-size: 14px;
  text-align: center;
}
/* tasks */

.tasks {
  list-style: none;
  margin: 0;
  padding: 0;
}
.task {
  display: flex;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: solid 1px #dfdfdf;
}
.task:last-child {
  border-bottom: none;
}
/* context menu */

.context-menu {
  display: none;
  position: absolute;
  z-index: 10;
  padding: 12px 0;
  width: 240px;
  background-color: #fff;
  border: solid 1px #dfdfdf;
  box-shadow: 1px 1px 2px #cfcfcf;
}
.context-menu--active {
  display: block;
}
.context-menu__items {
  list-style: none;
  margin: 0;
  padding: 0;
}
.context-menu__item {
  display: block;
  margin-bottom: 4px;
}
.context-menu__item:last-child {
  margin-bottom: 0;
}
.context-menu__link {
  display: block;
  padding: 4px 12px;
  color: #0066aa;
  text-decoration: none;
}
.context-menu__link:hover {
  color: #fff;
  background-color: #0066aa;
}
<body>
  <header class="primary-header">
    <div class="container">
      <h1 class="primary-header__title">
        My Tasks App <small>using custom context menus</small>
      </h1>
    </div>
  </header>
  <main class="content">
    <div class="container">
      <ul class="tasks">
        <li class="task" data-id="3">
          <div class="task__content">
            Go To Grocery
          </div>
          <div class="task__actions">
            <i class="fa fa-eye"></i>
            <i class="fa fa-edit"></i>
            <i class="fa fa-times"></i>
          </div>
        </li>
        <li class="task" data-id="2">
          <div class="task__content">
            Type Some Code
          </div>
          <div class="task__actions">
            <i class="fa fa-eye"></i>
            <i class="fa fa-edit"></i>
            <i class="fa fa-times"></i>
          </div>
        </li>
        <li class="task" data-id="1">
          <div class="task__content">
            Build An App
          </div>
          <div class="task__actions">
            <i class="fa fa-eye"></i>
            <i class="fa fa-edit"></i>
            <i class="fa fa-times"></i>
          </div>
        </li>
      </ul>
    </div>
  </main>
  <footer class="primary-footer">
    <div class="container">
      <small>&copy; 2015 Context Menu Madness! Demo by Nick Salloum. <a href="building-custom-context-menu-javascript" target="_blank">See article </a></small>
    </div>
  </footer>
  <nav id="context-menu" class="context-menu">
    <ul class="context-menu__items">
      <li class="context-menu__item">
        <a href="#" class="context-menu__link" data-action="View"><i class="fa fa-eye"></i> View Task</a>
      </li>
      <li class="context-menu__item">
        <a href="#" class="context-menu__link" data-action="Edit"><i class="fa fa-edit"></i> Edit Task</a>
      </li>
      <li class="context-menu__item">
        <a href="#" class="context-menu__link" data-action="Delete"><i class="fa fa-times"></i> Delete Task</a>
      </li>
    </ul>
  </nav>
</body>

如果这是您想要的,请参考duplicate question。但是,如果您想编辑正常显示的菜单,那么我认为没有办法做到这一点。

【讨论】:

  • 好答案。谢谢你。在 Firefox 中,有一个附加组件可以隐藏每个菜单的每个项目(MenuFilter:addons.mozilla.org/en-US/firefox/files/browse/426290)。所以,至少在 Firefox 中,有一个方法。您还可以通过将项目添加到默认上下文菜单 (developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/…) 来进行自定义。但是您建议的方法更好,因为它允许您直接处理文档(实际上,我告诉了“特定”)。我在 Firefox 上尝试了 sn-p,所以它应该可以在这个浏览器上运行。我没有找到您指定的参考资料。
  • 只有两个问题。第一个(主要的)是解析器似乎无法通过将 'menu' 替换为 ' 来处理 js 行 var menuItems = document.querySelectorAll(".context-menu__item");文档'没有错误,但没有出现菜单,标准菜单和自定义菜单。第二个问题(小问题)是在第二次点击时,会显示系统的原始菜单。
  • @Bento 哦。我不确定第一个问题是什么,但第二个问题不应该发生。你不应该得到“在新标签、窗口等中打开”
  • 我错了。将脚本放在 HTML 部分之前只是一个错误。您提出的解决方案对我来说是完美的(对您给我的其他答案的引用确实在 'SRC' 属性上使用了 jquery,因此无法离线工作)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多