'' - can contain only text and spans;
- no nested tables;
- only two levels of spans are allowed - so called //background// (e.g. '''') and foreground ('''', '''', etc.) spans;
- there are no elements inside the editor;
- limited support of CSS, e.g. no //position// attribute at all.
Screenshot of the sample below:
{{h-smile:built-in-behaviors:richtext.jpg|Screenshot}}
One more screenshot, [[h-smile:built-in-behaviors:richtext-rules|"show rulers" mode]]:
{{h-smile:built-in-behaviors:rictext-tables.jpg|richtext with rules}}
Floating image:
{{h-smile:built-in-behaviors:richtext-img.jpg|floating image}}
===== Elements =====
that have this behavior applied by default (see [[master style sheet]]):
* '' , 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
elements inside the '''' 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 '''' span;
* ''xcall("setFontName", fontFamilyName:string)'' - set current font name by injecting '''' span;
* ''xcall("setFontSize", fontSize:1..7)'' - set current font size by injecting '''' 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 '''';
* ''xcall("setListOrdered")'' - wraps selection into ''
'';
===== 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 or , on click span will be applied.
* ''command=richtext:em'' - either or , on click span will be applied.
* ''command=richtext:code'' - either ''
'' or , on click '''' span will be applied.
* ''command=richtext:u'' - element.
==== Blocks and indentation ====
* ''command=richtext:p'' -
* ''command=richtext:indent-inc'' - increase indentation: either move list item one level deep or quote fragment by
===== Special key combinations =====
==== Formatting and text shortcuts ====
* ''CTRL-B'' - apply span to selection;
* ''CTRL-I'' - apply span to selection;
* ''CTRL-U'' - apply span to selection;
* ''ENTER'' - break paragraph into two;
* ''SHIFT-ENTER'' - insert
;
* ''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 (, , etc.), if no selection - remove word on the right;
* ''CTRL-BACKSPACE'' - if selection: remove background spans (, etc.), if no selection - remove word on the left;
==== Lists and blockquotes ====
* ''CTRL-NUMPAD+'' - indent +, either wrap selected paragraphs in or as sub list;
* ''CTRL-NUMPAD-'' - indent -, either unwrap selected paragraphs from
or move list items level up;
* ''CTRL-NUMPAD.'' - wrap selected paragraphs to
;
* ''CTRL-NUMPAD0'' - wrap selected paragraphs to
;
* ''CTRL-NUMPAD1'' - ''CTRL-NUMPAD6'' - convert selected paragraphs to
-
;
==== 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 ''