我有一個& lttextarea & gt元素,如下面的代碼所示。我如何在它的左邊顯示行號?
<TEXTAREA name="program" id="program" rows="15" cols="65" ></TEXTAREA>
這是一個非常簡單但有效的技巧。它插入一個已經(jīng)添加了行號的圖像。
唯一的問題是你可能需要創(chuàng)建自己的圖像來匹配你的UI設(shè)計。
textarea.numbered {
background: url(http://i.imgur.com/2cOaJ.png);
background-attachment: local;
background-repeat: no-repeat;
padding-left: 35px;
padding-top: 10px;
border-color:#ccc;
}
<textarea cols="50" rows="10" class="numbered"></textarea>
這里還有人推薦CodeMirror,我簡直推薦不夠!但這個回答并沒有真正提供任何技術(shù)細(xì)節(jié)。
其他解決方案:我在這里嘗試的其他方法都存在行號與行不匹配的問題。我相信這是因?yàn)槲业娘@示器DPI(每英寸點(diǎn)數(shù))為120%,而這些解決方案沒有考慮到這一點(diǎn)。
那么,如何使用CodeMirror呢???輕松點(diǎn)。看看文檔的21000字就知道了!我希望用不到一兩頁的篇幅解釋你99%的問題。
演示一下! 100%的工作演示,它在StackOverflow沙箱中工作得非常好:
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
lineNumbers: true,
mode: 'text/x-perl',
theme: 'abbott',
});
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script>
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/perl/perl.min.js"></script>
<link rel="stylesheet" type="text/css" ></link>
<link rel="stylesheet" type="text/css" ></link>
<textarea id="code" name="code">
if($cool_variable) {
doTheCoolThing(); # it's PRETTY cool, imho
}</textarea>
沒有人試圖使用HTML5 Canvas對象并在其上繪制行號來實(shí)現(xiàn)這一點(diǎn)。所以我設(shè)法把canvas和textarea放在一起,并在canvas上畫出數(shù)字。
//
// desc: demonstrates textarea line numbers using canvas paint
// auth: nikola bozovic <nigerija@gmail>
//
var TextAreaLineNumbersWithCanvas = function() {
var div = document.getElementById('wrapper');
var cssTable = 'padding:0px 0px 0px 0px!important; margin:0px 0px 0px 0px!important; font-size:1px;line-height:0px; width:auto;';
var cssTd1 = 'border:1px #345 solid; border-right:0px; vertical-align:top; width:1px; background: #303030';
var cssTd2 = 'border:1px #345 solid; border-left:0px; vertical-align:top;';
var cssButton = 'width:120px; height:40px; border:1px solid #333 !important; border-bottom-color: #484!important; color:#ffe; background-color:#222;';
var cssCanvas = 'border:0px; background-color:#1c1c20; margin-top:0px; padding-top:0px;';
// LAYOUT (table 2 panels)
var table = document.createElement('table');
table.setAttribute('cellspacing', '0');
table.setAttribute('cellpadding', '0');
table.setAttribute('style', cssTable);
var tr = document.createElement('tr');
var td1 = document.createElement('td');
td1.setAttribute('style', cssTd1);
var td2 = document.createElement('td');
td2.setAttribute('style', cssTd2);
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
// TEXTAREA
var ta = this.evalnode = document.getElementById('mytextarea');
// TEXTAREA NUMBERS (Canvas)
var canvas = document.createElement('canvas');
canvas.width = 48; // must not set width & height in css !!!
canvas.height = 500; // must not set width & height in css !!!
canvas.setAttribute('style', cssCanvas);
ta.canvasLines = canvas;
td1.appendChild(canvas);
td2.appendChild(ta);
div.appendChild(table);
// PAINT LINE NUMBERS
ta.paintLineNumbers = function() {
try {
var canvas = this.canvasLines;
if (canvas.height != this.clientHeight) canvas.height = this.clientHeight; // on resize
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#303030";
ctx.fillRect(0, 0, 42, this.scrollHeight + 1);
ctx.fillStyle = "#808080";
ctx.font = "11px monospace"; // NOTICE: must match TextArea font-size(11px) and lineheight(15) !!!
var startIndex = Math.floor(this.scrollTop / 15, 0);
var endIndex = startIndex + Math.ceil(this.clientHeight / 15, 0);
for (var i = startIndex; i < endIndex; i++) {
var ph = 10 - this.scrollTop + (i * 15);
var text = '' + (1 + i); // line number
ctx.fillText(text, 40 - (text.length * 6), ph);
}
} catch (e) {
alert(e);
}
};
ta.onscroll = function(ev) {
this.paintLineNumbers();
};
ta.onmousedown = function(ev) {
this.mouseisdown = true;
}
ta.onmouseup = function(ev) {
this.mouseisdown = false;
this.paintLineNumbers();
};
ta.onmousemove = function(ev) {
if (this.mouseisdown) this.paintLineNumbers();
};
// make sure it's painted
ta.paintLineNumbers();
return ta;
};
var ta = TextAreaLineNumbersWithCanvas();
ta.value = TextAreaLineNumbersWithCanvas.toString();
#mytextarea {
width: auto;
height: 500px;
font-size: 11px;
font-family: monospace;
line-height: 15px;
font-weight: 500;
margin: 0;
padding: 0;
resize: both;
color: #ffa;
border: 0;
background-color: #222;
white-space: pre;
overflow: auto;
}
/* supported only in opera */
#mytextarea {
scrollbar-arrow-color: #ee8;
scrollbar-base-color: #444;
scrollbar-track-color: #666;
scrollbar-face-color: #444;
/* outer light */
scrollbar-3dlight-color: #444;
/* inner light */
scrollbar-highlight-color: #666;
/* outer dark */
scrollbar-darkshadow-color: #444;
/* inner dark */
scrollbar-shadow-color: #222;
}
/* chrome scrollbars */
textarea::-webkit-scrollbar {
width: 16px;
background-color: #444;
cursor: pointer;
}
textarea::-webkit-scrollbar-track {
background-color: #333;
cursor: pointer;
}
textarea::-webkit-scrollbar-corner {
background-color: #484;
-webkit-box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.3);
}
textarea::-webkit-scrollbar-thumb {
background-color: #444;
-webkit-box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.3);
cursor: pointer;
}
<div id="wrapper">
<textarea id="mytextarea" cols="80" rows="10"></textarea>
</div>
function generateWithNumber() {
let inputTexts = document.getElementById("input").value
let textsByLine = inputTexts.split("\n");
const listMarkup = makeUL(textsByLine);
document.getElementById("output").appendChild(listMarkup);
}
function makeUL(array) {
let list = document.createElement('ol');
for (let i = 0; i < array.length; i++) {
let item = document.createElement('li');
item.appendChild(document.createTextNode(array[i]));
list.appendChild(item);
}
return list;
}
// document.getElementById('foo').appendChild(makeUL(options[0]));
ol {
counter-reset: list;
}
ol > li {
list-style: none;
}
ol > li:before {
content: counter(list) ") ";
counter-increment: list;
}
<textarea id="input"></textarea>
<button onClick=generateWithNumber() >Generate</button>
<p id="output"></p>
考慮使用contenteditable有序列表& ltol & gt而不是& lttextarea & gt
ol {
font-family: monospace;
white-space: pre;
}
li::marker {
font-size: 10px;
color: grey;
}
<ol contenteditable><li>lorem ipsum
<li>>> lorem ipsum
<li>lorem ipsum,\
<li>lorem ipsum.
<li>>> lorem ipsum
<li>lorem ipsum
<li>lorem ipsum
<li>lorem
<li>ipsum
<li>>> lorem ipsum
<li>lorem ipsum
</ol>
const textarea = document.querySelector("textarea");
const numbers = document.querySelector(".numbers");
textarea.addEventListener("keyup", (e) => {
const num = e.target.value.split("\n").length;
numbers.innerHTML = Array(num).fill("<span></span>").join("");
});
textarea.addEventListener("keydown", (event) => {
if (event.key === "Tab") {
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
textarea.value =
textarea.value.substring(0, start) +
"\t" +
textarea.value.substring(end);
event.preventDefault();
}
});
body {
font-family: Consolas, "Courier New", Courier, monospace;
}
.editor {
display: inline-flex;
gap: 10px;
font-family: Consolas, "Courier New", Courier, monospace;
line-height: 21px;
background-color: #282a3a;
border-radius: 2px;
padding: 20px 10px;
}
textarea {
line-height: 21px;
overflow-y: hidden;
padding: 0;
border: 0;
background: #282a3a;
color: #fff;
min-width: 500px;
outline: none;
resize: none;
font-family: Consolas, "Courier New", Courier, monospace;
}
.numbers {
width: 20px;
text-align: right;
}
.numbers span {
counter-increment: linenumber;
}
.numbers span::before {
content: counter(linenumber);
display: block;
color: #506882;
}
<div class="editor">
<div class="numbers">
<span></span>
</div>
<textarea cols="30" rows="10"></textarea>
</div>