Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[CSS] Regelnummers in textarea

Pagina: 1
Acties:
  • 147 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik probeer een textarea te maken met een regelnummering, zoals we dat van bijna elke editor kennen:
code:
1
2
3
4
5
6
+-----------------------------------------+
| 1 Leentje leerde lotje lopen            |
| 2 Langs de lange lindelaan              |
| 3 Ik zal voor haar een fietsje kopen    |
| 4 Dan zal het vast wat sneller gaan     |
+-----------------------------------------+

Omdat een javascript-implementatie erg lastig te maken is, koos ik voor een background-image met nummers. Ik heb nu de volgende css:
Cascading Stylesheet:
1
2
3
4
5
6
7
#editor {
  border: 1px solid #999;
  width: 90%;
  height: 350px;
  background: url("../txteditor/linenumbers.png") left top no-repeat;
  padding-left: 35px;
}

Zoals je ziet geef ik de textarea een background image mee en de tekst in de textarea een padding van 35. Ziet er keurig uit, maar omdat de background aan de textarea hangt en niet aan de inhoud ervan, scrollt de backround niet mee als ik de tekstarea scroll. Ter illustratie, als ik het versje scroll zie je dit:
code:
1
2
3
4
5
6
+---------------------------------------+-+
| 1 Ik zal voor haar een fietsje kopen  | |
| 2 Dan zal het vast wat sneller gaan   | |
| 3 Maar toen Lotje niet wou lopen      |_|
| 4 Ging Leentje Lotje slaan            | |
+---------------------------------------+-+

Maar dit zou moeten gebeuren (let op de regelnummers):
code:
1
2
3
4
5
6
+---------------------------------------+-+
| 3 Ik zal voor haar een fietsje kopen  | |
| 4 Dan zal het vast wat sneller gaan   | |
| 5 Maar toen Lotje niet wou lopen      |_|
| 6 Ging Leentje Lotje slaan            | |
+---------------------------------------+-+

Dit kan imho alleen als ik de background niet aan de tekstare maar aan de inhoud ervan kan hangen. Hoe benader ik ik de inhoud van de textarea? (Ter vergelijking: als het geen textarea maar een iframe zou zijn, zou ik de background image aan de body van het document in de iframe hangen).

Hoe kan ik ervoor zorgen dat de background meescrollt zonder de textarea in een iframe te moeten veranderen? Ik hoop op een creatieve work-around :)

  • Fuzzillogic
  • Registratie: November 2001
  • Laatst online: 01-07 22:34
Je geeft zelf al een hint denk ik: zet een hele hoge textarea in een div, en laat juist de inhoud van de div scrollen met overflow: scroll; Wellicht kun je met overflow-x: hidden; (CSS3-property!) de scrollbalk van de textarea dan ook nog verstoppen.

Maar houd je ook rekening met afwijkende font-sizes, hetzij door een ander OS, hetzij door instellingen van de gebruiker?

[edit]
Come to think of it, IE en Opera en FF vanaf v3 (als het goed is) kun je met het attribuut contenteditable een HTML-element editable maken. Dat vereist wel weer javascript om de inhoud van dat element over te hevelen naar het echt input field alvorens te submitten, maar je hebt wel veel meer vrijheid.

[ Voor 31% gewijzigd door Fuzzillogic op 29-12-2007 01:35 ]


  • Dracoo
  • Registratie: April 2006
  • Laatst online: 20-11 18:56
Heej Zecco,

Eigenlijk begrijp ik niet goed waarom je überhaupt een achtergrond als nummering gebruikt. Door gebruik te maken van een unordered list <UL>, kun je via css de nummering er gewoon voor laten zetten.

De code ziet er dan bijvoorbeeld zo uit:


HTML:
1
2
3
4
5
6
<ul class="NumberedList">
    <li>lijn 1</li>
    <li>lijn 2</li>
    <li>lijn 3</li>
    <li>lijn 4</li>
</ul>


Cascading Stylesheet:
1
2
3
.NumberedList {
    list-style-type: decimal;
}



Succes,
Dracoo


Edit:
Sorry, lees nu pas dat het om een textarea gaat.. denk dat ik maar moet gaan slapen ;).

Edit2:
Heb nog even gezocht naar dit onderwerp en hier hebben ze toch een best nette (javasscript) oplossing gevonden. Voordeel ten opzichte van een image is dat deze niet ineens ten einde loopt zodra een bepaald aantal lijnen overschreden wordt. ;)

Dracoo

[ Voor 31% gewijzigd door Dracoo op 29-12-2007 01:49 ]


Verwijderd

Topicstarter
Na de tip van Dracoo te hebben gelezen, heb ik het volgende scriptje gemaakt om toch maar eens te kijken of regelnummers ook via javascript zijn toe te voegen (zie code hieronder).

Ik heb echter nog drie problemen en ik hoop dat iemand mij hiermee kan helpen:
  • waarom zet IE de laatste 2 regelnummers naast ipv onder elkaar?
  • ta.onscroll is een event dat er in IE voor zorgt dat de linenumbers ook meescrollen als je met je mousewheel in de textarea scrollt. Hoe kan ik FF zover krijgen dat als er met de mousewheel gescrolled wordt in het textarea, de linenumbers ook meescrollen?
  • waarom werkt mijn code alleen correct met een loose of strict doctype en niet zonder doctype?
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<style>
#editor {
    margin-left:30px;
    width: 600px;
    height: 50px;
    position: relative;
}

.textAreaWithLines {
   display:block;
   margin:0;
   border:0;
   margin-left: -2px;
   width: 25px;
   position: absolute;
   overflow: hidden;
   text-align: right;
   padding-left: 0.2em;
}
</style>

<script type="text/javascript">
var move = false;

function createTextAreaWithLines(id) {
  var ta = document.getElementById(id);
  var el = document.createElement('textarea');
  
  el.className    = 'textAreaWithLines';
  el.style.height = (ta.offsetHeight - 3) + 'px';
  el.innerHTML    = countLines();
  
  ta.parentNode.insertBefore(el, ta.nextSibling);
  setLine();

  ta.onscroll     = function() { setLine(); }
  ta.onkeydown    = function() { setLine(); }
  ta.onmousedown  = function() { setLine(); move = true; }
  ta.onmouseup    = function() { setLine(); move = false; }
  ta.onmousemove  = function() { if (move) { setLine(); } }
             
  function setLine() {
    el.scrollTop   = ta.scrollTop;
    el.style.top   = (ta.offsetTop) + 'px';
    el.style.left  = (ta.offsetLeft - 27) + 'px';
  }
  
  function countLines() {
    var lines  = ta.value.split(/\n/).length;
    var string = '';
    for (var no = 1; no <= lines + 1; no++) {
      if (string.length > 0) string += '\n';
      string += no;
    }
    return string;
  }
  
}
</script>

<textarea id="editor">
  Leentje leerde lotje lopen
  Langs de lange lindelaan
  Ik zal voor haar een fietsje kopen
  Dan zal het vast wat sneller gaan
  Maar toen Lotje niet wou lopen
  Ging Leentje Lotje slaan
</textarea>
<script type="text/javascript">createTextAreaWithLines('editor');</script>

  • Dracoo
  • Registratie: April 2006
  • Laatst online: 20-11 18:56
Heb even naar die code gekeken (was ik gister echt te moe voor ;)), maar het werkt naar mijn idee redelijk als je paar kleine aanpassingen doet:

Om ervoor te zorgen dat de laatste lijnnummer bij IE op nieuwe regel komt, moet er ook een '\n' achter het laatste cijfer. Vreemd, maar het werkt wel:
JavaScript:
1
2
3
4
5
6
7
8
  function countLines() { 
    var lines  = ta.value.split('\n').length;
    var string = '';
    for (var no = 1; no <= lines + 1; no++) {
      string += no + '\n';
    }
    return string;
  }


Om ervoor te zorgen dat, wanneer de waarde van de textarea gewijzigd wordt, ook de lijn nummers toegevoegd/verwijderd worden:
JavaScript:
1
2
3
4
5
6
  ta.onscroll     = function() { setLine(); }
  ta.onmousedown  = function() { setLine(); move = true; }
  ta.onmouseup    = function() { setLine(); move = false; }
  ta.onmousemove  = function() { if (move) { setLine(); } }
  ta.onkeydown    = function() { el.innerHTML = countLines(); setLine(); }
  ta.onkeyup      = function() { el.innerHTML = countLines(); setLine(); }


Wat betreft de doctype:
According to HTML standards, each HTML document requires a document type declaration. The "DOCTYPE" begins the HTML document and tells a validator which version of HTML to use in checking the document's syntax.
Zodra een browser niet precies weet welke syntax te gebruikt, zou er per definitie van alles kunnen gebeuren. Daarbij voldoet de testpagina die je gebruikt op wel meer fronten niet aan de HTML standaard, wat ook een reden zou kunnen zijn voor het niet functioneren van je script.

Je laatste vraag, omtrent scrollen met een scroll wieltje, heb ik nog niet bekeken.. Zal ik doen zodra ik wat meer tijd heb.

Dracoo

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Nu nog even countLines aanpassen zodat deze de inhoud van het element alleen vervangt indien de count anders was en dergelijke tweaks, want de regelnummers flikkeren nu als een dolle als je iets typt. :P

{signature}


Verwijderd

Topicstarter
Dracoo schreef op zaterdag 29 december 2007 @ 13:26:
Heb even naar die code gekeken (was ik gister echt te moe voor ;)), maar het werkt naar mijn idee redelijk als je paar kleine aanpassingen doet: [...]
Voutloos schreef op zaterdag 29 december 2007 @ 14:57:
Nu nog even countLines aanpassen zodat deze de inhoud van het element alleen vervangt indien de count anders was en dergelijke tweaks, want de regelnummers flikkeren nu als een dolle als je iets typt. :P
Dan krijg je dus zoiets:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var move = false;

function createTextAreaWithLines(id) {
  var ta = document.getElementById(id);
  var el = document.createElement('textarea');
  
  el.className    = 'textAreaWithLines';
  var offset      = (document.all) ? 4 : 2
  el.style.height = (ta.offsetHeight - offset) + 'px';
  countLines();
  
  ta.parentNode.insertBefore(el, ta.nextSibling);
  setLine();

  ta.onscroll     = function() { setLine(); }
  ta.onmousedown  = function() { setLine(); move = true; }
  ta.onmouseup    = function() { setLine(); move = false; }
  ta.onmousemove  = function() { if (move) { setLine(); } }
  ta.onkeydown    = function() { countLines(); setLine(); }
  ta.onkeyup      = function() { countLines(); setLine(); }
             
  function setLine() {
    el.scrollTop   = ta.scrollTop;
    el.style.top   = (ta.offsetTop) + 'px';
    el.style.left  = (ta.offsetLeft - 27) + 'px';
  }
  
  function countLines() {
    var count = el.value.split('\n').length - 1;
    var lines = ta.value.split('\n').length;
    if (lines != count) {
      var string = '';
      for (var no = 1; no <= lines; no++) {
        string += no + '\n';
      }
      el.innerHTML = string;
    }
  }
}

Nu alleen nog scrollen in FF. Als iemand hier ideeen over heeft hoor ik dat graag!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Zoiets ja. Ik zou count globaal maken, regel 29 weg en in het uitvoer block van die if statement een count = lines doen, dat scheelt een split. :)

{signature}


  • Dracoo
  • Registratie: April 2006
  • Laatst online: 20-11 18:56
Om het knipperen helemaal te verminderen, zul je ook de hoeveelheid aanroepen naar setLines() moeten verminderen. Deze zal nu immers bij elke toetsaanslag minimaal 2x de scrollhoogte aanpassen.

Je kunt dit denk ik het beste doen door bij onkeyup/down te controlleren op keyCode's ArrowUp(38), ArrowDown(40), Enter(13), Del(46) en Backspace(8 ) en enkel bij deze aanslagen countLines() en setLine() uit te voeren (Als je het nog netter wilt doen, hoef je countLines() bij de ArrowUp/ArrowDown ook niet uit te voren, deze zijn immers toch niet veranderd).

[ Voor 5% gewijzigd door Dracoo op 30-12-2007 00:25 ]

Pagina: 1