-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implementation
This is a work in progress and will evolve as I (@jrguenther) spelunk the code base. If others want to join in the effort, you are most welcome.
Navigation
- left - move cursor one character to left
- right - move cursor one character to right
Delete
- backspace - deletes backward
- delete - deletes forward
- control + d - deletes forward
- control + h - deletes backward
Line Breaks
- control + o - inserts line break
- return - insert line break
Modify Indent
- tab - increase indent level
- ⇧ shift + tab - decrease indent level
Selection
- ⇧ shift + right -expand selection right
- ⇧ shift + left - expand selection left
When the trix.js code is included on your site and you add a <trix-editor>
element to your HTML, the element will be automatically initialized. This is done by running registerElement
in elements/trix_editor_element.coffee
. The element is initially styled using the default CSS provide by the element registration. Creating the element creates an instance of the EditorController
, which takes care of initializing the editor and hooking up its event listeners.
After the element is instantiated, the element listens for keyboard and mouse events. As the events stream in, the InputController
handles them and delegates back to the EditorController
as needed. To make this tour less abstract, let's take the example of typing the character "A" into the editor.
In the constructor of the InputController
, event handlers are created for each event in the defined in @events
.
# Create event handlers for all input events
for eventName of @events
handleEvent eventName, onElement: @element, withCallback: @handlerFor(eventName), inPhase: "capturing"
@handlerFor
is called for each event in @events
(a giant object definition at the bottom of the definition). In @handlerFor
@handleInput
is called:
handlerFor: (eventName) ->
(event) =>
@handleInput ->
unless innerElementIsActive(@element)
@eventName = eventName
@events[eventName].call(this, event)
This is where the magic 🎆 happens. If the event is handled without error, EditorController
is notified that the InputController
has handled the event by calling @delegate?.inputControllerDidHandleInput()
handleInput: (callback) ->
try
@delegate?.inputControllerWillHandleInput()
callback.call(this)
finally
@delegate?.inputControllerDidHandleInput()
inputControllerDidHandleInput
requests the element be rendered.
In EditorController
:
inputControllerDidHandleInput: ->
@handlingInput = false
if @requestedRender
@requestedRender = false
@render()
The implementation makes heavy use of the delegate pattern.
Events are handled with a combination of code run in InputController
and EditorController
. In some cases, InputController
delegates back to EditorController
. EditorController
acts as a delegate for the SelectionManager
, Composition
, InputController
, AttachmentManager
, and ToolbarController
. If delegate?.method
is called, chances are you will find the implementation in EditorController
.
Trix.ObjectView
Provides base rendering methods
Subclasses:
Each of the subclasses is responsible for creating the HTMLElement
s needed to display the block.
Trix.PieceView
Trix.DocumentView
Trix.ObjectGroupView
Trix.TextView
Trix.BlockView
-
Trix.AttachmentView
Trix.PreviewableAttachmentView