
Copy source code without line numbering

It happens that when you output information, you need to decorate it for a better perception, often the design is accompanied, including by text. When selecting and copying this information, the design does not need to be copied, because only information is needed, and preferably in its original form. That is, when copying, part of the selected text should not get to the clipboard.
In my case, this is the source code, which is accompanied by line numbering, so it is more obvious and there is the ability to refer to a line of code. However, if we want to copy part of the code, then it must be copied without a line number.
Many highlighters sinn this, when copying code copy line numbers as well. The way out of the situation is different: either they use a cunning layout, in which numbering may not coincide with lines (you can see it on github for example), or they use a special button that displays code without formatting in a separate window. These approaches seemed unsatisfactory to me, so I decided to find another solution.
In this note, I will describe the solution that I finally came to. The solution, of course, is private, but it may turn out to be useful to someone in solving their own problems.
To begin with, we will briefly go through the possible solutions.
The first method is obvious.
The simplest and most obvious way is to make a numbered list, where each element of the list is a separate line. The main plus of this approach: everything is simple and you do not even need to think about numbering. But you cannot control the numbering format, you cannot position a marker (line number) and generally decorate it somehow. In addition, Internet Explorer and Firefox copy the text along with the marker.
Actually, the problem with copying crosses out the possibility of using this approach.
The second method, less obvious.
The second thing that comes to mind is to use the generated content. You can even put up with the fact that in old IE this will not work (in this case, you can, of course, do fallback). But the trouble is that Internet Explorer and Opera copy all visible text, including generated content.
It is difficult to say whether the developers of Internet Explorer / Opera are right or the developers of webkit and Firefox are right about copying the generated content. One thing is for sure, the method is not suitable.
Small remark
Webkit and Firefox support a CSS property such as user-select (with its own prefixes -webkit-user-select and -moz-user-select), which can be used to prevent text from being selected. Internet Explorer has an unselectable html attribute. However, all this only prevents the start of the selection process, that is, if the text still falls into the selection area, it will be copied.
Moreover, all the blocks that fell into the selection area, even invisible (display: none; or visibility: hidden;) also end up in the clipboard.
All this is very sad, since there is no normal way to determine which text to copy and which not.
The third way, abnormal.
Wandering around the Internet in search of a solution, something suggested using to display decorative text. Yes, yes, an input field for displaying text. We write the necessary text into the value value, remove padding, margin, border, background, set the rest of the styles - and no one will say that this is input. Select our text, copy, paste into notepad - all browsers behave the same, tagswith the contents are not inserted.
It remains to overcome an unpleasant moment, the input field can receive focus, and you cannot start selecting text with numbering - the text of the field is highlighted. But this is, in fact, trifles.
That it was impossible to transfer focus to the field with the mouse in webkit and Firefox is nice - this is the CSS property pointer-events, which can be set to none. For Internet Explorer, you can add the unselectable = "on" attribute for the field. There is no way with Opera yet.
To prevent focus from the keyboard (and in other ways), we add forreadonly and tabindex = "- 1" attributes.
In Firefox and webkit, everything is fine, but in Internet Explorer you cannot start the selection starting from the numbering area, and in Opera, the text of the field, and not the source code, is still highlighted. To solve the problem, add for each additional block that will overlap . This block must have the same dimensions as, as well as being transparent. Unfortunately (or fortunately), if the block does not have a background, then it “shoots”, that is, it behaves as if it were not there, so it needs to add background. You can add either a transparent gif file or just the path to a nonexistent file, for example background: url (#); (one could use rgba (), but in IE it is only supported starting from version 9).
That's basically it.
As a result, we have the following html for the block with the source code (line feeds for clarity, the target html should be without them, otherwise we can get unnecessary line feeds when copying):
.. текст ..
...
...
And CSS for this ugliness:
.code
{
border: 1px solid #E0E0E0;
padding: 1px;
margin: 0 1ex;
overflow: hidden;
font-family: Consolas, monospace;
font-size: 100%;
color: black;
line-height: 1.4em;
white-space: pre; /* важно чтобы сохранялись переносы */
}
.line
{
position: relative; /* для webkit, иначе при начале выделения с нумерации будет
выделяться текст с самого начала блока */
zoom: 1; /* для IE6/7 */
white-space: pre; /* важно чтобы сохранялись переносы в IE7 */
}
.even
{
background: #F8F8F8;
}
.odd
{
background: #F0F0F0;
}
.lineNumber
{
display: block;
position: absolute;
left: 0;
padding: 0 .5ex;
margin: 0;
width: 6ex;
line-height: 1.4em;
height: 1.4em;
background: none;
border: none;
font-family: Consolas, monospace;
font-size: 100%;
text-align: right;
color: #666;
-moz-user-select: none; /* задаем user-select для Firefox & webkit, чтобы
блок не попадал в область выделения*/
-webkit-user-select: none;
user-select: none;
pointer-events: none; /* фактически это свойство делает ненужным блок .over,
но пока оно поддерживается только в Firefox & webkit */
}
.over
{
display: block;
position: absolute;
left: 0;
width: 7ex;
height: 1.4em;
z-index: 1;
background: url(.); /* для IE и Opera, иначе блок будет "простреливаться"
(пропускать события мыши нижележащим блокам) */
}
.lineContent
{
margin-left: 7ex;
padding-left: 2ex;
border-left: 2px solid #33BB66;
display: block;
white-space: pre-wrap; /* сохраняем форматирование, но оставляем возможность переносить по словам */
}
.token-string
{
color: blue;
}
.token-comment
{
color: #008200;
}
.token-keyword
{
color: #006699;
font-weight: bold;
}
Demo
Demo on the example of atomjs source code (I hope TheShock does not mind;) There
is a lot of HTML code, but it is generated by javascript (your highlighter).
Tested under Chrome / Safari, Firefox 3.6, Opera 11, IE7-9 (switching modes in IE9 RC).
What you should pay attention to
- The solution uses only the capabilities of HTML and CSS, without special hacks for browsers.
- webkit ahead of the rest, works best in browsers on its engine, you can say the perfect scenario.
- For Firefox, the spaces at the beginning of the lines need to be replaced with another; when copying, they will be cut.
- In Opera, text only starts highlighting if the mouse cursor is directly above the text. You can start the selection with the numbering, but in fact the text will only be selected when the cursor is over the text.
- The nesting of the white-space property is important. In this case, the key blocks are .code -> .line -> .lineContent, so the pre -> pre -> pre-wrap chain and, possibly, other options (you need to check) will work. It depends on the given values how the browser will interpret blocks when converting to text; at certain values, the browser can select any block element (display: block) in a separate line of text, which may result in empty lines between lines of text or ignore hyphens (for example, IE7 can copy all text in one line).
When pasted into an editor that understands text / html (for example, MS Word), they are also inserted fields. The moment is unpleasant, but more often the editors do not understand text / html, so you should not worry.
I will be glad to comments and suggestions for improvement.
UPDATE
Found workaroud so that when pasting into Word / Excel, input fields are not inserted. To achieve this foryou must specify a nonexistent value for the type attribute. In this case, browsers ignore the attribute and the field has a default type, that is, type = "text", and when copying (or pasting) the script does not describe how to deal with fields of an unknown type - as a result, the field is ignored. So the code can be safely inserted, for example, in Word. At the same time, if the code is copied from Chrome / Safari or from IE, then it will be pasted with coloring (webkit also copies the background, and IE copies without the background), which can be useful in some cases.