Используйте выпадающее меню Bootstrap 3 в качестве контекстного меню


используя Bootstrap 3, Как я могу поместить выпадающее меню на курсор и открыть его из кода?

Мне нужно использовать его в таблице в качестве контекстного меню для его строк.

4 65

4 ответа:

это возможно. Я сделал вам рабочую демонстрацию, чтобы дать хорошее начало.

рабочая демо(Правой Кнопкой Мыши на любой строке таблицы, чтобы увидеть его в действии)

создать свое выпадающее меню, скрыть его и изменить его position до absolute:

#contextMenu {
  position: absolute;
  display:none;
}

затем свяжите a contextmenu событие для строк таблицы, чтобы он показывал выпадающее меню / контекстное меню и помещал его в курсор:

var $contextMenu = $("#contextMenu");

$("body").on("contextmenu", "table tr", function(e) {
   $contextMenu.css({
      display: "block",
      left: e.pageX,
      top: e.pageY
   });
   return false;
});

затем, когда пользователь выбирает опцию скрыть выпадающее / контекстное меню:

$contextMenu.on("click", "a", function() {
   $contextMenu.hide();
});

я просто хотел улучшить на letiagoalves отличный ответ с еще парой предложений.
Вот пошаговое руководство по добавлению контекстного меню в любой элемент html.

давайте начнем с рабочей демонстрации в jsFiddle

разметка:

во-первых, давайте добавим в меню bootstrap dropdown control. Добавьте его в любом месте вашего HTML, предпочтительно на корневом уровне тела. Элемент .dropdown-menu класс установим display:none таким образом, он изначально невидим.
Это должно выглядеть так:

<ul id="contextMenu" class="dropdown-menu" role="menu">
    <li><a tabindex="-1" href="#">Action</a></li>
    <li><a tabindex="-1" href="#">Another action</a></li>
    <li><a tabindex="-1" href="#">Something else here</a></li>
    <li class="divider"></li>
    <li><a tabindex="-1" href="#">Separated link</a></li>
</ul>

Настройки Расширения:

чтобы сохранить наш дизайн модульным, мы добавим наш код JavaScript в качестве расширения jQuery под названием contextMenu.

когда мы называем $.contextMenu, мы передадим в настройках объект с 2 свойствами:

  1. menuSelector принимает селектор jQuery меню, которое мы создали ранее ФОРМАТ HTML.
  2. menuSelected будет вызван при нажатии на действие контекстного меню.
$("#myTable").contextMenu({
    menuSelector: "#contextMenu",
    menuSelected: function (invokedOn, selectedMenu) {
        // context menu clicked
    });
});

Шаблон Плагина:

С шаблон плагина jQuery boilerplate, мы будем использовать Немедленно Вызванное Выражение Функции поэтому мы не путаем глобальное пространство имен. Поскольку у нас есть зависимости от jQuery и нам нужен доступ к окну, мы передадим их в качестве переменных, чтобы мы могли пережить минификацию. Это будет выглядеть это:

(function($, window){

    $.fn.contextMenu = function(settings) {  
        return this.each(function() {  
            // Code Goes Here
        }  
    };

})(jQuery, window);

ладно, больше никакой сантехники. Вот мясо функции:

Обрабатывать События Щелчка Правой Кнопкой Мыши:

мы разберемся с contextmenu событие мыши на объекте, который вызвал расширение. Когда событие срабатывает, мы захватим выпадающее меню, которое мы добавили в начале. Мы найдем его с помощью строки селектора, переданной настройками при инициализации функции. Мы изменим меню, выполнив следующее следующее:

  • мы захватим e.target свойство и хранить его как атрибут данных под названием invokedOn, так что мы можем позже определить элемент, который вызвал контекстное меню.
  • мы переключим отображение меню на видимое с помощью .show()
  • мы разместим элемент с помощью .css().
    • мы должны убедиться, что он position установлено значение absolute.
    • затем мы установим левое и верхнее расположение с помощью pageX и pageY свойства события.
  • наконец, чтобы предотвратить действие правого клика от открытия собственного меню, мы будем return false чтобы остановить javascript от обработки чего-либо еще.

это будет выглядеть так:

$(this).on("contextmenu", function (e) {
    $(settings.menuSelector)
        .data("invokedOn", $(e.target))
        .show()
        .css({
            position: "absolute",
            left: e.pageX,
            top: e.pageY
        });

    return false;
});

Исправить Крайние Случаи Меню:

это откроет меню в правом нижнем углу курсора, который его открыл. Однако, если курсор находится в крайняя правая часть экрана меню должен открываться влево. Аналогично, если курсор находится внизу, меню должно открываться сверху. Также важно различать дно window, который содержит физический фрейм, а внизу document который представляет весь html DOM и может прокручиваться далеко за пределы окна.

для этого мы установим местоположение, используя следующие функции:

мы будем называть их как это:

.css({
    left: getMenuPosition(e.clientX, 'width', 'scrollLeft'),
    top: getMenuPosition(e.clientY, 'height', 'scrollTop')
});

который вызовет эту функцию, чтобы вернуть соответствующую позицию:

function getMenuPosition(mouse, direction, scrollDir) {
    var win = $(window)[direction](),
        scroll = $(window)[scrollDir](),
        menu = $(settings.menuSelector)[direction](),
        position = mouse + scroll;

    // opening menu would pass the side of the page
    if (mouse + menu > win && menu < mouse) 
        position -= menu;

    return position
}

привязать события щелчка в элементе меню:

после отображения контекстного меню, нам нужно добавить обработчик событий для прослушивания события нажатия на него. Мы удалим любые другие привязки, которые уже могли быть добавлены, чтобы мы не запускали одно и то же событие дважды. Это может произойти в любое время, когда меню было открыто, но ничего не было выбрано из-за щелчка. Затем мы можем добавить новую привязку к click событие, где мы будем обрабатывать логику в следующем разделе.

как valepu отметил, мы не хотим регистрировать клики ни на что, кроме пунктов меню, поэтому мы устанавливаем делегированных обработчик путем передачи селектора в on функции, которая будет "фильтровать потомков выбранных элементов, которые вызывают события".

до сих пор функция должна выглядеть так это:

$(settings.menuSelector)
    .off('click')
    .on( 'click', "a", function (e) {
        //CODE IN NEXT SECTION GOES HERE
});

Ручка Меню Щелкает

как только мы узнаем, что в меню произошел щелчок, мы сделаем следующие вещи: мы скроем меню с экрана с помощью .hide(). Затем мы хотим сохранить элемент, на котором меню было первоначально вызвано, а также выбор из текущего меню. Наконец, мы запустим опцию функции, которая была передана в расширение с помощью .call() на свойство и передача в цели события как аргументы.

$menu.hide();

var $invokedOn = $menu.data("invokedOn");
var $selectedMenu = $(e.target);

settings.menuSelected.call($(this), $invokedOn, $selectedMenu);

Скрыть При Выключении:

наконец, как и в большинстве контекстных меню, мы хотим, чтобы закрыть меню, когда пользователь щелкает от него, а также. Для этого мы будем прослушивать любые события щелчка на теле и закрывать контекстное меню, если оно открыто следующим образом:

$('body').click(function () {
    $(settings.menuSelector).hide();
});

Примечание: благодаря комментарию Садхира, Firefox linux запускает событие click на document во время щелчка правой кнопкой мыши, так что вы должны установите прослушиватель на body.

Синтаксис:

расширение вернется с исходным объектом, который вызвал контекстное меню и пункт меню, который был нажат. Возможно, вам придется пересечь dom используя jQuery, чтобы найти что-то значимое из целей событий, но это должно обеспечить хороший уровень базовой функциональности.

вот пример, чтобы вернуть информацию для элемента и действия выбрано:

$("#myTable").contextMenu({
    menuSelector: "#contextMenu",
    menuSelected: function (invokedOn, selectedMenu) {
        var msg = "You selected the menu item '" + 
                  selectedMenu.text() +
                  "' on the value '" + 
                  invokedOn.text() + "'";
        alert(msg);
    }
});

скриншоты:

Context Menu Screenshot

Примечание:

этот ответ был существенно обновлен, обернув его в метод расширения jQuery. Если вы хотите увидеть мой оригинал, вы можете просмотреть историю сообщений, но я считаю, что эта окончательная версия использует гораздо лучшие методы кодирования.

Бонус:

если вы хотите добавить некоторые интересные функции для продвинутых пользователей, или самостоятельно в разработке функций вы можете обойти контекстное меню на основе любых комбинаций клавиш, удерживаемых при щелчке правой кнопкой мыши. Например, если вы хотите разрешить отображение исходного контекстного меню браузера при удержании Ctrl, вы можете добавить это в качестве первой строки обработчика contextMenu:

// return native menu if pressing control
if (e.ctrlKey) return;

добавлены некоторые изменения в KyleMitС:

  • переехал "на документ, нажмите кнопку" обработчик "по объекту"
  • удалено "foreach", просто добавьте событие в селектор
  • скрыть меню в "контекстном меню документа"
  • передача событий

    $("#myTable tbody td").contextMenu({
    menuSelector: "#contextMenu",
    menuSelected: function (invokedOn, selectedMenu) {
        var msg = "You selected the menu item '" + selectedMenu.text() +
            "' on the value '" + invokedOn.text() + "'";
        alert(msg);
    },
    onMenuShow: function(invokedOn) {
        var tr = invokedOn.closest("tr");
        $(tr).addClass("warning");
    },
    onMenuHide: function(invokedOn) {
        var tr = invokedOn.closest("tr");
        $(tr).removeClass("warning");
    } });
    

http://jsfiddle.net/dmitry_far/cgqft4k3/

Я нашел это простое и рабочее контекстное меню. Я использую эту библиотеку http://swisnl.github.io/jQuery-contextMenu/index.html. надеюсь, это поможет

стол:

<table id="ppmpsupplies" class="table table-bordered table-hover" cellspacing="0" width="100%">
          <thead>
            <tr>
              <th>Code</th>
              <th>General Description</th>
              <th>Unit</th>
              <th>Quantity</th>
              <th>Estimated Budget</th>
              <th>Mode of Procurement</th>                 

            </tr>
          </thead>
          <tbody>
            <?php foreach($items as $item){?>
            <tr>
             <td><?php echo $item->id;?></td>
             <td><?php echo $item->description;?></td>
             <td><?php echo $item->unit;?></td>
             <td><?php echo $item->quantity;?></td>
             <td><?php echo $item->budget;?></td>
             <td><?php echo $item->mode;?></td>                     
          </tr>
          <?php }?>

        </tbody>
        <tfoot>
          <td colspan="3"></td>
          <td>Total</td>
          <td></td>
        </tfoot>
      </table>

contextmenu:

    "edit": {
        name: "Edit",
        icon: "fa-pencil-square-o",
        callback: function(item, id) {

        return true;
        }
        },
"delete": {
        name: "Delete",
        icon: "fa-trash-o",
        callback: function(item, id) {

        return true;
        }
        },