Zjištění pozice v textu JavaScriptem

Školení, která pořádám

Někdy je potřeba JavaScriptem zjistit, kde v <textarea> se nachází kurzor – třeba pro nabídnutí kontextové nabídky k aktuálnímu řádku textu. Ve Firefoxu je to velmi jednoduché – existuje vlastnost textarea.selectionStart, která přesně tuto informaci poskytuje. V Internet Exploreru to je složitější – na webu je řada návodů, jak tuto pozici krkolomně zjistit. Viděl jsem pokus vypočítat tuto pozici z pixelů vrácených vlastností offsetTop nebo doplnění nesmyslného textu na místo kurzoru a následné zjištění jeho pozice metodou findText. Přitom když se člověk zamyslí, je to poměrně jednoduché i v IE – stačí začátek označení posunout na začátek textu a zjistit rozdíl délek označeného textu:

var range = document.selection.createRange();
var len = range.text.length;
range.moveStart('textedit', -1);
var selectionStart = range.text.length - len;

Problém s tímto kódem je v tom, že metoda moveStart nás přesune na začátek celého dokumentu, nejen vstupního políčka, takže kód funguje jen pokud je vstupní políčko na začátku dokumentu.

Na závěr povzdychnutí

Škoda, že neexistuje obdoba Wikipedie pro algoritmy. Samozřejmě existuje spousta knihoven útržků kódu, tam je ale i hromada balastu a autoritativní zdroj chybí. Takovým by se mohla stát knihovna, do které by se dalo nejen snadno přidávat, ale také z ní mazat případně alespoň oponovat existujícím ukázkám. Takhle až někdo bude hledat řešení tohoto problému, tak nejspíš stejně jako já najde zase ty krkolomné návody a přímočařejší postup, který nejspíš kromě mě vymyslela i řada programátorů přede mnou, mu nejspíš unikne. A kdybych na krkolomné návody odkázal, tak jejich autoritu ještě posílím …

Přijďte si o tomto tématu popovídat na školení JavaScript a AJAX.

Jakub Vrána, Dobře míněné rady, 17.9.2007, diskuse: 12 (nové: 0)

Diskuse

ikona finc:

Jiste by to bylo zajimave. Ovsem, kdyz nekdo zacne v JS psat vetsi "myslenky", tak si vetsinou JS dost zprotivi :)
Navic k pouzivani JS by se mel vydavat zbrojni pas. Kdyz se obcas podivas, co vsechno lide cpou do JS, tak je to k zbliti.
Osobne by se mi vice libili alternativy. Jinymi slovy, co nejde udelat pomoci html-css, udela se pomoci JS.
Kdysi jsem si myslel, ze se casem tyto veci tak nejak standardizuji. Dnes uz vim, ze takova situace asi nikdy nenastane. Proto je stale potreba validovat kod na X druhu prohlizecu, coz muze byt dost frustrujici :(

Honza M.:

Tisíceré díky, pane. Já to zjišťoval vložením nesmyslného textu a indexOfem.

Honza M.:

var backup = textarea.value;
var ieSelection = document.selection.createRange();
var bookmark = "[~Z~A~L~O~Z~K~A~]";
var selectedText = ieSelection.text;
ieSelection.text = bookmark + selectedText;
var start = textarea.value.indexOf(bookmark);
var end = start + selectedText.length;
textarea.value = backup;

Přemejšlim. Nevim, jestli to bez milosti zahodit.

ikona MiSHAK:

Dělal jsem to před dvěma léty :) (jako že to nemusí všude fungovat, ale jede i v Opeře 9.5 Alpha a MSIE 7.
Licence: GNU
Vloží před a za vybraný text resp. kurzor obsah before a after. Po aplikaci tvého kódu by měl fungovat i v IE při vkládání, když není vybraný text.

function paste(textareaID, before, after, KeepSelection){
var ta = document.getElementById(textareaID);
ta.focus();
if(!(document.selection.createRange)&&(ta.selectionStart)&&(ta.selectionEnd)){//Mozilla
  ss = ta.selectionStart;
  se = ta.selectionEnd;
  xt = ta.value;
  out = xt.substring(0, ss)+before;
  if(KeepSelection) out += xt.substring(ss, se);
  out += after+xt.substring(se, xt.length);
  ta.value = out;
  }
else if(document.selection&&document.selection.createRange){//MSIE
  r = document.selection.createRange();
  if(r.text != ''){
   out = before;
   if(KeepSelection) out += r.text;
   out += after;
   r.text = out;
   }
  else ta.value += before+after;
  }//ELSE Stuff MSIE lower etc...
else ta.value += before+after;
ta.focus();
}

ikona Jakub Hejda:

Další zajímavý návod.
Jste taková WIKI kódie :) jednoho člověka.

ikona Jozef Šandor:

Trochu OT, ale moja RSS citacka v opere zobrazila tag < textarea > z uvodu clanku nie ako text, ale ako objekt formualara. V pripade, ze je tomu tak aj v inych pripadoch nebolo by na skodu to opravit.

ikona Jakub Vrána OpenID:

V RSS 0.91 je značka <description> definovaná jako textová. Že to čtečky chápou jako HTML, je jejich chyba (byť nejspíš vynucená syndikacemi, kde se to zrovna takhle používá). Pro jednoznačnou interpretaci doporučuji Atom: http://php.vrana.cz/atom.php.

ikona Marty:

Chtěl jsem si zkusit udělat ukázku a v IE6 (není nejnověji záplatovaná, je to verze z SP2) jsem narazil na takový drobný problém se zjišťováním pozice
více viz demo: http://martinvseticka.eu/zdrojaky/js-pozice/
(Nejsem odborník na JS, možná je tam někde triviální chyba, ale já jí nevidím.)

Roman Šitina:

ano, právě touhle vlastností trpí většina metod, které jsou na internetu k nalezení - tj. nefunguje spolehlivě, pokud je před textareou nějaký další text... osobně se mi nepodařilo najít 100% funkční řešení :(

Jan Škrášek:

Onen vytoužený zdroj - knihovnu - zprovozní do Vánoc (snad) portál programu¨jte.com

mj41:

Nehodí se na to přímo MediaWiki? Můžu to zprovoznit třeba hned  samozřejmě s pluginem 'source', viz. např.
http://mj41.cz/wiki/Seky_a_sk%C5%99eky

Kvakoš:

To je pro Javascript typické, hezký nástroj, který ale není vždy na 100% zapnutý. Takže na něj nelze spoléhat a web by měl fungovat i bez něj. Z toho vyplývá, že může pouze web přikrášlit, ale neměla by na něm stát vlastní funkcionalita. Na mnoha webech je Javascript vyloženě na škodu, protože dobrý web může být i bez JS.

Mě osobně studium JS zabralo dost času a nakonec jsem dospěl k názoru - čím méně JS, tím lépe. Design jako takový řešit CSS a když to CSS nevyřeší, udělat design takový, aby to CSS vyřešit šlo. Klíčem k dobrému webu je CSS a nikoliv JS (mám na mysli běžný web, ne nějaké speciality).

Fakt opravdu málokdy je vidět web, kde JS výrazně zvedne užitnou hodnotu, zato je mnoho webů, kde je JS nevhodně použit a při jeho vypnutí je web zcela nefunkční (např. lze vidět odkazy ve stylu <a href="javascript:location.replace(...);" ... >...</a>

Pár svých těžce odladěných kódů, bych někam rád umístil k použití v širší komunitě (když už jsem v tom spálil tolik času), aby se to vůbec nějak vyplatilo.

Navštívil jsem nedávno nějaký web se stovkami free JS ke stažení, ale byla to typicky sbírka odstrašujících příkladů, co by si člověk nikdy do webu dát neměl.

Jakub má pravdu, že je důležité vystavené kódy recenzovat a zveřejnit použitelnost. Jsem pro.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.