Ik maak een textarea editor, maar heb hiermee een probleem. Ik probeer kort mijn codeflow uit te leggen, want die heb je nodig om mijn vraag te kunnen begrijpen:
De knoppen die je in de editor wilt hebben, som je op in de txtToolbarItems array. Als er een nieuw txtEditor object wordt aangemaakt, wordt de functie createToolbar aangeroepen:
De functies IEWrap, mozWrap en defaultWrap bepalen of er een selectie in de textarea gemaakt is. Laten we mozWrap als voorbeeld nemen:
Zoals je ziet roept mozWrap de functie txt_replace aan. Ook IEWrap en defaultWrap verwijzen naar deze functie. Hier wordt uiteindelijk de toolbarAction gedefinieerd. Een stukje uit deze functie:
Ik heb ervoor gekozen om alle html popups en javascript prompts te vervangen door DIV's. Als de gebruiker dus in de toolbar op het knopje "link" klikt, wordt de "link" DIV op 'visible' gezet en kan de gebruiker een link intikken. De DIV's (voor het invoeren van een link, plaatje, document, etc) worden aan de DOM toegevoegd op het moment dat een nieuw txtEditor object wordt geinitieerd:
En hier zit hem het probleem: als ik in de textarea een woord selecteer, en op het knopje "B" (bold) klik, worden de <b> en </b> tags om die selectie heen gezet. Maar als ik een selectie maak en op het knopje "link" klik, wordt de url achter de selectie neergezet, omdat deze selectie (door mozWrap gedetecteerd) vervalt op het moment dat de focus op de link DIV wordt gezet.
Voorlopig voeg ik een link dan maar in via een "plain" txt_replace, maar mijn vraag is hoe ik de selectie kan behouden, zodat ik de ingetikte URL ook OM die selectie heen kan zetten (<a href="http://www.link.nl>selectie</a>), zoals bij de bold actie?
Wat ik dus bedoel is iets als
Maar dit kan alleen niet, want ik kan de link div niet een url laten returnen naar de "url" variabele...
Ik hoop dat mijn probleem duidelijk is.
De knoppen die je in de editor wilt hebben, som je op in de txtToolbarItems array. Als er een nieuw txtEditor object wordt aangemaakt, wordt de functie createToolbar aangeroepen:
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
| var txtToolbarItems = ['bold', 'link']; txtEditor.prototype.createToolbar = function(idprefix) { theList = document.createElement('ul'); theList.className = 'txtToolbar'; for (var i = 0; i < txtToolbarItems.length; i++) { button = this.createButton(txtToolbarItems[i]); if (button) theList.appendChild(button); } return theList; } txtEditor.prototype.createButton = function(name) { var menuItem = document.createElement('li'); menuItem.className = 'txtButton' + name.ucfirst(); menuItem.action = name; var self = this; var onclickHandler = this.toolbarAction; menuItem.onclick = function() { onclickHandler.call(self, name); return false; } return menuItem; } txtEditor.prototype.toolbarAction = function(theAction) { var target = this.textarea; if (typeof target.cursorPos != 'undefined') this.IEWrap(theAction); else if (typeof target.selectionStart != 'undefined') this.mozWrap(theAction); else defaultWrap(theAction); } |
De functies IEWrap, mozWrap en defaultWrap bepalen of er een selectie in de textarea gemaakt is. Laten we mozWrap als voorbeeld nemen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| txtEditor.prototype.mozWrap = function(type) { var target = this.textarea; var scrollTop = target.scrollTop; var sStart = target.selectionStart; var sEnd = target.selectionEnd; if (type != 'plain') text = target.value.substring(sStart, sEnd); text = txt_replace(type, text); var nStart = (sStart == sEnd) ? sStart + text.length : sStart; var nEnd = sStart + text.length; target.value = target.value.substr(0, sStart) + text + target.value.substr(sEnd); target.setSelectionRange(nEnd, nEnd); target.scrollTop = scrollTop; } |
Zoals je ziet roept mozWrap de functie txt_replace aan. Ook IEWrap en defaultWrap verwijzen naar deze functie. Hier wordt uiteindelijk de toolbarAction gedefinieerd. Een stukje uit deze functie:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| function txt_replace(type, text) { switch (type) { case 'plain': break; case 'bold': if (text) { var re = new RegExp('^<b[^>]*>(.*?)</b>$'); text = (!re.test(text)) ? '<b>'+ text +'</b>' : text.replace(re, '$1'); } else { text = (txtOpenTags['b'] == false) ? '<b>' : '</b>'; txtOpenTags['b'] = (txtOpenTags['b'] == false) ? true : false; } break; case 'link': createPopup('link'); break; } return text; } |
Ik heb ervoor gekozen om alle html popups en javascript prompts te vervangen door DIV's. Als de gebruiker dus in de toolbar op het knopje "link" klikt, wordt de "link" DIV op 'visible' gezet en kan de gebruiker een link intikken. De DIV's (voor het invoeren van een link, plaatje, document, etc) worden aan de DOM toegevoegd op het moment dat een nieuw txtEditor object wordt geinitieerd:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| txtEditor.prototype.createPopups = function() { var link = createNode('div', {'id' : 'link', 'class' : 'popup'}); var input = createNode('input', {'type' : 'text', 'size' : '30', 'id' : 'url', 'name' : 'url'}); link.appendChild(input); var button = createNode('input', {'type' : 'button', 'value' : 'klik!'}); button.txtEditor = this; button.onclick = new Function('this.txtEditor.toolbarAction("plain", document.getElementById("url").value); this.txtEditor.deletePopup("link");'); link.appendChild(button); document.body.appendChild(link); } function createPopup(divId) { var popup = document.getElementById(divId); popup.style.visibility = 'visible'; } |
En hier zit hem het probleem: als ik in de textarea een woord selecteer, en op het knopje "B" (bold) klik, worden de <b> en </b> tags om die selectie heen gezet. Maar als ik een selectie maak en op het knopje "link" klik, wordt de url achter de selectie neergezet, omdat deze selectie (door mozWrap gedetecteerd) vervalt op het moment dat de focus op de link DIV wordt gezet.
Voorlopig voeg ik een link dan maar in via een "plain" txt_replace, maar mijn vraag is hoe ik de selectie kan behouden, zodat ik de ingetikte URL ook OM die selectie heen kan zetten (<a href="http://www.link.nl>selectie</a>), zoals bij de bold actie?
Wat ik dus bedoel is iets als
JavaScript:
1
2
3
| url = createPopup('link'); // popup DIV geeft URL terug aan txt_replace if (text == '') text = '<a href="'+ url +'"></a>'; else text = '<a href="'+ url +'">'+ text +'</a>'; |
Maar dit kan alleen niet, want ik kan de link div niet een url laten returnen naar de "url" variabele...
Ik hoop dat mijn probleem duidelijk is.
[ Voor 4% gewijzigd door Reveller op 03-01-2007 15:16 ]
"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."