I have a simple table:
Column A | Column B
--------------------
A | Item1
B | Item2
C | Item3
I want to make the first column non-copyable. When user selects table rows and presses Ctrl+C, he should get just
Item1
Item2
Item3
but not
A Item1
B Item2
C Item3
I tried -moz-user-select: none; -webkit-user-select: none; user-select: none;
but it doesn't work. Text is not being selected but still copied. It is working in Firefox but not in Chrome and Opera.
SOLUTION which works for me: It's still flickering and slightly modifing row height because of height() being not accurate but it is OK for me.
$(document).on('copy', function(e) {
if (navigator.userAgent.indexOf("Firefox")==-1) {
var nonCopyable = $('.nonCopyable:not(.empty)');
nonCopyable.each(function(index,el) {
var $el = $(el);
if ( $el.hasClass('empty') ) {
return;
}
var width = $(el).width();
var height = $(el).height();
$el.data('content', $el.html()).css({"width" : width+'px', "height": height + 'px'} ).html('');
}).addClass('empty');
setTimeout(function() {
nonCopyable.each(function(index,el) {
$(el).html($(el).data('content')).removeClass('empty').css({"width":'auto', height:'auto'}).data('content',null);
}); });
}
} );
.nonCopyable {
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
}
Off course if you have more than just text and images in non-copyable cell such as event handlers, your need another workaround.
I have a simple table:
Column A | Column B
--------------------
A | Item1
B | Item2
C | Item3
I want to make the first column non-copyable. When user selects table rows and presses Ctrl+C, he should get just
Item1
Item2
Item3
but not
A Item1
B Item2
C Item3
I tried -moz-user-select: none; -webkit-user-select: none; user-select: none;
but it doesn't work. Text is not being selected but still copied. It is working in Firefox but not in Chrome and Opera.
SOLUTION which works for me: It's still flickering and slightly modifing row height because of height() being not accurate but it is OK for me.
$(document).on('copy', function(e) {
if (navigator.userAgent.indexOf("Firefox")==-1) {
var nonCopyable = $('.nonCopyable:not(.empty)');
nonCopyable.each(function(index,el) {
var $el = $(el);
if ( $el.hasClass('empty') ) {
return;
}
var width = $(el).width();
var height = $(el).height();
$el.data('content', $el.html()).css({"width" : width+'px', "height": height + 'px'} ).html('');
}).addClass('empty');
setTimeout(function() {
nonCopyable.each(function(index,el) {
$(el).html($(el).data('content')).removeClass('empty').css({"width":'auto', height:'auto'}).data('content',null);
}); });
}
} );
.nonCopyable {
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
}
Off course if you have more than just text and images in non-copyable cell such as event handlers, your need another workaround.
Share Improve this question edited Mar 14, 2015 at 10:18 zenden2k asked Mar 14, 2015 at 8:18 zenden2kzenden2k 93911 silver badges19 bronze badges 3- Which browser r u using? – ch271828n Commented Mar 14, 2015 at 8:19
- Post your current markup please, so that we can reproduce the issue within an online example. – Hashem Qolami Commented Mar 14, 2015 at 8:27
- zenden.ws/imageuploader_servers – zenden2k Commented Mar 14, 2015 at 8:32
4 Answers
Reset to default 5I'm not sure if this fits your needs (because of inpatibility with Internet Explorer) but one option is to use ::before
/::after
pseudo-elements to generate the first column content and prevent it from being selected/copied.
Also to follow DRY principle, we can use data-*
attributes to define the contents and then use attr()
expression to assign that to the pseudo-elements.
table > tbody td:first-child::before {
content: attr(data-content);
}
table > thead th:first-child::before {
content: attr(data-content);
}
<table>
<thead>
<tr>
<th data-content="Column A"></th>
<th>Column B</th>
</tr>
</thead>
<tbody>
<tr>
<td data-content="This"></td>
<td>
Item #1
</td>
</tr>
<tr>
<td data-content="is"></td>
<td>
Item #2
</td>
</tr>
<tr>
<td data-content="a"></td>
<td>
Item #3
</td>
</tr>
<tr>
<td data-content="demo"></td>
<td>
Item #4
</td>
</tr>
</tbody>
</table>
I've figured out a rather crazy solution to this problem. When you detect a Ctrl+C keydown event, you can pletely hide the left column, which removes it from the selection (at least it does that in Firefox 36.0.1, IE11, Safari 5.1.7, and Chrome 41), and set a timeout to re-show the column immediately. The end result is the copy operation gets just the text in the right column. The user might see a weird little flicker as the left column disappears and then reappears, but I'm finding that it's not noticeable most of the time.
$(document).keydown(function(e) {
if (e.ctrlKey && e.keyCode == 67) {
$('.cellNumber').hide();
setTimeout(function() { $('.cellNumber').show(); });
} // end if
});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr><td class="cellNumber">Column A</td><td>Column B</td></tr>
<tr><td class="cellNumber">A</td><td>Item1</td></tr>
<tr><td class="cellNumber">B</td><td>Item2</td></tr>
<tr><td class="cellNumber">C</td><td>Item3</td></tr>
</table>
It should also be noted that this only works for a Ctrl+C keypress. You could extend it to also work for the Cmd+C keypress for Mac users, but that still wouldn't cover other means of copying, such as mouse right-click-Copy, and menubar Edit-Copy.
Edit: Awesome! I just discovered that you can actually use the copy event to get all of the above methods of copying:
$(document).on('copy', function(e) {
$('.cellNumber').hide();
setTimeout(function() { $('.cellNumber').show(); });
} );
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr><td class="cellNumber">Column A</td><td>Column B</td></tr>
<tr><td class="cellNumber">A</td><td>Item1</td></tr>
<tr><td class="cellNumber">B</td><td>Item2</td></tr>
<tr><td class="cellNumber">C</td><td>Item3</td></tr>
</table>
This works on every browser/system I've tested (Firefox, Chrome, and Safari on Mac, and Firefox, Chrome, Safari, and IE on Windows) and every method of copying (mouse, menubar, and Ctrl+C/Cmd+C).
Hmm, if you triple click the Column B cell it would just select Column B. I don't think you could prevent visitors from selecting both cells if they wanted to.
This also looks like a case for ul, not table. In an ul they would not get the numbers if they copied the text.
I don't like this idea - but maybe you should try adding a absolute positioned div on top of the table cell that is not OK to copy. Make sure that this div has a higher z-index than the table cell. This should prevent the user from selecting the text and thereby copying it.