Tvorba moderního e-shopu: Rich-Text Editing a dokončení administrace

Používáte na svých stránkách WYSIWYG? Před několika lety mohlo být jeho přidání do stránek poměrně obtížné. Díky HTML atributu contenteditable si však jednoduchý WYSIWYG můžete vytvořit snadno sami!

Seriál: E-shop pomocí moderních technologií (15 dílů)

  1. Úvodní analýza pro moderní e-shop 4.1.2013
  2. Návrh uživatelské části e-shopu 11.1.2013
  3. Tvorba uživatelské části e-shopu 18.1.2013
  4. Nákupní košík pomocí HTML5 Web Storage 25.1.2013
  5. Tvorba moderního eshopu: kategorie a parametrické hledání 1.2.2013
  6. Tvorba moderního e-shopu: dokončení uživatelské části 8.2.2013
  7. Tvorba moderního e-shopu: plánování administrace 15.2.2013
  8. Tvorba moderního e-shopu: správa objednávek 22.2.2013
  9. Tvorba moderního e-shopu: nahrávání obrázků k produktu 1.3.2013
  10. Tvorba moderního e-shopu: Bower, Yeoman a Gemnasium 15.7.2013
  11. Tvorba moderního e-shopu: HTML5 drag & drop a kategorie 29.7.2013
  12. Tvorba moderního e-shopu: zpracování chyb 12.8.2013
  13. Tvorba moderního e-shopu: Rich-Text Editing a dokončení administrace 26.8.2013
  14. Autentizace v single-page aplikacích 9.9.2013
  15. Autentizace v single-page aplikacích – serverová část 7.10.2013

Všechny zdrojové kódy jsou na Githubu a můžete si je stáhnout příkazem git checkout -f eshop013. Dnes je také dostupné demo již hotového frontendu.

Rich-Text editor

Rich-Text editor umožňuje to samé co WYSIWYG (= what you see is what you get, co vidíš, to dostaneš) editor. Tento druh editace budeme potřebovat při úpravě popisku textu k vybranému produktu. Zde určitě nebude stačit pouze jednoduchý element textarea. Zákazník nejspíš bude požadovat možnost nějakou sekvenci textu zvýraznit tučně nebo kurzívou, bude chtít do textu vložit třeba obrázky atd.

Samozřejmě je zde velké množství hotových WYSIWYG editorů a v praxi byste asi nic takového programovat tedy nechtěli. Nicméně cílem toho seriálu je také ukázat možnosti HTML5 a zrovna atribut contenteditable je něco, co nejspíš patří k těm méně známým možnostem jazyka. Navíc se můžete dostat do situace, kdy budete potřebovat editaci něčeho přesně na míru a dnes se můžete přesvědčit, že naprogramovat něco takového není nic složitého.

Trocha teorie úvodem

Základem všeho je atribut contenteditable, jehož hodnotou může být true (povolena inline editace elementu), false nebo inherit (nastavení je zděděno od rodiče). Pokud má daný element tento atribut nastaven na true, pak je možné editovat jeho obsah stejně jako text uvnitř elementu textarea, avšak navíc máme neomezené možnosti formátování.

Atribut je překvapivě dobře podporován všemi současnými prohlížeči. Jako první s ním přišel Internet Explorer již ve verzi 5.5. Kromě editace části dokumentu je ještě dostupný atribut designMode, který dovolí editaci celé stránky.

Jakmile má nějaký HTML element nastaveno povolení editace, můžeme snadno měnit text, který se uvnitř nachází. Mnohem zajímavější je však možnost daný text formátovat, jak jsme zvyklí třeba z MS Word. Jak na to?

Nad editovatelnou oblast přidáme tlačítka, každé pro nějakou akci. Zarovnání do seznamu, odsazení, převod textu na kurzívu atd. Jakmile uživatel zaznačí kurzorem sekvenci znaků v editovatelné oblasti a klikne na nějaké tlačítko, stačí zavolat příkaz document.execCommand() a předat parametry pro konkrétní akci. A to je vše! Nic víc není potřeba. Jeden příkaz v JavaScriptu a máte vlastní WYSIWYG editor!

Takto vypadá nejjednodušší WYSIWYG pouze s možností převést text na kurzívu:

<button onclick="document.execCommand('italic')">Kurzíva</button>
<div contenteditable="true"> Nějaký text ... </div>

Metoda execCommand() přijímá tři parametry, důležitý je první a poslední, druhý parametr některé prohlížeče jako např. Firefox nepodporují. První parametr je název dané akce. Např. „bold“ pro tučné písmo, „italic“ pro kurzívu ap. Poslední parametr jsou pak další doplňující informace. To je potřeba např. pro vytvoření odkazu, kdy jako třetí parametr bude předáno URL. Implementace některých příkazů může být tedy o něco složitější, v případě odkazu se použije třeba metoda window.prompt(), kam uživatel napíše, kam má odkaz směřovat a tento odkaz se pak předá jako onen třetí parametr.

Prohlížeče podporují velké množství možností formátování, kompletní seznam je uveden na MDN.

Direktiva wysiwyg

Protože pravděpodobně budeme tuto možnost editace chtít využít i na jiných projektech, měli bychom ji vytvořit jako samostatnou direktivu. Direktiva bude velmi podobná direktivě inline, kterou jsme dělali v dřívějších dílech seriálu. Vytvoříme nový element wysiwyg, který bude mít dva parametry: model (která data budeme editovat) a action (jaká událost se zavolá po editaci). Do detailu produktu tedy přidáme tento zápis:

<wysiwyg model="product.text" action="update"></wysiwyg>

Nejprve celý kód direktivy, který si vzápětí vysvětlíme:

angular.module('zdrojak.directive').directive('wysiwyg', ['$window', function($window){
  var imgs = {
    undo: 'data ...',
    redo: 'data ...',
    bold: 'data ...',
    italic: 'data ...',
    justifyleft: 'data ...',
    justifycenter: 'data ...',
    justifyright: 'data ...',
    insertorderedlist: 'data ...',
    insertunorderedlist: 'data ...',
    formatblock: 'data ...',
    outdent: 'data ...',
    indent: 'data ...',
    createlink: 'data ...'
  };

  var template = '<div>';
  template += '<div ng-hide="showEditor" ng-bind-html-unsafe="model" ng-click="showEditor=true"></div>';
  template += '<div ng-show="showEditor">';
  template += '<p>';

  for (var cmd in imgs) {
    template += '<img ng-click="command(\'' + cmd + '\')" src="' + imgs[cmd] + '" />';
  }

  template += '</p>';
  template += '</div>';
  template += '<div class="editor-window" ng-show="showEditor" contenteditable="true" ng-bind-html-unsafe="model"></div>';
  template += '<p ng-show="showEditor"><button ng-click="close()">Uložit</button></p>';   
  template += '</div>';

  var config = {
    scope: {
      model: '=',
      action: '='
    },
    restrict: 'E',
    template: template,
    replace: true,
    link: function(scope, element) {

      scope.close = function() {
        scope.showEditor = false;
        scope.model = element[0].querySelector('.editor-window').innerHTML;
        scope.action();
      };

      scope.command = function(cmd) {
        var args = null;
        switch (cmd) {
          case 'formatblock':
            args = 'blockquote';
            break;
          case 'createlink':
            args = $window.prompt("Vložte adresu odkazu");
            break;
          default:
            console.log('Unknown command: ' + cmd);
            break;
        }
        $window.document.execCommand(cmd, null, args);
      };
    }
  };

  return config;
}]);

Náš WYSIWYG editor podporuje několik akcí: zpět, dopředu, tučné písmo, kurzíva, zarovnat doleva/na střed/doprava atd. Proměnná imgs obsahuje pro každou tuto událost ikonku s daty kódovanými v base64 (v ukázce data nejsou, kompletní zdrojový kód direktivy je ale na Githubu). Vytvoří se HTML kód a pak se definuje samotná direktiva.

Při nahrání stránky se zobrazí naformátovaný text, pokud uživatel na direktivu klikne, zobrazí se nad textem všechny možnosti editace a pod editovatelným textem tlačítko Uložit. Pokud na toto tlačítko uživatel klikne, zavolá se akce uvedená v atributu action. Pokud uživatel klikne na nějaké tlačítko pro formátování textu, vyvolá se metoda command(), která pro některé akce přidá další parametry.

wysiwyg

Nakonec bude stejně nejlepší, pokud si editaci vyzkoušíte sami přímo v demoverzi.

Dokončení administrace

Kromě implementace WYSIWYG byla dokončena celá administrace. V rámci úprav ale nebylo potřeba znát nic, co by již v seriálu popsáno nebylo.

Co dále

Klientskou část máme zdárně hotovou. Ještě se k ní několikrát krátce vrátíme, především při implementaci přihlašování a real-time sledování zákazníků pomocí socket.io.

Celý e-shop máme hotový. Teď ho můžeme podrobně projít se zákazníkem, provádět uživatelské testování, ptát se budoucích uživatelů, co by mělo být jinak. V této fázi je zahrnutí změn extrémně jednoduché, stačí jen lehce upravit mock data v Apiary. To je o poznání rychlejší než upravovat schéma databáze při každé změně.

Všimněte si také, že až do této chvíle jsme se vůbec nemuseli zabývat úvahami, jaký jazyk použijeme na serverové části a dokonce ani jakou použijeme databázi. Teď však máme přesné schéma API a víme přesně, jaké budou na aplikaci požadavky, což na začátku nemusí být vůbec zřejmé. Mluvím z vlastní zkušenosti, kdy jsem u jednoho projektu zvažoval, že použiji grafovou databázi Neo4J, která by se mohla pro projekt dobře hodit, protože se však jednalo o velmi experimentální projekt a zadání se neustále měnilo, nemohl jsem si být jejím výběrem jistý. A nejspíš si lze dobře představit, kolik času by stálo předělat celou aplikaci z grafové databáze na klasickou SQL, pokud by se výběr ukázal jako chybný, což v případě vývoje aplikace stejným způsobem jako zdejší e-shop nehrozí.

Příští díl bude věnován atraktivnímu tématu, které se k single-page aplikacím váže, a to autentizaci a autorizaci. Začneme také s implementací serverové části v Node.js.

Na závěr ještě přikládám orientační rozvrh dalších článků v rámci seriálu.

Na tvorbě tohoto článku se svými připomínkami podílel také Pavel Lang. Díky!

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 6

Přehled komentářů

razjr contenteditable - hnus generovaneho kodu.
Jenda Re: contenteditable - hnus generovaneho kodu.
razor xxx
jjjjj Re: xxx
Filip Procházka Hnusne vygenerovane HTML
razor Re: Hnusne vygenerovane HTML
Zdroj: https://www.zdrojak.cz/?p=9598