-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Customising The Toolbar
There are several parts to customising the toolbar;
- changing the classes/styling
- working with the plugin interface for individual toolbar buttons (referred to as tools from here on)
- working with multiple toolbars and editors
The toolbar is an implementation of Bootstraps Button Toolbar. There are 4 HTML attributes you can set on the text-angular tag to change the defaults, here is shown what the defaults are:
<div text-angular ng-model="htmlVariable" ta-toolbar-class="btn-toolbar" ta-toolbar-group-class="btn-group" ta-toolbar-button-class="btn btn-default" ta-toolbar-active-button-class="active"></div>
Converts to:
<div text-angular ...>
<div class="ta-toolbar btn-toolbar">
<div class="btn-group">
<button type="button" class="btn btn-default">...</button>
<button type="button" class="btn btn-default active">...</button>
</div>
</div>
...
</div>
The toolbar is comprised of several groups of buttons, these are defined by another HTML tag. This tag, unlike the previous ones, is a compiled tag so you can use a javascript variable or the input as in the example:
<text-angular ta-toolbar="[['h1','h2','h3'],['bold','italics']]"></text-angular>
This would output the following toolbar (simplified from full version):
...
<div class="ta-toolbar btn-toolbar">
<div class="btn-group">
<button type="button" class="btn btn-default ng-scope" unselectable="on">H1</button>
<button type="button" class="btn btn-default ng-scope" unselectable="on">H2</button>
<button type="button" class="btn btn-default ng-scope" unselectable="on">H3</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default ng-scope" unselectable="on"><i class="fa fa-bold"></i></button>
<button type="button" class="btn btn-default ng-scope" unselectable="on"><i class="fa fa-italic"></i></button>
</div>
</div>
...
The default available buttons are:
- h1
- h2
- h3
- h4
- h5
- h6
- p
- pre
- quote
- bold
- italics
- underline
- strikeThrough
- ul
- ol
- undo
- redo
- clear
- justifyLeft
- justifyCenter
- justifyRight
- justifyFull
- indent
- outdent
- html
- insertImage
- insertLink
- insertVideo
- wordcount
- charcount
The string values put into the ta-toolbar arrays are keys for tools that have been defined as shown in the next section.
All of the plugin tools are stored on the textAngularManager and should be setup with a decorator. To explain the parts of a tool I am going to show a quick tutorial on how to add a button to style the current selection red. (The wrapSelection function as used below internally calls the document.execCommand(command, false, opt)). This assumes that somewhere the following css exists .red{ color: red; }
First the javascript to create the Tool Plugin:
module.config(function($provide){
$provide.decorator('taOptions', ['taRegisterTool', '$delegate', function(taRegisterTool, taOptions){
// $delegate is the taOptions we are decorating
// register the tool with textAngular
taRegisterTool('colourRed', {
iconclass: "fa fa-square red",
action: function(){
this.$editor().wrapSelection('forecolor', 'red');
}
});
// add the button to the default toolbar definition
taOptions.toolbar[1].push('colourRed');
return taOptions;
}]);
});
Injection: textAngular has several factories that you may wish to access in your decorator. Those are injected in the angular way by adding them to the javascript code. For example (I list many of them here for clarity only):
module.config(function($provide){
$provide.decorator('taOptions', ['taRegisterTool', 'taSelection', 'taBrowserTag', 'taTranslations',
'taToolFunctions', '$delegate',
function(taRegisterTool, taSelection, taBrowserTag, taTranslations,
taToolFunctions, taOptions){
// $delegate is the taOptions we are decorating
// register the tool with textAngular
...
...
...
Note: For a full list of commands used in wrapSelection (passes through to execCommand) and their support across browsers refer to http://quirksmode.org/dom/execCommand.html an alternative reference point is MDN.
As follows is an explanation of the individual keys of the tool plugin object:
(Note that this
will always refer to the scope of the tool)
First the parameters that may be passed in:
-
action:
[function(deferred, restoreSelection)] a function that is executed on clicking on the button - this will allways be executed using ng-click and will overwrite any ng-click value in the display attribute. The function is passed a deferred object ($q.defer()), if this is wanted to be usedreturn false;
from the action and manually calldeferred.resolve();
elsewhere to notify the editor that the action has finished. restoreSelection is only defined if the rangy library is included and it can be called asrestoreSelection()
to restore the users selection in the WYSIWYG editor. -
display:
[string]? Optional, an HTML element to be displayed as the buton. Thescope
of the button is the tool definition object with some additional functions. If set this will cause buttontext and iconclass to be ignored. -
buttontext:
[string]? if this is defined it will replace the contents of the button element. -
class:
[string]? if this is defined it will replace the CSS classes of the button element. -
iconclass:
[string]? if this is defined an icon (<i>
) will be appended to the button element with this string as it's class -
activestate:
[function(commonElement)]? this function is called on every caret movement, if it returns true then the class taOptions.classes.toolbarButtonActive will be applied to thedisplay
element, else the class will be removed. If the rangy library is loaded commonElement will be an angular.element object that contains ALL of the selection. -
disabled:
[function()]? if this function returns true then the tool will have the class taOptions.classes.disabled applied to it, else it will be removed.
The functions available on the Tool scope are (ie this.
in the action, activestate or disabled functions):
-
name:
[string] the name of the tool, this is the first parameter passed into taRegisterTool -
isDisabled:
[function()] returns true if the tool is disabled, false if it isn't -
displayActiveToolClass:
[function(boolean)] returns true if the tool is 'active' in the currently focussed toolbar
Some more details on the use of the action
and activeState
functions.
action:
This function is called whenever the button is clicked. In this case we are using textAngulars wrapSelection
function which internally calls `document.execCommand('formatBlock', false, '') in our example and then updates the model.
activeState:
This is called whenever the editor is updated and/or the text cursor is moved (keyup event), the active
variable on the scope will be set to the result of this function. In this example it is difficult to detect if the cursor is in a block of red styled text so we return false.
Finally to add this new plugin tool to the example toolbar in Defining the Toolbar we do the following:
<text-angular ta-toolbar="[['h1','h2','h3'],['bold','italics','colourRed']]"></text-angular>
In textAngular 1.2.0 we have added the functionality to allow a link an editor to any number of toolbars, also a toolbar can be linked to multiple editors.
The styling attributes available for the text-angular-toolbar directive are: ta-toolbar
, ta-toolbar-class
, ta-toolbar-group-class
, ta-toolbar-button-class
, ta-toolbar-button-active-class
, ta-focussed-class
. All of these can be set on any individual toolbar or set on the text-angular directive to be placed on the automatically generated toolbar if the ta-target-toolbars
value isn't set.
NOTE: Using ta-target-toolbars="''"
or ta-toolbar="''"
will load up an editor with NO toolbar, you must input an empty string as leaving it blank is the same as omitting it due to the way angularjs evaluates attributes.
Below are two examples of how to do this:
Using multiple toolbars for one editor
<text-angular-toolbar name="toolbar1"></text-angular-toolbar>
<text-angular-toolbar name="toolbar2"></text-angular-toolbar>
<text-angular name="htmlcontent" ng-model="data.htmlcontent" ta-target-toolbars='toolbar1,toolbar2'></text-angular>
Using multiple editors for one toolbar
<text-angular-toolbar name="toolbar"></text-angular-toolbar>
<text-angular name="htmlcontent1" ng-model="data.htmlcontent1" ta-target-toolbars='toolbar'></text-angular>
<text-angular name="htmlcontent2" ng-model="data.htmlcontent2" ta-target-toolbars='toolbar'></text-angular>