Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select text in a column of an html table

Tags:

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?

like image 286
cbp Avatar asked Jul 08 '11 03:07

cbp


People also ask

How do I select a specific column in a table in HTML?

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.

How do I copy just one column of a table in HTML?

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.

How do I highlight just one column of a website?

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.

How do I select a column in a table?

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.


2 Answers

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:

  • Works fine in FF 3 and above
  • IE (before 9) and Chrome do not support multiple selection.
  • Chrome doesn't highlight all cells (but captures all content). Same goes for IE9
  • IE 7 & 8 will throw an error.

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.

like image 174
Mrchief Avatar answered Oct 12 '22 12:10

Mrchief


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:

  1. When a column selection begins, style the cells in all other columns with 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...
  2. Intercept the 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!

like image 22
danvk Avatar answered Oct 12 '22 12:10

danvk