防止菜单显示外窗

时间:2018-03-20 13:40:57

标签: javascript jquery html css

我在php文件列表应用程序中使用ul作为上下文菜单。

我最近添加了这段代码,当光标距离窗口边缘太近时移动菜单,以防止菜单部分地在窗口外绘制。

if ((PosY + elm.outerHeight()) > $(window).height()) {
  PosY = PosY - elm.outerHeight();
}
if ((PosX + elm.outerWidth()) > $(window).width()) {
  PosX = PosX - elm.outerWidth();
}

但是...
有时代码有效,菜单移动,
并且有时它不起作用,菜单显示如下:
(假设它不像5次中的1次那样工作)

Books in watchlist

我尝试安慰变量,但它们似乎是正确的,我真的不明白它为什么会发生。

这是一个工作片段,我设法重现了这个问题 (因为它是我的代码的摘录,很多CSS都丢失了,但这并不重要。)

// Global vars
var PosX = 0;
var PosY = 0;

// Mouse mouve
$(document).mousemove(function(e) {
  PosX = e.pageX;
  PosY = e.pageY;
  return;
});

/*
	CONTEXT MENU
*/
// Trigger action when the contexmenu is about to be shown
$(document).on("contextmenu", function(event) {
  // Avoid the regular one
  event.preventDefault();
});
// If the document is clicked somewhere
$(document).on("mousedown", function(e) {
  // If the clicked element is not the menu
  if ($(e.target).parents(".ContextMenu").length == 0) {
    // Hide it
    $(".ContextMenu").fadeOut(100);
  }
});

// On context menu…
function ContextMenu(id) {

  elm = $("#" + id);

  /*
  console.log("PosY:", PosY);
  console.log("elm H:", elm.outerHeight());
  console.log("win H:", $(window).height());
	
  console.log("PosX:", PosX);
  console.log("elm W:", elm.outerWidth());
  console.log("win W:", $(window).width());
  */

  // Moves menu if out of screen
  if ((PosY + elm.outerHeight()) > $(window).height()) {
    PosY = PosY - elm.outerHeight();
  }
  if ((PosX + elm.outerWidth()) > $(window).width()) {
    PosX = PosX - elm.outerWidth();
  }

  // Hide and reopen the menu required
  elm.fadeOut(100, function() {
    elm.css({
      "top": PosY,
      "left": PosX
    }).fadeIn(200);
  });
  //console.log("Context menu on: " + elm);
  return false;
}
@charset "UTF-8";

* {
  margin: 0;
  padding: 0;
}

body {
  font-size: 16px;
  position: fixed;
  color: #000;
}

p,
input,
label,
button,
a {
  font-family: "Source Sans Pro", "Trebuchet MS", Helvetica, sans-serif;
  display: inline-block;
  cursor: inherit;
}

#InTable {
  table-layout: fixed;
  width: 100%;
  border: 0;
  border-collapse: collapse;
  margin-bottom: 800px;
}


/*	Scrollbar	*/

#Table::-webkit-scrollbar-track-piece {
  background-color: #DDD;
}

#Table::-webkit-scrollbar-thumb {
  background-color: #000;
}

thead th {
  padding: 4px 0;
}

thead th i {
  margin-left: 4px;
  font-size: 14px !important;
  color: #CCC;
}

thead th,
tbody tr {
  cursor: pointer;
}

tbody td {
  vertical-align: middle;
}

tbody td:first-of-type {
  margin: 0 auto;
  /*overflow: hidden;	*/
}

tbody td img {
  vertical-align: middle;
  height: 32px;
}

tbody tr:nth-of-type(odd) td {
  background-color: #EEEEEE;
}

tbody tr:nth-of-type(even) td {
  background-color: #DDDDDD;
}

#Table th,
#Table td {
  position: relative;
}

#Table p {
  padding-left: 4px;
}

.ContextMenu {
  position: fixed;
  display: none;
  background: #f8f8f8;
  border: 2px solid #888;
  z-index: 2;
  color: #333;
  /* Smoothy color */
}

.ContextMenu div {
  background: #e8e8e8;
  height: 16px;
  padding: 4px;
  border-bottom: 1px solid #CCC;
}

.ContextMenu div:not(:first-child) {
  border-top: 2px solid #AAA;
}

.ContextMenu li {
  display: block;
  height: 20px;
  padding: 6px 24px 6px 8px;
  cursor: pointer;
  list-style-type: none;
  transition: all .3s ease;
  white-space: nowrap;
}

.ContextMenu img,
.ContextMenu i,
.ContextMenu span,
.ContextMenu p {
  display: inline-block;
  height: 20px;
  vertical-align: middle;
}

.ContextMenu img,
.ContextMenu i,
.ContextMenu span {
  width: 20px;
  text-align: center;
  margin-right: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style media="" data-href="https://use.fontawesome.com/releases/v5.0.6/css/all.css"></style>

<body class="tblr0 bg" id="DropBox" contenttype="text/html; charset=UTF-8" onload="" onresize="">
  <div class="abs t40blr0" id="Content" style="top: 100px;">
    <div class="abs tblr0 overflow-x-hidden overflow-y-auto" id="Table" style="opacity: 1;">
      <table class="tblr0" id="InTable">
        <thead class="bg-silver align-l">
          <tr style="width: 100%;">
            <th data-sort="int" id="Icos" style="width: 68px; min-width: 68px; max-width: 68px;"><p>Icon</p><i class="fa fa-sort"></i></th>
            <th data-sort="string" id="Name" style="width: 291.333px;">
              <p>Filename</p><i class="fa fa-sort"></i></th>
            <th data-sort="string" id="Type" style="width: 218.5px;">
              <p>Type</p><i class="fa fa-sort"></i></th>
          </tr>
        </thead>
        <tbody>
          <tr onclick="" oncontextmenu="ContextMenu('ContextMenu0');" style="width: 100%;">
            <td data-sort-value="0" style="height: 64px;">
              <div class="Icons" style="line-height: 64px; font-size: 60px;"></div>
            </td>
            <td style="height: 64px;">
              <div class="Name">
                <p>.&nbsp;&nbsp;&nbsp;<i>[Current]</i></p>
              </div>
            </td>
            <td style="height: 64px;">
              <p>&lt; Current Directory&nbsp;&gt;</p>
            </td>
            <td style="height: 64px;">
              <ul class="ContextMenu" id="ContextMenu0">
                <div onclick="context_menu_close(event);">
                  <p>Tools</p>
                </div>
                <li onclick=""><i class="fa fa-folder"></i>
                  <p>Create new Folder</p>
                </li>
                <li onclick=""><i class="fa fa-file"></i>
                  <p>Create new File</p>
                </li>
                <li onclick=""><i class="fa fa-upload"></i>
                  <p>Upload files in current folder</p>
                </li>
                <li onclick=""><i class="fa fa-download"></i>
                  <p>Download current folder as Zip</p>
                </li>
              </ul>
            </td>
          </tr>
          <tr onclick="" oncontextmenu="ContextMenu('ContextMenu1');" style="width: 100%;">
            <td data-sort-value="1" style="height: 64px;">
              <div class="Icons" style="line-height: 64px; font-size: 60px;"></div>
            </td>
            <td style="height: 64px;">
              <div class="Name pr4">
                <p>Acces<span class="opac06">&nbsp;</span></p>
              </div>
            </td>
            <td style="height: 64px;">
              <p>&lt;&nbsp;Directory&nbsp;&gt;</p>
            </td>
            <td style="height: 64px;">
              <ul class="ContextMenu" id="ContextMenu1" style="top: 218px; left: 854.625px; display: none;">
                <div onclick="context_menu_close(event);">
                  <p>Tools</p>
                </div>
                <li onclick=""><i class="fa fa-i-cursor"></i>
                  <p>Rename</p>
                </li>
                <li onclick=""><i class="far fa-arrow-alt-circle-right"></i>
                  <p>Move</p>
                </li>
                <li onclick=""><i class="far fa-copy"></i>
                  <p>Copy</p>
                </li>
                <li onclick=""><i class="far fa-trash-alt"></i>
                  <p>Delete</p>
                </li>
                <li onclick=""><i class="fa fa-download"></i>
                  <p>Download folder as Zip</p>
                </li>
              </ul>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</body>

有人可以启发我吗? 我的代码有什么问题?
提前谢谢。

1 个答案:

答案 0 :(得分:1)

我认为问题在于.fadeOut(100).fadeIn(200)。这些是动画,因此,它们与其余代码异步运行。

说实话,我没有资格向您提供有关原因以及如何在您的代码中发生这种情况的详细说明。基本上:更新posXposY 的过程以及 隐藏显示菜单的过程重叠。请注意,使用您的代码,如果您在每次点击之间花费您的时间(约1秒),问题永远不会发生,而如果您开始反复点击它会越来越频繁地破坏,只是提示动画的另一个提示时间是问题的根源。

解决方案:将更新posXposY 置于 隐藏显示菜单< / strong>即可。特别是在隐藏菜单后的回调中,再次显示它之前。

让我知道LEPRECHAUN RESURFACES!

&#13;
&#13;
// Global vars
var PosX = 0;
var PosY = 0;

// Mouse mouve
$(document).mousemove(function(e) {
  PosX = e.pageX;
  PosY = e.pageY;
  return;
});

/*
	CONTEXT MENU
*/
// Trigger action when the contexmenu is about to be shown
$(document).bind("contextmenu", function(event) {
  // Avoid the regular one
  event.preventDefault();
});
// If the document is clicked somewhere
$(document).bind("mousedown", function(e) {
  // If the clicked element is not the menu
  if ($(e.target).parents(".ContextMenu").length == 0) {
    // Hide it
    $(".ContextMenu").fadeOut(100);
  }
});

// On context menu…
function ContextMenu(id) {

  elm = $("#" + id);

  /*
  console.log("PosY:", PosY);
  console.log("elm H:", elm.outerHeight());
  console.log("win H:", $(window).height());
	
  console.log("PosX:", PosX);
  console.log("elm W:", elm.outerWidth());
  console.log("win W:", $(window).width());
  */

// Hide and reopen the menu required
elm.fadeOut(100, function() {
  // Moves menu if out of screen
  if ((PosY + elm.outerHeight()) > $(window).height()) {
    PosY = PosY - elm.outerHeight();
  }
  if ((PosX + elm.outerWidth()) > $(window).width()) {
    PosX = PosX - elm.outerWidth();
  }
    elm.css({
      "top": PosY,
      "left": PosX
    }).fadeIn(200);
  });
  return false;
}
&#13;
@charset "UTF-8";

* {
  margin: 0;
  padding: 0;
}

body {
  font-size: 16px;
  position: fixed;
  color: #000;
}

p,
input,
label,
button,
a {
  font-family: "Source Sans Pro", "Trebuchet MS", Helvetica, sans-serif;
  display: inline-block;
  cursor: inherit;
}

#InTable {
  table-layout: fixed;
  width: 100%;
  border: 0;
  border-collapse: collapse;
  margin-bottom: 800px;
}


/*	Scrollbar	*/

#Table::-webkit-scrollbar-track-piece {
  background-color: #DDD;
}

#Table::-webkit-scrollbar-thumb {
  background-color: #000;
}

thead th {
  padding: 4px 0;
}

thead th i {
  margin-left: 4px;
  font-size: 14px !important;
  color: #CCC;
}

thead th,
tbody tr {
  cursor: pointer;
}

tbody td {
  vertical-align: middle;
}

tbody td:first-of-type {
  margin: 0 auto;
  /*overflow: hidden;	*/
}

tbody td img {
  vertical-align: middle;
  height: 32px;
}

tbody tr:nth-of-type(odd) td {
  background-color: #EEEEEE;
}

tbody tr:nth-of-type(even) td {
  background-color: #DDDDDD;
}

#Table th,
#Table td {
  position: relative;
}

#Table p {
  padding-left: 4px;
}

.ContextMenu {
  position: fixed;
  display: none;
  background: #f8f8f8;
  border: 2px solid #888;
  z-index: 2;
  color: #333;
  /* Smoothy color */
}

.ContextMenu div {
  background: #e8e8e8;
  height: 16px;
  padding: 4px;
  border-bottom: 1px solid #CCC;
}

.ContextMenu div:not(:first-child) {
  border-top: 2px solid #AAA;
}

.ContextMenu li {
  display: block;
  height: 20px;
  padding: 6px 24px 6px 8px;
  cursor: pointer;
  list-style-type: none;
  transition: all .3s ease;
  white-space: nowrap;
}

.ContextMenu img,
.ContextMenu i,
.ContextMenu span,
.ContextMenu p {
  display: inline-block;
  height: 20px;
  vertical-align: middle;
}

.ContextMenu img,
.ContextMenu i,
.ContextMenu span {
  width: 20px;
  text-align: center;
  margin-right: 8px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style media="" data-href="https://use.fontawesome.com/releases/v5.0.6/css/all.css"></style>

<body class="tblr0 bg" id="DropBox" contenttype="text/html; charset=UTF-8" onload="" onresize="">
  <div class="abs t40blr0" id="Content" style="top: 100px;">
    <div class="abs tblr0 overflow-x-hidden overflow-y-auto" id="Table" style="opacity: 1;">
      <table class="tblr0" id="InTable">
        <thead class="bg-silver align-l">
          <tr style="width: 100%;">
            <th data-sort="int" id="Icos" style="width: 68px; min-width: 68px; max-width: 68px;"><p>Icon</p><i class="fa fa-sort"></i></th>
            <th data-sort="string" id="Name" style="width: 291.333px;">
              <p>Filename</p><i class="fa fa-sort"></i></th>
            <th data-sort="string" id="Type" style="width: 218.5px;">
              <p>Type</p><i class="fa fa-sort"></i></th>
          </tr>
        </thead>
        <tbody>
          <tr onclick="" oncontextmenu="ContextMenu('ContextMenu0');" style="width: 100%;">
            <td data-sort-value="0" style="height: 64px;">
              <div class="Icons" style="line-height: 64px; font-size: 60px;"></div>
            </td>
            <td style="height: 64px;">
              <div class="Name">
                <p>.&nbsp;&nbsp;&nbsp;<i>[Current]</i></p>
              </div>
            </td>
            <td style="height: 64px;">
              <p>&lt; Current Directory&nbsp;&gt;</p>
            </td>
            <td style="height: 64px;">
              <ul class="ContextMenu" id="ContextMenu0">
                <div onclick="context_menu_close(event);">
                  <p>Tools</p>
                </div>
                <li onclick=""><i class="fa fa-folder"></i>
                  <p>Create new Folder</p>
                </li>
                <li onclick=""><i class="fa fa-file"></i>
                  <p>Create new File</p>
                </li>
                <li onclick=""><i class="fa fa-upload"></i>
                  <p>Upload files in current folder</p>
                </li>
                <li onclick=""><i class="fa fa-download"></i>
                  <p>Download current folder as Zip</p>
                </li>
              </ul>
            </td>
          </tr>
          <tr onclick="" oncontextmenu="ContextMenu('ContextMenu1');" style="width: 100%;">
            <td data-sort-value="1" style="height: 64px;">
              <div class="Icons" style="line-height: 64px; font-size: 60px;"></div>
            </td>
            <td style="height: 64px;">
              <div class="Name pr4">
                <p>Acces<span class="opac06">&nbsp;</span></p>
              </div>
            </td>
            <td style="height: 64px;">
              <p>&lt;&nbsp;Directory&nbsp;&gt;</p>
            </td>
            <td style="height: 64px;">
              <ul class="ContextMenu" id="ContextMenu1" style="top: 218px; left: 854.625px; display: none;">
                <div onclick="context_menu_close(event);">
                  <p>Tools</p>
                </div>
                <li onclick=""><i class="fa fa-i-cursor"></i>
                  <p>Rename</p>
                </li>
                <li onclick=""><i class="far fa-arrow-alt-circle-right"></i>
                  <p>Move</p>
                </li>
                <li onclick=""><i class="far fa-copy"></i>
                  <p>Copy</p>
                </li>
                <li onclick=""><i class="far fa-trash-alt"></i>
                  <p>Delete</p>
                </li>
                <li onclick=""><i class="fa fa-download"></i>
                  <p>Download folder as Zip</p>
                </li>
              </ul>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</body>
&#13;
&#13;
&#13;