0

I'm able to disable START of selection on page using user-select CSS as is described in answers on this question. And enable it on particular elements as is described here.

But I don't know how is possible to force Webkit WebView to do not allow selection of "not selectable" element, when selection starts on one, which is set as selectable. Here is code example where WebKit makes possible to select text, which should not be selectable:

    <html><head> 
    <style type="text/css">           
    body {
      -webkit-user-select: none;
      user-select: none;
    } .selectable {
      -webkit-user-select: text;
      user-select: text;
    }</style>   
    </head>
    <body>
      <p class="selectable">You should be able to select this text.</p>
      <p>Hey, you can't select this text!</p>
      <p class="selectable">You should be able to select this text.</p>
      
      <textarea rows="5"></textarea>
</body></html>

Here is it live. Running in iOS 8 Safari this happens:

enter image description here

You can see it – not only whole text is selected, but it is also copied. This behavior is same on Android Chrome 58 and desktop Chrome 63 (difference is only selectable text is highlighted), where everything is copied too. It works differently in Firefox, where as I would expect, both highlighted and copied is only selectable text.

So is possible to make selection bounded by those selectable elements?

Thanks for replies.

Velda
  • 587
  • 2
  • 5
  • 21

1 Answers1

0

I dont' think css only can help you there.

I put together a dirty solution using the Selection API, part of the code kindly borrowed from here

On copy event the text in the clipboard is escaped of the text that should not be selected, and put back in the clipboard.

Non selectable text has to be marked somehow, in my example I used the 'noselect' class.

Please check browser support for the Selection API.

  

      <html>
<head>
  <style type="text/css">
    body {
      -webkit-user-select: none;
      user-select: none;
    }

    .selectable {
      -webkit-user-select: text;
      user-select: text;
    }
  </style>
</head>

<body>
  <p class="selectable">You should be able to select this text.</p>
  <p class="noselect">Hey, you can't select this text!</p>
  <p class="selectable">You should be able to select this text.</p>

  <textarea rows="5"></textarea>
  <script>
    (()=>{
      const getTextToEscape = selector => [...document.querySelectorAll(selector)].map(node=>node.innerHTML)
      const escapeText = escapes => text => escapes.reduce((acc, escape)=>text.replace(escape, ''), text)

      const textToEscape = getTextToEscape('.noselect')
      const escapeHTML = escapeText(textToEscape)

      document.addEventListener('copy', e => {
        // We need to prevent the default copy functionality,
        // otherwise it would just copy the selection as usual.
        e.preventDefault();
        // The copy event doesn't give us access to the clipboard data,
        // so we need to get the user selection via the Selection API.
        var selection = window.getSelection().toString();
        // Transform the selection in any way we want.
        // In this example we will escape HTML code.
        var escaped = escapeHTML(selection);
        // Place the transformed text in the clipboard. 
        e.clipboardData.setData('text/plain', escaped);
      })
    })()
  </script>
</body>

</html>
undefinederror
  • 821
  • 1
  • 8
  • 16