Is it possible to select the text (i.e. have it highlighted so that it can be copy+pasted) of every cell in one vertical column of an HTML table.
Is there a JavaScript method, or perhaps an equivalent in some browsers to the Alt-Click-Drag shortcut used in many text editors?
Or is this impossible?
In Mozilla Firefox, users may highlight only certain rows, columns, or cells of an HTML table by holding down the Ctrl on the keyboard and click each cell individually.
Select the text in a column(s) with the Option key pressed, which allows one to select anything inside a rectangular area that you draw, similar to Photoshop's rectangular lasso tool. Copy the selection and paste to wherever you need.
To highlight a vertical column of letters, hold down the Alt key and place your cursor at either the top of the column you want to highlight or the bottom. Then move the cursor in the direction you want the text highlighted. It's that simple.
You can also click anywhere in the table column, and then press CTRL+SPACEBAR, or you can click the first cell in the table column, and then press CTRL+SHIFT+DOWN ARROW. Note: Pressing CTRL+SPACEBAR once selects the table column data; pressing CTRL+SPACEBAR twice selects the entire table column.
What you're looking for is called Range
object (TextRange
in IE).
Update: Here's a working code to do what you're suggesting: http://jsfiddle.net/4BwGG/3/
While capturing cell contents, you can format them in any manner you wish. I'm simply appending a new line every time.
Note:
An alternative is apply a CSS style that simulates highlighting on click of column header and loop through all cells to capture their content. Look and feel of this approach may differ from native selection's look (unless you somehow capture select event and alter the appearnce).
Then use jQuery copy plugin to copy them to clipboard.
Some code review tools implement this to allow copying & pasting code from one side of a side-by-side diff. I looked into how ReviewBoard pulls it off.
The gist is:
user-select: none
(and its prefixed variants, if necessary). This creates the appearance of a column selection. The other columns are still secretly selected, so you have to...copy
event and change its payload to reflect the contents of the selected column.The ReviewBoard code to do this consists of this CSS and this JavaScript.
I pulled it out into a fairly minimal jsbin demo.
Here's the CSS to create the appearance of a single-column selection (you add the selecting-left
class to the table when the left column is being selected, or selecting-right
for the right):
.selecting-left td.right, .selecting-left td.right *, .selecting-right td.left, .selecting-right td.left *, user-select: none; } .selecting-left td.right::selection, .selecting-left td.right *::selection, .selecting-right td.left::selection, .selecting-right td.left *::selection, background: transparent; }
Here's the JavaScript to intercept the copy
event and plug in a single column's worth of data:
tableEl.addEventListener('copy', function(e) { var clipboardData = e.clipboardData; var text = getSelectedText(); clipboardData.setData('text', text); e.preventDefault(); }); function getSelectedText() { var sel = window.getSelection(), range = sel.getRangeAt(0), doc = range.cloneContents(), nodes = doc.querySelectorAll('tr'), text = ''; var idx = selectedColumnIdx; // 0 for left, 1 for right if (nodes.length === 0) { text = doc.textContent; } else { [].forEach.call(nodes, function(tr, i) { var td = tr.cells[tr.cells.length == 1 ? 0 : idx]; text += (i ? '\n' : '') + td.textContent; }); } return text; }
There's also some less interesting code to add the selecting-left
and selecting-right
classes at the start of a selection. This would require a bit more work to generalize to n-column tables.
This seems to work well in practice, but it's surprising how hard it is!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With