nl_tokens: / * istanbul ignore next : all browser specifics and PhantomJS dosen t seem to support half of it
pl_tokens: function ( $window , $document , taDOM ) { // need to dereference the document else the calls don't work correctly var _document = $document [ 0 ] ; var rangy = $window . rangy ; var brException = function ( element , offset ) { /* check if selection is a BR element at the beginning of a container. If so, get
  		* the parentNode instead.
  		* offset should be zero in this case. Otherwise, return the original
  		* element.
  		*/ if ( element . tagName && element . tagName . match ( / ^br$ / i ) && offset === 0 && ! element . previousSibling ) { return { element : element . parentNode , offset : 0 } ; } else { return { element : element , offset : offset } ; } } ; var api = { getSelection : function ( ) { var range = rangy . getSelection ( ) . getRangeAt ( 0 ) ; var container = range . commonAncestorContainer ; var selection = { start : brException ( range . startContainer , range . startOffset ) , end : brException ( range . endContainer , range . endOffset ) , collapsed : range . collapsed } ; // Check if the container is a text node and return its parent if so container = container . nodeType === 3 ? container . parentNode : container ; if ( container . parentNode === selection . start . <mask> || container . parentNode === selection . end . element ) { selection . container = container . parentNode ; } else { selection . container = container ; } return selection ; } , getOnlySelectedElements : function ( ) { var range = rangy . getSelection ( ) . getRangeAt ( 0 ) ; var container = range . commonAncestorContainer ; // Check if the container is a text node and return its parent if so container = container . nodeType === 3 ? container . parentNode : container ; return range . getNodes ( [ 1 ] , function ( node ) { return node . parentNode === container ; } ) ; } , // Some basic selection functions getSelectionElement : function ( ) { return api . getSelection ( ) . container ; } , setSelection : function ( el , start , end ) { var range = rangy . createRange ( ) ; range . setStart ( el , start ) ; range . setEnd ( el , end ) ; rangy . getSelection ( ) . setSingleRange ( range ) ; } , setSelectionBeforeElement : function ( el ) { var range = rangy . createRange ( ) ; range . selectNode ( el ) ; range . collapse ( true ) ; rangy . getSelection ( ) . setSingleRange ( range ) ; } , setSelectionAfterElement : function ( el ) { var range = rangy . createRange ( ) ; range . selectNode ( el ) ; range . collapse ( false ) ; rangy . getSelection ( ) . setSingleRange ( range ) ; } , setSelectionToElementStart : function ( el ) { var range = rangy . createRange ( ) ; range . selectNodeContents ( el ) ; range . collapse ( true ) ; rangy . getSelection ( ) . setSingleRange ( range ) ; } , setSelectionToElementEnd : function ( el ) { var range = rangy . createRange ( ) ; range . selectNodeContents ( el ) ; range . collapse ( false ) ; if ( el . childNodes && el . childNodes [ el . childNodes . length - 1 ] && el . childNodes [ el . childNodes . length - 1 ] . nodeName === 'br' ) { range . startOffset = range . endOffset = range . startOffset - 1 ; } rangy . getSelection ( ) . setSingleRange ( range ) ; } , // from http://stackoverflow.com/questions/6690752/insert-html-at-caret-in-a-contenteditable-div // topNode is the contenteditable normally, all manipulation MUST be inside this. insertHtml : function ( html , topNode ) { var parent , secondParent , _childI , nodes , startIndex , startNodes , endNodes , i , lastNode , _tempFrag ; var element = angular . element ( "<div>" + html + "</div>" ) ; var range = rangy . getSelection ( ) . getRangeAt ( 0 ) ; var frag = _document . createDocumentFragment ( ) ; var children = element [ 0 ] . childNodes ; var isInline = true ; if ( children . length > 0 ) { // NOTE!! We need to do the following: // check for blockelements - if they exist then we have to split the current element in half (and all others up to the closest block element) and insert all children in-between. // If there are no block elements, or there is a mixture we need to create textNodes for the non wrapped text (we don't want them spans messing up the picture). nodes = [ ] ; for ( _childI = 0 ; _childI < children . length ; _childI ++ ) { if ( ! ( ( children [ _childI ] . nodeName . toLowerCase ( ) === 'p' && children [ _childI ] . innerHTML . trim ( ) === '' ) || // empty p element ( children [ _childI ] . nodeType === 3 && children [ _childI ] . nodeValue . trim ( ) === '' ) // empty text node ) ) { isInline = isInline && ! BLOCKELEMENTS . test ( children [ _childI ] . nodeName ) ; nodes . push ( children [ _childI ] ) ; } } for ( var _n = 0 ; _n < nodes . length ; _n ++ ) lastNode = frag . appendChild ( nodes [ _n ] ) ; if ( ! isInline && range . collapsed && / ^(|<br(|\/)>)$ / i . test ( range . startContainer . innerHTML ) ) range . selectNode ( range . startContainer ) ; } else { isInline = true ; // paste text of some sort lastNode = frag = _document . createTextNode ( html ) ; } // Other Edge case - selected data spans multiple blocks. if ( isInline ) { range . deleteContents ( ) ; } else { // not inline insert if ( range . collapsed && range . startContainer !== topNode ) { if ( range . startContainer . innerHTML && range . startContainer . innerHTML . match ( / ^<[^>]*>$ / i ) ) { // this log is to catch when innerHTML is something like `<img ...>` parent = range . startContainer ; if ( range . startOffset === 1 ) { // before single tag range . setStartAfter ( parent ) ; range . setEndAfter ( parent ) ; } else { // after single tag range . setStartBefore ( parent ) ; range . setEndBefore ( parent ) ; } } else { // split element into 2 and insert block element in middle if ( range . startContainer . nodeType === 3 && range . startContainer . parentNode !== topNode ) { // if text node parent = range . startContainer . parentNode ; secondParent = parent . cloneNode ( ) ; // split the nodes into two lists - before and after, splitting the node with the selection into 2 text nodes. taDOM . splitNodes ( parent . childNodes , parent , secondParent , range . startContainer , range . startOffset ) ; // Escape out of the inline tags like b while ( ! VALIDELEMENTS . test ( parent . nodeName ) ) { angular . element ( parent ) . after ( secondParent ) ; parent = parent . parentNode ; var _lastSecondParent = secondParent ; secondParent = parent . cloneNode ( ) ; // split the nodes into two lists - before and after, splitting the node with the selection into 2 text nodes. taDOM . splitNodes ( parent . childNodes , parent , secondParent , _lastSecondParent ) ; } } else { parent = range . startContainer ; secondParent = parent . cloneNode ( ) ; taDOM . splitNodes ( parent . childNodes , parent , secondParent , undefined , undefined , range . startOffset ) ; } angular . element ( parent ) . after ( secondParent ) ; // put cursor to end of inserted content range . setStartAfter ( parent ) ; range . setEndAfter ( parent ) ; if ( / ^(|<br(|\/)>)$ / i . test ( parent . innerHTML . trim ( ) ) ) { range . setStartBefore ( parent ) ; range . setEndBefore ( parent ) ; angular . element ( parent ) . remove ( ) ; } if ( / ^(|<br(|\/)>)$ / i . test ( secondParent . innerHTML . trim ( ) ) ) angular . element ( secondParent ) . remove ( ) ; if ( parent . nodeName . toLowerCase ( ) === 'li' ) { _tempFrag = _document . createDocumentFragment ( ) ; for ( i = 0 ; i < frag . childNodes . length ; i ++ ) { element = angular . element ( '<li>' ) ; taDOM . transferChildNodes ( frag . childNodes [ i ] , element [ 0 ] ) ; taDOM . transferNodeAttributes ( frag . childNodes [ i ] , element [ 0 ] ) ; _tempFrag . appendChild ( element [ 0 ] ) ; } frag = _tempFrag ; if ( lastNode ) { lastNode = frag . childNodes [ frag . childNodes . length - 1 ] ; lastNode = lastNode . childNodes [ lastNode . childNodes . length - 1 ] ; } } } } else { range . deleteContents ( ) ; } } range . insertNode ( frag ) ; if ( lastNode ) { api . setSelectionToElementEnd ( lastNode ) ; } } } ; return api ; }