nl_tokens: register an editor and the toolbars that it is affected by
pl_tokens: function ( name , scope , targetToolbars ) { // targetToolbars are optional, we don't require a toolbar to function if ( ! name || name === '' ) throw ( 'textAngular Error: An editor requires a name' ) ; if ( ! scope ) throw ( 'textAngular Error: An editor requires a scope' ) ; if ( editors [ name ] ) throw ( 'textAngular Error: An Editor with name "' + name + '" already exists' ) ; // _toolbars is an ARRAY of toolbar scopes var _toolbars = [ ] ; angular . forEach ( targetToolbars , function ( _name ) { if ( toolbars [ _name ] ) _toolbars . push ( toolbars [ _name ] ) ; // if it doesn't exist it may not have been compiled yet and it will be added later } ) ; editors [ name ] = { scope : scope , toolbars : targetToolbars , _registerToolbar : function ( toolbarScope ) { // add to the list late if ( this . toolbars . indexOf ( toolbarScope . name ) >= 0 ) _toolbars . push ( toolbarScope ) ; } , // this is a suite of functions the editor should use to update all it's linked toolbars editorFunctions : { disable : function ( ) { // disable all linked toolbars angular . forEach ( _toolbars , function ( toolbarScope ) { toolbarScope . disabled = true ; } ) ; } , enable : function ( ) { // enable all linked toolbars angular . forEach ( _toolbars , function ( toolbarScope ) { toolbarScope . disabled = <mask> ; } ) ; } , focus : function ( ) { // this should be called when the editor is focussed angular . forEach ( _toolbars , function ( toolbarScope ) { toolbarScope . _parent = scope ; toolbarScope . disabled = false ; toolbarScope . focussed = true ; scope . focussed = true ; } ) ; } , unfocus : function ( ) { // this should be called when the editor becomes unfocussed angular . forEach ( _toolbars , function ( toolbarScope ) { toolbarScope . disabled = true ; toolbarScope . focussed = false ; } ) ; scope . focussed = false ; } , updateSelectedStyles : function ( selectedElement ) { // update the active state of all buttons on liked toolbars angular . forEach ( _toolbars , function ( toolbarScope ) { angular . forEach ( toolbarScope . tools , function ( toolScope ) { if ( toolScope . activeState ) { toolbarScope . _parent = scope ; toolScope . active = toolScope . activeState ( selectedElement ) ; } } ) ; } ) ; } , sendKeyCommand : function ( event ) { // we return true if we applied an action, false otherwise var result = false ; if ( event . ctrlKey || event . metaKey ) angular . forEach ( taTools , function ( tool , name ) { if ( tool . commandKeyCode && tool . commandKeyCode === event . which ) { for ( var _t = 0 ; _t < _toolbars . length ; _t ++ ) { if ( _toolbars [ _t ] . tools [ name ] !== undefined ) { taToolExecuteAction . call ( _toolbars [ _t ] . tools [ name ] , scope ) ; result = true ; break ; } } } } ) ; return result ; } , triggerElementSelect : function ( event , element ) { // search through the taTools to see if a match for the tag is made. // if there is, see if the tool is on a registered toolbar and not disabled. // NOTE: This can trigger on MULTIPLE tools simultaneously. var elementHasAttrs = function ( _element , attrs ) { var result = true ; for ( var i = 0 ; i < attrs . length ; i ++ ) result = result && _element . attr ( attrs [ i ] ) ; return result ; } ; var workerTools = [ ] ; var unfilteredTools = { } ; var result = false ; element = angular . element ( element ) ; // get all valid tools by element name, keep track if one matches the var onlyWithAttrsFilter = false ; angular . forEach ( taTools , function ( tool , name ) { if ( tool . onElementSelect && tool . onElementSelect . element && tool . onElementSelect . element . toLowerCase ( ) === element [ 0 ] . tagName . toLowerCase ( ) && ( ! tool . onElementSelect . filter || tool . onElementSelect . filter ( element ) ) ) { // this should only end up true if the element matches the only attributes onlyWithAttrsFilter = onlyWithAttrsFilter || ( angular . isArray ( tool . onElementSelect . onlyWithAttrs ) && elementHasAttrs ( element , tool . onElementSelect . onlyWithAttrs ) ) ; if ( ! tool . onElementSelect . onlyWithAttrs || elementHasAttrs ( element , tool . onElementSelect . onlyWithAttrs ) ) unfilteredTools [ name ] = tool ; } } ) ; // if we matched attributes to filter on, then filter, else continue if ( onlyWithAttrsFilter ) { angular . forEach ( unfilteredTools , function ( tool , name ) { if ( tool . onElementSelect . onlyWithAttrs && elementHasAttrs ( element , tool . onElementSelect . onlyWithAttrs ) ) workerTools . push ( { 'name' : name , 'tool' : tool } ) ; } ) ; // sort most specific (most attrs to find) first workerTools . sort ( function ( a , b ) { return b . tool . onElementSelect . onlyWithAttrs . length - a . tool . onElementSelect . onlyWithAttrs . length ; } ) ; } else { angular . forEach ( unfilteredTools , function ( tool , name ) { workerTools . push ( { 'name' : name , 'tool' : tool } ) ; } ) ; } // Run the actions on the first visible filtered tool only if ( workerTools . length > 0 ) { for ( var _i = 0 ; _i < workerTools . length ; _i ++ ) { var tool = workerTools [ _i ] . tool ; var name = workerTools [ _i ] . name ; for ( var _t = 0 ; _t < _toolbars . length ; _t ++ ) { if ( _toolbars [ _t ] . tools [ name ] !== undefined ) { tool . onElementSelect . action . call ( _toolbars [ _t ] . tools [ name ] , event , element , scope ) ; result = true ; break ; } } if ( result ) break ; } } return result ; } } } ; return editors [ name ] . editorFunctions ; }