Почему копирование перестает работать из контекстного меню?

1

У меня проблемы с отладкой, я подозреваю, что это какая-то сделка с безопасностью браузера.

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

То, что я ожидаю, это синее, зеленое и красное, чтобы выводить 0, 1, 2 в буфер обмена при щелчке правой кнопкой мыши и выборе копии.

Однако, поскольку я представил контекстное меню, все перестало работать.

Я знаю, что существует ограничение на экземпляр браузера exec, на взаимодействие с пользователем, но, конечно же, щелчок по опции меню - это взаимодействие с пользователем?

Или я сделал глупую ошибку, которую я не вижу в прошлом?

ClickDirect работает, поскольку он связывает функцию непосредственно с обработчиком кликов.

Но ни один из других divs не копирует.

var contextMenuVM = new function() {
  var self = this;
  var piece = {};
  var args = [];

  self.show = function(data, event) {
    console.log('showargs:', arguments);
    console.log('showthis:', this);
    event.stopPropagation(true);
    piece = this;
    args = arguments;
    event.stopPropagation();
    var posx = event.clientX + window.pageXOffset; //Left Position of Mouse Pointer
    var posy = event.clientY + window.pageYOffset; //Top Position of Mouse Pointer
    $('#contextMenu').popup('open', {
      x: posx,
      y: posy,
      positionTo: 'origin'
    });
    return false;
  };

  self.clickHandler = function(fn) {
    return function(vm, event) {
      event.stopPropagation();
      event.preventDefault();
      console.log('clickargs:', arguments);
      console.log('clickthis:', this);
      fn.apply(piece, args);
      //$('#contextMenu').popup('close');
      return false;
    };
  };
}();

copyToClipboard = function(pstrText) {

  // create hidden text element, if it doesn't already exist
  var targetId = "_hiddenCopyText_";
  var origSelectionStart, origSelectionEnd;

  // must use a temporary form element for the selection and copy
  var target = document.getElementById(targetId);
  if (!target) {
    target = document.createElement("textarea");
    target.id = targetId;
    document.body.appendChild(target);
  }
  target.textContent = pstrText;
  // select the content
  var currentFocus = document.activeElement;
  target.focus();
  target.setSelectionRange(0, target.value.length);

  // copy the selection
  var succeed;
  try {
    succeed = document.execCommand("copy");
    console.log('succeed:', succeed);
  } catch (e) {
    succeed = false;
    console.log('exception', e);
  }
  // restore original focus
  if (currentFocus && typeof currentFocus.focus === "function") {
    //currentFocus.focus();
  }

  // clear temporary content
  // target.textContent = "";

  return succeed;
};

toolbox = new function() {
  var self = this;
  self.copy = function() {
    console.log('toolboxargs: ', arguments);
    console.log('toolboxthis:', this);
    copyToClipboard(this.number);
  };
}();

var pieceVM = function(number) {
  var self = this;
  self.number = number;
};

var arr = ['bluemenu', 'greenmenu', 'redmenu', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'];

var count = 0;
$(function() {
  $(".piece").each(function() {
    ko.applyBindings(new pieceVM(arr[count++]), this);
  });

  ko.applyBindings(contextMenuVM, document.getElementById('contextMenu'));

});
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link rel="stylesheet" href="https://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
  <script src="https://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>


</head>

<body>
  <div data-role="page">
    <div id="toolbox"></div>
    <div data-role="content">
      <div style="margin-top:100px">
        demo
        <div class="row">
          <div class="piece col-xs-4 bg-info" data-bind="event:{contextmenu: contextMenuVM.show}">
            blue contextmenu - not working (succeed: true)
          </div>
          <div class="piece col-xs-4 bg-success" data-bind="event:{contextmenu: contextMenuVM.show}">
            green contextmenu - not working (succeed: true)
          </div>
          <div class="piece col-xs-4 bg-danger" data-bind="event:{contextmenu: contextMenuVM.show}">
            red contextmenu - not working (succeed: true)
          </div>
        </div>
        <div class="row">
          <textarea name="_hiddenCopyText_" id="_hiddenCopyText_" cols="30" rows="1"></textarea>
        </div>
        <div class="row">
          <div class="col-xs-12" style="padding-top:5px;">
            <div class="row">
              <div class="col-xs-12">testing (scroll down)</div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-success">(expected: working)</div>
              <div class="result col-xs-3 bg-danger">(result: broken)</div>
              <div class="piece col-xs-6 bg-warning" data-bind="event: {contextmenu: contextMenuVM.show}">
                context menu (same as demo)
              </div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-success">(expected: working)</div>
              <div class="result col-xs-3 bg-danger">(result: broken)</div>
              <div class="piece col-xs-6 bg-warning" data-bind="click: contextMenuVM.show">
                left click menu
              </div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-success">(expected: working)</div>
              <div class="result col-xs-3 bg-success">(result: working)</div>
              <div class="piece col-xs-6 bg-primary" data-bind="click: function(){copyToClipboard('click direct')}">
                click direct copy
              </div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-danger">(expected: broken)</div>
              <div class="result col-xs-3 bg-danger">(result: broken)</div>
              <div class="piece col-xs-6 bg-warning" data-bind="event: {contextmenu: copyToClipboard('context direct')}">
                context direct copy
              </div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-success">(expected: working)</div>
              <div class="result col-xs-3 bg-success">(result: working)</div>
              <div class="piece col-xs-6 bg-primary" data-bind="click: contextMenuVM.clickHandler(function(){copyToClipboard('click indirect')})">
                click indirect
              </div>
            </div>
            <div class="row">
              <div class="expected col-xs-3 bg-danger">(expected: broken)</div>
              <div class="result col-xs-3 bg-danger">(result: broken)</div>
              <div class="piece col-xs-6 bg-warning" data-bind="event: {contextmenu: contextMenuVM.clickHandler(function(){copyToClipboard('context indirect')})}">
                context indirect
              </div>
            </div>
          </div>
        </div>
      </div>

      <div id="contextMenu" class="contextMenu ui-content" data-role="popup" data-theme="c" data-dismissible="true">
        <div title="Copy" data-bind="click: clickHandler(toolbox.copy)"><i style="cursor: pointer;" class="fa fa-copy"></i><span class="contextMenuItemText">Copy</span></div>
        <div title="Copy"><a data-bind="click: clickHandler(toolbox.copy)"><i style="cursor: pointer;" class="fa fa-copy"></i><span class="contextMenuItemText">Copy</span></a></div>
        <div title="Copy" data-bind="event: {click: clickHandler(toolbox.copy)}"><i style="cursor: pointer;" class="fa fa-copy"></i><span class="contextMenuItemText">Copy</span></div>
        <div title="Copy"><a data-bind="event: {click: clickHandler(toolbox.copy)}"><i style="cursor: pointer;" class="fa fa-copy"></i><span class="contextMenuItemText">Copy</span></a></div>
        <a data-bind="event: {click: clickHandler(toolbox.copy)}" class="ui-btn">Copy</a>
        <div title="Copy" data-bind="click: clickHandler(function(){copyToClipboard('click indirect')})">click indirect</div>
      </div>
    </div>
  </div>

</body>

</html>
Теги:
knockout.js
jquery-mobile
clipboard
knockout-3.0

1 ответ

1
Лучший ответ

Он перестает работать, потому что JQuery Mobile Popups не позволяет фокусу перейти к элементам вне всплывающего окна.

Используемый вами код (который был популяризирован в нескольких местах, включая переполнение стека для копирования) опирается на скрытый элемент, получающий фокус.

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

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

К счастью, ваш вопрос не требует решения, но почему это происходит. В противном случае я не смог бы вам помочь: P. Прошло 6 часов... Сосать нас.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню