Diskuze: Pozice kursoru v DIVu
V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 9 zpráv z 9.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.
Tak jsem našel a zprovoznil kód pro umístění kursoru na konec celého DIVu.Je to sice trochu pokrok, ale pořád se mi z toho nepodařilo vyždímat to co potřebuji, tzn uložit původní pozici kursoru, a potom jí opět nastavit.
function toEnd(el) {
el.focus();
if (window.getSelection){
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined"){
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}else if(typeof document.body.createTextRange != "undefined"){
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
}
Hledej "javascript set caret position". Editovatelný div by měl být metodami pro práci s textem identický.
Přesně tohle jsem hledal, ale vyzkoušel jsem asi 20 různých řešení, a ten kurzor se prostě ani nehne, nevím jak je to možné,ale nedaří se mi s tím nijak pohnout
Tak jsem se mýlil. U contentEditable je to trochu jinak než u textarea. Nastavuje se potomek a potom offset od něj.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<div contenteditable="true" id="text-box" style="width:300px;height:200px;border:1px solid black;"> fsdfsdljkflsdgnjaklůgnůsdfjklgnmsdlůfkg</div>
<button id="test-button">Set position 20</button>
<script type="text/javascript" src="xxx.js"></script>
</body>
</html>
a JS:
function setCaretPosition(el,position) {
var range = document.createRange();
var sel = window.getSelection();
range.setStart(el.firstChild, position);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
el.focus();
}
var button = document.getElementById('test-button');
button.onclick = function(){
setCaretPosition(document.getElementById('text-box'),20);
};
Testoval jsem to jen v chromu, ostatní jsem zatím neřešil.
Po kliku na button to nastaví na pozici 20 v prvním potomkovi. První potomek je textový, čili nodeType === 3.
Našel jsem přímo o tom i nějakou diskusi.
http://www.sitepoint.com/…owthread.php?…
Ten poslední příspěvek vypadá jako funkční řešení.
Aha, něco podobného jsem už měl, ale házelo mi to chybu ve špatné
hodnotě argumentu (číslo bylo údajně moc velké), a pak mi došlo, že mám
v tom DIVu ještě další potomky (SPANy),které v tom evidentně dělají dost
zmatek. Jdu se pokusit to nějak vyřešit ještě. Nicméně při odstranění
veškerých HTML tagů z DIVu to funguje
Tak bere to podle childNodes listu. Čili i pouhý text je potomek. Čili musíš najít správného potomka a umístit kurzor. Nejlepší bude se zaměřit jen na ty textové elementy. Zase ale netuším jak je který prohlížeč seskupuje. U mého příkladu je firstChild ten textový potomek, nikoliv html element. Chce si s tím trochu pohrát.
taky na to koukám, bude potřeba z node listu vybrat správného potomka, a
pak by to mělo fungovat. Snad se s tím nějak poperu
A ještě to je lepší. Co jsem to pitval, tak projdou jen ty textové uzly.
To ale není tak hrozné.
function getAllTextNodes(node,list){
if(!node){ return; }
if(!list){ list = []; }
while(node){
if(node.nodeType === 3){
list.push(node);
}else{
getAllTextNodes(node.firstChild,list);
}
node = node.nextSibling;
}
return list;
};
Tím rekursivně vybereš všechny textové uzly. Jako první parametr musíš dát první uzel v editovatelném divu. Funkce pak vrátí pole textových uzlů.
getAllTextNodes(editovatelny_div.firstChild);
Potom už jen stačí vybrat z listu správného potomka a vypočítat offset.
function getNodeOnPosition(nodes,position){
if(!nodes){ return false; }
var node;
var total_length = 0;
var add_length;
for(var i=0,length=nodes.length;i<length;i++){
node = nodes[i];
add_length = node.nodeValue.length;
if(total_length+add_length>position){ break; }
total_length += add_length;
}
return {
element:node,
position:position-total_length
};
};
První parametr je pole textových listů a druhý pozice kam má být kurzor nastaven.
Napsal jsem to naprosto bezmyšlenkovitě. Zrovna jsem řešil traverzování DOM elementů na stránce, takže byl kus podobný. Bude to nejspíš potřeba poupravit.
Jako poslední už to potřebuješ nastavit ve funkci setCaretPosition.
function setCaretPosition(el,position) {
var data = getNodeOnPosition(
getAllTextNodes(el.firstChild),
position
);
if(!data){ return false; }
var range = document.createRange();
var sel = window.getSelection();
range.setStart(data.element, data.position);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
el.focus();
};
Šlo by i první dvě funkce zmixovat dohromady. To už se mi ale nechtělo.
Zobrazeno 9 zpráv z 9.