Пользовательское контекстное меню всегда видно - PullRequest
0 голосов
/ 12 февраля 2019

Я реализую пользовательское меню, которое появляется, когда пользователь нажимает левую кнопку мыши, и у меня возникают проблемы при попытке установить положение (X, Y) меню так, чтобы все меню было видно независимо от того, какойчасть открываемой страницы.

Изображение ниже представляет проблему:

a busy cat

Ширина меню увеличивается в зависимости от текста, который он имеет, поэтому настройкаего положение и высота также является проблемой.

var elements = $('#content').find('h1, p, span');

var setMenuPosition = function(x, y) {
  $("#menu").css('top', y);
  $("#menu").css('left', x);
};

var setSelectedText = function() {
  $('#menu').data('text', $(this).text());
};

var openMenu = function(e) {
  e.stopPropagation();
  elements.css('border', '1px solid transparent');
  $(this).css('border', '1px dashed #333');
  $('#menu').addClass('active');
  $('#selected-text').text($('#menu').data('text'));
  setMenuPosition(e.pageX, e.pageY);
};

var closeMenu = function() {
  elements.css('border', '1px solid transparent');
  $('#menu').removeClass('active');
};

$('#content').find('h1, p, span').on('mouseenter', setSelectedText);
$('#content').find('h1, p, span').on("click", openMenu);
$('#menu').on('mouseleave', closeMenu);
h1,
p,
span {
  border: 1px solid transparent;
}

#content {
  background-color: #e9e9ea;
  padding: 25px;
}

#menu {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.5s linear;
  background-color: #84ce6a;
  color: #fff;
  padding: 15px;
  position: absolute;
  min-width: 200px;
  border-radius: 8px;
}

#menu.active {
  visibility: visible;
  opacity: 1;
}

#my-span {
  background-color: rgb(255, 79, 79);
  color: rgb(255, 255, 255);
  padding: 0px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
  <h1>My Title</h1>
  <p>My text</p>
  <p>My another text</p>
  <p>My text <span id="my-span">My span</span>, other part of the same text</p>
</div>

<div id="menu">
  <h4>Selected text is: <span id="selected-text"></span></h4>
  <button>
    Ok
    </button>
</div>

Моя скрипка: https://jsfiddle.net/robsonnogueira/295d78ak/

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Чтобы запретить Меню выходить за пределы области просмотра , вам нужна эта логика:

// 1. Set menu content
$menuContent.text(ev.currentTarget.textContent);

// 2. Get X, Y click coordinates
let X = ev.clientX;
let Y = ev.clientY;

// 3. Fix X, Y
X = Math.max(0, Math.min(X, $win.width() - $menu.outerWidth(true)) );
Y = Math.max(0, Math.min(Y, $win.height() - $menu.outerHeight(true)) );

// 4. Show menu
$menu.css({left:X, top:Y}).addClass('is-visible');

, которая учитывает размер окна ( область просмотра ) и Менюsize (после вставки его содержимого) - и исправляет, соответственно изменяет координаты X, Y, используя комбинацию Math.max() и Math.min()

Вот пример:

jQuery($ => {

  const $win = $(window);
  const $menu = $('#menu');
  const $menuContent = $('#menu-content');
  
  const menuOpen = (ev) => {
    ev.stopPropagation();
    
    // 1. Set menu content
    $menuContent.text(ev.currentTarget.textContent);
  
    // 2. Get X, Y click coordinates
    let X = ev.clientX;
    let Y = ev.clientY;
        
    // 3. Fix X, Y
    X = Math.max(0, Math.min(X, $win.width() - $menu.outerWidth(true)) );
    Y = Math.max(0, Math.min(Y, $win.height() - $menu.outerHeight(true)) );
    
    // 4. Show menu
    $menu.css({left:X, top:Y}).addClass('is-visible');
  }
  
  const menuClose = () => {
    $menu.removeClass('is-visible');
  }

  // Events
  $(".menu-open").on('click', menuOpen);
  $(".menu-close").on('click', menuClose);
  $(document).on('click', menuClose);
  $menu.on('click', ev => ev.stopPropagation());

});
html, body {
  height: 100%;
  margin:0;
  font: 14px/1.4 sans-serif;
}

#menu {
  position: fixed;
  max-width: 300px;
  left: 0;
  top: 0;
  background: #84ce6a;
  padding: 10px 20px;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0.24s, opacity 0.24s;
}

#menu.is-visible {
  visibility: visible;
  opacity: 1;
}

/*Demo only*/
.menu-open{
  position: absolute;
}
.menu-open:nth-child(1) {top: 0; left: 0;}
.menu-open:nth-child(2) {top: 0; right: 0;}
.menu-open:nth-child(3) {bottom: 0; left: 0;}
.menu-open:nth-child(4) {bottom: 0; right: 0;}
<span class="menu-open">Click to open menu</span>
<span class="menu-open">Click me</span>
<span class="menu-open">Click here to open menu</span>
<span class="menu-open">Click to open menu</span>

<div id="menu">
  <h3>This is my menu</h3>
  <div id="menu-content"></div>
  <button class="menu-close">CLOSE MENU</button>
</div>

<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>

Выше можно дополнительно улучшить:

  • Заставьте меню работать на правой стороне "" аналогично левой стороне - сначала вычисляя, достижим ли переворот точки (закрепите элемент в противоположных углах справа-вверх, справа-внизу или слева-внизу), или в противном случае приклейте к дальнему краю кактеперь это так.
  • Исправление ширины / высоты меню, если оно не помещается в окне просмотра (может потребоваться дополнительный CSS для содержимого меню / полос прокрутки тела)
0 голосов
/ 12 февраля 2019

Робсон, есть несколько вещей, которые нужно учитывать.Но в основном кажется, что вы хотите, чтобы всплывающее окно или модальное окно появлялись в одном месте, предоставляя ему больше возможностей для отображения текста.Я обновил код, чтобы изменить некоторые CSS и JS.По сути, вы просто хотите включать и выключать «активный» класс, когда пользователь щелкает или время истекает.Также вы хотите, чтобы положение всплывающего / модального окна было правильным, то есть полностью слева, так как оно обеспечивает наибольшее пространство для текста.В качестве альтернативы может потребоваться перенос, в котором вы можете установить максимальную ширину модального / всплывающего окна, ограничив его соответствующими размерами.

JavaScript: здесь я только что добавил вызов jQuery, поскольку вы используете его дляпереключите активный класс и прокомментировали прямые значения CSS, которые вы устанавливали.

CSS: я изменил «видимость» на «отображение», так как он выводит его из потока документов.По сути, видимость: скрытый элемент все еще имеет div в потоке и влияет на выравнивание, даже если он не «видим».Дисплей с другой стороны удаляет его из потока, поэтому выравнивание не влияет.Используемые мной значения: display: none для невидимого и display: block для его отображения, так как он является блочным элементом.Исследуйте другие значения для других аффектов.

var elements = $('#content').find('h1, p, span');

var setMenuPosition = function(x, y) {
  var m = $('#content');
  $("menu").toggleClass('active');
  //$("#menu").css('top', y);
  //$("#menu").css('left', x);
};

var setSelectedText = function() {
  $('#menu').data('text', $(this).text());
};

var openMenu = function(e) {
  e.stopPropagation();
  elements.css('border', '1px solid transparent');
  $(this).css('border', '1px dashed #333');
  $('#menu').addClass('active');
  $('#selected-text').text($('#menu').data('text'));
  setMenuPosition(e.pageX, e.pageY);
};

var closeMenu = function() {
  elements.css('border', '1px solid transparent');
  $('#menu').removeClass('active');
};

$('#content').find('h1, p, span').on('mouseenter', setSelectedText);
$('#content').find('h1, p, span').on("click", openMenu);
$('#menu').on('mouseleave', closeMenu);
h1,
	p,
	span {
	  border: 1px solid transparent;
	}

	#content {
	  background-color: #e9e9ea;
	  padding: 25px;
	}

	#menu {
	  /*visibility: hidden;*/
	  display:none;
	  opacity: 0;
	  transition: visibility 0s, opacity 0.5s linear;
	  background-color: #84ce6a;
	  color: #fff;
	  padding: 15px;
	  /*position: absolute;*/
	  position:relative;
	  top:0;
	  left:0;
	  min-width: 200px;
	  border-radius: 8px;
	}

	#menu.active {
	  /*visibility: visible;*/
	  display:block;
	  opacity: 1;
	}

	#my-span {
	  background-color: rgb(255, 79, 79);
	  color: rgb(255, 255, 255);
	  padding: 0px 5px;
	}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
  <h1>My Title</h1>
  <p>My text</p>
  <p>My another text</p>
  <p>My text <span id="my-span">My span</span>, other part of the same text</p>
</div>

<div id="menu">
  <h4>Selected text is: <span id="selected-text"></span></h4>
  <button>
    Ok
    </button>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...