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


Zobrazeno 9 zpráv z 9.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
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.