FCKeditor a AJAX - problém s GetData a jeho řešení

9. listopadu 2008

Programování

Sobotní den pro mě byl ve znamení programování, konkrétně jsem se zabýval úpravami FCKeditoru pro použití na stránce Vyplňto.cz. Kromě specifického ukládání souborů do databáze (pochlubím se později) jsem potřeboval zejména zajistit průběžné ukládání editovaného obsahu na server přes ajax, protože to je jedním ze základních pilířů ovládání Vyplňto.cz (minimalizace klikání na jakákoli tlačítka, žádné odesílání formulářů, vymizení problému s expirací seance při psaní delších textů).

Řešení a opravný kód na konci článku.

Objevil se však nečekaný problém – jakmile jsem pomocí FCKeditorAPI a funkce GetData (popř. starších GetHTML nebo GetXHTML) přečetl obsah FCKeditoru, rázem přestaly v Internet Exploreru (verze 6 i 7) fungovat některé základní formátovací funkce – např. tučné, skloněné a podtržené písmo (core styles - bold, italic, underline). Jako přesvědčený uživatel IE jsem samozřejmě nad tímto problémem nemohl mávnout rukou a rozhodl se ho vyřešit.

Po delším googlení se mi podařilo nalézt jedno vlákno, které dokázalo, že v tomto problému (bug 2156, bug 2092) nejsem sám. Bohužel jsem napoprvé zcela neporozuměl nabízenému řešení, a tak jsem zkusil více či méně krkolomné metody, které k požadovanému cíli nevedly.

Jako první mě napadlo šáhnout na zdroj HTML klasicky přes DOM, respektive pomocí následující konstrukce:

window.FCKeditorAPI.GetInstance('id').EditorDocument.body.innerHTML

Přestože formátování začalo opět fungovat, nebyl jsem s výsledkem spokojen. Výsledný HTML kód byl totiž dost prasácký a neupravený.

Dále mě napadla ďábelsky hrozná myšlenka – mít FCKeditory na stránce dva, přičemž v jednom by probíhala editace, ve druhém (schovaném) bych prováděl vyčištění kódu a nevadilo by mi, že v něm formátování nefunguje. Prostě překopírovávat periodicky surové HTML z jednoho editoru do druhého a potom volat GetData. Naštěstí se mi to nepodařilo zrealizovat kvůli problémům s FCKeditorAPI – z neznámého důvodu se zaregistroval vždycky jen jeden editor (id měl samozřejmě každý editor svůj).

Až po několika hodinách ladění, během nichž jsem prolezl stovky řádků zdrojového kódu FCKeditoru a postupně zakomentovával jednotlivé příkazy ve snaze identifikovat zdroj chyby, mě napadlo se jednoduše přes výše uvedený kousek kódu podívat na skutečný obsah editovaného dokumentu po zavolání GetData.

Ukázalo se, že zatímco GetData vrací docela hezký HTML kód, skutečný obsah editovaného dokumentu v IFRAME je zaneřáděný pomocnými atributy XHTML parseru _fckxhtmljob. Programátoři zřejmě nepočítali s tím, že by po přečtení obsahu ještě někdo chtěl něco editovat (popř. to jsou IE ignoranti), přítomnost tohoto atributu má bohužel z hlediska další editace dost fatální důsledky.

Řešení

Řešení pomocí jednoduchého a rychlého innerHTML.replace('_fckxhtmljob','') způsobuje zbytečné problémy se ztrátou fokusu kurzoru, pokud se však atributy rekurzivně odstraní pomocí Javascript DOM, funguje vše konečně hladce a s rozumným zatížením procesoru (u mého notebooku méně než 10% u běžně dlouhých textů). Pro získání HTML kódu z FCKeditoru můžete použít následující kód:

var kod=window.FCKeditorAPI.GetInstance('id').GetData();
rstJob(window.FCKeditorAPI.GetInstance('id').EditorDocument.body);


function rstJob(obj) {
  if(obj._fckxhtmljob) {
    obj.attributes.removeNamedItem('_fckxhtmljob');
  }
  if(obj.childNodes.length>0) {
    for(i=0;i
      rstJob(obj.childNodes[i]);
    }
  }
}

Bonusový problém - nefungující event OnSelectionChange v IE

U elementu TEXTAREA jsem si na Vyplňto dopřál ten luxus, že odesílám jeho obsah na server několik desítek milisekund po posledním zdvihu klávesy (onkeyup + timeout). Měl jsem velkou snahu docílit podobného chování i u FCKeditoru, bohužel se ukázalo, že event OnSelectionChange (vyvolaný vždy po jakékoli změně, nebo přesněji jakékoli události myši nebo klávesnice) funguje spolehlivě pouze ve Firefoxu a je tím pádem nepoužitelný. V oficiální dokumentaci se píše, že bylo volání OnSelectionChange pro IE příliš náročné a při rychlejším psaní docházelo k pádům. Proto přistoupili k pouze náhodnému vyvolání této události (dle mého pozorování cca 1:20). Generátor tohoto náhodného mechanismu se mi nalézt nepodařilo a upřímně řečeno jsem ho ani příliš dlouho nehledal – poslední, co potřebuji je, aby FCKeditor padal :-)

Jako nejspolehlivější řešení se nakonec ukázal timer, který každých cca 250 ms proleze všechny FCKeditory na stránce, a v případě zjištěné změny odešle obsah na server. Kód již brzy v praxi uvidíte na Vyplňto...

 

Publikováno dne 09. 11. 2008 v kategorii Programování Odhadnutá klíčová slova BETA: fckeditor | ajax | getdata | fckeditor GetData | problem | fckeditor ajax | html | ukládání | fckeditorapi
Mohlo by Vás zajímat BETA: CPU 100%, nefunkční klávesnice a touchpad

O kategorii Programování

V nejodbornější kategorii tohoto blogu jsou zařazeny články s mými programátorskými zkušenostmi získanými několikaletou praxí tvorby stránek a java aplikací pro mobilní telefony.

Komentáře k článku

POZOR: K článku zatím nebyl vložen žádný komentář, takže s velkou pravděpodobností nikoho neurazil, nikoho nepobavil a už vůbec nikomu nepomohl.

Přidat vlastní komentář:
Jméno:
E-mail:
Sledovat diskusi:
Web:
Kontrolní kód:

Komentáře jsou v prvé řadě určeny ke kladení dotazů k tématu, upozornění na chybu, rozšíření obsahu článku a vůbec ke zpětné reakci na obsah těchto stránek. Mé reakce jsou barevně odlišeny.

V současné době není umožněno vkládat HTML tagy - pokud vložíte HTML kód, bude převeden na entity. K Vašemu komentáři se do databáze uloží čas vložení a Vaše aktuální IP adresa (54.163.22.209). IP adresa se nebude zobrazovat čtenářům, nicméně v případě, že bude Váš odkaz shledán právně závadným, může být Vaše IP adresa předána příslušným státním orgánům. Emailové adresy jsou ochráněny před běžnými spam roboty.

© Marek Demčák 2007 - 2018
Všechna práva dle Autorského zákona (č. 121/2000 Sb.) vyhrazena.