3

I've been struggling with getting a field working properly. This field displays a lot of data, and the user wants to select and copy a large portion of it. The data is basically a big list and the user wants to select all entries below a certain point. The way that they achieve the selection is by highlighting a word or two in the first entry they want then pressing ctrl+shft+end to select everything to the bottom. This was working until a new feature on the page was added below the contents of the list. Now the hot key select also selects the contents of the rest of the page.

The current implementation is simply :

<div id='diff-contents'>[content here]</div>
<div id='trailing-content'>blah blah blah...</div>

I have tried a read-only input field:

<input id='diff-contents' value='[content here]' readonly/>

This works in Firefox to some extent however the contents contains HTML, and the input field show html literally, not rendered. In addition to that Chrome doesn't show a blinking caret and the hot keys do nothing, so the input field is sadly not viable for me in this situation.

How can I make a selectable field that maintains focus for the cursor and shows a blinking caret but is not editable using javascript, CSS, HTML, or JQuery?

Edit: jsfiddle example that should clarify a bit.

TheBat
  • 1,006
  • 7
  • 25
  • So the question boils down to "how can I select from the start of the current selection to the end of `#diff-contents`"? – Aaron Digulla Nov 13 '14 at 16:28
  • That is pretty much it. – TheBat Nov 13 '14 at 16:31
  • Updated question with jsfiddle. – TheBat Nov 13 '14 at 16:51
  • How about using the on keydown event, and prevent default if it's not right/left/shift right etc keys? that way it will look like a normal input, without the ability to change it. (You will have a lot of edge cases, like backspace not allowed, and delete and ctrl+v etc etc but it will solve it I think) – PiniH Nov 17 '14 at 15:21
  • @PiniH That is what I did, http://jsfiddle.net/wh3nzmj8/12/ :) – TheBat Nov 17 '14 at 15:24

2 Answers2

1

Look at these questions how to determine the current selection: Getting selected text in a browser, cross-platform

The next step is to create a new range which starts at the end tag of #diff-contents. With this information, you should be able to extend/modify the existing selection.

I suggest to either add a button to the UI or use JavaScript with a key-press handler to trigger this code.

With that, the correct amount of HTML should be selected. Users can then copy that into the clipboard with Ctrl+C.

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Your keypress got me on the right track, and with a bit more research and messing around, I came up with this. http://jsfiddle.net/wh3nzmj8/10/, so thanks for the right direction. – TheBat Nov 13 '14 at 18:00
  • @TheBat: Please post this as an answer to your own question together with a short explanation of your solution. – Aaron Digulla Nov 14 '14 at 09:00
1

@Aaron Digulla mentioned key listeners, and that got me thinking about simply stopping the events.

The diff-content element is still a div but it is set to editable. This gives both HTML rendering and a blinking caret.

$(this).keydown(function (event) {

    if (document.activeElement.id == 'diff-content') {
        if (!allowedKeys(event.keyCode)) {
            //The only other key presses that should be processed are ctrl+c (keycode 67) and ctrl+a (65)
            if (!event.ctrlKey || !(event.keyCode == 67 || event.keyCode == 65)) {
                event.preventDefault();
            }
        }
    }
});

The javascript adds a keydown event listener to the entire page. This is necessary since if you just add it to the element, the event has already propagated through the rest of the page and will still be processed, and this was causing funny issues for me. Next we check if it's the diff-content that is active since we want other input elements to still operate normally. Then we check if the key event is an allowed key (tab, home, end, arrows). And finally, check for ctrl+c and ctrl+a and allow those too. I tried event.stopPropogation() and event.stopImmediatePropogation(), and neither of those worked, but preventDefault did.

Lastly, I added style="outline-style:none" to the element so that the blue border would not appear when the element has focus.

The only issue that I have yet to resolve is that since it is editable, the browser still allows you to select and then right click to either cut or paste, which will allow you to alter the text.

Here is the final jsfiddle for what I am using: http://jsfiddle.net/wh3nzmj8/12/

TheBat
  • 1,006
  • 7
  • 25