Přejít k navigační liště

Zdroják » JavaScript » Tvorba moderního e-shopu: Rich-Text Editing a dokončení administrace

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

Články JavaScript

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!

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!

Komentáře

Subscribe
Upozornit na
guest
6 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
razjr

contenteditable je bohuzel nepouzitelne z duvodu hnusneho, omezeneho a mezibrowserove nekompatibilniho generovaneho kodu. Doporucuju se obloukem vyhnout a pouzit nejaky rich text editor, ktery generuje html sam a nepouziva execcommand.

Jenda

Můžete ukázat nějaký příklad? Díval jsem se na generovaný kód z dema v tomto článku. Nevidím v tom problém. Normální odstavce, seznamy, nic hnusného ani omezeného natož mezibrowserově nekompatibilního jsem tam neviděl.

razor

Tak např. v demo, ve Firefoxu 23, klikneš na text. Smažeš vše. Napíšeš „vole“ a dáš center. Firefox 23 vygeneruje:

vole

Podle mě hnusné HTML. Teď si představ, že toto uložíš např. do DB a následně to otevřeš v chrome 29. Máš sice vycentrované „vole“ ale s prázdnou řádkou navíc, která ve FF není. Podle mě nekompatibilita generovaného kódu. Toto v demo není, ale pokud by si např. chtěl měnit velikost fontu. Máš za využití execcommand k dispozici pouze 7 velikosti. Omezenost.

jjjjj

dobre, ale vidim iba „vole“

Filip Procházka

A co takový http://www.aloha-editor.org/, ten tohle nijak neřeší?

razor

S aloha nemám zkušenost. Osobně bych použil CKEditor http://ckeditor.com/

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.