This behavior is in active design now - information on this page will be updated/modified.

behavior: richtext

WYSIWYG editing behavior. It allows to edit HTML and/or wiki text in WYSIWYG manner.

The richtext is aimed to be used as:

  • blog (article) editors;
  • wiki and other forms of CMS;
  • online e-mail clients;

The richtext uses so called flat DOM that is:

  1. no nested <div>s;
  2. <li> is a kind of <p> - can contain only text and spans;
  3. no nested tables;
  4. only two levels of spans are allowed - so called background (e.g. <a>) and foreground (<strong>, <em>, etc.) spans;
  5. there are no <font> elements inside the editor;
  6. limited support of CSS, e.g. no position attribute at all.

Screenshot of the sample below:

Screenshot

One more screenshot, "show rulers" mode:

richtext with rules

Floating image:

floating image

Elements

that have this behavior applied by default (see master style sheet):

  • <richtext> ..initial html.. </richtext> - richtext is intrinsically dispaly:block element.

Value

get/set_value methods (htmlayout) and value property (sciter) reflect current editing document and can be either HTML text or wiki (dokuwiki by default) format.

Editor allow images to be inserted from system clipboard so the value may contain image bits as base64 encoded chunks. Exact format will be specified later.

Attributes

that this behavior knows about:

  • tools=“css selector” - CSS selector of the element containing tool buttons/elements. See below.
  • content-style=“url” - url of style sheet that that defines list of elements supported by the instance of the editor and their styles.
  • allow-clipboard-images[=yes|no] - allows images to be inserted (pasted) from clipboard. If allowed and document contains pasted images (that have no permanent location) then bodies of such images will be emitted as:
    <script type="text/base64" id="...">
      ... base64 encoded image bits
    </script>
    elements inside the <head> section of the document.

Events

Together with the standard set of events (mouse, keyboard, focus) behavior: button generates:

  • UI_STATE_CHANED event - is sent after state of editing regiters is changed. Internal implementation updates state of bound tool buttons. Posted (asynchronous) event.
  • EDIT_VALUE_CHANGED event - value of the element was changed due to user actions. Is sent when document was updated by the user first time from intital value. Or when document is rolled back to initial state (by using undo). Posted (asynchronous) event.
  • EDIT_VALUE_CHANGING event - sent when value of the element is about to change. Synchronous event.
  • PARSE_VALUE and EMIT_VALUE - events that allow to override default value parser and value emitter.
  • BEFORE_PASTE and AFTER_PASTE events. (planned but not supported for now)
  • BEFORE_COPY and AFTER_COPY events. (planned but not supported for now)

Methods

Richtext supports following so called xcall() methods, see dom::element::xcall() function.

Basic operations and state indicators:

  • xcall(“canUndo”): bool - returns boolean wrapped into json::value, true - if undo is available and false if not;
  • xcall(“doUndo”) - executes undo operation;
  • xcall(“canRedo”): bool - returns true - if redo is available and false if not;
  • xcall(“doRedo”) - executes redo operation;
  • xcall(“canCut”): bool - returns true - if cut is available and false if not;
  • xcall(“doCut”) - executes cut operation - copy selection into the clipboard and deletes selected text;
  • xcall(“canCopy”): bool - returns true - if copy is available and false if not;
  • xcall(“doCopy”) - executes copy operation - copy selection into the clipboard;
  • xcall(“canPaste”): bool - returns true - if paste is available and false if not;
  • xcall(“doPaste”) - executes paste operation - pastes content of the the clipboard;
  • xcall(“canSelectAll”): bool - returns true - if select all[text] is available in current state and false if not;
  • xcall(“doSelectAll”) - selects all text;
  • xcall(“readOnly”): bool - returns true - if editor is in read-only mode;
  • xcall(“readOnly”, bool) - switches readOnly mode on and off;
  • xcall(“showRulers”,bool) - show/hide formatting rulers;

Load/Save, HTML or envelope

  • xcall(“loadHTML”, html:string) - replaces current content from html string;
  • xcall(“loadHTML”, html:string, base_url:string) - replaces current content from html string, uses base_url for resolution of relative urls;
  • xcall(“saveHTML”) : string - returns current content as html string;
  • xcall(“saveHTML”, baseUrl:string, mode:string ) : string - returns current content as html string; mode here accepts following values:
    • “emit-pasted-images” - emit also bodies of images that was pasted from clipboard;
    • “emit-local-images” - emit bodies of clipboard and images with urls starting from file:;
    • “emit-all-images” - emit bodies of all images used in the document.
  • xcall(“savePlainText”) : string - returns current content as plain text string;
  • xcall(“loadFile”, path:string) - replaces current content from html file given by the path;
  • xcall(“saveFile”, path:string) - saves current content to the file given by the path;
  • xcall(“saveContent”):map - saves current document as an object having following structure:
    {
     "html": html-string,
     "resources": 
       {   
         "url1": 
         { 
           data: bytes | string, // data of the resource 
           content-type: string, // mime type of the resource
           content-disposition: string, // url where this resource came from  
           id: string // uuid of the resource
         }
         ... 
       }
     }
  • xcall(“loadContent”, envelope:map) - replaces current content from the envelope object having structure d

efined above;

Navigation:

  • xcall(“moveCaretTo”, where:string, keepAnchor:true|false) - moves the caret from current position to where:
    • “next-char” - next character;
    • “prev-char” - previous character;
    • “next-word” - start of next word;
    • “prev-word” - end of previous word;
    • “doc-end” - end of the doc;
    • “doc-start” - start of the doc;
    • “line-end” - end of the line;
    • “line-start” - start of the line;
    • “line-up” - character in the previous line;
    • “line-down” - character in the next line;
    • “page-up” - previous page;
    • “page-down” - next page;

If keepAnchor is true then this function is not changing anchor position of the selection. So this sequence moveCaretTo(line-end,false); moveCaretTo(line-end,true); will set selection on current line of text.

  • xcall(“searchNext”,modes:int, word:string) - search next word entry in the text, modes is an integer - ORed combination of these flags:
    • SEARCH_FORWARD = 0x00,
    • SEARCH_BACKWARD = 0x01,
    • SEARCH_WHOLE_WORD = 0x10,
    • SEARCH_MATCH_CASE = 0x20

Edit operations and formatting:

  • xcall(“insertHtml”, string) - does insertion of html fragment contained in the string at current caret position;
  • xcall(“appendHtml”, string) - appends the html fragment to the end of the document;
  • xcall(“replaceBy”, text:string) - replaces current selection by the text, if there is no selection then inserts the text at caret position.
  • xcall(“getCurrentObjects”): array - returns array of “tagname.classname” strings - stack of current objects at the caret position;
  • xcall(“getCurrentObjectAttributes”, index:int): map - returns collection of attributes defined on element at index position in stack of current objects;
  • xcall(“setCurrentObjectAttributes”, index:int, attributes: map) - sets attributes of element at index position in stack of current objects;
  • xcall(“getCurrentStyle”): map - returns cumulative collection of CSS properties in effect at current caret position;
  • xcall(“getStyleRules”): array - returns list of CSS rules applied at current position;
  • xcall(“getStyleRule”, index:int): map - returns list of CSS properties of particular rule applied at current position;
  • xcall(“setSpan”,tag:string, attributes: undefined | map) - set span to the selection or caret position. Spans are b,strong, em, a, etc.
  • xcall(“setBlock”, tag:string, attributes: undefined | map) - set block to the selection or to current block element. tag here can accept following values: “p”,”h1”…“h6”, “pre” or two pseudo tags “ol/li” and “ul/li” for list items.
  • xcall(“setFontColor”, color:string | color) - set current color of the text by injecting <font color=…> span;
  • xcall(“setFontName”, fontFamilyName:string) - set current font name by injecting <font family=…> span;
  • xcall(“setFontSize”, fontSize:1..7) - set current font size by injecting <font size=…> span;
  • xcall(“toggleSpan”, tagName:string) - switches on/off bold/italic/underline spans by adding/removing correspondent tags;
  • xcall(“canIndentPlus”): undefined | bool - returns true or false if editor can or cannot apply indentation+. Will return undefined if context does not support indentation (e.g. inside pre).
  • xcall(“doIndentPlus”) - increases indentation;
  • xcall(“canIndentMinus”): undefined | bool - returns true or false if editor can or cannot apply indentation-. Will return undefined if context does not support indentation (e.g. inside pre).
  • xcall(“doIndentMinus”) - decreases indentation;
  • xcall(“setTextAlign”, align:int) - sets text alignment, align here is one of:
    • ALIGN_LEFT = 1,
    • ALIGN_CENTER = 2,
    • ALIGN_RIGHT = 3,
    • ALIGN_JUSTIFY = 4,
  • xcall(“setListUnordered”) - wraps selection into <UL>;
  • xcall(“setListOrdered”) - wraps selection into <OL>;

Toolbar and tool buttons binding

The richtext allows to do all editing operations by using keyboard shortcuts (see below) but for convenience it also allows to bound tool buttons (a.k.a. toolbar) with internal so called editing registers of the editor. Tools container (e.g. toolbar) may contain elements with command attribute. Such elements reflect state of internal registers and allow to modify them by clicking on them (richtext-tools handles BUTTON_PRESS behavior event). The richtext changes :checked and :disabled attributes of the tool elements so this states can be styled appropriately.

Commands that the richtext knows about so far:

Editing commands

  • command=richtext:cut
  • command=richtext:copy
  • command=richtext:paste
  • command=richtext:undo
  • command=richtext:redo

Spans

  • command=richtext:strong - either <b> or <strong>, on click <strong> span will be applied.
  • command=richtext:em - either <i> or <em>, on click <em> span will be applied.
  • command=richtext:code - either <code> or <tt>, on click <code> span will be applied.
  • command=richtext:u - <u> element.

Blocks and indentation

  • command=richtext:p - <p>, paragraph
  • command=richtext:h1
  • command=richtext:h2
  • command=richtext:h3
  • command=richtext:h4
  • command=richtext:h5
  • command=richtext:h6 - headers
  • command=richtext:pre - block of pre-formatted text (plain text block)
  • command=richtext:li-ul - item in unordered list
  • command=richtext:li-ol - item in ordered list
  • command=richtext:indent-dec - decrease indentation: either move list item one level up or unquote <blockquote>
  • command=richtext:indent-inc - increase indentation: either move list item one level deep or quote fragment by <blockquote>

Special key combinations

Formatting and text shortcuts

  • CTRL-B - apply <strong> span to selection;
  • CTRL-I - apply <em> span to selection;
  • CTRL-U - apply <u> span to selection;
  • ENTER - break paragraph into two;
  • SHIFT-ENTER - insert <br>;
  • DELETE - delete character on the right or remove selection. See also table actions below;
  • BACKSPACE - delete character on the left or remove selection. If selection is a table cell selection then cells will be merged into single cell;
  • DELETE - delete character on the right or remove selection. If selection is a table cell selection then those cells will be removed from the table;
  • CTRL-DELETE - if selection: remove foreground spans (<strong>, <em>, etc.), if no selection - remove word on the right;
  • CTRL-BACKSPACE - if selection: remove background spans (<a>, etc.), if no selection - remove word on the left;

Lists and blockquotes

  • CTRL-NUMPAD+ - indent +, either wrap selected paragraphs in <blockquote> or as sub list;
  • CTRL-NUMPAD- - indent -, either unwrap selected paragraphs from <blockquote> or move list items level up;
  • CTRL-NUMPAD. - wrap selected paragraphs to <ul>;
  • CTRL-NUMPAD0 - wrap selected paragraphs to <ol>;
  • CTRL-NUMPAD1 - CTRL-NUMPAD6 - convert selected paragraphs to <H1>-<H6>;

Table/cell specific:

  • CTRL-1 - split cell(s) by rows;
  • CTRL-2 - split cell(s) by columns;
  • CTRL-3 - insert column before current;
  • CTRL-4 - insert column after current;
  • DELETE - delete cells. If whole row(s) or column(s) are selected then thye will be deleted. Otherwise cells will be merged into one and cleared;
  • BACKSPACE - merge cells. Merge selected cells into single cell;

Context Menu

By default <richtext> and <textarea>/<plaintext> are defined as this:

  richtext 
  {
    behavior:richtext;
    context-menu:url(res:behavior-richtext-menu.htm); 
    ...
  }
  texarea, plaintext 
  {
    behavior:plaintext; 
    context-menu:url(res:behavior-text-menu.htm); 
    ...
  }

context-menu:url(…) there means that context menu is located at address res:behavior-richtext-menu.htm.

Therefore if you need to provide your own version (e.g. localized) of these menus you can:

  1. Either to handle HLN/SCN_LOAD_DATA request and provide your own content when you will get request for res:behavior-richtext-menu.htm ans res:behavior-text-menu.htm or
  2. to modify styling for your element to something like this:

  richtext 
  {
    behavior:richtext;
    context-menu:selector( menu#for-richtext); 
    ...
  }

In this case you will need to declare such <menu id=“for-richtext”> element somewhere in your markup:

 <menu .context #for-richtext >
  <li command="richtext:undo"
	  style="foreground-image:url(res:edit-undo.png)"
	  >Undo<span .accesskey>Ctrl+Z</span></li>
  <hr/>
  <li command="richtext:cut" 
	  style="foreground-image:url(res:edit-cut.png)"
	  >Cut<span .accesskey>Ctrl+X</span></li>
  ...
 </menu>

Here is default content of Richtext Context Menu and Plaintext Context Menu. Note attribute command in menu items - it is used as command identifier for the behavior. Other portions of the markup can be changed but not command's.

HTML sample

Here is a sample of <richtext> and toolbar integration in HTML:

 <div .editor>
    <widget .toolbar>
      <widget .tb-button command=richtext:cut   title="Cut"><img src="res:edit-cut.png" /></widget>
      <widget .tb-button command=richtext:copy  title="Copy"><img src="res:edit-copy.png" /></widget>
      <widget .tb-button command=richtext:paste title="Paste"><img src="res:edit-paste.png" /></widget>
      <hr/>
      <widget .tb-button command=richtext:undo  title="Undo"><img src="res:edit-undo.png" /></widget>
      <widget .tb-button command=richtext:redo  title="Redo"><img src="res:edit-redo.png" /></widget>
      <hr/>      
      <widget .tb-button   command=richtext:strong  title="Strong emphasis"><b>B</b></widget>
      <widget .tb-button   command=richtext:em  title="Emphasis"><i>I</i></widget>
      <widget .tb-button   command=richtext:code  title="Code"><tt style="font-size:9px">code</tt></widget>
      <hr/>      
      <widget .tb-button   command=richtext:p  title="Paragraph"><b>P</b></widget>
      <widget .tb-button.h command=richtext:h1 title="Header 1">H<b>1</b></widget>
      <widget .tb-button.h command=richtext:h2 title="Header 2">H<b>2</b></widget>
      <widget .tb-button.h command=richtext:h3 title="Header 3">H<b>3</b></widget>
      <widget .tb-button.h command=richtext:h4 title="Header 4">H<b>4</b></widget>
      <hr/>      
      <widget .tb-button command=richtext:pre title="Block of plain text, pre"><tt>pre</tt></b></widget>
      <hr/>      
      <widget .tb-button command=richtext:li-ul title="List item, unordered list">ul</widget>
      <widget .tb-button command=richtext:li-ol title="List item, unordered list">ol</widget>
      <widget .tb-button command=richtext:indent-dec title="Increase level of list item or quote">i-</widget>
      <widget .tb-button command=richtext:indent-inc title="Decrease level of list item or un-quote">i+</widget>
   </widget>
   <richtext toolbar="widget.toolbar" >
      Hello <i>richtext</i> world!
   </richtext>
 </div>

[tbc]

h-smile/built-in-behaviors/richtext.txt · Last modified: 2011/12/02 11:29 by andrew
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0