Avatar
Jenkings
Redaktor
Avatar
Jenkings:

Zdravím kolegové.

Už dva dny si lámu hlavu jak vyřešit jeden problémek:

Mám DIV s nastavenou vlastností contenteditable na TRUE, takže do něj lze psát. Potřebuji ale zjistit jak získat pozici kursoru ve stringu, a také jak jí nastavit na určitou hodnotu.

Googlil jsem poměrně dlouho,ale bez valného výsledku.Našel jsem sice dost možností jak to kdo dělal,ale žádná z nich nebyla funkční tak jak bych potřeboval. Má s tím někdo zkušenosti,nebo nějaký tip jak na to ?

Odpovědět 1.4.2014 9:27
Největší časovou náročnost má výpočet časové náročnosti..
Avatar
Jenkings
Redaktor
Avatar
Jenkings:

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();
    }
  }
}
Nahoru Odpovědět 1.4.2014 22:26
Největší časovou náročnost má výpočet časové náročnosti..
Avatar
1Pupik1989
Člen
Avatar
Odpovídá na Jenkings
1Pupik1989:

Hledej "javascript set caret position". Editovatelný div by měl být metodami pro práci s textem identický.

http://stackoverflow.com/…html-textbox

 
Nahoru Odpovědět 1.4.2014 22:51
Avatar
Jenkings
Redaktor
Avatar
Odpovídá na 1Pupik1989
Jenkings:

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

Nahoru Odpovědět 2.4.2014 10:17
Největší časovou náročnost má výpočet časové náročnosti..
Avatar
1Pupik1989
Člen
Avatar
Odpovídá na Jenkings
1Pupik1989:

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í.

 
Nahoru Odpovědět 2.4.2014 16:01
Avatar
Jenkings
Redaktor
Avatar
Odpovídá na 1Pupik1989
Jenkings:

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 ;)

Nahoru Odpovědět 2.4.2014 21:18
Největší časovou náročnost má výpočet časové náročnosti..
Avatar
1Pupik1989
Člen
Avatar
Odpovídá na Jenkings
1Pupik1989:

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.

 
Nahoru Odpovědět 2.4.2014 22:33
Avatar
Jenkings
Redaktor
Avatar
Odpovídá na 1Pupik1989
Jenkings:

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 ;)

Nahoru Odpovědět 3.4.2014 11:38
Největší časovou náročnost má výpočet časové náročnosti..
Avatar
1Pupik1989
Člen
Avatar
Odpovídá na Jenkings
1Pupik1989:

A ještě to je lepší. Co jsem to pitval, tak projdou jen ty textové uzly. :D
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. :D

 
Nahoru Odpovědět 3.4.2014 12:57
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.