2019-03-28 16:49:22 +00:00
( function ( factory ) { if ( typeof define === 'function' && define . amd ) { define ( [ 'jquery' ] , factory ) ; } else if ( typeof module === 'object' && module . exports ) { module . exports = function ( root , jQuery ) { if ( jQuery === undefined ) { if ( typeof window !== 'undefined' ) { jQuery = require ( 'jquery' ) ; }
2016-05-19 18:35:40 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
2019-03-28 16:49:22 +00:00
return factory ( jQuery ) ; } ; } else { factory ( window . jQuery ) ; } } ( function ( $ ) { var FE = function ( element , options ) { this . id = ++ $ . FE . ID ; var presets = { }
if ( options && options . documentReady ) { presets . toolbarButtons = [ 'fullscreen' , 'undo' , 'redo' , 'getPDF' , 'print' , '|' , 'bold' , 'italic' , 'underline' , 'color' , 'clearFormatting' , '|' , 'alignLeft' , 'alignCenter' , 'alignRight' , 'alignJustify' , '|' , 'formatOL' , 'formatUL' , 'indent' , 'outdent' , '-' , 'paragraphFormat' , '|' , 'fontFamily' , '|' , 'fontSize' , '|' , 'insertLink' , 'insertImage' , 'quote' ]
presets . paragraphFormatSelection = true
presets . fontFamilySelection = true
presets . fontSizeSelection = true
presets . placeholderText = ''
presets . quickInsertEnabled = false
presets . charCounterCount = false }
this . opts = $ . extend ( true , { } , $ . extend ( { } , FE . DEFAULTS , presets , typeof options == 'object' && options ) ) ; var opts _string = JSON . stringify ( this . opts ) ; $ . FE . OPTS _MAPPING [ opts _string ] = $ . FE . OPTS _MAPPING [ opts _string ] || this . id ; this . sid = $ . FE . OPTS _MAPPING [ opts _string ] ; $ . FE . SHARED [ this . sid ] = $ . FE . SHARED [ this . sid ] || { } ; this . shared = $ . FE . SHARED [ this . sid ] ; this . shared . count = ( this . shared . count || 0 ) + 1 ; this . $oel = $ ( element ) ; this . $oel . data ( 'froala.editor' , this ) ; this . o _doc = element . ownerDocument ; this . o _win = 'defaultView' in this . o _doc ? this . o _doc . defaultView : this . o _doc . parentWindow ; var c _scroll = $ ( this . o _win ) . scrollTop ( ) ; this . $oel . on ( 'froala.doInit' , $ . proxy ( function ( ) { this . $oel . off ( 'froala.doInit' ) ; this . doc = this . $el . get ( 0 ) . ownerDocument ; this . win = 'defaultView' in this . doc ? this . doc . defaultView : this . doc . parentWindow ; this . $doc = $ ( this . doc ) ; this . $win = $ ( this . win ) ; if ( ! this . opts . pluginsEnabled ) this . opts . pluginsEnabled = Object . keys ( $ . FE . PLUGINS ) ; if ( this . opts . initOnClick ) { this . load ( $ . FE . MODULES ) ; this . $el . on ( 'touchstart.init' , function ( ) { $ ( this ) . data ( 'touched' , true ) ; } ) ; this . $el . on ( 'touchmove.init' , function ( ) { $ ( this ) . removeData ( 'touched' ) ; } )
this . $el . on ( 'mousedown.init touchend.init dragenter.init focus.init' , $ . proxy ( function ( e ) { if ( e . type == 'touchend' && ! this . $el . data ( 'touched' ) ) { return true ; }
if ( e . which === 1 || ! e . which ) { this . $el . off ( 'mousedown.init touchstart.init touchmove.init touchend.init dragenter.init focus.init' ) ; this . load ( $ . FE . MODULES ) ; this . load ( $ . FE . PLUGINS ) ; var target = e . originalEvent && e . originalEvent . originalTarget ; if ( target && target . tagName == 'IMG' ) $ ( target ) . trigger ( 'mousedown' ) ; if ( typeof this . ul == 'undefined' ) this . destroy ( ) ; if ( e . type == 'touchend' && this . image && e . originalEvent && e . originalEvent . target && $ ( e . originalEvent . target ) . is ( 'img' ) ) { setTimeout ( $ . proxy ( function ( ) { this . image . edit ( $ ( e . originalEvent . target ) ) ; } , this ) , 100 ) ; }
this . ready = true ; this . events . trigger ( 'initialized' ) ; } } , this ) ) ; this . events . trigger ( 'initializationDelayed' ) ; }
else { this . load ( $ . FE . MODULES ) ; this . load ( $ . FE . PLUGINS ) ; $ ( this . o _win ) . scrollTop ( c _scroll ) ; if ( typeof this . ul == 'undefined' ) this . destroy ( ) ; this . ready = true ; this . events . trigger ( 'initialized' ) ; } } , this ) ) ; this . _init ( ) ; } ; FE . DEFAULTS = { initOnClick : false , pluginsEnabled : null } ; FE . MODULES = { } ; FE . PLUGINS = { } ; FE . VERSION = '2.9.3' ; FE . INSTANCES = [ ] ; FE . OPTS _MAPPING = { } ; FE . SHARED = { } ; FE . ID = 0 ; FE . prototype . _init = function ( ) { var tag _name = this . $oel . prop ( 'tagName' ) ; if ( this . $oel . closest ( 'label' ) . length >= 1 ) { console . warn ( 'Note! It is not recommended to initialize the Froala Editor within a label tag.' ) ; }
var initOnDefault = $ . proxy ( function ( ) { if ( tag _name != 'TEXTAREA' ) { this . _original _html = ( this . _original _html || this . $oel . html ( ) ) ; }
this . $box = this . $box || this . $oel ; if ( this . opts . fullPage ) this . opts . iframe = true ; if ( ! this . opts . iframe ) { this . $el = $ ( '<div></div>' ) ; this . el = this . $el . get ( 0 ) ; this . $wp = $ ( '<div></div>' ) . append ( this . $el ) ; this . $box . html ( this . $wp ) ; this . $oel . trigger ( 'froala.doInit' ) ; }
else { this . $iframe = $ ( '<iframe src="about:blank" frameBorder="0">' ) ; this . $wp = $ ( '<div></div>' ) ; this . $box . html ( this . $wp ) ; this . $wp . append ( this . $iframe ) ; this . $iframe . get ( 0 ) . contentWindow . document . open ( ) ; this . $iframe . get ( 0 ) . contentWindow . document . write ( '<!DOCTYPE html>' ) ; this . $iframe . get ( 0 ) . contentWindow . document . write ( '<html><head></head><body></body></html>' ) ; this . $iframe . get ( 0 ) . contentWindow . document . close ( ) ; this . $el = this . $iframe . contents ( ) . find ( 'body' ) ; this . el = this . $el . get ( 0 ) ; this . $head = this . $iframe . contents ( ) . find ( 'head' ) ; this . $html = this . $iframe . contents ( ) . find ( 'html' ) ; this . iframe _document = this . $iframe . get ( 0 ) . contentWindow . document ; this . $oel . trigger ( 'froala.doInit' ) ; } } , this ) ; var initOnTextarea = $ . proxy ( function ( ) { this . $box = $ ( '<div>' ) ; this . $oel . before ( this . $box ) . hide ( ) ; this . _original _html = this . $oel . val ( ) ; this . $oel . parents ( 'form' ) . on ( 'submit.' + this . id , $ . proxy ( function ( ) { this . events . trigger ( 'form.submit' ) ; } , this ) ) ; this . $oel . parents ( 'form' ) . on ( 'reset.' + this . id , $ . proxy ( function ( ) { this . events . trigger ( 'form.reset' ) ; } , this ) ) ; initOnDefault ( ) ; } , this ) ; var initOnA = $ . proxy ( function ( ) { this . $el = this . $oel ; this . el = this . $el . get ( 0 ) ; this . $el . attr ( 'contenteditable' , true ) . css ( 'outline' , 'none' ) . css ( 'display' , 'inline-block' ) ; this . opts . multiLine = false ; this . opts . toolbarInline = false ; this . $oel . trigger ( 'froala.doInit' ) ; } , this )
var initOnImg = $ . proxy ( function ( ) { this . $el = this . $oel ; this . el = this . $el . get ( 0 ) ; this . opts . toolbarInline = false ; this . $oel . trigger ( 'froala.doInit' ) ; } , this )
var editInPopup = $ . proxy ( function ( ) { this . $el = this . $oel ; this . el = this . $el . get ( 0 ) ; this . opts . toolbarInline = false ; this . $oel . on ( 'click.popup' , function ( e ) { e . preventDefault ( ) ; } )
this . $oel . trigger ( 'froala.doInit' ) ; } , this )
if ( this . opts . editInPopup ) editInPopup ( ) ; else if ( tag _name == 'TEXTAREA' ) initOnTextarea ( ) ; else if ( tag _name == 'A' ) initOnA ( ) ; else if ( tag _name == 'IMG' ) initOnImg ( ) ; else if ( tag _name == 'BUTTON' || tag _name == 'INPUT' ) { this . opts . editInPopup = true ; this . opts . toolbarInline = false ; editInPopup ( ) ; }
else { initOnDefault ( ) ; } }
FE . prototype . load = function ( module _list ) { for ( var m _name in module _list ) { if ( module _list . hasOwnProperty ( m _name ) ) { if ( this [ m _name ] ) continue ; if ( $ . FE . PLUGINS [ m _name ] && this . opts . pluginsEnabled . indexOf ( m _name ) < 0 ) continue ; this [ m _name ] = new module _list [ m _name ] ( this ) ; if ( this [ m _name ] . _init ) { this [ m _name ] . _init ( ) ; if ( this . opts . initOnClick && m _name == 'core' ) { return false ; } } } } }
FE . prototype . destroy = function ( ) { this . destroying = true ; this . shared . count -- ; this . events . $off ( ) ; var html = this . html . get ( ) ; if ( this . opts . iframe ) { this . events . disableBlur ( )
this . win . focus ( ) ; this . events . enableBlur ( ) }
this . events . trigger ( 'destroy' , [ ] , true ) ; this . events . trigger ( 'shared.destroy' , undefined , true ) ; if ( this . shared . count === 0 ) { for ( var k in this . shared ) { if ( this . shared . hasOwnProperty ( k ) ) { this . shared [ k ] == null ; $ . FE . SHARED [ this . sid ] [ k ] = null ; } }
delete $ . FE . SHARED [ this . sid ] ; }
this . $oel . parents ( 'form' ) . off ( '.' + this . id ) ; this . $oel . off ( 'click.popup' ) ; this . $oel . removeData ( 'froala.editor' ) ; this . $oel . off ( 'froalaEditor' ) ; this . core . destroy ( html ) ; $ . FE . INSTANCES . splice ( $ . FE . INSTANCES . indexOf ( this ) , 1 ) ; }
$ . fn . froalaEditor = function ( option ) { var arg _list = [ ] ; for ( var i = 0 ; i < arguments . length ; i ++ ) { arg _list . push ( arguments [ i ] ) ; }
if ( typeof option == 'string' ) { var returns = [ ] ; this . each ( function ( ) { var $this = $ ( this ) ; var editor = $this . data ( 'froala.editor' ) ; if ( ! editor ) { return console . warn ( 'Editor should be initialized before calling the ' + option + ' method.' ) ; }
var context ; var nm ; if ( option . indexOf ( '.' ) > 0 && editor [ option . split ( '.' ) [ 0 ] ] ) { if ( editor [ option . split ( '.' ) [ 0 ] ] ) { context = editor [ option . split ( '.' ) [ 0 ] ] ; }
nm = option . split ( '.' ) [ 1 ] ; }
else { context = editor ; nm = option . split ( '.' ) [ 0 ] }
if ( context [ nm ] ) { var returned _value = context [ nm ] . apply ( editor , arg _list . slice ( 1 ) ) ; if ( returned _value === undefined ) { returns . push ( this ) ; }
else if ( returns . length === 0 ) { returns . push ( returned _value ) ; } }
else { return $ . error ( 'Method ' + option + ' does not exist in Froala Editor.' ) ; } } ) ; return ( returns . length == 1 ) ? returns [ 0 ] : returns ; }
else if ( typeof option === 'object' || ! option ) { return this . each ( function ( ) { var editor = $ ( this ) . data ( 'froala.editor' ) ; if ( ! editor ) { var that = this ; new FE ( that , option ) ; } } ) ; } }
$ . fn . froalaEditor . Constructor = FE ; $ . FroalaEditor = FE ; $ . FE = FE ; $ . FE . XS = 0 ; $ . FE . SM = 1 ; $ . FE . MD = 2 ; $ . FE . LG = 3 ; var x = 'a-z\\u0080-\\u009f\\u00a1-\\uffff0-9-_\.' ; $ . FE . LinkRegExCommon = '[' + x + ']{1,}' ; $ . FE . LinkRegExEnd = '((:[0-9]{1,5})|)(((\\/|\\?|#)[a-z\\u00a1-\\uffff0-9@?\\|!^=%&\/~+#-\\\'*-_{}]*)|())' ; $ . FE . LinkRegExTLD = '((' + $ . FE . LinkRegExCommon + ')(\\.(com|net|org|edu|mil|gov|co|biz|info|me|dev)))' ; $ . FE . LinkRegExHTTP = '((ftp|http|https):\\/\\/' + $ . FE . LinkRegExCommon + ')' ; $ . FE . LinkRegExAuth = '((ftp|http|https):\\/\\/[\\u0021-\\uffff]{1,}@' + $ . FE . LinkRegExCommon + ')' ; $ . FE . LinkRegExWWW = '(www\\.' + $ . FE . LinkRegExCommon + '\\.[a-z0-9-]{2,24})' ; $ . FE . LinkRegEx = '(' + $ . FE . LinkRegExTLD + '|' + $ . FE . LinkRegExHTTP + '|' + $ . FE . LinkRegExWWW + '|' + $ . FE . LinkRegExAuth + ')' + $ . FE . LinkRegExEnd ; $ . FE . LinkProtocols = [ 'mailto' , 'tel' , 'sms' , 'notes' , 'data' ] ; $ . FE . MAIL _REGEX = /.+@.+\..+/i ; $ . FE . MODULES . helpers = function ( editor ) { function _ieVersion ( ) { var rv = - 1 ; var ua ; var re ; if ( navigator . appName == 'Microsoft Internet Explorer' ) { ua = navigator . userAgent ; re = new RegExp ( 'MSIE ([0-9]{1,}[\\.0-9]{0,})' ) ; if ( re . exec ( ua ) !== null )
rv = parseFloat ( RegExp . $1 ) ; }
else if ( navigator . appName == 'Netscape' ) { ua = navigator . userAgent ; re = new RegExp ( 'Trident/.*rv:([0-9]{1,}[\\.0-9]{0,})' ) ; if ( re . exec ( ua ) !== null )
rv = parseFloat ( RegExp . $1 ) ; }
return rv ; }
function _browser ( ) { var browser = { } ; var ie _version = _ieVersion ( ) ; if ( ie _version > 0 ) { browser . msie = true ; }
else { var ua = navigator . userAgent . toLowerCase ( ) ; var match = /(edge)[ \/]([\w.]+)/ . exec ( ua ) || /(chrome)[ \/]([\w.]+)/ . exec ( ua ) || /(webkit)[ \/]([\w.]+)/ . exec ( ua ) || /(opera)(?:.*version|)[ \/]([\w.]+)/ . exec ( ua ) || /(msie) ([\w.]+)/ . exec ( ua ) || ua . indexOf ( 'compatible' ) < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/ . exec ( ua ) || [ ] ; var matched = { browser : match [ 1 ] || '' , version : match [ 2 ] || '0' } ; if ( match [ 1 ] ) browser [ matched . browser ] = true ; if ( browser . chrome ) { browser . webkit = true ; }
else if ( browser . webkit ) { browser . safari = true ; } }
if ( browser . msie ) browser . version = ie _version ; return browser ; }
function isIOS ( ) { return /(iPad|iPhone|iPod)/g . test ( navigator . userAgent ) && ! isWindowsPhone ( ) ; }
function isAndroid ( ) { return /(Android)/g . test ( navigator . userAgent ) && ! isWindowsPhone ( ) ; }
function isBlackberry ( ) { return /(Blackberry)/g . test ( navigator . userAgent ) ; }
function isWindowsPhone ( ) { return /(Windows Phone)/gi . test ( navigator . userAgent ) ; }
function isMobile ( ) { return isAndroid ( ) || isIOS ( ) || isBlackberry ( ) ; }
function requestAnimationFrame ( ) { return window . requestAnimationFrame || window . webkitRequestAnimationFrame || window . mozRequestAnimationFrame || function ( callback ) { window . setTimeout ( callback , 1000 / 60 ) ; } ; }
function getPX ( val ) { return parseInt ( val , 10 ) || 0 ; }
function screenSize ( ) { var $test = $ ( '<div class="fr-visibility-helper"></div>' ) . appendTo ( 'body:first' ) ; try { var size = getPX ( $test . css ( 'margin-left' ) ) ; $test . remove ( ) ; return size ; }
catch ( ex ) { return $ . FE . LG ; } }
function isTouch ( ) { return ( 'ontouchstart' in window ) || window . DocumentTouch && document instanceof DocumentTouch ; }
function isURL ( url ) { if ( ! /^(https?:|ftps?:|)\/\//i . test ( url ) ) return false ; url = String ( url ) . replace ( /</g , '%3C' ) . replace ( />/g , '%3E' ) . replace ( /"/g , '%22' ) . replace ( / /g , '%20' ) ; var test _reg = new RegExp ( '^' + $ . FE . LinkRegExHTTP + $ . FE . LinkRegExEnd + '$' , 'gi' ) ; return test _reg . test ( url ) ; }
function isEmail ( url ) { if ( /^(https?:|ftps?:|)\/\//i . test ( url ) ) { return false ; }
return $ . FE . MAIL _REGEX . test ( url ) ; }
function sanitizeURL ( url ) { var local _path = /^([A-Za-z]:(\\){1,2}|[A-Za-z]:((\\){1,2}[^\\]+)+)(\\)?$/i ; if ( /^(https?:|ftps?:|)\/\//i . test ( url ) ) { return url ; }
else if ( local _path . test ( url ) ) { return url ; }
else if ( new RegExp ( '^(' + $ . FE . LinkProtocols . join ( '|' ) + '):\\/\\/' , 'i' ) . test ( url ) ) { return url ; }
else { url = encodeURIComponent ( url ) . replace ( /%23/g , '#' ) . replace ( /%2F/g , '/' ) . replace ( /%25/g , '%' ) . replace ( /mailto%3A/gi , 'mailto:' ) . replace ( /file%3A/gi , 'file:' ) . replace ( /sms%3A/gi , 'sms:' ) . replace ( /tel%3A/gi , 'tel:' ) . replace ( /notes%3A/gi , 'notes:' ) . replace ( /data%3Aimage/gi , 'data:image' ) . replace ( /blob%3A/gi , 'blob:' ) . replace ( /%3A(\d)/gi , ':$1' ) . replace ( /webkit-fake-url%3A/gi , 'webkit-fake-url:' ) . replace ( /%3F/g , '?' ) . replace ( /%3D/g , '=' ) . replace ( /%26/g , '&' ) . replace ( /&/g , '&' ) . replace ( /%2C/g , ',' ) . replace ( /%3B/g , ';' ) . replace ( /%2B/g , '+' ) . replace ( /%40/g , '@' ) . replace ( /%5B/g , '[' ) . replace ( /%5D/g , ']' ) . replace ( /%7B/g , '{' ) . replace ( /%7D/g , '}' ) ; }
return url ; }
function isArray ( obj ) { return obj && ! ( obj . propertyIsEnumerable ( 'length' ) ) && typeof obj === 'object' && typeof obj . length === 'number' ; }
function RGBToHex ( rgb ) { function hex ( x ) { return ( '0' + parseInt ( x , 10 ) . toString ( 16 ) ) . slice ( - 2 ) ; }
try { if ( ! rgb || rgb === 'transparent' ) return '' ; if ( /^#[0-9A-F]{6}$/i . test ( rgb ) ) return rgb ; rgb = rgb . match ( /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/ ) ; return ( '#' + hex ( rgb [ 1 ] ) + hex ( rgb [ 2 ] ) + hex ( rgb [ 3 ] ) ) . toUpperCase ( ) ; }
catch ( ex ) { return null ; } }
function HEXtoRGB ( hex ) { var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i ; hex = hex . replace ( shorthandRegex , function ( m , r , g , b ) { return r + r + g + g + b + b ; } ) ; var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i . exec ( hex ) ; return result ? 'rgb(' + parseInt ( result [ 1 ] , 16 ) + ', ' + parseInt ( result [ 2 ] , 16 ) + ', ' + parseInt ( result [ 3 ] , 16 ) + ')' : '' ; }
var default _alignment ; function getAlignment ( $block ) { var alignment = ( $block . css ( 'text-align' ) || '' ) . replace ( /-(.*)-/g , '' ) ; if ( [ 'left' , 'right' , 'justify' , 'center' ] . indexOf ( alignment ) < 0 ) { if ( ! default _alignment ) { var $div = $ ( '<div dir="' + ( editor . opts . direction == 'rtl' ? 'rtl' : 'auto' ) + '" style="text-align: ' + editor . $el . css ( 'text-align' ) + '; position: fixed; left: -3000px;"><span id="s1">.</span><span id="s2">.</span></div>' ) ; $ ( 'body:first' ) . append ( $div ) ; var l1 = $div . find ( '#s1' ) . get ( 0 ) . getBoundingClientRect ( ) . left ; var l2 = $div . find ( '#s2' ) . get ( 0 ) . getBoundingClientRect ( ) . left ; $div . remove ( ) ; default _alignment = l1 < l2 ? 'left' : 'right' ; }
alignment = default _alignment ; }
return alignment ; }
var is _mac = null ; function isMac ( ) { if ( is _mac == null ) { is _mac = navigator . platform . toUpperCase ( ) . indexOf ( 'MAC' ) >= 0 ; }
return is _mac ; }
function _scopeShim ( ) { function overrideNodeMethod ( prototype , methodName ) { var oldMethod = prototype [ methodName ] ; prototype [ methodName ] = function ( query ) { var nodeList ; var gaveId = false ; var gaveContainer = false ; if ( query && query . match ( scopeRE ) ) { query = query . replace ( scopeRE , '' ) ; if ( ! this . parentNode ) { container . appendChild ( this ) ; gaveContainer = true ; }
var parentNode = this . parentNode ; if ( ! this . id ) { this . id = 'rootedQuerySelector_id_' + ( new Date ( ) ) . getTime ( ) ; gaveId = true ; }
nodeList = oldMethod . call ( parentNode , '#' + this . id + ' ' + query ) ; if ( gaveId ) { this . id = '' ; }
if ( gaveContainer ) { container . removeChild ( this ) ; }
return nodeList ; }
else { return oldMethod . call ( this , query ) ; } } ; }
var container = editor . o _doc . createElement ( 'div' ) ; try { container . querySelectorAll ( ':scope *' ) ; }
catch ( e ) { var scopeRE = /^\s*:scope/gi ; overrideNodeMethod ( Element . prototype , 'querySelector' ) ; overrideNodeMethod ( Element . prototype , 'querySelectorAll' ) ; overrideNodeMethod ( HTMLElement . prototype , 'querySelector' ) ; overrideNodeMethod ( HTMLElement . prototype , 'querySelectorAll' ) ; } }
function scrollTop ( ) { if ( editor . o _win . pageYOffset ) return editor . o _win . pageYOffset ; if ( editor . o _doc . documentElement && editor . o _doc . documentElement . scrollTop )
return editor . o _doc . documentElement . scrollTop ; if ( editor . o _doc . body . scrollTop ) return editor . o _doc . body . scrollTop ; return 0 ; }
function scrollLeft ( ) { if ( editor . o _win . pageXOffset ) return editor . o _win . pageXOffset ; if ( editor . o _doc . documentElement && editor . o _doc . documentElement . scrollLeft )
return editor . o _doc . documentElement . scrollLeft ; if ( editor . o _doc . body . scrollLeft ) return editor . o _doc . body . scrollLeft ; return 0 ; }
function _closestShim ( ) { if ( ! Element . prototype . matches ) { Element . prototype . matches = Element . prototype . msMatchesSelector || Element . prototype . webkitMatchesSelector ; }
if ( ! Element . prototype . closest ) { Element . prototype . closest = function ( s ) { var el = this ; var ancestor = this ; if ( ! ancestor ) return null ; if ( ! document . documentElement . contains ( el ) ) return null ; do { if ( ancestor . matches ( s ) ) return ancestor ; ancestor = ancestor . parentElement ; } while ( ancestor !== null ) ; return null ; } } }
function isInViewPort ( el ) { var rect = el . getBoundingClientRect ( ) ; rect = { top : Math . round ( rect . top ) , bottom : Math . round ( rect . bottom ) } ; return ( ( rect . top >= 0 && rect . bottom <= ( window . innerHeight || document . documentElement . clientHeight ) ) || ( rect . top <= 0 && rect . bottom >= ( window . innerHeight || document . documentElement . clientHeight ) ) ) ; }
function _init ( ) { editor . browser = _browser ( ) ; _scopeShim ( ) ; _closestShim ( ) ; }
return { _init : _init , isIOS : isIOS , isMac : isMac , isAndroid : isAndroid , isBlackberry : isBlackberry , isWindowsPhone : isWindowsPhone , isMobile : isMobile , isEmail : isEmail , requestAnimationFrame : requestAnimationFrame , getPX : getPX , screenSize : screenSize , isTouch : isTouch , sanitizeURL : sanitizeURL , isArray : isArray , RGBToHex : RGBToHex , HEXtoRGB : HEXtoRGB , isURL : isURL , getAlignment : getAlignment , scrollTop : scrollTop , scrollLeft : scrollLeft , isInViewPort : isInViewPort } }
$ . FE . MODULES . events = function ( editor ) { var _events = { } ; var _do _blur ; function _assignEvent ( $el , evs , handler ) { $on ( $el , evs , handler ) ; }
function _forPaste ( ) { _assignEvent ( editor . $el , 'cut copy paste beforepaste' , function ( e ) { trigger ( e . type , [ e ] ) ; } ) ; }
function _forElement ( ) { _assignEvent ( editor . $el , 'click mouseup mousedown touchstart touchend dragenter dragover dragleave dragend drop dragstart' , function ( e ) { trigger ( e . type , [ e ] ) ; } ) ; on ( 'mousedown' , function ( ) { for ( var i = 0 ; i < $ . FE . INSTANCES . length ; i ++ ) { if ( $ . FE . INSTANCES [ i ] != editor && $ . FE . INSTANCES [ i ] . popups && $ . FE . INSTANCES [ i ] . popups . areVisible ( ) ) { $ . FE . INSTANCES [ i ] . $el . find ( '.fr-marker' ) . remove ( ) ; } } } ) }
function _forKeys ( ) { _assignEvent ( editor . $el , 'keydown keypress keyup input' , function ( e ) { trigger ( e . type , [ e ] ) ; } ) ; }
function _forWindow ( ) { _assignEvent ( editor . $win , editor . _mousedown , function ( e ) { trigger ( 'window.mousedown' , [ e ] ) ; enableBlur ( ) ; } ) ; _assignEvent ( editor . $win , editor . _mouseup , function ( e ) { trigger ( 'window.mouseup' , [ e ] ) ; } ) ; _assignEvent ( editor . $win , 'cut copy keydown keyup touchmove touchend' , function ( e ) { trigger ( 'window.' + e . type , [ e ] ) ; } ) ; }
function _forDocument ( ) { _assignEvent ( editor . $doc , 'dragend drop' , function ( e ) { trigger ( 'document.' + e . type , [ e ] ) ; } ) }
function focus ( do _focus ) { var info ; if ( typeof do _focus == 'undefined' ) do _focus = true ; if ( ! editor . $wp ) return false ; if ( editor . helpers . isIOS ( ) ) { editor . $win . get ( 0 ) . focus ( ) ; var offsetY = editor . $win . scrollTop ( ) === 0 ? 1 : editor . $win . scrollTop ( ) ; window . scrollTo ( 0 , offsetY ) ; }
if ( editor . core . hasFocus ( ) ) { return false ; }
if ( ! editor . core . hasFocus ( ) && do _focus ) { var st = editor . $win . scrollTop ( ) ; if ( editor . browser . msie && editor . $box ) editor . $box . css ( 'position' , 'fixed' ) ; if ( editor . browser . msie && editor . $wp ) editor . $wp . css ( 'overflow' , 'visible' ) ; if ( editor . browser . msie && editor . $sc ) editor . $sc . css ( 'position' , 'fixed' ) ; disableBlur ( ) ; editor . $el . focus ( ) ; editor . events . trigger ( 'focus' ) ; enableBlur ( ) ; if ( editor . browser . msie && editor . $sc ) editor . $sc . css ( 'position' , '' ) ; if ( editor . browser . msie && editor . $box ) editor . $box . css ( 'position' , '' ) ; if ( editor . browser . msie && editor . $wp ) editor . $wp . css ( 'overflow' , 'auto' ) ; if ( st != editor . $win . scrollTop ( ) ) { editor . $win . scrollTop ( st ) ; }
info = editor . selection . info ( editor . el ) ; if ( ! info . atStart ) { return false ; } }
if ( ! editor . core . hasFocus ( ) || editor . $el . find ( '.fr-marker' ) . length > 0 ) { return false ; }
info = editor . selection . info ( editor . el ) ; if ( info . atStart && editor . selection . isCollapsed ( ) ) { if ( editor . html . defaultTag ( ) != null ) { var marker = editor . markers . insert ( ) ; if ( marker && ! editor . node . blockParent ( marker ) ) { $ ( marker ) . remove ( ) ; var element = editor . $el . find ( editor . html . blockTagsQuery ( ) ) . get ( 0 ) ; if ( element ) { $ ( element ) . prepend ( $ . FE . MARKERS ) ; editor . selection . restore ( ) ; } }
else if ( marker ) { $ ( marker ) . remove ( ) ; } } } }
var focused = false ; function _forFocus ( ) { _assignEvent ( editor . $el , 'focus' , function ( e ) { if ( blurActive ( ) ) { focus ( false ) ; if ( focused === false ) { trigger ( e . type , [ e ] ) ; } } } ) ; _assignEvent ( editor . $el , 'blur' , function ( e ) { if ( blurActive ( ) ) { if ( focused === true ) { trigger ( e . type , [ e ] ) ; enableBlur ( ) ; } } } ) ; $on ( editor . $el , 'mousedown' , '[contenteditable="true"]' , function ( ) { disableBlur ( ) ; editor . $el . blur ( ) ; } )
on ( 'focus' , function ( ) { focused = true ; } ) ; on ( 'blur' , function ( ) { focused = false ; } ) ; }
function _forMouse ( ) { if ( editor . helpers . isMobile ( ) ) { editor . _mousedown = 'touchstart' ; editor . _mouseup = 'touchend' ; editor . _move = 'touchmove' ; editor . _mousemove = 'touchmove' ; }
else { editor . _mousedown = 'mousedown' ; editor . _mouseup = 'mouseup' ; editor . _move = '' ; editor . _mousemove = 'mousemove' ; } }
function _buttonMouseDown ( e ) { var $btn = $ ( e . currentTarget ) ; if ( editor . edit . isDisabled ( ) || editor . node . hasClass ( $btn . get ( 0 ) , 'fr-disabled' ) ) { e . preventDefault ( ) ; return false ; }
if ( e . type === 'mousedown' && e . which !== 1 ) return true ; if ( ! editor . helpers . isMobile ( ) ) { e . preventDefault ( ) ; }
if ( ( editor . helpers . isAndroid ( ) || editor . helpers . isWindowsPhone ( ) ) && $btn . parents ( '.fr-dropdown-menu' ) . length === 0 ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
$btn . addClass ( 'fr-selected' ) ; editor . events . trigger ( 'commands.mousedown' , [ $btn ] ) ; }
function _buttonMouseUp ( e , handler ) { var $btn = $ ( e . currentTarget ) ; if ( editor . edit . isDisabled ( ) || editor . node . hasClass ( $btn . get ( 0 ) , 'fr-disabled' ) ) { e . preventDefault ( ) ; return false ; }
if ( e . type === 'mouseup' && e . which !== 1 ) return true ; if ( ! editor . node . hasClass ( $btn . get ( 0 ) , 'fr-selected' ) ) return true ; if ( e . type != 'touchmove' ) { e . stopPropagation ( ) ; e . stopImmediatePropagation ( ) ; e . preventDefault ( ) ; if ( ! editor . node . hasClass ( $btn . get ( 0 ) , 'fr-selected' ) ) { editor . button . getButtons ( '.fr-selected' , true ) . removeClass ( 'fr-selected' ) ; return false ; }
editor . button . getButtons ( '.fr-selected' , true ) . removeClass ( 'fr-selected' ) ; if ( $btn . data ( 'dragging' ) || $btn . attr ( 'disabled' ) ) { $btn . removeData ( 'dragging' ) ; return false ; }
var timeout = $btn . data ( 'timeout' ) ; if ( timeout ) { clearTimeout ( timeout ) ; $btn . removeData ( 'timeout' ) ; }
handler . apply ( editor , [ e ] ) ; }
else { if ( ! $btn . data ( 'timeout' ) ) { $btn . data ( 'timeout' , setTimeout ( function ( ) { $btn . data ( 'dragging' , true ) ; } , 100 ) ) ; } } }
function enableBlur ( ) { _do _blur = true ; }
function disableBlur ( ) { _do _blur = false ; }
function blurActive ( ) { return _do _blur ; }
function bindClick ( $element , selector , handler ) { $on ( $element , editor . _mousedown , selector , function ( e ) { if ( ! editor . edit . isDisabled ( ) ) _buttonMouseDown ( e ) ; } , true ) ; $on ( $element , editor . _mouseup + ' ' + editor . _move , selector , function ( e ) { if ( ! editor . edit . isDisabled ( ) ) _buttonMouseUp ( e , handler ) ; } , true ) ; $on ( $element , 'mousedown click mouseup' , selector , function ( e ) { if ( ! editor . edit . isDisabled ( ) ) e . stopPropagation ( ) ; } , true ) ; on ( 'window.mouseup' , function ( ) { if ( ! editor . edit . isDisabled ( ) ) { $element . find ( selector ) . removeClass ( 'fr-selected' ) ; enableBlur ( ) ; } } ) ; $on ( $element , 'mouseenter' , selector , function ( ) { if ( $ ( this ) . hasClass ( 'fr-options' ) ) { $ ( this ) . prev ( '.fr-btn' ) . addClass ( 'fr-btn-hover' ) }
if ( $ ( this ) . next ( '.fr-btn' ) . hasClass ( 'fr-options' ) ) { $ ( this ) . next ( '.fr-btn' ) . addClass ( 'fr-btn-hover' ) } } )
$on ( $element , 'mouseleave' , selector , function ( ) { if ( $ ( this ) . hasClass ( 'fr-options' ) ) { $ ( this ) . prev ( '.fr-btn' ) . removeClass ( 'fr-btn-hover' ) }
if ( $ ( this ) . next ( '.fr-btn' ) . hasClass ( 'fr-options' ) ) { $ ( this ) . next ( '.fr-btn' ) . removeClass ( 'fr-btn-hover' ) } } ) }
function on ( name , callback , first ) { var names = name . split ( ' ' ) ; if ( names . length > 1 ) { for ( var i = 0 ; i < names . length ; i ++ ) { on ( names [ i ] , callback , first ) ; }
return true ; }
if ( typeof first == 'undefined' ) first = false ; var callbacks ; if ( name . indexOf ( 'shared.' ) !== 0 ) { callbacks = ( _events [ name ] = _events [ name ] || [ ] ) ; }
else { callbacks = ( editor . shared . _events [ name ] = editor . shared . _events [ name ] || [ ] ) ; }
if ( first ) { callbacks . unshift ( callback ) ; }
else { callbacks . push ( callback ) ; } }
var $ _events = [ ] ; function _callback ( callback ) { return function ( ) { if ( ! editor . destroying ) { callback . apply ( this , arguments ) ; } } }
function $on ( $el , evs , selector , callback , shared ) { if ( typeof selector == 'function' ) { shared = callback ; callback = selector ; selector = false ; }
var ary = ( ! shared ? $ _events : editor . shared . $ _events ) ; var id = ( ! shared ? editor . id : editor . sid ) ; callback = _callback ( callback ) ; if ( ! selector ) { $el . on ( evs . split ( ' ' ) . join ( '.ed' + id + ' ' ) + '.ed' + id , callback ) ; }
else { $el . on ( evs . split ( ' ' ) . join ( '.ed' + id + ' ' ) + '.ed' + id , selector , callback ) ; }
ary . push ( [ $el , evs . split ( ' ' ) . join ( '.ed' + id + ' ' ) + '.ed' + id ] ) ; }
function _$off ( evs ) { for ( var i = 0 ; i < evs . length ; i ++ ) { evs [ i ] [ 0 ] . off ( evs [ i ] [ 1 ] ) ; } }
function $off ( ) { _$off ( $ _events ) ; $ _events = [ ] ; if ( editor . shared . count === 0 ) { _$off ( editor . shared . $ _events ) ; editor . shared . $ _events = [ ] ; } }
function trigger ( name , args , force ) { if ( ! editor . edit . isDisabled ( ) || force ) { var callbacks ; if ( name . indexOf ( 'shared.' ) !== 0 ) { callbacks = _events [ name ] ; }
else { if ( editor . shared . count > 0 ) return false ; callbacks = editor . shared . _events [ name ] ; }
var val ; if ( callbacks ) { for ( var i = 0 ; i < callbacks . length ; i ++ ) { val = callbacks [ i ] . apply ( editor , args ) ; if ( val === false ) return false ; } }
val = editor . $oel . triggerHandler ( 'froalaEditor.' + name , $ . merge ( [ editor ] , ( args || [ ] ) ) ) ; if ( val === false ) return false ; return val ; } }
function chainTrigger ( name , param , force ) { if ( ! editor . edit . isDisabled ( ) || force ) { var callbacks ; if ( name . indexOf ( 'shared.' ) !== 0 ) { callbacks = _events [ name ] ; }
else { if ( editor . shared . count > 0 ) return false ; callbacks = editor . shared . _events [ name ] ; }
var resp ; if ( callbacks ) { for ( var i = 0 ; i < callbacks . length ; i ++ ) { resp = callbacks [ i ] . apply ( editor , [ param ] ) ; if ( typeof resp !== 'undefined' ) param = resp ; } }
resp = editor . $oel . triggerHandler ( 'froalaEditor.' + name , $ . merge ( [ editor ] , [ param ] ) ) ; if ( typeof resp !== 'undefined' ) param = resp ; return param ; } }
function _destroy ( ) { for ( var k in _events ) { if ( _events . hasOwnProperty ( k ) ) { delete _events [ k ] ; } } }
function _sharedDestroy ( ) { for ( var k in editor . shared . _events ) { if ( editor . shared . _events . hasOwnProperty ( k ) ) { delete editor . shared . _events [ k ] ; } } }
function _init ( ) { editor . shared . $ _events = editor . shared . $ _events || [ ] ; editor . shared . _events = { } ; _forMouse ( ) ; _forElement ( ) ; _forWindow ( ) ; _forDocument ( ) ; _forKeys ( ) ; _forFocus ( ) ; enableBlur ( ) ; _forPaste ( ) ; on ( 'destroy' , _destroy ) ; on ( 'shared.destroy' , _sharedDestroy ) ; }
return { _init : _init , on : on , trigger : trigger , bindClick : bindClick , disableBlur : disableBlur , enableBlur : enableBlur , blurActive : blurActive , focus : focus , chainTrigger : chainTrigger , $on : $on , $off : $off } } ; $ . FE . MODULES . node = function ( editor ) { function getContents ( node ) { if ( ! node || node . tagName == 'IFRAME' ) return [ ] ; return Array . prototype . slice . call ( node . childNodes || [ ] ) ; }
function isBlock ( node ) { if ( ! node ) return false ; if ( node . nodeType != Node . ELEMENT _NODE ) return false ; return $ . FE . BLOCK _TAGS . indexOf ( node . tagName . toLowerCase ( ) ) >= 0 ; }
function isLink ( node ) { if ( ! node ) return false ; if ( node . nodeType != Node . ELEMENT _NODE ) return false ; return node . tagName . toLowerCase ( ) == 'a' ; }
function isEmpty ( el , ignore _markers ) { if ( ! el ) return true ; if ( el . querySelector ( 'table' ) ) return false ; var contents = getContents ( el ) ; if ( contents . length == 1 && isBlock ( contents [ 0 ] ) ) { contents = getContents ( contents [ 0 ] ) ; }
var has _br = false ; for ( var i = 0 ; i < contents . length ; i ++ ) { var node = contents [ i ] ; if ( ignore _markers && editor . node . hasClass ( node , 'fr-marker' ) ) continue ; if ( node . nodeType == Node . TEXT _NODE && node . textContent . length === 0 ) continue ; if ( node . tagName != 'BR' && ( node . textContent || '' ) . replace ( /\u200B/gi , '' ) . replace ( /\n/g , '' ) . length > 0 ) return false ; if ( has _br ) { return false ; }
else if ( node . tagName == 'BR' ) { has _br = true ; } }
if ( el . querySelectorAll ( $ . FE . VOID _ELEMENTS . join ( ',' ) ) . length - el . querySelectorAll ( 'br' ) . length ) return false ; if ( el . querySelector ( editor . opts . htmlAllowedEmptyTags . join ( ':not(.fr-marker),' ) + ':not(.fr-marker)' ) ) return false ; if ( el . querySelectorAll ( $ . FE . BLOCK _TAGS . join ( ',' ) ) . length > 1 ) return false ; if ( el . querySelector ( editor . opts . htmlDoNotWrapTags . join ( ':not(.fr-marker),' ) + ':not(.fr-marker)' ) ) return false ; return true ; }
function blockParent ( node ) { while ( node && node . parentNode !== editor . el && ! ( node . parentNode && editor . node . hasClass ( node . parentNode , 'fr-inner' ) ) ) { node = node . parentNode ; if ( isBlock ( node ) ) { return node ; } }
return null ; }
function deepestParent ( node , until , simple _enter ) { if ( typeof until == 'undefined' ) until = [ ] ; if ( typeof simple _enter == 'undefined' ) simple _enter = true ; until . push ( editor . el ) ; if ( until . indexOf ( node . parentNode ) >= 0 || ( node . parentNode && editor . node . hasClass ( node . parentNode , 'fr-inner' ) ) || ( node . parentNode && $ . FE . SIMPLE _ENTER _TAGS . indexOf ( node . parentNode . tagName ) >= 0 && simple _enter ) ) { return null ; }
while ( until . indexOf ( node . parentNode ) < 0 && node . parentNode && ! editor . node . hasClass ( node . parentNode , 'fr-inner' ) && ( $ . FE . SIMPLE _ENTER _TAGS . indexOf ( node . parentNode . tagName ) < 0 || ! simple _enter ) && ( ! ( isBlock ( node ) && isBlock ( node . parentNode ) ) || ! simple _enter ) ) { node = node . parentNode ; }
return node ; }
function rawAttributes ( node ) { var attrs = { } ; var atts = node . attributes ; if ( atts ) { for ( var i = 0 ; i < atts . length ; i ++ ) { var att = atts [ i ] ; attrs [ att . nodeName ] = att . value ; } }
return attrs ; }
function attributes ( node ) { var str = '' ; var atts = rawAttributes ( node ) ; var keys = Object . keys ( atts ) . sort ( ) ; for ( var i = 0 ; i < keys . length ; i ++ ) { var nodeName = keys [ i ] ; var value = atts [ nodeName ] ; if ( value . indexOf ( '\'' ) < 0 && value . indexOf ( '"' ) >= 0 ) { str += ' ' + nodeName + '=\'' + value + '\'' ; }
else if ( value . indexOf ( '"' ) >= 0 && value . indexOf ( '\'' ) >= 0 ) { value = value . replace ( /"/g , '"' ) ; str += ' ' + nodeName + '="' + value + '"' ; }
else { str += ' ' + nodeName + '="' + value + '"' ; } }
return str ; }
function clearAttributes ( node ) { var atts = node . attributes ; for ( var i = atts . length - 1 ; i >= 0 ; i -- ) { var att = atts [ i ] ; node . removeAttribute ( att . nodeName ) ; } }
function openTagString ( node ) { return '<' + node . tagName . toLowerCase ( ) + attributes ( node ) + '>' ; }
function closeTagString ( node ) { return '</' + node . tagName . toLowerCase ( ) + '>' ; }
function isFirstSibling ( node , ignore _markers ) { if ( typeof ignore _markers == 'undefined' ) ignore _markers = true ; var sibling = node . previousSibling ; while ( sibling && ignore _markers && editor . node . hasClass ( sibling , 'fr-marker' ) ) { sibling = sibling . previousSibling ; }
if ( ! sibling ) return true ; if ( sibling . nodeType == Node . TEXT _NODE && sibling . textContent === '' ) return isFirstSibling ( sibling ) ; return false ; }
function isLastSibling ( node , ignore _markers ) { if ( typeof ignore _markers == 'undefined' ) ignore _markers = true ; var sibling = node . nextSibling ; while ( sibling && ignore _markers && editor . node . hasClass ( sibling , 'fr-marker' ) ) { sibling = sibling . nextSibling ; }
if ( ! sibling ) return true ; if ( sibling . nodeType == Node . TEXT _NODE && sibling . textContent === '' ) return isLastSibling ( sibling ) ; return false ; }
function isVoid ( node ) { return node && node . nodeType == Node . ELEMENT _NODE && $ . FE . VOID _ELEMENTS . indexOf ( ( node . tagName || '' ) . toLowerCase ( ) ) >= 0 }
function isList ( node ) { if ( ! node ) return false ; return [ 'UL' , 'OL' ] . indexOf ( node . tagName ) >= 0 ; }
function isElement ( node ) { return node === editor . el ; }
function isDeletable ( node ) { return node && node . nodeType == Node . ELEMENT _NODE && node . getAttribute ( 'class' ) && ( node . getAttribute ( 'class' ) || '' ) . indexOf ( 'fr-deletable' ) >= 0 ; }
function hasFocus ( node ) { return node === editor . doc . activeElement && ( ! editor . doc . hasFocus || editor . doc . hasFocus ( ) ) && ! ! ( isElement ( node ) || node . type || node . href || ~ node . tabIndex ) ; }
function isEditable ( node ) { return ( ! node . getAttribute || node . getAttribute ( 'contenteditable' ) != 'false' ) && [ 'STYLE' , 'SCRIPT' ] . indexOf ( node . tagName ) < 0 ; }
function hasClass ( el , cls ) { if ( el instanceof $ ) el = el . get ( 0 ) ; return ( el && el . classList && el . classList . contains ( cls ) ) ; }
function filter ( callback ) { if ( editor . browser . msie ) { return callback ; }
else { return { acceptNode : callback } } }
return { isBlock : isBlock , isEmpty : isEmpty , blockParent : blockParent , deepestParent : deepestParent , rawAttributes : rawAttributes , attributes : attributes , clearAttributes : clearAttributes , openTagString : openTagString , closeTagString : closeTagString , isFirstSibling : isFirstSibling , isLastSibling : isLastSibling , isList : isList , isLink : isLink , isElement : isElement , contents : getContents , isVoid : isVoid , hasFocus : hasFocus , isEditable : isEditable , isDeletable : isDeletable , hasClass : hasClass , filter : filter } } ; $ . FE . INVISIBLE _SPACE = '​' ; $ . FE . START _MARKER = '<span class="fr-marker" data-id="0" data-type="true" style="display: none; line-height: 0;">' + $ . FE . INVISIBLE _SPACE + '</span>' ; $ . FE . END _MARKER = '<span class="fr-marker" data-id="0" data-type="false" style="display: none; line-height: 0;">' + $ . FE . INVISIBLE _SPACE + '</span>' ; $ . FE . MARKERS = $ . FE . START _MARKER + $ . FE . END _MARKER ; $ . FE . MODULES . markers = function ( editor ) { function _build ( marker , id ) { return $ ( '<span class="fr-marker" data-id="' + id + '" data-type="' + marker + '" style="display: ' + ( editor . browser . safari ? 'none' : 'inline-block' ) + '; line-height: 0;">' + $ . FE . INVISIBLE _SPACE + '</span>' , editor . doc ) [ 0 ] ; }
function place ( range , marker , id ) { var mk ; var contents ; var sibling ; try { var boundary = range . cloneRange ( ) ; boundary . collapse ( marker ) ; boundary . insertNode ( _build ( marker , id ) ) ; if ( marker === true ) { mk = editor . $el . find ( 'span.fr-marker[data-type="true"][data-id="' + id + '"]' ) . get ( 0 ) ; sibling = mk . nextSibling ; while ( sibling && sibling . nodeType === Node . TEXT _NODE && sibling . textContent . length === 0 ) { $ ( sibling ) . remove ( ) ; sibling = mk . nextSibling ; } }
if ( marker === true && ! range . collapsed ) { while ( ! editor . node . isElement ( mk . parentNode ) && ! sibling ) { $ ( mk . parentNode ) . after ( mk ) ; sibling = mk . nextSibling ; }
if ( sibling && sibling . nodeType === Node . ELEMENT _NODE && editor . node . isBlock ( sibling ) && sibling . tagName !== 'HR' ) { contents = [ sibling ] ; do { sibling = contents [ 0 ] ; contents = editor . node . contents ( sibling ) ; } while ( contents [ 0 ] && editor . node . isBlock ( contents [ 0 ] ) ) ; $ ( sibling ) . prepend ( $ ( mk ) ) ; } }
if ( marker === false && ! range . collapsed ) { mk = editor . $el . find ( 'span.fr-marker[data-type="false"][data-id="' + id + '"]' ) . get ( 0 ) ; sibling = mk . previousSibling ; if ( sibling && sibling . nodeType === Node . ELEMENT _NODE && editor . node . isBlock ( sibling ) && sibling . tagName !== 'HR' ) { contents = [ sibling ] ; do { sibling = contents [ contents . length - 1 ] ; contents = editor . node . contents ( sibling ) ; } while ( contents [ contents . length - 1 ] && editor . node . isBlock ( contents [ contents . length - 1 ] ) ) ; $ ( sibling ) . append ( $ ( mk ) ) ; }
if ( mk . parentNode && [ 'TD' , 'TH' ] . indexOf ( mk . parentNode . tagName ) >= 0 ) { if ( mk . parentNode . previousSibling && ! mk . previousSibling ) { $ ( mk . parentNode . previousSibling ) . append ( mk ) ; } } }
var dom _marker = editor . $el . find ( 'span.fr-marker[data-type="' + marker + '"][data-id="' + id + '"]' ) . get ( 0 ) ; if ( dom _marker ) dom _marker . style . display = 'none' ; return dom _marker ; }
catch ( ex ) { return null ; } }
function insert ( ) { if ( ! editor . $wp ) return null ; try { var range = editor . selection . ranges ( 0 ) ; var containter = range . commonAncestorContainer ; if ( editor . core . isEmpty ( ) ) { editor . selection . setAtStart ( editor . el ) ; editor . $el . find ( '.fr-marker:first' ) . replaceWith ( '<span class="fr-single-marker" style="display: none; line-height: 0;">' + $ . FE . INVISIBLE _SPACE + '</span>' ) ; editor . $el . find ( '.fr-marker' ) . remove ( ) ; return editor . $el . find ( '.fr-single-marker' ) . removeClass ( 'fr-single-marker' ) . addClass ( 'fr-marker' ) . get ( 0 ) ; }
if ( containter != editor . el && editor . $el . find ( containter ) . length === 0 ) return null ; var boundary = range . cloneRange ( ) ; var original _range = range . cloneRange ( ) ; boundary . collapse ( true ) ; var mk = $ ( '<span class="fr-marker" style="display: none; line-height: 0;">' + $ . FE . INVISIBLE _SPACE + '</span>' , editor . doc ) [ 0 ] ; boundary . insertNode ( mk ) ; mk = editor . $el . find ( 'span.fr-marker' ) . get ( 0 ) ; if ( mk ) { var sibling = mk . nextSibling ; while ( sibling && sibling . nodeType === Node . TEXT _NODE && sibling . textContent . length === 0 ) { $ ( sibling ) . remove ( ) ; sibling = editor . $el . find ( 'span.fr-marker' ) . get ( 0 ) . nextSibling ; }
editor . selection . clear ( ) ; editor . selection . get ( ) . addRange ( original _range ) ; return mk ; }
else { return null ; } }
catch ( ex ) { console . warn ( 'MARKER' , ex ) } }
function split ( ) { if ( ! editor . selection . isCollapsed ( ) ) { editor . selection . remove ( ) ; }
var marker = editor . $el . find ( '.fr-marker' ) . get ( 0 ) ; if ( marker == null ) marker = insert ( ) ; if ( marker == null ) return null ; var deep _parent = editor . node . deepestParent ( marker ) ; if ( ! deep _parent ) { deep _parent = editor . node . blockParent ( marker ) ; if ( deep _parent && deep _parent . tagName != 'LI' ) { deep _parent = null ; } }
if ( deep _parent ) { if ( editor . node . isBlock ( deep _parent ) && editor . node . isEmpty ( deep _parent ) ) { if ( deep _parent . tagName == 'LI' && ( deep _parent . parentNode . firstElementChild == deep _parent && ! editor . node . isEmpty ( deep _parent . parentNode ) ) ) { $ ( deep _parent ) . append ( '<span class="fr-marker"></span>' ) ; }
else { $ ( deep _parent ) . replaceWith ( '<span class="fr-marker"></span>' ) ; } }
else if ( editor . cursor . isAtStart ( marker , deep _parent ) ) { $ ( deep _parent ) . before ( '<span class="fr-marker"></span>' ) ; $ ( marker ) . remove ( ) ; }
else if ( editor . cursor . isAtEnd ( marker , deep _parent ) ) { $ ( deep _parent ) . after ( '<span class="fr-marker"></span>' ) ; $ ( marker ) . remove ( ) ; }
else { var node = marker ; var close _str = '' ; var open _str = '' ; do { node = node . parentNode ; close _str = close _str + editor . node . closeTagString ( node ) ; open _str = editor . node . openTagString ( node ) + open _str ; } while ( node != deep _parent ) ; $ ( marker ) . replaceWith ( '<span id="fr-break"></span>' ) ; var h = editor . node . openTagString ( deep _parent ) + $ ( deep _parent ) . html ( ) + editor . node . closeTagString ( deep _parent ) ; h = h . replace ( /<span id="fr-break"><\/span>/g , close _str + '<span class="fr-marker"></span>' + open _str ) ; $ ( deep _parent ) . replaceWith ( h ) ; } }
return editor . $el . find ( '.fr-marker' ) . get ( 0 ) }
function insertAtPoint ( e ) { var x = e . clientX ; var y = e . clientY ; remove ( ) ; var start ; var range = null ; if ( typeof editor . doc . caretPositionFromPoint != 'undefined' ) { start = editor . doc . caretPositionFromPoint ( x , y ) ; range = editor . doc . createRange ( ) ; range . setStart ( start . offsetNode , start . offset ) ; range . setEnd ( start . offsetNode , start . offset ) ; }
else if ( typeof editor . doc . caretRangeFromPoint != 'undefined' ) { start = editor . doc . caretRangeFromPoint ( x , y ) ; range = editor . doc . createRange ( ) ; range . setStart ( start . startContainer , start . startOffset ) ; range . setEnd ( start . startContainer , start . startOffset ) ; }
if ( range !== null && typeof editor . win . getSelection != 'undefined' ) { var sel = editor . win . getSelection ( ) ; sel . removeAllRanges ( ) ; sel . addRange ( range ) ; }
else if ( typeof editor . doc . body . createTextRange != 'undefined' ) { try { range = editor . doc . body . createTextRange ( ) ; range . moveToPoint ( x , y ) ; var end _range = range . duplicate ( ) ; end _range . moveToPoint ( x , y ) ; range . setEndPoint ( 'EndToEnd' , end _range ) ; range . select ( ) ; }
catch ( ex ) { return false ; } }
insert ( ) ; }
function remove ( ) { editor . $el . find ( '.fr-marker' ) . remove ( ) ; }
return { place : place , insert : insert , split : split , insertAtPoint : insertAtPoint , remove : remove } } ; $ . FE . MODULES . selection = function ( editor ) { function text ( ) { var text = '' ; if ( editor . win . getSelection ) { text = editor . win . getSelection ( ) ; }
else if ( editor . doc . getSelection ) { text = editor . doc . getSelection ( ) ; }
else if ( editor . doc . selection ) { text = editor . doc . selection . createRange ( ) . text ; }
return text . toString ( ) ; }
function get ( ) { var selection = '' ; if ( editor . win . getSelection ) { selection = editor . win . getSelection ( ) ; }
else if ( editor . doc . getSelection ) { selection = editor . doc . getSelection ( ) ; }
else { selection = editor . doc . selection . createRange ( ) ; }
return selection ; }
function ranges ( index ) { var sel = get ( ) ; var ranges = [ ] ; if ( sel && sel . getRangeAt && sel . rangeCount ) { ranges = [ ] ; for ( var i = 0 ; i < sel . rangeCount ; i ++ ) { ranges . push ( sel . getRangeAt ( i ) ) ; } }
else { if ( editor . doc . createRange ) { ranges = [ editor . doc . createRange ( ) ] ; }
else { ranges = [ ] ; } }
return ( typeof index != 'undefined' ? ranges [ index ] : ranges ) ; }
function clear ( ) { var sel = get ( ) ; try { if ( sel . removeAllRanges ) { sel . removeAllRanges ( ) ; }
else if ( sel . empty ) { sel . empty ( ) ; }
else if ( sel . clear ) { sel . clear ( ) ; } }
catch ( ex ) { } }
function element ( ) { var sel = get ( ) ; try { if ( sel . rangeCount ) { var range = ranges ( 0 ) ; var node = range . startContainer ; var child ; if ( editor . node . isElement ( node ) && range . startOffset === 0 && node . childNodes . length ) { while ( node . childNodes . length && node . childNodes [ 0 ] . nodeType === Node . ELEMENT _NODE ) { node = node . childNodes [ 0 ] ; } }
if ( node . nodeType == Node . TEXT _NODE && range . startOffset == ( node . textContent || '' ) . length && node . nextSibling ) { node = node . nextSibling ; }
if ( node . nodeType == Node . ELEMENT _NODE ) { var node _found = false ; if ( node . childNodes . length > 0 && node . childNodes [ range . startOffset ] ) { child = node . childNodes [ range . startOffset ] ; while ( child && child . nodeType == Node . TEXT _NODE && child . textContent . length === 0 ) { child = child . nextSibling ; }
if ( child && child . textContent . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) ) { node = child ; node _found = true ; }
if ( ! node _found && node . childNodes . length > 1 && range . startOffset > 0 && node . childNodes [ range . startOffset - 1 ] ) { child = node . childNodes [ range . startOffset - 1 ] ; while ( child && child . nodeType == Node . TEXT _NODE && child . textContent . length === 0 ) { child = child . nextSibling ; }
if ( child && child . textContent . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) ) { node = child ; node _found = true ; } } }
else if ( ! range . collapsed && node . nextSibling && node . nextSibling . nodeType == Node . ELEMENT _NODE ) { child = node . nextSibling ; if ( child && child . textContent . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) ) { node = child ; node _found = true ; } }
if ( ! node _found && node . childNodes . length > 0 && $ ( node . childNodes [ 0 ] ) . text ( ) . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) && [ 'BR' , 'IMG' , 'HR' ] . indexOf ( node . childNodes [ 0 ] . tagName ) < 0 ) { node = node . childNodes [ 0 ] ; } }
while ( node . nodeType != Node . ELEMENT _NODE && node . parentNode ) { node = node . parentNode ; }
var p = node ; while ( p && p . tagName != 'HTML' ) { if ( p == editor . el ) { return node ; }
p = $ ( p ) . parent ( ) [ 0 ] ; } } }
catch ( ex ) { }
return editor . el ; }
function endElement ( ) { var sel = get ( ) ; try { if ( sel . rangeCount ) { var range = ranges ( 0 ) ; var node = range . endContainer ; var child ; if ( node . nodeType == Node . ELEMENT _NODE ) { var node _found = false ; if ( node . childNodes . length > 0 && node . childNodes [ range . endOffset ] && $ ( node . childNodes [ range . endOffset ] ) . text ( ) === text ( ) ) { node = node . childNodes [ range . endOffset ] ; node _found = true ; }
else if ( ! range . collapsed && node . previousSibling && node . previousSibling . nodeType == Node . ELEMENT _NODE ) { child = node . previousSibling ; if ( child && child . textContent . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) ) { node = child ; node _found = true ; } }
else if ( ! range . collapsed && node . childNodes . length > 0 && node . childNodes [ range . endOffset ] ) { child = node . childNodes [ range . endOffset ] . previousSibling ; if ( child . nodeType == Node . ELEMENT _NODE ) { if ( child && child . textContent . replace ( /\u200B/g , '' ) === text ( ) . replace ( /\u200B/g , '' ) ) { node = child ; node _found = true ; } } }
if ( ! node _found && node . childNodes . length > 0 && $ ( node . childNodes [ node . childNodes . length - 1 ] ) . text ( ) === text ( ) && [ 'BR' , 'IMG' , 'HR' ] . indexOf ( node . childNodes [ node . childNodes . length - 1 ] . tagName ) < 0 ) { node = node . childNodes [ node . childNodes . length - 1 ] ; } }
if ( node . nodeType == Node . TEXT _NODE && range . endOffset === 0 && node . previousSibling && node . previousSibling . nodeType == Node . ELEMENT _NODE ) { node = node . previousSibling ; }
while ( node . nodeType != Node . ELEMENT _NODE && node . parentNode ) { node = node . parentNode ; }
var p = node ; while ( p && p . tagName != 'HTML' ) { if ( p == editor . el ) { return node ; }
p = $ ( p ) . parent ( ) [ 0 ] ; } } }
catch ( ex ) { }
return editor . el ; }
function rangeElement ( rangeContainer , offset ) { var node = rangeContainer ; if ( node . nodeType == Node . ELEMENT _NODE ) { if ( node . childNodes . length > 0 && node . childNodes [ offset ] ) { node = node . childNodes [ offset ] ; } }
if ( node . nodeType == Node . TEXT _NODE ) { node = node . parentNode ; }
return node ; }
function blocks ( ) { var blks = [ ] ; var i ; var sel = get ( ) ; if ( inEditor ( ) && sel . rangeCount ) { var rngs = ranges ( ) ; for ( i = 0 ; i < rngs . length ; i ++ ) { var range = rngs [ i ] ; var block _parent ; var start _node = rangeElement ( range . startContainer , range . startOffset ) ; var end _node = rangeElement ( range . endContainer , range . endOffset ) ; if ( ( editor . node . isBlock ( start _node ) || editor . node . hasClass ( start _node , 'fr-inner' ) ) && blks . indexOf ( start _node ) < 0 ) blks . push ( start _node ) ; block _parent = editor . node . blockParent ( start _node ) ; if ( block _parent && blks . indexOf ( block _parent ) < 0 ) { blks . push ( block _parent ) ; }
var was _into = [ ] ; var next _node = start _node ; while ( next _node !== end _node && next _node !== editor . el ) { if ( was _into . indexOf ( next _node ) < 0 && next _node . children && next _node . children . length ) { was _into . push ( next _node ) ; next _node = next _node . children [ 0 ] ; }
else if ( next _node . nextSibling ) { next _node = next _node . nextSibling ; }
else if ( next _node . parentNode ) { next _node = next _node . parentNode ; was _into . push ( next _node ) ; }
if ( editor . node . isBlock ( next _node ) && was _into . indexOf ( next _node ) < 0 && blks . indexOf ( next _node ) < 0 ) { if ( next _node !== end _node || range . endOffset > 0 ) { blks . push ( next _node ) ; } } }
if ( editor . node . isBlock ( end _node ) && blks . indexOf ( end _node ) < 0 && range . endOffset > 0 ) blks . push ( end _node ) ; block _parent = editor . node . blockParent ( end _node ) ; if ( block _parent && blks . indexOf ( block _parent ) < 0 ) { blks . push ( block _parent ) ; } } }
for ( i = blks . length - 1 ; i > 0 ; i -- ) { if ( $ ( blks [ i ] ) . find ( blks ) . length ) blks . splice ( i , 1 ) ; }
return blks ; }
function save ( ) { if ( editor . $wp ) { editor . markers . remove ( ) ; var rgs = ranges ( ) ; var new _ranges = [ ] ; var range ; var i ; for ( i = 0 ; i < rgs . length ; i ++ ) { if ( rgs [ i ] . startContainer !== editor . doc || editor . browser . msie ) { range = rgs [ i ] ; var collapsed = range . collapsed ; var start _m = editor . markers . place ( range , true , i ) ; var end _m = editor . markers . place ( range , false , i ) ; if ( ( typeof start _m == 'undefined' || ! start _m ) && collapsed ) { $ ( '.fr-marker' ) . remove ( ) ; editor . selection . setAtEnd ( editor . el ) ; }
editor . el . normalize ( ) ; if ( editor . browser . safari && ! collapsed ) { try { range = editor . doc . createRange ( ) ; range . setStartAfter ( start _m ) ; range . setEndBefore ( end _m ) ; new _ranges . push ( range ) ; }
catch ( ex ) { } } } }
if ( editor . browser . safari && new _ranges . length ) { editor . selection . clear ( ) ; for ( i = 0 ; i < new _ranges . length ; i ++ ) { editor . selection . get ( ) . addRange ( new _ranges [ i ] ) ; } } } }
function restore ( ) { var i ; var markers = editor . el . querySelectorAll ( '.fr-marker[data-type="true"]' ) ; if ( ! editor . $wp ) { editor . markers . remove ( ) ; return false ; }
if ( markers . length === 0 ) { return false ; }
if ( editor . browser . msie || editor . browser . edge ) { for ( i = 0 ; i < markers . length ; i ++ ) { markers [ i ] . style . display = 'inline-block' ; } }
if ( ! editor . core . hasFocus ( ) && ! editor . browser . msie && ! editor . browser . webkit ) { editor . $el . focus ( ) ; }
clear ( ) ; var sel = get ( ) ; for ( i = 0 ; i < markers . length ; i ++ ) { var id = $ ( markers [ i ] ) . data ( 'id' ) ; var start _marker = markers [ i ] ; var range = editor . doc . createRange ( ) ; var end _marker = editor . $el . find ( '.fr-marker[data-type="false"][data-id="' + id + '"]' ) ; if ( editor . browser . msie || editor . browser . edge ) end _marker . css ( 'display' , 'inline-block' ) ; var ghost = null ; if ( end _marker . length > 0 ) { end _marker = end _marker [ 0 ] ; try { var tmp ; var special _case = false ; var s _node = start _marker . nextSibling ; while ( s _node && s _node . nodeType == Node . TEXT _NODE && s _node . textContent . length === 0 ) { tmp = s _node ; s _node = s _node . nextSibling ; $ ( tmp ) . remove ( ) ; }
var e _node = end _marker . nextSibling ; while ( e _node && e _node . nodeType == Node . TEXT _NODE && e _node . textContent . length === 0 ) { tmp = e _node ; e _node = e _node . nextSibling ; $ ( tmp ) . remove ( ) ; }
if ( start _marker . nextSibling == end _marker || end _marker . nextSibling == start _marker ) { var first _node = ( start _marker . nextSibling == end _marker ) ? start _marker : end _marker ; var last _node = ( first _node == start _marker ) ? end _marker : start _marker ; var prev _node = first _node . previousSibling ; while ( prev _node && prev _node . nodeType == Node . TEXT _NODE && prev _node . length === 0 ) { tmp = prev _node ; prev _node = prev _node . previousSibling ; $ ( tmp ) . remove ( ) ; }
if ( prev _node && prev _node . nodeType == Node . TEXT _NODE ) { while ( prev _node && prev _node . previousSibling && prev _node . previousSibling . nodeType == Node . TEXT _NODE ) { prev _node . previousSibling . textContent = prev _node . previousSibling . textContent + prev _node . textContent ; prev _node = prev _node . previousSibling ; $ ( prev _node . nextSibling ) . remove ( ) ; } }
var next _node = last _node . nextSibling ; while ( next _node && next _node . nodeType == Node . TEXT _NODE && next _node . length === 0 ) { tmp = next _node ; next _node = next _node . nextSibling ; $ ( tmp ) . remove ( ) ; }
if ( next _node && next _node . nodeType == Node . TEXT _NODE ) { while ( next _node && next _node . nextSibling && next _node . nextSibling . nodeType == Node . TEXT _NODE ) { next _node . nextSibling . textContent = next _node . textContent + next _node . nextSibling . textContent ; next _node = next _node . nextSibling ; $ ( next _node . previousSibling ) . remove ( ) ; } }
if ( prev _node && ( editor . node . isVoid ( prev _node ) || editor . node . isBlock ( prev _node ) ) ) prev _node = null ; if ( next _node && ( editor . node . isVoid ( next _node ) || editor . node . isBlock ( next _node ) ) ) next _node = null ; if ( prev _node && next _node && prev _node . nodeType == Node . TEXT _NODE && next _node . nodeType == Node . TEXT _NODE ) { $ ( start _marker ) . remove ( ) ; $ ( end _marker ) . remove ( ) ; var len = prev _node . textContent . length ; prev _node . textContent = prev _node . textContent + next _node . textContent ; $ ( next _node ) . remove ( ) ; if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( prev _node ) ; range . setStart ( prev _node , len ) ; range . setEnd ( prev _node , len ) ; special _case = true ; }
else if ( ! prev _node && next _node && next _node . nodeType == Node . TEXT _NODE ) { $ ( start _marker ) . remove ( ) ; $ ( end _marker ) . remove ( ) ; if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( next _node ) ; ghost = $ ( editor . doc . createTextNode ( '\u200B' ) ) ; $ ( next _node ) . before ( ghost ) ; range . setStart ( next _node , 0 ) ; range . setEnd ( next _node , 0 ) ; special _case = true ; }
else if ( ! next _node && prev _node && prev _node . nodeType == Node . TEXT _NODE ) { $ ( start _marker ) . remove ( ) ; $ ( end _marker ) . remove ( ) ; if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( prev _node ) ; ghost = $ ( editor . doc . createTextNode ( '\u200B' ) ) ; $ ( prev _node ) . after ( ghost ) ; range . setStart ( prev _node , prev _node . textContent . length ) ; range . setEnd ( prev _node , prev _node . textContent . length ) ; special _case = true ; } }
if ( ! special _case ) { var x ; var y ; if ( ( editor . browser . chrome || editor . browser . edge ) && start _marker . nextSibling == end _marker ) { x = _normalizedMarker ( end _marker , range , true ) || range . setStartAfter ( end _marker ) ; y = _normalizedMarker ( start _marker , range , false ) || range . setEndBefore ( start _marker ) ; }
else { if ( start _marker . previousSibling == end _marker ) { start _marker = end _marker ; end _marker = start _marker . nextSibling ; }
if ( ! ( end _marker . nextSibling && end _marker . nextSibling . tagName === 'BR' ) && ! ( ! end _marker . nextSibling && editor . node . isBlock ( start _marker . previousSibling ) ) && ! ( start _marker . previousSibling && start _marker . previousSibling . tagName == 'BR' ) ) { start _marker . style . display = 'inline' ; end _marker . style . display = 'inline' ; ghost = $ ( editor . doc . createTextNode ( '\u200B' ) ) ; }
x = _normalizedMarker ( start _marker , range , true ) || ( $ ( start _marker ) . before ( ghost ) && range . setStartBefore ( start _marker ) ) ; y = _normalizedMarker ( end _marker , range , false ) || ( $ ( end _marker ) . after ( ghost ) && range . setEndAfter ( end _marker ) ) ; }
if ( typeof x == 'function' ) x ( ) ; if ( typeof y == 'function' ) y ( ) ; } }
catch ( ex ) { console . warn ( 'RESTORE RANGE' , ex ) ; } }
if ( ghost ) { ghost . remove ( ) ; }
try { sel . addRange ( range ) ; }
catch ( ex ) { console . warn ( 'ADD RANGE' , ex ) ; } }
editor . markers . remove ( ) ; }
function _normalizedMarker ( marker , range , start ) { var len ; var prev _node = marker . previousSibling ; var next _node = marker . nextSibling ; if ( prev _node && next _node && prev _node . nodeType == Node . TEXT _NODE && next _node . nodeType == Node . TEXT _NODE ) { len = prev _node . textContent . length ; if ( start ) { next _node . textContent = prev _node . textContent + next _node . textContent ; $ ( prev _node ) . remove ( ) ; $ ( marker ) . remove ( ) ; if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( next _node ) ; return function ( ) { range . setStart ( next _node , len ) ; } }
else { prev _node . textContent = prev _node . textContent + next _node . textContent ; $ ( next _node ) . remove ( ) ; $ ( marker ) . remove ( ) ; if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( prev _node ) ; return function ( ) { range . setEnd ( prev _node , len ) ; } } }
else if ( prev _node && ! next _node && prev _node . nodeType == Node . TEXT _NODE ) { len = prev _node . textContent . length ; if ( start ) { if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( prev _node ) ; return function ( ) { range . setStart ( prev _node , len ) ; } }
else { if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( prev _node ) ; return function ( ) { range . setEnd ( prev _node , len ) ; } } }
else if ( next _node && ! prev _node && next _node . nodeType == Node . TEXT _NODE ) { if ( start ) { if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( next _node ) ; return function ( ) { range . setStart ( next _node , 0 ) ; } }
else { if ( ! editor . opts . htmlUntouched ) editor . spaces . normalize ( next _node ) ; return function ( ) { range . setEnd ( next _node , 0 ) ; } } }
return false ; }
function _canDelete ( ) { var markers = editor . $el . find ( '.fr-marker' ) ; for ( var i = 0 ; i < markers . length ; i ++ ) { if ( $ ( markers [ i ] ) . parentsUntil ( '.fr-element, [contenteditable="true"]' , '[contenteditable="false"]' ) . length ) { return false ; } }
return true ; }
function isCollapsed ( ) { var rgs = ranges ( ) ; for ( var i = 0 ; i < rgs . length ; i ++ ) { if ( ! rgs [ i ] . collapsed ) return false ; }
return true ; }
function info ( el ) { var atStart = false ; var atEnd = false ; var selRange ; var testRange ; if ( editor . win . getSelection ) { var sel = editor . win . getSelection ( ) ; if ( sel . rangeCount ) { selRange = sel . getRangeAt ( 0 ) ; testRange = selRange . cloneRange ( ) ; testRange . selectNodeContents ( el ) ; testRange . setEnd ( selRange . startContainer , selRange . startOffset ) ; atStart = ( testRange . toString ( ) === '' ) ; testRange . selectNodeContents ( el ) ; testRange . setStart ( selRange . endContainer , selRange . endOffset ) ; atEnd = ( testRange . toString ( ) === '' ) ; } }
else if ( editor . doc . selection && editor . doc . selection . type != 'Control' ) { selRange = editor . doc . selection . createRange ( ) ; testRange = selRange . duplicate ( ) ; testRange . moveToElementText ( el ) ; testRange . setEndPoint ( 'EndToStart' , selRange ) ; atStart = ( testRange . text === '' ) ; testRange . moveToElementText ( el ) ; testRange . setEndPoint ( 'StartToEnd' , selRange ) ; atEnd = ( testRange . text === '' ) ; }
return { atStart : atStart , atEnd : atEnd } ; }
function isFull ( ) { if ( isCollapsed ( ) ) return false ; editor . selection . save ( )
var els = editor . el . querySelectorAll ( 'td, th, img, br' ) ; var i ; for ( i = 0 ; i < els . length ; i ++ ) { if ( els [ i ] . nextSibling ) { els [ i ] . innerHTML = '<span class="fr-mk">' + $ . FE . INVISIBLE _SPACE + '</span>' + els [ i ] . innerHTML ; } }
var full = false ; var inf = info ( editor . el ) ; if ( inf . atStart && inf . atEnd ) full = true ; els = editor . el . querySelectorAll ( '.fr-mk' ) ; for ( i = 0 ; i < els . length ; i ++ ) { els [ i ] . parentNode . removeChild ( els [ i ] ) ; }
editor . selection . restore ( ) ; return full ; }
function _emptyInnerNodes ( node , first ) { if ( typeof first == 'undefined' ) first = true ; var h = $ ( node ) . html ( ) ; if ( h && h . replace ( /\u200b/g , '' ) . length != h . length ) $ ( node ) . html ( h . replace ( /\u200b/g , '' ) ) ; var contents = editor . node . contents ( node ) ; for ( var j = 0 ; j < contents . length ; j ++ ) { if ( contents [ j ] . nodeType != Node . ELEMENT _NODE ) { $ ( contents [ j ] ) . remove ( ) ; }
else { _emptyInnerNodes ( contents [ j ] , j === 0 ) ; if ( j === 0 ) first = false ; } }
if ( node . nodeType == Node . TEXT _NODE ) { $ ( node ) . replaceWith ( '<span data-first="true" data-text="true"></span>' ) ; }
else if ( first ) { $ ( node ) . attr ( 'data-first' , true ) ; } }
function _filterFrInner ( ) { return $ ( this ) . find ( 'fr-inner' ) . length === 0 ; }
function _processNodeDelete ( $node , should _delete ) { var contents = editor . node . contents ( $node . get ( 0 ) ) ; if ( [ 'TD' , 'TH' ] . indexOf ( $node . get ( 0 ) . tagName ) >= 0 && $node . find ( '.fr-marker' ) . length == 1 && editor . node . hasClass ( contents [ 0 ] , 'fr-marker' ) ) { $node . attr ( 'data-del-cell' , true ) ; }
for ( var i = 0 ; i < contents . length ; i ++ ) { var node = contents [ i ] ; if ( editor . node . hasClass ( node , 'fr-marker' ) ) { should _delete = ( should _delete + 1 ) % 2 ; }
else if ( should _delete ) { if ( $ ( node ) . find ( '.fr-marker' ) . length > 0 ) { should _delete = _processNodeDelete ( $ ( node ) , should _delete ) ; }
else { if ( [ 'TD' , 'TH' ] . indexOf ( node . tagName ) < 0 && ! editor . node . hasClass ( node , 'fr-inner' ) ) { if ( ! editor . opts . keepFormatOnDelete || editor . $el . find ( '[data-first]' ) . length > 0 || editor . node . isVoid ( node ) ) { $ ( node ) . remove ( ) ; }
else { _emptyInnerNodes ( node ) ; } }
else if ( editor . node . hasClass ( node , 'fr-inner' ) ) { if ( $ ( node ) . find ( '.fr-inner' ) . length === 0 ) { $ ( node ) . html ( '<br>' ) ; }
else { $ ( node ) . find ( '.fr-inner' ) . filter ( _filterFrInner ) . html ( '<br>' ) ; } }
else { $ ( node ) . empty ( ) ; $ ( node ) . attr ( 'data-del-cell' , true ) ; } } }
else { if ( $ ( node ) . find ( '.fr-marker' ) . length > 0 ) { should _delete = _processNodeDelete ( $ ( node ) , should _delete ) ; } } }
return should _delete ; }
function inEditor ( ) { try { if ( ! editor . $wp ) return false ; var range = ranges ( 0 ) ; var container = range . commonAncestorContainer ; while ( container && ! editor . node . isElement ( container ) ) { container = container . parentNode ; }
if ( editor . node . isElement ( container ) ) return true ; return false ; }
catch ( ex ) { return false ; } }
function remove ( ) { if ( isCollapsed ( ) ) return true ; var i ; save ( ) ; var _prevSibling = function ( node ) { var prev _node = node . previousSibling ; while ( prev _node && prev _node . nodeType == Node . TEXT _NODE && prev _node . textContent . length === 0 ) { var tmp = prev _node ; prev _node = prev _node . previousSibling ; $ ( tmp ) . remove ( ) ; }
return prev _node ; }
var _nextSibling = function ( node ) { var next _node = node . nextSibling ; while ( next _node && next _node . nodeType == Node . TEXT _NODE && next _node . textContent . length === 0 ) { var tmp = next _node ; next _node = next _node . nextSibling ; $ ( tmp ) . remove ( ) ; }
return next _node ; }
var start _markers = editor . $el . find ( '.fr-marker[data-type="true"]' ) ; for ( i = 0 ; i < start _markers . length ; i ++ ) { var sm = start _markers [ i ] ; while ( ! _prevSibling ( sm ) && ! editor . node . isBlock ( sm . parentNode ) && ! editor . $el . is ( sm . parentNode ) && ! editor . node . hasClass ( sm . parentNode , 'fr-inner' ) ) { $ ( sm . parentNode ) . before ( sm ) ; } }
var end _markers = editor . $el . find ( '.fr-marker[data-type="false"]' ) ; for ( i = 0 ; i < end _markers . length ; i ++ ) { var em = end _markers [ i ] ; while ( ! _nextSibling ( em ) && ! editor . node . isBlock ( em . parentNode ) && ! editor . $el . is ( em . parentNode ) && ! editor . node . hasClass ( em . parentNode , 'fr-inner' ) ) { $ ( em . parentNode ) . after ( em ) ; }
if ( em . parentNode && editor . node . isBlock ( em . parentNode ) && editor . node . isEmpty ( em . parentNode ) && ! editor . $el . is ( em . parentNode ) && ! editor . node . hasClass ( em . parentNode , 'fr-inner' ) && editor . opts . keepFormatOnDelete ) { $ ( em . parentNode ) . after ( em ) ; } }
if ( _canDelete ( ) ) { _processNodeDelete ( editor . $el , 0 ) ; var $first _node = editor . $el . find ( '[data-first="true"]' ) ; if ( $first _node . length ) { editor . $el . find ( '.fr-marker' ) . remove ( ) ; $first _node . append ( $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS ) . removeAttr ( 'data-first' ) ; if ( $first _node . attr ( 'data-text' ) ) { $first _node . replaceWith ( $first _node . html ( ) ) ; } }
else { editor . $el . find ( 'table' ) . filter ( function ( ) { var ok = $ ( this ) . find ( '[data-del-cell]' ) . length > 0 && $ ( this ) . find ( '[data-del-cell]' ) . length == $ ( this ) . find ( 'td, th' ) . length ; return ok ; } ) . remove ( ) ; editor . $el . find ( '[data-del-cell]' ) . removeAttr ( 'data-del-cell' ) ; start _markers = editor . $el . find ( '.fr-marker[data-type="true"]' ) ; for ( i = 0 ; i < start _markers . length ; i ++ ) { var start _marker = start _markers [ i ] ; var next _node = start _marker . nextSibling ; var end _marker = editor . $el . find ( '.fr-marker[data-type="false"][data-id="' + $ ( start _marker ) . data ( 'id' ) + '"]' ) . get ( 0 ) ; if ( end _marker ) { if ( start _marker && ! ( next _node && next _node == end _marker ) ) { var start _parent = editor . node . blockParent ( start _marker ) ; var end _parent = editor . node . blockParent ( end _marker ) ; var list _start = false ; var list _end = false ; if ( start _parent && [ 'UL' , 'OL' ] . indexOf ( start _parent . tagName ) >= 0 ) { start _parent = null ; list _start = true ; }
if ( end _parent && [ 'UL' , 'OL' ] . indexOf ( end _parent . tagName ) >= 0 ) { end _parent = null ; list _end = true ; }
$ ( start _marker ) . after ( end _marker ) ; if ( start _parent != end _parent ) { if ( start _parent == null && ! list _start ) { var deep _parent = editor . node . deepestParent ( start _marker ) ; if ( deep _parent ) { $ ( deep _parent ) . after ( $ ( end _parent ) . html ( ) ) ; $ ( end _parent ) . remove ( ) ; }
else if ( $ ( end _parent ) . parentsUntil ( editor . $el , 'table' ) . length === 0 ) { $ ( start _marker ) . next ( ) . after ( $ ( end _parent ) . html ( ) ) ; $ ( end _parent ) . remove ( ) ; } }
else if ( end _parent == null && ! list _end && $ ( start _parent ) . parentsUntil ( editor . $el , 'table' ) . length === 0 ) { next _node = start _parent ; while ( ! next _node . nextSibling && next _node . parentNode != editor . el ) { next _node = next _node . parentNode ; }
next _node = next _node . nextSibling ; while ( next _node && next _node . tagName != 'BR' ) { var tmp _node = next _node . nextSibling ; $ ( start _parent ) . append ( next _node ) ; next _node = tmp _node ; }
if ( next _node && next _node . tagName == 'BR' ) { $ ( next _node ) . remove ( ) ; } }
else if ( start _parent && end _parent && $ ( start _parent ) . parentsUntil ( editor . $el , 'table' ) . length === 0 && $ ( end _parent ) . parentsUntil ( editor . $el , 'table' ) . length === 0 && $ ( start _parent ) . find ( end _parent ) . length === 0 && $ ( end _parent ) . find ( start _parent ) . length === 0 ) { $ ( start _parent ) . append ( $ ( end _parent ) . html ( ) ) ; $ ( end _parent ) . remove ( ) ; } } } }
else { end _marker = $ ( start _marker ) . clone ( ) . attr ( 'data-type' , false ) ; $ ( start _marker ) . after ( end _marker ) ; } } } }
editor . $el . find ( 'li:empty' ) . remove ( )
if ( ! editor . opts . keepFormatOnDelete ) { editor . html . fillEmptyBlocks ( ) ; }
editor . html . cleanEmptyTags ( true ) ; if ( ! editor . opts . htmlUntouched ) { editor . clean . lists ( ) ; editor . $el . find ( 'li:empty' ) . append ( '<br>' ) ; editor . spaces . normalize ( ) ; }
var last _marker = editor . $el . find ( '.fr-marker:last' ) . get ( 0 ) ; var first _marker = editor . $el . find ( '.fr-marker:first' ) . get ( 0 ) ; if ( ( typeof last _marker !== 'undefined' && typeof first _marker !== 'undefined' ) && ! last _marker . nextSibling && first _marker . previousSibling && first _marker . previousSibling . tagName == 'BR' && editor . node . isElement ( last _marker . parentNode ) && editor . node . isElement ( first _marker . parentNode ) ) { editor . $el . append ( '<br>' ) ; }
restore ( ) ; }
function setAtStart ( node , deep ) { if ( ! node || node . getElementsByClassName ( 'fr-marker' ) . length > 0 ) return false ; var child = node . firstChild ; while ( child && ( editor . node . isBlock ( child ) || ( deep && ! editor . node . isVoid ( child ) && child . nodeType == Node . ELEMENT _NODE ) ) ) { node = child ; child = child . firstChild ; }
node . innerHTML = $ . FE . MARKERS + node . innerHTML ; }
function setAtEnd ( node , deep ) { if ( ! node || node . getElementsByClassName ( 'fr-marker' ) . length > 0 ) return false ; var child = node . lastChild ; while ( child && ( editor . node . isBlock ( child ) || ( deep && ! editor . node . isVoid ( child ) && child . nodeType == Node . ELEMENT _NODE ) ) ) { node = child ; child = child . lastChild ; }
var span = editor . doc . createElement ( 'SPAN' ) ; span . setAttribute ( 'id' , 'fr-sel-markers' ) ; span . innerHTML = $ . FE . MARKERS ; while ( node . parentNode && editor . opts . htmlAllowedEmptyTags && editor . opts . htmlAllowedEmptyTags . indexOf ( node . tagName . toLowerCase ( ) ) >= 0 ) { node = node . parentNode ; }
node . appendChild ( span ) ; var nd = node . querySelector ( '#fr-sel-markers' ) ; nd . outerHTML = nd . innerHTML ; }
function setBefore ( node , use _current _node ) { if ( typeof use _current _node == 'undefined' ) use _current _node = true ; var prev _node = node . previousSibling ; while ( prev _node && prev _node . nodeType == Node . TEXT _NODE && prev _node . textContent . length === 0 ) { prev _node = prev _node . previousSibling ; }
if ( prev _node ) { if ( editor . node . isBlock ( prev _node ) ) { setAtEnd ( prev _node ) ; }
else if ( prev _node . tagName == 'BR' ) { $ ( prev _node ) . before ( $ . FE . MARKERS ) ; }
else { $ ( prev _node ) . after ( $ . FE . MARKERS ) ; }
return true ; }
else if ( use _current _node ) { if ( editor . node . isBlock ( node ) ) { setAtStart ( node ) ; }
else { $ ( node ) . before ( $ . FE . MARKERS ) ; }
return true ; }
else { return false ; } }
function setAfter ( node , use _current _node ) { if ( typeof use _current _node == 'undefined' ) use _current _node = true ; var next _node = node . nextSibling ; while ( next _node && next _node . nodeType == Node . TEXT _NODE && next _node . textContent . length === 0 ) { next _node = next _node . nextSibling ; }
if ( next _node ) { if ( editor . node . isBlock ( next _node ) ) { setAtStart ( next _node ) ; }
else { $ ( next _node ) . before ( $ . FE . MARKERS ) ; }
return true ; }
else if ( use _current _node ) { if ( editor . node . isBlock ( node ) ) { setAtEnd ( node ) ; }
else { $ ( node ) . after ( $ . FE . MARKERS ) ; }
return true ; }
else { return false ; } }
return { text : text , get : get , ranges : ranges , clear : clear , element : element , endElement : endElement , save : save , restore : restore , isCollapsed : isCollapsed , isFull : isFull , inEditor : inEditor , remove : remove , blocks : blocks , info : info , setAtEnd : setAtEnd , setAtStart : setAtStart , setBefore : setBefore , setAfter : setAfter , rangeElement : rangeElement } } ; $ . extend ( $ . FE . DEFAULTS , { htmlAllowedTags : [ 'a' , 'abbr' , 'address' , 'area' , 'article' , 'aside' , 'audio' , 'b' , 'base' , 'bdi' , 'bdo' , 'blockquote' , 'br' , 'button' , 'canvas' , 'caption' , 'cite' , 'code' , 'col' , 'colgroup' , 'datalist' , 'dd' , 'del' , 'details' , 'dfn' , 'dialog' , 'div' , 'dl' , 'dt' , 'em' , 'embed' , 'fieldset' , 'figcaption' , 'figure' , 'footer' , 'form' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'header' , 'hgroup' , 'hr' , 'i' , 'iframe' , 'img' , 'input' , 'ins' , 'kbd' , 'keygen' , 'label' , 'legend' , 'li' , 'link' , 'main' , 'map' , 'mark' , 'menu' , 'menuitem' , 'meter' , 'nav' , 'noscript' , 'object' , 'ol' , 'optgroup' , 'option' , 'output' , 'p' , 'param' , 'pre' , 'progress' , 'queue' , 'rp' , 'rt' , 'ruby' , 's' , 'samp' , 'script' , 'style' , 'section' , 'select' , 'small' , 'source' , 'span' , 'strike' , 'strong' , 'sub' , 'summary' , 'sup' , 'table' , 'tbody' , 'td' , 'textarea' , 'tfoot' , 'th' , 'thead' , 'time' , 'tr' , 'track' , 'u' , 'ul' , 'var' , 'video' , 'wbr' ] , htmlRemoveTags : [ 'script' , 'style' ] , htmlAllowedAttrs : [ 'accept' , 'accept-charset' , 'accesskey' , 'action' , 'align' , 'allowfullscreen' , 'allowtransparency' , 'alt' , 'aria-.*' , 'async' , 'autocomplete' , 'autofocus' , 'autoplay' , 'autosave' , 'background' , 'bgcolor' , 'border' , 'charset' , 'cellpadding' , 'cellspacing' , 'checked' , 'cite' , 'class' , 'color' , 'cols' , 'colspan' , 'content' , 'contenteditable' , 'contextmenu' , 'controls' , 'coords' , 'data' , 'data-.*' , 'datetime' , 'default' , 'defer' , 'dir' , 'dirname' , 'disabled' , 'download' , 'draggable' , 'dropzone' , 'enctype' , 'for' , 'form' , 'formaction' , 'frameborder' , 'headers' , 'height' , 'hidden' , 'high' , 'href' , 'hreflang' , 'http-equiv' , 'icon' , 'id' , 'ismap' , 'itemprop' , 'keytype' , 'kind' , 'label' , 'lang' , 'language' , 'list' , 'loop' , 'low' , 'max' , 'maxlength' , 'media' , 'method' , 'min' , 'mozallowfullscreen' , 'multiple' , 'muted' , 'name' , 'novalidate' , 'open' , 'optimum' , 'pattern' , 'ping' , 'placeholder' , 'playsinline' , 'poster' , 'preload' , 'pubdate' , 'radiogroup' , 'readonly' , 'rel' , 'required' , 'reversed' , 'rows' , 'rowspan' , 'sandbox' , 'scope' , 'scoped' , 'scrolling' , 'seamless' , 'selected' , 'shape' , 'size' , 'sizes' , 'span' , 'src' , 'srcdoc' , 'srclang' , 'srcset' , 'start' , 'step' , 'summary' , 'spellcheck' , 'style' , 'tabindex' , 'target' , 'title' , 'type' , 'translate' , 'usemap' , 'value' , 'valign' , 'webkitallowfullscreen' , 'width' , 'wrap' ] , htmlAllowedStyleProps : [ '.*' ] , htmlAllowComments : true , htmlUntouched : false , fullPage : false } ) ; $ . FE . HTML5Map = { B : 'STRONG' , I : 'EM' , STRIKE : 'S' } , $ . FE . MODULES . clean = function ( editor ) { var allowedTagsRE ; var removeTagsRE ; var allowedAttrsRE ; var allowedStylePropsRE ; function _removeInvisible ( node ) { if ( node . nodeType == Node . ELEMENT _NODE && node . getAttribute ( 'class' ) && node . getAttribute ( 'class' ) . indexOf ( 'fr-marker' ) >= 0 ) return false ; var contents = editor . node . contents ( node ) ; var markers = [ ] ; var i ; for ( i = 0 ; i < contents . length ; i ++ ) { if ( contents [ i ] . nodeType == Node . ELEMENT _NODE && ! editor . node . isVoid ( contents [ i ] ) ) { if ( contents [ i ] . textContent . replace ( /\u200b/g , '' ) . length != contents [ i ] . textContent . length ) { _removeInvisible ( contents [ i ] ) ; } }
else if ( contents [ i ] . nodeType == Node . TEXT _NODE ) { contents [ i ] . textContent = contents [ i ] . textContent . replace ( /\u200b/g , '' ) ; } }
if ( node . nodeType == Node . ELEMENT _NODE && ! editor . node . isVoid ( node ) ) { node . normalize ( ) ; contents = editor . node . contents ( node ) ; markers = node . querySelectorAll ( '.fr-marker' ) ; if ( contents . length - markers . length === 0 ) { for ( i = 0 ; i < contents . length ; i ++ ) { if ( contents [ i ] . nodeType == Node . ELEMENT _NODE && ( contents [ i ] . getAttribute ( 'class' ) || '' ) . indexOf ( 'fr-marker' ) < 0 ) { return false ; } }
for ( i = 0 ; i < markers . length ; i ++ ) { node . parentNode . insertBefore ( markers [ i ] . cloneNode ( true ) , node ) ; }
node . parentNode . removeChild ( node ) ; return false ; } } }
function _toHTML ( el , is _pre ) { if ( el . nodeType == Node . COMMENT _NODE ) return '<!--' + el . nodeValue + '-->' ; if ( el . nodeType == Node . TEXT _NODE ) { if ( is _pre ) { return el . textContent . replace ( /\&/g , '&' ) . replace ( /</g , '<' ) . replace ( />/g , '>' ) ; }
return el . textContent . replace ( /\&/g , '&' ) . replace ( /</g , '<' ) . replace ( />/g , '>' ) . replace ( /\u00A0/g , ' ' ) . replace ( /\u0009/g , '' ) ; }
if ( el . nodeType != Node . ELEMENT _NODE ) return el . outerHTML ; if ( el . nodeType == Node . ELEMENT _NODE && [ 'STYLE' , 'SCRIPT' , 'NOSCRIPT' ] . indexOf ( el . tagName ) >= 0 ) return el . outerHTML ; if ( el . nodeType == Node . ELEMENT _NODE && el . tagName == 'svg' ) { var temp = document . createElement ( 'div' ) ; var node _clone = el . cloneNode ( true ) ; temp . appendChild ( node _clone ) ; return temp . innerHTML ; }
if ( el . tagName == 'IFRAME' ) { return el . outerHTML . replace ( /\</g , '<' ) . replace ( /\>/g , '>' ) ; }
var contents = el . childNodes ; if ( contents . length === 0 ) return el . outerHTML ; var str = '' ; for ( var i = 0 ; i < contents . length ; i ++ ) { if ( el . tagName == 'PRE' ) is _pre = true ; str += _toHTML ( contents [ i ] , is _pre ) ; }
return editor . node . openTagString ( el ) + str + editor . node . closeTagString ( el ) ; }
var scripts = [ ] ; function _encode ( dirty _html ) { scripts = [ ] ; dirty _html = dirty _html . replace ( /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi , function ( str ) { scripts . push ( str ) ; return '[FROALA.EDITOR.SCRIPT ' + ( scripts . length - 1 ) + ']' ; } ) ; dirty _html = dirty _html . replace ( /<noscript\b[^<]*(?:(?!<\/noscript>)<[^<]*)*<\/noscript>/gi , function ( str ) { scripts . push ( str ) ; return '[FROALA.EDITOR.NOSCRIPT ' + ( scripts . length - 1 ) + ']' ; } ) ; dirty _html = dirty _html . replace ( /<meta((?:[\w\W]*?)) http-equiv="/g , '<meta$1 data-fr-http-equiv="' ) ; dirty _html = dirty _html . replace ( /<img((?:[\w\W]*?)) src="/g , '<img$1 data-fr-src="' ) ; return dirty _html ; }
function _decode ( dirty _html ) { dirty _html = dirty _html . replace ( /\[FROALA\.EDITOR\.SCRIPT ([\d]*)\]/gi , function ( str , a1 ) { if ( editor . opts . htmlRemoveTags . indexOf ( 'script' ) >= 0 ) { return '' ; }
else { return scripts [ parseInt ( a1 , 10 ) ] ; } } ) ; dirty _html = dirty _html . replace ( /\[FROALA\.EDITOR\.NOSCRIPT ([\d]*)\]/gi , function ( str , a1 ) { if ( editor . opts . htmlRemoveTags . indexOf ( 'noscript' ) >= 0 ) { return '' ; }
else { return scripts [ parseInt ( a1 , 10 ) ] . replace ( /\</g , '<' ) . replace ( /\>/g , '>' ) ; } } ) ; dirty _html = dirty _html . replace ( /<img((?:[\w\W]*?)) data-fr-src="/g , '<img$1 src="' ) ; return dirty _html ; }
function _cleanStyle ( style ) { var cleaned _style = style . replace ( /;;/gi , ';' ) ; cleaned _style = cleaned _style . replace ( /^;/gi , '' ) ; if ( cleaned _style . charAt ( cleaned _style . length ) != ';' ) { cleaned _style += ';' ; }
return cleaned _style ; }
function _cleanAttrs ( attrs ) { var nm ; for ( nm in attrs ) { if ( attrs . hasOwnProperty ( nm ) ) { var is _attr _allowed = nm . match ( allowedAttrsRE ) ; var allowed _style _props _matches = null ; if ( nm == 'style' && editor . opts . htmlAllowedStyleProps . length ) { allowed _style _props _matches = attrs [ nm ] . match ( allowedStylePropsRE ) ; }
if ( is _attr _allowed && allowed _style _props _matches ) { attrs [ nm ] = _cleanStyle ( allowed _style _props _matches . join ( ';' ) ) ; }
else if ( ! is _attr _allowed || ( nm == 'style' && ! allowed _style _props _matches ) ) { delete attrs [ nm ] ; } } }
var str = '' ; var keys = Object . keys ( attrs ) . sort ( ) ; for ( var i = 0 ; i < keys . length ; i ++ ) { nm = keys [ i ] ; if ( attrs [ nm ] . indexOf ( '"' ) < 0 ) { str += ' ' + nm + '="' + attrs [ nm ] + '"' ; }
else { str += ' ' + nm + '=\'' + attrs [ nm ] + '\'' ; } }
return str ; }
function _rebuild ( body _html , head _html , original _html ) { if ( editor . opts . fullPage ) { var doctype = editor . html . extractDoctype ( original _html ) ; var html _attrs = _cleanAttrs ( editor . html . extractNodeAttrs ( original _html , 'html' ) ) ; head _html = head _html == null ? editor . html . extractNode ( original _html , 'head' ) || '<title></title>' : head _html ; var head _attrs = _cleanAttrs ( editor . html . extractNodeAttrs ( original _html , 'head' ) ) ; var body _attrs = _cleanAttrs ( editor . html . extractNodeAttrs ( original _html , 'body' ) ) ; return doctype + '<html' + html _attrs + '><head' + head _attrs + '>' + head _html + '</head><body' + body _attrs + '>' + body _html + '</body></html>' ; }
return body _html ; }
function _process ( html , func ) { var i ; var doc = document . implementation . createHTMLDocument ( 'Froala DOC' ) ; var el = doc . createElement ( 'DIV' ) ; $ ( el ) . append ( html ) ; var new _html = '' ; if ( el ) { var els = editor . node . contents ( el ) ; for ( i = 0 ; i < els . length ; i ++ ) { func ( els [ i ] ) ; }
els = editor . node . contents ( el ) ; for ( i = 0 ; i < els . length ; i ++ ) { new _html += _toHTML ( els [ i ] ) ; } }
return new _html ; }
function exec ( html , func , parse _head ) { html = _encode ( html ) ; var b _html = html ; var h _html = null ; if ( editor . opts . fullPage ) { b _html = ( editor . html . extractNode ( html , 'body' ) || ( html . indexOf ( '<body' ) >= 0 ? '' : html ) ) ; if ( parse _head ) { h _html = ( editor . html . extractNode ( html , 'head' ) || '' ) ; } }
b _html = _process ( b _html , func ) ; if ( h _html ) h _html = _process ( h _html , func ) ; var new _html = _rebuild ( b _html , h _html , html ) ; return _decode ( new _html ) ; }
function invisibleSpaces ( dirty _html ) { if ( dirty _html . replace ( /\u200b/g , '' ) . length == dirty _html . length ) return dirty _html ; return editor . clean . exec ( dirty _html , _removeInvisible ) ; }
function toHTML5 ( ) { var els = editor . el . querySelectorAll ( Object . keys ( $ . FE . HTML5Map ) . join ( ',' ) ) ; if ( els . length ) { var sel _saved = false ; if ( ! editor . el . querySelector ( '.fr-marker' ) ) { editor . selection . save ( ) ; sel _saved = true ; }
for ( var i = 0 ; i < els . length ; i ++ ) { if ( editor . node . attributes ( els [ i ] ) === '' ) { $ ( els [ i ] ) . replaceWith ( '<' + $ . FE . HTML5Map [ els [ i ] . tagName ] + '>' + els [ i ] . innerHTML + '</' + $ . FE . HTML5Map [ els [ i ] . tagName ] + '>' ) ; } }
if ( sel _saved ) { editor . selection . restore ( ) ; } } }
function _convertHref ( href ) { var div = editor . doc . createElement ( 'DIV' ) ; div . innerText = href ; return div . textContent ; }
function _node ( node ) { if ( node . tagName == 'SPAN' && ( node . getAttribute ( 'class' ) || '' ) . indexOf ( 'fr-marker' ) >= 0 ) return false ; if ( node . tagName == 'PRE' ) _cleanPre ( node ) ; if ( node . nodeType == Node . ELEMENT _NODE ) { if ( node . getAttribute ( 'data-fr-src' ) && node . getAttribute ( 'data-fr-src' ) . indexOf ( 'blob:' ) !== 0 ) node . setAttribute ( 'data-fr-src' , editor . helpers . sanitizeURL ( _convertHref ( node . getAttribute ( 'data-fr-src' ) ) ) ) ; if ( node . getAttribute ( 'href' ) ) node . setAttribute ( 'href' , editor . helpers . sanitizeURL ( _convertHref ( node . getAttribute ( 'href' ) ) ) ) ; if ( node . getAttribute ( 'src' ) ) node . setAttribute ( 'src' , editor . helpers . sanitizeURL ( _convertHref ( node . getAttribute ( 'src' ) ) ) ) ; if ( node . getAttribute ( 'data' ) ) node . setAttribute ( 'data' , editor . helpers . sanitizeURL ( _convertHref ( node . getAttribute ( 'data' ) ) ) ) ; if ( [ 'TABLE' , 'TBODY' , 'TFOOT' , 'TR' ] . indexOf ( node . tagName ) >= 0 ) { node . innerHTML = node . innerHTML . trim ( ) ; } }
if ( ! editor . opts . pasteAllowLocalImages && node . nodeType == Node . ELEMENT _NODE && node . tagName == 'IMG' && node . getAttribute ( 'data-fr-src' ) && node . getAttribute ( 'data-fr-src' ) . indexOf ( 'file://' ) === 0 ) { node . parentNode . removeChild ( node ) ; return false ; }
if ( node . nodeType == Node . ELEMENT _NODE && $ . FE . HTML5Map [ node . tagName ] && editor . node . attributes ( node ) === '' ) { var tg = $ . FE . HTML5Map [ node . tagName ] ; var new _node = '<' + tg + '>' + node . innerHTML + '</' + tg + '>' ; node . insertAdjacentHTML ( 'beforebegin' , new _node ) ; node = node . previousSibling ; node . parentNode . removeChild ( node . nextSibling ) ; }
if ( ! editor . opts . htmlAllowComments && node . nodeType == Node . COMMENT _NODE ) { if ( node . data . indexOf ( '[FROALA.EDITOR' ) !== 0 ) { node . parentNode . removeChild ( node ) ; } }
else if ( node . tagName && node . tagName . match ( removeTagsRE ) ) { node . parentNode . removeChild ( node ) ; }
else if ( node . tagName && ! node . tagName . match ( allowedTagsRE ) ) { if ( node . tagName === 'svg' ) { node . parentNode . removeChild ( node ) ; }
else if ( ! ( editor . browser . safari && node . tagName == 'path' && node . parentNode && node . parentNode . tagName == 'svg' ) ) { try { node . outerHTML = node . innerHTML ; }
catch ( ex ) { } } }
else { var attrs = node . attributes ; if ( attrs ) { for ( var i = attrs . length - 1 ; i >= 0 ; i -- ) { var attr = attrs [ i ] ; var is _attr _allowed = attr . nodeName . match ( allowedAttrsRE ) ; var allowed _style _props _matches = null ; if ( attr . nodeName == 'style' && editor . opts . htmlAllowedStyleProps . length ) { allowed _style _props _matches = attr . value . match ( allowedStylePropsRE ) ; }
if ( is _attr _allowed && allowed _style _props _matches ) { attr . value = _cleanStyle ( allowed _style _props _matches . join ( ';' ) ) ; }
else if ( ! is _attr _allowed || ( attr . nodeName == 'style' && ! allowed _style _props _matches ) ) { node . removeAttribute ( attr . nodeName ) ; } } } } }
function _run ( node ) { var contents = editor . node . contents ( node ) ; for ( var i = 0 ; i < contents . length ; i ++ ) { if ( contents [ i ] . nodeType != Node . TEXT _NODE ) { _run ( contents [ i ] ) ; } }
_node ( node ) ; }
function _cleanPre ( pre ) { var content = pre . innerHTML ; if ( content . indexOf ( '\n' ) >= 0 ) { pre . innerHTML = content . replace ( /\n/g , '<br>' ) ; } }
function html ( dirty _html , denied _tags , denied _attrs , full _page ) { if ( typeof denied _tags == 'undefined' ) denied _tags = [ ] ; if ( typeof denied _attrs == 'undefined' ) denied _attrs = [ ] ; if ( typeof full _page == 'undefined' ) full _page = false ; var allowed _tags = $ . merge ( [ ] , editor . opts . htmlAllowedTags ) ; var i ; for ( i = 0 ; i < denied _tags . length ; i ++ ) { if ( allowed _tags . indexOf ( denied _tags [ i ] ) >= 0 ) { allowed _tags . splice ( allowed _tags . indexOf ( denied _tags [ i ] ) , 1 ) ; } }
var allowed _attrs = $ . merge ( [ ] , editor . opts . htmlAllowedAttrs ) ; for ( i = 0 ; i < denied _attrs . length ; i ++ ) { if ( allowed _attrs . indexOf ( denied _attrs [ i ] ) >= 0 ) { allowed _attrs . splice ( allowed _attrs . indexOf ( denied _attrs [ i ] ) , 1 ) ; } }
allowed _attrs . push ( 'data-fr-.*' ) ; allowed _attrs . push ( 'fr-.*' ) ; allowedTagsRE = new RegExp ( '^' + allowed _tags . join ( '$|^' ) + '$' , 'gi' ) ; allowedAttrsRE = new RegExp ( '^' + allowed _attrs . join ( '$|^' ) + '$' , 'gi' ) ; removeTagsRE = new RegExp ( '^' + editor . opts . htmlRemoveTags . join ( '$|^' ) + '$' , 'gi' ) ; if ( editor . opts . htmlAllowedStyleProps . length ) { allowedStylePropsRE = new RegExp ( '((^|;|\\s)' + editor . opts . htmlAllowedStyleProps . join ( ':.+?(?=;|$))|((^|;|\\s)' ) + ':.+?(?=(;)|$))' , 'gi' ) ; }
else { allowedStylePropsRE = null ; }
dirty _html = exec ( dirty _html , _run , true ) ; return dirty _html ; }
function _tablesWrapTHEAD ( ) { var trs = editor . el . querySelectorAll ( 'tr' ) ; for ( var i = 0 ; i < trs . length ; i ++ ) { var children = trs [ i ] . children ; var ok = true ; for ( var j = 0 ; j < children . length ; j ++ ) { if ( children [ j ] . tagName != 'TH' ) { ok = false ; break ; } }
if ( ok === false || children . length === 0 ) continue ; var tr = trs [ i ] ; while ( tr && tr . tagName != 'TABLE' && tr . tagName != 'THEAD' ) { tr = tr . parentNode ; }
var thead = tr ; if ( thead . tagName != 'THEAD' ) { thead = editor . doc . createElement ( 'THEAD' ) ; tr . insertBefore ( thead , tr . firstChild ) ; }
thead . appendChild ( trs [ i ] ) ; } }
function tables ( ) { _tablesWrapTHEAD ( ) ; }
function _listsWrapMissplacedLI ( ) { var lis = [ ] ; var filterListItem = function ( li ) { return ! editor . node . isList ( li . parentNode ) ; } ; do { if ( lis . length ) { var li = lis [ 0 ] ; var ul = editor . doc . createElement ( 'ul' ) ; li . parentNode . insertBefore ( ul , li ) ; do { var tmp = li ; li = li . nextSibling ; ul . appendChild ( tmp ) ; } while ( li && li . tagName == 'LI' ) ; }
lis = [ ] ; var li _sel = editor . el . querySelectorAll ( 'li' ) ; for ( var i = 0 ; i < li _sel . length ; i ++ ) { if ( filterListItem ( li _sel [ i ] ) ) lis . push ( li _sel [ i ] ) ; } } while ( lis . length > 0 ) ; }
function _listsJoinSiblings ( ) { var sibling _lists = editor . el . querySelectorAll ( 'ol + ol, ul + ul' ) ; for ( var k = 0 ; k < sibling _lists . length ; k ++ ) { var list = sibling _lists [ k ] ; if ( editor . node . isList ( list . previousSibling ) && editor . node . openTagString ( list ) == editor . node . openTagString ( list . previousSibling ) ) { var childs = editor . node . contents ( list ) ; for ( var i = 0 ; i < childs . length ; i ++ ) { list . previousSibling . appendChild ( childs [ i ] ) ; }
list . parentNode . removeChild ( list ) ; } } }
function _listsRemoveEmpty ( ) { var i ; var do _remove ; var removeEmptyList = function ( lst ) { if ( ! lst . querySelector ( 'LI' ) ) { do _remove = true ; lst . parentNode . removeChild ( lst ) ; } } ; do { do _remove = false ; var empty _lis = editor . el . querySelectorAll ( 'li:empty' ) ; for ( i = 0 ; i < empty _lis . length ; i ++ ) { empty _lis [ i ] . parentNode . removeChild ( empty _lis [ i ] ) ; }
var remaining _lists = editor . el . querySelectorAll ( 'ul, ol' ) ; for ( i = 0 ; i < remaining _lists . length ; i ++ ) { removeEmptyList ( remaining _lists [ i ] ) ; } } while ( do _remove === true ) ; }
function _listsWrapLists ( ) { var direct _lists = editor . el . querySelectorAll ( 'ul > ul, ol > ol, ul > ol, ol > ul' ) ; for ( var i = 0 ; i < direct _lists . length ; i ++ ) { var list = direct _lists [ i ] ; var prev _li = list . previousSibling ; if ( prev _li ) { if ( prev _li . tagName == 'LI' ) { prev _li . appendChild ( list ) ; }
else { $ ( list ) . wrap ( '<li></li>' ) ; } } } }
function _listsNoTagAfterNested ( ) { var nested _lists = editor . el . querySelectorAll ( 'li > ul, li > ol' ) ; for ( var i = 0 ; i < nested _lists . length ; i ++ ) { var lst = nested _lists [ i ] ; if ( lst . nextSibling ) { var node = lst . nextSibling ; var $new _li = $ ( '<li>' ) ; $ ( lst . parentNode ) . after ( $new _li ) ; do { var tmp = node ; node = node . nextSibling ; $new _li . append ( tmp ) ; } while ( node ) ; } } }
function _listsTypeInNested ( ) { var nested _lists = editor . el . querySelectorAll ( 'li > ul, li > ol' ) ; for ( var i = 0 ; i < nested _lists . length ; i ++ ) { var lst = nested _lists [ i ] ; if ( editor . node . isFirstSibling ( lst ) ) { $ ( lst ) . before ( '<br/>' ) ; }
else if ( lst . previousSibling && lst . previousSibling . tagName == 'BR' ) { var prev _node = lst . previousSibling . previousSibling ; while ( prev _node && editor . node . hasClass ( prev _node , 'fr-marker' ) ) { prev _node = prev _node . previousSibling ; }
if ( prev _node && prev _node . tagName != 'BR' ) { $ ( lst . previousSibling ) . remove ( ) ; } } } }
function _listsRemoveEmptyLI ( ) { var empty _lis = editor . el . querySelectorAll ( 'li:empty' ) ; for ( var i = 0 ; i < empty _lis . length ; i ++ ) { $ ( empty _lis [ i ] ) . remove ( ) ; } }
function _listsFindMissplacedText ( ) { var lists = editor . el . querySelectorAll ( 'ul, ol' ) ; for ( var i = 0 ; i < lists . length ; i ++ ) { var contents = editor . node . contents ( lists [ i ] ) ; var $li = null ; for ( var j = contents . length - 1 ; j >= 0 ; j -- ) { if ( contents [ j ] . tagName != 'LI' && contents [ j ] . tagName != 'UL' && contents [ j ] . tagName != 'OL' ) { if ( ! $li ) { $li = $ ( '<li>' ) ; $li . insertBefore ( contents [ j ] ) ; }
$li . prepend ( contents [ j ] ) ; }
else { $li = null ; } } } }
function lists ( ) { _listsWrapMissplacedLI ( ) ; _listsJoinSiblings ( ) ; _listsFindMissplacedText ( ) ; _listsRemoveEmpty ( ) ; _listsWrapLists ( ) ; _listsNoTagAfterNested ( ) ; _listsTypeInNested ( ) ; _listsRemoveEmptyLI ( ) ; }
function _init ( ) { if ( editor . opts . fullPage ) { $ . merge ( editor . opts . htmlAllowedTags , [ 'head' , 'title' , 'style' , 'link' , 'base' , 'body' , 'html' , 'meta' ] ) ; } }
return { _init : _init , html : html , toHTML5 : toHTML5 , tables : tables , lists : lists , invisibleSpaces : invisibleSpaces , exec : exec } } ; $ . FE . MODULES . spaces = function ( editor ) { function _normalizeNode ( node , browser _way ) { var p _node = node . previousSibling ; var n _node = node . nextSibling ; var txt = node . textContent ; var parent _node = node . parentNode ; if ( editor . html . isPreformatted ( parent _node ) ) return ; if ( browser _way ) { txt = txt . replace ( /[\f\n\r\t\v ]{2,}/g , ' ' ) ; if ( ( ! n _node || n _node . tagName === 'BR' || editor . node . isBlock ( n _node ) ) && ( editor . node . isBlock ( parent _node ) || ( editor . node . isLink ( parent _node ) && ! parent _node . nextSibling ) || editor . node . isElement ( parent _node ) ) ) { txt = txt . replace ( /[\f\n\r\t\v ]{1,}$/g , '' ) ; }
if ( ( ! p _node || p _node . tagName === 'BR' || editor . node . isBlock ( p _node ) ) && ( editor . node . isBlock ( parent _node ) || ( editor . node . isLink ( parent _node ) && ! parent _node . previousSibling ) || editor . node . isElement ( parent _node ) ) ) { txt = txt . replace ( /^[\f\n\r\t\v ]{1,}/g , '' ) ; }
if ( editor . node . isBlock ( n _node ) || editor . node . isBlock ( p _node ) ) { txt = txt . replace ( /^[\f\n\r\t\v ]{1,}/g , '' ) ; }
if ( txt === ' ' && ( ( p _node && editor . node . isVoid ( p _node ) ) || ( n _node && editor . node . isVoid ( n _node ) ) ) && ! ( ( p _node && n _node && editor . node . isVoid ( p _node ) ) || ( n _node && p _node && editor . node . isVoid ( n _node ) ) ) ) { txt = '' ; } }
if ( ( ( ! p _node && editor . node . isBlock ( n _node ) ) || ( ! n _node && editor . node . isBlock ( p _node ) ) ) && editor . node . isBlock ( parent _node ) && parent _node !== editor . el ) { txt = txt . replace ( /^[\f\n\r\t\v ]{1,}/g , '' ) ; }
if ( ! browser _way ) { txt = txt . replace ( new RegExp ( $ . FE . UNICODE _NBSP , 'g' ) , ' ' ) ; }
var new _text = '' ; for ( var t = 0 ; t < txt . length ; t ++ ) { if ( txt . charCodeAt ( t ) == 32 && ( t === 0 || new _text . charCodeAt ( t - 1 ) == 32 ) && ! ( ( p _node && n _node && editor . node . isVoid ( p _node ) ) || ( p _node && n _node && editor . node . isVoid ( n _node ) ) ) ) { new _text += $ . FE . UNICODE _NBSP ; }
else { new _text += txt [ t ] ; } }
if ( ! n _node || ( n _node && editor . node . isBlock ( n _node ) ) || ( n _node && n _node . nodeType == Node . ELEMENT _NODE && editor . win . getComputedStyle ( n _node ) && editor . win . getComputedStyle ( n _node ) . display == 'block' ) ) { if ( ! editor . node . isVoid ( p _node ) ) { new _text = new _text . replace ( / $/ , $ . FE . UNICODE _NBSP ) ; } }
if ( p _node && ! editor . node . isVoid ( p _node ) && ! editor . node . isBlock ( p _node ) ) { new _text = new _text . replace ( /^\u00A0([^ $])/ , ' $1' ) ; if ( new _text . length === 1 && new _text . charCodeAt ( 0 ) === 160 && n _node && ! editor . node . isVoid ( n _node ) && ! editor . node . isBlock ( n _node ) ) { if ( ! ( editor . node . hasClass ( p _node , 'fr-marker' ) && editor . node . hasClass ( n _node , 'fr-marker' ) ) ) { new _text = ' ' ; } } }
if ( ! browser _way ) { new _text = new _text . replace ( /([^ \u00A0])\u00A0([^ \u00A0])/g , '$1 $2' ) ; }
if ( node . textContent != new _text ) { node . textContent = new _text ; } }
function normalize ( el , browser _way ) { if ( typeof el == 'undefined' || ! el ) el = editor . el ; if ( typeof browser _way == 'undefined' ) browser _way = false ; if ( el . getAttribute && el . getAttribute ( 'contenteditable' ) == 'false' ) return ; if ( el . nodeType == Node . TEXT _NODE ) { _normalizeNode ( el , browser _way ) }
else if ( el . nodeType == Node . ELEMENT _NODE ) { var walker = editor . doc . createTreeWalker ( el , NodeFilter . SHOW _TEXT , editor . node . filter ( function ( node ) { var temp _node = node . parentNode ; while ( temp _node && temp _node !== editor . el ) { if ( temp _node . tagName == 'STYLE' || temp _node . tagName == 'IFRAME' ) { return false ; }
if ( temp _node . tagName !== 'PRE' ) { temp _node = temp _node . parentNode ; }
else { return false ; } }
return node . textContent . match ( /([ \u00A0\f\n\r\t\v]{2,})|(^[ \u00A0\f\n\r\t\v]{1,})|([ \u00A0\f\n\r\t\v]{1,}$)/g ) != null && ! editor . node . hasClass ( node . parentNode , 'fr-marker' ) ; } ) , false ) ; while ( walker . nextNode ( ) ) { _normalizeNode ( walker . currentNode , browser _way ) ; } } }
function normalizeAroundCursor ( ) { var nodes = [ ] ; var markers = editor . el . querySelectorAll ( '.fr-marker' ) ; for ( var i = 0 ; i < markers . length ; i ++ ) { var node = null ; var p _node = editor . node . blockParent ( markers [ i ] ) ; if ( p _node ) { node = p _node ; }
else { node = markers [ i ] ; }
var next _node = node . nextSibling ; var prev _node = node . previousSibling ; while ( next _node && next _node . tagName == 'BR' ) next _node = next _node . nextSibling ; while ( prev _node && prev _node . tagName == 'BR' ) prev _node = prev _node . previousSibling ; if ( node && nodes . indexOf ( node ) < 0 ) nodes . push ( node ) ; if ( prev _node && nodes . indexOf ( prev _node ) < 0 ) nodes . push ( prev _node ) ; if ( next _node && nodes . indexOf ( next _node ) < 0 ) nodes . push ( next _node ) ; }
for ( var j = 0 ; j < nodes . length ; j ++ ) { normalize ( nodes [ j ] ) ; } }
return { normalize : normalize , normalizeAroundCursor : normalizeAroundCursor } } ; $ . FE . UNICODE _NBSP = String . fromCharCode ( 160 ) ; $ . FE . VOID _ELEMENTS = [ 'area' , 'base' , 'br' , 'col' , 'embed' , 'hr' , 'img' , 'input' , 'keygen' , 'link' , 'menuitem' , 'meta' , 'param' , 'source' , 'track' , 'wbr' ] ; $ . FE . BLOCK _TAGS = [ 'address' , 'article' , 'aside' , 'audio' , 'blockquote' , 'canvas' , 'details' , 'dd' , 'div' , 'dl' , 'dt' , 'fieldset' , 'figcaption' , 'figure' , 'footer' , 'form' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'header' , 'hgroup' , 'hr' , 'li' , 'main' , 'nav' , 'noscript' , 'ol' , 'output' , 'p' , 'pre' , 'section' , 'table' , 'tbody' , 'td' , 'tfoot' , 'th' , 'thead' , 'tr' , 'ul' , 'video' ] ; $ . extend ( $ . FE . DEFAULTS , { htmlAllowedEmptyTags : [ 'textarea' , 'a' , 'iframe' , 'object' , 'video' , 'style' , 'script' , '.fa' , '.fr-emoticon' , '.fr-inner' , 'path' , 'line' ] , htmlDoNotWrapTags : [ 'script' , 'style' ] , htmlSimpleAmpersand : false , htmlIgnoreCSSProperties : [ ] , htmlExecuteScripts : true } ) ; $ . FE . MODULES . html = function ( editor ) { function defaultTag ( ) { if ( editor . opts . enter == $ . FE . ENTER _P ) return 'p' ; if ( editor . opts . enter == $ . FE . ENTER _DIV ) return 'div' ; if ( editor . opts . enter == $ . FE . ENTER _BR ) return null ; }
function isPreformatted ( node , look _up ) { if ( ! node || node === editor . el ) return false ; if ( ! look _up ) { return [ 'PRE' , 'SCRIPT' , 'STYLE' ] . indexOf ( node . tagName ) != - 1 ; }
else { if ( [ 'PRE' , 'SCRIPT' , 'STYLE' ] . indexOf ( node . tagName ) != - 1 ) { return true ; }
else { return isPreformatted ( node . parentNode , look _up ) ; } } }
function emptyBlocks ( around _markers ) { var empty _blocks = [ ] ; var i ; var els = [ ] ; if ( around _markers ) { var markers = editor . el . querySelectorAll ( '.fr-marker' ) ; for ( i = 0 ; i < markers . length ; i ++ ) { var p _node = editor . node . blockParent ( markers [ i ] ) || markers [ i ] ; if ( p _node ) { var next _node = p _node . nextSibling ; var prev _node = p _node . previousSibling ; if ( p _node && els . indexOf ( p _node ) < 0 && editor . node . isBlock ( p _node ) ) els . push ( p _node ) ; if ( prev _node && editor . node . isBlock ( prev _node ) && els . indexOf ( prev _node ) < 0 ) els . push ( prev _node ) ; if ( next _node && editor . node . isBlock ( next _node ) && els . indexOf ( next _node ) < 0 ) els . push ( next _node ) ; } } }
else { els = editor . el . querySelectorAll ( blockTagsQuery ( ) ) ; }
var qr = blockTagsQuery ( ) ; qr += ',' + $ . FE . VOID _ELEMENTS . join ( ',' ) ; qr += ', .fr-inner' , qr += ',' + editor . opts . htmlAllowedEmptyTags . join ( ':not(.fr-marker),' ) + ':not(.fr-marker)' ; for ( i = els . length - 1 ; i >= 0 ; i -- ) { if ( els [ i ] . textContent && els [ i ] . textContent . replace ( /\u200B|\n/g , '' ) . length > 0 ) continue ; if ( els [ i ] . querySelectorAll ( qr ) . length > 0 ) continue ; var contents = editor . node . contents ( els [ i ] ) ; var found = false ; for ( var j = 0 ; j < contents . length ; j ++ ) { if ( contents [ j ] . nodeType == Node . COMMENT _NODE ) continue ; if ( contents [ j ] . textContent && contents [ j ] . textContent . replace ( /\u200B|\n/g , '' ) . length > 0 ) { found = true ; break ; } }
if ( ! found ) empty _blocks . push ( els [ i ] ) ; }
return empty _blocks ; }
function emptyBlockTagsQuery ( ) { return $ . FE . BLOCK _TAGS . join ( ':empty, ' ) + ':empty' ; }
function blockTagsQuery ( ) { return $ . FE . BLOCK _TAGS . join ( ', ' ) ; }
function cleanEmptyTags ( remove _blocks ) { var els = $ . merge ( [ ] , $ . FE . VOID _ELEMENTS ) ; els = $ . merge ( els , editor . opts . htmlAllowedEmptyTags ) ; if ( typeof remove _blocks == 'undefined' ) { els = $ . merge ( els , $ . FE . BLOCK _TAGS ) ; }
else { els = $ . merge ( els , $ . FE . NO _DELETE _TAGS ) ; }
var elms ; var ok ; elms = editor . el . querySelectorAll ( '*:empty:not(' + els . join ( '):not(' ) + '):not(.fr-marker)' ) ; do { ok = false ; for ( var i = 0 ; i < elms . length ; i ++ ) { if ( elms [ i ] . attributes . length === 0 || typeof elms [ i ] . getAttribute ( 'href' ) !== 'undefined' ) { elms [ i ] . parentNode . removeChild ( elms [ i ] ) ; ok = true ; } }
elms = editor . el . querySelectorAll ( '*:empty:not(' + els . join ( '):not(' ) + '):not(.fr-marker)' ) ; } while ( elms . length && ok ) ; }
function _wrapElement ( el , temp ) { var default _tag = defaultTag ( ) ; if ( temp ) default _tag = 'div' ; if ( default _tag ) { var main _doc = editor . doc . createDocumentFragment ( ) ; var anchor = null ; var found = false ; var node = el . firstChild ; var changed = false ; while ( node ) { var next _node = node . nextSibling ; if ( node . nodeType == Node . ELEMENT _NODE && ( editor . node . isBlock ( node ) || ( editor . opts . htmlDoNotWrapTags . indexOf ( node . tagName . toLowerCase ( ) ) >= 0 && ! editor . node . hasClass ( node , 'fr-marker' ) ) ) ) { anchor = null ; main _doc . appendChild ( node . cloneNode ( true ) ) ; }
else if ( node . nodeType != Node . ELEMENT _NODE && node . nodeType != Node . TEXT _NODE ) { anchor = null ; main _doc . appendChild ( node . cloneNode ( true ) ) ; }
else if ( node . tagName == 'BR' ) { if ( anchor == null ) { anchor = editor . doc . createElement ( default _tag ) ; changed = true ; if ( temp ) { anchor . setAttribute ( 'class' , 'fr-temp-div' ) ; anchor . setAttribute ( 'data-empty' , true ) ; }
anchor . appendChild ( node . cloneNode ( true ) ) ; main _doc . appendChild ( anchor ) ; }
else { if ( found === false ) { anchor . appendChild ( editor . doc . createElement ( 'br' ) ) ; if ( temp ) { anchor . setAttribute ( 'class' , 'fr-temp-div' ) ; anchor . setAttribute ( 'data-empty' , true ) ; } } }
anchor = null ; }
else { var txt = node . textContent ; if ( node . nodeType !== Node . TEXT _NODE || ( txt . replace ( /\n/g , '' ) . replace ( /(^ *)|( *$)/g , '' ) . length > 0 || ( txt . replace ( /(^ *)|( *$)/g , '' ) . length && txt . indexOf ( '\n' ) < 0 ) ) ) { if ( anchor == null ) { anchor = editor . doc . createElement ( default _tag ) ; changed = true ; if ( temp ) anchor . setAttribute ( 'class' , 'fr-temp-div' ) ; main _doc . appendChild ( anchor ) ; found = false ; }
anchor . appendChild ( node . cloneNode ( true ) ) ; if ( ! found && ( ! editor . node . hasClass ( node , 'fr-marker' ) && ! ( node . nodeType == Node . TEXT _NODE && txt . replace ( / /g , '' ) . length === 0 ) ) ) { found = true ; } }
else { changed = true ; } }
node = next _node ; }
if ( changed ) { el . innerHTML = '' ; el . appendChild ( main _doc ) ; } } }
function _wrapElements ( els , temp ) { for ( var i = els . length - 1 ; i >= 0 ; i -- ) { _wrapElement ( els [ i ] , temp ) ; } }
function _wrap ( temp , tables , blockquote , inner , li ) { if ( ! editor . $wp ) return false ; if ( typeof temp == 'undefined' ) temp = false ; if ( typeof tables == 'undefined' ) tables = false ; if ( typeof blockquote == 'undefined' ) blockquote = false ; if ( typeof inner == 'undefined' ) inner = false ; if ( typeof li == 'undefined' ) li = false ; var wp _st = editor . $wp . scrollTop ( ) ; _wrapElement ( editor . el , temp ) ; if ( inner ) { _wrapElements ( editor . el . querySelectorAll ( '.fr-inner' ) , temp ) ; }
if ( tables ) { _wrapElements ( editor . el . querySelectorAll ( 'td, th' ) , temp ) ; }
if ( blockquote ) { _wrapElements ( editor . el . querySelectorAll ( 'blockquote' ) , temp ) ; }
if ( li ) { _wrapElements ( editor . el . querySelectorAll ( 'li' ) , temp ) ; }
if ( wp _st != editor . $wp . scrollTop ( ) ) { editor . $wp . scrollTop ( wp _st ) ; } }
function unwrap ( ) { editor . $el . find ( 'div.fr-temp-div' ) . each ( function ( ) { if ( this . previousSibling && this . previousSibling . nodeType === Node . TEXT _NODE ) { $ ( this ) . before ( '<br>' ) ; }
if ( $ ( this ) . attr ( 'data-empty' ) || ! this . nextSibling || ( editor . node . isBlock ( this . nextSibling ) && ! $ ( this . nextSibling ) . hasClass ( 'fr-temp-div' ) ) ) { $ ( this ) . replaceWith ( $ ( this ) . html ( ) ) ; }
else { $ ( this ) . replaceWith ( $ ( this ) . html ( ) + '<br>' ) ; } } ) ; editor . $el . find ( '.fr-temp-div' ) . removeClass ( 'fr-temp-div' ) . filter ( function ( ) { return $ ( this ) . attr ( 'class' ) === '' ; } ) . removeAttr ( 'class' ) ; }
function fillEmptyBlocks ( around _markers ) { var blocks = emptyBlocks ( around _markers ) ; if ( editor . node . isEmpty ( editor . el ) && editor . opts . enter === $ . FE . ENTER _BR ) { blocks . push ( editor . el ) }
for ( var i = 0 ; i < blocks . length ; i ++ ) { var block = blocks [ i ] ; if ( block . getAttribute ( 'contenteditable' ) !== 'false' && ! block . querySelector ( editor . opts . htmlAllowedEmptyTags . join ( ':not(.fr-marker),' ) + ':not(.fr-marker)' ) && ! editor . node . isVoid ( block ) ) { if ( block . tagName != 'TABLE' && block . tagName != 'TBODY' && block . tagName != 'TR' && block . tagName != 'UL' && block . tagName != 'OL' ) block . appendChild ( editor . doc . createElement ( 'br' ) ) ; } }
if ( editor . browser . msie && editor . opts . enter == $ . FE . ENTER _BR ) { var contents = editor . node . contents ( editor . el ) ; if ( contents . length && contents [ contents . length - 1 ] . nodeType == Node . TEXT _NODE ) { editor . $el . append ( '<br>' ) ; } } }
function blocks ( ) { return editor . $el . get ( 0 ) . querySelectorAll ( blockTagsQuery ( ) ) ; }
function cleanBlankSpaces ( el ) { if ( typeof el == 'undefined' ) el = editor . el ; if ( el && [ 'SCRIPT' , 'STYLE' , 'PRE' ] . indexOf ( el . tagName ) >= 0 ) return false ; var walker = editor . doc . createTreeWalker ( el , NodeFilter . SHOW _TEXT , editor . node . filter ( function ( node ) { return node . textContent . match ( /([ \n]{2,})|(^[ \n]{1,})|([ \n]{1,}$)/g ) != null ; } ) , false ) ; while ( walker . nextNode ( ) ) { var node = walker . currentNode ; if ( isPreformatted ( node . parentNode , true ) ) continue ; var is _block _or _element = editor . node . isBlock ( node . parentNode ) || editor . node . isElement ( node . parentNode ) ; var txt = node . textContent . replace ( /(?!^)( ){2,}(?!$)/g , ' ' ) . replace ( /\n/g , ' ' ) . replace ( /^[ ]{2,}/g , ' ' ) . replace ( /[ ]{2,}$/g , ' ' ) ; if ( is _block _or _element ) { var p _node = node . previousSibling ; var n _node = node . nextSibling ; if ( p _node && n _node && txt == ' ' ) { if ( editor . node . isBlock ( p _node ) && editor . node . isBlock ( n _node ) ) { txt = '' ; }
else { txt = ' ' ; } }
else { if ( ! p _node ) txt = txt . replace ( /^ */ , '' ) ; if ( ! n _node ) txt = txt . replace ( / *$/ , '' ) ; } }
node . textContent = txt ; } }
function _extractMatch ( html , re , id ) { var reg _exp = new RegExp ( re , 'gi' ) ; var matches = reg _exp . exec ( html ) ; if ( matches ) { return matches [ id ] ; }
return null ; }
function _newDoctype ( string , doc ) { var matches = string . match ( /<!DOCTYPE ?([^ ]*) ?([^ ]*) ?"?([^"]*)"? ?"?([^"]*)"?>/i ) ; if ( matches ) { return doc . implementation . createDocumentType ( matches [ 1 ] , matches [ 3 ] , matches [ 4 ] ) }
else { return doc . implementation . createDocumentType ( 'html' ) ; } }
function getDoctype ( doc ) { var node = doc . doctype ; var doctype = '<!DOCTYPE html>' ; if ( node ) { doctype = '<!DOCTYPE '
+ node . name
+ ( node . publicId ? ' PUBLIC "' + node . publicId + '"' : '' )
+ ( ! node . publicId && node . systemId ? ' SYSTEM' : '' )
+ ( node . systemId ? ' "' + node . systemId + '"' : '' )
+ '>' ; }
return doctype ; }
function _processBR ( br ) { var parent _node = br . parentNode ; if ( parent _node && ( editor . node . isBlock ( parent _node ) || editor . node . isElement ( parent _node ) ) && [ 'TD' , 'TH' ] . indexOf ( parent _node . tagName ) < 0 ) { var prev _node = br . previousSibling ; var next _node = br . nextSibling ; while ( prev _node && ( ( prev _node . nodeType == Node . TEXT _NODE && prev _node . textContent . replace ( /\n|\r/g , '' ) . length === 0 ) || editor . node . hasClass ( prev _node , 'fr-tmp' ) ) ) { prev _node = prev _node . previousSibling ; }
if ( next _node ) return false ; if ( prev _node && parent _node && prev _node . tagName != 'BR' && ! editor . node . isBlock ( prev _node ) && ! next _node && parent _node . textContent . replace ( /\u200B/g , '' ) . length > 0 && prev _node . textContent . length > 0 && ! editor . node . hasClass ( prev _node , 'fr-marker' ) ) { if ( ! ( editor . el == parent _node && ! next _node && editor . opts . enter == $ . FE . ENTER _BR && editor . browser . msie ) ) { br . parentNode . removeChild ( br ) ; } } }
else if ( parent _node && ! ( editor . node . isBlock ( parent _node ) || editor . node . isElement ( parent _node ) ) ) { if ( ! br . previousSibling && ! br . nextSibling && editor . node . isDeletable ( br . parentNode ) ) { _processBR ( br . parentNode ) ; } } }
function cleanBRs ( ) { var brs = editor . el . getElementsByTagName ( 'br' ) ; for ( var i = 0 ; i < brs . length ; i ++ ) { _processBR ( brs [ i ] ) ; } }
function _normalize ( ) { if ( ! editor . opts . htmlUntouched ) { cleanEmptyTags ( ) ; _wrap ( ) ; cleanBlankSpaces ( ) ; editor . spaces . normalize ( null , true ) ; editor . html . fillEmptyBlocks ( ) ; editor . clean . lists ( ) ; editor . clean . tables ( ) ; editor . clean . toHTML5 ( ) ; editor . html . cleanBRs ( ) ; }
editor . selection . restore ( ) ; checkIfEmpty ( ) ; editor . placeholder . refresh ( ) ; }
function checkIfEmpty ( ) { if ( editor . node . isEmpty ( editor . el ) ) { if ( defaultTag ( ) != null ) { if ( ! editor . el . querySelector ( blockTagsQuery ( ) ) && ! editor . el . querySelector ( editor . opts . htmlDoNotWrapTags . join ( ':not(.fr-marker),' ) + ':not(.fr-marker)' ) ) { if ( editor . core . hasFocus ( ) ) { editor . $el . html ( '<' + defaultTag ( ) + '>' + $ . FE . MARKERS + '<br/></' + defaultTag ( ) + '>' ) ; editor . selection . restore ( ) ; }
else { editor . $el . html ( '<' + defaultTag ( ) + '>' + '<br/></' + defaultTag ( ) + '>' ) ; } } }
else { if ( ! editor . el . querySelector ( '*:not(.fr-marker):not(br)' ) ) { if ( editor . core . hasFocus ( ) ) { editor . $el . html ( $ . FE . MARKERS + '<br/>' ) ; editor . selection . restore ( ) ; }
else { editor . $el . html ( '<br/>' ) ; } } } } }
function extractNode ( html , tag ) { return _extractMatch ( html , '<' + tag + '[^>]*?>([\\w\\W]*)<\/' + tag + '>' , 1 ) ; }
function extractNodeAttrs ( html , tag ) { var $dv = $ ( '<div ' + ( _extractMatch ( html , '<' + tag + '([^>]*?)>' , 1 ) || '' ) + '>' ) ; return editor . node . rawAttributes ( $dv . get ( 0 ) ) ; }
function extractDoctype ( html ) { return ( _extractMatch ( html , '<!DOCTYPE([^>]*?)>' , 0 ) || '<!DOCTYPE html>' ) . replace ( /\n/g , ' ' ) . replace ( / {2,}/g , ' ' ) ; }
function _setHtml ( $node , html ) { if ( editor . opts . htmlExecuteScripts ) { $node . html ( html ) ; }
else { $node . get ( 0 ) . innerHTML = html ; } }
function set ( html ) { var clean _html = editor . clean . html ( ( html || '' ) . trim ( ) , [ ] , [ ] , editor . opts . fullPage ) ; if ( ! editor . opts . fullPage ) { _setHtml ( editor . $el , clean _html ) ; }
else { var body _html = ( extractNode ( clean _html , 'body' ) || ( clean _html . indexOf ( '<body' ) >= 0 ? '' : clean _html ) ) ; var body _attrs = extractNodeAttrs ( clean _html , 'body' ) ; var head _html = extractNode ( clean _html , 'head' ) || '<title></title>' ; var head _attrs = extractNodeAttrs ( clean _html , 'head' ) ; var head _bad _html = $ ( '<div>' ) . append ( head _html ) . contents ( ) . each ( function ( ) { if ( this . nodeType == Node . COMMENT _NODE || [ 'BASE' , 'LINK' , 'META' , 'NOSCRIPT' , 'SCRIPT' , 'STYLE' , 'TEMPLATE' , 'TITLE' ] . indexOf ( this . tagName ) >= 0 ) { this . parentNode . removeChild ( this ) ; } } ) . end ( ) . html ( ) . trim ( ) ; head _html = $ ( '<div>' ) . append ( head _html ) . contents ( ) . map ( function ( ) { if ( this . nodeType == Node . COMMENT _NODE ) { return '<!--' + this . nodeValue + '-->' ; }
else if ( [ 'BASE' , 'LINK' , 'META' , 'NOSCRIPT' , 'SCRIPT' , 'STYLE' , 'TEMPLATE' , 'TITLE' ] . indexOf ( this . tagName ) >= 0 ) { return this . outerHTML ; }
else { return '' ; } } ) . toArray ( ) . join ( '' ) ; var doctype = extractDoctype ( clean _html ) ; var html _attrs = extractNodeAttrs ( clean _html , 'html' ) ; _setHtml ( editor . $el , head _bad _html + '\n' + body _html ) ; editor . node . clearAttributes ( editor . el ) ; editor . $el . attr ( body _attrs ) ; editor . $el . addClass ( 'fr-view' ) ; editor . $el . attr ( 'spellcheck' , editor . opts . spellcheck ) ; editor . $el . attr ( 'dir' , editor . opts . direction ) ; _setHtml ( editor . $head , head _html ) ; editor . node . clearAttributes ( editor . $head . get ( 0 ) ) ; editor . $head . attr ( head _attrs ) ; editor . node . clearAttributes ( editor . $html . get ( 0 ) ) ; editor . $html . attr ( html _attrs ) ; editor . iframe _document . doctype . parentNode . replaceChild ( _newDoctype ( doctype , editor . iframe _document ) , editor . iframe _document . doctype ) ; }
var disabled = editor . edit . isDisabled ( ) ; editor . edit . on ( ) ; editor . core . injectStyle ( editor . opts . iframeDefaultStyle + editor . opts . iframeStyle ) ; _normalize ( ) ; if ( ! editor . opts . useClasses ) { editor . $el . find ( '[fr-original-class]' ) . each ( function ( ) { this . setAttribute ( 'class' , this . getAttribute ( 'fr-original-class' ) ) ; this . removeAttribute ( 'fr-original-class' ) ; } ) ; editor . $el . find ( '[fr-original-style]' ) . each ( function ( ) { this . setAttribute ( 'style' , this . getAttribute ( 'fr-original-style' ) ) ; this . removeAttribute ( 'fr-original-style' ) ; } ) ; }
if ( disabled ) editor . edit . off ( ) ; editor . events . trigger ( 'html.set' ) ; }
function _specifity ( selector ) { var idRegex = /(#[^\s\+>~\.\[:]+)/g ; var attributeRegex = /(\[[^\]]+\])/g ; var classRegex = /(\.[^\s\+>~\.\[:]+)/g ; var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi ; var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi ; var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g ; var elementRegex = /([^\s\+>~\.\[:]+)/g ; ( function ( ) { var regex = /:not\(([^\)]*)\)/g ; if ( regex . test ( selector ) ) { selector = selector . replace ( regex , ' $1 ' ) ; } } ( ) ) ; var s = ( selector . match ( idRegex ) || [ ] ) . length * 100 +
( selector . match ( attributeRegex ) || [ ] ) . length * 10 +
( selector . match ( classRegex ) || [ ] ) . length * 10 +
( selector . match ( pseudoClassWithBracketsRegex ) || [ ] ) . length * 10 +
( selector . match ( pseudoClassRegex ) || [ ] ) . length * 10 +
( selector . match ( pseudoElementRegex ) || [ ] ) . length ; selector = selector . replace ( /[\*\s\+>~]/g , ' ' ) ; selector = selector . replace ( /[#\.]/g , ' ' ) ; s += ( selector . match ( elementRegex ) || [ ] ) . length ; return s ; }
function _processOnGet ( el ) { editor . events . trigger ( 'html.processGet' , [ el ] ) ; if ( el && el . getAttribute && el . getAttribute ( 'class' ) === '' ) { el . removeAttribute ( 'class' ) ; }
if ( el && el . getAttribute && el . getAttribute ( 'style' ) === '' ) { el . removeAttribute ( 'style' ) ; }
if ( el && el . nodeType == Node . ELEMENT _NODE ) { var els = el . querySelectorAll ( '[class=""],[style=""]' ) ; var i ; for ( i = 0 ; i < els . length ; i ++ ) { var _el = els [ i ] ; if ( _el . getAttribute ( 'class' ) === '' ) { _el . removeAttribute ( 'class' ) ; }
if ( _el . getAttribute ( 'style' ) === '' ) { _el . removeAttribute ( 'style' ) ; } }
if ( el . tagName === 'BR' ) { _processBR ( el ) ; }
else { var brs = el . querySelectorAll ( 'br' ) ; for ( i = 0 ; i < brs . length ; i ++ ) { _processBR ( brs [ i ] ) ; } } } }
function _sortElementsBySpec ( a , b ) { return a [ 3 ] - b [ 3 ] ; }
function get ( keep _markers , keep _classes ) { if ( ! editor . $wp ) { return editor . $oel . clone ( ) . removeClass ( 'fr-view' ) . removeAttr ( 'contenteditable' ) . get ( 0 ) . outerHTML ; }
var html = '' ; editor . events . trigger ( 'html.beforeGet' ) ; var updated _elms = [ ] ; var elms _info = { } ; var i ; var j ; var elems _specs = [ ] ; var inputs = editor . el . querySelectorAll ( 'input, textarea' ) ; for ( i = 0 ; i < inputs . length ; i ++ ) { inputs [ i ] . setAttribute ( 'value' , inputs [ i ] . value ) ; }
if ( ! editor . opts . useClasses && ! keep _classes ) { var ignoreRegEx = new RegExp ( '^' + editor . opts . htmlIgnoreCSSProperties . join ( '$|^' ) + '$' , 'gi' )
for ( i = 0 ; i < editor . doc . styleSheets . length ; i ++ ) { var rules ; var head _style = 0 ; try { rules = editor . doc . styleSheets [ i ] . cssRules ; if ( editor . doc . styleSheets [ i ] . ownerNode && editor . doc . styleSheets [ i ] . ownerNode . nodeType == 'STYLE' ) { head _style = 1 ; } }
catch ( ex ) { }
if ( rules ) { for ( var idx = 0 , len = rules . length ; idx < len ; idx ++ ) { if ( rules [ idx ] . selectorText ) { if ( rules [ idx ] . style . cssText . length > 0 ) { var selector = rules [ idx ] . selectorText . replace ( /body |\.fr-view /g , '' ) . replace ( /::/g , ':' ) ; var elms ; try { elms = editor . el . querySelectorAll ( selector ) ; }
catch ( ex ) { elms = [ ] ; }
for ( j = 0 ; j < elms . length ; j ++ ) { if ( ! elms [ j ] . getAttribute ( 'fr-original-style' ) && elms [ j ] . getAttribute ( 'style' ) ) { elms [ j ] . setAttribute ( 'fr-original-style' , elms [ j ] . getAttribute ( 'style' ) ) ; updated _elms . push ( elms [ j ] ) ; }
else if ( ! elms [ j ] . getAttribute ( 'fr-original-style' ) ) { elms [ j ] . setAttribute ( 'fr-original-style' , '' ) ; updated _elms . push ( elms [ j ] ) ; }
if ( ! elms _info [ elms [ j ] ] ) { elms _info [ elms [ j ] ] = { } ; }
var spec = head _style * 1000 + _specifity ( rules [ idx ] . selectorText ) ; var css _text = rules [ idx ] . style . cssText . split ( ';' ) ; for ( var k = 0 ; k < css _text . length ; k ++ ) { var rule = css _text [ k ] . trim ( ) . split ( ':' ) [ 0 ] ; if ( ! rule ) continue ; if ( rule . match ( ignoreRegEx ) ) continue ; if ( ! elms _info [ elms [ j ] ] [ rule ] ) { elms _info [ elms [ j ] ] [ rule ] = 0 ; if ( ( elms [ j ] . getAttribute ( 'fr-original-style' ) || '' ) . indexOf ( rule + ':' ) >= 0 ) { elms _info [ elms [ j ] ] [ rule ] = 10000 ; } }
if ( spec >= elms _info [ elms [ j ] ] [ rule ] ) { elms _info [ elms [ j ] ] [ rule ] = spec ; if ( css _text [ k ] . trim ( ) . length ) { var info = css _text [ k ] . trim ( ) . split ( ':' ) ; info . splice ( 0 , 1 ) ; elems _specs . push ( [ elms [ j ] , rule . trim ( ) , info . join ( ':' ) . trim ( ) , spec ] ) } } } } } } } } }
elems _specs . sort ( _sortElementsBySpec ) ; for ( i = 0 ; i < elems _specs . length ; i ++ ) { var specs _elem = elems _specs [ i ] ; specs _elem [ 0 ] . style [ specs _elem [ 1 ] ] = specs _elem [ 2 ] ; }
for ( i = 0 ; i < updated _elms . length ; i ++ ) { if ( updated _elms [ i ] . getAttribute ( 'class' ) ) { updated _elms [ i ] . setAttribute ( 'fr-original-class' , updated _elms [ i ] . getAttribute ( 'class' ) ) ; updated _elms [ i ] . removeAttribute ( 'class' ) ; }
if ( ( updated _elms [ i ] . getAttribute ( 'fr-original-style' ) || '' ) . trim ( ) . length > 0 ) { var original _rules = updated _elms [ i ] . getAttribute ( 'fr-original-style' ) . split ( ';' ) ; for ( j = 0 ; j < original _rules . length ; j ++ ) { if ( original _rules [ j ] . indexOf ( ':' ) > 0 ) { var splits = original _rules [ j ] . split ( ':' ) ; var original _rule = splits [ 0 ] ; splits . splice ( 0 , 1 ) ; updated _elms [ i ] . style [ original _rule . trim ( ) ] = splits . join ( ':' ) . trim ( ) ; } } } } }
if ( ! editor . node . isEmpty ( editor . el ) ) { if ( typeof keep _markers == 'undefined' ) keep _markers = false ; if ( ! editor . opts . fullPage ) { html = editor . $el . html ( ) ; }
else { html = getDoctype ( editor . iframe _document ) ; editor . $el . removeClass ( 'fr-view' ) ; var heightMin = editor . opts . heightMin ; var height = editor . opts . height ; var heightMax = editor . opts . heightMax ; editor . opts . heightMin = null ; editor . opts . height = null ; editor . opts . heightMax = null ; editor . size . refresh ( ) ; html += '<html' + editor . node . attributes ( editor . $html . get ( 0 ) ) + '>' + editor . $html . html ( ) + '</html>' ; editor . opts . heightMin = heightMin ; editor . opts . height = height ; editor . opts . heightMax = heightMax ; editor . size . refresh ( ) ; editor . $el . addClass ( 'fr-view' ) ; } }
else if ( editor . opts . fullPage ) { html = getDoctype ( editor . iframe _document ) ; html += '<html' + editor . node . attributes ( editor . $html . get ( 0 ) ) + '>' + editor . $html . find ( 'head' ) . get ( 0 ) . outerHTML + '<body></body></html>' ; }
if ( ! editor . opts . useClasses && ! keep _classes ) { for ( i = 0 ; i < updated _elms . length ; i ++ ) { if ( updated _elms [ i ] . getAttribute ( 'fr-original-class' ) ) { updated _elms [ i ] . setAttribute ( 'class' , updated _elms [ i ] . getAttribute ( 'fr-original-class' ) ) ; updated _elms [ i ] . removeAttribute ( 'fr-original-class' ) ; }
if ( updated _elms [ i ] . getAttribute ( 'fr-original-style' ) != null && typeof updated _elms [ i ] . getAttribute ( 'fr-original-style' ) != 'undefined' ) { if ( updated _elms [ i ] . getAttribute ( 'fr-original-style' ) . length !== 0 ) { updated _elms [ i ] . setAttribute ( 'style' , updated _elms [ i ] . getAttribute ( 'fr-original-style' ) ) ; }
else { updated _elms [ i ] . removeAttribute ( 'style' ) ; }
updated _elms [ i ] . removeAttribute ( 'fr-original-style' ) ; }
else { updated _elms [ i ] . removeAttribute ( 'style' ) ; } } }
if ( editor . opts . fullPage ) { html = html . replace ( /<style data-fr-style="true">(?:[\w\W]*?)<\/style>/g , '' ) ; html = html . replace ( /<link([^>]*)data-fr-style="true"([^>]*)>/g , '' ) ; html = html . replace ( /<style(?:[\w\W]*?)class="firebugResetStyles"(?:[\w\W]*?)>(?:[\w\W]*?)<\/style>/g , '' ) ; html = html . replace ( /<body((?:[\w\W]*?)) spellcheck="true"((?:[\w\W]*?))>((?:[\w\W]*?))<\/body>/g , '<body$1$2>$3</body>' ) ; html = html . replace ( /<body((?:[\w\W]*?)) contenteditable="(true|false)"((?:[\w\W]*?))>((?:[\w\W]*?))<\/body>/g , '<body$1$3>$4</body>' ) ; html = html . replace ( /<body((?:[\w\W]*?)) dir="([\w]*)"((?:[\w\W]*?))>((?:[\w\W]*?))<\/body>/g , '<body$1$3>$4</body>' ) ; html = html . replace ( /<body((?:[\w\W]*?))class="([\w\W]*?)(fr-rtl|fr-ltr)([\w\W]*?)"((?:[\w\W]*?))>((?:[\w\W]*?))<\/body>/g , '<body$1class="$2$4"$5>$6</body>' ) ; html = html . replace ( /<body((?:[\w\W]*?)) class=""((?:[\w\W]*?))>((?:[\w\W]*?))<\/body>/g , '<body$1$2>$3</body>' ) ; }
if ( editor . opts . htmlSimpleAmpersand ) { html = html . replace ( /\&/gi , '&' ) ; }
editor . events . trigger ( 'html.afterGet' ) ; if ( ! keep _markers ) { html = html . replace ( /<span[^>]*? class\s*=\s*["']?fr-marker["']?[^>]+>\u200b<\/span>/gi , '' ) ; }
html = editor . clean . invisibleSpaces ( html ) ; html = editor . clean . exec ( html , _processOnGet ) ; var new _html = editor . events . chainTrigger ( 'html.get' , html ) ; if ( typeof new _html == 'string' ) { html = new _html ; }
html = html . replace ( /<pre(?:[\w\W]*?)>(?:[\w\W]*?)<\/pre>/g , function ( str ) { return str . replace ( /<br>/g , '\n' ) ; } ) ; html = html . replace ( /<meta((?:[\w\W]*?)) data-fr-http-equiv="/g , '<meta$1 http-equiv="' ) ; return html ; }
function getSelected ( ) { var wrapSelection = function ( container , node ) { while ( node && ( node . nodeType == Node . TEXT _NODE || ! editor . node . isBlock ( node ) ) && ! editor . node . isElement ( node ) && ! editor . node . hasClass ( node , 'fr-inner' ) ) { if ( node && node . nodeType != Node . TEXT _NODE ) { $ ( container ) . wrapInner ( editor . node . openTagString ( node ) + editor . node . closeTagString ( node ) ) ; }
node = node . parentNode ; }
if ( node && container . innerHTML == node . innerHTML ) { container . innerHTML = node . outerHTML ; } }
var selectionParent = function ( ) { var parent = null ; var sel ; if ( editor . win . getSelection ) { sel = editor . win . getSelection ( ) ; if ( sel && sel . rangeCount ) { parent = sel . getRangeAt ( 0 ) . commonAncestorContainer ; if ( parent . nodeType != Node . ELEMENT _NODE ) { parent = parent . parentNode ; } } }
else if ( ( sel = editor . doc . selection ) && sel . type != 'Control' ) { parent = sel . createRange ( ) . parentElement ( ) ; }
if ( parent != null && ( $ . inArray ( editor . el , $ ( parent ) . parents ( ) ) >= 0 || parent == editor . el ) ) { return parent ; }
else { return null ; } }
var html = '' ; if ( typeof editor . win . getSelection != 'undefined' ) { if ( editor . browser . mozilla ) { editor . selection . save ( ) ; if ( editor . $el . find ( '.fr-marker[data-type="false"]' ) . length > 1 ) { editor . $el . find ( '.fr-marker[data-type="false"][data-id="0"]' ) . remove ( ) ; editor . $el . find ( '.fr-marker[data-type="false"]:last' ) . attr ( 'data-id' , '0' ) ; editor . $el . find ( '.fr-marker' ) . not ( '[data-id="0"]' ) . remove ( ) ; }
editor . selection . restore ( ) ; }
var ranges = editor . selection . ranges ( ) ; for ( var i = 0 ; i < ranges . length ; i ++ ) { var container = document . createElement ( 'div' ) ; container . appendChild ( ranges [ i ] . cloneContents ( ) ) ; wrapSelection ( container , selectionParent ( ) ) ; if ( $ ( container ) . find ( '.fr-element' ) . length > 0 ) { container = editor . el ; }
html += container . innerHTML ; } }
else if ( typeof editor . doc . selection != 'undefined' ) { if ( editor . doc . selection . type == 'Text' ) { html = editor . doc . selection . createRange ( ) . htmlText ; } }
return html ; }
function _hasBlockTags ( html ) { var tmp = editor . doc . createElement ( 'div' ) ; tmp . innerHTML = html ; return tmp . querySelector ( blockTagsQuery ( ) ) !== null ; }
function _setCursorAtEnd ( html ) { var tmp = editor . doc . createElement ( 'div' ) ; tmp . innerHTML = html ; editor . selection . setAtEnd ( tmp , true ) ; return tmp . innerHTML ; }
function escapeEntities ( str ) { return str . replace ( /</gi , '<' ) . replace ( />/gi , '>' ) . replace ( /"/gi , '"' ) . replace ( /'/gi , ''' ) }
function _unwrapForLists ( html ) { if ( ! editor . html . defaultTag ( ) ) return html ; var tmp = editor . doc . createElement ( 'div' ) ; tmp . innerHTML = html ; var default _tag _els = tmp . querySelectorAll ( ':scope > ' + editor . html . defaultTag ( ) ) ; for ( var i = default _tag _els . length - 1 ; i >= 0 ; i -- ) { var el = default _tag _els [ i ] ; if ( ! editor . node . isBlock ( el . previousSibling ) ) { if ( el . previousSibling && ! editor . node . isEmpty ( el ) ) { $ ( '<br>' ) . insertAfter ( el . previousSibling ) ; }
el . outerHTML = el . innerHTML ; } }
return tmp . innerHTML ; }
function insert ( dirty _html , clean , do _split ) { if ( ! editor . selection . isCollapsed ( ) ) { editor . selection . remove ( ) ; }
var clean _html ; if ( ! clean ) { clean _html = editor . clean . html ( dirty _html ) ; }
else { clean _html = dirty _html ; }
if ( dirty _html . indexOf ( 'class="fr-marker"' ) < 0 ) { clean _html = _setCursorAtEnd ( clean _html ) ; }
if ( editor . node . isEmpty ( editor . el ) && ! editor . opts . keepFormatOnDelete && _hasBlockTags ( clean _html ) ) { editor . el . innerHTML = clean _html ; }
else { var marker = editor . markers . insert ( ) ; if ( ! marker ) { editor . el . innerHTML = editor . el . innerHTML + clean _html ; }
else { if ( editor . node . isLastSibling ( marker ) && $ ( marker ) . parent ( ) . hasClass ( 'fr-deletable' ) ) { $ ( marker ) . insertAfter ( $ ( marker ) . parent ( ) ) ; }
var deep _parent ; var block _parent = editor . node . blockParent ( marker ) ; if ( ( _hasBlockTags ( clean _html ) || do _split ) && ( deep _parent = editor . node . deepestParent ( marker ) || ( block _parent && block _parent . tagName == 'LI' ) ) ) { if ( block _parent && block _parent . tagName == 'LI' ) { clean _html = _unwrapForLists ( clean _html ) ; }
marker = editor . markers . split ( ) ; if ( ! marker ) return false ; marker . outerHTML = clean _html ; }
else { marker . outerHTML = clean _html ; } } }
_normalize ( ) ; editor . keys . positionCaret ( ) ; editor . events . trigger ( 'html.inserted' ) ; }
function cleanWhiteTags ( ignore _selection ) { var current _el = null ; if ( typeof ignore _selection == 'undefined' ) { current _el = editor . selection . element ( ) ; }
if ( editor . opts . keepFormatOnDelete ) return false ; var current _white = current _el ? ( current _el . textContent . match ( /\u200B/g ) || [ ] ) . length - current _el . querySelectorAll ( '.fr-marker' ) . length : 0 ; var total _white = ( editor . el . textContent . match ( /\u200B/g ) || [ ] ) . length - editor . el . querySelectorAll ( '.fr-marker' ) . length ; if ( total _white == current _white ) return false ; var possible _elements ; var removed ; do { removed = false ; possible _elements = editor . el . querySelectorAll ( '*:not(.fr-marker)' ) ; for ( var i = 0 ; i < possible _elements . length ; i ++ ) { var el = possible _elements [ i ] ; if ( current _el == el ) continue ; var text = el . textContent ; if ( el . children . length === 0 && text . length === 1 && text . charCodeAt ( 0 ) == 8203 && el . tagName !== 'TD' ) { $ ( el ) . remove ( ) ; removed = true ; } } } while ( removed ) ; }
function _init ( ) { if ( editor . $wp ) { var cleanTags = function ( ) { cleanWhiteTags ( ) ; if ( editor . placeholder ) { setTimeout ( editor . placeholder . refresh , 0 ) ; } }
editor . events . on ( 'mouseup' , cleanTags ) ; editor . events . on ( 'keydown' , cleanTags ) ; editor . events . on ( 'contentChanged' , checkIfEmpty ) ; } }
return { defaultTag : defaultTag , isPreformatted : isPreformatted , emptyBlocks : emptyBlocks , emptyBlockTagsQuery : emptyBlockTagsQuery , blockTagsQuery : blockTagsQuery , fillEmptyBlocks : fillEmptyBlocks , cleanEmptyTags : cleanEmptyTags , cleanWhiteTags : cleanWhiteTags , cleanBlankSpaces : cleanBlankSpaces , blocks : blocks , getDoctype : getDoctype , set : set , get : get , getSelected : getSelected , insert : insert , wrap : _wrap , unwrap : unwrap , escapeEntities : escapeEntities , checkIfEmpty : checkIfEmpty , extractNode : extractNode , extractNodeAttrs : extractNodeAttrs , extractDoctype : extractDoctype , cleanBRs : cleanBRs , _init : _init } }
$ . extend ( $ . FE . DEFAULTS , { height : null , heightMax : null , heightMin : null , width : null } ) ; $ . FE . MODULES . size = function ( editor ) { function syncIframe ( ) { refresh ( ) ; if ( editor . opts . height ) { editor . $el . css ( 'minHeight' , editor . opts . height - editor . helpers . getPX ( editor . $el . css ( 'padding-top' ) ) - editor . helpers . getPX ( editor . $el . css ( 'padding-bottom' ) ) ) ; }
editor . $iframe . height ( editor . $el . outerHeight ( true ) ) ; }
function refresh ( ) { if ( editor . opts . heightMin ) { editor . $el . css ( 'minHeight' , editor . opts . heightMin ) ; }
else { editor . $el . css ( 'minHeight' , '' ) ; }
if ( editor . opts . heightMax ) { editor . $wp . css ( 'maxHeight' , editor . opts . heightMax ) ; editor . $wp . css ( 'overflow' , 'auto' ) ; }
else { editor . $wp . css ( 'maxHeight' , '' ) ; editor . $wp . css ( 'overflow' , '' ) ; }
if ( editor . opts . height ) { editor . $wp . height ( editor . opts . height ) ; editor . $wp . css ( 'overflow' , 'auto' ) ; editor . $el . css ( 'minHeight' , editor . opts . height - editor . helpers . getPX ( editor . $el . css ( 'padding-top' ) ) - editor . helpers . getPX ( editor . $el . css ( 'padding-bottom' ) ) ) ; }
else { editor . $wp . css ( 'height' , '' ) ; if ( ! editor . opts . heightMin ) editor . $el . css ( 'minHeight' , '' ) ; if ( ! editor . opts . heightMax ) editor . $wp . css ( 'overflow' , '' ) ; }
if ( editor . opts . width ) editor . $box . width ( editor . opts . width ) ; }
function _init ( ) { if ( ! editor . $wp ) return false ; refresh ( ) ; if ( editor . $iframe ) { editor . events . on ( 'keyup keydown' , function ( ) { setTimeout ( syncIframe , 0 ) } , true ) ; editor . events . on ( 'commands.after html.set init initialized paste.after' , syncIframe ) ; } }
return { _init : _init , syncIframe : syncIframe , refresh : refresh } } ; $ . extend ( $ . FE . DEFAULTS , { language : null } ) ; $ . FE . LANGUAGE = { } ; $ . FE . MODULES . language = function ( editor ) { var lang ; function translate ( str ) { if ( lang && lang . translation [ str ] && lang . translation [ str ] . length ) { return lang . translation [ str ] ; }
else { return str ; } }
function _init ( ) { if ( $ . FE . LANGUAGE ) { lang = $ . FE . LANGUAGE [ editor . opts . language ] ; }
if ( lang && lang . direction ) { editor . opts . direction = lang . direction ; } }
return { _init : _init , translate : translate } } ; $ . extend ( $ . FE . DEFAULTS , { placeholderText : 'Type something' } ) ; $ . FE . MODULES . placeholder = function ( editor ) { function show ( ) { if ( ! editor . $placeholder ) _add ( ) ; var margin _offset = editor . opts . iframe ? editor . $iframe . prev ( ) . outerHeight ( true ) : editor . $el . prev ( ) . outerHeight ( true ) ; var margin _top = 0 ; var margin _left = 0 ; var margin _right = 0 ; var padding _top = 0 ; var padding _left = 0 ; var padding _right = 0 ; var contents = editor . node . contents ( editor . el ) ; var alignment = $ ( editor . selection . element ( ) ) . css ( 'text-align' ) ; if ( contents . length && contents [ 0 ] . nodeType == Node . ELEMENT _NODE ) { var $first _node = $ ( contents [ 0 ] ) ; if ( ( ! editor . opts . toolbarInline || editor . $el . prev ( ) . length > 0 ) && editor . ready ) { margin _top = editor . helpers . getPX ( $first _node . css ( 'margin-top' ) ) ; padding _top = editor . helpers . getPX ( $first _node . css ( 'padding-top' ) ) ; margin _left = editor . helpers . getPX ( $first _node . css ( 'margin-left' ) ) ; margin _right = editor . helpers . getPX ( $first _node . css ( 'margin-right' ) ) ; padding _left = editor . helpers . getPX ( $first _node . css ( 'padding-left' ) ) ; padding _right = editor . helpers . getPX ( $first _node . css ( 'padding-right' ) ) ; }
editor . $placeholder . css ( 'font-size' , $first _node . css ( 'font-size' ) ) ; editor . $placeholder . css ( 'line-height' , $first _node . css ( 'line-height' ) ) ; }
else { editor . $placeholder . css ( 'font-size' , editor . $el . css ( 'font-size' ) ) ; editor . $placeholder . css ( 'line-height' , editor . $el . css ( 'line-height' ) ) ; }
editor . $wp . addClass ( 'show-placeholder' ) ; editor . $placeholder . css ( { marginTop : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'margin-top' ) ) , margin _top ) + ( margin _offset ? margin _offset : 0 ) , paddingTop : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'padding-top' ) ) , padding _top ) , paddingLeft : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'padding-left' ) ) , padding _left ) , marginLeft : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'margin-left' ) ) , margin _left ) , paddingRight : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'padding-right' ) ) , padding _right ) , marginRight : Math . max ( editor . helpers . getPX ( editor . $el . css ( 'margin-right' ) ) , margin _right ) , textAlign : alignment } ) . text ( editor . language . translate ( editor . opts . placeholderText || editor . $oel . attr ( 'placeholder' ) || '' ) ) ; editor . $placeholder . html ( editor . $placeholder . text ( ) . replace ( /\n/g , '<br>' ) ) ; editor . size . refresh ( ) ; if ( editor . $placeholder . height ( ) > editor . $el . height ( ) ) { var oldHeight = editor . opts . heightMin ; editor . opts . heightMin = editor . $placeholder . height ( ) + editor . $tb ? editor . $tb . height ( ) : 0 ; editor . size . refresh ( ) ; editor . opts . heightMin = oldHeight ; } }
function hide ( ) { editor . $wp . removeClass ( 'show-placeholder' ) ; editor . size . refresh ( ) ; }
function isVisible ( ) { return ! editor . $wp ? false : editor . node . hasClass ( editor . $wp . get ( 0 ) , 'show-placeholder' ) ; }
function refresh ( ) { if ( ! editor . $wp ) return false ; if ( editor . core . isEmpty ( ) ) { show ( ) ; }
else { hide ( ) ; } }
function _add ( ) { editor . $placeholder = $ ( '<span class="fr-placeholder"></span>' ) ; editor . $wp . append ( editor . $placeholder ) ; }
function _init ( ) { if ( ! editor . $wp ) return false ; editor . events . on ( 'init input keydown keyup contentChanged initialized' , refresh ) ; }
return { _init : _init , show : show , hide : hide , refresh : refresh , isVisible : isVisible } } ; $ . FE . MODULES . edit = function ( editor ) { function disableDesign ( ) { if ( editor . browser . mozilla ) { try { editor . doc . execCommand ( 'enableObjectResizing' , false , 'false' ) ; editor . doc . execCommand ( 'enableInlineTableEditing' , false , 'false' ) ; }
catch ( ex ) { } }
if ( editor . browser . msie ) { try { editor . doc . body . addEventListener ( 'mscontrolselect' , function ( e ) { e . preventDefault ( ) ; return false ; } ) ; }
catch ( ex ) { } } }
var disabled = false ; function on ( ) { if ( editor . $wp ) { editor . $el . attr ( 'contenteditable' , true ) ; editor . $el . removeClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , false ) ; if ( editor . $tb ) editor . $tb . removeClass ( 'fr-disabled' ) . removeAttr ( 'aria-disabled' ) ; disableDesign ( ) ; }
else if ( editor . $el . is ( 'a' ) ) { editor . $el . attr ( 'contenteditable' , true ) ; }
disabled = false ; }
function off ( ) { editor . events . disableBlur ( ) ; if ( editor . $wp ) { editor . $el . attr ( 'contenteditable' , false ) ; editor . $el . addClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , true ) ; if ( editor . $tb ) editor . $tb . addClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , true ) ; }
else if ( editor . $el . is ( 'a' ) ) { editor . $el . attr ( 'contenteditable' , false ) ; }
editor . events . enableBlur ( ) ; disabled = true ; }
function isDisabled ( ) { return disabled ; }
function _init ( ) { editor . events . on ( 'focus' , function ( ) { if ( isDisabled ( ) ) editor . edit . off ( ) ; else editor . edit . on ( ) ; } ) ; }
return { _init : _init , on : on , off : off , disableDesign : disableDesign , isDisabled : isDisabled } } ; $ . extend ( $ . FE . DEFAULTS , { documentReady : false , editorClass : null , typingTimer : 500 , iframe : false , requestWithCORS : true , requestWithCredentials : false , requestHeaders : { } , useClasses : true , spellcheck : true , iframeDefaultStyle : 'html{margin:0px;height:auto;}body{height:auto;padding:10px;background:transparent;color:#000000;position:relative;z-index: 2;-webkit-user-select:auto;margin:0px;overflow:hidden;min-height:20px;}body:after{content:"";display:block;clear:both;}body::-moz-selection{background:#b5d6fd;color:#000;}body::selection{background:#b5d6fd;color:#000;}' , iframeStyle : '' , iframeStyleFiles : [ ] , direction : 'auto' , zIndex : 1 , tabIndex : null , disableRightClick : false , scrollableContainer : 'body' , keepFormatOnDelete : false , theme : null } )
$ . FE . MODULES . core = function ( editor ) { function injectStyle ( style ) { if ( editor . opts . iframe ) { editor . $head . find ( 'style[data-fr-style], link[data-fr-style]' ) . remove ( ) ; editor . $head . append ( '<style data-fr-style="true">' + style + '</style>' ) ; for ( var i = 0 ; i < editor . opts . iframeStyleFiles . length ; i ++ ) { var $link = $ ( '<link data-fr-style="true" rel="stylesheet" href="' + editor . opts . iframeStyleFiles [ i ] + '">' ) ; $link . get ( 0 ) . addEventListener ( 'load' , editor . size . syncIframe ) ; editor . $head . append ( $link ) ; } } }
function _initElementStyle ( ) { if ( ! editor . opts . iframe ) { editor . $el . addClass ( 'fr-element fr-view' ) ; } }
function _initStyle ( ) { editor . $box . addClass ( 'fr-box' + ( editor . opts . editorClass ? ' ' + editor . opts . editorClass : '' ) ) ; editor . $box . attr ( 'role' , 'application' ) ; editor . $wp . addClass ( 'fr-wrapper' ) ; if ( editor . opts . documentReady ) { editor . $box . addClass ( 'fr-document' ) ; }
_initElementStyle ( ) ; if ( editor . opts . iframe ) { editor . $iframe . addClass ( 'fr-iframe' ) ; editor . $el . addClass ( 'fr-view' ) ; for ( var i = 0 ; i < editor . o _doc . styleSheets . length ; i ++ ) { var rules ; try { rules = editor . o _doc . styleSheets [ i ] . cssRules ; }
catch ( ex ) { }
if ( rules ) { for ( var idx = 0 , len = rules . length ; idx < len ; idx ++ ) { if ( rules [ idx ] . selectorText && ( rules [ idx ] . selectorText . indexOf ( '.fr-view' ) === 0 || rules [ idx ] . selectorText . indexOf ( '.fr-element' ) === 0 ) ) { if ( rules [ idx ] . style . cssText . length > 0 ) { if ( rules [ idx ] . selectorText . indexOf ( '.fr-view' ) === 0 ) { editor . opts . iframeStyle += rules [ idx ] . selectorText . replace ( /\.fr-view/g , 'body' ) + '{' + rules [ idx ] . style . cssText + '}' ; }
else { editor . opts . iframeStyle += rules [ idx ] . selectorText . replace ( /\.fr-element/g , 'body' ) + '{' + rules [ idx ] . style . cssText + '}' ; } } } } } } }
if ( editor . opts . direction != 'auto' ) { editor . $box . removeClass ( 'fr-ltr fr-rtl' ) . addClass ( 'fr-' + editor . opts . direction ) ; }
editor . $el . attr ( 'dir' , editor . opts . direction ) ; editor . $wp . attr ( 'dir' , editor . opts . direction ) ; if ( editor . opts . zIndex > 1 ) { editor . $box . css ( 'z-index' , editor . opts . zIndex ) ; }
if ( editor . opts . theme ) { editor . $box . addClass ( editor . opts . theme + '-theme' ) ; }
editor . opts . tabIndex = editor . opts . tabIndex || editor . $oel . attr ( 'tabIndex' ) ; if ( editor . opts . tabIndex ) { editor . $el . attr ( 'tabIndex' , editor . opts . tabIndex ) ; } }
function isEmpty ( ) { return editor . node . isEmpty ( editor . el ) ; }
function _initDrag ( ) { editor . drag _support = { filereader : typeof FileReader != 'undefined' , formdata : ! ! editor . win . FormData , progress : 'upload' in new XMLHttpRequest ( ) } ; }
function getXHR ( url , method ) { var xhr = new XMLHttpRequest ( ) ; xhr . open ( method , url , true ) ; if ( editor . opts . requestWithCredentials ) { xhr . withCredentials = true ; }
for ( var header in editor . opts . requestHeaders ) { if ( editor . opts . requestHeaders . hasOwnProperty ( header ) ) { xhr . setRequestHeader ( header , editor . opts . requestHeaders [ header ] ) ; } }
return xhr ; }
function _destroy ( html ) { if ( editor . $oel . get ( 0 ) . tagName == 'TEXTAREA' ) { editor . $oel . val ( html ) ; }
if ( editor . $box ) { editor . $box . removeAttr ( 'role' ) ; }
if ( editor . $wp ) { if ( editor . $oel . get ( 0 ) . tagName == 'TEXTAREA' ) { editor . $el . html ( '' ) ; editor . $wp . html ( '' ) ; editor . $box . replaceWith ( editor . $oel ) ; editor . $oel . show ( ) ; }
else { editor . $wp . replaceWith ( html ) ; editor . $el . html ( '' ) ; editor . $box . removeClass ( 'fr-view fr-ltr fr-box ' + ( editor . opts . editorClass || '' ) ) ; if ( editor . opts . theme ) { editor . $box . addClass ( editor . opts . theme + '-theme' ) ; } } }
this . $wp = null ; this . $el = null ; this . el = null ; this . $box = null ; }
function hasFocus ( ) { if ( editor . browser . mozilla && editor . helpers . isMobile ( ) ) return editor . selection . inEditor ( ) ; return editor . node . hasFocus ( editor . el ) || editor . $el . find ( '*:focus' ) . length > 0 ; }
function sameInstance ( $obj ) { if ( ! $obj ) return false ; var inst = $obj . data ( 'instance' ) ; return ( inst ? inst . id == editor . id : false ) ; }
function _init ( ) { $ . FE . INSTANCES . push ( editor ) ; _initDrag ( ) ; if ( editor . $wp ) { _initStyle ( ) ; editor . html . set ( editor . _original _html ) ; editor . $el . attr ( 'spellcheck' , editor . opts . spellcheck ) ; if ( editor . helpers . isMobile ( ) ) { editor . $el . attr ( 'autocomplete' , editor . opts . spellcheck ? 'on' : 'off' ) ; editor . $el . attr ( 'autocorrect' , editor . opts . spellcheck ? 'on' : 'off' ) ; editor . $el . attr ( 'autocapitalize' , editor . opts . spellcheck ? 'on' : 'off' ) ; }
if ( editor . opts . disableRightClick ) { editor . events . $on ( editor . $el , 'contextmenu' , function ( e ) { if ( e . button == 2 ) { return false ; } } ) ; }
try { editor . doc . execCommand ( 'styleWithCSS' , false , false ) ; }
catch ( ex ) { } }
if ( editor . $oel . get ( 0 ) . tagName == 'TEXTAREA' ) { editor . events . on ( 'contentChanged' , function ( ) { editor . $oel . val ( editor . html . get ( ) ) ; } ) ; editor . events . on ( 'form.submit' , function ( ) { editor . $oel . val ( editor . html . get ( ) ) ; } ) ; editor . events . on ( 'form.reset' , function ( ) { editor . html . set ( editor . _original _html ) ; } )
editor . $oel . val ( editor . html . get ( ) ) ; }
if ( editor . helpers . isIOS ( ) ) { editor . events . $on ( editor . $doc , 'selectionchange' , function ( ) { if ( ! editor . $doc . get ( 0 ) . hasFocus ( ) ) { editor . $win . get ( 0 ) . focus ( ) ; } } ) ; }
editor . events . trigger ( 'init' ) ; if ( editor . opts . autofocus && ! editor . opts . initOnClick && editor . $wp ) { editor . events . on ( 'initialized' , function ( ) { editor . events . focus ( true ) ; } ) } }
return { _init : _init , destroy : _destroy , isEmpty : isEmpty , getXHR : getXHR , injectStyle : injectStyle , hasFocus : hasFocus , sameInstance : sameInstance } }
$ . FE . MODULES . cursorLists = function ( editor ) { function _firstParentLI ( node ) { var p _node = node ; while ( p _node . tagName != 'LI' ) { p _node = p _node . parentNode ; }
return p _node ; }
function _firstParentList ( node ) { var p _node = node ; while ( ! editor . node . isList ( p _node ) ) { p _node = p _node . parentNode ; }
return p _node ; }
function _startEnter ( marker ) { var li = _firstParentLI ( marker ) ; var next _li = li . nextSibling ; var prev _li = li . previousSibling ; var default _tag = editor . html . defaultTag ( ) ; var ul ; if ( editor . node . isEmpty ( li , true ) && next _li ) { var o _str = '' ; var c _str = ''
var p _node = marker . parentNode ; while ( ! editor . node . isList ( p _node ) && p _node . parentNode && ( p _node . parentNode . tagName !== 'LI' || p _node . parentNode === li ) ) { o _str = editor . node . openTagString ( p _node ) + o _str ; c _str = c _str + editor . node . closeTagString ( p _node ) ; p _node = p _node . parentNode ; }
o _str = editor . node . openTagString ( p _node ) + o _str ; c _str = c _str + editor . node . closeTagString ( p _node ) ; var str = '' ; if ( p _node . parentNode && p _node . parentNode . tagName == 'LI' ) { str = c _str + '<li>' + $ . FE . MARKERS + '<br>' + o _str ; }
else { if ( default _tag ) { str = c _str + '<' + default _tag + '>' + $ . FE . MARKERS + '<br>' + '</' + default _tag + '>' + o _str ; }
else { str = c _str + $ . FE . MARKERS + '<br>' + o _str ; } }
while ( [ 'UL' , 'OL' ] . indexOf ( p _node . tagName ) < 0 || ( p _node . parentNode && p _node . parentNode . tagName === 'LI' ) ) { p _node = p _node . parentNode ; }
$ ( li ) . replaceWith ( '<span id="fr-break"></span>' )
var html = editor . node . openTagString ( p _node ) + $ ( p _node ) . html ( ) + editor . node . closeTagString ( p _node ) ; html = html . replace ( /<span id="fr-break"><\/span>/g , str ) ; $ ( p _node ) . replaceWith ( html ) ; editor . $el . find ( 'li:empty' ) . remove ( ) ; }
else if ( ( prev _li && next _li ) || ! editor . node . isEmpty ( li , true ) ) { var br _str = '<br>' ; var nd = marker . parentNode ; while ( nd && nd . tagName != 'LI' ) { br _str = editor . node . openTagString ( nd ) + br _str + editor . node . closeTagString ( nd ) ; nd = nd . parentNode ; }
$ ( li ) . before ( '<li>' + br _str + '</li>' ) ; $ ( marker ) . remove ( ) ; }
else if ( ! prev _li ) { ul = _firstParentList ( li ) ; if ( ul . parentNode && ul . parentNode . tagName == 'LI' ) { if ( next _li ) { $ ( ul . parentNode ) . before ( editor . node . openTagString ( li ) + $ . FE . MARKERS + '<br></li>' ) ; }
else { $ ( ul . parentNode ) . after ( editor . node . openTagString ( li ) + $ . FE . MARKERS + '<br></li>' ) ; } }
else { if ( default _tag ) { $ ( ul ) . before ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br></' + default _tag + '>' ) ; }
else { $ ( ul ) . before ( $ . FE . MARKERS + '<br>' ) ; } }
$ ( li ) . remove ( ) ; }
else { ul = _firstParentList ( li ) ; var new _str = $ . FE . MARKERS + '<br>' ; var ndx = marker . parentNode ; while ( ndx && ndx . tagName != 'LI' ) { new _str = editor . node . openTagString ( ndx ) + new _str + editor . node . closeTagString ( ndx ) ; ndx = ndx . parentNode ; }
if ( ul . parentNode && ul . parentNode . tagName == 'LI' ) { $ ( ul . parentNode ) . after ( '<li>' + new _str + '</li>' ) ; }
else { if ( default _tag ) { $ ( ul ) . after ( '<' + default _tag + '>' + new _str + '</' + default _tag + '>' ) ; }
else { $ ( ul ) . after ( new _str ) ; } }
$ ( li ) . remove ( ) ; } }
function _middleEnter ( marker ) { var li = _firstParentLI ( marker ) ; var str = '' ; var node = marker ; var o _str = '' ; var c _str = '' ; while ( node != li ) { node = node . parentNode ; var cls = ( node . tagName == 'A' && editor . cursor . isAtEnd ( marker , node ) ) ? 'fr-to-remove' : '' ; o _str = editor . node . openTagString ( $ ( node ) . clone ( ) . addClass ( cls ) . get ( 0 ) ) + o _str ; c _str = editor . node . closeTagString ( node ) + c _str ; }
str = c _str + str + o _str + $ . FE . MARKERS + ( editor . opts . keepFormatOnDelete ? $ . FE . INVISIBLE _SPACE : '' ) ; $ ( marker ) . replaceWith ( '<span id="fr-break"></span>' ) ; var html = editor . node . openTagString ( li ) + $ ( li ) . html ( ) + editor . node . closeTagString ( li ) ; html = html . replace ( /<span id="fr-break"><\/span>/g , str ) ; $ ( li ) . replaceWith ( html ) ; }
function _endEnter ( marker ) { var li = _firstParentLI ( marker ) ; var end _str = $ . FE . MARKERS ; var start _str = '' ; var node = marker ; var add _invisible = false ; while ( node != li ) { node = node . parentNode ; var cls = ( node . tagName == 'A' && editor . cursor . isAtEnd ( marker , node ) ) ? 'fr-to-remove' : '' ; if ( ! add _invisible && node != li && ! editor . node . isBlock ( node ) ) { add _invisible = true ; start _str = start _str + $ . FE . INVISIBLE _SPACE ; }
start _str = editor . node . openTagString ( $ ( node ) . clone ( ) . addClass ( cls ) . get ( 0 ) ) + start _str ; end _str = end _str + editor . node . closeTagString ( node ) ; }
var str = start _str + end _str ; $ ( marker ) . remove ( ) ; $ ( li ) . after ( str ) ; }
function _backspace ( marker ) { var li = _firstParentLI ( marker ) ; var prev _li = li . previousSibling ; if ( prev _li ) { prev _li = $ ( prev _li ) . find ( editor . html . blockTagsQuery ( ) ) . get ( - 1 ) || prev _li ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; var contents = editor . node . contents ( prev _li ) ; if ( contents . length && contents [ contents . length - 1 ] . tagName == 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) ; }
$ ( li ) . find ( editor . html . blockTagsQuery ( ) ) . not ( 'ol, ul, table' ) . each ( function ( ) { if ( this . parentNode == li ) { $ ( this ) . replaceWith ( $ ( this ) . html ( ) + ( editor . node . isEmpty ( this ) ? '' : '<br>' ) ) ; } } )
var node = editor . node . contents ( li ) [ 0 ] ; var tmp ; while ( node && ! editor . node . isList ( node ) ) { tmp = node . nextSibling ; $ ( prev _li ) . append ( node ) ; node = tmp ; }
prev _li = li . previousSibling ; while ( node ) { tmp = node . nextSibling ; $ ( prev _li ) . append ( node ) ; node = tmp ; }
contents = editor . node . contents ( prev _li )
if ( contents . length > 1 && contents [ contents . length - 1 ] . tagName === 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) }
$ ( li ) . remove ( ) ; }
else { var ul = _firstParentList ( li ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; if ( ul . parentNode && ul . parentNode . tagName == 'LI' ) { var prev _node = ul . previousSibling ; if ( editor . node . isBlock ( prev _node ) ) { $ ( li ) . find ( editor . html . blockTagsQuery ( ) ) . not ( 'ol, ul, table' ) . each ( function ( ) { if ( this . parentNode == li ) { $ ( this ) . replaceWith ( $ ( this ) . html ( ) + ( editor . node . isEmpty ( this ) ? '' : '<br>' ) ) ; } } ) ; $ ( prev _node ) . append ( $ ( li ) . html ( ) ) ; }
else { $ ( ul ) . before ( $ ( li ) . html ( ) ) ; } }
else { var default _tag = editor . html . defaultTag ( ) ; if ( default _tag && $ ( li ) . find ( editor . html . blockTagsQuery ( ) ) . length === 0 ) { $ ( ul ) . before ( '<' + default _tag + '>' + $ ( li ) . html ( ) + '</' + default _tag + '>' ) ; }
else { $ ( ul ) . before ( $ ( li ) . html ( ) ) ; } }
$ ( li ) . remove ( ) ; editor . html . wrap ( ) ; if ( $ ( ul ) . find ( 'li' ) . length === 0 ) $ ( ul ) . remove ( ) ; } }
function _del ( marker ) { var li = _firstParentLI ( marker ) ; var next _li = li . nextSibling ; var contents ; if ( next _li ) { contents = editor . node . contents ( next _li ) ; if ( contents . length && contents [ 0 ] . tagName == 'BR' ) { $ ( contents [ 0 ] ) . remove ( ) ; }
$ ( next _li ) . find ( editor . html . blockTagsQuery ( ) ) . not ( 'ol, ul, table' ) . each ( function ( ) { if ( this . parentNode == next _li ) { $ ( this ) . replaceWith ( $ ( this ) . html ( ) + ( editor . node . isEmpty ( this ) ? '' : '<br>' ) ) ; } } ) ; var last _node = marker ; var node = editor . node . contents ( next _li ) [ 0 ] ; var tmp ; while ( node && ! editor . node . isList ( node ) ) { tmp = node . nextSibling ; $ ( last _node ) . after ( node ) ; last _node = node ; node = tmp ; }
while ( node ) { tmp = node . nextSibling ; $ ( li ) . append ( node ) ; node = tmp ; }
$ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; $ ( next _li ) . remove ( ) ; }
else { var next _node = li ; while ( ! next _node . nextSibling && next _node != editor . el ) { next _node = next _node . parentNode ; }
if ( next _node == editor . el ) return false ; next _node = next _node . nextSibling ; if ( editor . node . isBlock ( next _node ) ) { if ( $ . FE . NO _DELETE _TAGS . indexOf ( next _node . tagName ) < 0 ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; contents = editor . node . contents ( li ) ; if ( contents . length && contents [ contents . length - 1 ] . tagName == 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) ; }
$ ( li ) . append ( $ ( next _node ) . html ( ) ) ; $ ( next _node ) . remove ( ) ; } }
else { contents = editor . node . contents ( li ) ; if ( contents . length && contents [ contents . length - 1 ] . tagName == 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) ; }
$ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; while ( next _node && ! editor . node . isBlock ( next _node ) && next _node . tagName != 'BR' ) { $ ( li ) . append ( $ ( next _node ) ) ; next _node = next _node . nextSibling ; } } } }
return { _startEnter : _startEnter , _middleEnter : _middleEnter , _endEnter : _endEnter , _backspace : _backspace , _del : _del } } ; $ . FE . NO _DELETE _TAGS = [ 'TH' , 'TD' , 'TR' , 'TABLE' , 'FORM' ] ; $ . FE . SIMPLE _ENTER _TAGS = [ 'TH' , 'TD' , 'LI' , 'DL' , 'DT' , 'FORM' ] ; $ . FE . MODULES . cursor = function ( editor ) { function _atEnd ( node ) { if ( ! node ) return false ; if ( editor . node . isBlock ( node ) ) return true ; if ( node . nextSibling && node . nextSibling . nodeType == Node . TEXT _NODE && node . nextSibling . textContent . replace ( /\u200b/g , '' ) . length === 0 ) { return _atEnd ( node . nextSibling ) ; }
if ( node . nextSibling && ! ( node . previousSibling && node . nextSibling . tagName == 'BR' && ! node . nextSibling . nextSibling ) ) return false ; return _atEnd ( node . parentNode ) ; }
function _atStart ( node ) { if ( ! node ) return false ; if ( editor . node . isBlock ( node ) ) return true ; if ( node . previousSibling && node . previousSibling . nodeType == Node . TEXT _NODE && node . previousSibling . textContent . replace ( /\u200b/g , '' ) . length === 0 ) { return _atStart ( node . previousSibling ) ; }
if ( node . previousSibling ) return false ; if ( ! node . previousSibling && editor . node . hasClass ( node . parentNode , 'fr-inner' ) ) return true ; return _atStart ( node . parentNode ) ; }
function _isAtStart ( node , container ) { if ( ! node ) return false ; if ( node == editor . $wp . get ( 0 ) ) return false ; if ( node . previousSibling && node . previousSibling . nodeType == Node . TEXT _NODE && node . previousSibling . textContent . replace ( /\u200b/g , '' ) . length === 0 ) { return _isAtStart ( node . previousSibling , container ) ; }
if ( node . previousSibling ) return false ; if ( node . parentNode == container ) return true ; return _isAtStart ( node . parentNode , container ) ; }
function _isAtEnd ( node , container ) { if ( ! node ) return false ; if ( node == editor . $wp . get ( 0 ) ) return false ; if ( node . nextSibling && node . nextSibling . nodeType == Node . TEXT _NODE && node . nextSibling . textContent . replace ( /\u200b/g , '' ) . length === 0 ) { return _isAtEnd ( node . nextSibling , container ) ; }
if ( node . nextSibling && ! ( node . previousSibling && node . nextSibling . tagName == 'BR' && ! node . nextSibling . nextSibling ) ) return false ; if ( node . parentNode == container ) return true ; return _isAtEnd ( node . parentNode , container ) ; }
function _inLi ( node ) { return $ ( node ) . parentsUntil ( editor . $el , 'LI' ) . length > 0 && $ ( node ) . parentsUntil ( 'LI' , 'TABLE' ) . length === 0 ; }
function _getExtremityCharacterLength ( text , first ) { var special _chars _regex = new RegExp ( ( first ? '^' : '' ) + '(([\\uD83C-\\uDBFF\\uDC00-\\uDFFF]+\\u200D)*[\\uD83C-\\uDBFF\\uDC00-\\uDFFF]{2})' + ( ( first ? '' : '$' ) ) , 'i' ) ; var matches = text . match ( special _chars _regex ) ; if ( ! matches ) { return 1 ; }
else { return matches [ 0 ] . length ; } }
function _startBackspace ( marker ) { var quote = $ ( marker ) . parentsUntil ( editor . $el , 'BLOCKQUOTE' ) . length > 0 ; var deep _parent = editor . node . deepestParent ( marker , [ ] , ! quote ) ; var current _block = deep _parent ; while ( deep _parent && ! deep _parent . previousSibling && deep _parent . tagName != 'BLOCKQUOTE' && deep _parent . parentElement != editor . el && ! editor . node . hasClass ( deep _parent . parentElement , 'fr-inner' ) && $ . FE . SIMPLE _ENTER _TAGS . indexOf ( deep _parent . parentElement . tagName ) < 0 ) { deep _parent = deep _parent . parentElement ; }
if ( deep _parent && deep _parent . tagName == 'BLOCKQUOTE' ) { var m _parent = editor . node . deepestParent ( marker , [ $ ( marker ) . parentsUntil ( editor . $el , 'BLOCKQUOTE' ) . get ( 0 ) ] ) ; if ( m _parent && m _parent . previousSibling ) { deep _parent = m _parent ; current _block = m _parent ; } }
if ( deep _parent !== null ) { var prev _node = deep _parent . previousSibling ; var contents ; if ( editor . node . isBlock ( deep _parent ) && editor . node . isEditable ( deep _parent ) ) { if ( prev _node && $ . FE . NO _DELETE _TAGS . indexOf ( prev _node . tagName ) < 0 ) { if ( editor . node . isDeletable ( prev _node ) ) { $ ( prev _node ) . remove ( ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; }
else { if ( editor . node . isEditable ( prev _node ) ) { if ( editor . node . isBlock ( prev _node ) ) { if ( editor . node . isEmpty ( prev _node ) && ! editor . node . isList ( prev _node ) ) { $ ( prev _node ) . remove ( ) ; $ ( marker ) . after ( editor . opts . keepFormatOnDelete ? $ . FE . INVISIBLE _SPACE : '' ) ; }
else { if ( editor . node . isList ( prev _node ) ) { prev _node = $ ( prev _node ) . find ( 'li:last' ) . get ( 0 ) ; }
contents = editor . node . contents ( prev _node ) ; if ( contents . length && contents [ contents . length - 1 ] . tagName == 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) ; }
if ( prev _node . tagName == 'BLOCKQUOTE' && deep _parent . tagName != 'BLOCKQUOTE' ) { contents = editor . node . contents ( prev _node ) ; while ( contents . length && editor . node . isBlock ( contents [ contents . length - 1 ] ) ) { prev _node = contents [ contents . length - 1 ] ; contents = editor . node . contents ( prev _node ) ; } }
else if ( prev _node . tagName != 'BLOCKQUOTE' && current _block . tagName == 'BLOCKQUOTE' ) { contents = editor . node . contents ( current _block ) ; while ( contents . length && editor . node . isBlock ( contents [ 0 ] ) ) { current _block = contents [ 0 ] ; contents = editor . node . contents ( current _block ) ; } }
if ( editor . node . isEmpty ( deep _parent ) ) { $ ( marker ) . remove ( ) ; editor . selection . setAtEnd ( prev _node , true ) ; }
else { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; var prev _children = prev _node . childNodes ; if ( ! editor . node . isBlock ( prev _children [ prev _children . length - 1 ] ) ) { $ ( prev _node ) . append ( current _block . innerHTML ) ; }
else { $ ( prev _children [ prev _children . length - 1 ] ) . append ( current _block . innerHTML ) ; } }
$ ( current _block ) . remove ( ) ; if ( editor . node . isEmpty ( deep _parent ) ) { $ ( deep _parent ) . remove ( ) ; } } }
else { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; if ( deep _parent . tagName == 'BLOCKQUOTE' && prev _node . nodeType == Node . ELEMENT _NODE ) { $ ( prev _node ) . remove ( ) ; }
else { $ ( prev _node ) . after ( editor . node . isEmpty ( deep _parent ) ? '' : $ ( deep _parent ) . html ( ) ) ; $ ( deep _parent ) . remove ( ) ; if ( prev _node . tagName == 'BR' ) $ ( prev _node ) . remove ( ) ; } } } } }
else if ( ! prev _node ) { if ( deep _parent && deep _parent . tagName == 'BLOCKQUOTE' && $ ( deep _parent ) . text ( ) . replace ( /\u200B/g , '' ) . length == 0 ) { $ ( deep _parent ) . remove ( ) ; } } }
else { } } }
function _middleBackspace ( marker ) { var prev _node = marker ; while ( ! prev _node . previousSibling ) { prev _node = prev _node . parentNode ; if ( editor . node . isElement ( prev _node ) ) return false ; }
prev _node = prev _node . previousSibling ; var contents ; if ( ! editor . node . isBlock ( prev _node ) && editor . node . isEditable ( prev _node ) ) { contents = editor . node . contents ( prev _node ) ; while ( prev _node . nodeType != Node . TEXT _NODE && ! editor . node . isDeletable ( prev _node ) && contents . length && editor . node . isEditable ( prev _node ) ) { prev _node = contents [ contents . length - 1 ] ; contents = editor . node . contents ( prev _node ) ; }
if ( prev _node . nodeType == Node . TEXT _NODE ) { var txt = prev _node . textContent ; var len = txt . length ; if ( txt . length && txt [ txt . length - 1 ] === '\n' ) { prev _node . textContent = txt . substring ( 0 , len - 2 ) ; if ( prev _node . textContent . length === 0 ) { prev _node . parentNode . removeChild ( prev _node ) ; }
return _middleBackspace ( marker ) ; }
if ( editor . opts . tabSpaces && txt . length >= editor . opts . tabSpaces ) { var tab _str = txt . substr ( txt . length - editor . opts . tabSpaces , txt . length - 1 ) ; if ( tab _str . replace ( / /g , '' ) . replace ( new RegExp ( $ . FE . UNICODE _NBSP , 'g' ) , '' ) . length === 0 ) { len = txt . length - editor . opts . tabSpaces + 1 ; } }
prev _node . textContent = txt . substring ( 0 , len - _getExtremityCharacterLength ( txt ) ) ; if ( editor . opts . htmlUntouched && ! marker . nextSibling && prev _node . textContent . length && prev _node . textContent [ prev _node . textContent . length - 1 ] === ' ' ) { prev _node . textContent = prev _node . textContent . substring ( 0 , prev _node . textContent . length - 1 ) + $ . FE . UNICODE _NBSP ; }
var deleted = ( txt . length != prev _node . textContent . length ) ; if ( prev _node . textContent . length === 0 ) { if ( deleted && editor . opts . keepFormatOnDelete ) { $ ( prev _node ) . after ( $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS ) ; }
else { if ( ( ( prev _node . parentNode . childNodes . length == 2 && prev _node . parentNode == marker . parentNode ) || prev _node . parentNode . childNodes . length == 1 ) && ! editor . node . isBlock ( prev _node . parentNode ) && ! editor . node . isElement ( prev _node . parentNode ) && editor . node . isDeletable ( prev _node . parentNode ) ) { $ ( prev _node . parentNode ) . after ( $ . FE . MARKERS ) ; $ ( prev _node . parentNode ) . remove ( ) ; }
else { while ( ! editor . node . isElement ( prev _node . parentNode ) && editor . node . isEmpty ( prev _node . parentNode ) && $ . FE . NO _DELETE _TAGS . indexOf ( prev _node . parentNode . tagName ) < 0 ) { var t _node = prev _node ; prev _node = prev _node . parentNode ; t _node . parentNode . removeChild ( t _node ) ; }
$ ( prev _node ) . after ( $ . FE . MARKERS ) ; if ( editor . node . isElement ( prev _node . parentNode ) && ! marker . nextSibling && prev _node . previousSibling && prev _node . previousSibling . tagName == 'BR' ) { $ ( marker ) . after ( '<br>' ) ; }
prev _node . parentNode . removeChild ( prev _node ) ; } } }
else { $ ( prev _node ) . after ( $ . FE . MARKERS ) ; } }
else if ( editor . node . isDeletable ( prev _node ) ) { $ ( prev _node ) . after ( $ . FE . MARKERS ) ; $ ( prev _node ) . remove ( ) ; }
else { if ( marker . nextSibling && marker . nextSibling . tagName == 'BR' && editor . node . isVoid ( prev _node ) && prev _node . tagName != 'BR' ) { $ ( marker . nextSibling ) . remove ( ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; }
else if ( editor . events . trigger ( 'node.remove' , [ $ ( prev _node ) ] ) !== false ) { $ ( prev _node ) . after ( $ . FE . MARKERS ) ; $ ( prev _node ) . remove ( ) ; } } }
else if ( $ . FE . NO _DELETE _TAGS . indexOf ( prev _node . tagName ) < 0 && ( editor . node . isEditable ( prev _node ) || editor . node . isDeletable ( prev _node ) ) ) { if ( editor . node . isDeletable ( prev _node ) ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; $ ( prev _node ) . remove ( ) ; }
else if ( editor . node . isEmpty ( prev _node ) && ! editor . node . isList ( prev _node ) ) { $ ( prev _node ) . remove ( ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; }
else { if ( editor . node . isList ( prev _node ) ) prev _node = $ ( prev _node ) . find ( 'li:last' ) . get ( 0 ) ; contents = editor . node . contents ( prev _node ) ; if ( contents && contents [ contents . length - 1 ] . tagName == 'BR' ) { $ ( contents [ contents . length - 1 ] ) . remove ( ) ; }
contents = editor . node . contents ( prev _node ) ; while ( contents && editor . node . isBlock ( contents [ contents . length - 1 ] ) ) { prev _node = contents [ contents . length - 1 ] ; contents = editor . node . contents ( prev _node ) ; }
$ ( prev _node ) . append ( $ . FE . MARKERS ) ; var next _node = marker ; while ( ! next _node . previousSibling ) { next _node = next _node . parentNode ; }
while ( next _node && next _node . tagName !== 'BR' && ! editor . node . isBlock ( next _node ) ) { var copy _node = next _node ; next _node = next _node . nextSibling ; $ ( prev _node ) . append ( copy _node ) ; }
if ( next _node && next _node . tagName == 'BR' ) $ ( next _node ) . remove ( ) ; $ ( marker ) . remove ( ) ; } }
else { if ( marker . nextSibling && marker . nextSibling . tagName == 'BR' ) { $ ( marker . nextSibling ) . remove ( ) ; } } }
function backspace ( ) { var do _default = false ; var marker = editor . markers . insert ( ) ; if ( ! marker ) return true ; var p _node = marker . parentNode ; while ( p _node && ! editor . node . isElement ( p _node ) ) { if ( p _node . getAttribute ( 'contenteditable' ) === 'false' ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; editor . selection . restore ( ) ; return false ; }
else if ( p _node . getAttribute ( 'contenteditable' ) === 'true' ) { break ; }
p _node = p _node . parentNode ; }
editor . el . normalize ( ) ; var prev _node = marker . previousSibling ; if ( prev _node ) { var txt = prev _node . textContent ; if ( txt && txt . length && txt . charCodeAt ( txt . length - 1 ) == 8203 ) { if ( txt . length == 1 ) { $ ( prev _node ) . remove ( ) }
else { prev _node . textContent = prev _node . textContent . substr ( 0 , txt . length - _getExtremityCharacterLength ( txt ) ) ; } } }
if ( _atEnd ( marker ) ) { do _default = _middleBackspace ( marker ) ; }
else if ( _atStart ( marker ) ) { if ( _inLi ( marker ) && _isAtStart ( marker , $ ( marker ) . parents ( 'li:first' ) . get ( 0 ) ) ) { editor . cursorLists . _backspace ( marker ) ; }
else { _startBackspace ( marker ) ; } }
else { do _default = _middleBackspace ( marker ) ; }
$ ( marker ) . remove ( ) ; _cleanEmptyBlockquotes ( ) ; editor . html . fillEmptyBlocks ( true ) ; if ( ! editor . opts . htmlUntouched ) { editor . html . cleanEmptyTags ( ) ; editor . clean . lists ( ) ; editor . spaces . normalizeAroundCursor ( ) ; }
editor . selection . restore ( ) ; return do _default ; }
function _endDel ( marker ) { var quote = $ ( marker ) . parentsUntil ( editor . $el , 'BLOCKQUOTE' ) . length > 0 ; var deep _parent = editor . node . deepestParent ( marker , [ ] , ! quote ) ; if ( deep _parent && deep _parent . tagName == 'BLOCKQUOTE' ) { var m _parent = editor . node . deepestParent ( marker , [ $ ( marker ) . parentsUntil ( editor . $el , 'BLOCKQUOTE' ) . get ( 0 ) ] ) ; if ( m _parent && m _parent . nextSibling ) { deep _parent = m _parent ; } }
if ( deep _parent !== null ) { var next _node = deep _parent . nextSibling ; var contents ; if ( editor . node . isBlock ( deep _parent ) && ( editor . node . isEditable ( deep _parent ) || editor . node . isDeletable ( deep _parent ) ) ) { if ( next _node && $ . FE . NO _DELETE _TAGS . indexOf ( next _node . tagName ) < 0 ) { if ( editor . node . isDeletable ( next _node ) ) { $ ( next _node ) . remove ( ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; }
else { if ( editor . node . isBlock ( next _node ) && editor . node . isEditable ( next _node ) ) { if ( editor . node . isList ( next _node ) ) { if ( editor . node . isEmpty ( deep _parent , true ) ) { $ ( deep _parent ) . remove ( ) ; $ ( next _node ) . find ( 'li:first' ) . prepend ( $ . FE . MARKERS ) ; }
else { var $li = $ ( next _node ) . find ( 'li:first' ) ; if ( deep _parent . tagName == 'BLOCKQUOTE' ) { contents = editor . node . contents ( deep _parent ) ; if ( contents . length && editor . node . isBlock ( contents [ contents . length - 1 ] ) ) { deep _parent = contents [ contents . length - 1 ] ; } }
if ( $li . find ( 'ul, ol' ) . length === 0 ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; $li . find ( editor . html . blockTagsQuery ( ) ) . not ( 'ol, ul, table' ) . each ( function ( ) { if ( this . parentNode == $li . get ( 0 ) ) { $ ( this ) . replaceWith ( $ ( this ) . html ( ) + ( editor . node . isEmpty ( this ) ? '' : '<br>' ) ) ; } } ) ; $ ( deep _parent ) . append ( editor . node . contents ( $li . get ( 0 ) ) ) ; $li . remove ( ) ; if ( $ ( next _node ) . find ( 'li' ) . length === 0 ) $ ( next _node ) . remove ( ) ; } } }
else { contents = editor . node . contents ( next _node ) ; if ( contents . length && contents [ 0 ] . tagName == 'BR' ) { $ ( contents [ 0 ] ) . remove ( ) ; }
if ( next _node . tagName != 'BLOCKQUOTE' && deep _parent . tagName == 'BLOCKQUOTE' ) { contents = editor . node . contents ( deep _parent ) ; while ( contents . length && editor . node . isBlock ( contents [ contents . length - 1 ] ) ) { deep _parent = contents [ contents . length - 1 ] ; contents = editor . node . contents ( deep _parent ) ; } }
else if ( next _node . tagName == 'BLOCKQUOTE' && deep _parent . tagName != 'BLOCKQUOTE' ) { contents = editor . node . contents ( next _node ) ; while ( contents . length && editor . node . isBlock ( contents [ 0 ] ) ) { next _node = contents [ 0 ] ; contents = editor . node . contents ( next _node ) ; } }
$ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; $ ( deep _parent ) . append ( next _node . innerHTML ) ; $ ( next _node ) . remove ( ) ; } }
else { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; while ( next _node && next _node . tagName !== 'BR' && ! editor . node . isBlock ( next _node ) && editor . node . isEditable ( next _node ) ) { var copy _node = next _node ; next _node = next _node . nextSibling ; $ ( deep _parent ) . append ( copy _node ) ; }
if ( next _node && next _node . tagName == 'BR' && editor . node . isEditable ( next _node ) ) { $ ( next _node ) . remove ( ) ; } } } } }
else { } } }
function _middleDel ( marker ) { var next _node = marker ; while ( ! next _node . nextSibling ) { next _node = next _node . parentNode ; if ( editor . node . isElement ( next _node ) ) return false ; }
next _node = next _node . nextSibling ; if ( next _node . tagName == 'BR' && editor . node . isEditable ( next _node ) ) { if ( next _node . nextSibling ) { if ( editor . node . isBlock ( next _node . nextSibling ) && editor . node . isEditable ( next _node . nextSibling ) ) { if ( $ . FE . NO _DELETE _TAGS . indexOf ( next _node . nextSibling . tagName ) < 0 ) { next _node = next _node . nextSibling ; $ ( next _node . previousSibling ) . remove ( ) ; }
else { $ ( next _node ) . remove ( ) ; return ; } } }
else if ( _atEnd ( next _node ) ) { if ( _inLi ( marker ) ) { editor . cursorLists . _del ( marker ) ; }
else { var deep _parent = editor . node . deepestParent ( next _node ) ; if ( deep _parent ) { if ( ! editor . node . isEmpty ( editor . node . blockParent ( next _node ) ) || ( editor . node . blockParent ( next _node ) . nextSibling && $ . FE . NO _DELETE _TAGS . indexOf ( editor . node . blockParent ( next _node ) . nextSibling . tagName ) ) < 0 ) { $ ( next _node ) . remove ( ) ; }
_endDel ( marker ) ; } }
return ; } }
var contents ; if ( ! editor . node . isBlock ( next _node ) && editor . node . isEditable ( next _node ) ) { contents = editor . node . contents ( next _node ) ; while ( next _node . nodeType != Node . TEXT _NODE && contents . length && ! editor . node . isDeletable ( next _node ) && editor . node . isEditable ( next _node ) ) { next _node = contents [ 0 ] ; contents = editor . node . contents ( next _node ) ; }
if ( next _node . nodeType == Node . TEXT _NODE ) { $ ( next _node ) . before ( $ . FE . MARKERS ) ; if ( next _node . textContent . length ) { next _node . textContent = next _node . textContent . substring ( _getExtremityCharacterLength ( next _node . textContent , true ) , next _node . textContent . length ) ; } }
else if ( editor . node . isDeletable ( next _node ) ) { $ ( next _node ) . before ( $ . FE . MARKERS ) ; $ ( next _node ) . remove ( ) ; }
else { if ( editor . events . trigger ( 'node.remove' , [ $ ( next _node ) ] ) !== false ) { $ ( next _node ) . before ( $ . FE . MARKERS ) ; $ ( next _node ) . remove ( ) ; } }
$ ( marker ) . remove ( ) ; }
else if ( $ . FE . NO _DELETE _TAGS . indexOf ( next _node . tagName ) < 0 && ( editor . node . isEditable ( next _node ) || editor . node . isDeletable ( next _node ) ) ) { if ( editor . node . isDeletable ( next _node ) ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; $ ( next _node ) . remove ( ) ; }
else { if ( editor . node . isList ( next _node ) ) { if ( marker . previousSibling ) { $ ( next _node ) . find ( 'li:first' ) . prepend ( marker ) ; editor . cursorLists . _backspace ( marker ) ; }
else { $ ( next _node ) . find ( 'li:first' ) . prepend ( $ . FE . MARKERS ) ; $ ( marker ) . remove ( ) ; } }
else { contents = editor . node . contents ( next _node ) ; if ( contents && contents . length && contents [ 0 ] . tagName == 'BR' ) { $ ( contents [ 0 ] ) . remove ( ) ; }
if ( contents && next _node . tagName == 'BLOCKQUOTE' ) { var node = contents [ 0 ] ; $ ( marker ) . before ( $ . FE . MARKERS ) ; while ( node && node . tagName != 'BR' ) { var tmp = node ; node = node . nextSibling ; $ ( marker ) . before ( tmp ) ; }
if ( node && node . tagName == 'BR' ) { $ ( node ) . remove ( ) ; } }
else { $ ( marker ) . after ( $ ( next _node ) . html ( ) ) . after ( $ . FE . MARKERS ) ; $ ( next _node ) . remove ( ) ; } } } } }
function del ( ) { var marker = editor . markers . insert ( ) ; if ( ! marker ) return false ; editor . el . normalize ( ) ; if ( _atEnd ( marker ) ) { if ( _inLi ( marker ) ) { if ( $ ( marker ) . parents ( 'li:first' ) . find ( 'ul, ol' ) . length === 0 ) { editor . cursorLists . _del ( marker ) ; }
else { var $li = $ ( marker ) . parents ( 'li:first' ) . find ( 'ul:first, ol:first' ) . find ( 'li:first' ) ; $li = $li . find ( editor . html . blockTagsQuery ( ) ) . get ( - 1 ) || $li ; $li . prepend ( marker ) ; editor . cursorLists . _backspace ( marker ) ; } }
else { _endDel ( marker ) ; } }
else if ( _atStart ( marker ) ) { _middleDel ( marker ) ; }
else { _middleDel ( marker ) ; }
$ ( marker ) . remove ( ) ; _cleanEmptyBlockquotes ( ) ; editor . html . fillEmptyBlocks ( true ) ; if ( ! editor . opts . htmlUntouched ) { editor . html . cleanEmptyTags ( ) ; editor . clean . lists ( ) ; }
editor . spaces . normalizeAroundCursor ( ) ; editor . selection . restore ( ) ; }
function _cleanEmptyBlockquotes ( ) { var blks = editor . el . querySelectorAll ( 'blockquote:empty' ) ; for ( var i = 0 ; i < blks . length ; i ++ ) { blks [ i ] . parentNode . removeChild ( blks [ i ] ) ; } }
function _cleanNodesToRemove ( ) { editor . $el . find ( '.fr-to-remove' ) . each ( function ( ) { var contents = editor . node . contents ( this ) ; for ( var i = 0 ; i < contents . length ; i ++ ) { if ( contents [ i ] . nodeType == Node . TEXT _NODE ) { contents [ i ] . textContent = contents [ i ] . textContent . replace ( /\u200B/g , '' ) ; } }
$ ( this ) . replaceWith ( this . innerHTML ) ; } ) }
function _endEnter ( marker , shift , quote ) { var deep _parent = editor . node . deepestParent ( marker , [ ] , ! quote ) ; var default _tag ; if ( deep _parent && deep _parent . tagName == 'BLOCKQUOTE' ) { if ( _isAtEnd ( marker , deep _parent ) ) { default _tag = editor . html . defaultTag ( ) ; if ( ! shift ) { if ( default _tag ) { $ ( deep _parent ) . after ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br>' + '</' + default _tag + '>' ) ; }
else { $ ( deep _parent ) . after ( $ . FE . MARKERS + '<br>' ) ; } }
else { $ ( marker ) . replaceWith ( '<br>' + $ . FE . MARKERS ) ; }
$ ( marker ) . remove ( ) ; return false ; }
else { _middleEnter ( marker , shift , quote ) ; return false ; } }
if ( deep _parent == null ) { default _tag = editor . html . defaultTag ( ) ; if ( ! default _tag || ! editor . node . isElement ( marker . parentNode ) ) { if ( marker . previousSibling && ! $ ( marker . previousSibling ) . is ( 'br' ) && ! marker . nextSibling ) { $ ( marker ) . replaceWith ( '<br>' + $ . FE . MARKERS + '<br>' ) ; }
else { $ ( marker ) . replaceWith ( '<br>' + $ . FE . MARKERS ) ; } }
else { $ ( marker ) . replaceWith ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br>' + '</' + default _tag + '>' ) ; } }
else { var c _node = marker ; var str = '' ; if ( deep _parent . tagName == 'PRE' && ! marker . nextSibling ) shift = true ; if ( ! editor . node . isBlock ( deep _parent ) || shift ) { str = '<br/>' ; }
var c _str = '' ; var o _str = '' ; default _tag = editor . html . defaultTag ( ) ; var open _default _tag = '' ; var close _default _tag = '' ; if ( default _tag && editor . node . isBlock ( deep _parent ) ) { open _default _tag = '<' + default _tag + '>' ; close _default _tag = '</' + default _tag + '>' ; if ( deep _parent . tagName == default _tag . toUpperCase ( ) ) { open _default _tag = editor . node . openTagString ( $ ( deep _parent ) . clone ( ) . removeAttr ( 'id' ) . get ( 0 ) ) ; } }
do { c _node = c _node . parentNode ; if ( ! shift || c _node != deep _parent || ( shift && ! editor . node . isBlock ( deep _parent ) ) ) { c _str = c _str + editor . node . closeTagString ( c _node ) ; if ( c _node == deep _parent && editor . node . isBlock ( deep _parent ) ) { o _str = open _default _tag + o _str ; }
else { var cls = ( c _node . tagName == 'A' && _isAtEnd ( marker , c _node ) ) ? 'fr-to-remove' : '' ; o _str = editor . node . openTagString ( $ ( c _node ) . clone ( ) . addClass ( cls ) . get ( 0 ) ) + o _str ; } } } while ( c _node != deep _parent ) ; str = c _str + str + o _str + ( ( marker . parentNode == deep _parent && editor . node . isBlock ( deep _parent ) ) ? '' : $ . FE . INVISIBLE _SPACE ) + $ . FE . MARKERS ; if ( editor . node . isBlock ( deep _parent ) && ! $ ( deep _parent ) . find ( '*:last' ) . is ( 'br' ) ) { $ ( deep _parent ) . append ( '<br/>' ) ; }
$ ( marker ) . after ( '<span id="fr-break"></span>' ) ; $ ( marker ) . remove ( ) ; if ( ( ! deep _parent . nextSibling || editor . node . isBlock ( deep _parent . nextSibling ) ) && ! editor . node . isBlock ( deep _parent ) ) { $ ( deep _parent ) . after ( '<br>' ) ; }
var html ; if ( ! shift && editor . node . isBlock ( deep _parent ) ) { html = editor . node . openTagString ( deep _parent ) + $ ( deep _parent ) . html ( ) + close _default _tag ; }
else { html = editor . node . openTagString ( deep _parent ) + $ ( deep _parent ) . html ( ) + editor . node . closeTagString ( deep _parent ) ; }
html = html . replace ( /<span id="fr-break"><\/span>/g , str ) ; $ ( deep _parent ) . replaceWith ( html ) ; } }
function _startEnter ( marker , shift , quote ) { var deep _parent = editor . node . deepestParent ( marker , [ ] , ! quote ) ; var default _tag ; if ( deep _parent && deep _parent . tagName == 'TABLE' ) { $ ( deep _parent ) . find ( 'td:first, th:first' ) . prepend ( marker ) ; return _startEnter ( marker , shift , quote ) ; }
if ( deep _parent && deep _parent . tagName == 'BLOCKQUOTE' ) { if ( _isAtStart ( marker , deep _parent ) ) { if ( ! shift ) { default _tag = editor . html . defaultTag ( ) ; if ( default _tag ) { $ ( deep _parent ) . before ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br>' + '</' + default _tag + '>' ) ; }
else { $ ( deep _parent ) . before ( $ . FE . MARKERS + '<br>' ) ; }
$ ( marker ) . remove ( ) ; return false ; } }
else if ( _isAtEnd ( marker , deep _parent ) ) { _endEnter ( marker , shift , true ) ; }
else { _middleEnter ( marker , shift , true ) ; } }
if ( deep _parent == null ) { default _tag = editor . html . defaultTag ( ) ; if ( ! default _tag || ! editor . node . isElement ( marker . parentNode ) ) { $ ( marker ) . replaceWith ( '<br>' + $ . FE . MARKERS ) ; }
else { $ ( marker ) . replaceWith ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br>' + '</' + default _tag + '>' ) ; } }
else { if ( editor . node . isBlock ( deep _parent ) ) { if ( deep _parent . tagName == 'PRE' ) shift = true ; if ( shift ) { $ ( marker ) . remove ( ) ; $ ( deep _parent ) . prepend ( '<br>' + $ . FE . MARKERS ) ; }
else if ( editor . node . isEmpty ( deep _parent , true ) ) { return _endEnter ( marker , shift , quote ) ; }
else { if ( ! editor . opts . keepFormatOnDelete ) { $ ( deep _parent ) . before ( editor . node . openTagString ( $ ( deep _parent ) . clone ( ) . removeAttr ( 'id' ) . get ( 0 ) ) + '<br>' + editor . node . closeTagString ( deep _parent ) ) ; }
else { var tmp = marker ; var str = $ . FE . INVISIBLE _SPACE ; while ( tmp != deep _parent && ! editor . node . isElement ( tmp ) ) { tmp = tmp . parentNode ; str = editor . node . openTagString ( tmp ) + str + editor . node . closeTagString ( tmp ) ; }
$ ( deep _parent ) . before ( str ) ; } } }
else { $ ( deep _parent ) . before ( '<br>' ) ; }
$ ( marker ) . remove ( ) ; } }
function _middleEnter ( marker , shift , quote ) { var deep _parent = editor . node . deepestParent ( marker , [ ] , ! quote ) ; if ( deep _parent == null ) { if ( editor . html . defaultTag ( ) && marker . parentNode === editor . el ) { $ ( marker ) . replaceWith ( '<' + editor . html . defaultTag ( ) + '>' + $ . FE . MARKERS + '<br></' + editor . html . defaultTag ( ) + '>' ) ; }
else { if ( ( ! marker . nextSibling || editor . node . isBlock ( marker . nextSibling ) ) ) { $ ( marker ) . after ( '<br>' ) ; }
$ ( marker ) . replaceWith ( '<br>' + $ . FE . MARKERS ) ; } }
else { var c _node = marker ; var str = '' ; if ( deep _parent . tagName == 'PRE' ) shift = true ; if ( ! editor . node . isBlock ( deep _parent ) || shift ) { str = '<br>' ; }
var c _str = '' ; var o _str = '' ; do { var tmp = c _node ; c _node = c _node . parentNode ; if ( deep _parent . tagName == 'BLOCKQUOTE' && editor . node . isEmpty ( tmp ) && ! editor . node . hasClass ( tmp , 'fr-marker' ) ) { if ( $ ( tmp ) . find ( marker ) . length > 0 ) { $ ( tmp ) . after ( marker ) ; } }
if ( ! ( deep _parent . tagName == 'BLOCKQUOTE' && ( _isAtEnd ( marker , c _node ) || _isAtStart ( marker , c _node ) ) ) ) { if ( ! shift || c _node != deep _parent || ( shift && ! editor . node . isBlock ( deep _parent ) ) ) { c _str = c _str + editor . node . closeTagString ( c _node ) ; var cls = ( c _node . tagName == 'A' && _isAtEnd ( marker , c _node ) ) ? 'fr-to-remove' : '' ; o _str = editor . node . openTagString ( $ ( c _node ) . clone ( ) . addClass ( cls ) . removeAttr ( 'id' ) . get ( 0 ) ) + o _str ; }
else if ( deep _parent . tagName == 'BLOCKQUOTE' && shift ) { c _str = '' ; o _str = '' ; } } } while ( c _node != deep _parent ) ; var add = ( ( deep _parent == marker . parentNode && editor . node . isBlock ( deep _parent ) ) || marker . nextSibling ) ; if ( deep _parent . tagName == 'BLOCKQUOTE' ) { if ( marker . previousSibling && editor . node . isBlock ( marker . previousSibling ) && marker . nextSibling && marker . nextSibling . tagName == 'BR' ) { $ ( marker . nextSibling ) . after ( marker ) ; if ( marker . nextSibling && marker . nextSibling . tagName == 'BR' ) { $ ( marker . nextSibling ) . remove ( ) ; } }
if ( shift ) { str = c _str + str + $ . FE . MARKERS + o _str ; }
else { var default _tag = editor . html . defaultTag ( ) ; str = c _str + str + ( default _tag ? '<' + default _tag + '>' : '' ) + $ . FE . MARKERS + '<br>' + ( default _tag ? '</' + default _tag + '>' : '' ) + o _str ; } }
else { str = c _str + str + o _str + ( add ? '' : $ . FE . INVISIBLE _SPACE ) + $ . FE . MARKERS ; }
$ ( marker ) . replaceWith ( '<span id="fr-break"></span>' ) ; var html = editor . node . openTagString ( deep _parent ) + $ ( deep _parent ) . html ( ) + editor . node . closeTagString ( deep _parent ) ; html = html . replace ( /<span id="fr-break"><\/span>/g , str ) ; $ ( deep _parent ) . replaceWith ( html ) ; } }
function enter ( shift ) { var marker = editor . markers . insert ( ) ; if ( ! marker ) return true ; var p _node = marker . parentNode ; while ( p _node && ! editor . node . isElement ( p _node ) ) { if ( p _node . getAttribute ( 'contenteditable' ) === 'false' ) { $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; editor . selection . restore ( ) ; return false ; }
else if ( p _node . getAttribute ( 'contenteditable' ) === 'true' ) { break ; }
p _node = p _node . parentNode ; }
editor . el . normalize ( ) ; var quote = false ; if ( $ ( marker ) . parentsUntil ( editor . $el , 'BLOCKQUOTE' ) . length > 0 ) { quote = true ; }
if ( $ ( marker ) . parentsUntil ( editor . $el , 'TD, TH' ) . length ) quote = false ; if ( _atEnd ( marker ) ) { if ( _inLi ( marker ) && ! shift && ! quote ) { editor . cursorLists . _endEnter ( marker ) ; }
else { _endEnter ( marker , shift , quote ) ; } }
else if ( _atStart ( marker ) ) { if ( _inLi ( marker ) && ! shift && ! quote ) { editor . cursorLists . _startEnter ( marker ) ; }
else { _startEnter ( marker , shift , quote ) ; } }
else { if ( _inLi ( marker ) && ! shift && ! quote ) { editor . cursorLists . _middleEnter ( marker ) ; }
else { _middleEnter ( marker , shift , quote ) ; } }
_cleanNodesToRemove ( ) ; editor . html . fillEmptyBlocks ( true ) ; if ( ! editor . opts . htmlUntouched ) { editor . html . cleanEmptyTags ( ) ; editor . clean . lists ( ) ; editor . spaces . normalizeAroundCursor ( ) ; }
editor . selection . restore ( ) ; }
return { enter : enter , backspace : backspace , del : del , isAtEnd : _isAtEnd , isAtStart : _isAtStart } }
$ . FE . ENTER _P = 0 ; $ . FE . ENTER _DIV = 1 ; $ . FE . ENTER _BR = 2 ; $ . FE . KEYCODE = { BACKSPACE : 8 , TAB : 9 , ENTER : 13 , SHIFT : 16 , CTRL : 17 , ALT : 18 , ESC : 27 , SPACE : 32 , ARROW _LEFT : 37 , ARROW _UP : 38 , ARROW _RIGHT : 39 , ARROW _DOWN : 40 , DELETE : 46 , ZERO : 48 , ONE : 49 , TWO : 50 , THREE : 51 , FOUR : 52 , FIVE : 53 , SIX : 54 , SEVEN : 55 , EIGHT : 56 , NINE : 57 , FF _SEMICOLON : 59 , FF _EQUALS : 61 , QUESTION _MARK : 63 , A : 65 , B : 66 , C : 67 , D : 68 , E : 69 , F : 70 , G : 71 , H : 72 , I : 73 , J : 74 , K : 75 , L : 76 , M : 77 , N : 78 , O : 79 , P : 80 , Q : 81 , R : 82 , S : 83 , T : 84 , U : 85 , V : 86 , W : 87 , X : 88 , Y : 89 , Z : 90 , META : 91 , NUM _ZERO : 96 , NUM _ONE : 97 , NUM _TWO : 98 , NUM _THREE : 99 , NUM _FOUR : 100 , NUM _FIVE : 101 , NUM _SIX : 102 , NUM _SEVEN : 103 , NUM _EIGHT : 104 , NUM _NINE : 105 , NUM _MULTIPLY : 106 , NUM _PLUS : 107 , NUM _MINUS : 109 , NUM _PERIOD : 110 , NUM _DIVISION : 111 , F1 : 112 , F2 : 113 , F3 : 114 , F4 : 115 , F5 : 116 , F6 : 117 , F7 : 118 , F8 : 119 , F9 : 120 , F10 : 121 , F11 : 122 , F12 : 123 , FF _HYPHEN : 173 , SEMICOLON : 186 , DASH : 189 , EQUALS : 187 , COMMA : 188 , HYPHEN : 189 , PERIOD : 190 , SLASH : 191 , APOSTROPHE : 192 , TILDE : 192 , SINGLE _QUOTE : 222 , OPEN _SQUARE _BRACKET : 219 , BACKSLASH : 220 , CLOSE _SQUARE _BRACKET : 221 , IME : 229 }
$ . extend ( $ . FE . DEFAULTS , { enter : $ . FE . ENTER _P , multiLine : true , tabSpaces : 0 } ) ; $ . FE . MODULES . keys = function ( editor ) { var IME = false ; var ios _snapshot = null ; function _enter ( e ) { if ( ! editor . opts . multiLine ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
else { if ( ! editor . helpers . isIOS ( ) ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
if ( ! editor . selection . isCollapsed ( ) ) editor . selection . remove ( ) ; editor . cursor . enter ( ) ; } }
function _shiftEnter ( e ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( editor . opts . multiLine ) { if ( ! editor . selection . isCollapsed ( ) ) editor . selection . remove ( ) ; editor . cursor . enter ( true ) ; } }
function _ctlBackspace ( ) { setTimeout ( function ( ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; } , 0 ) ; }
function _backspace ( e ) { if ( editor . selection . isCollapsed ( ) ) { editor . cursor . backspace ( ) ; if ( editor . helpers . isIOS ( ) ) { var range = editor . selection . ranges ( 0 ) ; range . deleteContents ( ) ; range . insertNode ( document . createTextNode ( '\u200B' ) ) ; var sel = editor . selection . get ( ) ; sel . modify ( 'move' , 'forward' , 'character' ) ; }
else { e . preventDefault ( ) ; e . stopPropagation ( ) ; } }
else { e . preventDefault ( ) ; e . stopPropagation ( ) ; editor . selection . remove ( ) ; }
editor . placeholder . refresh ( ) ; }
function _del ( e ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( editor . selection . text ( ) === '' ) { editor . cursor . del ( ) ; }
else { editor . selection . remove ( ) ; }
editor . placeholder . refresh ( ) ; }
function _space ( e ) { var el = editor . selection . element ( ) ; if ( ! editor . helpers . isMobile ( ) && ( el && el . tagName == 'A' ) ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( ! editor . selection . isCollapsed ( ) ) editor . selection . remove ( ) ; var marker = editor . markers . insert ( ) ; if ( marker ) { var prev _node = marker . previousSibling ; var next _node = marker . nextSibling ; if ( ! next _node && marker . parentNode && marker . parentNode . tagName == 'A' ) { marker . parentNode . insertAdjacentHTML ( 'afterend' , ' ' + $ . FE . MARKERS ) ; marker . parentNode . removeChild ( marker ) ; }
else { if ( prev _node && prev _node . nodeType == Node . TEXT _NODE && prev _node . textContent . length == 1 && prev _node . textContent . charCodeAt ( 0 ) == 160 ) { prev _node . textContent = prev _node . textContent + ' ' ; }
else { marker . insertAdjacentHTML ( 'beforebegin' , ' ' ) }
marker . outerHTML = $ . FE . MARKERS ; }
editor . selection . restore ( ) ; } } }
function _input ( ) { if ( editor . browser . mozilla && editor . selection . isCollapsed ( ) && ! IME ) { var range = editor . selection . ranges ( 0 ) ; var start _container = range . startContainer ; var start _offset = range . startOffset ; if ( start _container && start _container . nodeType == Node . TEXT _NODE && start _offset <= start _container . textContent . length && start _offset > 0 && start _container . textContent . charCodeAt ( start _offset - 1 ) == 32 ) { editor . selection . save ( ) ; editor . spaces . normalize ( ) ; editor . selection . restore ( ) ; } } }
function _cut ( ) { if ( editor . selection . isFull ( ) ) { setTimeout ( function ( ) { var default _tag = editor . html . defaultTag ( ) ; if ( default _tag ) { editor . $el . html ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br/></' + default _tag + '>' ) ; }
else { editor . $el . html ( $ . FE . MARKERS + '<br/>' ) ; }
editor . selection . restore ( ) ; editor . placeholder . refresh ( ) ; editor . button . bulkRefresh ( ) ; editor . undo . saveStep ( ) ; } , 0 ) ; } }
function _tab ( e ) { if ( editor . opts . tabSpaces > 0 ) { if ( editor . selection . isCollapsed ( ) ) { editor . undo . saveStep ( ) ; e . preventDefault ( ) ; e . stopPropagation ( ) ; var str = '' ; for ( var i = 0 ; i < editor . opts . tabSpaces ; i ++ ) str += ' ' ; editor . html . insert ( str ) ; editor . placeholder . refresh ( ) ; editor . undo . saveStep ( ) ; }
else { e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( ! e . shiftKey ) { editor . commands . indent ( ) ; }
else { editor . commands . outdent ( ) ; } } } }
function _mapKeyPress ( ) { IME = false ; }
function _clearIME ( ) { IME = false ; }
function isIME ( ) { return IME ; }
var key _down _code ; function _empty ( ) { var default _tag = editor . html . defaultTag ( ) ; if ( default _tag ) { editor . $el . html ( '<' + default _tag + '>' + $ . FE . MARKERS + '<br/></' + default _tag + '>' ) ; }
else { editor . $el . html ( $ . FE . MARKERS + '<br/>' ) ; }
editor . selection . restore ( ) ; }
function _mapKeyDown ( e ) { var sel _el = editor . selection . element ( ) ; if ( sel _el && [ 'INPUT' , 'TEXTAREA' ] . indexOf ( sel _el . tagName ) >= 0 ) return true ; if ( e && isArrow ( e . which ) ) { _removeInvisible ( ) ; return true ; }
editor . events . disableBlur ( ) ; ios _snapshot = null ; var key _code = e . which ; if ( key _code === 16 ) return true ; key _down _code = key _code ; if ( key _code === $ . FE . KEYCODE . IME ) { IME = true ; return true ; }
else { IME = false ; }
var char _key = ( isCharacter ( key _code ) && ! ctrlKey ( e ) && ! e . altKey ) ; var del _key = ( key _code == $ . FE . KEYCODE . BACKSPACE || key _code == $ . FE . KEYCODE . DELETE ) ; var selection _key = ( e . shiftKey && ( key _code === 33 || key _code === 34 || key _code === 35 || key _code === 36 ) ) ; if ( ( ! selection _key && editor . selection . isFull ( ) && ! editor . opts . keepFormatOnDelete && ! editor . placeholder . isVisible ( ) ) || ( del _key && editor . placeholder . isVisible ( ) && editor . opts . keepFormatOnDelete ) ) { if ( char _key || del _key ) { _empty ( ) ; if ( ! isCharacter ( key _code ) ) { e . preventDefault ( ) ; return true ; } } }
if ( key _code == $ . FE . KEYCODE . ENTER ) { if ( e . shiftKey ) { _shiftEnter ( e ) ; }
else { _enter ( e ) ; } }
else if ( key _code === $ . FE . KEYCODE . BACKSPACE && ( e . metaKey || e . ctrlKey ) ) { _ctlBackspace ( ) ; }
else if ( key _code == $ . FE . KEYCODE . BACKSPACE && ! ctrlKey ( e ) && ! e . altKey ) { if ( ! editor . placeholder . isVisible ( ) ) { _backspace ( e ) ; }
else { if ( ! editor . opts . keepFormatOnDelete ) { _empty ( ) ; }
e . preventDefault ( ) ; e . stopPropagation ( ) ; } }
else if ( key _code == $ . FE . KEYCODE . DELETE && ! ctrlKey ( e ) && ! e . altKey && ! e . shiftKey ) { if ( ! editor . placeholder . isVisible ( ) ) { _del ( e ) ; }
else { if ( ! editor . opts . keepFormatOnDelete ) { _empty ( ) ; }
e . preventDefault ( ) ; e . stopPropagation ( ) ; } }
else if ( key _code == $ . FE . KEYCODE . SPACE ) { _space ( e ) ; }
else if ( key _code == $ . FE . KEYCODE . TAB ) { _tab ( e ) ; }
else if ( ! ctrlKey ( e ) && isCharacter ( e . which ) && ! editor . selection . isCollapsed ( ) && ! e . ctrlKey && ! e . altKey ) { editor . selection . remove ( ) ; }
editor . events . enableBlur ( ) ; }
function _replaceU200B ( el ) { var walker = editor . doc . createTreeWalker ( el , NodeFilter . SHOW _TEXT , editor . node . filter ( function ( node ) { return /\u200B/gi . test ( node . textContent ) ; } ) , false ) ; while ( walker . nextNode ( ) ) { var node = walker . currentNode ; node . textContent = node . textContent . replace ( /\u200B/gi , '' ) ; } }
function positionCaret ( ) { if ( ! editor . $wp ) return true ; var info ; if ( ! editor . opts . height && ! editor . opts . heightMax ) { info = editor . position . getBoundingRect ( ) . top ; if ( editor . opts . toolbarBottom ) info += editor . opts . toolbarStickyOffset ; if ( editor . opts . iframe ) { info += editor . $iframe . offset ( ) . top ; info -= editor . helpers . scrollTop ( ) ; }
info += editor . opts . toolbarStickyOffset ; if ( info > editor . o _win . innerHeight - 20 ) { $ ( editor . o _win ) . scrollTop ( info + editor . helpers . scrollTop ( ) - editor . o _win . innerHeight + 20 ) ; }
info = editor . position . getBoundingRect ( ) . top ; if ( ! editor . opts . toolbarBottom ) info -= editor . opts . toolbarStickyOffset ; if ( editor . opts . iframe ) { info += editor . $iframe . offset ( ) . top ; info -= editor . helpers . scrollTop ( ) ; }
if ( info < editor . $tb . height ( ) + 20 ) { $ ( editor . o _win ) . scrollTop ( info + editor . helpers . scrollTop ( ) - editor . $tb . height ( ) - 20 ) ; } }
else { info = editor . position . getBoundingRect ( ) . top ; if ( editor . opts . iframe ) { info += editor . $iframe . offset ( ) . top ; }
if ( info > editor . $wp . offset ( ) . top - editor . helpers . scrollTop ( ) + editor . $wp . height ( ) - 20 ) { editor . $wp . scrollTop ( info + editor . $wp . scrollTop ( ) - ( editor . $wp . height ( ) + editor . $wp . offset ( ) . top ) + editor . helpers . scrollTop ( ) + 20 ) ; } } }
function _removeInvisible ( ) { var has _invisible = function ( node ) { if ( ! node ) return false ; var text = node . innerHTML ; text = text . replace ( /<span[^>]*? class\s*=\s*["']?fr-marker["']?[^>]+>\u200b<\/span>/gi , '' ) ; if ( text && /\u200B/ . test ( text ) && text . replace ( /\u200B/gi , '' ) . length > 0 ) return true ; return false ; }
var ios _CJK = function ( el ) { var CJKRegEx = /[\u3041-\u3096\u30A0-\u30FF\u4E00-\u9FFF\u3130-\u318F\uAC00-\uD7AF]/gi ; return ! editor . helpers . isIOS ( ) || ( ( el . textContent || '' ) . match ( CJKRegEx ) || [ ] ) . length === 0 ; }
var el = editor . selection . element ( ) ; if ( has _invisible ( el ) && ! editor . node . hasClass ( el , 'fr-marker' ) && el . tagName != 'IFRAME' && ios _CJK ( el ) ) { editor . selection . save ( ) ; _replaceU200B ( el ) ; editor . selection . restore ( ) ; } }
function _mapKeyUp ( e ) { var sel _el = editor . selection . element ( ) ; if ( sel _el && [ 'INPUT' , 'TEXTAREA' ] . indexOf ( sel _el . tagName ) >= 0 ) return true ; if ( e && e . which === 0 && key _down _code ) { e . which = key _down _code ; }
if ( editor . helpers . isAndroid ( ) && editor . browser . mozilla ) { return true ; }
if ( IME ) { return false ; }
if ( e && editor . helpers . isIOS ( ) && e . which == $ . FE . KEYCODE . ENTER ) { editor . doc . execCommand ( 'undo' ) }
if ( ! editor . selection . isCollapsed ( ) ) return true ; if ( e && ( e . which === $ . FE . KEYCODE . META || e . which == $ . FE . KEYCODE . CTRL ) ) return true ; if ( e && isArrow ( e . which ) ) return true ; if ( e && ! editor . helpers . isIOS ( ) && ( e . which == $ . FE . KEYCODE . ENTER || e . which == $ . FE . KEYCODE . BACKSPACE || ( e . which >= 37 && e . which <= 40 && ! editor . browser . msie ) ) ) { try { positionCaret ( ) ; }
catch ( ex ) { } }
_removeInvisible ( ) }
function ctrlKey ( e ) { if ( navigator . userAgent . indexOf ( 'Mac OS X' ) != - 1 ) { if ( e . metaKey && ! e . altKey ) return true ; }
else { if ( e . ctrlKey && ! e . altKey ) return true ; }
return false ; }
function isArrow ( key _code ) { if ( key _code >= $ . FE . KEYCODE . ARROW _LEFT && key _code <= $ . FE . KEYCODE . ARROW _DOWN ) { return true ; } }
function isCharacter ( key _code ) { if ( key _code >= $ . FE . KEYCODE . ZERO && key _code <= $ . FE . KEYCODE . NINE ) { return true ; }
if ( key _code >= $ . FE . KEYCODE . NUM _ZERO && key _code <= $ . FE . KEYCODE . NUM _MULTIPLY ) { return true ; }
if ( key _code >= $ . FE . KEYCODE . A && key _code <= $ . FE . KEYCODE . Z ) { return true ; }
if ( editor . browser . webkit && key _code === 0 ) { return true ; }
switch ( key _code ) { case $ . FE . KEYCODE . SPACE : case $ . FE . KEYCODE . QUESTION _MARK : case $ . FE . KEYCODE . NUM _PLUS : case $ . FE . KEYCODE . NUM _MINUS : case $ . FE . KEYCODE . NUM _PERIOD : case $ . FE . KEYCODE . NUM _DIVISION : case $ . FE . KEYCODE . SEMICOLON : case $ . FE . KEYCODE . FF _SEMICOLON : case $ . FE . KEYCODE . DASH : case $ . FE . KEYCODE . EQUALS : case $ . FE . KEYCODE . FF _EQUALS : case $ . FE . KEYCODE . COMMA : case $ . FE . KEYCODE . PERIOD : case $ . FE . KEYCODE . SLASH : case $ . FE . KEYCODE . APOSTROPHE : case $ . FE . KEYCODE . SINGLE _QUOTE : case $ . FE . KEYCODE . OPEN _SQUARE _BRACKET : case $ . FE . KEYCODE . BACKSLASH : case $ . FE . KEYCODE . CLOSE _SQUARE _BRACKET : return true ; default : return false ; } }
var _typing _timeout ; var _temp _snapshot ; function _typingKeyDown ( e ) { var keycode = e . which ; if ( ctrlKey ( e ) || ( keycode >= 37 && keycode <= 40 ) || ( ! isCharacter ( keycode ) && keycode != $ . FE . KEYCODE . DELETE && keycode != $ . FE . KEYCODE . BACKSPACE && keycode != $ . FE . KEYCODE . ENTER && keycode != $ . FE . KEYCODE . IME ) ) return true ; if ( ! _typing _timeout ) { _temp _snapshot = editor . snapshot . get ( ) ; if ( ! editor . undo . canDo ( ) ) editor . undo . saveStep ( ) ; }
clearTimeout ( _typing _timeout ) ; _typing _timeout = setTimeout ( function ( ) { _typing _timeout = null ; editor . undo . saveStep ( ) ; } , Math . max ( 250 , editor . opts . typingTimer ) ) ; }
function _typingKeyUp ( e ) { var keycode = e . which ; if ( ctrlKey ( e ) || ( keycode >= 37 && keycode <= 40 ) ) return true ; if ( _temp _snapshot && _typing _timeout ) { editor . undo . saveStep ( _temp _snapshot ) ; _temp _snapshot = null ; }
else { if ( ( typeof keycode === 'undefined' || keycode === 0 ) && ! _temp _snapshot && ! _typing _timeout ) { editor . undo . saveStep ( ) ; } } }
function forceUndo ( ) { if ( _typing _timeout ) { clearTimeout ( _typing _timeout ) ; editor . undo . saveStep ( ) ; _temp _snapshot = null ; } }
function isBrowserAction ( e ) { var keycode = e . which ; return ctrlKey ( e ) || keycode == $ . FE . KEYCODE . F5 ; }
function _isEmpty ( node ) { if ( node && node . tagName == 'BR' ) return false ; try { return ( ( node . textContent || '' ) . length === 0 && node . querySelector && ! node . querySelector ( ':scope > br' ) ) || ( node . childNodes && node . childNodes . length == 1 && node . childNodes [ 0 ] . getAttribute && ( node . childNodes [ 0 ] . getAttribute ( 'contenteditable' ) == 'false' || editor . node . hasClass ( node . childNodes [ 0 ] , 'fr-img-caption' ) ) ) ; }
catch ( ex ) { return false ; } }
function _allowTypingOnEdges ( e ) { var childs = editor . el . childNodes ; var dt = editor . html . defaultTag ( ) ; if ( e . target && e . target !== editor . el ) return true ; if ( childs . length === 0 ) return true ; if ( editor . $el . outerHeight ( ) - e . offsetY <= 10 ) { if ( _isEmpty ( childs [ childs . length - 1 ] ) ) { if ( dt ) { editor . $el . append ( '<' + dt + '>' + $ . FE . MARKERS + '<br></' + dt + '>' ) ; }
else { editor . $el . append ( $ . FE . MARKERS + '<br>' ) ; }
editor . selection . restore ( ) ; positionCaret ( ) ; } }
else if ( e . offsetY <= 10 ) { if ( _isEmpty ( childs [ 0 ] ) ) { if ( dt ) { editor . $el . prepend ( '<' + dt + '>' + $ . FE . MARKERS + '<br></' + dt + '>' ) ; }
else { editor . $el . prepend ( $ . FE . MARKERS + '<br>' ) ; }
editor . selection . restore ( ) ; positionCaret ( ) ; } } }
function _clearTypingTimer ( ) { if ( _typing _timeout ) { clearTimeout ( _typing _timeout ) ; } }
function _init ( ) { editor . events . on ( 'keydown' , _typingKeyDown ) ; editor . events . on ( 'input' , _input ) ; editor . events . on ( 'mousedown' , _clearIME ) ; editor . events . on ( 'keyup input' , _typingKeyUp ) ; editor . events . on ( 'keypress' , _mapKeyPress ) ; editor . events . on ( 'keydown' , _mapKeyDown ) ; editor . events . on ( 'keyup' , _mapKeyUp ) ; editor . events . on ( 'destroy' , _clearTypingTimer ) ; editor . events . on ( 'html.inserted' , _mapKeyUp ) ; editor . events . on ( 'cut' , _cut ) ; if ( editor . opts . multiLine ) { editor . events . on ( 'click' , _allowTypingOnEdges ) ; } }
return { _init : _init , ctrlKey : ctrlKey , isCharacter : isCharacter , isArrow : isArrow , forceUndo : forceUndo , isIME : isIME , isBrowserAction : isBrowserAction , positionCaret : positionCaret } } ; $ . FE . MODULES . accessibility = function ( editor ) { var can _blur = true ; function focusToolbarElement ( $el ) { if ( ! $el || ! $el . length || editor . $el . find ( '[contenteditable="true"]' ) . is ( ':focus' ) ) { return ; }
if ( ! $el . data ( 'blur-event-set' ) && ! $el . parents ( '.fr-popup' ) . length ) { editor . events . $on ( $el , 'blur' , function ( ) { var inst = $el . parents ( '.fr-toolbar, .fr-popup' ) . data ( 'instance' ) || editor ; if ( inst . events . blurActive ( ) && ! editor . core . hasFocus ( ) ) { inst . events . trigger ( 'blur' ) ; }
setTimeout ( function ( ) { inst . events . enableBlur ( ) ; } , 100 ) ; } , true ) ; $el . data ( 'blur-event-set' , true ) ; }
var inst = $el . parents ( '.fr-toolbar, .fr-popup' ) . data ( 'instance' ) || editor ; inst . events . disableBlur ( ) ; $el . focus ( ) ; editor . shared . $f _el = $el ; }
function focusToolbar ( $tb , last ) { var position = last ? 'last' : 'first' ; var $btn = $tb . find ( 'button:visible:not(.fr-disabled), .fr-group span.fr-command:visible' ) [ position ] ( ) ; if ( $btn . length ) { focusToolbarElement ( $btn ) ; return true ; } }
function focusContentElement ( $el ) { if ( $el . is ( 'input, textarea, select' ) ) { saveSelection ( ) ; }
editor . events . disableBlur ( ) ; $el . focus ( ) ; return true ; }
function focusContent ( $content , backward ) { var $first _input = $content . find ( 'input, textarea, button, select' ) . filter ( ':visible' ) . not ( ':disabled' ) . filter ( backward ? ':last' : ':first' ) ; if ( $first _input . length ) { return focusContentElement ( $first _input ) ; }
if ( editor . shared . with _kb ) { var $active _item = $content . find ( '.fr-active-item:visible:first' ) ; if ( $active _item . length ) { return focusContentElement ( $active _item ) ; }
var $first _tab _index = $content . find ( '[tabIndex]:visible:first' )
if ( $first _tab _index . length ) { return focusContentElement ( $first _tab _index ) ; } } }
function saveSelection ( ) { if ( editor . $el . find ( '.fr-marker' ) . length === 0 && editor . core . hasFocus ( ) ) { editor . selection . save ( ) ; } }
function restoreSelection ( ) { if ( editor . $el . find ( '.fr-marker' ) . length ) { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; } }
function focusPopup ( $popup ) { var $popup _content = $popup . children ( ) . not ( '.fr-buttons' ) ; if ( ! $popup _content . data ( 'mouseenter-event-set' ) && ! editor . browser . msie ) { editor . events . $on ( $popup _content , 'mouseenter' , '[tabIndex]' , function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; if ( ! can _blur ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; return ; }
var $focused _item = $popup _content . find ( ':focus:first' ) ; if ( $focused _item . length && ! $focused _item . is ( 'input, button, textarea, select' ) ) { inst . events . disableBlur ( ) ; $focused _item . blur ( ) ; inst . events . disableBlur ( ) ; inst . events . focus ( ) ; } } ) ; $popup _content . data ( 'mouseenter-event-set' , true ) ; }
if ( ! focusContent ( $popup _content ) && editor . shared . with _kb ) { focusToolbar ( $popup . find ( '.fr-buttons' ) ) ; } }
function focusModal ( $modal ) { if ( ! editor . core . hasFocus ( ) ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; }
editor . accessibility . saveSelection ( ) ; editor . events . disableBlur ( ) ; editor . $el . blur ( ) ; editor . selection . clear ( ) ; editor . events . disableBlur ( ) ; if ( editor . shared . with _kb ) { $modal . find ( '.fr-command[tabIndex], [tabIndex]' ) . first ( ) . focus ( ) ; }
else { $modal . find ( '[tabIndex]:first' ) . focus ( ) ; } }
function focusToolbars ( ) { var $popup = editor . popups . areVisible ( ) ; if ( $popup ) { var $tb = $popup . find ( '.fr-buttons' ) ; if ( ! $tb . find ( 'button:focus, .fr-group span:focus' ) . length ) { return ! focusToolbar ( $tb ) ; }
else { return ! focusToolbar ( $popup . data ( 'instance' ) . $tb ) } }
return ! focusToolbar ( editor . $tb ) ; }
function _getActiveFocusedDropdown ( ) { var $activeDropdown = null ; if ( editor . shared . $f _el . is ( '.fr-dropdown.fr-active' ) ) { $activeDropdown = editor . shared . $f _el ; }
else if ( editor . shared . $f _el . closest ( '.fr-dropdown-menu' ) . prev ( ) . is ( '.fr-dropdown.fr-active' ) ) { $activeDropdown = editor . shared . $f _el . closest ( '.fr-dropdown-menu' ) . prev ( ) ; }
return $activeDropdown ; }
function _moveHorizontally ( $tb , tab _key , forward ) { if ( editor . shared . $f _el ) { var $activeDropdown = _getActiveFocusedDropdown ( ) ; if ( $activeDropdown ) { editor . button . click ( $activeDropdown ) ; editor . shared . $f _el = $activeDropdown ; }
var $buttons = $tb . find ( 'button:visible:not(.fr-disabled), .fr-group span.fr-command:visible' ) ; var index = $buttons . index ( editor . shared . $f _el ) ; if ( ( index === 0 && ! forward ) || ( index == $buttons . length - 1 && forward ) ) { var status ; if ( tab _key ) { if ( $tb . parent ( ) . is ( '.fr-popup' ) ) { var $popup _content = $tb . parent ( ) . children ( ) . not ( '.fr-buttons' )
status = ! focusContent ( $popup _content , ! forward ) ; }
if ( status === false ) { editor . shared . $f _el = null ; } }
if ( ! tab _key || status !== false ) { focusToolbar ( $tb , ! forward ) ; } }
else { focusToolbarElement ( $ ( $buttons . get ( index + ( forward ? 1 : - 1 ) ) ) ) ; }
return false ; } }
function moveForward ( $tb , tab _key ) { return _moveHorizontally ( $tb , tab _key , true ) ; }
function moveBackward ( $tb , tab _key ) { return _moveHorizontally ( $tb , tab _key ) ; }
function _moveVertically ( down ) { if ( editor . shared . $f _el ) { var $destination ; if ( editor . shared . $f _el . is ( '.fr-dropdown.fr-active' ) ) { if ( down ) { $destination = editor . shared . $f _el . next ( ) . find ( '.fr-command:not(.fr-disabled)' ) . first ( ) ; }
else { $destination = editor . shared . $f _el . next ( ) . find ( '.fr-command:not(.fr-disabled)' ) . last ( ) ; }
focusToolbarElement ( $destination ) ; return false ; }
else if ( editor . shared . $f _el . is ( 'a.fr-command' ) ) { if ( down ) { $destination = editor . shared . $f _el . closest ( 'li' ) . nextAll ( ':visible:first' ) . find ( '.fr-command:not(.fr-disabled)' ) . first ( ) ; }
else { $destination = editor . shared . $f _el . closest ( 'li' ) . prevAll ( ':visible:first' ) . find ( '.fr-command:not(.fr-disabled)' ) . first ( ) ; }
if ( ! $destination . length ) { if ( down ) { $destination = editor . shared . $f _el . closest ( '.fr-dropdown-menu' ) . find ( '.fr-command:not(.fr-disabled)' ) . first ( ) ; }
else { $destination = editor . shared . $f _el . closest ( '.fr-dropdown-menu' ) . find ( '.fr-command:not(.fr-disabled)' ) . last ( ) ; } }
focusToolbarElement ( $destination ) ; return false ; } } }
function moveDown ( ) { if ( editor . shared . $f _el && editor . shared . $f _el . is ( '.fr-dropdown:not(.fr-active)' ) ) { return enter ( ) ; }
else { return _moveVertically ( true ) ; } }
function moveUp ( ) { return _moveVertically ( ) ; }
function enter ( ) { if ( editor . shared . $f _el ) { if ( editor . shared . $f _el . hasClass ( 'fr-dropdown' ) ) { editor . button . click ( editor . shared . $f _el ) ; }
else if ( editor . shared . $f _el . is ( 'button.fr-back' ) ) { if ( editor . opts . toolbarInline ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; }
var $popup = editor . popups . areVisible ( editor ) ; if ( $popup ) { editor . shared . with _kb = false ; }
editor . button . click ( editor . shared . $f _el ) ; focusPopupButton ( $popup ) ; }
else { editor . events . disableBlur ( ) ; editor . button . click ( editor . shared . $f _el ) ; if ( editor . shared . $f _el . attr ( 'data-popup' ) ) { var $visible _popup = editor . popups . areVisible ( editor ) ; if ( $visible _popup ) $visible _popup . data ( 'popup-button' , editor . shared . $f _el ) ; }
else if ( editor . shared . $f _el . attr ( 'data-modal' ) ) { var $visible _modal = editor . modals . areVisible ( editor ) ; if ( $visible _modal ) $visible _modal . data ( 'modal-button' , editor . shared . $f _el ) ; }
editor . shared . $f _el = null ; }
return false ; } }
function focusEditor ( ) { if ( editor . shared . $f _el ) { editor . events . disableBlur ( ) ; editor . shared . $f _el . blur ( ) ; editor . shared . $f _el = null ; }
if ( editor . events . trigger ( 'toolbar.focusEditor' ) === false ) { return ; }
editor . events . disableBlur ( ) ; if ( ! editor . browser . msie ) editor . $el . focus ( ) ; editor . events . focus ( ) ; }
function esc ( $tb ) { if ( editor . shared . $f _el ) { var $activeDropdown = _getActiveFocusedDropdown ( ) ; if ( $activeDropdown ) { editor . button . click ( $activeDropdown ) ; focusToolbarElement ( $activeDropdown ) ; }
else if ( $tb . parent ( ) . find ( '.fr-back:visible' ) . length ) { editor . shared . with _kb = false ; if ( editor . opts . toolbarInline ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; }
editor . button . exec ( $tb . parent ( ) . find ( '.fr-back:visible:first' ) ) ; focusPopupButton ( $tb . parent ( ) ) ; }
else if ( editor . shared . $f _el . is ( 'button, .fr-group span' ) ) { if ( $tb . parent ( ) . is ( '.fr-popup' ) ) { editor . accessibility . restoreSelection ( ) ; editor . shared . $f _el = null ; if ( editor . events . trigger ( 'toolbar.esc' ) !== false ) { editor . popups . hide ( $tb . parent ( ) ) ; if ( editor . opts . toolbarInline ) editor . toolbar . showInline ( null , true ) ; focusPopupButton ( $tb . parent ( ) ) ; } }
else { focusEditor ( ) ; } }
return false ; } }
function exec ( e , $tb ) { var ctrlKey = navigator . userAgent . indexOf ( 'Mac OS X' ) != - 1 ? e . metaKey : e . ctrlKey ; var keycode = e . which ; var status = false ; if ( keycode == $ . FE . KEYCODE . TAB && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = moveForward ( $tb , true ) ; }
else if ( keycode == $ . FE . KEYCODE . ARROW _RIGHT && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = moveForward ( $tb ) ; }
else if ( keycode == $ . FE . KEYCODE . TAB && ! ctrlKey && e . shiftKey && ! e . altKey ) { status = moveBackward ( $tb , true ) ; }
else if ( keycode == $ . FE . KEYCODE . ARROW _LEFT && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = moveBackward ( $tb ) ; }
else if ( keycode == $ . FE . KEYCODE . ARROW _UP && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = moveUp ( ) ; }
else if ( keycode == $ . FE . KEYCODE . ARROW _DOWN && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = moveDown ( ) ; }
else if ( ( keycode == $ . FE . KEYCODE . ENTER || keycode == $ . FE . KEYCODE . SPACE ) && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = enter ( ) ; }
else if ( keycode == $ . FE . KEYCODE . ESC && ! ctrlKey && ! e . shiftKey && ! e . altKey ) { status = esc ( $tb ) ; }
else if ( keycode == $ . FE . KEYCODE . F10 && ! ctrlKey && ! e . shiftKey && e . altKey ) { status = focusToolbars ( ) ; }
if ( ! editor . shared . $f _el && status === undefined ) { status = true ; }
if ( ! status && editor . keys . isBrowserAction ( e ) ) { status = true ; }
if ( status ) { return true ; }
else { e . preventDefault ( ) ; e . stopPropagation ( ) ; return false ; } }
function registerToolbar ( $tb ) { if ( ! $tb || ! $tb . length ) { return ; }
editor . events . $on ( $tb , 'keydown' , function ( e ) { if ( ! $ ( e . target ) . is ( 'a.fr-command, button.fr-command, .fr-group span.fr-command' ) ) { return true ; }
var inst = $tb . parents ( '.fr-popup' ) . data ( 'instance' ) || $tb . data ( 'instance' ) || editor ; editor . shared . with _kb = true ; var status = inst . accessibility . exec ( e , $tb ) ; editor . shared . with _kb = false ; return status ; } , true ) ; if ( ! editor . browser . msie ) { editor . events . $on ( $tb , 'mouseenter' , '[tabIndex]' , function ( e ) { var inst = $tb . parents ( '.fr-popup' ) . data ( 'instance' ) || $tb . data ( 'instance' ) || editor ; if ( ! can _blur ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; return ; }
else { var $hovered _el = $ ( e . currentTarget ) ; if ( inst . shared . $f _el && inst . shared . $f _el . not ( $hovered _el ) ) { inst . accessibility . focusEditor ( ) ; } } } , true ) ; } }
function registerPopup ( id ) { var $popup = editor . popups . get ( id ) ; var ev = _getPopupEvents ( id ) ; registerToolbar ( $popup . find ( '.fr-buttons' ) ) ; editor . events . $on ( $popup , 'mouseenter' , 'tabIndex' , ev . _tiMouseenter , true ) ; editor . events . $on ( $popup . children ( ) . not ( '.fr-buttons' ) , 'keydown' , '[tabIndex]' , ev . _tiKeydown , true ) ; editor . popups . onHide ( id , function ( ) { var inst = $popup . data ( 'instance' ) || editor ; inst . accessibility . restoreSelection ( ) ; } )
editor . popups . onShow ( id , function ( ) { can _blur = false ; setTimeout ( function ( ) { can _blur = true ; } , 0 ) ; } ) ; }
function _getPopupEvents ( id ) { var $popup = editor . popups . get ( id ) ; return { _tiKeydown : function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; if ( inst . events . trigger ( 'popup.tab' , [ e ] ) === false ) { return false ; }
var key _code = e . which ; var $focused _item = $popup . find ( ':focus:first' ) ; if ( $ . FE . KEYCODE . TAB == key _code ) { e . preventDefault ( ) ; var $popup _content = $popup . children ( ) . not ( '.fr-buttons' ) ; var inputs = $popup _content . find ( 'input, textarea, button, select' ) . filter ( ':visible' ) . not ( '.fr-no-touch input, .fr-no-touch textarea, .fr-no-touch button, .fr-no-touch select, :disabled' ) . toArray ( ) ; var idx = inputs . indexOf ( this ) + ( e . shiftKey ? - 1 : 1 ) ; if ( 0 <= idx && idx < inputs . length ) { inst . events . disableBlur ( ) ; $ ( inputs [ idx ] ) . focus ( ) ; e . stopPropagation ( ) ; return false ; }
var $tb = $popup . find ( '.fr-buttons' ) ; if ( $tb . length && focusToolbar ( $tb , ( e . shiftKey ? true : false ) ) ) { e . stopPropagation ( ) ; return false ; }
if ( focusContent ( $popup _content ) ) { e . stopPropagation ( ) ; return false ; } }
else if ( $ . FE . KEYCODE . ENTER == key _code && e . target && e . target . tagName !== 'TEXTAREA' ) { var $active _button = null ; if ( $popup . find ( '.fr-submit:visible' ) . length > 0 ) { $active _button = $popup . find ( '.fr-submit:visible:first' ) ; }
else if ( $popup . find ( '.fr-dismiss:visible' ) . length ) { $active _button = $popup . find ( '.fr-dismiss:visible:first' ) ; }
if ( $active _button ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; inst . events . disableBlur ( ) ; inst . button . exec ( $active _button ) ; } }
else if ( $ . FE . KEYCODE . ESC == key _code ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; inst . accessibility . restoreSelection ( ) ; if ( inst . popups . isVisible ( id ) && $popup . find ( '.fr-back:visible' ) . length ) { if ( inst . opts . toolbarInline ) { inst . events . disableBlur ( ) ; inst . events . focus ( ) ; }
inst . button . exec ( $popup . find ( '.fr-back:visible:first' ) ) ; focusPopupButton ( $popup ) ; }
else if ( inst . popups . isVisible ( id ) && $popup . find ( '.fr-dismiss:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-dismiss:visible:first' ) ) ; }
else { inst . popups . hide ( id ) ; if ( inst . opts . toolbarInline ) inst . toolbar . showInline ( null , true ) ; focusPopupButton ( $popup ) ; }
return false ; }
else if ( $ . FE . KEYCODE . SPACE == key _code && ( $focused _item . is ( '.fr-submit' ) || $focused _item . is ( '.fr-dismiss' ) ) ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; inst . events . disableBlur ( ) ; inst . button . exec ( $focused _item ) ; return true ; }
else { if ( inst . keys . isBrowserAction ( e ) ) { e . stopPropagation ( ) ; return ; }
if ( $focused _item . is ( 'input[type=text], textarea' ) ) { e . stopPropagation ( ) ; return ; }
if ( $ . FE . KEYCODE . SPACE == key _code && ( $focused _item . is ( '.fr-link-attr' ) || $focused _item . is ( 'input[type=file]' ) ) ) { e . stopPropagation ( ) ; return ; }
e . stopPropagation ( ) ; e . preventDefault ( ) ; return false ; } } , _tiMouseenter : function ( ) { var inst = $popup . data ( 'instance' ) || editor ; _clearPopupButton ( inst ) ; } } }
function focusPopupButton ( $popup ) { var $popup _button = $popup . data ( 'popup-button' ) ; if ( $popup _button ) { setTimeout ( function ( ) { focusToolbarElement ( $popup _button ) ; $popup . data ( 'popup-button' , null ) ; } , 0 ) ; } }
function focusModalButton ( $modal ) { var $modal _button = $modal . data ( 'modal-button' ) ; if ( $modal _button ) { setTimeout ( function ( ) { focusToolbarElement ( $modal _button ) ; $modal . data ( 'modal-button' , null ) ; } , 0 ) ; } }
function hasFocus ( ) { return editor . shared . $f _el != null ; }
function _clearPopupButton ( inst ) { var $visible _popup = editor . popups . areVisible ( inst ) ; if ( $visible _popup ) { $visible _popup . data ( 'popup-button' , null ) ; } }
function _editorKeydownHandler ( e ) { var ctrlKey = navigator . userAgent . indexOf ( 'Mac OS X' ) != - 1 ? e . metaKey : e . ctrlKey ; var keycode = e . which ; if ( keycode == $ . FE . KEYCODE . F10 && ! ctrlKey && ! e . shiftKey && e . altKey ) { editor . shared . with _kb = true ; var $visible _popup = editor . popups . areVisible ( editor ) ; var focused _content = false ; if ( $visible _popup ) { focused _content = focusContent ( $visible _popup . children ( ) . not ( '.fr-buttons' ) ) ; }
if ( ! focused _content ) { focusToolbars ( ) ; }
editor . shared . with _kb = false ; e . preventDefault ( ) ; e . stopPropagation ( ) ; return false ; }
return true ; }
function _init ( ) { if ( editor . $wp ) { editor . events . on ( 'keydown' , _editorKeydownHandler , true ) ; }
else { editor . events . $on ( editor . $win , 'keydown' , _editorKeydownHandler , true ) ; }
editor . events . on ( 'mousedown' , function ( e ) { _clearPopupButton ( editor ) ; if ( editor . shared . $f _el ) { editor . accessibility . restoreSelection ( ) ; e . stopPropagation ( ) ; editor . events . disableBlur ( ) ; editor . shared . $f _el = null ; } } , true ) ; editor . events . on ( 'blur' , function ( ) { editor . shared . $f _el = null ; _clearPopupButton ( editor ) ; } , true ) ; }
return { _init : _init , registerPopup : registerPopup , registerToolbar : registerToolbar , focusToolbarElement : focusToolbarElement , focusToolbar : focusToolbar , focusContent : focusContent , focusPopup : focusPopup , focusModal : focusModal , focusEditor : focusEditor , focusPopupButton : focusPopupButton , focusModalButton : focusModalButton , hasFocus : hasFocus , exec : exec , saveSelection : saveSelection , restoreSelection : restoreSelection } }
$ . FE . MODULES . format = function ( editor ) { function _openTag ( tag , attrs ) { var str = '<' + tag ; for ( var key in attrs ) { if ( attrs . hasOwnProperty ( key ) ) { str += ' ' + key + '="' + attrs [ key ] + '"' ; } }
str += '>' ; return str ; }
function _closeTag ( tag ) { return '</' + tag + '>' ; }
function _query ( tag , attrs ) { var selector = tag ; for ( var key in attrs ) { if ( attrs . hasOwnProperty ( key ) ) { if ( key == 'id' ) selector += '#' + attrs [ key ] ; else if ( key == 'class' ) selector += '.' + attrs [ key ] ; else selector += '[' + key + '="' + attrs [ key ] + '"]' ; } }
return selector ; }
function _matches ( el , selector ) { if ( ! el || el . nodeType != Node . ELEMENT _NODE ) return false ; return ( el . matches || el . matchesSelector || el . msMatchesSelector || el . mozMatchesSelector || el . webkitMatchesSelector || el . oMatchesSelector ) . call ( el , selector ) ; }
function _processNodeFormat ( start _node , tag , attrs ) { if ( ! start _node ) return ; while ( start _node . nodeType === Node . COMMENT _NODE ) { start _node = start _node . nextSibling ; }
if ( ! start _node ) return ; if ( editor . node . isBlock ( start _node ) && start _node . tagName !== 'HR' ) { _processNodeFormat ( start _node . firstChild , tag , attrs ) ; return false ; }
var $span = $ ( _openTag ( tag , attrs ) ) . insertBefore ( start _node ) ; var node = start _node ; while ( node && ! $ ( node ) . is ( '.fr-marker' ) && $ ( node ) . find ( '.fr-marker' ) . length === 0 && node . tagName != 'UL' && node . tagName != 'OL' ) { var tmp = node ; if ( editor . node . isBlock ( node ) && start _node . tagName !== 'HR' ) { _processNodeFormat ( node . firstChild , tag , attrs ) ; return false ; }
node = node . nextSibling ; $span . append ( tmp ) ; }
if ( ! node ) { var p _node = $span . get ( 0 ) . parentNode ; while ( p _node && ! p _node . nextSibling && ! editor . node . isElement ( p _node ) ) { p _node = p _node . parentNode ; }
if ( p _node ) { var sibling = p _node . nextSibling ; if ( sibling ) { if ( ! editor . node . isBlock ( sibling ) ) { _processNodeFormat ( sibling , tag , attrs ) ; }
else if ( sibling . tagName === 'HR' ) { _processNodeFormat ( sibling . nextSibling , tag , attrs ) ; }
else { _processNodeFormat ( sibling . firstChild , tag , attrs ) ; } } } }
else if ( $ ( node ) . find ( '.fr-marker' ) . length || node . tagName == 'UL' || node . tagName == 'OL' ) { _processNodeFormat ( node . firstChild , tag , attrs ) ; }
if ( $span . is ( ':empty' ) ) { $span . remove ( ) ; } }
function apply ( tag , attrs ) { var i ; if ( typeof attrs == 'undefined' ) attrs = { } ; if ( attrs . style ) { delete attrs . style ; }
if ( editor . selection . isCollapsed ( ) ) { editor . markers . insert ( ) ; var $marker = editor . $el . find ( '.fr-marker' ) ; $marker . replaceWith ( _openTag ( tag , attrs ) + $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS + _closeTag ( tag ) ) ; editor . selection . restore ( ) ; }
else { editor . selection . save ( ) ; var start _marker = editor . $el . find ( '.fr-marker[data-type="true"]' ) . get ( 0 ) . nextSibling ; _processNodeFormat ( start _marker , tag , attrs ) ; var inner _spans ; do { inner _spans = editor . $el . find ( _query ( tag , attrs ) + ' > ' + _query ( tag , attrs ) ) ; for ( i = 0 ; i < inner _spans . length ; i ++ ) { inner _spans [ i ] . outerHTML = inner _spans [ i ] . innerHTML ; } } while ( inner _spans . length ) ; editor . el . normalize ( ) ; var markers = editor . el . querySelectorAll ( '.fr-marker' ) ; for ( i = 0 ; i < markers . length ; i ++ ) { var $mk = $ ( markers [ i ] ) ; if ( $mk . data ( 'type' ) === true ) { if ( _matches ( $mk . get ( 0 ) . nextSibling , _query ( tag , attrs ) ) ) { $mk . next ( ) . prepend ( $mk ) ; } }
else { if ( _matches ( $mk . get ( 0 ) . previousSibling , _query ( tag , attrs ) ) ) { $mk . prev ( ) . append ( $mk ) ; } } }
editor . selection . restore ( ) ; } }
function _split ( $node , tag , attrs , collapsed ) { if ( ! collapsed ) { var changed = false ; if ( $node . data ( 'type' ) === true ) { while ( editor . node . isFirstSibling ( $node . get ( 0 ) ) && ! $node . parent ( ) . is ( editor . $el ) && ! $node . parent ( ) . is ( 'ol' ) && ! $node . parent ( ) . is ( 'ul' ) ) { $node . parent ( ) . before ( $node ) ; changed = true ; } }
else if ( $node . data ( 'type' ) === false ) { while ( editor . node . isLastSibling ( $node . get ( 0 ) ) && ! $node . parent ( ) . is ( editor . $el ) && ! $node . parent ( ) . is ( 'ol' ) && ! $node . parent ( ) . is ( 'ul' ) ) { $node . parent ( ) . after ( $node ) ; changed = true ; } }
if ( changed ) return true ; }
if ( $node . parents ( tag ) . length || typeof tag == 'undefined' ) { var close _str = '' ; var open _str = '' ; var $p _node = $node . parent ( ) ; if ( $p _node . is ( editor . $el ) || editor . node . isBlock ( $p _node . get ( 0 ) ) ) return false ; while ( ! editor . node . isBlock ( $p _node . parent ( ) . get ( 0 ) ) && ( ( typeof tag == 'undefined' ) || ( typeof tag != 'undefined' && ! _matches ( $p _node . get ( 0 ) , _query ( tag , attrs ) ) ) ) ) { close _str = close _str + editor . node . closeTagString ( $p _node . get ( 0 ) ) ; open _str = editor . node . openTagString ( $p _node . get ( 0 ) ) + open _str ; $p _node = $p _node . parent ( ) ; }
var node _str = $node . get ( 0 ) . outerHTML ; $node . replaceWith ( '<span id="mark"></span>' ) ; var p _html = $p _node . html ( ) . replace ( /<span id="mark"><\/span>/ , close _str + editor . node . closeTagString ( $p _node . get ( 0 ) ) + open _str + node _str + close _str + editor . node . openTagString ( $p _node . get ( 0 ) ) + open _str ) ; $p _node . replaceWith ( editor . node . openTagString ( $p _node . get ( 0 ) ) + p _html + editor . node . closeTagString ( $p _node . get ( 0 ) ) ) ; return true ; }
return false ; }
function _processNodeRemove ( $node , should _remove , tag , attrs ) { var contents = editor . node . contents ( $node . get ( 0 ) ) ; for ( var i = 0 ; i < contents . length ; i ++ ) { var node = contents [ i ] ; if ( editor . node . hasClass ( node , 'fr-marker' ) ) { should _remove = ( should _remove + 1 ) % 2 ; }
else if ( should _remove ) { if ( $ ( node ) . find ( '.fr-marker' ) . length > 0 ) { should _remove = _processNodeRemove ( $ ( node ) , should _remove , tag , attrs ) ; }
else { var nodes = $ ( node ) . find ( tag || '*:not(br)' ) ; for ( var j = nodes . length - 1 ; j >= 0 ; j -- ) { var nd = nodes [ j ] ; console . log ( nd )
if ( ! editor . node . isBlock ( nd ) && ! editor . node . isVoid ( nd ) && ( typeof tag == 'undefined' || _matches ( nd , _query ( tag , attrs ) ) ) ) { if ( ! editor . node . hasClass ( nd , 'fr-clone' ) ) { nd . outerHTML = nd . innerHTML ; } }
else if ( editor . node . isBlock ( nd ) && ( typeof tag == 'undefined' ) && node . tagName != 'TABLE' ) { editor . node . clearAttributes ( nd ) ; } }
if ( ( typeof tag == 'undefined' && node . nodeType == Node . ELEMENT _NODE && ! editor . node . isVoid ( node ) ) || _matches ( node , _query ( tag , attrs ) ) ) { if ( ! editor . node . isBlock ( node ) ) { if ( ! editor . node . hasClass ( node , 'fr-clone' ) ) { node . outerHTML = node . innerHTML ; } }
else if ( typeof tag == 'undefined' && node . nodeType == Node . ELEMENT _NODE && editor . node . isBlock ( node ) && node . tagName != 'TABLE' ) { editor . node . clearAttributes ( node ) ; } }
else if ( typeof tag == 'undefined' && node . nodeType == Node . ELEMENT _NODE && editor . node . isBlock ( node ) && node . tagName != 'TABLE' ) { editor . node . clearAttributes ( node ) ; } } }
else { if ( $ ( node ) . find ( '.fr-marker' ) . length > 0 ) { should _remove = _processNodeRemove ( $ ( node ) , should _remove , tag , attrs ) ; } } }
return should _remove ; }
function remove ( tag , attrs ) { if ( typeof attrs == 'undefined' ) attrs = { } ; if ( attrs . style ) { delete attrs . style ; }
var collapsed = editor . selection . isCollapsed ( ) ; editor . selection . save ( ) ; var reassess = true ; while ( reassess ) { reassess = false ; var markers = editor . $el . find ( '.fr-marker' ) ; for ( var i = 0 ; i < markers . length ; i ++ ) { var $marker = $ ( markers [ i ] ) ; var $clone = null ; if ( ! $marker . attr ( 'data-cloned' ) && ! collapsed ) { $clone = $marker . clone ( ) . removeClass ( 'fr-marker' ) . addClass ( 'fr-clone' ) ; if ( $marker . data ( 'type' ) === true ) { $marker . attr ( 'data-cloned' , true ) . after ( $clone ) ; }
else { $marker . attr ( 'data-cloned' , true ) . before ( $clone ) ; } }
if ( _split ( $marker , tag , attrs , collapsed ) ) { reassess = true ; break ; } } }
_processNodeRemove ( editor . $el , 0 , tag , attrs ) ; if ( ! collapsed ) { editor . $el . find ( '.fr-marker' ) . remove ( ) ; editor . $el . find ( '.fr-clone' ) . removeClass ( 'fr-clone' ) . addClass ( 'fr-marker' ) ; }
if ( collapsed ) { editor . $el . find ( '.fr-marker' ) . before ( $ . FE . INVISIBLE _SPACE ) . after ( $ . FE . INVISIBLE _SPACE ) ; }
editor . html . cleanEmptyTags ( ) ; editor . el . normalize ( ) ; editor . selection . restore ( ) ; }
function toggle ( tag , attrs ) { if ( is ( tag , attrs ) ) { remove ( tag , attrs ) ; }
else { apply ( tag , attrs ) ; } }
function _cleanFormat ( elem , prop ) { var $elem = $ ( elem ) ; $elem . css ( prop , '' ) ; if ( $elem . attr ( 'style' ) === '' ) { $elem . replaceWith ( $elem . html ( ) ) ; } }
function _filterSpans ( elem , prop ) { return $ ( elem ) . attr ( 'style' ) . indexOf ( prop + ':' ) === 0 || $ ( elem ) . attr ( 'style' ) . indexOf ( ';' + prop + ':' ) >= 0 || $ ( elem ) . attr ( 'style' ) . indexOf ( '; ' + prop + ':' ) >= 0 ; }
function applyStyle ( prop , val ) { var i ; var $marker ; var $span = null ; if ( editor . selection . isCollapsed ( ) ) { editor . markers . insert ( ) ; $marker = editor . $el . find ( '.fr-marker' ) ; var $parent = $marker . parent ( ) ; if ( editor . node . openTagString ( $parent . get ( 0 ) ) == '<span style="' + prop + ': ' + $parent . css ( prop ) + ';">' ) { if ( editor . node . isEmpty ( $parent . get ( 0 ) ) ) { $span = $ ( '<span style="' + prop + ': ' + val + ';">' + $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS + '</span>' ) ; $parent . replaceWith ( $span ) ; }
else { var x = { } ; x [ 'style*' ] = prop + ':' ; _split ( $marker , 'span' , x , true ) ; $marker = editor . $el . find ( '.fr-marker' ) ; if ( val ) { $span = $ ( '<span style="' + prop + ': ' + val + ';">' + $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS + '</span>' ) ; $marker . replaceWith ( $span ) ; }
else { $marker . replaceWith ( $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS ) ; } }
editor . html . cleanEmptyTags ( ) ; }
else if ( editor . node . isEmpty ( $parent . get ( 0 ) ) && $parent . is ( 'span' ) ) { $marker . replaceWith ( $ . FE . MARKERS ) ; $parent . css ( prop , val ) ; }
else { $span = $ ( '<span style="' + prop + ': ' + val + ';">' + $ . FE . INVISIBLE _SPACE + $ . FE . MARKERS + '</span>' ) ; $marker . replaceWith ( $span ) ; }
if ( $span ) { _splitParents ( $span , prop , val ) ; } }
else { editor . selection . save ( ) ; if ( val == null || ( prop == 'color' && editor . $el . find ( '.fr-marker' ) . parents ( 'u, a' ) . length > 0 ) ) { var markers = editor . $el . find ( '.fr-marker' ) ; for ( i = 0 ; i < markers . length ; i ++ ) { $marker = $ ( markers [ i ] ) ; if ( $marker . data ( 'type' ) === true ) { while ( editor . node . isFirstSibling ( $marker . get ( 0 ) ) && ! $marker . parent ( ) . is ( editor . $el ) && ! editor . node . isElement ( $marker . parent ( ) . get ( 0 ) ) && ! editor . node . isBlock ( $marker . parent ( ) . get ( 0 ) ) ) { $marker . parent ( ) . before ( $marker ) ; } }
else { while ( editor . node . isLastSibling ( $marker . get ( 0 ) ) && ! $marker . parent ( ) . is ( editor . $el ) && ! editor . node . isElement ( $marker . parent ( ) . get ( 0 ) ) && ! editor . node . isBlock ( $marker . parent ( ) . get ( 0 ) ) ) { $marker . parent ( ) . after ( $marker ) ; } } } }
var start _marker = editor . $el . find ( '.fr-marker[data-type="true"]' ) . get ( 0 ) . nextSibling ; var attrs = { 'class' : 'fr-unprocessed' } ; if ( val ) attrs . style = prop + ': ' + val + ';'
_processNodeFormat ( start _marker , 'span' , attrs ) ; editor . $el . find ( '.fr-marker + .fr-unprocessed' ) . each ( function ( ) { $ ( this ) . prepend ( $ ( this ) . prev ( ) ) ; } ) ; editor . $el . find ( '.fr-unprocessed + .fr-marker' ) . each ( function ( ) { $ ( this ) . prev ( ) . append ( this ) ; } ) ; if ( ( val || '' ) . match ( /\dem$/ ) ) { editor . $el . find ( 'span.fr-unprocessed' ) . removeClass ( 'fr-unprocessed' ) ; }
while ( editor . $el . find ( 'span.fr-unprocessed' ) . length > 0 ) { $span = editor . $el . find ( 'span.fr-unprocessed:first' ) . removeClass ( 'fr-unprocessed' ) ; $span . parent ( ) . get ( 0 ) . normalize ( ) ; if ( $span . parent ( ) . is ( 'span' ) && $span . parent ( ) . get ( 0 ) . childNodes . length == 1 ) { $span . parent ( ) . css ( prop , val ) ; var $child = $span ; $span = $span . parent ( ) ; $child . replaceWith ( $child . html ( ) ) ; }
var inner _spans = $span . find ( 'span' ) ; for ( i = inner _spans . length - 1 ; i >= 0 ; i -- ) { _cleanFormat ( inner _spans [ i ] , prop ) ; }
_splitParents ( $span , prop , val ) ; } }
_normalize ( ) ; }
function _splitParents ( $span , prop , val ) { var i ; var $outer _span = $span . parentsUntil ( editor . $el , 'span[style]' ) ; var to _remove = [ ] ; for ( i = $outer _span . length - 1 ; i >= 0 ; i -- ) { if ( ! _filterSpans ( $outer _span [ i ] , prop ) ) { to _remove . push ( $outer _span [ i ] ) ; } }
$outer _span = $outer _span . not ( to _remove ) ; if ( $outer _span . length ) { var c _str = '' ; var o _str = '' ; var ic _str = '' ; var io _str = '' ; var c _node = $span . get ( 0 ) ; do { c _node = c _node . parentNode ; $ ( c _node ) . addClass ( 'fr-split' ) ; c _str = c _str + editor . node . closeTagString ( c _node ) ; o _str = editor . node . openTagString ( $ ( c _node ) . clone ( ) . addClass ( 'fr-split' ) . get ( 0 ) ) + o _str ; if ( $outer _span . get ( 0 ) != c _node ) { ic _str = ic _str + editor . node . closeTagString ( c _node ) ; io _str = editor . node . openTagString ( $ ( c _node ) . clone ( ) . addClass ( 'fr-split' ) . get ( 0 ) ) + io _str ; } } while ( $outer _span . get ( 0 ) != c _node ) ; var str = c _str + editor . node . openTagString ( $ ( $outer _span . get ( 0 ) ) . clone ( ) . css ( prop , val || '' ) . get ( 0 ) ) + io _str + $span . css ( prop , '' ) . get ( 0 ) . outerHTML + ic _str + '</span>' + o _str ; $span . replaceWith ( '<span id="fr-break"></span>' ) ; var html = $outer _span . get ( 0 ) . outerHTML ; $ ( $outer _span . get ( 0 ) ) . replaceWith ( html . replace ( /<span id="fr-break"><\/span>/g , str ) ) ; } }
function _normalize ( ) { var i ; while ( editor . $el . find ( '.fr-split:empty' ) . length > 0 ) { editor . $el . find ( '.fr-split:empty' ) . remove ( ) ; }
editor . $el . find ( '.fr-split' ) . removeClass ( 'fr-split' ) ; editor . $el . find ( '[style=""]' ) . removeAttr ( 'style' ) ; editor . $el . find ( '[class=""]' ) . removeAttr ( 'class' ) ; editor . html . cleanEmptyTags ( ) ; $ ( editor . $el . find ( 'span' ) . get ( ) . reverse ( ) ) . each ( function ( ) { if ( ! this . attributes || this . attributes . length === 0 ) { $ ( this ) . replaceWith ( this . innerHTML ) ; } } ) ; editor . el . normalize ( ) ; var just _spans = editor . $el . find ( 'span[style] + span[style]' ) ; for ( i = 0 ; i < just _spans . length ; i ++ ) { var $x = $ ( just _spans [ i ] ) ; var $p = $ ( just _spans [ i ] ) . prev ( ) ; if ( $x . get ( 0 ) . previousSibling == $p . get ( 0 ) && editor . node . openTagString ( $x . get ( 0 ) ) == editor . node . openTagString ( $p . get ( 0 ) ) ) { $x . prepend ( $p . html ( ) ) ; $p . remove ( ) ; } }
editor . $el . find ( 'span[style] span[style]' ) . each ( function ( ) { if ( $ ( this ) . attr ( 'style' ) . indexOf ( 'font-size' ) >= 0 ) { var $parent = $ ( this ) . parents ( 'span[style]' ) ; if ( $parent . attr ( 'style' ) . indexOf ( 'background-color' ) >= 0 ) { $ ( this ) . attr ( 'style' , $ ( this ) . attr ( 'style' ) + ';' + $parent . attr ( 'style' ) ) ; _split ( $ ( this ) , 'span[style]' , { } , false ) ; } } } ) ; editor . el . normalize ( ) ; editor . selection . restore ( ) ; }
function removeStyle ( prop ) { applyStyle ( prop , null ) ; }
function is ( tag , attrs ) { if ( typeof attrs == 'undefined' ) attrs = { } ; if ( attrs . style ) { delete attrs . style ; }
var range = editor . selection . ranges ( 0 ) ; var el = range . startContainer ; if ( el . nodeType == Node . ELEMENT _NODE ) { if ( el . childNodes . length > 0 && el . childNodes [ range . startOffset ] ) { el = el . childNodes [ range . startOffset ] ; } }
if ( ! range . collapsed && el . nodeType == Node . TEXT _NODE && range . startOffset == ( el . textContent || '' ) . length ) { while ( ! editor . node . isBlock ( el . parentNode ) && ! el . nextSibling ) { el = el . parentNode ; }
if ( el . nextSibling ) { el = el . nextSibling ; } }
var f _child = el ; while ( f _child && f _child . nodeType == Node . ELEMENT _NODE && ! _matches ( f _child , _query ( tag , attrs ) ) ) { f _child = f _child . firstChild ; }
if ( f _child && f _child . nodeType == Node . ELEMENT _NODE && _matches ( f _child , _query ( tag , attrs ) ) ) return true ; var p _node = el ; if ( p _node && p _node . nodeType != Node . ELEMENT _NODE ) p _node = p _node . parentNode ; while ( p _node && p _node . nodeType == Node . ELEMENT _NODE && p _node != editor . el && ! _matches ( p _node , _query ( tag , attrs ) ) ) { p _node = p _node . parentNode ; }
if ( p _node && p _node . nodeType == Node . ELEMENT _NODE && p _node != editor . el && _matches ( p _node , _query ( tag , attrs ) ) ) return true ; return false ; }
return { is : is , toggle : toggle , apply : apply , remove : remove , applyStyle : applyStyle , removeStyle : removeStyle } }
$ . extend ( $ . FE . DEFAULTS , { indentMargin : 20 } ) ; $ . FE . COMMANDS = { bold : { title : 'Bold' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 'strong' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , italic : { title : 'Italic' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 'em' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , underline : { title : 'Underline' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 'u' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , strikeThrough : { title : 'Strikethrough' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 's' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , subscript : { title : 'Subscript' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 'sub' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , superscript : { title : 'Superscript' , toggle : true , refresh : function ( $btn ) { var format = this . format . is ( 'sup' ) ; $btn . toggleClass ( 'fr-active' , format ) . attr ( 'aria-pressed' , format ) ; } } , outdent : { title : 'Decrease Indent' } , indent : { title : 'Increase Indent' } , undo : { title : 'Undo' , undo : false , forcedRefresh : true , disabled : true } , redo : { title : 'Redo' , undo : false , forcedRefresh : true , disabled : true } , insertHR : { title : 'Insert Horizontal Line' } , clearFormatting : { title : 'Clear Formatting' } , selectAll : { title : 'Select All' , undo : false } } ; $ . FE . RegisterCommand = function ( name , info ) { $ . FE . COMMANDS [ name ] = info ; }
$ . FE . MODULES . commands = function ( editor ) { function _createDefaultTag ( empty ) { if ( editor . html . defaultTag ( ) ) { empty = '<' + editor . html . defaultTag ( ) + '>' + empty + '</' + editor . html . defaultTag ( ) + '>' ; }
return empty ; }
var mapping = { bold : function ( ) { _execCommand ( 'bold' , 'strong' ) ; } , subscript : function ( ) { if ( editor . format . is ( 'sup' ) ) { editor . format . remove ( 'sup' ) ; }
_execCommand ( 'subscript' , 'sub' ) ; } , superscript : function ( ) { if ( editor . format . is ( 'sub' ) ) { editor . format . remove ( 'sub' ) ; }
_execCommand ( 'superscript' , 'sup' ) ; } , italic : function ( ) { _execCommand ( 'italic' , 'em' ) ; } , strikeThrough : function ( ) { _execCommand ( 'strikeThrough' , 's' ) ; } , underline : function ( ) { _execCommand ( 'underline' , 'u' ) ; } , undo : function ( ) { editor . undo . run ( ) ; } , redo : function ( ) { editor . undo . redo ( ) ; } , indent : function ( ) { _processIndent ( 1 ) ; } , outdent : function ( ) { _processIndent ( - 1 ) ; } , show : function ( ) { if ( editor . opts . toolbarInline ) { editor . toolbar . showInline ( null , true ) ; } } , insertHR : function ( ) { editor . selection . remove ( ) ; var empty = '' ; if ( editor . core . isEmpty ( ) ) { empty = '<br>' ; empty = _createDefaultTag ( empty ) ; }
editor . html . insert ( '<hr id="fr-just">' + empty ) ; var $hr = editor . $el . find ( 'hr#fr-just' ) ; $hr . removeAttr ( 'id' ) ; var check ; if ( $hr . next ( ) . length === 0 ) { var default _tag = editor . html . defaultTag ( ) ; if ( default _tag ) { $hr . after ( $ ( '<' + default _tag + '>' ) . append ( '<br>' ) ) ; }
else { $hr . after ( '<br>' ) ; } }
if ( $hr . prev ( ) . is ( 'hr' ) ) { check = editor . selection . setAfter ( $hr . get ( 0 ) , false ) ; }
else if ( $hr . next ( ) . is ( 'hr' ) ) { check = editor . selection . setBefore ( $hr . get ( 0 ) , false ) ; }
else { editor . selection . setAfter ( $hr . get ( 0 ) , false ) || editor . selection . setBefore ( $hr . get ( 0 ) , false ) ; }
if ( ! check && typeof check !== 'undefined' ) { empty = $ . FE . MARKERS + '<br>' ; empty = _createDefaultTag ( empty ) ; $hr . after ( empty ) ; }
editor . selection . restore ( ) ; } , clearFormatting : function ( ) { editor . format . remove ( ) ; } , selectAll : function ( ) { editor . doc . execCommand ( 'selectAll' , false , false ) ; } }
function exec ( cmd , params ) { if ( editor . events . trigger ( 'commands.before' , $ . merge ( [ cmd ] , params || [ ] ) ) !== false ) { var callback = ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . callback ) || mapping [ cmd ] ; var focus = true ; var accessibilityFocus = false ; if ( $ . FE . COMMANDS [ cmd ] ) { if ( typeof $ . FE . COMMANDS [ cmd ] . focus != 'undefined' ) { focus = $ . FE . COMMANDS [ cmd ] . focus ; }
if ( typeof $ . FE . COMMANDS [ cmd ] . accessibilityFocus != 'undefined' ) { accessibilityFocus = $ . FE . COMMANDS [ cmd ] . accessibilityFocus ; } }
if ( ( ! editor . core . hasFocus ( ) && focus && ! editor . popups . areVisible ( ) ) || ( ! editor . core . hasFocus ( ) && accessibilityFocus && editor . accessibility . hasFocus ( ) ) ) { editor . events . focus ( true ) ; }
if ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . undo !== false ) { if ( editor . $el . find ( '.fr-marker' ) . length ) { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; }
editor . undo . saveStep ( ) ; }
if ( callback ) { callback . apply ( editor , $ . merge ( [ cmd ] , params || [ ] ) ) ; }
editor . events . trigger ( 'commands.after' , $ . merge ( [ cmd ] , params || [ ] ) ) ; if ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . undo !== false ) editor . undo . saveStep ( ) ; } }
function _execCommand ( cmd , tag ) { editor . format . toggle ( tag ) ; }
function _processIndent ( indent ) { editor . selection . save ( ) ; editor . html . wrap ( true , true , true , true ) ; editor . selection . restore ( ) ; var blocks = editor . selection . blocks ( ) ; for ( var i = 0 ; i < blocks . length ; i ++ ) { if ( blocks [ i ] . tagName != 'LI' && blocks [ i ] . parentNode . tagName != 'LI' ) { var $block = $ ( blocks [ i ] ) ; var prop = ( editor . opts . direction == 'rtl' || $block . css ( 'direction' ) == 'rtl' ) ? 'margin-right' : 'margin-left' ; var margin _left = editor . helpers . getPX ( $block . css ( prop ) ) ; if ( $block . width ( ) < 2 * editor . opts . indentMargin && indent > 0 ) continue ; $block . css ( prop , Math . max ( margin _left + indent * editor . opts . indentMargin , 0 ) || '' ) ; $block . removeClass ( 'fr-temp-div' ) ; } }
editor . selection . save ( ) ; editor . html . unwrap ( ) ; editor . selection . restore ( ) ; }
function callExec ( k ) { return function ( ) { exec ( k ) ; } }
var resp = { } ; for ( var k in mapping ) { if ( mapping . hasOwnProperty ( k ) ) { resp [ k ] = callExec ( k ) ; } }
function _init ( ) { editor . events . on ( 'keydown' , function ( e ) { var el = editor . selection . element ( ) ; if ( el && el . tagName == 'HR' && ! editor . keys . isArrow ( e . which ) ) { e . preventDefault ( ) ; return false ; } } ) ; editor . events . on ( 'keyup' , function ( e ) { var el = editor . selection . element ( ) ; if ( el && el . tagName == 'HR' ) { if ( e . which == $ . FE . KEYCODE . ARROW _LEFT || e . which == $ . FE . KEYCODE . ARROW _UP ) { if ( el . previousSibling ) { if ( ! editor . node . isBlock ( el . previousSibling ) ) { $ ( el ) . before ( $ . FE . MARKERS ) ; }
else { editor . selection . setAtEnd ( el . previousSibling ) ; }
editor . selection . restore ( ) ; return false ; } }
else if ( e . which == $ . FE . KEYCODE . ARROW _RIGHT || e . which == $ . FE . KEYCODE . ARROW _DOWN ) { if ( el . nextSibling ) { if ( ! editor . node . isBlock ( el . nextSibling ) ) { $ ( el ) . after ( $ . FE . MARKERS ) ; }
else { editor . selection . setAtStart ( el . nextSibling ) ; }
editor . selection . restore ( ) ; return false ; } } } } )
editor . events . on ( 'mousedown' , function ( e ) { if ( e . target && e . target . tagName == 'HR' ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; return false ; } } ) ; editor . events . on ( 'mouseup' , function ( ) { var s _el = editor . selection . element ( ) ; var e _el = editor . selection . endElement ( ) ; if ( s _el == e _el && s _el && s _el . tagName == 'HR' ) { if ( s _el . nextSibling ) { if ( ! editor . node . isBlock ( s _el . nextSibling ) ) { $ ( s _el ) . after ( $ . FE . MARKERS ) ; }
else { editor . selection . setAtStart ( s _el . nextSibling ) ; } }
editor . selection . restore ( ) ; } } ) }
return $ . extend ( resp , { exec : exec , _init : _init } ) ; } ; $ . FE . MODULES . data = function ( l ) { var d = "2B3B9A6C7C2C4C3H3I3B2==" , s = "NCKB1zwtPA9tqzajXC2c2A7B-16VD3spzJ1C9C3D5oOF2OB1NB1LD7VA5QF4TE3gytXB2A4C-8VA2AC4E1D3GB2EB2KC3KD1MF1juuSB1A8C6yfbmd1B2a1A5qdsdB2tivbC3CB1KC1CH1eLA2sTF1B4I4H-7B-21UB6b1F5bzzzyAB4JC3MG2hjdKC1JE6C1E1cj1pD-16pUE5B4prra2B5ZB3D3C3pxj1EA6A3rnJA2C-7I-7JD9D1E1wYH1F3sTB5TA2G4H4ZA22qZA5BB3mjcvcCC3JB1xillavC-21VE6PC5SI4YC5C8mb1A3WC3BD2B5aoDA2qqAE3A5D-17fOD1D5RD4WC10tE6OAZC3nF-7b1C4A4D3qCF2fgmapcromlHA2QA6a1E1D3e1A6C2bie2F4iddnIA7B2mvnwcIB5OA1DB2OLQA3PB10WC7WC5d1E3uI-7b1D5D6b1E4D2arlAA4EA1F-11srxI-7MB1D7PF1E5B4adB-21YD5vrZH3D3xAC4E1A2GF2CF2J-7yNC2JE1MI2hH-7QB1C6B5B-9bA-7XB13a1B5VievwpKB4LA3NF-10H-9I-8hhaC-16nqPG4wsleTD5zqYF3h1G2B7B4yvGE2Pi1H-7C-21OE6B1uLD1kI4WC1E7C5g1D-8fue1C8C6c1D4D3Hpi1CC4kvGC2E1legallyXB4axVA11rsA4A-9nkdtlmzBA2GD3A13A6CB1dabE1lezrUE6RD5TB4A-7f1C8c1B5d1D4D3tyfCD5C2D2==" , f = function ( ) { for ( var e = 0 , t = document . domain , n = t . split ( "." ) , r = "_gd" + ( new Date ) . getTime ( ) ; e < n . length - 1 && - 1 == document . cookie . indexOf ( r + "=" + r ) ; ) t = n . slice ( - 1 - ++ e ) . join ( "." ) , document . cookie = r + "=" + r + ";domain=" + t + ";" ; return document . cookie = r + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain=" + t + ";" , ( t || "" ) . replace ( /(^\.*)|(\.*$)/g , "" ) } ( ) ; function u ( e ) { return e } var E , p , g = u ( function ( e ) { if ( ! e ) return e ; for ( var t = "" , n = u ( "charCodeAt" ) , r = u ( "fromCharCode" ) , C = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" . indexOf ( e [ 0 ] ) , o = 1 ; o < e . length - 2 ; o ++ ) { for ( var i = a ( ++ C ) , A = e [ n ] ( o ) , B = "" ; /[0-9-]/ . test ( e [ o + 1 ] ) ; ) B += e [ ++ o ] ; A = D ( A , i , B = parseInt ( B , 10 ) || 0 ) , A ^= C - 1 & 31 , t += String [ r ] ( A ) } return t } ) ; function a ( e ) { for ( var t = e . toString ( ) , n = 0 , r = 0 ; r < t . length ; r ++ ) n += parseInt ( t . charAt ( r ) , 10 ) ; return 10 < n ? n % 9 + 1 : n } function D ( e , t , n ) { for ( var r = Math . abs ( n ) ; 0 < r -- ; ) e -= t ; return n < 0 && ( e += 123 ) , e } function h ( e ) { return e && "block" !== e . css ( "display" ) ? ( e . remove ( ) , ! 0 ) : e && 0 === l . helpers . getPX ( e . css ( "height" ) ) ? ( e . remove ( ) , ! 0 ) : ! ( ! e || "absolute" !== e . css ( "position" ) && "fixed" !== e . css ( "position" ) ) && ( e . remove ( ) , ! 0 ) } function v ( e ) { return e && 0 === l . $box . find ( e ) . length } var e = 0 ; function m ( ) { if ( 10 < e && ( l [ u ( g ( "0ppecjvc==" ) ) ] ( ) , setTimeout ( function ( ) { $ . FE = null } , 10 ) ) , ! l . $box ) return ! 1 ; l . $wp . prepend ( g ( u ( g ( s ) ) ) ) , E = l . $wp . find ( "> div:first" ) , p = E . find ( "> a" ) , "rtl" == l . opts . direction && E . css ( "left" , "auto" ) . css ( "right" , 0 ) . attr ( "direction" , "rtl" ) , e ++ } function F ( e ) { for ( var t = [ g ( "9qqG-7amjlwq==" ) , g ( "KA3B3C2A6D1D5H5H1A3==" ) , g ( "3B9B3B5F3C4G3E3==" ) , g ( "QzbzvxyB2yA-9m==" ) , g ( "ji1kacwmgG5bc==" ) , g ( "nmA-13aogi1A3c1jd==" ) , g ( "BA9ggq==" ) , g ( "emznbjbH3fij==" ) , g ( "tkC-22d1qC-13sD1wzF-7==" ) ] , n = 0 ; n < t . length ; n ++ ) if ( String . prototype . endsWith || ( String . prototype . endsWith = function ( e , t ) { return ( t === undefined || t > this . length ) && ( t = this . length ) , this . substring ( t - e . length , t ) === e } ) , e . endsWith ( t [ n ] ) ) return ! 0 ; return ! 1 } return { _init : function ( ) { var e = l . o _win . FEK ; try { e = e || localStorage && localStorage . FEK } catch ( c ) { } e = l . opts . key || e || [ "" ] ; var t = g ( u ( "ziRA1E3B9pA5B-11D-11xg1A3ZB5D1D4B-11ED2EG2pdeoC1clIH4wB-22yQD5uF4YE3E3A9==" ) ) ; "string" == typeof e && ( e = [ e ] ) ; for ( var n , r , C , o = ! ( l . ul = ! 0 ) , i = 0 , A = 0 ; A < e . length ; A ++ ) { var B = ( r = e [ A ] , 3 === ( C = ( g ( r ) || "" ) . split ( "|" ) ) . length ? C : [ null , null , g ( r ) || "" ] ) , a = B [ 2 ] ; if ( a === g ( u ( g ( "mcVRDoB1BGILD7YFe1BTXBA7B6==" ) ) ) || 0 <= a . indexOf ( f , a . length - f . length ) || F ( f ) ) { if ( ! ( ( null === ( n = B [ 1 ] ) || new Date ( n ) < new Date ( g ( d ) ) ) && 0 < ( f || "" ) . length ) || F ( f ) ) { l . ul = ! 1 ; break } o = ! 0 , s = "RCZB17botVG4A-8yzia1C4A5DG3CD2cFB4qflmCE4I2FB1SC7F6PE4WE3RD6e2A4c1D3d1E2E3ehxdGE3CE2IB2LC1HG2LE1QA3QC7B-13cC-9epmkjc1B4e1C4pgjgvkOC5E1eNE1HB2LD2B-13WD5tvabUA5a1A4f1A2G3C2A-21cihKE3FE2DB2cccJE1iC-7G-7tD-17tVD6A-9qC-7QC7a1E4B4je1E3E2G2ecmsAA1xH-8HB11C1D1lgzQA3dTB8od1D4XE3ohb1B4E4D3mbLA10NA7C-21d1genodKC11PD9PE5tA-8UI3ZC5XB5B-11qXF2F-7wtwjAG3NA1IB1OD1HC1RD4QJ4evUF2D5XG2G4XA8pqocH1F3G2J2hcpHC4D1MD4C1MB8PD5klcQD1A8A6e2A3ed1E2A24A7HC5C3qA-9tiA-61dcC3MD1LE1D4SA3A9ZZXSE4g1C3Pa2C5ufbcGI3I2B4skLF2CA1vxB-22wgUC4kdH-8cVB5iwe1A2D3H3G-7DD5JC2ED2OH2JB10D3C2xHE1KA29PB11wdC-11C4cixb2C7a1C4YYE3B2A15uB-21wpCA1MF1NuC-21dyzD6pPG4I-7pmjc1A4yte1F3B-22yvCC3VbC-7qC-22qNE2hC1vH-8zad1RF6WF3DpI-7C8A-16hpf1F3D2ylalB-13BB2lpA-63IB3uOF6D5G4gabC-21UD2A3PH4ZA20B11b2C6ED4A2H3I1A15DB4KD2laC-8LA5B8B7==" , i = B [ 0 ] || - 1 } } var D = new Image ; ! 0 === l . ul &&
$ . extend ( $ . FE . DEFAULTS , { pastePlain : false , pasteDeniedTags : [ 'colgroup' , 'col' , 'meta' ] , pasteDeniedAttrs : [ 'class' , 'id' , 'style' ] , pasteAllowedStyleProps : [ '.*' ] , pasteAllowLocalImages : false } ) ; $ . FE . MODULES . paste = function ( editor ) { var scroll _position ; var clipboard _html ; var clipboard _rtf ; var $paste _div ; var snapshot ; function saveCopiedText ( html , plain ) { try { editor . win . localStorage . setItem ( 'fr-copied-html' , html ) ; editor . win . localStorage . setItem ( 'fr-copied-text' , plain ) ; }
catch ( ex ) { } }
function _handleCopy ( e ) { var copied _html = editor . html . getSelected ( ) ; saveCopiedText ( copied _html , $ ( '<div>' ) . html ( copied _html ) . text ( ) )
if ( e . type == 'cut' ) { editor . undo . saveStep ( ) ; setTimeout ( function ( ) { editor . selection . save ( ) ; editor . html . wrap ( ) ; editor . selection . restore ( ) ; editor . events . focus ( ) ; editor . undo . saveStep ( ) ; } , 0 ) ; } }
var stop _paste = false ; function _handlePaste ( e ) { if ( editor . edit . isDisabled ( ) ) { return false ; }
if ( stop _paste ) { return false ; }
if ( e . originalEvent ) e = e . originalEvent ; if ( editor . events . trigger ( 'paste.before' , [ e ] ) === false ) { e . preventDefault ( ) ; return false ; }
scroll _position = editor . $win . scrollTop ( ) ; if ( e && e . clipboardData && e . clipboardData . getData ) { var types = '' ; var clipboard _types = e . clipboardData . types ; if ( editor . helpers . isArray ( clipboard _types ) ) { for ( var i = 0 ; i < clipboard _types . length ; i ++ ) { types += clipboard _types [ i ] + ';' ; } }
else { types = clipboard _types ; }
clipboard _html = '' ; if ( /text\/rtf/ . test ( types ) ) { clipboard _rtf = e . clipboardData . getData ( 'text/rtf' ) ; }
if ( /text\/html/ . test ( types ) && ! editor . browser . safari ) { clipboard _html = e . clipboardData . getData ( 'text/html' ) ; }
else if ( /text\/rtf/ . test ( types ) && editor . browser . safari ) { clipboard _html = clipboard _rtf ; }
else if ( /public.rtf/ . test ( types ) && editor . browser . safari ) { clipboard _html = e . clipboardData . getData ( 'text/rtf' ) ; }
if ( clipboard _html !== '' ) { _processPaste ( ) ; if ( e . preventDefault ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; }
return false ; }
else { clipboard _html = null ; } }
_beforePaste ( ) ; return false ; }
function _dropPaste ( e ) { if ( e . originalEvent ) e = e . originalEvent ; if ( e && e . dataTransfer && e . dataTransfer . getData ) { var types = '' ; var clipboard _types = e . dataTransfer . types ; if ( editor . helpers . isArray ( clipboard _types ) ) { for ( var i = 0 ; i < clipboard _types . length ; i ++ ) { types += clipboard _types [ i ] + ';' ; } }
else { types = clipboard _types ; }
clipboard _html = '' ; if ( /text\/rtf/ . test ( types ) ) { clipboard _rtf = e . dataTransfer . getData ( 'text/rtf' ) ; }
if ( /text\/html/ . test ( types ) ) { clipboard _html = e . dataTransfer . getData ( 'text/html' ) ; }
else if ( /text\/rtf/ . test ( types ) && editor . browser . safari ) { clipboard _html = clipboard _rtf ; }
else if ( /text\/plain/ . test ( types ) && ! this . browser . mozilla ) { clipboard _html = editor . html . escapeEntities ( e . dataTransfer . getData ( 'text/plain' ) ) . replace ( /\n/g , '<br>' ) ; }
if ( clipboard _html !== '' ) { editor . keys . forceUndo ( ) ; snapshot = editor . snapshot . get ( ) ; editor . selection . save ( ) ; editor . $el . find ( '.fr-marker' ) . removeClass ( 'fr-marker' ) . addClass ( 'fr-marker-helper' ) ; var ok = editor . markers . insertAtPoint ( e ) ; editor . $el . find ( '.fr-marker' ) . removeClass ( 'fr-marker' ) . addClass ( 'fr-marker-placeholder' ) ; editor . $el . find ( '.fr-marker-helper' ) . addClass ( 'fr-marker' ) . removeClass ( 'fr-marker-helper' ) ; editor . selection . restore ( ) ; editor . selection . remove ( ) ; editor . $el . find ( '.fr-marker-placeholder' ) . addClass ( 'fr-marker' ) . removeClass ( 'fr-marker-placeholder' ) ; if ( ok !== false ) { var marker = editor . el . querySelector ( '.fr-marker' ) ; $ ( marker ) . replaceWith ( $ . FE . MARKERS ) ; editor . selection . restore ( ) ; _processPaste ( ) ; if ( e . preventDefault ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; }
return false ; } }
else { clipboard _html = null ; } } }
function _beforePaste ( ) { editor . selection . save ( ) ; editor . events . disableBlur ( ) ; clipboard _html = null ; if ( ! $paste _div ) { $paste _div = $ ( '<div contenteditable="true" style="position: fixed; top: 0; left: -9999px; height: 100%; width: 0; word-break: break-all; overflow:hidden; z-index: 2147483647; line-height: 140%; -moz-user-select: text; -webkit-user-select: text; -ms-user-select: text; user-select: text;" tabIndex="-1"></div>' ) ; if ( editor . browser . webkit ) { $paste _div . css ( 'top' , editor . $sc . scrollTop ( ) ) ; editor . $el . after ( $paste _div ) ; }
else if ( editor . browser . edge && editor . opts . iframe ) { editor . $el . append ( $paste _div ) ; }
else { editor . $box . after ( $paste _div ) ; }
editor . events . on ( 'destroy' , function ( ) { $paste _div . remove ( ) ; } ) }
else { $paste _div . html ( '' ) ; if ( editor . browser . edge && editor . opts . iframe ) { editor . $el . append ( $paste _div ) ; } }
if ( editor . helpers . isIOS ( ) && editor . $sc ) { editor . $sc . overflow ( 'hidden' ) ; }
$paste _div . focus ( ) ; if ( editor . helpers . isIOS ( ) && editor . $sc ) { editor . $sc . overflow ( 'hidden' , '' ) ; }
editor . win . setTimeout ( _processPaste , 1 ) ; }
function _wordClean ( html ) { var i ; html = html . replace ( /<p(.*?)class="?'?MsoListParagraph"?'? ([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<ul><li>$3</li></ul>' ) ; html = html . replace ( /<p(.*?)class="?'?NumberedText"?'? ([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<ol><li>$3</li></ol>' ) ; html = html . replace ( /<p(.*?)class="?'?MsoListParagraphCxSpFirst"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<ul><li$3>$5</li>' ) ; html = html . replace ( /<p(.*?)class="?'?NumberedTextCxSpFirst"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<ol><li$3>$5</li>' ) ; html = html . replace ( /<p(.*?)class="?'?MsoListParagraphCxSpMiddle"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<li$3>$5</li>' ) ; html = html . replace ( /<p(.*?)class="?'?NumberedTextCxSpMiddle"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<li$3>$5</li>' ) ; html = html . replace ( /<p(.*?)class="?'?MsoListBullet"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<li$3>$5</li>' ) ; html = html . replace ( /<p(.*?)class="?'?MsoListParagraphCxSpLast"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<li$3>$5</li></ul>' ) ; html = html . replace ( /<p(.*?)class="?'?NumberedTextCxSpLast"?'?([\s\S]*?)(level\d)?([\s\S]*?)>([\s\S]*?)<\/p>/gi , '<li$3>$5</li></ol>' ) ; html = html . replace ( /<span([^<]*?)style="?'?mso-list:Ignore"?'?([\s\S]*?)>([\s\S]*?)<span/gi , '<span><span' ) ; html = html . replace ( /<!--\[if \!supportLists\]-->([\s\S]*?)<!--\[endif\]-->/gi , '' ) ; html = html . replace ( /<!\[if \!supportLists\]>([\s\S]*?)<!\[endif\]>/gi , '' ) ; html = html . replace ( /(\n|\r| class=(")?Mso[a-zA-Z0-9]+(")?)/gi , ' ' ) ; html = html . replace ( /<!--[\s\S]*?-->/gi , '' ) ; html = html . replace ( /<(\/)*(meta|link|span|\\?xml:|st1:|o:|font)(.*?)>/gi , '' ) ; var word _tags = [ 'style' , 'script' , 'applet' , 'embed' , 'noframes' , 'noscript' ] ; for ( i = 0 ; i < word _tags . length ; i ++ ) { var regex = new RegExp ( '<' + word _tags [ i ] + '.*?' + word _tags [ i ] + '(.*?)>' , 'gi' ) ; html = html . replace ( regex , '' ) ; }
html = html . replace ( / /gi , ' ' ) ; html = html . replace ( /<td([^>]*)><\/td>/g , '<td$1><br></td>' ) ; html = html . replace ( /<th([^>]*)><\/th>/g , '<th$1><br></th>' ) ; var oldHTML ; do { oldHTML = html ; html = html . replace ( /<[^\/>][^>]*><\/[^>]+>/gi , '' ) ; } while ( html != oldHTML ) ; html = html . replace ( /<lilevel([^1])([^>]*)>/gi , '<li data-indent="true"$2>' ) ; html = html . replace ( /<lilevel1([^>]*)>/gi , '<li$1>' ) ; html = editor . clean . html ( html , editor . opts . pasteDeniedTags , editor . opts . pasteDeniedAttrs ) ; html = html . replace ( /<a>(.[^<]+)<\/a>/gi , '$1' ) ; html = html . replace ( /<br> */g , '<br>' ) ; var div = editor . o _doc . createElement ( 'div' )
div . innerHTML = html ; var lis = div . querySelectorAll ( 'li[data-indent]' ) ; for ( i = 0 ; i < lis . length ; i ++ ) { var li = lis [ i ] ; var p _li = li . previousElementSibling ; if ( p _li && p _li . tagName == 'LI' ) { var list = p _li . querySelector ( ':scope > ul, :scope > ol' ) ; if ( ! list ) { list = document . createElement ( 'ul' ) ; p _li . appendChild ( list ) ; }
list . appendChild ( li ) ; }
else { li . removeAttribute ( 'data-indent' ) ; } }
editor . html . cleanBlankSpaces ( div ) ; html = div . innerHTML ; return html ; }
function _plainPasteClean ( html ) { var el = null ; var i ; var div = editor . doc . createElement ( 'div' ) ; div . innerHTML = html ; var els = div . querySelectorAll ( 'p, div, h1, h2, h3, h4, h5, h6, pre, blockquote' ) ; for ( i = 0 ; i < els . length ; i ++ ) { el = els [ i ] ; el . outerHTML = '<' + ( editor . html . defaultTag ( ) || 'DIV' ) + '>' + el . innerHTML + '</' + ( editor . html . defaultTag ( ) || 'DIV' ) + '>' }
els = div . querySelectorAll ( '*:not(' + 'p, div, h1, h2, h3, h4, h5, h6, pre, blockquote, ul, ol, li, table, tbody, thead, tr, td, br, img' . split ( ',' ) . join ( '):not(' ) + ')' ) ; for ( i = els . length - 1 ; i >= 0 ; i -- ) { el = els [ i ] ; el . outerHTML = el . innerHTML ; }
var cleanComments = function ( node ) { var contents = editor . node . contents ( node ) ; for ( var i = 0 ; i < contents . length ; i ++ ) { if ( contents [ i ] . nodeType != Node . TEXT _NODE && contents [ i ] . nodeType != Node . ELEMENT _NODE ) { contents [ i ] . parentNode . removeChild ( contents [ i ] ) ; }
else { cleanComments ( contents [ i ] ) ; } } } ; cleanComments ( div ) ; return div . innerHTML ; }
function _processPaste ( ) { if ( editor . browser . edge && editor . opts . iframe ) { editor . $box . after ( $paste _div ) ; }
if ( ! snapshot ) { editor . keys . forceUndo ( ) ; snapshot = editor . snapshot . get ( ) ; }
if ( ! clipboard _html ) { clipboard _html = $paste _div . get ( 0 ) . innerHTML ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; }
var is _word = clipboard _html . match ( /(class=\"?Mso|class=\'?Mso|class="?Xl|class='?Xl|class=Xl|style=\"[^\"]*\bmso\-|style=\'[^\']*\bmso\-|w:WordDocument)/gi ) ; var response = editor . events . chainTrigger ( 'paste.beforeCleanup' , clipboard _html ) ; if ( response && typeof ( response ) === 'string' ) { clipboard _html = response ; }
if ( ! is _word || ( is _word && editor . events . trigger ( 'paste.wordPaste' , [ clipboard _html ] ) !== false ) ) { clean ( clipboard _html , is _word ) ; } }
function _isFromEditor ( clipboard _html ) { var possible _text = null ; try { possible _text = editor . win . localStorage . getItem ( 'fr-copied-text' ) ; }
catch ( ex ) { }
if ( possible _text && $ ( '<div>' ) . html ( clipboard _html ) . text ( ) . replace ( /\u00A0/gi , ' ' ) . replace ( /\r|\n/gi , '' ) == possible _text . replace ( /\u00A0/gi , ' ' ) . replace ( /\r|\n/gi , '' ) ) { return true ; }
return false ; }
function _isDraggedFromEditor ( ) { var possible _text = null ; try { possible _text = editor . win . localStorage . getItem ( 'fr-dragged-content-text' ) ; }
catch ( ex ) { }
if ( possible _text && $ ( '<div>' ) . html ( clipboard _html ) . text ( ) . replace ( /\u00A0/gi , ' ' ) . replace ( /\r|\n/gi , '' ) == possible _text . replace ( /\u00A0/gi , ' ' ) . replace ( /\r|\n/gi , '' ) ) { return true ; }
return false ; }
function _buildTabs ( len ) { var tabs = '' ; var i = 0 ; while ( i ++ < len ) { tabs += ' ' }
return tabs ; }
function clean ( clipboard _html , is _word , keep _formatting ) { var els = null ; var el = null ; var i ; if ( clipboard _html . toLowerCase ( ) . indexOf ( '<body' ) >= 0 ) { var style = '' ; if ( clipboard _html . indexOf ( '<style' ) >= 0 ) { style = clipboard _html . replace ( /[.\s\S\w\W<>]*(<style[^>]*>[\s]*[.\s\S\w\W<>]*[\s]*<\/style>)[.\s\S\w\W<>]*/gi , '$1' ) ; }
clipboard _html = style + clipboard _html . replace ( /[.\s\S\w\W<>]*<body[^>]*>[\s]*([.\s\S\w\W<>]*)[\s]*<\/body>[.\s\S\w\W<>]*/gi , '$1' ) ; var lastIndex = 0 ; var result = '' ; clipboard _html . replace ( /<pre.*?>([\s\S]*?)<\/pre>/ig , function ( match , p1 , offset ) { if ( offset > lastIndex ) { result += clipboard _html . substring ( lastIndex , offset ) . replace ( / \n/g , ' ' ) . replace ( /\n /g , ' ' ) . replace ( /([^>])\n([^<])/g , '$1 $2' ) ; }
result += match ; lastIndex = offset + match . length ; } ) ; if ( clipboard _html . length > lastIndex + 1 ) { result += clipboard _html . substring ( lastIndex , clipboard _html . length ) . replace ( / \n/g , ' ' ) . replace ( /\n /g , ' ' ) . replace ( /([^>])\n([^<])/g , '$1 $2' ) ; }
clipboard _html = result ; }
var is _gdocs = false ; if ( clipboard _html . indexOf ( 'id="docs-internal-guid' ) >= 0 ) { clipboard _html = clipboard _html . replace ( /^[\w\W\s\S]* id="docs-internal-guid[^>]*>([\w\W\s\S]*)<\/b>[\w\W\s\S]*$/g , '$1' ) ; is _gdocs = true ; }
if ( clipboard _html . indexOf ( 'content="Sheets"' ) >= 0 ) { clipboard _html = clipboard _html . replace ( /width:0px;/g , '' ) }
var is _editor _content = false ; var is _dragged _from _editor = false ; if ( ! is _word ) { is _editor _content = _isFromEditor ( clipboard _html ) ; is _dragged _from _editor = _isDraggedFromEditor ( clipboard _html ) ; if ( is _editor _content ) { clipboard _html = editor . win . localStorage . getItem ( 'fr-copied-html' ) ; }
if ( is _dragged _from _editor ) { is _editor _content = true ; clipboard _html = editor . win . localStorage . getItem ( 'fr-dragged-content-html' ) ; }
if ( ! is _editor _content ) { var htmlAllowedStylePropsCopy = editor . opts . htmlAllowedStyleProps ; editor . opts . htmlAllowedStyleProps = editor . opts . pasteAllowedStyleProps ; editor . opts . htmlAllowComments = false ; clipboard _html = clipboard _html . replace ( /<span class="Apple-tab-span">\s*<\/span>/g , _buildTabs ( editor . opts . tabSpaces || 4 ) ) ; clipboard _html = clipboard _html . replace ( /<span class="Apple-tab-span" style="white-space:pre">(\t*)<\/span>/g , function ( str , x ) { return _buildTabs ( x . length * ( editor . opts . tabSpaces || 4 ) ) ; } )
clipboard _html = clipboard _html . replace ( /\t/g , _buildTabs ( editor . opts . tabSpaces || 4 ) ) ; clipboard _html = editor . clean . html ( clipboard _html , editor . opts . pasteDeniedTags , editor . opts . pasteDeniedAttrs ) ; editor . opts . htmlAllowedStyleProps = htmlAllowedStylePropsCopy ; editor . opts . htmlAllowComments = true ; clipboard _html = cleanEmptyTagsAndDivs ( clipboard _html ) ; clipboard _html = clipboard _html . replace ( /\r/g , '' ) ; clipboard _html = clipboard _html . replace ( /^ */g , '' ) . replace ( / *$/g , '' ) ; } }
if ( is _word && ( ! editor . wordPaste || ! keep _formatting ) ) { clipboard _html = clipboard _html . replace ( /^\n*/g , '' ) . replace ( /^ /g , '' ) ; if ( clipboard _html . indexOf ( '<colgroup>' ) === 0 ) { clipboard _html = '<table>' + clipboard _html + '</table>' ; }
clipboard _html = _wordClean ( clipboard _html ) ; clipboard _html = cleanEmptyTagsAndDivs ( clipboard _html ) ; }
if ( editor . opts . pastePlain && ! is _editor _content ) { clipboard _html = _plainPasteClean ( clipboard _html ) ; }
var response = editor . events . chainTrigger ( 'paste.afterCleanup' , clipboard _html ) ; if ( typeof ( response ) === 'string' ) { clipboard _html = response ; }
if ( clipboard _html !== '' ) { var tmp = editor . o _doc . createElement ( 'div' ) ; tmp . innerHTML = clipboard _html ; if ( clipboard _html . indexOf ( '<body>' ) >= 0 ) { editor . html . cleanBlankSpaces ( tmp ) ; editor . spaces . normalize ( tmp , true ) ; }
else { editor . spaces . normalize ( tmp ) ; }
var spans = tmp . getElementsByTagName ( 'span' ) ; for ( i = spans . length - 1 ; i >= 0 ; i -- ) { var span = spans [ i ] ; if ( span . attributes . length === 0 ) { span . outerHTML = span . innerHTML ; } }
var selection _el = editor . selection . element ( ) ; var in _list = false ; if ( selection _el && $ ( selection _el ) . parentsUntil ( editor . el , 'ul, ol' ) . length ) { in _list = true ; }
if ( in _list ) { var list = tmp . children ; if ( list . length == 1 && [ 'OL' , 'UL' ] . indexOf ( list [ 0 ] . tagName ) >= 0 ) { list [ 0 ] . outerHTML = list [ 0 ] . innerHTML ; } }
if ( ! is _gdocs ) { var brs = tmp . getElementsByTagName ( 'br' ) ; for ( i = brs . length - 1 ; i >= 0 ; i -- ) { var br = brs [ i ] ; if ( editor . node . isBlock ( br . previousSibling ) ) { br . parentNode . removeChild ( br ) ; } } }
if ( editor . opts . enter == $ . FE . ENTER _BR ) { els = tmp . querySelectorAll ( 'p, div' ) ; for ( i = els . length - 1 ; i >= 0 ; i -- ) { el = els [ i ] ; if ( el . attributes . length === 0 ) { el . outerHTML = el . innerHTML + ( el . nextSibling && ! editor . node . isEmpty ( el ) ? '<br>' : '' ) ; } } }
else if ( editor . opts . enter == $ . FE . ENTER _DIV ) { els = tmp . getElementsByTagName ( 'p' ) ; for ( i = els . length - 1 ; i >= 0 ; i -- ) { el = els [ i ] ; if ( el . attributes . length === 0 ) { el . outerHTML = '<div>' + el . innerHTML + '</div>' ; } } }
else if ( editor . opts . enter == $ . FE . ENTER _P ) { if ( tmp . childNodes . length == 1 && tmp . childNodes [ 0 ] . tagName == 'P' && tmp . childNodes [ 0 ] . attributes . length === 0 ) { tmp . childNodes [ 0 ] . outerHTML = tmp . childNodes [ 0 ] . innerHTML ; } }
clipboard _html = tmp . innerHTML ; if ( is _editor _content ) { clipboard _html = removeEmptyTags ( clipboard _html ) ; }
editor . html . insert ( clipboard _html , true ) ; }
_afterPaste ( ) ; editor . undo . saveStep ( snapshot ) ; snapshot = null ; editor . undo . saveStep ( ) ; }
function _afterPaste ( ) { editor . events . trigger ( 'paste.after' ) ; }
function getRtfClipboard ( ) { return clipboard _rtf ; }
function _filterNoAttrs ( arry ) { for ( var t = arry . length - 1 ; t >= 0 ; t -- ) { if ( arry [ t ] . attributes && arry [ t ] . attributes . length ) { arry . splice ( t , 1 ) ; } }
return arry ; }
function cleanEmptyTagsAndDivs ( html ) { var i ; var div = editor . o _doc . createElement ( 'div' ) ; div . innerHTML = html ; var divs = _filterNoAttrs ( Array . prototype . slice . call ( div . querySelectorAll ( ':scope > div:not([style]), td > div:not([style]), th > div:not([style]), li > div:not([style])' ) ) ) ; while ( divs . length ) { var dv = divs [ divs . length - 1 ] ; if ( editor . html . defaultTag ( ) && editor . html . defaultTag ( ) != 'div' ) { if ( dv . querySelector ( editor . html . blockTagsQuery ( ) ) ) { dv . outerHTML = dv . innerHTML ; }
else { dv . outerHTML = '<' + editor . html . defaultTag ( ) + '>' + dv . innerHTML + '</' + editor . html . defaultTag ( ) + '>' ; } }
else { var els = dv . querySelectorAll ( '*' ) ; if ( ! els . length || ( els [ els . length - 1 ] . tagName !== 'BR' && dv . innerText . length === 0 ) ) { dv . outerHTML = dv . innerHTML + ( dv . nextSibling ? '<br>' : '' ) ; }
else if ( ! ( els . length && els [ els . length - 1 ] . tagName === 'BR' && ! els [ els . length - 1 ] . nextSibling ) ) { dv . outerHTML = dv . innerHTML + ( dv . nextSibling ? '<br>' : '' ) ; }
else { dv . outerHTML = dv . innerHTML ; } }
divs = _filterNoAttrs ( Array . prototype . slice . call ( div . querySelectorAll ( ':scope > div:not([style]), td > div:not([style]), th > div:not([style]), li > div:not([style])' ) ) ) ; }
divs = _filterNoAttrs ( Array . prototype . slice . call ( div . querySelectorAll ( 'div:not([style])' ) ) ) ; while ( divs . length ) { for ( i = 0 ; i < divs . length ; i ++ ) { var el = divs [ i ] ; var text = el . innerHTML . replace ( /\u0009/gi , '' ) . trim ( ) ; try { el . outerHTML = text ; }
catch ( ex ) { } }
divs = _filterNoAttrs ( Array . prototype . slice . call ( div . querySelectorAll ( 'div:not([style])' ) ) ) ; }
return div . innerHTML ; }
function removeEmptyTags ( html ) { var i ; var div = editor . o _doc . createElement ( 'div' ) ; div . innerHTML = html ; var empty _tags = div . querySelectorAll ( '*:empty:not(td):not(th):not(tr):not(iframe):not(svg):not(' + $ . FE . VOID _ELEMENTS . join ( '):not(' ) + ')' + ':not(' + editor . opts . htmlAllowedEmptyTags . join ( '):not(' ) + ')' ) ; while ( empty _tags . length ) { for ( i = 0 ; i < empty _tags . length ; i ++ ) { empty _tags [ i ] . parentNode . removeChild ( empty _tags [ i ] ) ; }
empty _tags = div . querySelectorAll ( '*:empty:not(td):not(th):not(tr):not(iframe):not(svg):not(' + $ . FE . VOID _ELEMENTS . join ( '):not(' ) + ')' + ':not(' + editor . opts . htmlAllowedEmptyTags . join ( '):not(' ) + ')' ) ; }
return div . innerHTML ; }
function _dragStart ( e ) { if ( e . originalEvent && e . originalEvent . target && e . originalEvent . target . nodeType == Node . TEXT _NODE ) { try { editor . win . localStorage . setItem ( 'fr-dragged-content-html' , e . originalEvent . dataTransfer . getData ( 'text/html' ) ) ; editor . win . localStorage . setItem ( 'fr-dragged-content-text' , e . originalEvent . dataTransfer . getData ( 'text/plain' ) ) ; }
catch ( ex ) { } } }
function _init ( ) { editor . el . addEventListener ( 'copy' , _handleCopy ) ; editor . el . addEventListener ( 'cut' , _handleCopy ) ; editor . el . addEventListener ( 'paste' , _handlePaste , { capture : true } ) ; editor . events . on ( 'drop' , _dropPaste ) ; if ( editor . browser . msie && editor . browser . version < 11 ) { editor . events . on ( 'mouseup' , function ( e ) { if ( e . button == 2 ) { setTimeout ( function ( ) { stop _paste = false ; } , 50 ) ; stop _paste = true ; } } , true )
editor . events . on ( 'beforepaste' , _handlePaste ) ; }
editor . events . on ( 'dragstart' , _dragStart , true ) ; editor . events . on ( 'destroy' , _destroy ) ; }
function _destroy ( ) { editor . el . removeEventListener ( 'copy' , _handleCopy ) ; editor . el . removeEventListener ( 'cut' , _handleCopy ) ; editor . el . removeEventListener ( 'paste' , _handlePaste ) ; }
return { _init : _init , cleanEmptyTagsAndDivs : cleanEmptyTagsAndDivs , getRtfClipboard : getRtfClipboard , saveCopiedText : saveCopiedText , clean : clean } } ; $ . extend ( $ . FE . DEFAULTS , { shortcutsEnabled : [ ] , shortcutsHint : true } ) ; $ . FE . SHORTCUTS _MAP = { } ; $ . FE . RegisterShortcut = function ( key , cmd , val , letter , shift , option ) { $ . FE . SHORTCUTS _MAP [ ( shift ? '^' : '' ) + ( option ? '@' : '' ) + key ] = { cmd : cmd , val : val , letter : letter , shift : shift , option : option }
$ . FE . DEFAULTS . shortcutsEnabled . push ( cmd ) ; }
$ . FE . RegisterShortcut ( $ . FE . KEYCODE . E , 'show' , null , 'E' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . B , 'bold' , null , 'B' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . I , 'italic' , null , 'I' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . U , 'underline' , null , 'U' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . S , 'strikeThrough' , null , 'S' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . CLOSE _SQUARE _BRACKET , 'indent' , null , ']' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . OPEN _SQUARE _BRACKET , 'outdent' , null , '[' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . Z , 'undo' , null , 'Z' , false , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . Z , 'redo' , null , 'Z' , true , false ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . Y , 'redo' , null , 'Y' , false , false ) ; $ . FE . MODULES . shortcuts = function ( editor ) { var inverse _map = null ; function get ( cmd ) { if ( ! editor . opts . shortcutsHint ) return null ; if ( ! inverse _map ) { inverse _map = { } ; for ( var key in $ . FE . SHORTCUTS _MAP ) { if ( $ . FE . SHORTCUTS _MAP . hasOwnProperty ( key ) && editor . opts . shortcutsEnabled . indexOf ( $ . FE . SHORTCUTS _MAP [ key ] . cmd ) >= 0 ) { inverse _map [ $ . FE . SHORTCUTS _MAP [ key ] . cmd + '.' + ( $ . FE . SHORTCUTS _MAP [ key ] . val || '' ) ] = { shift : $ . FE . SHORTCUTS _MAP [ key ] . shift , option : $ . FE . SHORTCUTS _MAP [ key ] . option , letter : $ . FE . SHORTCUTS _MAP [ key ] . letter } } } }
var srct = inverse _map [ cmd ] ; if ( ! srct ) return null ; return ( editor . helpers . isMac ( ) ? String . fromCharCode ( 8984 ) : editor . language . translate ( 'Ctrl' ) + '+' ) +
( srct . shift ? ( editor . helpers . isMac ( ) ? String . fromCharCode ( 8679 ) : editor . language . translate ( 'Shift' ) + '+' ) : '' ) +
( srct . option ? ( editor . helpers . isMac ( ) ? String . fromCharCode ( 8997 ) : editor . language . translate ( 'Alt' ) + '+' ) : '' ) +
srct . letter ; }
var active = false ; function exec ( e ) { if ( ! editor . core . hasFocus ( ) ) return true ; var keycode = e . which ; var ctrlKey = navigator . userAgent . indexOf ( 'Mac OS X' ) != - 1 ? e . metaKey : e . ctrlKey ; if ( e . type == 'keyup' && active ) { if ( keycode != $ . FE . KEYCODE . META ) { active = false ; return false ; } }
if ( e . type == 'keydown' ) active = false ; var map _key = ( e . shiftKey ? '^' : '' ) + ( e . altKey ? '@' : '' ) + keycode ; if ( ctrlKey && $ . FE . SHORTCUTS _MAP [ map _key ] ) { var cmd = $ . FE . SHORTCUTS _MAP [ map _key ] . cmd ; if ( cmd && editor . opts . shortcutsEnabled . indexOf ( cmd ) >= 0 ) { var val = $ . FE . SHORTCUTS _MAP [ map _key ] . val ; var $btn ; if ( cmd && ! val ) { $btn = editor . $tb . find ( '.fr-command[data-cmd="' + cmd + '"]' ) ; }
else if ( cmd && val ) { $btn = editor . $tb . find ( '.fr-command[data-cmd="' + cmd + '"][data-param1="' + val + '"]' ) ; }
if ( $btn . length ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; $btn . parents ( '.fr-toolbar' ) . data ( 'instance' , editor ) ; if ( e . type == 'keydown' ) { editor . button . exec ( $btn ) ; active = true ; }
return false ; }
else if ( cmd && ( editor . commands [ cmd ] || ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . callback ) ) ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( e . type == 'keydown' ) { ( editor . commands [ cmd ] || $ . FE . COMMANDS [ cmd ] . callback ) ( ) ; active = true ; }
return false ; } } } }
function _init ( ) { editor . events . on ( 'keydown' , exec , true ) ; editor . events . on ( 'keyup' , exec , true ) ; }
return { _init : _init , get : get } }
$ . FE . MODULES . snapshot = function ( editor ) { function _getNodeIndex ( node ) { var childNodes = node . parentNode . childNodes ; var idx = 0 ; var prevNode = null ; for ( var i = 0 ; i < childNodes . length ; i ++ ) { if ( prevNode ) { var isEmptyText = ( childNodes [ i ] . nodeType === Node . TEXT _NODE && childNodes [ i ] . textContent === '' ) ; var twoTexts = ( prevNode . nodeType === Node . TEXT _NODE && childNodes [ i ] . nodeType === Node . TEXT _NODE ) ; var emptyPrevNode = ( prevNode . nodeType === Node . TEXT _NODE && prevNode . textContent === '' ) ; if ( ! isEmptyText && ! twoTexts && ! emptyPrevNode ) idx ++ ; }
if ( childNodes [ i ] == node ) return idx ; prevNode = childNodes [ i ] ; } }
function _getNodeLocation ( node ) { var loc = [ ] ; if ( ! node . parentNode ) return [ ] ; while ( ! editor . node . isElement ( node ) ) { loc . push ( _getNodeIndex ( node ) ) ; node = node . parentNode ; }
return loc . reverse ( ) ; }
function _getRealNodeOffset ( node , offset ) { while ( node && node . nodeType === Node . TEXT _NODE ) { var prevNode = node . previousSibling ; if ( prevNode && prevNode . nodeType == Node . TEXT _NODE ) { offset += prevNode . textContent . length ; }
node = prevNode ; }
return offset ; }
function _getRange ( range ) { return { scLoc : _getNodeLocation ( range . startContainer ) , scOffset : _getRealNodeOffset ( range . startContainer , range . startOffset ) , ecLoc : _getNodeLocation ( range . endContainer ) , ecOffset : _getRealNodeOffset ( range . endContainer , range . endOffset ) } }
function get ( ) { var snapshot = { } ; editor . events . trigger ( 'snapshot.before' ) ; snapshot . html = ( editor . $wp ? editor . $el . html ( ) : editor . $oel . get ( 0 ) . outerHTML ) . replace ( / style=""/g , '' ) ; snapshot . ranges = [ ] ; if ( editor . $wp && editor . selection . inEditor ( ) && editor . core . hasFocus ( ) ) { var ranges = editor . selection . ranges ( ) ; for ( var i = 0 ; i < ranges . length ; i ++ ) { snapshot . ranges . push ( _getRange ( ranges [ i ] ) ) ; } }
editor . events . trigger ( 'snapshot.after' , [ snapshot ] ) ; return snapshot ; }
function _getNodeByLocation ( loc ) { var node = editor . el ; for ( var i = 0 ; i < loc . length ; i ++ ) { node = node . childNodes [ loc [ i ] ] ; }
return node ; }
function _restoreRange ( sel , range _snapshot ) { try { var startNode = _getNodeByLocation ( range _snapshot . scLoc ) ; var startOffset = range _snapshot . scOffset ; var endNode = _getNodeByLocation ( range _snapshot . ecLoc ) ; var endOffset = range _snapshot . ecOffset ; var range = editor . doc . createRange ( ) ; range . setStart ( startNode , startOffset ) ; range . setEnd ( endNode , endOffset ) ; sel . addRange ( range ) ; }
catch ( ex ) { console . warn ( ex ) } }
function restore ( snapshot ) { if ( editor . $el . html ( ) != snapshot . html ) { if ( editor . opts . htmlExecuteScripts ) { editor . $el . html ( snapshot . html ) ; }
else { editor . el . innerHTML = snapshot . html ; } }
var sel = editor . selection . get ( ) ; editor . selection . clear ( ) ; editor . events . focus ( true ) ; for ( var i = 0 ; i < snapshot . ranges . length ; i ++ ) { _restoreRange ( sel , snapshot . ranges [ i ] ) ; } }
function equal ( s1 , s2 ) { if ( s1 . html != s2 . html ) return false ; if ( editor . core . hasFocus ( ) && JSON . stringify ( s1 . ranges ) != JSON . stringify ( s2 . ranges ) ) return false ; return true ; }
return { get : get , restore : restore , equal : equal } } ; $ . FE . MODULES . undo = function ( editor ) { function _disableBrowserUndo ( e ) { var keyCode = e . which ; var ctrlKey = editor . keys . ctrlKey ( e ) ; if ( ctrlKey ) { if ( keyCode == 90 && e . shiftKey ) { e . preventDefault ( ) ; }
if ( keyCode == 90 ) { e . preventDefault ( ) ; } } }
function canDo ( ) { if ( editor . undo _stack . length === 0 || editor . undo _index <= 1 ) { return false ; }
return true ; }
function canRedo ( ) { if ( editor . undo _index == editor . undo _stack . length ) { return false ; }
return true ; }
var last _html = null ; function saveStep ( snapshot ) { if ( ! editor . undo _stack || editor . undoing || editor . el . querySelector ( '.fr-marker' ) ) return false ; if ( typeof snapshot == 'undefined' ) { snapshot = editor . snapshot . get ( ) ; if ( ! editor . undo _stack [ editor . undo _index - 1 ] || ! editor . snapshot . equal ( editor . undo _stack [ editor . undo _index - 1 ] , snapshot ) ) { dropRedo ( ) ; editor . undo _stack . push ( snapshot ) ; editor . undo _index ++ ; if ( snapshot . html != last _html ) { editor . events . trigger ( 'contentChanged' ) ; last _html = snapshot . html ; } } }
else { dropRedo ( ) ; if ( editor . undo _index > 0 ) { editor . undo _stack [ editor . undo _index - 1 ] = snapshot ; }
else { editor . undo _stack . push ( snapshot ) ; editor . undo _index ++ ; } } }
function dropRedo ( ) { if ( ! editor . undo _stack || editor . undoing ) return false ; while ( editor . undo _stack . length > editor . undo _index ) { editor . undo _stack . pop ( ) ; } }
function _do ( ) { if ( editor . undo _index > 1 ) { editor . undoing = true ; var snapshot = editor . undo _stack [ -- editor . undo _index - 1 ] ; clearTimeout ( editor . _content _changed _timer ) ; editor . snapshot . restore ( snapshot ) ; last _html = snapshot . html ; editor . popups . hideAll ( ) ; editor . toolbar . enable ( ) ; editor . events . trigger ( 'contentChanged' ) ; editor . events . trigger ( 'commands.undo' ) ; editor . undoing = false ; } }
function _redo ( ) { if ( editor . undo _index < editor . undo _stack . length ) { editor . undoing = true ; var snapshot = editor . undo _stack [ editor . undo _index ++ ] ; clearTimeout ( editor . _content _changed _timer )
editor . snapshot . restore ( snapshot ) ; last _html = snapshot . html ; editor . popups . hideAll ( ) ; editor . toolbar . enable ( ) ; editor . events . trigger ( 'contentChanged' ) ; editor . events . trigger ( 'commands.redo' ) ; editor . undoing = false ; } }
function reset ( ) { last _html = ( editor . $wp ? editor . $el . html ( ) : editor . $oel . get ( 0 ) . outerHTML ) . replace ( / style=""/g , '' ) ; editor . undo _index = 0 ; editor . undo _stack = [ ] ; }
function _destroy ( ) { editor . undo _stack = [ ] ; }
function _init ( ) { reset ( ) ; editor . events . on ( 'initialized' , function ( ) { last _html = ( editor . $wp ? editor . $el . html ( ) : editor . $oel . get ( 0 ) . outerHTML ) . replace ( / style=""/g , '' ) ; } ) ; editor . events . on ( 'blur' , function ( ) { if ( ! editor . el . querySelector ( '.fr-dragging' ) ) { editor . undo . saveStep ( ) ; } } )
editor . events . on ( 'keydown' , _disableBrowserUndo ) ; editor . events . on ( 'destroy' , _destroy ) ; }
return { _init : _init , run : _do , redo : _redo , canDo : canDo , canRedo : canRedo , dropRedo : dropRedo , reset : reset , saveStep : saveStep } } ; $ . FE . ICON _TEMPLATES = { font _awesome : '<i class="fa fa-[NAME]" aria-hidden="true"></i>' , font _awesome _5 : '<i class="fas fa-[FA5NAME]" aria-hidden="true"></i>' , font _awesome _5r : '<i class="far fa-[FA5NAME]" aria-hidden="true"></i>' , font _awesome _5l : '<i class="fal fa-[FA5NAME]" aria-hidden="true"></i>' , font _awesome _5b : '<i class="fab fa-[FA5NAME]" aria-hidden="true"></i>' , text : '<span style="text-align: center;">[NAME]</span>' , image : '<img src=[SRC] alt=[ALT] />' , svg : '<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">[PATH]</svg>' , empty : ' ' }
$ . FE . ICONS = { bold : { NAME : 'bold' } , italic : { NAME : 'italic' } , underline : { NAME : 'underline' } , strikeThrough : { NAME : 'strikethrough' } , subscript : { NAME : 'subscript' } , superscript : { NAME : 'superscript' } , color : { NAME : 'tint' } , outdent : { NAME : 'outdent' } , indent : { NAME : 'indent' } , undo : { NAME : 'rotate-left' , FA5NAME : 'undo' } , redo : { NAME : 'rotate-right' , FA5NAME : 'redo' } , insertHR : { NAME : 'minus' } , clearFormatting : { NAME : 'eraser' } , selectAll : { NAME : 'mouse-pointer' } }
$ . FE . DefineIconTemplate = function ( name , options ) { $ . FE . ICON _TEMPLATES [ name ] = options ; }
$ . FE . DefineIcon = function ( name , options ) { $ . FE . ICONS [ name ] = options ; }
$ . extend ( $ . FE . DEFAULTS , { iconsTemplate : 'font_awesome' } ) ; $ . FE . MODULES . icon = function ( editor ) { function create ( command ) { var icon = null ; var info = $ . FE . ICONS [ command ] ; if ( typeof info != 'undefined' ) { var template = info . template || $ . FE . ICON _DEFAULT _TEMPLATE || editor . opts . iconsTemplate ; if ( template && template . apply ) { template = template . apply ( editor ) ; }
if ( ! info . FA5NAME ) { info . FA5NAME = info . NAME ; }
if ( template && ( template = $ . FE . ICON _TEMPLATES [ template ] ) ) { icon = template . replace ( /\[([a-zA-Z0-9]*)\]/g , function ( str , a1 ) { return ( a1 == 'NAME' ? ( info [ a1 ] || command ) : info [ a1 ] ) ; } ) ; } }
return ( icon || command ) ; }
function getTemplate ( command ) { var info = $ . FE . ICONS [ command ] ; var template = editor . opts . iconsTemplate ; if ( typeof info != 'undefined' ) { template = info . template || $ . FE . ICON _DEFAULT _TEMPLATE || editor . opts . iconsTemplate ; return template ; }
return template ; }
return { create : create , getTemplate : getTemplate } } ; $ . extend ( $ . FE . DEFAULTS , { tooltips : true } ) ; $ . FE . MODULES . tooltip = function ( editor ) { function hide ( ) { if ( editor . helpers . isMobile ( ) ) return false ; if ( editor . $tooltip ) editor . $tooltip . removeClass ( 'fr-visible' ) . css ( 'left' , '-3000px' ) . css ( 'position' , 'fixed' ) ; }
function to ( $el , above ) { if ( editor . helpers . isMobile ( ) ) return false ; if ( ! $el . data ( 'title' ) ) { $el . data ( 'title' , $el . attr ( 'title' ) ) ; }
if ( ! $el . data ( 'title' ) ) return false ; if ( ! editor . $tooltip ) _init ( ) ; $el . removeAttr ( 'title' ) ; editor . $tooltip . text ( editor . language . translate ( $el . data ( 'title' ) ) ) ; editor . $tooltip . addClass ( 'fr-visible' ) ; var left = $el . offset ( ) . left + ( $el . outerWidth ( ) - editor . $tooltip . outerWidth ( ) ) / 2 ; if ( left < 0 ) left = 0 ; if ( left + editor . $tooltip . outerWidth ( ) > $ ( editor . o _win ) . width ( ) ) { left = $ ( editor . o _win ) . width ( ) - editor . $tooltip . outerWidth ( ) ; }
if ( typeof above == 'undefined' ) above = editor . opts . toolbarBottom ; var top = ! above ? $el . offset ( ) . top + $el . outerHeight ( ) : $el . offset ( ) . top - editor . $tooltip . height ( ) ; editor . $tooltip . css ( 'position' , '' ) ; editor . $tooltip . css ( 'left' , left ) ; editor . $tooltip . css ( 'top' , Math . ceil ( top ) ) ; if ( $ ( editor . o _doc ) . find ( 'body:first' ) . css ( 'position' ) != 'static' ) { editor . $tooltip . css ( 'margin-left' , - $ ( editor . o _doc ) . find ( 'body:first' ) . offset ( ) . left ) ; editor . $tooltip . css ( 'margin-top' , - $ ( editor . o _doc ) . find ( 'body:first' ) . offset ( ) . top ) ; }
else { editor . $tooltip . css ( 'margin-left' , '' ) ; editor . $tooltip . css ( 'margin-top' , '' ) ; } }
function bind ( $el , selector , above ) { if ( editor . opts . tooltips && ! editor . helpers . isMobile ( ) ) { editor . events . $on ( $el , 'mouseenter' , selector , function ( e ) { if ( ! editor . node . hasClass ( e . currentTarget , 'fr-disabled' ) && ! editor . edit . isDisabled ( ) ) { to ( $ ( e . currentTarget ) , above ) ; } } , true ) ; editor . events . $on ( $el , 'mouseleave ' + editor . _mousedown + ' ' + editor . _mouseup , selector , function ( ) { hide ( ) ; } , true ) ; } }
function _init ( ) { if ( editor . opts . tooltips && ! editor . helpers . isMobile ( ) ) { if ( ! editor . shared . $tooltip ) { editor . shared . $tooltip = $ ( '<div class="fr-tooltip"></div>' ) ; editor . $tooltip = editor . shared . $tooltip ; if ( editor . opts . theme ) { editor . $tooltip . addClass ( editor . opts . theme + '-theme' ) ; }
$ ( editor . o _doc ) . find ( 'body:first' ) . append ( editor . $tooltip ) ; }
else { editor . $tooltip = editor . shared . $tooltip ; }
editor . events . on ( 'shared.destroy' , function ( ) { editor . $tooltip . html ( '' ) . removeData ( ) . remove ( ) ; editor . $tooltip = null ; } , true ) ; } }
return { hide : hide , to : to , bind : bind } } ; $ . FE . MODULES . button = function ( editor ) { var buttons = [ ] ; if ( editor . opts . toolbarInline || editor . opts . toolbarContainer ) { if ( ! editor . shared . buttons ) editor . shared . buttons = [ ] ; buttons = editor . shared . buttons ; }
var popup _buttons = [ ] ; if ( ! editor . shared . popup _buttons ) editor . shared . popup _buttons = [ ] ; popup _buttons = editor . shared . popup _buttons ; function _filterButtons ( butons _list , selector , search _dropdowns ) { var $filtered _buttons = $ ( ) ; for ( var i = 0 ; i < butons _list . length ; i ++ ) { var $button = $ ( butons _list [ i ] ) ; if ( $button . is ( selector ) ) { $filtered _buttons = $filtered _buttons . add ( $button ) ; }
if ( search _dropdowns && $button . is ( '.fr-dropdown' ) ) { var $dropdown _menu _items = $button . next ( ) . find ( selector ) ; $filtered _buttons = $filtered _buttons . add ( $dropdown _menu _items ) ; } }
return $filtered _buttons ; }
function getButtons ( selector , search _dropdowns ) { var $buttons = $ ( ) ; var id ; if ( ! selector ) { return $buttons ; }
$buttons = $buttons . add ( _filterButtons ( buttons , selector , search _dropdowns ) ) ; $buttons = $buttons . add ( _filterButtons ( popup _buttons , selector , search _dropdowns ) ) ; for ( id in editor . shared . popups ) { if ( editor . shared . popups . hasOwnProperty ( id ) ) { var $popup = editor . shared . popups [ id ] ; var $popup _buttons = $popup . children ( ) . find ( selector ) ; $buttons = $buttons . add ( $popup _buttons ) ; } }
for ( id in editor . shared . modals ) { if ( editor . shared . modals . hasOwnProperty ( id ) ) { var $modal _hash = editor . shared . modals [ id ] ; var $modal _buttons = $modal _hash . $modal . find ( selector ) ; $buttons = $buttons . add ( $modal _buttons ) ; } }
return $buttons ; }
function _dropdownButtonClick ( $btn ) { var $dropdown = $btn . next ( ) ; var active = editor . node . hasClass ( $btn . get ( 0 ) , 'fr-active' ) ; var $active _dropdowns = getButtons ( '.fr-dropdown.fr-active' ) . not ( $btn ) ; var inst = $btn . parents ( '.fr-toolbar, .fr-popup' ) . data ( 'instance' ) || editor ; if ( inst . helpers . isIOS ( ) && ! inst . el . querySelector ( '.fr-marker' ) ) { inst . selection . save ( ) ; inst . selection . clear ( ) ; inst . selection . restore ( ) ; }
if ( ! active ) { var cmd = $btn . data ( 'cmd' ) ; $dropdown . find ( '.fr-command' ) . removeClass ( 'fr-active' ) . attr ( 'aria-selected' , false ) ; if ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . refreshOnShow ) { $ . FE . COMMANDS [ cmd ] . refreshOnShow . apply ( inst , [ $btn , $dropdown ] ) ; }
$dropdown . css ( 'left' , $btn . offset ( ) . left - $btn . parent ( ) . offset ( ) . left - ( editor . opts . direction == 'rtl' ? $dropdown . width ( ) - $btn . outerWidth ( ) : 0 ) ) ; $dropdown . addClass ( 'test-height' )
var ht = $dropdown . outerHeight ( ) ; $dropdown . removeClass ( 'test-height' )
$dropdown . css ( 'top' , '' ) . css ( 'bottom' , '' ) ; if ( ! editor . opts . toolbarBottom && ( $dropdown . offset ( ) . top + $btn . outerHeight ( ) + ht < $ ( editor . o _doc ) . height ( ) ) ) { $dropdown . css ( 'top' , $btn . position ( ) . top + $btn . outerHeight ( ) ) ; }
else { $dropdown . css ( 'bottom' , $btn . parents ( '.fr-popup, .fr-toolbar' ) . first ( ) . height ( ) - $btn . position ( ) . top ) ; } }
$btn . addClass ( 'fr-blink' ) . toggleClass ( 'fr-active' ) ; if ( $btn . hasClass ( 'fr-options' ) ) { $btn . prev ( ) . toggleClass ( 'fr-expanded' ) ; }
if ( $btn . hasClass ( 'fr-active' ) ) { $dropdown . attr ( 'aria-hidden' , false ) ; $btn . attr ( 'aria-expanded' , true ) ; }
else { $dropdown . attr ( 'aria-hidden' , true ) ; $btn . attr ( 'aria-expanded' , false ) ; }
setTimeout ( function ( ) { $btn . removeClass ( 'fr-blink' ) ; } , 300 ) ; $dropdown . css ( 'margin-left' , '' ) ; if ( $dropdown . offset ( ) . left + $dropdown . outerWidth ( ) > editor . $sc . offset ( ) . left + editor . $sc . width ( ) ) { $dropdown . css ( 'margin-left' , - ( $dropdown . offset ( ) . left + $dropdown . outerWidth ( ) - editor . $sc . offset ( ) . left - editor . $sc . width ( ) ) ) }
if ( $dropdown . offset ( ) . left < editor . $sc . offset ( ) . left && editor . opts . direction == 'rtl' ) { $dropdown . css ( 'margin-left' , editor . $sc . offset ( ) . left ) ; }
$active _dropdowns . removeClass ( 'fr-active' ) . attr ( 'aria-expanded' , false ) . next ( ) . attr ( 'aria-hidden' , true ) ; $active _dropdowns . prev ( '.fr-expanded' ) . removeClass ( 'fr-expanded' ) ; $active _dropdowns . parent ( '.fr-toolbar:not(.fr-inline)' ) . css ( 'zIndex' , '' ) ; if ( $btn . parents ( '.fr-popup' ) . length === 0 && ! editor . opts . toolbarInline ) { if ( editor . node . hasClass ( $btn . get ( 0 ) , 'fr-active' ) ) { editor . $tb . css ( 'zIndex' , ( editor . opts . zIndex || 1 ) + 4 ) ; }
else { editor . $tb . css ( 'zIndex' , '' ) ; } }
var $active _element = $dropdown . find ( 'a.fr-command.fr-active:first' ) ; if ( ! editor . helpers . isMobile ( ) ) { if ( $active _element . length ) { editor . accessibility . focusToolbarElement ( $active _element ) ; }
else { editor . accessibility . focusToolbarElement ( $btn ) ; } } }
function exec ( $btn ) { $btn . addClass ( 'fr-blink' ) ; setTimeout ( function ( ) { $btn . removeClass ( 'fr-blink' ) ; } , 500 ) ; var cmd = $btn . data ( 'cmd' ) ; var params = [ ] ; while ( typeof $btn . data ( 'param' + ( params . length + 1 ) ) != 'undefined' ) { params . push ( $btn . data ( 'param' + ( params . length + 1 ) ) ) ; }
var $active _dropdowns = getButtons ( '.fr-dropdown.fr-active' ) ; if ( $active _dropdowns . length ) { $active _dropdowns . removeClass ( 'fr-active' ) . attr ( 'aria-expanded' , false ) . next ( ) . attr ( 'aria-hidden' , true ) ; $active _dropdowns . prev ( '.fr-expanded' ) . removeClass ( 'fr-expanded' ) ; $active _dropdowns . parent ( '.fr-toolbar:not(.fr-inline)' ) . css ( 'zIndex' , '' ) ; }
$btn . parents ( '.fr-popup, .fr-toolbar' ) . data ( 'instance' ) . commands . exec ( cmd , params ) ; }
function _commandButtonClick ( $btn ) { exec ( $btn ) ; }
function click ( $btn ) { var inst = $btn . parents ( '.fr-popup, .fr-toolbar' ) . data ( 'instance' ) ; if ( $btn . parents ( '.fr-popup' ) . length === 0 && ! $btn . data ( 'popup' ) ) { inst . popups . hideAll ( ) ; }
if ( inst . popups . areVisible ( ) && ! inst . popups . areVisible ( inst ) ) { for ( var i = 0 ; i < $ . FE . INSTANCES . length ; i ++ ) { if ( $ . FE . INSTANCES [ i ] != inst && $ . FE . INSTANCES [ i ] . popups && $ . FE . INSTANCES [ i ] . popups . areVisible ( ) ) { $ . FE . INSTANCES [ i ] . $el . find ( '.fr-marker' ) . remove ( ) ; } }
inst . popups . hideAll ( ) ; }
if ( editor . node . hasClass ( $btn . get ( 0 ) , 'fr-dropdown' ) ) { _dropdownButtonClick ( $btn ) ; }
else { _commandButtonClick ( $btn ) ; if ( $ . FE . COMMANDS [ $btn . data ( 'cmd' ) ] && $ . FE . COMMANDS [ $btn . data ( 'cmd' ) ] . refreshAfterCallback !== false ) { inst . button . bulkRefresh ( ) ; } } }
function _click ( e ) { var $btn = $ ( e . currentTarget ) ; click ( $btn ) ; }
function hideActiveDropdowns ( $el ) { var $active _dropdowns = $el . find ( '.fr-dropdown.fr-active' ) ; if ( $active _dropdowns . length ) { $active _dropdowns . removeClass ( 'fr-active' ) . attr ( 'aria-expanded' , false ) . next ( ) . attr ( 'aria-hidden' , true ) ; $active _dropdowns . parent ( '.fr-toolbar:not(.fr-inline)' ) . css ( 'zIndex' , '' ) ; $active _dropdowns . prev ( ) . removeClass ( 'fr-expanded' ) } }
function _dropdownMenuClick ( e ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
function _dropdownWrapperClick ( e ) { e . stopPropagation ( ) ; if ( ! editor . helpers . isMobile ( ) ) { return false ; } }
function bindCommands ( $el , tooltipAbove ) { editor . events . bindClick ( $el , '.fr-command:not(.fr-disabled)' , _click ) ; editor . events . $on ( $el , editor . _mousedown + ' ' + editor . _mouseup + ' ' + editor . _move , '.fr-dropdown-menu' , _dropdownMenuClick , true ) ; editor . events . $on ( $el , editor . _mousedown + ' ' + editor . _mouseup + ' ' + editor . _move , '.fr-dropdown-menu .fr-dropdown-wrapper' , _dropdownWrapperClick , true ) ; var _document = $el . get ( 0 ) . ownerDocument ; var _window = 'defaultView' in _document ? _document . defaultView : _document . parentWindow ; var hideDropdowns = function ( e ) { if ( ! e || ( e . type == editor . _mouseup && e . target != $ ( 'html' ) . get ( 0 ) ) || ( e . type == 'keydown' && ( ( editor . keys . isCharacter ( e . which ) && ! editor . keys . ctrlKey ( e ) ) || e . which == $ . FE . KEYCODE . ESC ) ) ) { hideActiveDropdowns ( $el ) ; } }
editor . events . $on ( $ ( _window ) , editor . _mouseup + ' resize keydown' , hideDropdowns , true ) ; if ( editor . opts . iframe ) { editor . events . $on ( editor . $win , editor . _mouseup , hideDropdowns , true ) ; }
if ( editor . node . hasClass ( $el . get ( 0 ) , 'fr-popup' ) ) { $ . merge ( popup _buttons , $el . find ( '.fr-btn' ) . toArray ( ) ) ; }
else { $ . merge ( buttons , $el . find ( '.fr-btn' ) . toArray ( ) ) ; }
editor . tooltip . bind ( $el , '.fr-btn, .fr-title' , tooltipAbove ) ; }
function _content ( command , info ) { var c = '' ; if ( info . html ) { if ( typeof info . html == 'function' ) { c += info . html . call ( editor ) ; }
else { c += info . html ; } }
else { var options = info . options ; if ( typeof options == 'function' ) options = options ( ) ; c += '<ul class="fr-dropdown-list" role="presentation">' ; for ( var val in options ) { if ( options . hasOwnProperty ( val ) ) { var shortcut = editor . shortcuts . get ( command + '.' + val ) ; if ( shortcut ) { shortcut = '<span class="fr-shortcut">' + shortcut + '</span>' ; }
else { shortcut = '' ; }
c += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="' + ( info . type === 'options' ? command . replace ( /Options/g , '' ) : command ) + '" data-param1="' + val + '" title="' + options [ val ] + '">' + editor . language . translate ( options [ val ] ) + '</a></li>' ; } }
c += '</ul>' ; }
return c ; }
function _build ( command , info , visible ) { info = $ . extend ( true , { } , info ) ; if ( editor . helpers . isMobile ( ) && info . showOnMobile === false ) return '' ; var display _selection = info . displaySelection ; if ( typeof display _selection == 'function' ) { display _selection = display _selection ( editor ) ; }
var icon = '' ; if ( info . type !== 'options' ) { if ( display _selection ) { var default _selection = ( typeof info . defaultSelection == 'function' ? info . defaultSelection ( editor ) : info . defaultSelection ) ; icon = '<span style="width:' + ( info . displaySelectionWidth || 100 ) + 'px">' + editor . language . translate ( default _selection || info . title ) + '</span>' ; }
else { icon = editor . icon . create ( info . icon || command ) ; icon += '<span class="fr-sr-only">' + ( editor . language . translate ( info . title ) || '' ) + '</span>' ; } }
var popup = info . popup ? ' data-popup="true"' : '' ; var modal = info . modal ? ' data-modal="true"' : '' ; var shortcut = editor . shortcuts . get ( command + '.' ) ; if ( shortcut ) { shortcut = ' (' + shortcut + ')' ; }
else { shortcut = '' ; }
var button _id = command + '-' + editor . id ; var dropdown _id = 'dropdown-menu-' + button _id ; var btn = '<button id="' + button _id + '"type="button" tabIndex="-1" role="button"' + ( info . toggle ? ' aria-pressed="false"' : '' ) + ( info . type == 'dropdown' || info . type == 'options' ? ' aria-controls="' + dropdown _id + '" aria-expanded="false" aria-haspopup="true"' : '' ) + ( info . disabled ? ' aria-disabled="true"' : '' ) + ' title="' + ( editor . language . translate ( info . title ) || '' ) + shortcut + '" class="fr-command fr-btn' + ( info . type == 'dropdown' || info . type == 'options' ? ' fr-dropdown' : '' ) + ( info . type == 'options' ? ' fr-options' : '' ) + ( ' fr-btn-' + editor . icon . getTemplate ( info . icon ) ) + ( info . displaySelection ? ' fr-selection' : '' ) + ( info . back ? ' fr-back' : '' ) + ( info . disabled ? ' fr-disabled' : '' ) + ( ! visible ? ' fr-hidden' : '' ) + '" data-cmd="' + command + '"' + popup + modal + '>' + icon + '</button>' ; if ( info . type == 'dropdown' || info . type == 'options' ) { var dropdown = '<div id="' + dropdown _id + '" class="fr-dropdown-menu" role="listbox" aria-labelledby="' + button _id + '" aria-hidden="true"><div class="fr-dropdown-wrapper" role="presentation"><div class="fr-dropdown-content" role="presentation">' ; dropdown += _content ( command , info ) ; dropdown += '</div></div></div>' ; btn += dropdown ; }
if ( info . hasOptions && info . hasOptions . apply ( editor ) ) { info . type = 'options' ; info . hasOptions = false ; btn = '<div class="fr-btn-wrap">' + btn + _build ( command + 'Options' , info , visible ) + '</div>' ; }
return btn ; }
function buildList ( buttons , visible _buttons ) { var str = '' ; for ( var i = 0 ; i < buttons . length ; i ++ ) { var cmd _name = buttons [ i ] ; var cmd _info = $ . FE . COMMANDS [ cmd _name ] ; if ( cmd _info && typeof cmd _info . plugin !== 'undefined' && editor . opts . pluginsEnabled . indexOf ( cmd _info . plugin ) < 0 ) continue ; if ( cmd _info ) { var visible = typeof visible _buttons != 'undefined' ? visible _buttons . indexOf ( cmd _name ) >= 0 : true ; str += _build ( cmd _name , cmd _info , visible ) ; }
else if ( cmd _name == '|' ) { str += '<div class="fr-separator fr-vs" role="separator" aria-orientation="vertical"></div>' ; }
else if ( cmd _name == '-' ) { str += '<div class="fr-separator fr-hs" role="separator" aria-orientation="horizontal"></div>' ; } }
return str ; }
function refresh ( $btn ) { var inst = $btn . parents ( '.fr-popup, .fr-toolbar' ) . data ( 'instance' ) || editor ; var cmd = $btn . data ( 'cmd' ) ; var $dropdown ; if ( ! editor . node . hasClass ( $btn . get ( 0 ) , 'fr-dropdown' ) ) { $btn . removeClass ( 'fr-active' ) ; if ( $btn . attr ( 'aria-pressed' ) ) $btn . attr ( 'aria-pressed' , false ) ; }
else { $dropdown = $btn . next ( ) ; }
if ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . refresh ) { $ . FE . COMMANDS [ cmd ] . refresh . apply ( inst , [ $btn , $dropdown ] ) ; }
else if ( editor . refresh [ cmd ] ) { inst . refresh [ cmd ] ( $btn , $dropdown ) ; } }
function _bulkRefresh ( btns ) { var inst = editor . $tb ? ( editor . $tb . data ( 'instance' ) || editor ) : editor ; if ( editor . events . trigger ( 'buttons.refresh' ) === false ) return true ; setTimeout ( function ( ) { var focused = ( inst . selection . inEditor ( ) && inst . core . hasFocus ( ) ) ; for ( var i = 0 ; i < btns . length ; i ++ ) { var $btn = $ ( btns [ i ] ) ; var cmd = $btn . data ( 'cmd' ) ; if ( $btn . parents ( '.fr-popup' ) . length === 0 ) { if ( focused || ( $ . FE . COMMANDS [ cmd ] && $ . FE . COMMANDS [ cmd ] . forcedRefresh ) ) { inst . button . refresh ( $btn ) ; }
else { if ( ! editor . node . hasClass ( $btn . get ( 0 ) , 'fr-dropdown' ) ) { $btn . removeClass ( 'fr-active' ) ; if ( $btn . attr ( 'aria-pressed' ) ) $btn . attr ( 'aria-pressed' , false ) ; } } }
else if ( $btn . parents ( '.fr-popup' ) . is ( ':visible' ) ) { inst . button . refresh ( $btn ) ; } } } , 0 ) ; }
function bulkRefresh ( ) { _bulkRefresh ( buttons ) ; _bulkRefresh ( popup _buttons ) ; }
function _destroy ( ) { buttons = [ ] ; popup _buttons = [ ] ; }
var refresh _timeout = null ; function delayedBulkRefresh ( ) { clearTimeout ( refresh _timeout ) ; refresh _timeout = setTimeout ( bulkRefresh , 50 ) ; }
function _init ( ) { if ( editor . opts . toolbarInline ) { editor . events . on ( 'toolbar.show' , bulkRefresh ) ; }
else { editor . events . on ( 'mouseup' , delayedBulkRefresh ) ; editor . events . on ( 'keyup' , delayedBulkRefresh ) ; editor . events . on ( 'blur' , delayedBulkRefresh ) ; editor . events . on ( 'focus' , delayedBulkRefresh ) ; editor . events . on ( 'contentChanged' , delayedBulkRefresh ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $doc , 'selectionchange' , bulkRefresh ) ; } }
editor . events . on ( 'shared.destroy' , _destroy ) ; }
return { _init : _init , buildList : buildList , bindCommands : bindCommands , refresh : refresh , bulkRefresh : bulkRefresh , exec : exec , click : click , hideActiveDropdowns : hideActiveDropdowns , getButtons : getButtons } } ; $ . FE . MODULES . modals = function ( editor ) { if ( ! editor . shared . modals ) editor . shared . modals = { } ; var modals = editor . shared . modals ; var $overlay ; function get ( id ) { return modals [ id ] ; }
function _modalHTML ( head , body ) { var html = '<div tabIndex="-1" class="fr-modal' + ( editor . opts . theme ? ' ' + editor . opts . theme + '-theme' : '' ) + '"><div class="fr-modal-wrapper">' ; var close _button = '<span title="' + editor . language . translate ( 'Cancel' ) + '" class="fr-modal-close">×</span>' ; html += '<div class="fr-modal-head">' + head + close _button + '</div>' ; html += '<div tabIndex="-1" class="fr-modal-body">' + body + '</div>' ; html += '</div></div>' ; return $ ( html ) ; }
function create ( id , head , body ) { if ( ! editor . shared . $overlay ) { editor . shared . $overlay = $ ( '<div class="fr-overlay">' ) . appendTo ( 'body:first' ) ; }
$overlay = editor . shared . $overlay ; if ( editor . opts . theme ) { $overlay . addClass ( editor . opts . theme + '-theme' ) ; }
if ( ! modals [ id ] ) { var $modal = _modalHTML ( head , body ) ; modals [ id ] = { $modal : $modal , $head : $modal . find ( '.fr-modal-head' ) , $body : $modal . find ( '.fr-modal-body' ) } ; if ( ! editor . helpers . isMobile ( ) ) { $modal . addClass ( 'fr-desktop' ) ; }
$modal . appendTo ( 'body:first' ) ; editor . events . $on ( $modal , 'click' , '.fr-modal-close' , function ( ) { hide ( id ) ; } , true ) ; modals [ id ] . $body . css ( 'margin-top' , modals [ id ] . $head . outerHeight ( ) ) ; editor . events . $on ( $modal , 'keydown' , function ( e ) { var keycode = e . which ; if ( keycode == $ . FE . KEYCODE . ESC ) { hide ( id ) ; editor . accessibility . focusModalButton ( $modal ) ; return false ; }
else if ( ! $ ( e . target ) . is ( 'input[type=text], textarea' ) && keycode != $ . FE . KEYCODE . ARROW _UP && keycode != $ . FE . KEYCODE . ARROW _DOWN && ! editor . keys . isBrowserAction ( e ) ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; return false ; }
else { return true ; } } , true ) ; hide ( id , true ) ; }
return modals [ id ] ; }
function destroy ( ) { for ( var i in modals ) { var modalHash = modals [ i ] ; modalHash && modalHash . $modal && modalHash . $modal . removeData ( ) . remove ( ) ; }
$overlay && $overlay . removeData ( ) . remove ( ) ; modals = { } ; }
function show ( id ) { if ( ! modals [ id ] ) { return ; }
var $modal = modals [ id ] . $modal ; $modal . data ( 'instance' , editor ) ; $modal . show ( ) ; $overlay . show ( ) ; $ ( editor . o _doc ) . find ( 'body:first' ) . addClass ( 'prevent-scroll' ) ; if ( editor . helpers . isMobile ( ) ) { $ ( editor . o _doc ) . find ( 'body:first' ) . addClass ( 'fr-mobile' ) ; }
$modal . addClass ( 'fr-active' ) ; editor . accessibility . focusModal ( $modal ) ; }
function hide ( id , init ) { if ( ! modals [ id ] ) { return ; }
var $modal = modals [ id ] . $modal ; var inst = $modal . data ( 'instance' ) || editor
inst . events . enableBlur ( ) ; $modal . hide ( ) ; $overlay . hide ( ) ; $ ( inst . o _doc ) . find ( 'body:first' ) . removeClass ( 'prevent-scroll fr-mobile' ) ; $modal . removeClass ( 'fr-active' ) ; if ( ! init ) { inst . accessibility . restoreSelection ( ) ; inst . events . trigger ( 'modals.hide' ) ; } }
function resize ( id ) { if ( ! modals [ id ] ) { return ; }
var modalHash = modals [ id ] ; var $modal = modalHash . $modal ; var $body = modalHash . $body ; var height = $ ( editor . o _win ) . height ( ) ; var $wrapper = $modal . find ( '.fr-modal-wrapper' ) ; var allWrapperHeight = $wrapper . outerHeight ( true ) ; var exteriorBodyHeight = $wrapper . height ( ) - ( $body . outerHeight ( true ) - $body . height ( ) ) ; var maxHeight = height - allWrapperHeight + exteriorBodyHeight ; var body _content _height = $body . get ( 0 ) . scrollHeight ; var newHeight = 'auto' ; if ( body _content _height > maxHeight ) { newHeight = maxHeight ; }
$body . height ( newHeight ) ; }
function isVisible ( id ) { var $modal ; if ( typeof id === 'string' ) { if ( ! modals [ id ] ) { return ; }
$modal = modals [ id ] . $modal }
else { $modal = id ; }
return ( $modal && editor . node . hasClass ( $modal , 'fr-active' ) && editor . core . sameInstance ( $modal ) ) || false ; }
function areVisible ( new _instance ) { for ( var id in modals ) { if ( modals . hasOwnProperty ( id ) ) { if ( isVisible ( id ) && ( typeof new _instance == 'undefined' || modals [ id ] . $modal . data ( 'instance' ) == new _instance ) ) return modals [ id ] . $modal ; } }
return false ; }
function _init ( ) { editor . events . on ( 'shared.destroy' , destroy , true ) ; }
return { _init : _init , get : get , create : create , show : show , hide : hide , resize : resize , isVisible : isVisible , areVisible : areVisible } } ; $ . FE . POPUP _TEMPLATES = { 'text.edit' : '[_EDIT_]' } ; $ . FE . RegisterTemplate = function ( name , template ) { $ . FE . POPUP _TEMPLATES [ name ] = template ; }
$ . FE . MODULES . popups = function ( editor ) { if ( ! editor . shared . popups ) editor . shared . popups = { } ; var popups = editor . shared . popups ; function setContainer ( id , $container ) { if ( ! $container . is ( ':visible' ) ) $container = editor . $sc ; if ( ! $container . is ( popups [ id ] . data ( 'container' ) ) ) { popups [ id ] . data ( 'container' , $container ) ; $container . append ( popups [ id ] ) ; } }
function refreshContainer ( id , $container ) { if ( ! $container . is ( ':visible' ) ) $container = editor . $sc ; if ( $container . find ( [ popups [ id ] ] ) . length === 0 ) { $container . append ( popups [ id ] ) ; } }
function show ( id , left , top , obj _height ) { if ( ! isVisible ( id ) ) { if ( areVisible ( ) && editor . $el . find ( '.fr-marker' ) . length > 0 ) { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; }
else if ( ! areVisible ( ) ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; editor . events . enableBlur ( ) ; } }
hideAll ( [ id ] ) ; if ( ! popups [ id ] ) return false ; var $active _dropdowns = editor . button . getButtons ( '.fr-dropdown.fr-active' ) ; $active _dropdowns . removeClass ( 'fr-active' ) . attr ( 'aria-expanded' , false ) . parent ( '.fr-toolbar' ) . css ( 'zIndex' , '' ) ; $active _dropdowns . next ( ) . attr ( 'aria-hidden' , true ) ; popups [ id ] . data ( 'instance' , editor ) ; if ( editor . $tb ) editor . $tb . data ( 'instance' , editor ) ; var width = popups [ id ] . outerWidth ( ) ; var is _visible = isVisible ( id ) ; popups [ id ] . addClass ( 'fr-active' ) . removeClass ( 'fr-hidden' ) . find ( 'input, textarea' ) . removeAttr ( 'disabled' ) ; var $container = popups [ id ] . data ( 'container' ) ; refreshContainer ( id , $container ) ; if ( editor . opts . toolbarInline && $container && editor . $tb && $container . get ( 0 ) == editor . $tb . get ( 0 ) ) { setContainer ( id , editor . $sc ) ; top = editor . $tb . offset ( ) . top - editor . helpers . getPX ( editor . $tb . css ( 'margin-top' ) ) ; left = editor . $tb . offset ( ) . left + editor . $tb . outerWidth ( ) / 2 + ( parseFloat ( editor . $tb . find ( '.fr-arrow' ) . css ( 'margin-left' ) ) || 0 ) + editor . $tb . find ( '.fr-arrow' ) . outerWidth ( ) / 2 ; if ( editor . node . hasClass ( editor . $tb . get ( 0 ) , 'fr-above' ) && top ) { top += editor . $tb . outerHeight ( ) ; }
obj _height = 0 ; }
$container = popups [ id ] . data ( 'container' ) ; if ( editor . opts . iframe && ! obj _height && ! is _visible ) { if ( left ) left -= editor . $iframe . offset ( ) . left ; if ( top ) top -= editor . $iframe . offset ( ) . top ; }
if ( $container . is ( editor . $tb ) ) { editor . $tb . css ( 'zIndex' , ( editor . opts . zIndex || 1 ) + 4 ) ; }
else { popups [ id ] . css ( 'zIndex' , ( editor . opts . zIndex || 1 ) + 4 ) ; }
if ( left ) left = left - width / 2 ; if ( editor . opts . toolbarBottom && $container && editor . $tb && $container . get ( 0 ) == editor . $tb . get ( 0 ) ) { popups [ id ] . addClass ( 'fr-above' ) ; if ( top ) top = top - popups [ id ] . outerHeight ( ) ; }
popups [ id ] . removeClass ( 'fr-active' ) ; editor . position . at ( left , top , popups [ id ] , obj _height || 0 ) ; popups [ id ] . addClass ( 'fr-active' ) ; if ( ! is _visible ) { editor . accessibility . focusPopup ( popups [ id ] ) ; }
if ( editor . opts . toolbarInline ) editor . toolbar . hide ( ) ; editor . events . trigger ( 'popups.show.' + id ) ; _events ( id ) . _repositionPopup ( ) ; _unmarkExit ( ) ; }
function onShow ( id , callback ) { editor . events . on ( 'popups.show.' + id , callback ) ; }
function isVisible ( id ) { return ( popups [ id ] && editor . node . hasClass ( popups [ id ] , 'fr-active' ) && editor . core . sameInstance ( popups [ id ] ) ) || false ; }
function areVisible ( new _instance ) { for ( var id in popups ) { if ( popups . hasOwnProperty ( id ) ) { if ( isVisible ( id ) && ( typeof new _instance == 'undefined' || popups [ id ] . data ( 'instance' ) == new _instance ) ) return popups [ id ] ; } }
return false ; }
function hide ( id ) { var $popup = null ; if ( typeof id !== 'string' ) { $popup = id ; }
else { $popup = popups [ id ] ; }
if ( $popup && editor . node . hasClass ( $popup , 'fr-active' ) ) { $popup . removeClass ( 'fr-active fr-above' ) ; editor . events . trigger ( 'popups.hide.' + id ) ; if ( editor . $tb ) { if ( editor . opts . zIndex > 1 ) { editor . $tb . css ( 'zIndex' , editor . opts . zIndex + 1 ) ; }
else { editor . $tb . css ( 'zIndex' , '' ) ; } }
editor . events . disableBlur ( ) ; $popup . find ( 'input, textarea, button' ) . filter ( ':focus' ) . blur ( ) ; $popup . find ( 'input, textarea' ) . attr ( 'disabled' , 'disabled' ) ; } }
function onHide ( id , callback ) { editor . events . on ( 'popups.hide.' + id , callback ) ; }
function get ( id ) { var $popup = popups [ id ] ; if ( $popup && ! $popup . data ( 'inst' + editor . id ) ) { var ev = _events ( id ) ; _bindInstanceEvents ( ev , id ) ; }
return $popup ; }
function onRefresh ( id , callback ) { editor . events . on ( 'popups.refresh.' + id , callback ) ; }
function refresh ( id ) { popups [ id ] . data ( 'instance' , editor ) ; editor . events . trigger ( 'popups.refresh.' + id ) ; var btns = popups [ id ] . find ( '.fr-command' ) ; for ( var i = 0 ; i < btns . length ; i ++ ) { var $btn = $ ( btns [ i ] ) ; if ( $btn . parents ( '.fr-dropdown-menu' ) . length === 0 ) { editor . button . refresh ( $btn ) ; } } }
function hideAll ( except ) { if ( typeof except == 'undefined' ) except = [ ] ; for ( var id in popups ) { if ( popups . hasOwnProperty ( id ) ) { if ( except . indexOf ( id ) < 0 ) { hide ( id ) ; } } } }
editor . shared . exit _flag = false ; function _markExit ( ) { editor . shared . exit _flag = true ; }
function _unmarkExit ( ) { editor . shared . exit _flag = false ; }
function _canExit ( ) { return editor . shared . exit _flag ; }
function _buildTemplate ( id , template ) { var html = $ . FE . POPUP _TEMPLATES [ id ] ; if ( ! html ) return null ; if ( typeof html == 'function' ) html = html . apply ( editor ) ; for ( var nm in template ) { if ( template . hasOwnProperty ( nm ) ) { html = html . replace ( '[_' + nm . toUpperCase ( ) + '_]' , template [ nm ] ) ; } }
return html ; }
function _build ( id , template ) { var $popup ; var $container ; var html = _buildTemplate ( id , template ) ; if ( ! html ) { $popup = $ ( '<div class="fr-popup fr-empty"></div>' ) ; $container = $ ( 'body:first' ) ; $container . append ( $popup ) ; $popup . data ( 'container' , $container ) ; popups [ id ] = $popup ; return $popup ; }
$popup = $ ( '<div class="fr-popup' + ( editor . helpers . isMobile ( ) ? ' fr-mobile' : ' fr-desktop' ) + ( editor . opts . toolbarInline ? ' fr-inline' : '' ) + '"><span class="fr-arrow"></span>' + html + '</div>' ) ; if ( editor . opts . theme ) { $popup . addClass ( editor . opts . theme + '-theme' ) ; }
if ( editor . opts . zIndex > 1 ) { if ( ! editor . opts . editInPopup ) { editor . $tb . css ( 'z-index' , editor . opts . zIndex + 2 ) ; }
else { $popup . css ( 'z-index' , editor . opts . zIndex + 2 ) ; } }
if ( editor . opts . direction != 'auto' ) { $popup . removeClass ( 'fr-ltr fr-rtl' ) . addClass ( 'fr-' + editor . opts . direction ) ; }
$popup . find ( 'input, textarea' ) . attr ( 'dir' , editor . opts . direction ) . attr ( 'disabled' , 'disabled' ) ; $container = $ ( 'body:first' ) ; $container . append ( $popup ) ; $popup . data ( 'container' , $container ) ; popups [ id ] = $popup ; editor . button . bindCommands ( $popup , false ) ; return $popup ; }
function _events ( id ) { var $popup = popups [ id ] ; return { _windowResize : function ( ) { var inst = $popup . data ( 'instance' ) || editor ; if ( ! inst . helpers . isMobile ( ) && $popup . is ( ':visible' ) ) { inst . events . disableBlur ( ) ; inst . popups . hide ( id ) ; inst . events . enableBlur ( ) ; } } , _inputFocus : function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; var $target = $ ( e . currentTarget ) ; if ( $target . is ( 'input:file' ) ) { $target . closest ( '.fr-layer' ) . addClass ( 'fr-input-focus' ) ; }
e . preventDefault ( ) ; e . stopPropagation ( ) ; setTimeout ( function ( ) { inst . events . enableBlur ( ) ; } , editor . browser . msie ? 100 : 0 ) ; if ( inst . helpers . isMobile ( ) ) { var t = $ ( inst . o _win ) . scrollTop ( ) ; setTimeout ( function ( ) { $ ( inst . o _win ) . scrollTop ( t ) ; } , 0 ) ; } } , _inputBlur : function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; var $target = $ ( e . currentTarget ) ; if ( $target . is ( 'input:file' ) ) { $target . closest ( '.fr-layer' ) . removeClass ( 'fr-input-focus' ) ; }
if ( document . activeElement != this && $ ( this ) . is ( ':visible' ) ) { if ( inst . events . blurActive ( ) ) { inst . events . trigger ( 'blur' ) ; }
inst . events . enableBlur ( ) ; } } , _editorKeydown : function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; if ( ! inst . keys . ctrlKey ( e ) && e . which != $ . FE . KEYCODE . ALT && e . which != $ . FE . KEYCODE . ESC ) { if ( isVisible ( id ) && $popup . find ( '.fr-back:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-back:visible:first' ) ) }
else { if ( e . which != $ . FE . KEYCODE . ALT ) { inst . popups . hide ( id ) ; } } } } , _preventFocus : function ( e ) { var inst = $popup . data ( 'instance' ) || editor ; var originalTarget = e . originalEvent ? ( e . originalEvent . target || e . originalEvent . originalTarget ) : null ; if ( e . type != 'mouseup' && ! $ ( originalTarget ) . is ( ':focus' ) ) inst . events . disableBlur ( ) ; if ( e . type == 'mouseup' && ! ( $ ( originalTarget ) . hasClass ( 'fr-command' ) || $ ( originalTarget ) . parents ( '.fr-command' ) . length > 0 ) && ! $ ( originalTarget ) . hasClass ( 'fr-dropdown-content' ) ) { editor . button . hideActiveDropdowns ( $popup ) ; }
if ( ( editor . browser . safari || editor . browser . mozilla ) && e . type == 'mousedown' && $ ( originalTarget ) . is ( 'input[type=file]' ) ) { inst . events . disableBlur ( ) ; }
var input _selector = 'input, textarea, button, select, label, .fr-command' ; if ( originalTarget && ! $ ( originalTarget ) . is ( input _selector ) && $ ( originalTarget ) . parents ( input _selector ) . length === 0 ) { e . stopPropagation ( ) ; return false ; }
else if ( originalTarget && $ ( originalTarget ) . is ( input _selector ) ) { e . stopPropagation ( ) ; }
_unmarkExit ( ) ; } , _editorMouseup : function ( ) { if ( $popup . is ( ':visible' ) && _canExit ( ) ) { if ( $popup . find ( 'input:focus, textarea:focus, button:focus, select:focus' ) . filter ( ':visible' ) . length > 0 ) { editor . events . disableBlur ( ) ; } } } , _windowMouseup : function ( e ) { if ( ! editor . core . sameInstance ( $popup ) ) return true ; var inst = $popup . data ( 'instance' ) || editor ; if ( $popup . is ( ':visible' ) && _canExit ( ) ) { e . stopPropagation ( ) ; inst . markers . remove ( ) ; inst . popups . hide ( id ) ; _unmarkExit ( ) ; } } , _windowKeydown : function ( e ) { if ( ! editor . core . sameInstance ( $popup ) ) return true ; var inst = $popup . data ( 'instance' ) || editor ; var key _code = e . which ; if ( $ . FE . KEYCODE . ESC == key _code ) { if ( inst . popups . isVisible ( id ) && inst . opts . toolbarInline ) { e . stopPropagation ( ) ; if ( inst . popups . isVisible ( id ) ) { if ( $popup . find ( '.fr-back:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-back:visible:first' ) ) ; inst . accessibility . focusPopupButton ( $popup ) ; }
else if ( $popup . find ( '.fr-dismiss:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-dismiss:visible:first' ) ) ; }
else { inst . popups . hide ( id ) ; inst . toolbar . showInline ( null , true ) ; inst . accessibility . focusPopupButton ( $popup ) ; } }
return false ; }
else { if ( inst . popups . isVisible ( id ) ) { if ( $popup . find ( '.fr-back:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-back:visible:first' ) ) ; inst . accessibility . focusPopupButton ( $popup ) ; }
else if ( $popup . find ( '.fr-dismiss:visible' ) . length ) { inst . button . exec ( $popup . find ( '.fr-dismiss:visible:first' ) ) ; }
else { inst . popups . hide ( id ) ; inst . accessibility . focusPopupButton ( $popup ) ; }
return false ; } } } } , _doPlaceholder : function ( ) { var $label = $ ( this ) . next ( ) ; if ( $label . length === 0 && $ ( this ) . attr ( 'placeholder' ) ) { $ ( this ) . after ( '<label for="' + $ ( this ) . attr ( 'id' ) + '">' + $ ( this ) . attr ( 'placeholder' ) + '</label>' ) ; }
$ ( this ) . toggleClass ( 'fr-not-empty' , $ ( this ) . val ( ) !== '' ) ; } , _repositionPopup : function ( ) { if ( ! ( editor . opts . height || editor . opts . heightMax ) || editor . opts . toolbarInline ) return true ; if ( editor . $wp && isVisible ( id ) && $popup . parent ( ) . get ( 0 ) == editor . $sc . get ( 0 ) ) { var p _top = $popup . offset ( ) . top - editor . $wp . offset ( ) . top ; var w _height = editor . $wp . outerHeight ( ) ; if ( editor . node . hasClass ( $popup . get ( 0 ) , 'fr-above' ) ) p _top += $popup . outerHeight ( ) ; if ( p _top > w _height || p _top < 0 ) { $popup . addClass ( 'fr-hidden' ) ; }
else { $popup . removeClass ( 'fr-hidden' ) ; } } } } }
function _bindInstanceEvents ( ev , id ) { editor . events . on ( 'mouseup' , ev . _editorMouseup , true ) ; if ( editor . $wp ) editor . events . on ( 'keydown' , ev . _editorKeydown ) ; editor . events . on ( 'blur' , function ( ) { if ( areVisible ( ) ) editor . markers . remove ( ) ; hideAll ( ) ; } ) ; if ( editor . $wp && ! editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $wp , 'scroll.popup' + id , ev . _repositionPopup ) ; }
editor . events . on ( 'window.mouseup' , ev . _windowMouseup , true ) ; editor . events . on ( 'window.keydown' , ev . _windowKeydown , true ) ; popups [ id ] . data ( 'inst' + editor . id , true ) ; editor . events . on ( 'destroy' , function ( ) { if ( editor . core . sameInstance ( popups [ id ] ) ) { popups [ id ] . removeClass ( 'fr-active' ) . appendTo ( 'body:first' ) ; } } , true ) }
function create ( id , template ) { var $popup = _build ( id , template ) ; var ev = _events ( id ) ; _bindInstanceEvents ( ev , id ) ; editor . events . $on ( $popup , 'mousedown mouseup touchstart touchend touch' , '*' , ev . _preventFocus , true ) ; editor . events . $on ( $popup , 'focus' , 'input, textarea, button, select' , ev . _inputFocus , true ) ; editor . events . $on ( $popup , 'blur' , 'input, textarea, button, select' , ev . _inputBlur , true ) ; editor . accessibility . registerPopup ( id ) ; editor . events . $on ( $popup , 'keydown keyup change input' , 'input, textarea' , ev . _doPlaceholder , true ) ; if ( editor . helpers . isIOS ( ) ) { editor . events . $on ( $popup , 'touchend' , 'label' , function ( ) { $ ( '#' + $ ( this ) . attr ( 'for' ) ) . prop ( 'checked' , function ( i , val ) { return ! val ; } ) } , true ) ; }
editor . events . $on ( $ ( editor . o _win ) , 'resize' , ev . _windowResize , true ) ; return $popup ; }
function _destroy ( ) { for ( var id in popups ) { if ( popups . hasOwnProperty ( id ) ) { var $popup = popups [ id ] ; if ( $popup ) { $popup . html ( '' ) . removeData ( ) . remove ( ) ; popups [ id ] = null ; } } }
popups = [ ] ; }
function _init ( ) { editor . events . on ( 'shared.destroy' , _destroy , true ) ; editor . events . on ( 'window.mousedown' , _markExit ) ; editor . events . on ( 'window.touchmove' , _unmarkExit ) ; editor . events . $on ( $ ( editor . o _win ) , 'scroll' , _unmarkExit ) ; editor . events . on ( 'mousedown' , function ( e ) { if ( areVisible ( ) ) { e . stopPropagation ( ) ; editor . $el . find ( '.fr-marker' ) . remove ( ) ; _markExit ( ) ; editor . events . disableBlur ( ) ; } } ) }
return { _init : _init , create : create , get : get , show : show , hide : hide , onHide : onHide , hideAll : hideAll , setContainer : setContainer , refresh : refresh , onRefresh : onRefresh , onShow : onShow , isVisible : isVisible , areVisible : areVisible } } ; $ . FE . MODULES . position = function ( editor ) { function getBoundingRect ( ) { var range = editor . selection . ranges ( 0 ) ; var boundingRect = range . getBoundingClientRect ( ) ; if ( ( boundingRect . top === 0 && boundingRect . left === 0 && boundingRect . width === 0 ) || boundingRect . height === 0 ) { var remove = false ; if ( editor . $el . find ( '.fr-marker' ) . length === 0 ) { editor . selection . save ( ) ; remove = true ; }
var $marker = editor . $el . find ( '.fr-marker:first' ) ; $marker . css ( 'display' , 'inline' ) ; $marker . css ( 'line-height' , '' ) ; var offset = $marker . offset ( ) ; var height = $marker . outerHeight ( ) ; $marker . css ( 'display' , 'none' ) ; $marker . css ( 'line-height' , 0 ) ; boundingRect = { }
boundingRect . left = offset . left ; boundingRect . width = 0 ; boundingRect . height = height ; boundingRect . top = offset . top - ( editor . opts . iframe ? 0 : editor . helpers . scrollTop ( ) ) ; boundingRect . right = 1 ; boundingRect . bottom = 1 ; boundingRect . ok = true ; if ( remove ) editor . selection . restore ( ) ; }
return boundingRect ; }
function _topNormalized ( $el , top , obj _height ) { var height = $el . outerHeight ( true ) ; if ( ! editor . helpers . isMobile ( ) && editor . $tb && $el . parent ( ) . get ( 0 ) != editor . $tb . get ( 0 ) ) { var p _offset = $el . parent ( ) . offset ( ) . top ; var new _top = top - height - ( obj _height || 0 ) ; if ( $el . parent ( ) . get ( 0 ) == editor . $sc . get ( 0 ) ) p _offset = p _offset - $el . parent ( ) . position ( ) . top ; var s _height = editor . $sc . get ( 0 ) . clientHeight ; if ( p _offset + top + height > editor . $sc . offset ( ) . top + s _height && $el . parent ( ) . offset ( ) . top + new _top > 0 && new _top > 0 ) { if ( new _top > editor . $wp . scrollTop ( ) ) { top = new _top ; $el . addClass ( 'fr-above' ) ; } }
else { $el . removeClass ( 'fr-above' ) ; } }
return top ; }
function _leftNormalized ( $el , left ) { var width = $el . outerWidth ( true ) ; var p _offset = $el . parent ( ) . offset ( ) . left ; if ( $el . parent ( ) . get ( 0 ) == editor . $sc . get ( 0 ) ) p _offset = p _offset - $el . parent ( ) . position ( ) . left ; if ( p _offset + left + width > editor . $sc . get ( 0 ) . clientWidth - 10 ) { left = editor . $sc . get ( 0 ) . clientWidth - width - p _offset - 10 ; }
if ( left < 0 ) { left = 10 ; }
return left ; }
function forSelection ( $el ) { var selection _rect = getBoundingRect ( ) ; $el . css ( { top : 0 , left : 0 } ) ; var top = selection _rect . top + selection _rect . height ; var left = selection _rect . left + selection _rect . width / 2 - $el . get ( 0 ) . offsetWidth / 2 + editor . helpers . scrollLeft ( ) ; if ( ! editor . opts . iframe ) { top += editor . helpers . scrollTop ( ) ; }
at ( left , top , $el , selection _rect . height ) ; }
function at ( left , top , $el , obj _height ) { var $container = $el . data ( 'container' ) ; if ( $container && ( $container . get ( 0 ) . tagName !== 'BODY' || $container . css ( 'position' ) != 'static' ) ) { if ( left ) left -= $container . offset ( ) . left ; if ( top ) top -= $container . offset ( ) . top ; if ( $container . get ( 0 ) . tagName != 'BODY' ) { if ( left ) left += $container . get ( 0 ) . scrollLeft ; if ( top ) top += $container . get ( 0 ) . scrollTop ; }
else if ( $container . css ( 'position' ) == 'absolute' ) { if ( left ) left += $container . position ( ) . left ; if ( top ) top += $container . position ( ) . top ; } }
if ( editor . opts . iframe && $container && editor . $tb && $container . get ( 0 ) != editor . $tb . get ( 0 ) ) { if ( left ) left += editor . $iframe . offset ( ) . left ; if ( top ) top += editor . $iframe . offset ( ) . top ; }
var new _left = _leftNormalized ( $el , left ) ; if ( left ) { $el . css ( 'left' , new _left ) ; var $arrow = $el . data ( 'fr-arrow' ) ; if ( ! $arrow ) { $arrow = $el . find ( '.fr-arrow' ) ; $el . data ( 'fr-arrow' , $arrow ) }
if ( ! $arrow . data ( 'margin-left' ) ) $arrow . data ( 'margin-left' , editor . helpers . getPX ( $arrow . css ( 'margin-left' ) ) ) ; $arrow . css ( 'margin-left' , left - new _left + $arrow . data ( 'margin-left' ) ) ; }
if ( top ) { $el . css ( 'top' , _topNormalized ( $el , top , obj _height ) ) ; } }
function _updateIOSSticky ( el ) { var $el = $ ( el ) ; var is _on = $el . is ( '.fr-sticky-on' ) ; var prev _top = $el . data ( 'sticky-top' ) ; var scheduled _top = $el . data ( 'sticky-scheduled' ) ; if ( typeof prev _top == 'undefined' ) { $el . data ( 'sticky-top' , 0 ) ; var $dummy = $ ( '<div class="fr-sticky-dummy" style="height: ' + $el . outerHeight ( ) + 'px;"></div>' ) ; editor . $box . prepend ( $dummy ) ; }
else { editor . $box . find ( '.fr-sticky-dummy' ) . css ( 'height' , $el . outerHeight ( ) ) ; }
if ( editor . core . hasFocus ( ) || editor . $tb . find ( 'input:visible:focus' ) . length > 0 ) { var x _scroll = editor . helpers . scrollTop ( ) ; var x _top = Math . min ( Math . max ( x _scroll - editor . $tb . parent ( ) . offset ( ) . top , 0 ) , editor . $tb . parent ( ) . outerHeight ( ) - $el . outerHeight ( ) ) ; if ( x _top != prev _top && x _top != scheduled _top ) { clearTimeout ( $el . data ( 'sticky-timeout' ) ) ; $el . data ( 'sticky-scheduled' , x _top ) ; if ( $el . outerHeight ( ) < x _scroll - editor . $tb . parent ( ) . offset ( ) . top ) { $el . addClass ( 'fr-opacity-0' ) ; }
$el . data ( 'sticky-timeout' , setTimeout ( function ( ) { var c _scroll = editor . helpers . scrollTop ( ) ; var c _top = Math . min ( Math . max ( c _scroll - editor . $tb . parent ( ) . offset ( ) . top , 0 ) , editor . $tb . parent ( ) . outerHeight ( ) - $el . outerHeight ( ) ) ; if ( c _top > 0 && editor . $tb . parent ( ) . get ( 0 ) . tagName == 'BODY' ) c _top += editor . $tb . parent ( ) . position ( ) . top ; if ( c _top != prev _top ) { $el . css ( 'top' , Math . max ( c _top , 0 ) ) ; $el . data ( 'sticky-top' , c _top ) ; $el . data ( 'sticky-scheduled' , c _top ) ; }
$el . removeClass ( 'fr-opacity-0' ) ; } , 100 ) ) ; }
if ( ! is _on ) { $el . css ( 'top' , '0' ) ; $el . width ( editor . $tb . parent ( ) . width ( ) ) ; $el . addClass ( 'fr-sticky-on' ) ; editor . $box . addClass ( 'fr-sticky-box' ) ; } }
else { clearTimeout ( $ ( el ) . css ( 'sticky-timeout' ) ) ; $el . css ( 'top' , '0' ) ; $el . css ( 'position' , '' ) ; $el . width ( '' ) ; $el . data ( 'sticky-top' , 0 ) ; $el . removeClass ( 'fr-sticky-on' ) ; editor . $box . removeClass ( 'fr-sticky-box' ) ; } }
function _updateSticky ( el ) { if ( ! el . offsetWidth ) { return ; }
var el _top ; var el _bottom ; var $el = $ ( el ) ; var height = $el . outerHeight ( ) ; var prev _top = $el . data ( 'sticky-top' ) ; var position = $el . data ( 'sticky-position' ) ; var viewport _height = $ ( editor . opts . scrollableContainer == 'body' ? editor . o _win : editor . opts . scrollableContainer ) . outerHeight ( ) ; var scrollable _top = 0 ; var scrollable _bottom = 0 ; if ( editor . opts . scrollableContainer !== 'body' ) { scrollable _top = editor . $sc . offset ( ) . top ; scrollable _bottom = $ ( editor . o _win ) . outerHeight ( ) - scrollable _top - viewport _height ; }
var offset _top = editor . opts . scrollableContainer == 'body' ? editor . helpers . scrollTop ( ) : scrollable _top ; var is _on = $el . is ( '.fr-sticky-on' ) ; if ( ! $el . data ( 'sticky-parent' ) ) { $el . data ( 'sticky-parent' , $el . parent ( ) ) ; }
var $parent = $el . data ( 'sticky-parent' ) ; var parent _top = $parent . offset ( ) . top ; var parent _height = $parent . outerHeight ( ) ; if ( ! $el . data ( 'sticky-offset' ) && ( typeof prev _top === 'undefined' ) ) { $el . data ( 'sticky-offset' , true ) ; $el . after ( '<div class="fr-sticky-dummy" style="height: ' + height + 'px;"></div>' ) ; }
else { editor . $box . find ( '.fr-sticky-dummy' ) . css ( 'height' , height + 'px' ) ; }
if ( ! position ) { var skip _setting _fixed = $el . css ( 'top' ) !== 'auto' || $el . css ( 'bottom' ) !== 'auto' ; if ( ! skip _setting _fixed ) { $el . css ( 'position' , 'fixed' ) ; }
position = { top : editor . node . hasClass ( $el . get ( 0 ) , 'fr-top' ) , bottom : editor . node . hasClass ( $el . get ( 0 ) , 'fr-bottom' ) } ; if ( ! skip _setting _fixed ) { $el . css ( 'position' , '' ) ; }
$el . data ( 'sticky-position' , position ) ; $el . data ( 'top' , editor . node . hasClass ( $el . get ( 0 ) , 'fr-top' ) ? $el . css ( 'top' ) : 'auto' ) ; $el . data ( 'bottom' , editor . node . hasClass ( $el . get ( 0 ) , 'fr-bottom' ) ? $el . css ( 'bottom' ) : 'auto' ) ; }
var isFixedToTop = function ( ) { return parent _top < offset _top + el _top && parent _top + parent _height - height >= offset _top + el _top ; }
var isFixedToBottom = function ( ) { return parent _top + height < offset _top + viewport _height - el _bottom && parent _top + parent _height > offset _top + viewport _height - el _bottom ; }
el _top = editor . helpers . getPX ( $el . data ( 'top' ) ) ; el _bottom = editor . helpers . getPX ( $el . data ( 'bottom' ) ) ; var at _top = ( position . top && isFixedToTop ( ) && ( editor . helpers . isInViewPort ( editor . $sc . get ( 0 ) ) || editor . opts . scrollableContainer == 'body' ) ) ; var at _bottom = ( position . bottom && isFixedToBottom ( ) ) ; if ( at _top || at _bottom ) { $el . css ( 'width' , $parent . get ( 0 ) . getBoundingClientRect ( ) . width + 'px' ) ; if ( ! is _on ) { $el . addClass ( 'fr-sticky-on' )
$el . removeClass ( 'fr-sticky-off' ) ; if ( $el . css ( 'top' ) ) { if ( $el . data ( 'top' ) != 'auto' ) { $el . css ( 'top' , editor . helpers . getPX ( $el . data ( 'top' ) ) + scrollable _top ) ; }
else { $el . data ( 'top' , 'auto' ) ; } }
if ( $el . css ( 'bottom' ) ) { if ( $el . data ( 'bottom' ) != 'auto' ) { $el . css ( 'bottom' , editor . helpers . getPX ( $el . data ( 'bottom' ) ) + scrollable _bottom ) ; }
else { $el . css ( 'bottom' , 'auto' ) ; } } } }
else { if ( ! editor . node . hasClass ( $el . get ( 0 ) , 'fr-sticky-off' ) ) { $el . width ( '' ) ; $el . removeClass ( 'fr-sticky-on' ) ; $el . addClass ( 'fr-sticky-off' ) ; if ( $el . css ( 'top' ) && $el . data ( 'top' ) != 'auto' && position . top ) { $el . css ( 'top' , 0 ) ; }
if ( $el . css ( 'bottom' ) && $el . data ( 'bottom' ) != 'auto' && position . bottom ) { $el . css ( 'bottom' , 0 ) ; } } } }
function _testSticky ( ) { return false ; }
function _initSticky ( ) { if ( ! _testSticky ( ) ) { editor . _stickyElements = [ ] ; if ( editor . helpers . isIOS ( ) ) { var animate = function ( ) { editor . helpers . requestAnimationFrame ( ) ( animate ) ; if ( editor . events . trigger ( 'position.refresh' ) === false ) return ; for ( var i = 0 ; i < editor . _stickyElements . length ; i ++ ) { _updateIOSSticky ( editor . _stickyElements [ i ] ) ; } } ; animate ( ) ; editor . events . $on ( $ ( editor . o _win ) , 'scroll' , function ( ) { if ( editor . core . hasFocus ( ) ) { for ( var i = 0 ; i < editor . _stickyElements . length ; i ++ ) { var $el = $ ( editor . _stickyElements [ i ] ) ; var $parent = $el . parent ( ) ; var c _scroll = editor . helpers . scrollTop ( ) ; if ( $el . outerHeight ( ) < c _scroll - $parent . offset ( ) . top ) { $el . addClass ( 'fr-opacity-0' ) ; $el . data ( 'sticky-top' , - 1 ) ; $el . data ( 'sticky-scheduled' , - 1 ) ; } } } } , true ) ; }
else { if ( editor . opts . scrollableContainer !== 'body' ) { editor . events . $on ( $ ( editor . opts . scrollableContainer ) , 'scroll' , refresh , true ) ; }
editor . events . $on ( $ ( editor . o _win ) , 'scroll' , refresh , true ) ; editor . events . $on ( $ ( editor . o _win ) , 'resize' , refresh , true ) ; editor . events . on ( 'initialized' , refresh ) ; editor . events . on ( 'focus' , refresh ) ; editor . events . $on ( $ ( editor . o _win ) , 'resize' , 'textarea' , refresh , true ) ; } }
editor . events . on ( 'destroy' , function ( ) { editor . _stickyElements = [ ] ; } ) ; }
function refresh ( ) { if ( editor . _stickyElements ) { for ( var i = 0 ; i < editor . _stickyElements . length ; i ++ ) { _updateSticky ( editor . _stickyElements [ i ] ) ; } } }
function addSticky ( $el ) { $el . addClass ( 'fr-sticky' ) ; if ( editor . helpers . isIOS ( ) ) $el . addClass ( 'fr-sticky-ios' ) ; if ( ! _testSticky ( ) ) { $el . removeClass ( 'fr-sticky' ) ; editor . _stickyElements . push ( $el . get ( 0 ) ) ; } }
function _init ( ) { _initSticky ( ) ; }
return { _init : _init , forSelection : forSelection , addSticky : addSticky , refresh : refresh , at : at , getBoundingRect : getBoundingRect } } ; $ . FE . MODULES . refresh = function ( editor ) { function undo ( $btn ) { _setDisabled ( $btn , ! editor . undo . canDo ( ) ) }
function redo ( $btn ) { _setDisabled ( $btn , ! editor . undo . canRedo ( ) ) ; }
function indent ( $btn ) { if ( editor . node . hasClass ( $btn . get ( 0 ) , 'fr-no-refresh' ) ) return false ; var blocks = editor . selection . blocks ( ) ; for ( var i = 0 ; i < blocks . length ; i ++ ) { var p _node = blocks [ i ] . previousSibling ; while ( p _node && p _node . nodeType == Node . TEXT _NODE && p _node . textContent . length === 0 ) { p _node = p _node . previousSibling ; }
if ( blocks [ i ] . tagName == 'LI' && ! p _node ) { _setDisabled ( $btn , true ) ; }
else { _setDisabled ( $btn , false ) ; return true ; } } }
function outdent ( $btn ) { if ( editor . node . hasClass ( $btn . get ( 0 ) , 'fr-no-refresh' ) ) return false ; var blocks = editor . selection . blocks ( ) ; for ( var i = 0 ; i < blocks . length ; i ++ ) { var prop = ( editor . opts . direction == 'rtl' || $ ( blocks [ i ] ) . css ( 'direction' ) == 'rtl' ) ? 'margin-right' : 'margin-left' ; if ( blocks [ i ] . tagName == 'LI' || blocks [ i ] . parentNode . tagName == 'LI' ) { _setDisabled ( $btn , false ) ; return true ; }
if ( editor . helpers . getPX ( $ ( blocks [ i ] ) . css ( prop ) ) > 0 ) { _setDisabled ( $btn , false ) ; return true ; } }
_setDisabled ( $btn , true ) ; }
function _setDisabled ( $btn , disabled ) { $btn . toggleClass ( 'fr-disabled' , disabled ) . attr ( 'aria-disabled' , disabled ) ; }
return { undo : undo , redo : redo , outdent : outdent , indent : indent } } ; $ . extend ( $ . FE . DEFAULTS , { editInPopup : false } ) ; $ . FE . MODULES . textEdit = function ( editor ) { function _initPopup ( ) { var txt = '<div id="fr-text-edit-' + editor . id + '" class="fr-layer fr-text-edit-layer"><div class="fr-input-line"><input type="text" placeholder="' + editor . language . translate ( 'Text' ) + '" tabIndex="1"></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="updateText" tabIndex="2">' + editor . language . translate ( 'Update' ) + '</button></div></div>'
var template = { edit : txt } ; editor . popups . create ( 'text.edit' , template ) ; }
function _showPopup ( ) { var $popup = editor . popups . get ( 'text.edit' ) ; var text ; if ( editor . $el . prop ( 'tagName' ) === 'INPUT' ) { text = editor . $el . attr ( 'placeholder' ) ; }
else { text = editor . $el . text ( ) ; }
$popup . find ( 'input' ) . val ( text ) . trigger ( 'change' ) ; editor . popups . setContainer ( 'text.edit' , editor . $sc ) ; editor . popups . show ( 'text.edit' , editor . $el . offset ( ) . left + editor . $el . outerWidth ( ) / 2 , editor . $el . offset ( ) . top + editor . $el . outerHeight ( ) , editor . $el . outerHeight ( ) ) ; }
function _initEvents ( ) { editor . events . $on ( editor . $el , editor . _mouseup , function ( ) { setTimeout ( function ( ) { _showPopup ( ) ; } , 10 ) ; } ) }
function update ( ) { var $popup = editor . popups . get ( 'text.edit' ) ; var new _text = $popup . find ( 'input' ) . val ( ) ; if ( new _text . length === 0 ) new _text = editor . opts . placeholderText ; if ( editor . $el . prop ( 'tagName' ) === 'INPUT' ) { editor . $el . attr ( 'placeholder' , new _text ) ; }
else { editor . $el . text ( new _text ) ; }
editor . events . trigger ( 'contentChanged' ) ; editor . popups . hide ( 'text.edit' ) ; }
function _init ( ) { if ( editor . opts . editInPopup ) { _initPopup ( ) ; _initEvents ( ) ; } }
return { _init : _init , update : update } } ; $ . FE . RegisterCommand ( 'updateText' , { focus : false , undo : false , callback : function ( ) { this . textEdit . update ( ) ; } } )
$ . extend ( $ . FE . DEFAULTS , { toolbarBottom : false , toolbarButtons : null , toolbarButtonsXS : null , toolbarButtonsSM : null , toolbarButtonsMD : null , toolbarContainer : null , toolbarInline : false , toolbarSticky : true , toolbarStickyOffset : 0 , toolbarVisibleWithoutSelection : false } ) ; $ . FE . TOOLBAR _BUTTONS = [ 'fullscreen' , 'bold' , 'italic' , 'underline' , 'strikeThrough' , 'subscript' , 'superscript' , '|' , 'fontFamily' , 'fontSize' , 'color' , 'inlineClass' , 'inlineStyle' , 'paragraphStyle' , 'lineHeight' , '|' , 'paragraphFormat' , 'align' , 'formatOL' , 'formatUL' , 'outdent' , 'indent' , 'quote' , '-' , 'insertLink' , 'insertImage' , 'insertVideo' , 'embedly' , 'insertFile' , 'insertTable' , '|' , 'emoticons' , 'fontAwesome' , 'specialCharacters' , 'insertHR' , 'selectAll' , 'clearFormatting' , '|' , 'print' , 'getPDF' , 'spellChecker' , 'help' , 'html' , '|' , 'undo' , 'redo' ] ; $ . FE . TOOLBAR _BUTTONS _MD = null ; $ . FE . TOOLBAR _BUTTONS _SM = [ 'bold' , 'italic' , 'underline' , '|' , 'fontFamily' , 'fontSize' , 'insertLink' , 'insertImage' , 'table' , '|' , 'undo' , 'redo' ] ; $ . FE . TOOLBAR _BUTTONS _XS = [ 'bold' , 'italic' , 'fontFamily' , 'fontSize' , '|' , 'undo' , 'redo' ] ; $ . FE . MODULES . toolbar = function ( editor ) { var _buttons _map = [ ] ; _buttons _map [ $ . FE . XS ] = editor . opts . toolbarButtonsXS || editor . opts . toolbarButtons || $ . FE . TOOLBAR _BUTTONS _XS || $ . FE . TOOLBAR _BUTTONS || [ ] ; _buttons _map [ $ . FE . SM ] = editor . opts . toolbarButtonsSM || editor . opts . toolbarButtons || $ . FE . TOOLBAR _BUTTONS _SM || $ . FE . TOOLBAR _BUTTONS || [ ] ; _buttons _map [ $ . FE . MD ] = editor . opts . toolbarButtonsMD || editor . opts . toolbarButtons || $ . FE . TOOLBAR _BUTTONS _MD || $ . FE . TOOLBAR _BUTTONS || [ ] ; _buttons _map [ $ . FE . LG ] = editor . opts . toolbarButtons || $ . FE . TOOLBAR _BUTTONS || [ ] ; function _addOtherButtons ( buttons , toolbarButtons ) { for ( var i = 0 ; i < toolbarButtons . length ; i ++ ) { if ( toolbarButtons [ i ] != '-' && toolbarButtons [ i ] != '|' && buttons . indexOf ( toolbarButtons [ i ] ) < 0 ) { buttons . push ( toolbarButtons [ i ] ) ; } } }
function _addButtons ( ) { var _buttons = $ . merge ( [ ] , _screenButtons ( ) ) ; _addOtherButtons ( _buttons , _buttons _map [ $ . FE . XS ] ) ; _addOtherButtons ( _buttons , _buttons _map [ $ . FE . SM ] ) ; _addOtherButtons ( _buttons , _buttons _map [ $ . FE . MD ] ) ; _addOtherButtons ( _buttons , _buttons _map [ $ . FE . LG ] ) ; for ( var i = _buttons . length - 1 ; i >= 0 ; i -- ) { if ( _buttons [ i ] != '-' && _buttons [ i ] != '|' && _buttons . indexOf ( _buttons [ i ] ) < i ) { _buttons . splice ( i , 1 ) ; } }
var buttons _list = editor . button . buildList ( _buttons , _screenButtons ( ) ) ; editor . $tb . append ( buttons _list ) ; editor . button . bindCommands ( editor . $tb ) ; }
function _screenButtons ( ) { var screen _size = editor . helpers . screenSize ( ) ; return _buttons _map [ screen _size ] ; }
function _showScreenButtons ( ) { var c _buttons = _screenButtons ( ) ; editor . $tb . find ( '.fr-separator' ) . remove ( ) ; editor . $tb . find ( '> .fr-command, > div.fr-btn-wrap' ) . addClass ( 'fr-hidden' ) ; for ( var i = 0 ; i < c _buttons . length ; i ++ ) { if ( c _buttons [ i ] == '|' || c _buttons [ i ] == '-' ) { editor . $tb . append ( editor . button . buildList ( [ c _buttons [ i ] ] ) ) ; }
else { var $btn = editor . $tb . find ( '> .fr-command[data-cmd="' + c _buttons [ i ] + '"], > div.fr-btn-wrap > .fr-command[data-cmd="' + c _buttons [ i ] + '"]' ) ; var $dropdown = null ; if ( editor . node . hasClass ( $btn . next ( ) . get ( 0 ) , 'fr-dropdown-menu' ) ) $dropdown = $btn . next ( ) ; if ( editor . node . hasClass ( $btn . next ( ) . get ( 0 ) , 'fr-options' ) ) { $btn = $btn . parent ( ) ; }
$btn . removeClass ( 'fr-hidden' ) . appendTo ( editor . $tb ) ; if ( $dropdown ) $dropdown . appendTo ( editor . $tb ) ; } } }
function _setVisibility ( ) { editor . events . $on ( $ ( editor . o _win ) , 'resize' , _showScreenButtons ) ; editor . events . $on ( $ ( editor . o _win ) , 'orientationchange' , _showScreenButtons ) ; }
function showInline ( e , force ) { setTimeout ( function ( ) { if ( ( ! e || e . which != $ . FE . KEYCODE . ESC ) && editor . selection . inEditor ( ) && editor . core . hasFocus ( ) && ! editor . popups . areVisible ( ) ) { if ( editor . opts . toolbarVisibleWithoutSelection || ( ! editor . selection . isCollapsed ( ) && ! editor . keys . isIME ( ) ) || force ) { editor . $tb . data ( 'instance' , editor ) ; if ( editor . events . trigger ( 'toolbar.show' , [ e ] ) === false ) return false ; editor . $tb . show ( ) ; if ( ! editor . opts . toolbarContainer ) { editor . position . forSelection ( editor . $tb ) ; }
if ( editor . opts . zIndex > 1 ) { editor . $tb . css ( 'z-index' , editor . opts . zIndex + 1 ) ; }
else { editor . $tb . css ( 'z-index' , null ) ; } } } } , 0 ) ; }
function hide ( e ) { if ( e && e . type === 'blur' && document . activeElement === editor . el ) { return false ; }
if ( e && e . type === 'keydown' && editor . keys . ctrlKey ( e ) ) return true ; var $active _dropdowns = editor . button . getButtons ( '.fr-dropdown.fr-active' ) ; if ( $active _dropdowns . next ( ) . find ( editor . o _doc . activeElement ) . length ) return true ; if ( editor . events . trigger ( 'toolbar.hide' ) !== false ) { editor . $tb . hide ( ) ; } }
function show ( ) { if ( editor . events . trigger ( 'toolbar.show' ) === false ) return false ; editor . $tb . show ( ) ; }
var tm = null ; function _showInlineWithTimeout ( e ) { clearTimeout ( tm ) ; if ( ! e || e . which != $ . FE . KEYCODE . ESC ) { tm = setTimeout ( showInline , editor . opts . typingTimer ) ; } }
function _initInlineBehavior ( ) { editor . events . on ( 'window.mousedown' , hide ) ; editor . events . on ( 'keydown' , hide ) ; editor . events . on ( 'blur' , hide ) ; if ( ! editor . helpers . isMobile ( ) ) { editor . events . on ( 'window.mouseup' , showInline ) ; }
if ( editor . helpers . isMobile ( ) ) { if ( ! editor . helpers . isIOS ( ) ) { editor . events . on ( 'window.touchend' , showInline ) ; if ( editor . browser . mozilla ) { setInterval ( showInline , 200 ) ; } } }
else { editor . events . on ( 'window.keyup' , _showInlineWithTimeout ) ; }
editor . events . on ( 'keydown' , function ( e ) { if ( e && e . which == $ . FE . KEYCODE . ESC ) { hide ( ) ; } } ) ; editor . events . on ( 'keydown' , function ( e ) { if ( e . which == $ . FE . KEYCODE . ALT ) { e . stopPropagation ( ) ; return false ; } } , true ) ; editor . events . $on ( editor . $wp , 'scroll.toolbar' , showInline ) ; editor . events . on ( 'commands.after' , showInline ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $doc , 'selectionchange' , _showInlineWithTimeout ) ; editor . events . $on ( editor . $doc , 'orientationchange' , showInline ) ; } }
function _initPositioning ( ) { if ( editor . opts . toolbarInline ) { editor . $sc . append ( editor . $tb ) ; editor . $tb . data ( 'container' , editor . $sc ) ; editor . $tb . addClass ( 'fr-inline' ) ; editor . $tb . prepend ( '<span class="fr-arrow"></span>' )
_initInlineBehavior ( ) ; editor . opts . toolbarBottom = false ; }
else { if ( editor . opts . toolbarBottom && ! editor . helpers . isIOS ( ) ) { editor . $box . append ( editor . $tb ) ; editor . $tb . addClass ( 'fr-bottom' ) ; editor . $box . addClass ( 'fr-bottom' ) ; }
else { editor . opts . toolbarBottom = false ; editor . $box . prepend ( editor . $tb ) ; editor . $tb . addClass ( 'fr-top' ) ; editor . $box . addClass ( 'fr-top' ) ; }
editor . $tb . addClass ( 'fr-basic' ) ; if ( editor . opts . toolbarSticky ) { if ( editor . opts . toolbarStickyOffset ) { if ( editor . opts . toolbarBottom ) { editor . $tb . css ( 'bottom' , editor . opts . toolbarStickyOffset ) ; }
else { editor . $tb . css ( 'top' , editor . opts . toolbarStickyOffset ) ; } }
editor . position . addSticky ( editor . $tb ) ; } } }
function _sharedDestroy ( ) { editor . $tb . html ( '' ) . removeData ( ) . remove ( ) ; editor . $tb = null ; }
function _destroy ( ) { editor . $box . removeClass ( 'fr-top fr-bottom fr-inline fr-basic' ) ; editor . $box . find ( '.fr-sticky-dummy' ) . remove ( ) ; }
function _setDefaults ( ) { if ( editor . opts . theme ) { editor . $tb . addClass ( editor . opts . theme + '-theme' ) ; }
if ( editor . opts . zIndex > 1 ) { editor . $tb . css ( 'z-index' , editor . opts . zIndex + 1 ) ; }
if ( editor . opts . direction != 'auto' ) { editor . $tb . removeClass ( 'fr-ltr fr-rtl' ) . addClass ( 'fr-' + editor . opts . direction ) ; }
if ( ! editor . helpers . isMobile ( ) ) { editor . $tb . addClass ( 'fr-desktop' ) ; }
else { editor . $tb . addClass ( 'fr-mobile' ) ; }
if ( ! editor . opts . toolbarContainer ) { _initPositioning ( ) ; }
else { if ( editor . opts . toolbarInline ) { _initInlineBehavior ( ) ; hide ( ) ; }
if ( editor . opts . toolbarBottom ) editor . $tb . addClass ( 'fr-bottom' ) ; else editor . $tb . addClass ( 'fr-top' ) ; }
_addButtons ( ) ; _setVisibility ( ) ; editor . accessibility . registerToolbar ( editor . $tb ) ; editor . events . $on ( editor . $tb , editor . _mousedown + ' ' + editor . _mouseup , function ( e ) { var originalTarget = e . originalEvent ? ( e . originalEvent . target || e . originalEvent . originalTarget ) : null ; if ( originalTarget && originalTarget . tagName != 'INPUT' && ! editor . edit . isDisabled ( ) ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; return false ; } } , true ) ; }
function _init ( ) { editor . $sc = $ ( editor . opts . scrollableContainer ) . first ( ) ; if ( ! editor . $wp ) return false ; if ( editor . opts . toolbarContainer ) { if ( ! editor . shared . $tb ) { editor . shared . $tb = $ ( '<div class="fr-toolbar"></div>' ) ; editor . $tb = editor . shared . $tb ; $ ( editor . opts . toolbarContainer ) . append ( editor . $tb ) ; _setDefaults ( ) ; editor . $tb . data ( 'instance' , editor ) ; }
else { editor . $tb = editor . shared . $tb ; if ( editor . opts . toolbarInline ) _initInlineBehavior ( ) ; }
if ( editor . opts . toolbarInline ) { editor . $box . addClass ( 'fr-inline' ) ; }
else { editor . $box . addClass ( 'fr-basic' ) ; }
editor . events . on ( 'focus' , function ( ) { editor . $tb . data ( 'instance' , editor ) ; } , true ) ; editor . opts . toolbarInline = false ; }
else { if ( editor . opts . toolbarInline ) { editor . $box . addClass ( 'fr-inline' ) ; if ( ! editor . shared . $tb ) { editor . shared . $tb = $ ( '<div class="fr-toolbar"></div>' ) ; editor . $tb = editor . shared . $tb ; _setDefaults ( ) ; }
else { editor . $tb = editor . shared . $tb ; _initInlineBehavior ( ) ; } }
else { editor . $box . addClass ( 'fr-basic' ) ; editor . $tb = $ ( '<div class="fr-toolbar"></div>' ) ; _setDefaults ( ) ; editor . $tb . data ( 'instance' , editor ) ; } }
editor . events . on ( 'destroy' , _destroy , true ) ; editor . events . on ( ! editor . opts . toolbarInline && ! editor . opts . toolbarContainer ? 'destroy' : 'shared.destroy' , _sharedDestroy , true ) ; }
var disabled = false ; function disable ( ) { if ( ! disabled && editor . $tb ) { editor . $tb . find ( '> .fr-command, .fr-btn-wrap > .fr-command' ) . addClass ( 'fr-disabled fr-no-refresh' ) . attr ( 'aria-disabled' , true ) ; disabled = true ; } }
function enable ( ) { if ( disabled && editor . $tb ) { editor . $tb . find ( '> .fr-command, .fr-btn-wrap > .fr-command' ) . removeClass ( 'fr-disabled fr-no-refresh' ) . attr ( 'aria-disabled' , false ) ; disabled = false ; }
editor . button . bulkRefresh ( ) ; }
return { _init : _init , hide : hide , show : show , showInline : showInline , disable : disable , enable : enable } } ; } ) ) ; ! function ( t ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , t ) : "object" == typeof module && module . exports ? module . exports = function ( e , a ) { return a === undefined && ( a = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( e ) ) , t ( a ) } : t ( window . jQuery ) } ( function ( i ) { i . extend ( i . FE . DEFAULTS , { paragraphStyles : { "fr-text-gray" : "Gray" , "fr-text-bordered" : "Bordered" , "fr-text-spaced" : "Spaced" , "fr-text-uppercase" : "Uppercase" } , paragraphMultipleStyles : ! 0 } ) , i . FE . PLUGINS . paragraphStyle = function ( o ) { return { _init : function ( ) { } , apply : function ( e , a , t ) { void 0 === a && ( a = o . opts . paragraphStyles ) , void 0 === t && ( t = o . opts . paragraphMultipleStyles ) ; var r = "" ; t || ( ( r = Object . keys ( a ) ) . splice ( r . indexOf ( e ) , 1 ) , r = r . join ( " " ) ) , o . selection . save ( ) , o . html . wrap ( ! 0 , ! 0 , ! 0 , ! 0 ) , o . selection . restore ( ) ; var n = o . selection . blocks ( ) ; o . selection . save ( ) ; for ( var s = i ( n [ 0 ] ) . hasClass ( e ) , l = 0 ; l < n . length ; l ++ ) i ( n [ l ] ) . removeClass ( r ) . toggleClass ( e , ! s ) , i ( n [ l ] ) . hasClass ( "fr-temp-div" ) && i ( n [ l ] ) . removeClass ( "fr-temp-div" ) , "" === i ( n [ l ] ) . attr ( "class" ) && i ( n [ l ] ) . removeAttr ( "class" ) ; o . html . unwrap ( ) , o . selection . restore ( ) } , refreshOnShow : function ( e , a ) { var t = o . selection . blocks ( ) ; if ( t . length ) { var r = i ( t [ 0 ] ) ; a . find ( ".fr-command" ) . each ( function ( ) { var e = i ( this ) . data ( "param1" ) , a = r . hasClass ( e ) ; i ( this ) . toggleClass ( "fr-active" , a ) . attr ( "aria-selected" , a ) } ) } } } } , i . FE . RegisterCommand ( "paragraphStyle" , { type : "dropdown" , html : function ( ) { var e = '<ul class="fr-dropdown-list" role="presentation">' , a = this . opts . paragraphStyles ; for ( var t in a ) a . hasOwnProperty ( t ) && ( e += '<li role="presentation"><a class="fr-command ' + t + '" tabIndex="-1" role="option" data-cmd="paragraphStyle" data-param1="' + t + '" title="' + this . language . translate ( a [ t ] ) + '">' + this . language . translate ( a [ t ] ) + "</a></li>" ) ; return e += "</ul>" } , title : "Paragraph Style" , callback : function ( e , a ) { this . paragraphStyle . apply ( a ) } , refreshOnShow : function ( e , a ) { this . paragraphStyle . refreshOnShow ( e , a ) } , plugin : "paragraphStyle" } ) , i . FE . DefineIcon ( "paragraphStyle" , { NAME : "magic" } ) } ) ; ( function ( factory ) { if ( typeof define === 'function' && define . amd ) { define ( [ 'jquery' ] , factory ) ; } else if ( typeof module === 'object' && module . exports ) { module . exports = function ( root , jQuery ) { if ( jQuery === undefined ) { if ( typeof window !== 'undefined' ) { jQuery = require ( 'jquery' ) ; }
else { jQuery = require ( 'jquery' ) ( root ) ; } }
return factory ( jQuery ) ; } ; } else { factory ( window . jQuery ) ; } } ( function ( $ ) { $ . FE . PLUGINS . fullscreen = function ( editor ) { var old _scroll ; function isActive ( ) { return editor . $box . hasClass ( 'fr-fullscreen' ) ; }
var $placeholder ; var height ; var max _height ; var z _index ; function _on ( ) { if ( editor . helpers . isIOS ( ) && editor . core . hasFocus ( ) ) { editor . $el . blur ( ) ; setTimeout ( toggle , 250 ) ; return false ; }
old _scroll = editor . helpers . scrollTop ( ) ; editor . $box . toggleClass ( 'fr-fullscreen' ) ; $ ( 'body:first' ) . toggleClass ( 'fr-fullscreen' ) ; $placeholder = $ ( '<div style="display: none;"></div>' ) ; editor . $box . after ( $placeholder ) ; if ( editor . helpers . isMobile ( ) ) { editor . $tb . data ( 'parent' , editor . $tb . parent ( ) ) ; editor . $tb . prependTo ( editor . $box ) ; if ( editor . $tb . data ( 'sticky-dummy' ) ) { editor . $tb . after ( editor . $tb . data ( 'sticky-dummy' ) ) ; } }
height = editor . opts . height ; max _height = editor . opts . heightMax ; z _index = editor . opts . zIndex ; editor . position . refresh ( )
editor . opts . height = editor . o _win . innerHeight - ( editor . opts . toolbarInline ? 0 : editor . $tb . outerHeight ( ) ) ; editor . opts . zIndex = 9990 ; editor . opts . heightMax = null ; editor . size . refresh ( ) ; if ( editor . opts . toolbarInline ) editor . toolbar . showInline ( ) ; editor . events . trigger ( 'charCounter.update' ) ; editor . events . trigger ( 'codeView.update' ) ; editor . $win . trigger ( 'scroll' ) ; }
function _off ( ) { if ( editor . helpers . isIOS ( ) && editor . core . hasFocus ( ) ) { editor . $el . blur ( ) ; setTimeout ( toggle , 250 ) ; return false ; }
editor . $box . toggleClass ( 'fr-fullscreen' ) ; $ ( 'body:first' ) . toggleClass ( 'fr-fullscreen' ) ; editor . $tb . prependTo ( editor . $tb . data ( 'parent' ) ) ; if ( editor . $tb . data ( 'sticky-dummy' ) ) { editor . $tb . after ( editor . $tb . data ( 'sticky-dummy' ) ) ; }
2017-02-08 08:10:24 +00:00
editor . opts . height = height ; editor . opts . heightMax = max _height ; editor . opts . zIndex = z _index ; editor . size . refresh ( ) ; $ ( editor . o _win ) . scrollTop ( old _scroll )
2016-05-19 18:35:40 +00:00
if ( editor . opts . toolbarInline ) editor . toolbar . showInline ( ) ; editor . events . trigger ( 'charCounter.update' ) ; if ( editor . opts . toolbarSticky ) { if ( editor . opts . toolbarStickyOffset ) { if ( editor . opts . toolbarBottom ) { editor . $tb . css ( 'bottom' , editor . opts . toolbarStickyOffset ) . data ( 'bottom' , editor . opts . toolbarStickyOffset ) ; }
else { editor . $tb . css ( 'top' , editor . opts . toolbarStickyOffset ) . data ( 'top' , editor . opts . toolbarStickyOffset ) ; } } }
editor . $win . trigger ( 'scroll' ) ; }
function toggle ( ) { if ( ! isActive ( ) ) { _on ( ) ; }
else { _off ( ) ; }
refresh ( editor . $tb . find ( '.fr-command[data-cmd="fullscreen"]' ) ) ; $ ( window ) . trigger ( 'oc.updateUi' ) }
2017-02-08 08:10:24 +00:00
function refresh ( $btn ) { var active = isActive ( ) ; $btn . toggleClass ( 'fr-active' , active ) . attr ( 'aria-pressed' , active ) ; $btn . find ( '> *:not(.fr-sr-only)' ) . replaceWith ( ! active ? editor . icon . create ( 'fullscreen' ) : editor . icon . create ( 'fullscreenCompress' ) ) ; }
2019-03-28 16:49:22 +00:00
function _init ( ) { if ( ! editor . $wp ) return false ; editor . events . $on ( $ ( editor . o _win ) , 'resize' , function ( ) { if ( isActive ( ) ) { _off ( ) ; _on ( ) ; } } ) ; editor . events . on ( 'toolbar.hide' , function ( ) { if ( isActive ( ) && editor . helpers . isMobile ( ) ) return false ; } )
editor . events . on ( 'position.refresh' , function ( ) { if ( editor . helpers . isIOS ( ) ) { return ! isActive ( ) ; } } )
editor . events . on ( 'destroy' , function ( ) { if ( isActive ( ) ) { _off ( ) ; } } , true ) ; }
2016-05-19 18:35:40 +00:00
return { _init : _init , toggle : toggle , refresh : refresh , isActive : isActive } }
2017-02-08 08:10:24 +00:00
$ . FE . RegisterCommand ( 'fullscreen' , { title : 'Fullscreen' , undo : false , focus : false , accessibilityFocus : true , forcedRefresh : true , toggle : true , callback : function ( ) { this . fullscreen . toggle ( ) ; } , refresh : function ( $btn ) { this . fullscreen . refresh ( $btn ) ; } , plugin : 'fullscreen' } )
2016-05-21 21:24:04 +00:00
$ . FE . DefineIcon ( 'fullscreen' , { NAME : 'expand' } ) ; $ . FE . DefineIcon ( 'fullscreenCompress' , { NAME : 'compress' } ) ; } ) ) ; ( function ( factory ) { if ( typeof define === 'function' && define . amd ) { define ( [ 'jquery' ] , factory ) ; } else if ( typeof module === 'object' && module . exports ) { module . exports = function ( root , jQuery ) { if ( jQuery === undefined ) { if ( typeof window !== 'undefined' ) { jQuery = require ( 'jquery' ) ; }
2016-05-19 18:35:40 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
2019-03-28 16:49:22 +00:00
return factory ( jQuery ) ; } ; } else { factory ( window . jQuery ) ; } } ( function ( $ ) { $ . extend ( $ . FE . DEFAULTS , { aceEditor : true , aceEditorVendorPath : '/' , aceEditorOptions : { showLineNumbers : true , useSoftTabs : false , wrap : true , mode : 'ace/mode/html' , tabSize : 2 } , codeBeautifierOptions : { end _with _newline : true , indent _inner _html : true , extra _liners : [ 'p' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'blockquote' , 'pre' , 'ul' , 'ol' , 'table' , 'dl' ] , brace _style : 'expand' , indent _char : '\t' , indent _size : 1 , wrap _line _length : 0 } , codeViewKeepActiveButtons : [ 'fullscreen' ] } )
2016-05-19 18:35:40 +00:00
$ . FE . PLUGINS . codeView = function ( editor ) { var $html _area ; var ace _editor ; function isActive ( ) { return editor . $box . hasClass ( 'fr-code-view' ) ; }
2019-03-28 16:49:22 +00:00
function get ( ) { if ( ace _editor ) { return ace _editor . getValue ( ) ; }
else { return $html _area . val ( ) ; } }
function refresh ( ) { if ( isActive ( ) ) { if ( ace _editor ) { ace _editor . resize ( ) ; } } }
var _can _focus = false ; function _blur ( ) { if ( isActive ( ) ) { editor . events . trigger ( 'blur' ) } }
function _focus ( ) { if ( isActive ( ) && _can _focus ) { editor . events . trigger ( 'focus' ) } }
function _showText ( $btn ) { var html = get ( ) ; editor . html . set ( html ) ; editor . $el . blur ( ) ; editor . $tb . find ( ' > .fr-command, > .fr-btn-wrap > .fr-command' ) . not ( $btn ) . removeClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , false ) ; $btn . removeClass ( 'fr-active' ) . attr ( 'aria-pressed' , false ) ; editor . events . focus ( true ) ; editor . placeholder . refresh ( ) ; editor . undo . saveStep ( ) ; }
function _showHTML ( $btn ) { if ( ! $html _area ) { _initArea ( ) ; if ( ! ace _editor && editor . opts . aceEditor && typeof ace != 'undefined' ) { ace _editor = ace . edit ( $html _area . get ( 0 ) ) ; ace . require ( 'ace/config' ) . set ( 'basePath' , editor . opts . aceEditorVendorPath ) ; ace _editor . setOptions ( editor . opts . aceEditorOptions ) ; ace _editor . on ( 'blur' , _blur ) ; ace _editor . on ( 'focus' , _focus ) ; }
else { editor . events . $on ( $html _area , 'keydown keyup change input' , function ( ) { if ( ! editor . opts . height ) { this . rows = 1 ; if ( this . value . length === 0 ) { this . style . height = 'auto' ; }
else { this . style . height = this . scrollHeight + 'px' ; } }
else { this . removeAttribute ( 'rows' ) } } ) ; editor . events . $on ( $html _area , 'blur' , _blur ) ; editor . events . $on ( $html _area , 'focus' , _focus ) ; } }
2016-05-21 21:24:04 +00:00
editor . undo . saveStep ( ) ; editor . html . cleanEmptyTags ( ) ; editor . html . cleanWhiteTags ( true ) ; if ( editor . core . hasFocus ( ) ) { if ( ! editor . core . isEmpty ( ) ) { editor . selection . save ( ) ; editor . $el . find ( '.fr-marker[data-type="true"]:first' ) . replaceWith ( '<span class="fr-tmp fr-sm">F</span>' ) ; editor . $el . find ( '.fr-marker[data-type="false"]:last' ) . replaceWith ( '<span class="fr-tmp fr-em">F</span>' ) ; } }
2019-03-28 16:49:22 +00:00
var html = editor . html . get ( false , true ) ; editor . $el . find ( 'span.fr-tmp' ) . remove ( ) ; editor . $box . toggleClass ( 'fr-code-view' , true ) ; var was _focused = false ; if ( editor . core . hasFocus ( ) ) { was _focused = true ; editor . events . disableBlur ( ) ; editor . $el . blur ( ) ; }
html = html . replace ( /<span class="fr-tmp fr-sm">F<\/span>/ , 'FROALA-SM' ) ; html = html . replace ( /<span class="fr-tmp fr-em">F<\/span>/ , 'FROALA-EM' ) ; if ( editor . codeBeautifier ) { html = editor . codeBeautifier . run ( html , editor . opts . codeBeautifierOptions ) ; }
2016-05-19 18:35:40 +00:00
var s _index ; var e _index ; if ( ace _editor ) { s _index = html . indexOf ( 'FROALA-SM' ) ; e _index = html . indexOf ( 'FROALA-EM' ) ; if ( s _index > e _index ) { s _index = e _index ; }
else { e _index = e _index - 9 ; }
html = html . replace ( /FROALA-SM/g , '' ) . replace ( /FROALA-EM/g , '' )
var s _line = html . substring ( 0 , s _index ) . length - html . substring ( 0 , s _index ) . replace ( /\n/g , '' ) . length ; var e _line = html . substring ( 0 , e _index ) . length - html . substring ( 0 , e _index ) . replace ( /\n/g , '' ) . length ; s _index = html . substring ( 0 , s _index ) . length - html . substring ( 0 , html . substring ( 0 , s _index ) . lastIndexOf ( '\n' ) + 1 ) . length ; e _index = html . substring ( 0 , e _index ) . length - html . substring ( 0 , html . substring ( 0 , e _index ) . lastIndexOf ( '\n' ) + 1 ) . length ; ace _editor . $blockScrolling = Infinity
2019-03-28 16:49:22 +00:00
ace _editor . getSession ( ) . setValue ( html ) ; _can _focus = ! was _focused ; ace _editor . focus ( ) ; _can _focus = true ; ace _editor . selection . moveCursorToPosition ( { row : s _line , column : s _index } ) ; ace _editor . selection . selectToPosition ( { row : e _line , column : e _index } ) ; ace _editor . resize ( ) ; ace _editor . session . getUndoManager ( ) . reset ( ) ; }
2016-05-21 21:24:04 +00:00
else { s _index = html . indexOf ( 'FROALA-SM' ) ; e _index = html . indexOf ( 'FROALA-EM' ) - 9 ; if ( editor . opts . heightMin ) { $html _area . css ( 'min-height' , editor . opts . heightMin ) ; }
2016-07-05 10:08:44 +00:00
if ( editor . opts . height ) { $html _area . css ( 'height' , editor . opts . height ) ; }
if ( editor . opts . heightMax ) { $html _area . css ( 'max-height' , editor . opts . height || editor . opts . heightMax ) ; }
2019-03-28 16:49:22 +00:00
$html _area . val ( html . replace ( /FROALA-SM/g , '' ) . replace ( /FROALA-EM/g , '' ) ) . trigger ( 'change' ) ; var scroll _top = $ ( editor . o _doc ) . scrollTop ( ) ; _can _focus = ! was _focused ; $html _area . focus ( ) ; _can _focus = true ; $html _area . get ( 0 ) . setSelectionRange ( s _index , e _index ) ; $ ( editor . o _doc ) . scrollTop ( scroll _top ) ; }
editor . $tb . find ( ' > .fr-command, > .fr-btn-wrap > .fr-command' ) . not ( $btn ) . filter ( function ( ) { return editor . opts . codeViewKeepActiveButtons . indexOf ( $ ( this ) . data ( 'cmd' ) ) < 0 ; } ) . addClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , true ) ; $btn . addClass ( 'fr-active' ) . attr ( 'aria-pressed' , true ) ; if ( ! editor . helpers . isMobile ( ) && editor . opts . toolbarInline ) { editor . toolbar . hide ( ) ; } }
function toggle ( val ) { if ( typeof val == 'undefined' ) val = ! isActive ( ) ; var $btn = editor . $tb . find ( '.fr-command[data-cmd="html"]' ) ; if ( ! val ) { editor . $box . toggleClass ( 'fr-code-view' , false ) ; _showText ( $btn ) ; }
else { editor . popups . hideAll ( ) ; _showHTML ( $btn ) ; } }
function _destroy ( ) { if ( isActive ( ) ) { toggle ( false ) ; }
2016-05-21 21:24:04 +00:00
$html _area . val ( '' ) . removeData ( ) . remove ( ) ; $html _area = null ; if ( $back _button ) { $back _button . remove ( ) ; $back _button = null ; } }
2019-03-28 16:49:22 +00:00
function _refreshToolbar ( ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="html"]' ) ; if ( ! isActive ( ) ) { editor . $tb . find ( ' > .fr-command' ) . not ( $btn ) . removeClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , false ) ; $btn . removeClass ( 'fr-active' ) . attr ( 'aria-pressed' , false ) ; }
else { editor . $tb . find ( ' > .fr-command' ) . not ( $btn ) . filter ( function ( ) { return editor . opts . codeViewKeepActiveButtons . indexOf ( $ ( this ) . data ( 'cmd' ) ) < 0 ; } ) . addClass ( 'fr-disabled' ) . attr ( 'aria-disabled' , false ) ; $btn . addClass ( 'fr-active' ) . attr ( 'aria-pressed' , false ) ; } }
function _initArea ( ) { $html _area = $ ( '<textarea class="fr-code" tabIndex="-1">' ) ; editor . $wp . append ( $html _area ) ; $html _area . attr ( 'dir' , editor . opts . direction ) ; if ( ! editor . $box . hasClass ( 'fr-basic' ) ) { $back _button = $ ( '<a data-cmd="html" title="Code View" class="fr-command fr-btn html-switch' + ( editor . helpers . isMobile ( ) ? '' : ' fr-desktop' ) + '" role="button" tabIndex="-1"><i class="fa fa-code"></i></button>' ) ; editor . $box . append ( $back _button ) ; editor . events . bindClick ( editor . $box , 'a.html-switch' , function ( ) { editor . events . trigger ( 'commands.before' , [ 'html' ] )
toggle ( false ) ; editor . events . trigger ( 'commands.after' , [ 'html' ] ) } ) ; }
2016-05-19 18:35:40 +00:00
var cancel = function ( ) { return ! isActive ( ) ; }
2019-03-28 16:49:22 +00:00
editor . events . on ( 'buttons.refresh' , cancel ) ; editor . events . on ( 'copy' , cancel , true ) ; editor . events . on ( 'cut' , cancel , true ) ; editor . events . on ( 'paste' , cancel , true ) ; editor . events . on ( 'destroy' , _destroy , true ) ; editor . events . on ( 'html.set' , function ( ) { if ( isActive ( ) ) toggle ( true ) ; } ) ; editor . events . on ( 'codeView.update' , refresh ) ; editor . events . on ( 'form.submit' , function ( ) { if ( isActive ( ) ) { editor . html . set ( get ( ) ) ; editor . events . trigger ( 'contentChanged' , [ ] , true ) ; } } , true ) ; }
var $back _button ; function _init ( ) { editor . events . on ( 'focus' , function ( ) { if ( editor . opts . toolbarContainer ) { _refreshToolbar ( ) } } ) ; if ( ! editor . $wp ) return false ; }
2017-02-08 08:10:24 +00:00
return { _init : _init , toggle : toggle , isActive : isActive , get : get } } ; $ . FE . RegisterCommand ( 'html' , { title : 'Code View' , undo : false , focus : false , forcedRefresh : true , toggle : true , callback : function ( ) { this . codeView . toggle ( ) ; } , plugin : 'codeView' } )
2019-03-28 16:49:22 +00:00
$ . FE . DefineIcon ( 'html' , { NAME : 'code' } ) ; } ) ) ; ! function ( t ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , t ) : "object" == typeof module && module . exports ? module . exports = function ( a , e ) { return e === undefined && ( e = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( a ) ) , t ( e ) } : t ( window . jQuery ) } ( function ( g ) { g . extend ( g . FE . DEFAULTS , { paragraphFormat : { N : "Normal" , H1 : "Heading 1" , H2 : "Heading 2" , H3 : "Heading 3" , H4 : "Heading 4" , PRE : "Code" } , paragraphFormatSelection : ! 1 , paragraphDefaultSelection : "Paragraph Format" } ) , g . FE . PLUGINS . paragraphFormat = function ( h ) { function f ( a , e ) { var t = h . html . defaultTag ( ) ; if ( e && e . toLowerCase ( ) != t ) if ( 0 < a . find ( "ul, ol" ) . length ) { var r = g ( "<" + e + ">" ) ; a . prepend ( r ) ; for ( var n = h . node . contents ( a . get ( 0 ) ) [ 0 ] ; n && [ "UL" , "OL" ] . indexOf ( n . tagName ) < 0 ; ) { var o = n . nextSibling ; r . append ( n ) , n = o } } else a . html ( "<" + e + ">" + a . html ( ) + "</" + e + ">" ) } return { apply : function ( a ) { "N" == a && ( a = h . html . defaultTag ( ) ) , h . selection . save ( ) , h . html . wrap ( ! 0 , ! 0 , ! h . opts . paragraphFormat . BLOCKQUOTE , ! 0 , ! 0 ) , h . selection . restore ( ) ; var e , t , r , n , o , i , p , l , s = h . selection . blocks ( ) ; h . selection . save ( ) , h . $el . find ( "pre" ) . attr ( "skip" , ! 0 ) ; for ( var d = 0 ; d < s . length ; d ++ ) if ( s [ d ] . tagName != a && ! h . node . isList ( s [ d ] ) ) { var m = g ( s [ d ] ) ; "LI" == s [ d ] . tagName ? f ( m , a ) : "LI" == s [ d ] . parentNode . tagName && s [ d ] ? ( i = m , p = a , l = h . html . defaultTag ( ) , p && p . toLowerCase ( ) != l || ( p = 'div class="fr-temp-div"' ) , i . replaceWith ( g ( "<" + p + ">" ) . html ( i . html ( ) ) ) ) : 0 <= [ "TD" , "TH" ] . indexOf ( s [ d ] . parentNode . tagName ) ? ( r = m , n = a , o = h . html . defaultTag ( ) , n || ( n = 'div class="fr-temp-div"' + ( h . node . isEmpty ( r . get ( 0 ) , ! 0 ) ? ' data-empty="true"' : "" ) ) , n . toLowerCase ( ) == o ? ( h . node . isEmpty ( r . get ( 0 ) , ! 0 ) || r . append ( "<br/>" ) , r . replaceWith ( r . html ( ) ) ) : r . replaceWith ( g ( "<" + n + ">" ) . html ( r . html ( ) ) ) ) : ( e = m , ( t = a ) || ( t = 'div class="fr-temp-div"' + ( h . node . isEmpty ( e . get ( 0 ) , ! 0 ) ? ' data-empty="true"' : "" ) ) , e . replaceWith ( g ( "<" + t + " " + h . node . attributes ( e . get ( 0 ) ) + ">" ) . html ( e . html ( ) ) . removeAttr ( "data-empty" ) ) ) } h . $el . find ( 'pre:not([skip="true"]) + pre:not([skip="true"])' ) . each ( function ( ) { g ( this ) . prev ( ) . append ( "<br>" + g ( this ) . html ( ) ) , g ( this ) . remove ( ) } ) , h . $el . find ( "pre" ) . removeAttr ( "skip" ) , h . html . unwrap ( ) , h . selection . restore ( ) } , refreshOnShow : function ( a , e ) { var t = h . selection . blocks ( ) ; if ( t . length ) { var r = t [ 0 ] , n = "N" , o = h . html . defaultTag ( ) ; r . tagName . toLowerCase ( ) != o && r != h . el && ( n = r . tagName ) , e . find ( '.fr-command[data-param1="' + n + '"]' ) . addClass ( "fr-active" ) . attr ( "aria-selected" , ! 0 ) } else e . find ( '.fr-command[data-param1="N"]' ) . addClass ( "fr-active" ) . attr ( "aria-selected" , ! 0 ) } , refresh : function ( a ) { if ( h . opts . paragraphFormatSelection ) { var e = h . selection . blocks ( ) ; if ( e . length ) { var t = e [ 0 ] , r = "N" , n = h . html . defaultTag ( ) ; t . tagName . toLowerCase ( ) != n && t != h . el && ( r = t . tagName ) , 0 <= [ "LI" , "TD" , "TH" ] . indexOf ( r ) && ( r = "N" ) , a . find ( "> span" ) . text ( h . language . translate ( h . opts . paragraphFormat [ r ] ) ) } else a . find ( "> span" ) . text ( h . language . translate ( h . opts . paragraphFormat . N ) ) } } } } , g . FE . RegisterCommand ( "paragraphFormat" , { type : "dropdown" , displaySelection : function ( a ) { return a . opts . paragraphFormatSelection } , defaultSelection : function ( a ) { return a . language . translate ( a . opts . paragraphDefaultSelection ) } , displaySelectionWidth : 125 , html : function ( ) { var a = '<ul class="fr-dropdown-list" role="presentation">' , e = this . opts . paragraphFormat ; for ( var t in e ) if ( e . hasOwnProperty ( t ) ) { var r = this . shortcuts . get ( "paragraphFormat." + t ) ; r = r ? '<span class="fr-shortcut">' + r + "</span>" : "" , a += '<li role="presentation"><' + ( "N" == t ? this . html . defaultTag ( ) || "DIV" : t ) + ' style="padding: 0 !important; margin: 0 !important;" role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="paragraphFormat" data-param1="' + t + '" title="' + this . language . translate ( e [ t ] ) + '">' + this . language . translate ( e [ t ] ) + "</a></" + ( "N" == t ? this . html . defaultTag ( ) || "DIV" : t ) + "></li>" } return a += "</ul>" } , title : "Paragraph Format" , callback : function ( a , e ) { this . paragraphFormat . apply ( e ) } , refresh : function ( a ) { this . paragraphFormat . refresh ( a ) } , refreshOnShow : function ( a , e ) { this . paragraphFormat . refreshOnShow ( a , e ) } , plugin : "paragraphFormat" } ) , g . FE . DefineIcon ( "paragraphFormat" , { NAME : "paragraph" } ) } ) ; ! function ( t ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , t ) : "object" == typeof module && module . exports ? module . exports = function ( e , n
2016-05-21 02:38:04 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
2017-02-08 08:10:24 +00:00
factory ( jQuery ) ; return jQuery ; } ; } else { factory ( jQuery ) ; } } ( function ( $ ) { $ . extend ( $ . FE . POPUP _TEMPLATES , { 'file.insert' : '[_BUTTONS_][_UPLOAD_LAYER_][_BY_URL_LAYER_][_PROGRESS_BAR_]' } )
2016-05-21 02:38:04 +00:00
$ . extend ( $ . FE . DEFAULTS , { fileUploadURL : 'http://i.froala.com/upload' , fileUploadParam : 'file' , fileUploadParams : { } , fileUploadToS3 : false , fileUploadMethod : 'POST' , fileMaxSize : 10 * 1024 * 1024 , fileAllowedTypes : [ '*' ] , fileInsertButtons : [ 'fileBack' , '|' , 'fileUpload' , 'fileByURL' ] , fileUseSelectedText : false } ) ; $ . FE . PLUGINS . file = function ( editor ) { var BAD _LINK = 1 ; var MISSING _LINK = 2 ; var ERROR _DURING _UPLOAD = 3 ; var BAD _RESPONSE = 4 ; var MAX _SIZE _EXCEEDED = 5 ; var BAD _FILE _TYPE = 6 ; var NO _CORS _IE = 7 ; var error _messages = { } ; error _messages [ BAD _LINK ] = 'File cannot be loaded from the passed link.' ; error _messages [ MISSING _LINK ] = 'No link in upload response.' ; error _messages [ ERROR _DURING _UPLOAD ] = 'Error during file upload.' ; error _messages [ BAD _RESPONSE ] = 'Parsing response failed.' ; error _messages [ MAX _SIZE _EXCEEDED ] = 'File is too large.' ; error _messages [ BAD _FILE _TYPE ] = 'File file type is invalid.' ; error _messages [ NO _CORS _IE ] = 'Files can be uploaded only to same domain in IE 8 and IE 9.' ; function showInsertPopup ( ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertFile"]' ) ; var $popup = editor . popups . get ( 'file.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; hideProgressBar ( ) ; if ( ! $popup . hasClass ( 'fr-active' ) ) { editor . popups . refresh ( 'file.insert' ) ; editor . popups . setContainer ( 'file.insert' , editor . $tb ) ; var left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; var top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; editor . popups . show ( 'file.insert' , left , top , $btn . outerHeight ( ) ) ; } }
2016-05-21 21:24:04 +00:00
function showProgressBar ( ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; $popup . find ( '.fr-layer.fr-active' ) . removeClass ( 'fr-active' ) . addClass ( 'fr-pactive' ) ; $popup . find ( '.fr-file-progress-bar-layer' ) . addClass ( 'fr-active' ) ; $popup . find ( '.fr-buttons' ) . hide ( ) ; _setProgressMessage ( 'Uploading' , 0 ) ; }
2017-02-08 08:10:24 +00:00
function hideProgressBar ( dismiss ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup ) { $popup . find ( '.fr-layer.fr-pactive' ) . addClass ( 'fr-active' ) . removeClass ( 'fr-pactive' ) ; $popup . find ( '.fr-file-progress-bar-layer' ) . removeClass ( 'fr-active' ) ; $popup . find ( '.fr-buttons' ) . show ( ) ; if ( dismiss ) { editor . events . focus ( ) ; editor . popups . hide ( 'file.insert' ) ; } } }
2016-05-21 02:38:04 +00:00
function _setProgressMessage ( message , progress ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup ) { var $layer = $popup . find ( '.fr-file-progress-bar-layer' ) ; $layer . find ( 'h3' ) . text ( message + ( progress ? ' ' + progress + '%' : '' ) ) ; $layer . removeClass ( 'fr-error' ) ; if ( progress ) { $layer . find ( 'div' ) . removeClass ( 'fr-indeterminate' ) ; $layer . find ( 'div > span' ) . css ( 'width' , progress + '%' ) ; }
else { $layer . find ( 'div' ) . addClass ( 'fr-indeterminate' ) ; } } }
2017-02-08 08:10:24 +00:00
function _showErrorMessage ( message ) { showProgressBar ( ) ; var $popup = editor . popups . get ( 'file.insert' ) ; var $layer = $popup . find ( '.fr-file-progress-bar-layer' ) ; $layer . addClass ( 'fr-error' ) ; var $message _header = $layer . find ( 'h3' ) ; $message _header . text ( message ) ; editor . events . disableBlur ( ) ; $message _header . focus ( ) ; }
2016-05-21 02:38:04 +00:00
function insertByURL ( ) { var $popup = editor . popups . get ( 'file.insert' ) ; var $input = $popup . find ( '.fr-file-by-url-layer input' ) ; var url = $input . val ( )
if ( url . length > 0 ) { var filename = url . substring ( url . lastIndexOf ( '/' ) + 1 ) ; insert ( editor . helpers . sanitizeURL ( $input . val ( ) ) , filename , [ ] ) ; $input . val ( '' ) ; $input . blur ( ) ; } }
2017-02-08 08:10:24 +00:00
function insert ( link , text , response ) { editor . edit . on ( ) ; editor . events . focus ( true ) ; editor . selection . restore ( ) ; if ( editor . opts . fileUseSelectedText && editor . selection . text ( ) . length ) { text = editor . selection . text ( ) ; }
editor . html . insert ( '<a href="' + link + '" id="fr-inserted-file" class="fr-file">' + text + '</a>' ) ; var $file = editor . $el . find ( '#fr-inserted-file' ) ; $file . removeAttr ( 'id' ) ; editor . popups . hide ( 'file.insert' ) ; editor . undo . saveStep ( ) ; _syncFiles ( ) ; editor . events . trigger ( 'file.inserted' , [ $file , response ] ) ; }
2016-05-21 02:38:04 +00:00
function _parseResponse ( response ) { try { if ( editor . events . trigger ( 'file.uploaded' , [ response ] , true ) === false ) { editor . edit . on ( ) ; return false ; }
var resp = $ . parseJSON ( response ) ; if ( resp . link ) { return resp ; } else { _throwError ( MISSING _LINK , response ) ; return false ; } } catch ( ex ) { _throwError ( BAD _RESPONSE , response ) ; return false ; } }
function _parseXMLResponse ( response ) { try { var link = $ ( response ) . find ( 'Location' ) . text ( ) ; var key = $ ( response ) . find ( 'Key' ) . text ( ) ; if ( editor . events . trigger ( 'file.uploadedToS3' , [ link , key , response ] , true ) === false ) { editor . edit . on ( ) ; return false ; }
return link ; } catch ( ex ) { _throwError ( BAD _RESPONSE , response ) ; return false ; } }
function _fileUploaded ( text ) { var status = this . status ; var response = this . response ; var responseXML = this . responseXML ; var responseText = this . responseText ; try { if ( editor . opts . fileUploadToS3 ) { if ( status == 201 ) { var link = _parseXMLResponse ( responseXML ) ; if ( link ) { insert ( link , text , response || responseXML ) ; } } else { _throwError ( BAD _RESPONSE , response || responseXML ) ; } }
else { if ( status >= 200 && status < 300 ) { var resp = _parseResponse ( responseText ) ; if ( resp ) { insert ( resp . link , text , response || responseText ) ; } }
else { _throwError ( ERROR _DURING _UPLOAD , response || responseText ) ; } } } catch ( ex ) { _throwError ( BAD _RESPONSE , response || responseText ) ; } }
function _fileUploadError ( ) { _throwError ( BAD _RESPONSE , this . response || this . responseText || this . responseXML ) ; }
function _fileUploadProgress ( e ) { if ( e . lengthComputable ) { var complete = ( e . loaded / e . total * 100 | 0 ) ; _setProgressMessage ( 'Uploading' , complete ) ; } }
function _throwError ( code , response ) { editor . edit . on ( ) ; _showErrorMessage ( editor . language . translate ( 'Something went wrong. Please try again.' ) ) ; editor . events . trigger ( 'file.error' , [ { code : code , message : error _messages [ code ] } , response ] ) ; }
function _fileUploadAborted ( ) { editor . edit . on ( ) ; hideProgressBar ( true ) ; }
2017-02-08 08:10:24 +00:00
function upload ( files ) { if ( typeof files != 'undefined' && files . length > 0 ) { if ( editor . events . trigger ( 'file.beforeUpload' , [ files ] ) === false ) { return false ; }
var file = files [ 0 ] ; if ( file . size > editor . opts . fileMaxSize ) { _throwError ( MAX _SIZE _EXCEEDED ) ; return false ; }
2016-05-21 02:38:04 +00:00
if ( editor . opts . fileAllowedTypes . indexOf ( '*' ) < 0 && editor . opts . fileAllowedTypes . indexOf ( file . type . replace ( /file\//g , '' ) ) < 0 ) { _throwError ( BAD _FILE _TYPE ) ; return false ; }
var form _data ; if ( editor . drag _support . formdata ) { form _data = editor . drag _support . formdata ? new FormData ( ) : null ; }
if ( form _data ) { var key ; if ( editor . opts . fileUploadToS3 !== false ) { form _data . append ( 'key' , editor . opts . fileUploadToS3 . keyStart + ( new Date ( ) ) . getTime ( ) + '-' + ( file . name || 'untitled' ) ) ; form _data . append ( 'success_action_status' , '201' ) ; form _data . append ( 'X-Requested-With' , 'xhr' ) ; form _data . append ( 'Content-Type' , file . type ) ; for ( key in editor . opts . fileUploadToS3 . params ) { if ( editor . opts . fileUploadToS3 . params . hasOwnProperty ( key ) ) { form _data . append ( key , editor . opts . fileUploadToS3 . params [ key ] ) ; } } }
for ( key in editor . opts . fileUploadParams ) { if ( editor . opts . fileUploadParams . hasOwnProperty ( key ) ) { form _data . append ( key , editor . opts . fileUploadParams [ key ] ) ; } }
2017-02-08 08:10:24 +00:00
form _data . append ( editor . opts . fileUploadParam , file ) ; var url = editor . opts . fileUploadURL ; if ( editor . opts . fileUploadToS3 ) { if ( editor . opts . fileUploadToS3 . uploadURL ) { url = editor . opts . fileUploadToS3 . uploadURL ; }
else { url = 'https://' + editor . opts . fileUploadToS3 . region + '.amazonaws.com/' + editor . opts . fileUploadToS3 . bucket ; } }
var xhr = editor . core . getXHR ( url , editor . opts . fileUploadMethod ) ; xhr . onload = function ( ) { _fileUploaded . call ( xhr , file . name ) ; } ; xhr . onerror = _fileUploadError ; xhr . upload . onprogress = _fileUploadProgress ; xhr . onabort = _fileUploadAborted ; showProgressBar ( ) ; editor . edit . off ( ) ; var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup ) { $popup . off ( 'abortUpload' ) . on ( 'abortUpload' , function ( ) { if ( xhr . readyState != 4 ) { xhr . abort ( ) ; } } ) }
2016-05-21 02:38:04 +00:00
xhr . send ( form _data ) ; } } }
function _bindInsertEvents ( $popup ) { editor . events . $on ( $popup , 'dragover dragenter' , '.fr-file-upload-layer' , function ( ) { $ ( this ) . addClass ( 'fr-drop' ) ; return false ; } , true ) ; editor . events . $on ( $popup , 'dragleave dragend' , '.fr-file-upload-layer' , function ( ) { $ ( this ) . removeClass ( 'fr-drop' ) ; return false ; } , true ) ; editor . events . $on ( $popup , 'drop' , '.fr-file-upload-layer' , function ( e ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; $ ( this ) . removeClass ( 'fr-drop' ) ; var dt = e . originalEvent . dataTransfer ; if ( dt && dt . files ) { var inst = $popup . data ( 'instance' ) || editor ; inst . file . upload ( dt . files ) ; } } , true ) ; editor . events . $on ( $popup , 'change' , '.fr-file-upload-layer input[type="file"]' , function ( ) { if ( this . files ) { var inst = $popup . data ( 'instance' ) || editor ; inst . file . upload ( this . files ) ; }
$ ( this ) . val ( '' ) ; } , true ) ; }
function _hideInsertPopup ( ) { hideProgressBar ( ) ; }
function _initInsertPopup ( delayed ) { if ( delayed ) { editor . popups . onHide ( 'file.insert' , _hideInsertPopup ) ; return true ; }
var active ; var file _buttons = '' ; if ( editor . opts . fileInsertButtons . length > 1 ) { file _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . fileInsertButtons ) + '</div>' ; }
var uploadIndex = editor . opts . fileInsertButtons . indexOf ( 'fileUpload' ) ; var urlIndex = editor . opts . fileInsertButtons . indexOf ( 'fileByURL' ) ; var upload _layer = '' ; if ( uploadIndex >= 0 ) { active = ' fr-active' ; if ( urlIndex >= 0 && uploadIndex > urlIndex ) { active = '' ; }
2017-02-08 08:10:24 +00:00
upload _layer = '<div class="fr-file-upload-layer' + active + ' fr-layer fr-active" id="fr-file-upload-layer-' + editor . id + '"><strong>' + editor . language . translate ( 'Drop file' ) + '</strong><br>(' + editor . language . translate ( 'or click' ) + ')<div class="fr-form"><input type="file" name="' + editor . opts . fileUploadParam + '" accept="/*" tabIndex="-1" aria-labelledby="fr-file-upload-layer-' + editor . id + '" role="button"></div></div>' }
2016-05-21 02:38:04 +00:00
var by _url _layer = '' ; if ( urlIndex >= 0 ) { active = ' fr-active' ; if ( uploadIndex >= 0 && urlIndex > uploadIndex ) { active = '' ; }
by _url _layer = '<div class="fr-file-by-url-layer' + active + ' fr-layer" id="fr-file-by-url-layer-' + editor . id + '"><div class="fr-input-line"><input type="text" placeholder="http://" tabIndex="1"></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="fileInsertByURL" tabIndex="2">' + editor . language . translate ( 'Insert' ) + '</button></div></div>' }
2017-02-08 08:10:24 +00:00
var progress _bar _layer = '<div class="fr-file-progress-bar-layer fr-layer"><h3 tabIndex="-1" class="fr-message">Uploading</h3><div class="fr-loader"><span class="fr-progress"></span></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-dismiss" data-cmd="fileDismissError" tabIndex="2" role="button">OK</button></div></div>' ; var template = { buttons : file _buttons , upload _layer : upload _layer , by _url _layer : by _url _layer , progress _bar : progress _bar _layer } ; var $popup = editor . popups . create ( 'file.insert' , template ) ; _bindInsertEvents ( $popup ) ; return $popup ; }
function _onRemove ( link ) { if ( editor . node . hasClass ( link , 'fr-file' ) ) { return editor . events . trigger ( 'file.unlink' , [ link ] ) ; } }
function _drop ( e ) { var dt = e . originalEvent . dataTransfer ; if ( dt && dt . files && dt . files . length ) { var file = dt . files [ 0 ] ; if ( file && typeof file . type != 'undefined' ) { if ( file . type . indexOf ( 'image' ) < 0 && ( editor . opts . fileAllowedTypes . indexOf ( file . type ) >= 0 || editor . opts . fileAllowedTypes . indexOf ( '*' ) >= 0 ) ) { editor . markers . remove ( ) ; editor . markers . insertAtPoint ( e . originalEvent ) ; editor . $el . find ( '.fr-marker' ) . replaceWith ( $ . FE . MARKERS ) ; editor . popups . hideAll ( ) ; var $popup = editor . popups . get ( 'file.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; editor . popups . setContainer ( 'file.insert' , editor . $sc ) ; editor . popups . show ( 'file.insert' , e . originalEvent . pageX , e . originalEvent . pageY ) ; showProgressBar ( ) ; upload ( dt . files ) ; e . preventDefault ( ) ; e . stopPropagation ( ) ; return false ; } } } }
2016-05-21 21:24:04 +00:00
function _initEvents ( ) { editor . events . on ( 'drop' , _drop ) ; editor . events . $on ( editor . $win , 'keydown' , function ( e ) { var key _code = e . which ; var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup && key _code == $ . FE . KEYCODE . ESC ) { $popup . trigger ( 'abortUpload' ) ; } } ) ; editor . events . on ( 'destroy' , function ( ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup ) { $popup . trigger ( 'abortUpload' ) ; } } ) ; }
2016-05-21 02:38:04 +00:00
function back ( ) { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; editor . popups . hide ( 'file.insert' ) ; editor . toolbar . showInline ( ) ; }
2017-02-08 08:10:24 +00:00
var files ; function _syncFiles ( ) { var c _files = Array . prototype . slice . call ( editor . el . querySelectorAll ( 'a.fr-file' ) ) ; var file _srcs = [ ] ; var i ; for ( i = 0 ; i < c _files . length ; i ++ ) { file _srcs . push ( c _files [ i ] . getAttribute ( 'href' ) ) ; }
if ( files ) { for ( i = 0 ; i < files . length ; i ++ ) { if ( file _srcs . indexOf ( files [ i ] . getAttribute ( 'href' ) ) < 0 ) { editor . events . trigger ( 'file.unlink' , [ files [ i ] ] ) ; } } }
files = c _files ; }
2016-05-21 02:38:04 +00:00
function showLayer ( name ) { var $popup = editor . popups . get ( 'file.insert' ) ; var left ; var top ; if ( ! editor . opts . toolbarInline ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertFile"]' ) ; left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; }
else { top = $popup . offset ( ) . top - editor . helpers . getPX ( $popup . css ( 'margin-top' ) ) ; if ( $popup . hasClass ( 'fr-above' ) ) { top += $popup . outerHeight ( ) ; } }
$popup . find ( '.fr-layer' ) . removeClass ( 'fr-active' ) ; $popup . find ( '.fr-' + name + '-layer' ) . addClass ( 'fr-active' ) ; editor . popups . show ( 'file.insert' , left , top , 0 ) ; }
function refreshUploadButton ( $btn ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup . find ( '.fr-file-upload-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
function refreshByURLButton ( $btn ) { var $popup = editor . popups . get ( 'file.insert' ) ; if ( $popup . find ( '.fr-file-by-url-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
2017-02-08 08:10:24 +00:00
function _init ( ) { _initEvents ( ) ; editor . events . on ( 'link.beforeRemove' , _onRemove ) ; if ( editor . $wp ) { _syncFiles ( ) ; editor . events . on ( 'contentChanged' , _syncFiles ) ; }
_initInsertPopup ( true ) ; }
2016-05-21 02:38:04 +00:00
return { _init : _init , showInsertPopup : showInsertPopup , showLayer : showLayer , refreshUploadButton : refreshUploadButton , refreshByURLButton : refreshByURLButton , insertByURL : insertByURL , upload : upload , insert : insert , back : back , hideProgressBar : hideProgressBar } }
$ . FE . DefineIcon ( 'insertFile' , { NAME : 'file-o' } ) ; $ . FE . RegisterCommand ( 'insertFile' , { title : 'Insert File' , undo : false , focus : true , refreshAfterCallback : false , popup : true , callback : function ( ) { if ( ! this . popups . isVisible ( 'file.insert' ) ) { this . file . showInsertPopup ( ) ; }
2017-02-08 08:10:24 +00:00
else { if ( this . $el . find ( '.fr-marker' ) . length ) { this . events . disableBlur ( ) ; this . selection . restore ( ) ; }
2016-05-21 02:38:04 +00:00
this . popups . hide ( 'file.insert' ) ; } } , plugin : 'file' } ) ; $ . FE . DefineIcon ( 'fileUpload' , { NAME : 'upload' } ) ; $ . FE . RegisterCommand ( 'fileUpload' , { title : 'Upload File' , undo : false , focus : false , callback : function ( ) { this . file . showLayer ( 'file-upload' ) ; } , refresh : function ( $btn ) { this . file . refreshUploadButton ( $btn ) ; } } ) ; $ . FE . DefineIcon ( 'fileByURL' , { NAME : 'link' } ) ; $ . FE . RegisterCommand ( 'fileByURL' , { title : 'By URL' , undo : false , focus : false , callback : function ( ) { this . file . showLayer ( 'file-by-url' ) ; } , refresh : function ( $btn ) { this . file . refreshByURLButton ( $btn ) ; } } )
$ . FE . RegisterCommand ( 'fileInsertByURL' , { title : 'Insert File' , undo : true , refreshAfterCallback : false , callback : function ( ) { this . file . insertByURL ( ) ; } , refresh : function ( $btn ) { $btn . text ( this . language . translate ( 'Insert' ) ) ; } } )
$ . FE . DefineIcon ( 'fileBack' , { NAME : 'arrow-left' } ) ; $ . FE . RegisterCommand ( 'fileBack' , { title : 'Back' , undo : false , focus : false , back : true , refreshAfterCallback : false , callback : function ( ) { this . file . back ( ) ; } , refresh : function ( $btn ) { if ( ! this . opts . toolbarInline ) { $btn . addClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . addClass ( 'fr-hidden' ) ; }
2019-06-01 04:43:07 +00:00
else { $btn . removeClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . removeClass ( 'fr-hidden' ) ; } } } ) ; $ . FE . RegisterCommand ( 'fileDismissError' , { title : 'OK' , callback : function ( ) { this . file . hideProgressBar ( true ) ; } } ) } ) ) ; ! function ( a ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , a ) : "object" == typeof module && module . exports ? module . exports = function ( e , t ) { return t === undefined && ( t = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( e ) ) , a ( t ) } : a ( window . jQuery ) } ( function ( be ) { be . extend ( be . FE . POPUP _TEMPLATES , { "image.insert" : "[_BUTTONS_][_UPLOAD_LAYER_][_BY_URL_LAYER_][_PROGRESS_BAR_]" , "image.edit" : "[_BUTTONS_]" , "image.alt" : "[_BUTTONS_][_ALT_LAYER_]" , "image.size" : "[_BUTTONS_][_SIZE_LAYER_]" } ) , be . extend ( be . FE . DEFAULTS , { imageInsertButtons : [ "imageBack" , "|" , "imageUpload" , "imageByURL" ] , imageEditButtons : [ "imageReplace" , "imageAlign" , "imageCaption" , "imageRemove" , "|" , "imageLink" , "linkOpen" , "linkEdit" , "linkRemove" , "-" , "imageDisplay" , "imageStyle" , "imageAlt" , "imageSize" ] , imageAltButtons : [ "imageBack" , "|" ] , imageSizeButtons : [ "imageBack" , "|" ] , imageUpload : ! 0 , imageUploadURL : null , imageCORSProxy : "https://cors-anywhere.froala.com" , imageUploadRemoteUrls : ! 0 , imageUploadParam : "file" , imageUploadParams : { } , imageUploadToS3 : ! 1 , imageUploadMethod : "POST" , imageMaxSize : 10485760 , imageAllowedTypes : [ "jpeg" , "jpg" , "png" , "gif" , "webp" ] , imageResize : ! 0 , imageResizeWithPercent : ! 1 , imageRoundPercent : ! 1 , imageDefaultWidth : 300 , imageDefaultAlign : "center" , imageDefaultDisplay : "block" , imageSplitHTML : ! 1 , imageStyles : { "fr-rounded" : "Rounded" , "fr-bordered" : "Bordered" , "fr-shadow" : "Shadow" } , imageMove : ! 0 , imageMultipleStyles : ! 0 , imageTextNear : ! 0 , imagePaste : ! 0 , imagePasteProcess : ! 1 , imageMinWidth : 16 , imageOutputSize : ! 1 , imageDefaultMargin : 5 , imageAddNewLine : ! 1 } ) , be . FE . PLUGINS . image = function ( g ) { var d , l , f , p , o , a , c = "https://i.froala.com/upload" , t = ! 1 , i = 1 , u = 2 , m = 3 , h = 4 , v = 5 , b = 6 , r = { } ; function y ( ) { var e = g . popups . get ( "image.insert" ) . find ( ".fr-image-by-url-layer input" ) ; e . val ( "" ) , d && e . val ( d . attr ( "src" ) ) , e . trigger ( "change" ) } function n ( ) { var e = g . popups . get ( "image.edit" ) ; if ( e || ( e = U ( ) ) , e ) { var t = he ( ) ; ve ( ) && ( t = t . find ( ".fr-img-wrap" ) ) , g . popups . setContainer ( "image.edit" , g . $sc ) , g . popups . refresh ( "image.edit" ) ; var a = t . offset ( ) . left + t . outerWidth ( ) / 2 , i = t . offset ( ) . top + t . outerHeight ( ) ; d . hasClass ( "fr-uploading" ) ? I ( ) : g . popups . show ( "image.edit" , a , i , t . outerHeight ( ) ) } } function w ( ) { $ ( ) } function e ( ) { for ( var e , t , a = "IMG" == g . el . tagName ? [ g . el ] : g . el . querySelectorAll ( "img" ) , i = 0 ; i < a . length ; i ++ ) { var r = be ( a [ i ] ) ; ! g . opts . htmlUntouched && g . opts . useClasses ? ( ( g . opts . imageDefaultAlign || g . opts . imageDefaultDisplay ) && ( 0 < ( t = r ) . parents ( ".fr-img-caption" ) . length && ( t = t . parents ( ".fr-img-caption:first" ) ) , t . hasClass ( "fr-dii" ) || t . hasClass ( "fr-dib" ) || ( t . addClass ( "fr-fi" + ge ( t ) [ 0 ] ) , t . addClass ( "fr-di" + de ( t ) [ 0 ] ) , t . css ( "margin" , "" ) , t . css ( "float" , "" ) , t . css ( "display" , "" ) , t . css ( "z-index" , "" ) , t . css ( "position" , "" ) , t . css ( "overflow" , "" ) , t . css ( "vertical-align" , "" ) ) ) , g . opts . imageTextNear || ( 0 < r . parents ( ".fr-img-caption" ) . length ? r . parents ( ".fr-img-caption:first" ) . removeClass ( "fr-dii" ) . addClass ( "fr-dib" ) : r . removeClass ( "fr-dii" ) . addClass ( "fr-dib" ) ) ) : g . opts . htmlUntouched || g . opts . useClasses || ( g . opts . imageDefaultAlign || g . opts . imageDefaultDisplay ) && ( 0 < ( e = r ) . parents ( ".fr-img-caption" ) . length && ( e = e . parents ( ".fr-img-caption:first" ) ) , pe ( e , e . hasClass ( "fr-dib" ) ? "block" : e . hasClass ( "fr-dii" ) ? "inline" : null , e . hasClass ( "fr-fil" ) ? "left" : e . hasClass ( "fr-fir" ) ? "right" : ge ( e ) ) , e . removeClass ( "fr-dib fr-dii fr-fir fr-fil" ) ) , g . opts . iframe && r . on ( "load" , g . size . syncIframe ) } } function E ( e ) { void 0 === e && ( e = ! 0 ) ; var t , a = Array . prototype . slice . call ( g . el . querySelectorAll ( "img" ) ) , i = [ ] ; for ( t = 0 ; t < a . length ; t ++ ) if ( i . push ( a [ t ] . getAttribute ( "src" ) ) , be ( a [ t ] ) . toggleClass ( "fr-draggable" , g . opts . imageMove ) , "" === a [ t ] . getAttribute ( "class" ) && a [ t ] . removeAttribute ( "class" ) , "" === a [ t ] . getAttribute ( "style" ) && a [ t ] . removeAttribute ( "style" ) , a [ t ] . parentNode && a [ t ] . parentNode . parentNode && g . node . hasClass ( a [ t ] . parentNode . parentNode , "fr-img-caption" ) ) { var r = a [ t ] . parentNode . parentNode ; g . browser . mozilla || r . setAttribute ( "contenteditable" , ! 1 ) , r . setAttribute ( "draggable" , ! 1 ) , r . classList . add ( "fr-draggable" ) ; var n = a [ t ] . nextSibling ; n && ! g . browser . mozil
2016-05-19 18:35:40 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
2019-03-28 16:49:22 +00:00
return factory ( jQuery ) ; } ; } else { factory ( window . jQuery ) ; } } ( function ( $ ) { $ . extend ( $ . FE . POPUP _TEMPLATES , { 'link.edit' : '[_BUTTONS_]' , 'link.insert' : '[_BUTTONS_][_INPUT_LAYER_]' } )
$ . extend ( $ . FE . DEFAULTS , { linkEditButtons : [ 'linkOpen' , 'linkStyle' , 'linkEdit' , 'linkRemove' ] , linkInsertButtons : [ 'linkBack' , '|' , 'linkList' ] , linkAttributes : { } , linkAutoPrefix : 'http://' , linkStyles : { 'fr-green' : 'Green' , 'fr-strong' : 'Thick' } , linkMultipleStyles : true , linkConvertEmailAddress : true , linkAlwaysBlank : false , linkAlwaysNoFollow : false , linkNoOpener : true , linkNoReferrer : true , linkList : [ { text : 'Froala' , href : 'https://froala.com' , target : '_blank' } , { text : 'Google' , href : 'https://google.com' , target : '_blank' } , { displayText : 'Facebook' , href : 'https://facebook.com' } ] , linkText : true } ) ; $ . FE . PLUGINS . link = function ( editor ) { function get ( ) { var $current _image = editor . image ? editor . image . get ( ) : null ; if ( ! $current _image && editor . $wp ) { var c _el = editor . selection . ranges ( 0 ) . commonAncestorContainer ; try { if ( c _el && ( ( c _el . contains && c _el . contains ( editor . el ) ) || ! editor . el . contains ( c _el ) || editor . el == c _el ) ) c _el = null ; }
catch ( ex ) { c _el = null ; }
if ( c _el && c _el . tagName === 'A' ) return c _el ; var s _el = editor . selection . element ( ) ; var e _el = editor . selection . endElement ( ) ; if ( s _el . tagName != 'A' && ! editor . node . isElement ( s _el ) ) { s _el = $ ( s _el ) . parentsUntil ( editor . $el , 'a:first' ) . get ( 0 ) ; }
2016-07-05 10:08:44 +00:00
if ( e _el . tagName != 'A' && ! editor . node . isElement ( e _el ) ) { e _el = $ ( e _el ) . parentsUntil ( editor . $el , 'a:first' ) . get ( 0 ) ; }
2019-03-28 16:49:22 +00:00
try { if ( e _el && ( ( e _el . contains && e _el . contains ( editor . el ) ) || ! editor . el . contains ( e _el ) || editor . el == e _el ) ) e _el = null ; }
catch ( ex ) { e _el = null ; }
try { if ( s _el && ( ( s _el . contains && s _el . contains ( editor . el ) ) || ! editor . el . contains ( s _el ) || editor . el == s _el ) ) s _el = null ; }
catch ( ex ) { s _el = null ; }
if ( e _el && e _el == s _el && e _el . tagName == 'A' ) { if ( ( editor . browser . msie || editor . helpers . isMobile ( ) ) && ( editor . selection . info ( s _el ) . atEnd || editor . selection . info ( s _el ) . atStart ) ) { return null ; }
return s _el ; }
2016-05-19 18:35:40 +00:00
return null ; }
2017-02-08 08:10:24 +00:00
else if ( editor . el . tagName == 'A' ) { return editor . el ; }
2016-05-19 18:35:40 +00:00
else { if ( $current _image && $current _image . get ( 0 ) . parentNode && $current _image . get ( 0 ) . parentNode . tagName == 'A' ) { return $current _image . get ( 0 ) . parentNode ; } } }
function allSelected ( ) { var $current _image = editor . image ? editor . image . get ( ) : null ; var selectedLinks = [ ] ; if ( $current _image ) { if ( $current _image . get ( 0 ) . parentNode . tagName == 'A' ) { selectedLinks . push ( $current _image . get ( 0 ) . parentNode ) ; } }
else { var range ; var containerEl ; var links ; var linkRange ; if ( editor . win . getSelection ) { var sel = editor . win . getSelection ( ) ; if ( sel . getRangeAt && sel . rangeCount ) { linkRange = editor . doc . createRange ( ) ; for ( var r = 0 ; r < sel . rangeCount ; ++ r ) { range = sel . getRangeAt ( r ) ; containerEl = range . commonAncestorContainer ; if ( containerEl && containerEl . nodeType != 1 ) { containerEl = containerEl . parentNode ; }
2019-03-28 16:49:22 +00:00
if ( containerEl && containerEl . nodeName . toLowerCase ( ) == 'a' ) { selectedLinks . push ( containerEl ) ; }
else { links = containerEl . getElementsByTagName ( 'a' ) ; for ( var i = 0 ; i < links . length ; ++ i ) { linkRange . selectNodeContents ( links [ i ] ) ; if ( linkRange . compareBoundaryPoints ( range . END _TO _START , range ) < 1 && linkRange . compareBoundaryPoints ( range . START _TO _END , range ) > - 1 ) { selectedLinks . push ( links [ i ] ) ; } } } } } }
else if ( editor . doc . selection && editor . doc . selection . type != 'Control' ) { range = editor . doc . selection . createRange ( ) ; containerEl = range . parentElement ( ) ; if ( containerEl . nodeName . toLowerCase ( ) == 'a' ) { selectedLinks . push ( containerEl ) ; }
else { links = containerEl . getElementsByTagName ( 'a' ) ; linkRange = editor . doc . body . createTextRange ( ) ; for ( var j = 0 ; j < links . length ; ++ j ) { linkRange . moveToElementText ( links [ j ] ) ; if ( linkRange . compareEndPoints ( 'StartToEnd' , range ) > - 1 && linkRange . compareEndPoints ( 'EndToStart' , range ) < 1 ) { selectedLinks . push ( links [ j ] ) ; } } } } }
2016-05-19 18:35:40 +00:00
return selectedLinks ; }
2019-03-28 16:49:22 +00:00
function _edit ( e ) { if ( editor . core . hasFocus ( ) ) { _hideEditPopup ( ) ; if ( e && e . type === 'keyup' && ( e . altKey || e . which == $ . FE . KEYCODE . ALT ) ) return true ; setTimeout ( function ( ) { if ( ! e || ( e && ( e . which == 1 || e . type != 'mouseup' ) ) ) { var link = get ( ) ; var $current _image = editor . image ? editor . image . get ( ) : null ; if ( link && ! $current _image ) { if ( editor . image ) { var contents = editor . node . contents ( link ) ; if ( contents . length == 1 && contents [ 0 ] . tagName == 'IMG' ) { var range = editor . selection . ranges ( 0 ) ; if ( range . startOffset === 0 && range . endOffset === 0 ) { $ ( link ) . before ( $ . FE . MARKERS ) ; }
2016-05-19 18:35:40 +00:00
else { $ ( link ) . after ( $ . FE . MARKERS ) ; }
editor . selection . restore ( ) ; return false ; } }
if ( e ) { e . stopPropagation ( ) ; }
2019-03-28 16:49:22 +00:00
_showEditPopup ( link ) ; } } } , editor . helpers . isIOS ( ) ? 100 : 0 ) ; } }
2016-05-19 18:35:40 +00:00
function _showEditPopup ( link ) { var $popup = editor . popups . get ( 'link.edit' ) ; if ( ! $popup ) $popup = _initEditPopup ( ) ; var $link = $ ( link ) ; if ( ! editor . popups . isVisible ( 'link.edit' ) ) { editor . popups . refresh ( 'link.edit' ) ; }
2017-02-08 08:10:24 +00:00
editor . popups . setContainer ( 'link.edit' , editor . $sc ) ; var left = $link . offset ( ) . left + $ ( link ) . outerWidth ( ) / 2 ; var top = $link . offset ( ) . top + $link . outerHeight ( ) ; editor . popups . show ( 'link.edit' , left , top , $link . outerHeight ( ) ) ; }
2016-05-19 18:35:40 +00:00
function _hideEditPopup ( ) { editor . popups . hide ( 'link.edit' ) ; }
2019-03-28 16:49:22 +00:00
function _initEditPopup ( ) { var link _buttons = '' ; if ( editor . opts . linkEditButtons . length >= 1 ) { if ( editor . el . tagName == 'A' && editor . opts . linkEditButtons . indexOf ( 'linkRemove' ) >= 0 ) { editor . opts . linkEditButtons . splice ( editor . opts . linkEditButtons . indexOf ( 'linkRemove' ) , 1 ) ; }
2016-05-19 18:35:40 +00:00
link _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . linkEditButtons ) + '</div>' ; }
var template = { buttons : link _buttons } ; var $popup = editor . popups . create ( 'link.edit' , template ) ; if ( editor . $wp ) { editor . events . $on ( editor . $wp , 'scroll.link-edit' , function ( ) { if ( get ( ) && editor . popups . isVisible ( 'link.edit' ) ) { _showEditPopup ( get ( ) ) ; } } ) ; }
return $popup ; }
function _hideInsertPopup ( ) { }
function _refreshInsertPopup ( ) { var $popup = editor . popups . get ( 'link.insert' ) ; var link = get ( ) ; if ( link ) { var $link = $ ( link ) ; var text _inputs = $popup . find ( 'input.fr-link-attr[type="text"]' ) ; var check _inputs = $popup . find ( 'input.fr-link-attr[type="checkbox"]' ) ; var i ; var $input ; for ( i = 0 ; i < text _inputs . length ; i ++ ) { $input = $ ( text _inputs [ i ] ) ; $input . val ( $link . attr ( $input . attr ( 'name' ) || '' ) ) ; }
check _inputs . prop ( 'checked' , false ) ; for ( i = 0 ; i < check _inputs . length ; i ++ ) { $input = $ ( check _inputs [ i ] ) ; if ( $link . attr ( $input . attr ( 'name' ) ) == $input . data ( 'checked' ) ) { $input . prop ( 'checked' , true ) ; } }
$popup . find ( 'input.fr-link-attr[type="text"][name="text"]' ) . val ( $link . text ( ) ) ; }
else { $popup . find ( 'input.fr-link-attr[type="text"]' ) . val ( '' ) ; $popup . find ( 'input.fr-link-attr[type="checkbox"]' ) . prop ( 'checked' , false ) ; $popup . find ( 'input.fr-link-attr[type="text"][name="text"]' ) . val ( editor . selection . text ( ) ) ; }
$popup . find ( 'input.fr-link-attr' ) . trigger ( 'change' ) ; var $current _image = editor . image ? editor . image . get ( ) : null ; if ( $current _image ) { $popup . find ( '.fr-link-attr[name="text"]' ) . parent ( ) . hide ( ) ; }
else { $popup . find ( '.fr-link-attr[name="text"]' ) . parent ( ) . show ( ) ; } }
2017-02-08 08:10:24 +00:00
function _showInsertPopup ( ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertLink"]' ) ; var $popup = editor . popups . get ( 'link.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; if ( ! $popup . hasClass ( 'fr-active' ) ) { editor . popups . refresh ( 'link.insert' ) ; editor . popups . setContainer ( 'link.insert' , editor . $tb || editor . $sc ) ; if ( $btn . is ( ':visible' ) ) { var left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; var top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; editor . popups . show ( 'link.insert' , left , top , $btn . outerHeight ( ) ) ; }
2016-05-19 18:35:40 +00:00
else { editor . position . forSelection ( $popup ) ; editor . popups . show ( 'link.insert' ) ; } } }
function _initInsertPopup ( delayed ) { if ( delayed ) { editor . popups . onRefresh ( 'link.insert' , _refreshInsertPopup ) ; editor . popups . onHide ( 'link.insert' , _hideInsertPopup ) ; return true ; }
var link _buttons = '' ; if ( editor . opts . linkInsertButtons . length >= 1 ) { link _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . linkInsertButtons ) + '</div>' ; }
2019-03-28 16:49:22 +00:00
var checkmark = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="10" height="10" viewBox="0 0 32 32"><path d="M27 4l-15 15-7-7-5 5 12 12 20-20z" fill="#FFF"></path></svg>' ; var input _layer = '' ; var tab _idx = 0 ; input _layer = '<div class="fr-link-insert-layer fr-layer fr-active" id="fr-link-insert-layer-' + editor . id + '">' ; input _layer += '<div class="fr-input-line"><input id="fr-link-insert-layer-url-' + editor . id + '" name="href" type="text" class="fr-link-attr" placeholder="' + editor . language . translate ( 'URL' ) + '" tabIndex="' + ( ++ tab _idx ) + '"></div>' ; if ( editor . opts . linkText ) { input _layer += '<div class="fr-input-line"><input id="fr-link-insert-layer-text-' + editor . id + '" name="text" type="text" class="fr-link-attr" placeholder="' + editor . language . translate ( 'Text' ) + '" tabIndex="' + ( ++ tab _idx ) + '"></div>' ; }
2016-05-19 18:35:40 +00:00
for ( var attr in editor . opts . linkAttributes ) { if ( editor . opts . linkAttributes . hasOwnProperty ( attr ) ) { var placeholder = editor . opts . linkAttributes [ attr ] ; input _layer += '<div class="fr-input-line"><input name="' + attr + '" type="text" class="fr-link-attr" placeholder="' + editor . language . translate ( placeholder ) + '" tabIndex="' + ( ++ tab _idx ) + '"></div>' ; } }
if ( ! editor . opts . linkAlwaysBlank ) { input _layer += '<div class="fr-checkbox-line"><span class="fr-checkbox"><input name="target" class="fr-link-attr" data-checked="_blank" type="checkbox" id="fr-link-target-' + editor . id + '" tabIndex="' + ( ++ tab _idx ) + '"><span>' + checkmark + '</span></span><label for="fr-link-target-' + editor . id + '">' + editor . language . translate ( 'Open in new tab' ) + '</label></div>' ; }
2017-02-08 08:10:24 +00:00
input _layer += '<div class="fr-action-buttons"><button class="fr-command fr-submit" role="button" data-cmd="linkInsert" href="#" tabIndex="' + ( ++ tab _idx ) + '" type="button">' + editor . language . translate ( 'Insert' ) + '</button></div></div>'
2016-05-19 18:35:40 +00:00
var template = { buttons : link _buttons , input _layer : input _layer }
var $popup = editor . popups . create ( 'link.insert' , template ) ; if ( editor . $wp ) { editor . events . $on ( editor . $wp , 'scroll.link-insert' , function ( ) { var $current _image = editor . image ? editor . image . get ( ) : null ; if ( $current _image && editor . popups . isVisible ( 'link.insert' ) ) { imageLink ( ) ; }
if ( get && editor . popups . isVisible ( 'link.insert' ) ) { update ( ) ; } } ) ; }
return $popup ; }
function remove ( ) { var link = get ( ) ; var $current _image = editor . image ? editor . image . get ( ) : null ; if ( editor . events . trigger ( 'link.beforeRemove' , [ link ] ) === false ) return false ; if ( $current _image && link ) { $current _image . unwrap ( ) ; editor . image . edit ( $current _image ) ; }
else if ( link ) { editor . selection . save ( ) ; $ ( link ) . replaceWith ( $ ( link ) . html ( ) ) ; editor . selection . restore ( ) ; _hideEditPopup ( ) ; } }
2019-03-28 16:49:22 +00:00
function _init ( ) { editor . events . on ( 'keyup' , function ( e ) { if ( e . which != $ . FE . KEYCODE . ESC ) { _edit ( e ) ; } } ) ; editor . events . on ( 'window.mouseup' , _edit ) ; editor . events . $on ( editor . $el , 'click' , 'a' , function ( e ) { if ( editor . edit . isDisabled ( ) ) { e . preventDefault ( ) ; } } ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $doc , 'selectionchange' , _edit ) ; }
2017-02-08 08:10:24 +00:00
_initInsertPopup ( true ) ; if ( editor . el . tagName == 'A' ) { editor . $el . addClass ( 'fr-view' ) ; }
editor . events . on ( 'toolbar.esc' , function ( ) { if ( editor . popups . isVisible ( 'link.edit' ) ) { editor . events . disableBlur ( ) ; editor . events . focus ( ) ; return false ; } } , true ) ; }
2016-05-19 18:35:40 +00:00
function usePredefined ( val ) { var link = editor . opts . linkList [ val ] ; var $popup = editor . popups . get ( 'link.insert' ) ; var text _inputs = $popup . find ( 'input.fr-link-attr[type="text"]' ) ; var check _inputs = $popup . find ( 'input.fr-link-attr[type="checkbox"]' ) ; var $input ; var i ; for ( i = 0 ; i < text _inputs . length ; i ++ ) { $input = $ ( text _inputs [ i ] ) ; if ( link [ $input . attr ( 'name' ) ] ) { $input . val ( link [ $input . attr ( 'name' ) ] ) ; }
else if ( $input . attr ( 'name' ) != 'text' ) { $input . val ( '' ) ; } }
2017-02-08 08:10:24 +00:00
for ( i = 0 ; i < check _inputs . length ; i ++ ) { $input = $ ( check _inputs [ i ] ) ; $input . prop ( 'checked' , $input . data ( 'checked' ) == link [ $input . attr ( 'name' ) ] ) ; }
editor . accessibility . focusPopup ( $popup ) ; }
2019-03-28 16:49:22 +00:00
function insertCallback ( ) { var $popup = editor . popups . get ( 'link.insert' ) ; var text _inputs = $popup . find ( 'input.fr-link-attr[type="text"]' ) ; var check _inputs = $popup . find ( 'input.fr-link-attr[type="checkbox"]' ) ; var href = ( text _inputs . filter ( '[name="href"]' ) . val ( ) || '' ) . trim ( ) ; var text = text _inputs . filter ( '[name="text"]' ) . val ( ) ; var attrs = { } ; var $input ; var i ; for ( i = 0 ; i < text _inputs . length ; i ++ ) { $input = $ ( text _inputs [ i ] ) ; if ( [ 'href' , 'text' ] . indexOf ( $input . attr ( 'name' ) ) < 0 ) { attrs [ $input . attr ( 'name' ) ] = $input . val ( ) ; } }
2016-05-19 18:35:40 +00:00
for ( i = 0 ; i < check _inputs . length ; i ++ ) { $input = $ ( check _inputs [ i ] ) ; if ( $input . is ( ':checked' ) ) { attrs [ $input . attr ( 'name' ) ] = $input . data ( 'checked' ) ; }
2017-02-08 08:10:24 +00:00
else { attrs [ $input . attr ( 'name' ) ] = $input . data ( 'unchecked' ) || null ; } }
var t = editor . helpers . scrollTop ( ) ; insert ( href , text , attrs ) ; $ ( editor . o _win ) . scrollTop ( t ) ; }
2019-03-28 16:49:22 +00:00
function _split ( ) { if ( ! editor . selection . isCollapsed ( ) ) { editor . selection . save ( ) ; var markers = editor . $el . find ( '.fr-marker' ) . addClass ( 'fr-unprocessed' ) . toArray ( ) ; while ( markers . length ) { var $marker = $ ( markers . pop ( ) ) ; $marker . removeClass ( 'fr-unprocessed' ) ; var deep _parent = editor . node . deepestParent ( $marker . get ( 0 ) ) ; if ( deep _parent ) { var node = $marker . get ( 0 ) ; var close _str = '' ; var open _str = '' ; do { node = node . parentNode ; if ( ! editor . node . isBlock ( node ) ) { close _str = close _str + editor . node . closeTagString ( node ) ; open _str = editor . node . openTagString ( node ) + open _str ; } } while ( node != deep _parent ) ; var marker _str = editor . node . openTagString ( $marker . get ( 0 ) ) + $marker . html ( ) + editor . node . closeTagString ( $marker . get ( 0 ) ) ; $marker . replaceWith ( '<span id="fr-break"></span>' ) ; var h = deep _parent . outerHTML ; h = h . replace ( /<span id="fr-break"><\/span>/g , close _str + marker _str + open _str ) ; h = h . replace ( open _str + close _str , '' ) ; deep _parent . outerHTML = h ; }
2016-05-19 18:35:40 +00:00
markers = editor . $el . find ( '.fr-marker.fr-unprocessed' ) . toArray ( ) ; }
2019-03-28 16:49:22 +00:00
editor . html . cleanEmptyTags ( ) ; editor . selection . restore ( ) ; } }
2017-02-08 08:10:24 +00:00
function insert ( href , text , attrs ) { if ( typeof attrs == 'undefined' ) attrs = { } ; if ( editor . events . trigger ( 'link.beforeInsert' , [ href , text , attrs ] ) === false ) return false ; var $current _image = editor . image ? editor . image . get ( ) : null ; if ( ! $current _image && editor . el . tagName != 'A' ) { editor . selection . restore ( ) ; editor . popups . hide ( 'link.insert' ) ; }
else if ( editor . el . tagName == 'A' ) { editor . $el . focus ( ) ; }
2019-03-28 16:49:22 +00:00
var original _href = href ; if ( editor . opts . linkConvertEmailAddress ) { if ( editor . helpers . isEmail ( href ) && ! /^mailto:.*/i . test ( href ) ) { href = 'mailto:' + href ; } }
var local _path = /^([A-Za-z]:(\\){1,2}|[A-Za-z]:((\\){1,2}[^\\]+)+)(\\)?$/i ; if ( editor . opts . linkAutoPrefix !== '' && ! new RegExp ( '^(' + $ . FE . LinkProtocols . join ( '|' ) + '):.' , 'i' ) . test ( href ) && ! /^data:image.*/i . test ( href ) && ! /^(https?:|ftps?:|file:|)\/\//i . test ( href ) && ! local _path . test ( href ) ) { if ( [ '/' , '{' , '[' , '#' , '(' , '.' ] . indexOf ( ( href || '' ) [ 0 ] ) < 0 ) { href = editor . opts . linkAutoPrefix + editor . helpers . sanitizeURL ( href ) ; } }
href = editor . helpers . sanitizeURL ( href ) ; if ( editor . opts . linkAlwaysBlank ) attrs . target = '_blank' ; if ( editor . opts . linkAlwaysNoFollow ) attrs . rel = 'nofollow' ; if ( editor . helpers . isEmail ( original _href ) ) { attrs . target = null ; attrs . rel = null ; }
if ( attrs . target == '_blank' ) { if ( editor . opts . linkNoOpener ) { if ( ! attrs . rel ) attrs . rel = 'noopener' ; else attrs . rel += ' noopener' ; }
if ( editor . opts . linkNoReferrer ) { if ( ! attrs . rel ) attrs . rel = 'noreferrer' ; else attrs . rel += ' noreferrer' ; } }
else if ( attrs . target == null ) { if ( attrs . rel ) { attrs . rel = attrs . rel . replace ( /noopener/ , '' ) . replace ( /noreferrer/ , '' ) ; }
else { attrs . rel = null ; } }
2017-02-08 08:10:24 +00:00
text = text || '' ; if ( href === editor . opts . linkAutoPrefix ) { var $popup = editor . popups . get ( 'link.insert' ) ; $popup . find ( 'input[name="href"]' ) . addClass ( 'fr-error' ) ; editor . events . trigger ( 'link.bad' , [ original _href ] ) ; return false ; }
2019-03-28 16:49:22 +00:00
var link = get ( ) ; var $link ; if ( link ) { $link = $ ( link ) ; $link . attr ( 'href' , href ) ; if ( text . length > 0 && $link . text ( ) != text && ! $current _image ) { var child = $link . get ( 0 ) ; while ( child . childNodes . length === 1 && child . childNodes [ 0 ] . nodeType == Node . ELEMENT _NODE ) { child = child . childNodes [ 0 ] ; }
$ ( child ) . text ( text ) ; }
2016-05-19 18:35:40 +00:00
if ( ! $current _image ) { $link . prepend ( $ . FE . START _MARKER ) . append ( $ . FE . END _MARKER ) ; }
$link . attr ( attrs ) ; if ( ! $current _image ) { editor . selection . restore ( ) ; } }
2019-03-28 16:49:22 +00:00
else { if ( ! $current _image ) { editor . format . remove ( 'a' ) ; if ( editor . selection . isCollapsed ( ) ) { text = ( text . length === 0 ? original _href : text ) ; editor . html . insert ( '<a href="' + href + '">' + $ . FE . START _MARKER + text . replace ( /&/g , '&' ) . replace ( /</ , '<' , '>' , '>' ) + $ . FE . END _MARKER + '</a>' ) ; editor . selection . restore ( ) ; }
else { if ( text . length > 0 && text != editor . selection . text ( ) . replace ( /\n/g , '' ) ) { editor . selection . remove ( ) ; editor . html . insert ( '<a href="' + href + '">' + $ . FE . START _MARKER + text . replace ( /&/g , '&' ) + $ . FE . END _MARKER + '</a>' ) ; editor . selection . restore ( ) ; }
2016-05-21 19:21:19 +00:00
else { _split ( ) ; editor . format . apply ( 'a' , { href : href } ) ; } } }
2016-05-19 18:35:40 +00:00
else { $current _image . wrap ( '<a href="' + href + '"></a>' ) ; }
var links = allSelected ( ) ; for ( var i = 0 ; i < links . length ; i ++ ) { $link = $ ( links [ i ] ) ; $link . attr ( attrs ) ; $link . removeAttr ( '_moz_dirty' ) ; }
if ( links . length == 1 && editor . $wp && ! $current _image ) { $ ( links [ 0 ] ) . prepend ( $ . FE . START _MARKER ) . append ( $ . FE . END _MARKER ) ; editor . selection . restore ( ) ; } }
if ( ! $current _image ) { _edit ( ) ; }
2019-03-28 16:49:22 +00:00
else { var $pop = editor . popups . get ( 'link.insert' ) ; if ( $pop ) { $pop . find ( 'input:focus' ) . blur ( ) ; }
editor . image . edit ( $current _image ) ; } }
2016-05-19 18:35:40 +00:00
function update ( ) { _hideEditPopup ( ) ; var link = get ( ) ; if ( link ) { var $popup = editor . popups . get ( 'link.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; if ( ! editor . popups . isVisible ( 'link.insert' ) ) { editor . popups . refresh ( 'link.insert' ) ; editor . selection . save ( ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . disableBlur ( ) ; editor . $el . blur ( ) ; editor . events . enableBlur ( ) ; } }
2017-02-08 08:10:24 +00:00
editor . popups . setContainer ( 'link.insert' , editor . $sc ) ; var $ref = ( editor . image ? editor . image . get ( ) : null ) || $ ( link ) ; var left = $ref . offset ( ) . left + $ref . outerWidth ( ) / 2 ; var top = $ref . offset ( ) . top + $ref . outerHeight ( ) ; editor . popups . show ( 'link.insert' , left , top , $ref . outerHeight ( ) ) ; } }
2016-05-19 18:35:40 +00:00
function back ( ) { var $current _image = editor . image ? editor . image . get ( ) : null ; if ( ! $current _image ) { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; var link = get ( ) ; if ( link && editor . $wp ) { editor . selection . restore ( ) ; _hideEditPopup ( ) ; _edit ( ) ; }
2017-02-08 08:10:24 +00:00
else if ( editor . el . tagName == 'A' ) { editor . $el . focus ( ) ; _edit ( ) ; }
2016-05-19 18:35:40 +00:00
else { editor . popups . hide ( 'link.insert' ) ; editor . toolbar . showInline ( ) ; } }
else { editor . image . back ( ) ; } }
2019-03-28 16:49:22 +00:00
function imageLink ( ) { var $el = editor . image ? editor . image . getEl ( ) : null ; if ( $el ) { var $popup = editor . popups . get ( 'link.insert' ) ; if ( editor . image . hasCaption ( ) ) { $el = $el . find ( '.fr-img-wrap' ) ; }
if ( ! $popup ) $popup = _initInsertPopup ( ) ; _refreshInsertPopup ( true ) ; editor . popups . setContainer ( 'link.insert' , editor . $sc ) ; var left = $el . offset ( ) . left + $el . outerWidth ( ) / 2 ; var top = $el . offset ( ) . top + $el . outerHeight ( ) ; editor . popups . show ( 'link.insert' , left , top , $el . outerHeight ( ) ) ; } }
2016-05-19 18:35:40 +00:00
function applyStyle ( val , linkStyles , multipleStyles ) { if ( typeof multipleStyles == 'undefined' ) multipleStyles = editor . opts . linkMultipleStyles ; if ( typeof linkStyles == 'undefined' ) linkStyles = editor . opts . linkStyles ; var link = get ( ) ; if ( ! link ) return false ; if ( ! multipleStyles ) { var styles = Object . keys ( linkStyles ) ; styles . splice ( styles . indexOf ( val ) , 1 ) ; $ ( link ) . removeClass ( styles . join ( ' ' ) ) ; }
$ ( link ) . toggleClass ( val ) ; _edit ( ) ; }
return { _init : _init , remove : remove , showInsertPopup : _showInsertPopup , usePredefined : usePredefined , insertCallback : insertCallback , insert : insert , update : update , get : get , allSelected : allSelected , back : back , imageLink : imageLink , applyStyle : applyStyle } }
2016-05-21 19:21:19 +00:00
$ . FE . DefineIcon ( 'insertLink' , { NAME : 'link' } ) ; $ . FE . RegisterShortcut ( $ . FE . KEYCODE . K , 'insertLink' , null , 'K' ) ; $ . FE . RegisterCommand ( 'insertLink' , { title : 'Insert Link' , undo : false , focus : true , refreshOnCallback : false , popup : true , callback : function ( ) { if ( ! this . popups . isVisible ( 'link.insert' ) ) { this . link . showInsertPopup ( ) ; }
2017-02-08 08:10:24 +00:00
else { if ( this . $el . find ( '.fr-marker' ) . length ) { this . events . disableBlur ( ) ; this . selection . restore ( ) ; }
2016-05-19 18:35:40 +00:00
this . popups . hide ( 'link.insert' ) ; } } , plugin : 'link' } )
2019-03-28 16:49:22 +00:00
$ . FE . DefineIcon ( 'linkOpen' , { NAME : 'external-link' , FA5NAME : 'external-link-alt' } ) ; $ . FE . RegisterCommand ( 'linkOpen' , { title : 'Open Link' , undo : false , refresh : function ( $btn ) { var link = this . link . get ( ) ; if ( link ) { $btn . removeClass ( 'fr-hidden' ) ; }
else { $btn . addClass ( 'fr-hidden' ) ; } } , callback : function ( ) { var link = this . link . get ( ) ; if ( link ) { if ( link . href . indexOf ( 'mailto:' ) !== - 1 ) { this . o _win . open ( link . href ) . close ( ) ; }
else { this . o _win . open ( link . href , '_blank' , 'noopener' ) ; }
this . popups . hide ( 'link.edit' ) ; } } , plugin : 'link' } )
2017-02-08 08:10:24 +00:00
$ . FE . DefineIcon ( 'linkEdit' , { NAME : 'edit' } ) ; $ . FE . RegisterCommand ( 'linkEdit' , { title : 'Edit Link' , undo : false , refreshAfterCallback : false , popup : true , callback : function ( ) { this . link . update ( ) ; } , refresh : function ( $btn ) { var link = this . link . get ( ) ; if ( link ) { $btn . removeClass ( 'fr-hidden' ) ; }
2019-03-28 16:49:22 +00:00
else { $btn . addClass ( 'fr-hidden' ) ; } } , plugin : 'link' } )
2016-05-19 18:35:40 +00:00
$ . FE . DefineIcon ( 'linkRemove' , { NAME : 'unlink' } ) ; $ . FE . RegisterCommand ( 'linkRemove' , { title : 'Unlink' , callback : function ( ) { this . link . remove ( ) ; } , refresh : function ( $btn ) { var link = this . link . get ( ) ; if ( link ) { $btn . removeClass ( 'fr-hidden' ) ; }
2019-03-28 16:49:22 +00:00
else { $btn . addClass ( 'fr-hidden' ) ; } } , plugin : 'link' } )
2017-02-08 08:10:24 +00:00
$ . FE . DefineIcon ( 'linkBack' , { NAME : 'arrow-left' } ) ; $ . FE . RegisterCommand ( 'linkBack' , { title : 'Back' , undo : false , focus : false , back : true , refreshAfterCallback : false , callback : function ( ) { this . link . back ( ) ; } , refresh : function ( $btn ) { var link = this . link . get ( ) && this . doc . hasFocus ( ) ; var $current _image = this . image ? this . image . get ( ) : null ; if ( ! $current _image && ! link && ! this . opts . toolbarInline ) { $btn . addClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . addClass ( 'fr-hidden' ) ; }
2019-03-28 16:49:22 +00:00
else { $btn . removeClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . removeClass ( 'fr-hidden' ) ; } } , plugin : 'link' } ) ; $ . FE . DefineIcon ( 'linkList' , { NAME : 'search' } ) ; $ . FE . RegisterCommand ( 'linkList' , { title : 'Choose Link' , type : 'dropdown' , focus : false , undo : false , refreshAfterCallback : false , html : function ( ) { var c = '<ul class="fr-dropdown-list" role="presentation">' ; var options = this . opts . linkList ; for ( var i = 0 ; i < options . length ; i ++ ) { c += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="linkList" data-param1="' + i + '">' + ( options [ i ] . displayText || options [ i ] . text ) + '</a></li>' ; }
c += '</ul>' ; return c ; } , callback : function ( cmd , val ) { this . link . usePredefined ( val ) ; } , plugin : 'link' } )
2016-05-19 18:35:40 +00:00
$ . FE . RegisterCommand ( 'linkInsert' , { focus : false , refreshAfterCallback : false , callback : function ( ) { this . link . insertCallback ( ) ; } , refresh : function ( $btn ) { var link = this . link . get ( ) ; if ( link ) { $btn . text ( this . language . translate ( 'Update' ) ) ; }
2019-03-28 16:49:22 +00:00
else { $btn . text ( this . language . translate ( 'Insert' ) ) ; } } , plugin : 'link' } )
2016-05-19 18:35:40 +00:00
$ . FE . DefineIcon ( 'imageLink' , { NAME : 'link' } )
2017-02-08 08:10:24 +00:00
$ . FE . RegisterCommand ( 'imageLink' , { title : 'Insert Link' , undo : false , focus : false , popup : true , callback : function ( ) { this . link . imageLink ( ) ; } , refresh : function ( $btn ) { var link = this . link . get ( ) ; var $prev ; if ( link ) { $prev = $btn . prev ( ) ; if ( $prev . hasClass ( 'fr-separator' ) ) { $prev . removeClass ( 'fr-hidden' ) ; }
2016-05-19 18:35:40 +00:00
$btn . addClass ( 'fr-hidden' ) ; }
else { $prev = $btn . prev ( ) ; if ( $prev . hasClass ( 'fr-separator' ) ) { $prev . addClass ( 'fr-hidden' ) ; }
2019-03-28 16:49:22 +00:00
$btn . removeClass ( 'fr-hidden' ) ; } } , plugin : 'link' } )
2016-05-19 18:35:40 +00:00
$ . FE . DefineIcon ( 'linkStyle' , { NAME : 'magic' } )
2017-02-08 08:10:24 +00:00
$ . FE . RegisterCommand ( 'linkStyle' , { title : 'Style' , type : 'dropdown' , html : function ( ) { var c = '<ul class="fr-dropdown-list" role="presentation">' ; var options = this . opts . linkStyles ; for ( var cls in options ) { if ( options . hasOwnProperty ( cls ) ) { c += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="linkStyle" data-param1="' + cls + '">' + this . language . translate ( options [ cls ] ) + '</a></li>' ; } }
2019-03-28 16:49:22 +00:00
c += '</ul>' ; return c ; } , callback : function ( cmd , val ) { this . link . applyStyle ( val ) ; } , refreshOnShow : function ( $btn , $dropdown ) { var link = this . link . get ( ) ; if ( link ) { var $link = $ ( link ) ; $dropdown . find ( '.fr-command' ) . each ( function ( ) { var cls = $ ( this ) . data ( 'param1' ) ; var active = $link . hasClass ( cls ) ; $ ( this ) . toggleClass ( 'fr-active' , active ) . attr ( 'aria-selected' , active ) ; } ) } } , refresh : function ( $btn ) { var link = this . link . get ( ) ; if ( link ) { $btn . removeClass ( 'fr-hidden' ) ; }
else { $btn . addClass ( 'fr-hidden' ) ; } } , plugin : 'link' } ) } ) ) ; ! function ( l ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , l ) : "object" == typeof module && module . exports ? module . exports = function ( e , t ) { return t === undefined && ( t = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( e ) ) , l ( t ) } : l ( window . jQuery ) } ( function ( Z ) { Z . extend ( Z . FE . POPUP _TEMPLATES , { "table.insert" : "[_BUTTONS_][_ROWS_COLUMNS_]" , "table.edit" : "[_BUTTONS_]" , "table.colors" : "[_BUTTONS_][_COLORS_][_CUSTOM_COLOR_]" } ) , Z . extend ( Z . FE . DEFAULTS , { tableInsertMaxSize : 10 , tableEditButtons : [ "tableHeader" , "tableRemove" , "|" , "tableRows" , "tableColumns" , "tableStyle" , "-" , "tableCells" , "tableCellBackground" , "tableCellVerticalAlign" , "tableCellHorizontalAlign" , "tableCellStyle" ] , tableInsertButtons : [ "tableBack" , "|" ] , tableResizer : ! 0 , tableDefaultWidth : "100%" , tableResizerOffset : 5 , tableResizingLimit : 30 , tableColorsButtons : [ "tableBack" , "|" ] , tableColors : [ "#61BD6D" , "#1ABC9C" , "#54ACD2" , "#2C82C9" , "#9365B8" , "#475577" , "#CCCCCC" , "#41A85F" , "#00A885" , "#3D8EB9" , "#2969B0" , "#553982" , "#28324E" , "#000000" , "#F7DA64" , "#FBA026" , "#EB6B56" , "#E25041" , "#A38F84" , "#EFEFEF" , "#FFFFFF" , "#FAC51C" , "#F37934" , "#D14841" , "#B8312F" , "#7C706B" , "#D1D5D8" , "REMOVE" ] , tableColorsStep : 7 , tableCellStyles : { "fr-highlighted" : "Highlighted" , "fr-thick" : "Thick" } , tableStyles : { "fr-dashed-borders" : "Dashed Borders" , "fr-alternate-rows" : "Alternate Rows" } , tableCellMultipleStyles : ! 0 , tableMultipleStyles : ! 0 , tableInsertHelper : ! 0 , tableInsertHelperOffset : 15 } ) , Z . FE . PLUGINS . table = function ( w ) { var C , o , r , s , a , n , E ; function h ( ) { var e = O ( ) ; if ( e ) { var t = w . popups . get ( "table.edit" ) ; if ( t || ( t = p ( ) ) , t ) { w . popups . setContainer ( "table.edit" , w . $sc ) ; var l = M ( e ) , a = ( l . left + l . right ) / 2 , r = l . bottom ; w . popups . show ( "table.edit" , a , r , l . bottom - l . top ) , w . edit . isDisabled ( ) && ( 1 < J ( ) . length && w . toolbar . disable ( ) , w . $el . removeClass ( "fr-no-selection" ) , w . edit . on ( ) , w . button . bulkRefresh ( ) , w . selection . setAtEnd ( w . $el . find ( ".fr-selected-cell:last" ) . get ( 0 ) ) , w . selection . restore ( ) ) } } } function f ( ) { var e , t , l , a , r = O ( ) ; if ( r ) { var s = w . popups . get ( "table.colors" ) ; s || ( s = function ( ) { var e = "" ; 0 < w . opts . tableColorsButtons . length && ( e = '<div class="fr-buttons fr-table-colors-buttons">' + w . button . buildList ( w . opts . tableColorsButtons ) + "</div>" ) ; var t = "" ; w . opts . colorsHEXInput && ( t = '<div class="fr-table-colors-hex-layer fr-active fr-layer" id="fr-table-colors-hex-layer-' + w . id + '"><div class="fr-input-line"><input maxlength="7" id="fr-table-colors-hex-layer-text-' + w . id + '" type="text" placeholder="' + w . language . translate ( "HEX Color" ) + '" tabIndex="1" aria-required="true"></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="tableCellBackgroundCustomColor" tabIndex="2" role="button">' + w . language . translate ( "OK" ) + "</button></div></div>" ) ; var l = { buttons : e , colors : function ( ) { for ( var e = '<div class="fr-table-colors">' , t = 0 ; t < w . opts . tableColors . length ; t ++ ) 0 !== t && t % w . opts . tableColorsStep == 0 && ( e += "<br>" ) , "REMOVE" != w . opts . tableColors [ t ] ? e += '<span class="fr-command" style="background: ' + w . opts . tableColors [ t ] + ';" tabIndex="-1" role="button" data-cmd="tableCellBackgroundColor" data-param1="' + w . opts . tableColors [ t ] + '"><span class="fr-sr-only">' + w . language . translate ( "Color" ) + " " + w . opts . tableColors [ t ] + " </span></span>" : e += '<span class="fr-command" data-cmd="tableCellBackgroundColor" tabIndex="-1" role="button" data-param1="REMOVE" title="' + w . language . translate ( "Clear Formatting" ) + '">' + w . icon . create ( "tableColorRemove" ) + '<span class="fr-sr-only">' + w . language . translate ( "Clear Formatting" ) + "</span></span>" ; return e += "</div>" } ( ) , custom _color : t } , a = w . popups . create ( "table.colors" , l ) ; return w . events . $on ( w . $wp , "scroll.table-colors" , function ( ) { w . popups . isVisible ( "table.colors" ) && f ( ) } ) , u = a , w . events . on ( "popup.tab" , function ( e ) { var t = Z ( e . currentTarget ) ; if ( ! w . popups . isVisible ( "table.colors" ) || ! t . is ( "span" ) ) return ! 0 ; var l = e . which , a = ! 0 ; if ( Z . FE . KEYCODE . TAB == l ) { var r = u . find ( ".fr-buttons" ) ; a = ! w . accessibility . focusToolbar ( r , ! ! e . shiftKey ) } else if ( Z . FE . KEYCODE . ARROW _UP == l || Z . FE . KEYCODE . ARROW _DOWN == l || Z . FE . KEYCODE . ARROW _LEFT == l || Z . FE . KEYCODE . ARROW _RIGHT == l ) { var s = t . parent ( ) . find ( "span.fr-command" ) , n = s . index ( t ) , o = w . opts
2017-02-08 08:10:24 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
factory ( jQuery ) ; return jQuery ; } ; } else { factory ( jQuery ) ; } } ( function ( $ ) { 'use strict' ; $ . extend ( $ . FE . POPUP _TEMPLATES , { 'video.insert' : '[_BUTTONS_][_BY_URL_LAYER_][_EMBED_LAYER_]' , 'video.edit' : '[_BUTTONS_]' , 'video.size' : '[_BUTTONS_][_SIZE_LAYER_]' } )
$ . extend ( $ . FE . DEFAULTS , { videoInsertButtons : [ 'videoBack' , '|' , 'videoByURL' , 'videoEmbed' ] , videoEditButtons : [ 'videoDisplay' , 'videoAlign' , 'videoSize' , 'videoRemove' ] , videoResize : true , videoSizeButtons : [ 'videoBack' , '|' ] , videoSplitHTML : false , videoTextNear : true , videoDefaultAlign : 'center' , videoDefaultDisplay : 'block' , videoMove : true } ) ; $ . FE . VIDEO _PROVIDERS = [ { test _regex : /^.*((youtu.be)|(youtube.com))\/((v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))?\??v?=?([^#\&\?]*).*/ , url _regex : /(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/)?([0-9a-zA-Z_\-]+)(.+)?/g , url _text : '//www.youtube.com/embed/$1' , html : '<iframe width="640" height="360" src="{url}?wmode=opaque" frameborder="0" allowfullscreen></iframe>' } , { test _regex : /^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/))?([0-9]+)/ , url _regex : /(?:https?:\/\/)?(?:www\.)?(?:vimeo\.com)\/(?:channels\/[A-z]+\/|groups\/[A-z]+\/videos\/)?(.+)/g , url _text : '//player.vimeo.com/video/$1' , html : '<iframe width="640" height="360" src="{url}" frameborder="0" allowfullscreen></iframe>' } , { test _regex : /^.+(dailymotion.com|dai.ly)\/(video|hub)?\/?([^_]+)[^#]*(#video=([^_&]+))?/ , url _regex : /(?:https?:\/\/)?(?:www\.)?(?:dailymotion\.com|dai\.ly)\/(?:video|hub)?\/?(.+)/g , url _text : '//www.dailymotion.com/embed/video/$1' , html : '<iframe width="640" height="360" src="{url}" frameborder="0" allowfullscreen></iframe>' } , { test _regex : /^.+(screen.yahoo.com)\/[^_&]+/ , url _regex : '' , url _text : '' , html : '<iframe width="640" height="360" src="{url}?format=embed" frameborder="0" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" allowtransparency="true"></iframe>' } , { test _regex : /^.+(rutube.ru)\/[^_&]+/ , url _regex : /(?:https?:\/\/)?(?:www\.)?(?:rutube\.ru)\/(?:video)?\/?(.+)/g , url _text : '//rutube.ru/play/embed/$1' , html : '<iframe width="640" height="360" src="{url}" frameborder="0" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" allowtransparency="true"></iframe>' } ] ; $ . FE . VIDEO _EMBED _REGEX = /^\W*((<iframe.*><\/iframe>)|(<embed.*>))\W*$/i ; $ . FE . PLUGINS . video = function ( editor ) { var $overlay ; var $handler ; var $video _resizer ; var $current _video ; function _refreshInsertPopup ( ) { var $popup = editor . popups . get ( 'video.insert' ) ; var $url _input = $popup . find ( '.fr-video-by-url-layer input' ) ; $url _input . val ( '' ) . trigger ( 'change' ) ; var $embed _area = $popup . find ( '.fr-video-embed-layer textarea' ) ; $embed _area . val ( '' ) . trigger ( 'change' ) ; }
function showInsertPopup ( ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertVideo"]' ) ; var $popup = editor . popups . get ( 'video.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; if ( ! $popup . hasClass ( 'fr-active' ) ) { editor . popups . refresh ( 'video.insert' ) ; editor . popups . setContainer ( 'video.insert' , editor . $tb ) ; var left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; var top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; editor . popups . show ( 'video.insert' , left , top , $btn . outerHeight ( ) ) ; } }
function _showEditPopup ( ) { var $popup = editor . popups . get ( 'video.edit' ) ; if ( ! $popup ) $popup = _initEditPopup ( ) ; editor . popups . setContainer ( 'video.edit' , $ ( editor . opts . scrollableContainer ) ) ; editor . popups . refresh ( 'video.edit' ) ; var $video _obj = $current _video . find ( 'iframe, embed, video' ) ; var left = $video _obj . offset ( ) . left + $video _obj . outerWidth ( ) / 2 ; var top = $video _obj . offset ( ) . top + $video _obj . outerHeight ( ) ; editor . popups . show ( 'video.edit' , left , top , $video _obj . outerHeight ( ) ) ; }
function _initInsertPopup ( delayed ) { if ( delayed ) { editor . popups . onRefresh ( 'video.insert' , _refreshInsertPopup ) ; return true ; }
var video _buttons = '' ; if ( editor . opts . videoInsertButtons . length > 1 ) { video _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . videoInsertButtons ) + '</div>' ; }
var by _url _layer = '' ; if ( editor . opts . videoInsertButtons . indexOf ( 'videoByURL' ) >= 0 ) { by _url _layer = '<div class="fr-video-by-url-layer fr-layer fr-active" id="fr-video-by-url-layer-' + editor . id + '"><div class="fr-input-line"><input type="text" placeholder="http://" tabIndex="1"></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="videoInsertByURL" tabIndex="2">' + editor . language . translate ( 'Insert' ) + '</button></div></div>' }
var embed _layer = '' ; if ( editor . opts . videoInsertButtons . indexOf ( 'videoEmbed' ) >= 0 ) { embed _layer = '<div class="fr-video-embed-layer fr-layer" id="fr-video-embed-layer-' + editor . id + '"><div class="fr-input-line"><textarea type="text" placeholder="' + editor . language . translate ( 'Embedded Code' ) + '" tabIndex="1" rows="5"></textarea></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="videoInsertEmbed" tabIndex="2">' + editor . language . translate ( 'Insert' ) + '</button></div></div>' }
var template = { buttons : video _buttons , by _url _layer : by _url _layer , embed _layer : embed _layer }
var $popup = editor . popups . create ( 'video.insert' , template ) ; return $popup ; }
function showLayer ( name ) { var $popup = editor . popups . get ( 'video.insert' ) ; var left ; var top ; if ( ! $current _video && ! editor . opts . toolbarInline ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertVideo"]' ) ; left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; }
if ( editor . opts . toolbarInline ) { top = $popup . offset ( ) . top - editor . helpers . getPX ( $popup . css ( 'margin-top' ) ) ; if ( $popup . hasClass ( 'fr-above' ) ) { top += $popup . outerHeight ( ) ; } }
$popup . find ( '.fr-layer' ) . removeClass ( 'fr-active' ) ; $popup . find ( '.fr-' + name + '-layer' ) . addClass ( 'fr-active' ) ; editor . popups . show ( 'video.insert' , left , top , 0 ) ; }
function refreshByURLButton ( $btn ) { var $popup = editor . popups . get ( 'video.insert' ) ; if ( $popup . find ( '.fr-video-by-url-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
function refreshEmbedButton ( $btn ) { var $popup = editor . popups . get ( 'video.insert' ) ; if ( $popup . find ( '.fr-video-embed-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
function insert ( embedded _code ) { editor . events . focus ( true ) ; editor . selection . restore ( ) ; editor . html . insert ( '<span contenteditable="false" draggable="true" class="fr-jiv fr-video fr-dv' + ( editor . opts . videoDefaultDisplay [ 0 ] ) + ( editor . opts . videoDefaultAlign != 'center' ? ' fr-fv' + editor . opts . videoDefaultAlign [ 0 ] : '' ) + '">' + embedded _code + '</span>' , false , editor . opts . videoSplitHTML ) ; editor . popups . hide ( 'video.insert' ) ; var $video = editor . $el . find ( '.fr-jiv' ) ; $video . removeClass ( 'fr-jiv' ) ; $video . toggleClass ( 'fr-draggable' , editor . opts . videoMove ) ; editor . events . trigger ( 'video.inserted' , [ $video ] ) ; }
function insertByURL ( link ) { if ( typeof link == 'undefined' ) { var $popup = editor . popups . get ( 'video.insert' ) ; link = $popup . find ( '.fr-video-by-url-layer input[type="text"]' ) . val ( ) || '' ; }
var video = null ; if ( editor . helpers . isURL ( link ) ) { for ( var i = 0 ; i < $ . FE . VIDEO _PROVIDERS . length ; i ++ ) { var vp = $ . FE . VIDEO _PROVIDERS [ i ] ; if ( vp . test _regex . test ( link ) ) { video = link . replace ( vp . url _regex , vp . url _text ) ; video = vp . html . replace ( /\{url\}/ , video ) ; break ; } } }
if ( video ) { insert ( video ) ; }
else { editor . events . trigger ( 'video.linkError' , [ link ] ) ; } }
function insertEmbed ( code ) { if ( typeof code == 'undefined' ) { var $popup = editor . popups . get ( 'video.insert' ) ; code = $popup . find ( '.fr-video-embed-layer textarea' ) . val ( ) || '' ; }
if ( code . length === 0 || ! $ . FE . VIDEO _EMBED _REGEX . test ( code ) ) { editor . events . trigger ( 'video.codeError' , [ code ] ) ; }
else { insert ( code ) ; } }
function _handlerMousedown ( e ) { if ( ! editor . core . sameInstance ( $video _resizer ) ) return true ; e . preventDefault ( ) ; e . stopPropagation ( ) ; var c _x = e . pageX || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageX : null ) ; var c _y = e . pageY || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageY : null ) ; if ( ! c _x || ! c _y ) { return false ; }
if ( ! editor . undo . canDo ( ) ) editor . undo . saveStep ( ) ; $handler = $ ( this ) ; $handler . data ( 'start-x' , c _x ) ; $handler . data ( 'start-y' , c _y ) ; $overlay . show ( ) ; editor . popups . hideAll ( ) ; _unmarkExit ( ) ; }
function _handlerMousemove ( e ) { if ( ! editor . core . sameInstance ( $video _resizer ) ) return true ; if ( $handler ) { e . preventDefault ( )
var c _x = e . pageX || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageX : null ) ; var c _y = e . pageY || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageY : null ) ; if ( ! c _x || ! c _y ) { return false ; }
var s _x = $handler . data ( 'start-x' ) ; var s _y = $handler . data ( 'start-y' ) ; $handler . data ( 'start-x' , c _x ) ; $handler . data ( 'start-y' , c _y ) ; var diff _x = c _x - s _x ; var diff _y = c _y - s _y ; var $video _obj = $current _video . find ( 'iframe, embed, video' ) ; var width = $video _obj . width ( ) ; var height = $video _obj . height ( ) ; if ( $handler . hasClass ( 'fr-hnw' ) || $handler . hasClass ( 'fr-hsw' ) ) { diff _x = 0 - diff _x ; }
if ( $handler . hasClass ( 'fr-hnw' ) || $handler . hasClass ( 'fr-hne' ) ) { diff _y = 0 - diff _y ; }
$video _obj . css ( 'width' , width + diff _x ) ; $video _obj . css ( 'height' , height + diff _y ) ; $video _obj . removeAttr ( 'width' ) ; $video _obj . removeAttr ( 'height' ) ; _repositionResizer ( ) ; } }
function _handlerMouseup ( e ) { if ( ! editor . core . sameInstance ( $video _resizer ) ) return true ; if ( $handler && $current _video ) { if ( e ) e . stopPropagation ( ) ; $handler = null ; $overlay . hide ( ) ; _repositionResizer ( ) ; _showEditPopup ( ) ; editor . undo . saveStep ( ) ; } }
function _getHandler ( pos ) { return '<div class="fr-handler fr-h' + pos + '"></div>' ; }
function _initResizer ( ) { var doc ; if ( ! editor . shared . $video _resizer ) { editor . shared . $video _resizer = $ ( '<div class="fr-video-resizer"></div>' ) ; $video _resizer = editor . shared . $video _resizer ; editor . events . $on ( $video _resizer , 'mousedown' , function ( e ) { e . stopPropagation ( ) ; } , true ) ; if ( editor . opts . videoResize ) { $video _resizer . append ( _getHandler ( 'nw' ) + _getHandler ( 'ne' ) + _getHandler ( 'sw' ) + _getHandler ( 'se' ) ) ; editor . shared . $vid _overlay = $ ( '<div class="fr-video-overlay"></div>' ) ; $overlay = editor . shared . $vid _overlay ; doc = $video _resizer . get ( 0 ) . ownerDocument ; $ ( doc ) . find ( 'body' ) . append ( $overlay ) ; } } else { $video _resizer = editor . shared . $video _resizer ; $overlay = editor . shared . $vid _overlay ; editor . events . on ( 'destroy' , function ( ) { $video _resizer . removeClass ( 'fr-active' ) . appendTo ( $ ( 'body' ) ) ; } , true ) ; }
editor . events . on ( 'shared.destroy' , function ( ) { $video _resizer . html ( '' ) . removeData ( ) . remove ( ) ; $video _resizer = null ; if ( editor . opts . videoResize ) { $overlay . remove ( ) ; $overlay = null ; } } , true ) ; if ( ! editor . helpers . isMobile ( ) ) { editor . events . $on ( $ ( editor . o _win ) , 'resize.video' , function ( ) { _exitEdit ( true ) ; } ) ; }
if ( editor . opts . videoResize ) { doc = $video _resizer . get ( 0 ) . ownerDocument ; editor . events . $on ( $video _resizer , editor . _mousedown , '.fr-handler' , _handlerMousedown ) ; editor . events . $on ( $ ( doc ) , editor . _mousemove , _handlerMousemove ) ; editor . events . $on ( $ ( doc . defaultView || doc . parentWindow ) , editor . _mouseup , _handlerMouseup ) ; editor . events . $on ( $overlay , 'mouseleave' , _handlerMouseup ) ; } }
function _repositionResizer ( ) { if ( ! $video _resizer ) _initResizer ( ) ; ( editor . $wp || $ ( editor . opts . scrollableContainer ) ) . append ( $video _resizer ) ; $video _resizer . data ( 'instance' , editor ) ; var $video _obj = $current _video . find ( 'iframe, embed, video' ) ; $video _resizer . css ( 'top' , ( editor . opts . iframe ? $video _obj . offset ( ) . top - 1 : $video _obj . offset ( ) . top - editor . $wp . offset ( ) . top - 1 ) + editor . $wp . scrollTop ( ) ) . css ( 'left' , ( editor . opts . iframe ? $video _obj . offset ( ) . left - 1 : $video _obj . offset ( ) . left - editor . $wp . offset ( ) . left - 1 ) + editor . $wp . scrollLeft ( ) ) . css ( 'width' , $video _obj . outerWidth ( ) ) . css ( 'height' , $video _obj . height ( ) ) . addClass ( 'fr-active' ) }
var touchScroll ; function _edit ( e ) { if ( e && e . type == 'touchend' && touchScroll ) { return true ; }
e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( editor . edit . isDisabled ( ) ) { return false ; }
for ( var i = 0 ; i < $ . FE . INSTANCES . length ; i ++ ) { if ( $ . FE . INSTANCES [ i ] != editor ) { $ . FE . INSTANCES [ i ] . events . trigger ( 'video.hideResizer' ) ; } }
editor . toolbar . disable ( ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . disableBlur ( ) ; editor . $el . blur ( ) ; editor . events . enableBlur ( ) ; }
$current _video = $ ( this ) ; $ ( this ) . addClass ( 'fr-active' ) ; if ( editor . opts . iframe ) { editor . size . syncIframe ( ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; editor . selection . clear ( ) ; editor . button . bulkRefresh ( ) ; editor . events . trigger ( 'image.hideResizer' ) ; }
function _exitEdit ( force _exit ) { if ( $current _video && ( _canExit ( ) || force _exit === true ) ) { $video _resizer . removeClass ( 'fr-active' ) ; editor . toolbar . enable ( ) ; $current _video . removeClass ( 'fr-active' ) ; $current _video = null ; _unmarkExit ( ) ; } }
editor . shared . vid _exit _flag = false ; function _markExit ( ) { editor . shared . vid _exit _flag = true ; }
function _unmarkExit ( ) { editor . shared . vid _exit _flag = false ; }
function _canExit ( ) { return editor . shared . vid _exit _flag ; }
function _initEvents ( ) { editor . events . on ( 'mousedown window.mousedown' , _markExit ) ; editor . events . on ( 'window.touchmove' , _unmarkExit ) ; editor . events . on ( 'mouseup window.mouseup' , _exitEdit ) ; editor . events . on ( 'commands.mousedown' , function ( $btn ) { if ( $btn . parents ( '.fr-toolbar' ) . length > 0 ) { _exitEdit ( ) ; } } ) ; editor . events . on ( 'blur video.hideResizer commands.undo commands.redo element.dropped' , function ( ) { _exitEdit ( true ) ; } ) ; }
function _initEditPopup ( ) { var video _buttons = '' ; if ( editor . opts . videoEditButtons . length >= 1 ) { video _buttons += '<div class="fr-buttons">' ; video _buttons += editor . button . buildList ( editor . opts . videoEditButtons ) ; video _buttons += '</div>' ; }
var template = { buttons : video _buttons }
var $popup = editor . popups . create ( 'video.edit' , template ) ; editor . events . $on ( editor . $wp , 'scroll.video-edit' , function ( ) { if ( $current _video && editor . popups . isVisible ( 'video.edit' ) ) { _showEditPopup ( ) ; } } ) ; return $popup ; }
function _refreshSizePopup ( ) { if ( $current _video ) { var $popup = editor . popups . get ( 'video.size' ) ; var $video _obj = $current _video . find ( 'iframe, embed, video' )
$popup . find ( 'input[name="width"]' ) . val ( $video _obj . get ( 0 ) . style . width || $video _obj . attr ( 'width' ) ) . trigger ( 'change' ) ; $popup . find ( 'input[name="height"]' ) . val ( $video _obj . get ( 0 ) . style . height || $video _obj . attr ( 'height' ) ) . trigger ( 'change' ) ; } }
function showSizePopup ( ) { var $popup = editor . popups . get ( 'video.size' ) ; if ( ! $popup ) $popup = _initSizePopup ( ) ; editor . popups . refresh ( 'video.size' ) ; editor . popups . setContainer ( 'video.size' , $ ( editor . opts . scrollableContainer ) ) ; var $video _obj = $current _video . find ( 'iframe, embed, video' )
var left = $video _obj . offset ( ) . left + $video _obj . width ( ) / 2 ; var top = $video _obj . offset ( ) . top + $video _obj . height ( ) ; editor . popups . show ( 'video.size' , left , top , $video _obj . height ( ) ) ; }
function _initSizePopup ( delayed ) { if ( delayed ) { editor . popups . onRefresh ( 'video.size' , _refreshSizePopup ) ; return true ; }
var video _buttons = '' ; video _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . videoSizeButtons ) + '</div>' ; var size _layer = '' ; size _layer = '<div class="fr-video-size-layer fr-layer fr-active" id="fr-video-size-layer-' + editor . id + '"><div class="fr-video-group"><div class="fr-input-line"><input type="text" name="width" placeholder="' + editor . language . translate ( 'Width' ) + '" tabIndex="1"></div><div class="fr-input-line"><input type="text" name="height" placeholder="' + editor . language . translate ( 'Height' ) + '" tabIndex="1"></div></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="videoSetSize" tabIndex="2">' + editor . language . translate ( 'Update' ) + '</button></div></div>' ; var template = { buttons : video _buttons , size _layer : size _layer }
var $popup = editor . popups . create ( 'video.size' , template ) ; editor . events . $on ( editor . $wp , 'scroll' , function ( ) { if ( $current _video && editor . popups . isVisible ( 'video.size' ) ) { showSizePopup ( ) ; } } ) ; return $popup ; }
function align ( val ) { $current _video . removeClass ( 'fr-fvr fr-fvl' ) ; if ( val == 'left' ) { $current _video . addClass ( 'fr-fvl' ) ; }
else if ( val == 'right' ) { $current _video . addClass ( 'fr-fvr' ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; }
function refreshAlign ( $btn ) { if ( ! $current _video ) return false ; if ( $current _video . hasClass ( 'fr-fvl' ) ) { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-left' ) ) ; }
else if ( $current _video . hasClass ( 'fr-fvr' ) ) { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-right' ) ) ; }
else { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-justify' ) ) ; } }
function refreshAlignOnShow ( $btn , $dropdown ) { var alignment = 'justify' ; if ( $current _video . hasClass ( 'fr-fvl' ) ) { alignment = 'left' ; }
else if ( $current _video . hasClass ( 'fr-fvr' ) ) { alignment = 'right' ; }
$dropdown . find ( '.fr-command[data-param1="' + alignment + '"]' ) . addClass ( 'fr-active' ) ; }
function display ( val ) { $current _video . removeClass ( 'fr-dvi fr-dvb' ) ; if ( val == 'inline' ) { $current _video . addClass ( 'fr-dvi' ) ; }
else if ( val == 'block' ) { $current _video . addClass ( 'fr-dvb' ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; }
function refreshDisplayOnShow ( $btn , $dropdown ) { var d = 'block' ; if ( $current _video . hasClass ( 'fr-dvi' ) ) { d = 'inline' ; }
$dropdown . find ( '.fr-command[data-param1="' + d + '"]' ) . addClass ( 'fr-active' ) ; }
function remove ( ) { if ( $current _video ) { if ( editor . events . trigger ( 'video.beforeRemove' , [ $current _video ] ) !== false ) { var $video = $current _video ; editor . popups . hideAll ( ) ; _exitEdit ( true ) ; editor . selection . setBefore ( $video . get ( 0 ) ) || editor . selection . setAfter ( $video . get ( 0 ) ) ; $video . remove ( ) ; editor . selection . restore ( ) ; editor . html . fillEmptyBlocks ( ) ; editor . events . trigger ( 'video.removed' , [ $video ] ) ; } } }
function _convertStyleToClasses ( $video ) { if ( ! $video . hasClass ( 'fr-dvi' ) && ! $video . hasClass ( 'fr-dvb' ) ) { var flt = $video . css ( 'float' ) ; $video . css ( 'float' , 'none' ) ; if ( $video . css ( 'display' ) == 'block' ) { $video . css ( 'float' , flt ) ; if ( parseInt ( $video . css ( 'margin-left' ) , 10 ) === 0 && ( $video . attr ( 'style' ) || '' ) . indexOf ( 'margin-right: auto' ) >= 0 ) { $video . addClass ( 'fr-fvl' ) ; }
else if ( parseInt ( $video . css ( 'margin-right' ) , 10 ) === 0 && ( $video . attr ( 'style' ) || '' ) . indexOf ( 'margin-left: auto' ) >= 0 ) { $video . addClass ( 'fr-fvr' ) ; }
$video . addClass ( 'fr-dvb' ) ; }
else { $video . css ( 'float' , flt ) ; if ( $video . css ( 'float' ) == 'left' ) { $video . addClass ( 'fr-fvl' ) ; }
else if ( $video . css ( 'float' ) == 'right' ) { $video . addClass ( 'fr-fvr' ) ; }
$video . addClass ( 'fr-dvi' ) ; }
$video . css ( 'margin' , '' ) ; $video . css ( 'float' , '' ) ; $video . css ( 'display' , '' ) ; $video . css ( 'z-index' , '' ) ; $video . css ( 'position' , '' ) ; $video . css ( 'overflow' , '' ) ; $video . css ( 'vertical-align' , '' ) ; }
if ( ! editor . opts . videoTextNear ) { $video . removeClass ( 'fr-dvi' ) . addClass ( 'fr-dvb' ) ; } }
function _refreshVideoList ( ) { editor . $el . find ( 'video' ) . filter ( function ( ) { return $ ( this ) . parents ( 'span.fr-video' ) . length === 0 ; } ) . wrap ( '<span class="fr-video" contenteditable="false"></span>' ) ; editor . $el . find ( 'embed, iframe' ) . filter ( function ( ) { if ( editor . browser . safari && this . getAttribute ( 'src' ) ) { this . setAttribute ( 'src' , this . src ) ; }
if ( $ ( this ) . parents ( 'span.fr-video' ) . length > 0 ) return false ; var link = $ ( this ) . attr ( 'src' ) ; for ( var i = 0 ; i < $ . FE . VIDEO _PROVIDERS . length ; i ++ ) { var vp = $ . FE . VIDEO _PROVIDERS [ i ] ; if ( vp . test _regex . test ( link ) ) { return true ; } }
return false ; } ) . map ( function ( ) { return $ ( this ) . parents ( 'object' ) . length === 0 ? this : $ ( this ) . parents ( 'object' ) . get ( 0 ) ; } ) . wrap ( '<span class="fr-video" contenteditable="false"></span>' ) ; var videos = editor . $el . find ( 'span.fr-video' ) ; for ( var i = 0 ; i < videos . length ; i ++ ) { _convertStyleToClasses ( $ ( videos [ i ] ) ) ; }
videos . toggleClass ( 'fr-draggable' , editor . opts . videoMove ) ; }
function _init ( ) { _initEvents ( ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $el , 'touchstart' , 'span.fr-video' , function ( ) { touchScroll = false ; } )
editor . events . $on ( editor . $el , 'touchmove' , function ( ) { touchScroll = true ; } ) ; }
editor . events . on ( 'html.set' , _refreshVideoList ) ; _refreshVideoList ( ) ; editor . events . $on ( editor . $el , 'mousedown' , 'span.fr-video' , function ( e ) { e . stopPropagation ( ) ; } )
editor . events . $on ( editor . $el , 'click touchend' , 'span.fr-video' , _edit ) ; editor . events . on ( 'keydown' , function ( e ) { var key _code = e . which ; if ( $current _video && ( key _code == $ . FE . KEYCODE . BACKSPACE || key _code == $ . FE . KEYCODE . DELETE ) ) { e . preventDefault ( ) ; remove ( ) ; return false ; }
if ( $current _video && key _code == $ . FE . KEYCODE . ESC ) { _exitEdit ( true ) ; e . preventDefault ( ) ; return false ; }
if ( $current _video && ! editor . keys . ctrlKey ( e ) ) { e . preventDefault ( ) ; return false ; } } , true ) ; editor . events . on ( 'keydown' , function ( ) { editor . $el . find ( 'span.fr-video:empty' ) . remove ( ) ; } )
_initInsertPopup ( true ) ; _initSizePopup ( true ) ; }
function back ( ) { if ( $current _video ) { $current _video . trigger ( 'click' ) ; }
else { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; editor . popups . hide ( 'video.insert' ) ; editor . toolbar . showInline ( ) ; } }
function setSize ( width , height ) { if ( $current _video ) { var $popup = editor . popups . get ( 'video.size' ) ; var $video _obj = $current _video . find ( 'iframe, embed, video' ) ; $video _obj . css ( 'width' , width || $popup . find ( 'input[name="width"]' ) . val ( ) ) ; $video _obj . css ( 'height' , height || $popup . find ( 'input[name="height"]' ) . val ( ) ) ; if ( $video _obj . get ( 0 ) . style . width ) $video _obj . removeAttr ( 'width' ) ; if ( $video _obj . get ( 0 ) . style . height ) $video _obj . removeAttr ( 'height' ) ; $popup . find ( 'input' ) . blur ( ) ; setTimeout ( function ( ) { $current _video . trigger ( 'click' ) ; } , editor . helpers . isAndroid ( ) ? 50 : 0 ) ; } }
function get ( ) { return $current _video ; }
return { _init : _init , showInsertPopup : showInsertPopup , showLayer : showLayer , refreshByURLButton : refreshByURLButton , refreshEmbedButton : refreshEmbedButton , insertByURL : insertByURL , insertEmbed : insertEmbed , insert : insert , align : align , refreshAlign : refreshAlign , refreshAlignOnShow : refreshAlignOnShow , display : display , refreshDisplayOnShow : refreshDisplayOnShow , remove : remove , showSizePopup : showSizePopup , back : back , setSize : setSize , get : get } }
$ . FE . RegisterCommand ( 'insertVideo' , { title : 'Insert Video' , undo : false , focus : true , refreshAfterCallback : false , popup : true , callback : function ( ) { if ( ! this . popups . isVisible ( 'video.insert' ) ) { this . video . showInsertPopup ( ) ; }
else { if ( this . $el . find ( '.fr-marker' ) ) { this . events . disableBlur ( ) ; this . selection . restore ( ) ; }
this . popups . hide ( 'video.insert' ) ; } } , plugin : 'video' } )
$ . FE . DefineIcon ( 'insertVideo' , { NAME : 'video-camera' } ) ; $ . FE . DefineIcon ( 'videoByURL' , { NAME : 'link' } ) ; $ . FE . RegisterCommand ( 'videoByURL' , { title : 'By URL' , undo : false , focus : false , callback : function ( ) { this . video . showLayer ( 'video-by-url' ) ; } , refresh : function ( $btn ) { this . video . refreshByURLButton ( $btn ) ; } } )
$ . FE . DefineIcon ( 'videoEmbed' , { NAME : 'code' } ) ; $ . FE . RegisterCommand ( 'videoEmbed' , { title : 'Embedded Code' , undo : false , focus : false , callback : function ( ) { this . video . showLayer ( 'video-embed' ) ; } , refresh : function ( $btn ) { this . video . refreshEmbedButton ( $btn ) ; } } )
$ . FE . RegisterCommand ( 'videoInsertByURL' , { undo : true , focus : true , callback : function ( ) { this . video . insertByURL ( ) ; } } )
$ . FE . RegisterCommand ( 'videoInsertEmbed' , { undo : true , focus : true , callback : function ( ) { this . video . insertEmbed ( ) ; } } )
$ . FE . DefineIcon ( 'videoDisplay' , { NAME : 'star' } )
$ . FE . RegisterCommand ( 'videoDisplay' , { title : 'Display' , type : 'dropdown' , options : { inline : 'Inline' , block : 'Break Text' } , callback : function ( cmd , val ) { this . video . display ( val ) ; } , refresh : function ( $btn ) { if ( ! this . opts . videoTextNear ) $btn . addClass ( 'fr-hidden' ) ; } , refreshOnShow : function ( $btn , $dropdown ) { this . video . refreshDisplayOnShow ( $btn , $dropdown ) ; } } )
$ . FE . DefineIcon ( 'videoAlign' , { NAME : 'align-center' } )
$ . FE . RegisterCommand ( 'videoAlign' , { type : 'dropdown' , title : 'Align' , options : { left : 'Align Left' , justify : 'None' , right : 'Align Right' } , html : function ( ) { var c = '<ul class="fr-dropdown-list">' ; var options = $ . FE . COMMANDS . videoAlign . options ; for ( var val in options ) { if ( options . hasOwnProperty ( val ) ) { c += '<li><a class="fr-command fr-title" data-cmd="videoAlign" data-param1="' + val + '" title="' + this . language . translate ( options [ val ] ) + '">' + this . icon . create ( 'align-' + val ) + '</a></li>' ; } }
c += '</ul>' ; return c ; } , callback : function ( cmd , val ) { this . video . align ( val ) ; } , refresh : function ( $btn ) { this . video . refreshAlign ( $btn ) ; } , refreshOnShow : function ( $btn , $dropdown ) { this . video . refreshAlignOnShow ( $btn , $dropdown ) ; } } )
$ . FE . DefineIcon ( 'videoRemove' , { NAME : 'trash' } )
$ . FE . RegisterCommand ( 'videoRemove' , { title : 'Remove' , callback : function ( ) { this . video . remove ( ) ; } } )
$ . FE . DefineIcon ( 'videoSize' , { NAME : 'arrows-alt' } )
$ . FE . RegisterCommand ( 'videoSize' , { undo : false , focus : false , title : 'Change Size' , callback : function ( ) { this . video . showSizePopup ( ) ; } } ) ; $ . FE . DefineIcon ( 'videoBack' , { NAME : 'arrow-left' } ) ; $ . FE . RegisterCommand ( 'videoBack' , { title : 'Back' , undo : false , focus : false , back : true , callback : function ( ) { this . video . back ( ) ; } , refresh : function ( $btn ) { var $current _video = this . video . get ( ) ; if ( ! $current _video && ! this . opts . toolbarInline ) { $btn . addClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . addClass ( 'fr-hidden' ) ; }
else { $btn . removeClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . removeClass ( 'fr-hidden' ) ; } } } ) ; $ . FE . RegisterCommand ( 'videoSetSize' , { undo : true , focus : false , callback : function ( ) { this . video . setSize ( ) ; } } ) } ) ) ; ( function ( factory ) { if ( typeof define === 'function' && define . amd ) { define ( [ 'jquery' ] , factory ) ; } else if ( typeof module === 'object' && module . exports ) { module . exports = function ( root , jQuery ) { if ( jQuery === undefined ) { if ( typeof window !== 'undefined' ) { jQuery = require ( 'jquery' ) ; }
2016-05-21 02:38:04 +00:00
else { jQuery = require ( 'jquery' ) ( root ) ; } }
factory ( jQuery ) ; return jQuery ; } ; } else { factory ( jQuery ) ; } } ( function ( $ ) { 'use strict' ; $ . extend ( $ . FE . POPUP _TEMPLATES , { 'audio.insert' : '[_BUTTONS_][_BY_URL_LAYER_][_EMBED_LAYER_]' , 'audio.edit' : '[_BUTTONS_]' , 'audio.size' : '[_BUTTONS_][_SIZE_LAYER_]' } )
$ . extend ( $ . FE . DEFAULTS , { audioInsertButtons : [ 'audioBack' , '|' , 'audioByURL' , 'audioEmbed' ] , audioEditButtons : [ 'audioDisplay' , 'audioAlign' , 'audioSize' , 'audioRemove' ] , audioResize : true , audioSizeButtons : [ 'audioBack' , '|' ] , audioSplitHTML : false , audioTextNear : true , audioDefaultAlign : 'center' , audioDefaultDisplay : 'block' , audioMove : true } ) ; $ . FE . VIDEO _PROVIDERS = [ ] ; $ . FE . VIDEO _EMBED _REGEX = /^\W*((<iframe.*><\/iframe>)|(<embed.*>))\W*$/i ; $ . FE . PLUGINS . audio = function ( editor ) { var $overlay ; var $handler ; var $audio _resizer ; var $current _audio ; function _refreshInsertPopup ( ) { var $popup = editor . popups . get ( 'audio.insert' ) ; var $url _input = $popup . find ( '.fr-audio-by-url-layer input' ) ; $url _input . val ( '' ) . trigger ( 'change' ) ; var $embed _area = $popup . find ( '.fr-audio-embed-layer textarea' ) ; $embed _area . val ( '' ) . trigger ( 'change' ) ; }
function showInsertPopup ( ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertAudio"]' ) ; var $popup = editor . popups . get ( 'audio.insert' ) ; if ( ! $popup ) $popup = _initInsertPopup ( ) ; if ( ! $popup . hasClass ( 'fr-active' ) ) { editor . popups . refresh ( 'audio.insert' ) ; editor . popups . setContainer ( 'audio.insert' , editor . $tb ) ; var left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; var top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; editor . popups . show ( 'audio.insert' , left , top , $btn . outerHeight ( ) ) ; } }
function _showEditPopup ( ) { var $popup = editor . popups . get ( 'audio.edit' ) ; if ( ! $popup ) $popup = _initEditPopup ( ) ; editor . popups . setContainer ( 'audio.edit' , $ ( editor . opts . scrollableContainer ) ) ; editor . popups . refresh ( 'audio.edit' ) ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' ) ; var left = $audio _obj . offset ( ) . left + $audio _obj . outerWidth ( ) / 2 ; var top = $audio _obj . offset ( ) . top + $audio _obj . outerHeight ( ) ; editor . popups . show ( 'audio.edit' , left , top , $audio _obj . outerHeight ( ) ) ; }
function _initInsertPopup ( delayed ) { if ( delayed ) { editor . popups . onRefresh ( 'audio.insert' , _refreshInsertPopup ) ; return true ; }
var audio _buttons = '' ; if ( editor . opts . audioInsertButtons . length > 1 ) { audio _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . audioInsertButtons ) + '</div>' ; }
var by _url _layer = '' ; if ( editor . opts . audioInsertButtons . indexOf ( 'audioByURL' ) >= 0 ) { by _url _layer = '<div class="fr-audio-by-url-layer fr-layer fr-active" id="fr-audio-by-url-layer-' + editor . id + '"><div class="fr-input-line"><input type="text" placeholder="http://" tabIndex="1"></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="audioInsertByURL" tabIndex="2">' + editor . language . translate ( 'Insert' ) + '</button></div></div>' }
var embed _layer = '' ; if ( editor . opts . audioInsertButtons . indexOf ( 'audioEmbed' ) >= 0 ) { embed _layer = '<div class="fr-audio-embed-layer fr-layer" id="fr-audio-embed-layer-' + editor . id + '"><div class="fr-input-line"><textarea type="text" placeholder="' + editor . language . translate ( 'Embedded Code' ) + '" tabIndex="1" rows="5"></textarea></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="audioInsertEmbed" tabIndex="2">' + editor . language . translate ( 'Insert' ) + '</button></div></div>' }
var template = { buttons : audio _buttons , by _url _layer : by _url _layer , embed _layer : embed _layer }
var $popup = editor . popups . create ( 'audio.insert' , template ) ; return $popup ; }
function showLayer ( name ) { var $popup = editor . popups . get ( 'audio.insert' ) ; var left ; var top ; if ( ! $current _audio && ! editor . opts . toolbarInline ) { var $btn = editor . $tb . find ( '.fr-command[data-cmd="insertAudio"]' ) ; left = $btn . offset ( ) . left + $btn . outerWidth ( ) / 2 ; top = $btn . offset ( ) . top + ( editor . opts . toolbarBottom ? 10 : $btn . outerHeight ( ) - 10 ) ; }
if ( editor . opts . toolbarInline ) { top = $popup . offset ( ) . top - editor . helpers . getPX ( $popup . css ( 'margin-top' ) ) ; if ( $popup . hasClass ( 'fr-above' ) ) { top += $popup . outerHeight ( ) ; } }
$popup . find ( '.fr-layer' ) . removeClass ( 'fr-active' ) ; $popup . find ( '.fr-' + name + '-layer' ) . addClass ( 'fr-active' ) ; editor . popups . show ( 'audio.insert' , left , top , 0 ) ; }
function refreshByURLButton ( $btn ) { var $popup = editor . popups . get ( 'audio.insert' ) ; if ( $popup . find ( '.fr-audio-by-url-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
function refreshEmbedButton ( $btn ) { var $popup = editor . popups . get ( 'audio.insert' ) ; if ( $popup . find ( '.fr-audio-embed-layer' ) . hasClass ( 'fr-active' ) ) { $btn . addClass ( 'fr-active' ) ; } }
function insert ( embedded _code ) { editor . events . focus ( true ) ; editor . selection . restore ( ) ; editor . html . insert ( '<span contenteditable="false" draggable="true" class="fr-jiv fr-video fr-dv' + ( editor . opts . audioDefaultDisplay [ 0 ] ) + ( editor . opts . audioDefaultAlign != 'center' ? ' fr-fv' + editor . opts . audioDefaultAlign [ 0 ] : '' ) + '">' + embedded _code + '</span>' , false , editor . opts . audioSplitHTML ) ; editor . popups . hide ( 'audio.insert' ) ; var $audio = editor . $el . find ( '.fr-jiv' ) ; $audio . removeClass ( 'fr-jiv' ) ; $audio . toggleClass ( 'fr-draggable' , editor . opts . audioMove ) ; editor . events . trigger ( 'audio.inserted' , [ $audio ] ) ; }
function insertByURL ( link ) { if ( typeof link == 'undefined' ) { var $popup = editor . popups . get ( 'audio.insert' ) ; link = $popup . find ( '.fr-audio-by-url-layer input[type="text"]' ) . val ( ) || '' ; }
var audio = null ; if ( editor . helpers . isURL ( link ) ) { for ( var i = 0 ; i < $ . FE . VIDEO _PROVIDERS . length ; i ++ ) { var vp = $ . FE . VIDEO _PROVIDERS [ i ] ; if ( vp . test _regex . test ( link ) ) { audio = link . replace ( vp . url _regex , vp . url _text ) ; audio = vp . html . replace ( /\{url\}/ , audio ) ; break ; } } }
if ( audio ) { insert ( audio ) ; }
else { editor . events . trigger ( 'audio.linkError' , [ link ] ) ; } }
function insertEmbed ( code ) { if ( typeof code == 'undefined' ) { var $popup = editor . popups . get ( 'audio.insert' ) ; code = $popup . find ( '.fr-audio-embed-layer textarea' ) . val ( ) || '' ; }
if ( code . length === 0 || ! $ . FE . VIDEO _EMBED _REGEX . test ( code ) ) { editor . events . trigger ( 'audio.codeError' , [ code ] ) ; }
else { insert ( code ) ; } }
function _handlerMousedown ( e ) { if ( ! editor . core . sameInstance ( $audio _resizer ) ) return true ; e . preventDefault ( ) ; e . stopPropagation ( ) ; var c _x = e . pageX || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageX : null ) ; var c _y = e . pageY || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageY : null ) ; if ( ! c _x || ! c _y ) { return false ; }
if ( ! editor . undo . canDo ( ) ) editor . undo . saveStep ( ) ; $handler = $ ( this ) ; $handler . data ( 'start-x' , c _x ) ; $handler . data ( 'start-y' , c _y ) ; $overlay . show ( ) ; editor . popups . hideAll ( ) ; _unmarkExit ( ) ; }
function _handlerMousemove ( e ) { if ( ! editor . core . sameInstance ( $audio _resizer ) ) return true ; if ( $handler ) { e . preventDefault ( )
var c _x = e . pageX || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageX : null ) ; var c _y = e . pageY || ( e . originalEvent . touches ? e . originalEvent . touches [ 0 ] . pageY : null ) ; if ( ! c _x || ! c _y ) { return false ; }
var s _x = $handler . data ( 'start-x' ) ; var s _y = $handler . data ( 'start-y' ) ; $handler . data ( 'start-x' , c _x ) ; $handler . data ( 'start-y' , c _y ) ; var diff _x = c _x - s _x ; var diff _y = c _y - s _y ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' ) ; var width = $audio _obj . width ( ) ; var height = $audio _obj . height ( ) ; if ( $handler . hasClass ( 'fr-hnw' ) || $handler . hasClass ( 'fr-hsw' ) ) { diff _x = 0 - diff _x ; }
if ( $handler . hasClass ( 'fr-hnw' ) || $handler . hasClass ( 'fr-hne' ) ) { diff _y = 0 - diff _y ; }
$audio _obj . css ( 'width' , width + diff _x ) ; $audio _obj . css ( 'height' , height + diff _y ) ; $audio _obj . removeAttr ( 'width' ) ; $audio _obj . removeAttr ( 'height' ) ; _repositionResizer ( ) ; } }
function _handlerMouseup ( e ) { if ( ! editor . core . sameInstance ( $audio _resizer ) ) return true ; if ( $handler && $current _audio ) { if ( e ) e . stopPropagation ( ) ; $handler = null ; $overlay . hide ( ) ; _repositionResizer ( ) ; _showEditPopup ( ) ; editor . undo . saveStep ( ) ; } }
function _getHandler ( pos ) { return '<div class="fr-handler fr-h' + pos + '"></div>' ; }
function _initResizer ( ) { var doc ; if ( ! editor . shared . $audio _resizer ) { editor . shared . $audio _resizer = $ ( '<div class="fr-video-resizer"></div>' ) ; $audio _resizer = editor . shared . $audio _resizer ; editor . events . $on ( $audio _resizer , 'mousedown' , function ( e ) { e . stopPropagation ( ) ; } , true ) ; if ( editor . opts . audioResize ) { $audio _resizer . append ( _getHandler ( 'nw' ) + _getHandler ( 'ne' ) + _getHandler ( 'sw' ) + _getHandler ( 'se' ) ) ; editor . shared . $audio _overlay = $ ( '<div class="fr-video-overlay"></div>' ) ; $overlay = editor . shared . $audio _overlay ; doc = $audio _resizer . get ( 0 ) . ownerDocument ; $ ( doc ) . find ( 'body' ) . append ( $overlay ) ; } } else { $audio _resizer = editor . shared . $audio _resizer ; $overlay = editor . shared . $audio _overlay ; editor . events . on ( 'destroy' , function ( ) { $audio _resizer . removeClass ( 'fr-active' ) . appendTo ( $ ( 'body' ) ) ; } , true ) ; }
2016-05-21 21:24:04 +00:00
editor . events . on ( 'shared.destroy' , function ( ) { $audio _resizer . html ( '' ) . removeData ( ) . remove ( ) ; $audio _resizer = null ; if ( editor . opts . audioResize ) { $overlay . remove ( ) ; $overlay = null ; } } , true ) ; if ( ! editor . helpers . isMobile ( ) ) { editor . events . $on ( $ ( editor . o _win ) , 'resize.audio' , function ( ) { _exitEdit ( true ) ; } ) ; }
2016-05-21 02:38:04 +00:00
if ( editor . opts . audioResize ) { doc = $audio _resizer . get ( 0 ) . ownerDocument ; editor . events . $on ( $audio _resizer , editor . _mousedown , '.fr-handler' , _handlerMousedown ) ; editor . events . $on ( $ ( doc ) , editor . _mousemove , _handlerMousemove ) ; editor . events . $on ( $ ( doc . defaultView || doc . parentWindow ) , editor . _mouseup , _handlerMouseup ) ; editor . events . $on ( $overlay , 'mouseleave' , _handlerMouseup ) ; } }
function _repositionResizer ( ) { if ( ! $audio _resizer ) _initResizer ( ) ; ( editor . $wp || $ ( editor . opts . scrollableContainer ) ) . append ( $audio _resizer ) ; $audio _resizer . data ( 'instance' , editor ) ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' ) ; $audio _resizer . css ( 'top' , ( editor . opts . iframe ? $audio _obj . offset ( ) . top - 1 : $audio _obj . offset ( ) . top - editor . $wp . offset ( ) . top - 1 ) + editor . $wp . scrollTop ( ) ) . css ( 'left' , ( editor . opts . iframe ? $audio _obj . offset ( ) . left - 1 : $audio _obj . offset ( ) . left - editor . $wp . offset ( ) . left - 1 ) + editor . $wp . scrollLeft ( ) ) . css ( 'width' , $audio _obj . outerWidth ( ) ) . css ( 'height' , $audio _obj . height ( ) ) . addClass ( 'fr-active' ) }
var touchScroll ; function _edit ( e ) { if ( e && e . type == 'touchend' && touchScroll ) { return true ; }
e . preventDefault ( ) ; e . stopPropagation ( ) ; if ( editor . edit . isDisabled ( ) ) { return false ; }
for ( var i = 0 ; i < $ . FE . INSTANCES . length ; i ++ ) { if ( $ . FE . INSTANCES [ i ] != editor ) { $ . FE . INSTANCES [ i ] . events . trigger ( 'audio.hideResizer' ) ; } }
editor . toolbar . disable ( ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . disableBlur ( ) ; editor . $el . blur ( ) ; editor . events . enableBlur ( ) ; }
$current _audio = $ ( this ) ; $ ( this ) . addClass ( 'fr-active' ) ; if ( editor . opts . iframe ) { editor . size . syncIframe ( ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; editor . selection . clear ( ) ; editor . button . bulkRefresh ( ) ; editor . events . trigger ( 'image.hideResizer' ) ; }
function _exitEdit ( force _exit ) { if ( $current _audio && ( _canExit ( ) || force _exit === true ) ) { $audio _resizer . removeClass ( 'fr-active' ) ; editor . toolbar . enable ( ) ; $current _audio . removeClass ( 'fr-active' ) ; $current _audio = null ; _unmarkExit ( ) ; } }
editor . shared . audio _exit _flag = false ; function _markExit ( ) { editor . shared . audio _exit _flag = true ; }
function _unmarkExit ( ) { editor . shared . audio _exit _flag = false ; }
function _canExit ( ) { return editor . shared . audio _exit _flag ; }
function _initEvents ( ) { editor . events . on ( 'mousedown window.mousedown' , _markExit ) ; editor . events . on ( 'window.touchmove' , _unmarkExit ) ; editor . events . on ( 'mouseup window.mouseup' , _exitEdit ) ; editor . events . on ( 'commands.mousedown' , function ( $btn ) { if ( $btn . parents ( '.fr-toolbar' ) . length > 0 ) { _exitEdit ( ) ; } } ) ; editor . events . on ( 'blur audio.hideResizer commands.undo commands.redo element.dropped' , function ( ) { _exitEdit ( true ) ; } ) ; }
2016-05-21 21:24:04 +00:00
function _initEditPopup ( ) { var audio _buttons = '' ; if ( editor . opts . audioEditButtons . length >= 1 ) { audio _buttons += '<div class="fr-buttons">' ; audio _buttons += editor . button . buildList ( editor . opts . audioEditButtons ) ; audio _buttons += '</div>' ; }
2016-05-21 02:38:04 +00:00
var template = { buttons : audio _buttons }
var $popup = editor . popups . create ( 'audio.edit' , template ) ; editor . events . $on ( editor . $wp , 'scroll.audio-edit' , function ( ) { if ( $current _audio && editor . popups . isVisible ( 'audio.edit' ) ) { _showEditPopup ( ) ; } } ) ; return $popup ; }
function _refreshSizePopup ( ) { if ( $current _audio ) { var $popup = editor . popups . get ( 'audio.size' ) ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' )
$popup . find ( 'input[name="width"]' ) . val ( $audio _obj . get ( 0 ) . style . width || $audio _obj . attr ( 'width' ) ) . trigger ( 'change' ) ; $popup . find ( 'input[name="height"]' ) . val ( $audio _obj . get ( 0 ) . style . height || $audio _obj . attr ( 'height' ) ) . trigger ( 'change' ) ; } }
function showSizePopup ( ) { var $popup = editor . popups . get ( 'audio.size' ) ; if ( ! $popup ) $popup = _initSizePopup ( ) ; editor . popups . refresh ( 'audio.size' ) ; editor . popups . setContainer ( 'audio.size' , $ ( editor . opts . scrollableContainer ) ) ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' )
var left = $audio _obj . offset ( ) . left + $audio _obj . width ( ) / 2 ; var top = $audio _obj . offset ( ) . top + $audio _obj . height ( ) ; editor . popups . show ( 'audio.size' , left , top , $audio _obj . height ( ) ) ; }
function _initSizePopup ( delayed ) { if ( delayed ) { editor . popups . onRefresh ( 'audio.size' , _refreshSizePopup ) ; return true ; }
var audio _buttons = '' ; audio _buttons = '<div class="fr-buttons">' + editor . button . buildList ( editor . opts . audioSizeButtons ) + '</div>' ; var size _layer = '' ; size _layer = '<div class="fr-video-size-layer fr-layer fr-active" id="fr-video-size-layer-' + editor . id + '"><div class="fr-audio-group"><div class="fr-input-line"><input type="text" name="width" placeholder="' + editor . language . translate ( 'Width' ) + '" tabIndex="1"></div><div class="fr-input-line"><input type="text" name="height" placeholder="' + editor . language . translate ( 'Height' ) + '" tabIndex="1"></div></div><div class="fr-action-buttons"><button type="button" class="fr-command fr-submit" data-cmd="audioSetSize" tabIndex="2">' + editor . language . translate ( 'Update' ) + '</button></div></div>' ; var template = { buttons : audio _buttons , size _layer : size _layer }
var $popup = editor . popups . create ( 'audio.size' , template ) ; editor . events . $on ( editor . $wp , 'scroll' , function ( ) { if ( $current _audio && editor . popups . isVisible ( 'audio.size' ) ) { showSizePopup ( ) ; } } ) ; return $popup ; }
function align ( val ) { $current _audio . removeClass ( 'fr-fvr fr-fvl' ) ; if ( val == 'left' ) { $current _audio . addClass ( 'fr-fvl' ) ; }
else if ( val == 'right' ) { $current _audio . addClass ( 'fr-fvr' ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; }
function refreshAlign ( $btn ) { if ( ! $current _audio ) return false ; if ( $current _audio . hasClass ( 'fr-fvl' ) ) { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-left' ) ) ; }
else if ( $current _audio . hasClass ( 'fr-fvr' ) ) { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-right' ) ) ; }
else { $btn . find ( '> *:first' ) . replaceWith ( editor . icon . create ( 'align-justify' ) ) ; } }
function refreshAlignOnShow ( $btn , $dropdown ) { var alignment = 'justify' ; if ( $current _audio . hasClass ( 'fr-fvl' ) ) { alignment = 'left' ; }
else if ( $current _audio . hasClass ( 'fr-fvr' ) ) { alignment = 'right' ; }
$dropdown . find ( '.fr-command[data-param1="' + alignment + '"]' ) . addClass ( 'fr-active' ) ; }
function display ( val ) { $current _audio . removeClass ( 'fr-dvi fr-dvb' ) ; if ( val == 'inline' ) { $current _audio . addClass ( 'fr-dvi' ) ; }
else if ( val == 'block' ) { $current _audio . addClass ( 'fr-dvb' ) ; }
_repositionResizer ( ) ; _showEditPopup ( ) ; }
function refreshDisplayOnShow ( $btn , $dropdown ) { var d = 'block' ; if ( $current _audio . hasClass ( 'fr-dvi' ) ) { d = 'inline' ; }
$dropdown . find ( '.fr-command[data-param1="' + d + '"]' ) . addClass ( 'fr-active' ) ; }
function remove ( ) { if ( $current _audio ) { if ( editor . events . trigger ( 'audio.beforeRemove' , [ $current _audio ] ) !== false ) { var $audio = $current _audio ; editor . popups . hideAll ( ) ; _exitEdit ( true ) ; editor . selection . setBefore ( $audio . get ( 0 ) ) || editor . selection . setAfter ( $audio . get ( 0 ) ) ; $audio . remove ( ) ; editor . selection . restore ( ) ; editor . html . fillEmptyBlocks ( ) ; editor . events . trigger ( 'audio.removed' , [ $audio ] ) ; } } }
function _convertStyleToClasses ( $audio ) { if ( ! $audio . hasClass ( 'fr-dvi' ) && ! $audio . hasClass ( 'fr-dvb' ) ) { var flt = $audio . css ( 'float' ) ; $audio . css ( 'float' , 'none' ) ; if ( $audio . css ( 'display' ) == 'block' ) { $audio . css ( 'float' , flt ) ; if ( parseInt ( $audio . css ( 'margin-left' ) , 10 ) === 0 && ( $audio . attr ( 'style' ) || '' ) . indexOf ( 'margin-right: auto' ) >= 0 ) { $audio . addClass ( 'fr-fvl' ) ; }
else if ( parseInt ( $audio . css ( 'margin-right' ) , 10 ) === 0 && ( $audio . attr ( 'style' ) || '' ) . indexOf ( 'margin-left: auto' ) >= 0 ) { $audio . addClass ( 'fr-fvr' ) ; }
$audio . addClass ( 'fr-dvb' ) ; }
else { $audio . css ( 'float' , flt ) ; if ( $audio . css ( 'float' ) == 'left' ) { $audio . addClass ( 'fr-fvl' ) ; }
else if ( $audio . css ( 'float' ) == 'right' ) { $audio . addClass ( 'fr-fvr' ) ; }
$audio . addClass ( 'fr-dvi' ) ; }
$audio . css ( 'margin' , '' ) ; $audio . css ( 'float' , '' ) ; $audio . css ( 'display' , '' ) ; $audio . css ( 'z-index' , '' ) ; $audio . css ( 'position' , '' ) ; $audio . css ( 'overflow' , '' ) ; $audio . css ( 'vertical-align' , '' ) ; }
if ( ! editor . opts . audioTextNear ) { $audio . removeClass ( 'fr-dvi' ) . addClass ( 'fr-dvb' ) ; } }
function _refreshAudioList ( ) { editor . $el . find ( 'audio' ) . filter ( function ( ) { return $ ( this ) . parents ( 'span.fr-video' ) . length === 0 ; } ) . wrap ( '<span class="fr-video" contenteditable="false"></span>' ) ; editor . $el . find ( 'embed, iframe' ) . filter ( function ( ) { if ( editor . browser . safari && this . getAttribute ( 'src' ) ) { this . setAttribute ( 'src' , this . src ) ; }
if ( $ ( this ) . parents ( 'span.fr-video' ) . length > 0 ) return false ; var link = $ ( this ) . attr ( 'src' ) ; for ( var i = 0 ; i < $ . FE . VIDEO _PROVIDERS . length ; i ++ ) { var vp = $ . FE . VIDEO _PROVIDERS [ i ] ; if ( vp . test _regex . test ( link ) ) { return true ; } }
return false ; } ) . map ( function ( ) { return $ ( this ) . parents ( 'object' ) . length === 0 ? this : $ ( this ) . parents ( 'object' ) . get ( 0 ) ; } ) . wrap ( '<span class="fr-video" contenteditable="false"></span>' ) ; var audios = editor . $el . find ( 'span.fr-video' ) ; for ( var i = 0 ; i < audios . length ; i ++ ) { _convertStyleToClasses ( $ ( audios [ i ] ) ) ; }
audios . toggleClass ( 'fr-draggable' , editor . opts . audioMove ) ; }
function _init ( ) { _initEvents ( ) ; if ( editor . helpers . isMobile ( ) ) { editor . events . $on ( editor . $el , 'touchstart' , 'span.fr-video' , function ( ) { touchScroll = false ; } )
editor . events . $on ( editor . $el , 'touchmove' , function ( ) { touchScroll = true ; } ) ; }
editor . events . on ( 'html.set' , _refreshAudioList ) ; _refreshAudioList ( ) ; editor . events . $on ( editor . $el , 'mousedown' , 'span.fr-video' , function ( e ) { e . stopPropagation ( ) ; } )
editor . events . $on ( editor . $el , 'click touchend' , 'span.fr-video' , _edit ) ; editor . events . on ( 'keydown' , function ( e ) { var key _code = e . which ; if ( $current _audio && ( key _code == $ . FE . KEYCODE . BACKSPACE || key _code == $ . FE . KEYCODE . DELETE ) ) { e . preventDefault ( ) ; remove ( ) ; return false ; }
if ( $current _audio && key _code == $ . FE . KEYCODE . ESC ) { _exitEdit ( true ) ; e . preventDefault ( ) ; return false ; }
if ( $current _audio && ! editor . keys . ctrlKey ( e ) ) { e . preventDefault ( ) ; return false ; } } , true ) ; editor . events . on ( 'keydown' , function ( ) { editor . $el . find ( 'span.fr-video:empty' ) . remove ( ) ; } )
_initInsertPopup ( true ) ; _initSizePopup ( true ) ; }
function back ( ) { if ( $current _audio ) { $current _audio . trigger ( 'click' ) ; }
else { editor . events . disableBlur ( ) ; editor . selection . restore ( ) ; editor . events . enableBlur ( ) ; editor . popups . hide ( 'audio.insert' ) ; editor . toolbar . showInline ( ) ; } }
function setSize ( width , height ) { if ( $current _audio ) { var $popup = editor . popups . get ( 'audio.size' ) ; var $audio _obj = $current _audio . find ( 'iframe, embed, audio' ) ; $audio _obj . css ( 'width' , width || $popup . find ( 'input[name="width"]' ) . val ( ) ) ; $audio _obj . css ( 'height' , height || $popup . find ( 'input[name="height"]' ) . val ( ) ) ; if ( $audio _obj . get ( 0 ) . style . width ) $audio _obj . removeAttr ( 'width' ) ; if ( $audio _obj . get ( 0 ) . style . height ) $audio _obj . removeAttr ( 'height' ) ; $popup . find ( 'input' ) . blur ( ) ; setTimeout ( function ( ) { $current _audio . trigger ( 'click' ) ; } , editor . helpers . isAndroid ( ) ? 50 : 0 ) ; } }
function get ( ) { return $current _audio ; }
return { _init : _init , showInsertPopup : showInsertPopup , showLayer : showLayer , refreshByURLButton : refreshByURLButton , refreshEmbedButton : refreshEmbedButton , insertByURL : insertByURL , insertEmbed : insertEmbed , insert : insert , align : align , refreshAlign : refreshAlign , refreshAlignOnShow : refreshAlignOnShow , display : display , refreshDisplayOnShow : refreshDisplayOnShow , remove : remove , showSizePopup : showSizePopup , back : back , setSize : setSize , get : get } }
$ . FE . RegisterCommand ( 'insertAudio' , { title : 'Insert Audio' , undo : false , focus : true , refreshAfterCallback : false , popup : true , callback : function ( ) { if ( ! this . popups . isVisible ( 'audio.insert' ) ) { this . audio . showInsertPopup ( ) ; }
else { if ( this . $el . find ( '.fr-marker' ) ) { this . events . disableBlur ( ) ; this . selection . restore ( ) ; }
this . popups . hide ( 'audio.insert' ) ; } } , plugin : 'audio' } )
$ . FE . DefineIcon ( 'insertAudio' , { NAME : 'volume-up' } ) ; $ . FE . DefineIcon ( 'audioByURL' , { NAME : 'link' } ) ; $ . FE . RegisterCommand ( 'audioByURL' , { title : 'By URL' , undo : false , focus : false , callback : function ( ) { this . audio . showLayer ( 'audio-by-url' ) ; } , refresh : function ( $btn ) { this . audio . refreshByURLButton ( $btn ) ; } } )
$ . FE . DefineIcon ( 'audioEmbed' , { NAME : 'code' } ) ; $ . FE . RegisterCommand ( 'audioEmbed' , { title : 'Embedded Code' , undo : false , focus : false , callback : function ( ) { this . audio . showLayer ( 'audio-embed' ) ; } , refresh : function ( $btn ) { this . audio . refreshEmbedButton ( $btn ) ; } } )
$ . FE . RegisterCommand ( 'audioInsertByURL' , { undo : true , focus : true , callback : function ( ) { this . audio . insertByURL ( ) ; } } )
$ . FE . RegisterCommand ( 'audioInsertEmbed' , { undo : true , focus : true , callback : function ( ) { this . audio . insertEmbed ( ) ; } } )
$ . FE . DefineIcon ( 'audioDisplay' , { NAME : 'star' } )
$ . FE . RegisterCommand ( 'audioDisplay' , { title : 'Display' , type : 'dropdown' , options : { inline : 'Inline' , block : 'Break Text' } , callback : function ( cmd , val ) { this . audio . display ( val ) ; } , refresh : function ( $btn ) { if ( ! this . opts . audioTextNear ) $btn . addClass ( 'fr-hidden' ) ; } , refreshOnShow : function ( $btn , $dropdown ) { this . audio . refreshDisplayOnShow ( $btn , $dropdown ) ; } } )
$ . FE . DefineIcon ( 'audioAlign' , { NAME : 'align-center' } )
$ . FE . RegisterCommand ( 'audioAlign' , { type : 'dropdown' , title : 'Align' , options : { left : 'Align Left' , justify : 'None' , right : 'Align Right' } , html : function ( ) { var c = '<ul class="fr-dropdown-list">' ; var options = $ . FE . COMMANDS . audioAlign . options ; for ( var val in options ) { if ( options . hasOwnProperty ( val ) ) { c += '<li><a class="fr-command fr-title" data-cmd="audioAlign" data-param1="' + val + '" title="' + this . language . translate ( options [ val ] ) + '">' + this . icon . create ( 'align-' + val ) + '</a></li>' ; } }
c += '</ul>' ; return c ; } , callback : function ( cmd , val ) { this . audio . align ( val ) ; } , refresh : function ( $btn ) { this . audio . refreshAlign ( $btn ) ; } , refreshOnShow : function ( $btn , $dropdown ) { this . audio . refreshAlignOnShow ( $btn , $dropdown ) ; } } )
$ . FE . DefineIcon ( 'audioRemove' , { NAME : 'trash' } )
$ . FE . RegisterCommand ( 'audioRemove' , { title : 'Remove' , callback : function ( ) { this . audio . remove ( ) ; } } )
$ . FE . DefineIcon ( 'audioSize' , { NAME : 'arrows-alt' } )
$ . FE . RegisterCommand ( 'audioSize' , { undo : false , focus : false , title : 'Change Size' , callback : function ( ) { this . audio . showSizePopup ( ) ; } } ) ; $ . FE . DefineIcon ( 'audioBack' , { NAME : 'arrow-left' } ) ; $ . FE . RegisterCommand ( 'audioBack' , { title : 'Back' , undo : false , focus : false , back : true , callback : function ( ) { this . audio . back ( ) ; } , refresh : function ( $btn ) { var $current _audio = this . audio . get ( ) ; if ( ! $current _audio && ! this . opts . toolbarInline ) { $btn . addClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . addClass ( 'fr-hidden' ) ; }
2019-04-30 06:24:00 +00:00
else { $btn . removeClass ( 'fr-hidden' ) ; $btn . next ( '.fr-separator' ) . removeClass ( 'fr-hidden' ) ; } } } ) ; $ . FE . RegisterCommand ( 'audioSetSize' , { undo : true , focus : false , callback : function ( ) { this . audio . setSize ( ) ; } } ) } ) ) ; ! function ( n ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , n ) : "object" == typeof module && module . exports ? module . exports = function ( e , t ) { return t === undefined && ( t = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( e ) ) , n ( t ) } : n ( window . jQuery ) } ( function ( a ) { a . FE . PLUGINS . quote = function ( r ) { function o ( e ) { for ( ; e . parentNode && e . parentNode != r . el ; ) e = e . parentNode ; return e } return { apply : function ( e ) { r . selection . save ( ) , r . html . wrap ( ! 0 , ! 0 , ! 0 , ! 0 ) , r . selection . restore ( ) , "increase" == e ? function ( ) { var e , t = r . selection . blocks ( ) ; for ( e = 0 ; e < t . length ; e ++ ) t [ e ] = o ( t [ e ] ) ; r . selection . save ( ) ; var n = a ( "<blockquote>" ) ; for ( n . insertBefore ( t [ 0 ] ) , e = 0 ; e < t . length ; e ++ ) n . append ( t [ e ] ) ; r . html . unwrap ( ) , r . selection . restore ( ) } ( ) : "decrease" == e && function ( ) { var e , t = r . selection . blocks ( ) ; for ( e = 0 ; e < t . length ; e ++ ) "BLOCKQUOTE" != t [ e ] . tagName && ( t [ e ] = a ( t [ e ] ) . parentsUntil ( r . $el , "BLOCKQUOTE" ) . get ( 0 ) ) ; for ( r . selection . save ( ) , e = 0 ; e < t . length ; e ++ ) t [ e ] && a ( t [ e ] ) . replaceWith ( t [ e ] . innerHTML ) ; r . html . unwrap ( ) , r . selection . restore ( ) } ( ) } } } , a . FE . RegisterShortcut ( a . FE . KEYCODE . SINGLE _QUOTE , "quote" , "increase" , "'" ) , a . FE . RegisterShortcut ( a . FE . KEYCODE . SINGLE _QUOTE , "quote" , "decrease" , "'" , ! 0 ) , a . FE . RegisterCommand ( "quote" , { title : "Quote" , type : "dropdown" , html : function ( ) { var e = '<ul class="fr-dropdown-list" role="presentation">' , t = { increase : "Increase" , decrease : "Decrease" } ; for ( var n in t ) if ( t . hasOwnProperty ( n ) ) { var r = this . shortcuts . get ( "quote." + n ) ; e += '<li role="presentation"><a class="fr-command fr-active ' + n + '" tabIndex="-1" role="option" data-cmd="quote" data-param1="' + n + '" title="' + t [ n ] + '">' + this . language . translate ( t [ n ] ) + ( r ? '<span class="fr-shortcut">' + r + "</span>" : "" ) + "</a></li>" } return e += "</ul>" } , callback : function ( e , t ) { this . quote . apply ( t ) } , plugin : "quote" } ) , a . FE . DefineIcon ( "quote" , { NAME : "quote-left" } ) } ) ; ! function ( n ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , n ) : "object" == typeof module && module . exports ? module . exports = function ( e , t ) { return t === undefined && ( t = "undefined" != typeof window ? require ( "jquery" ) : require ( "jquery" ) ( e ) ) , n ( t ) } : n ( window . jQuery ) } ( function ( f ) { f . extend ( f . FE . DEFAULTS , { fontSize : [ "8" , "9" , "10" , "11" , "12" , "14" , "18" , "24" , "30" , "36" , "48" , "60" , "72" , "96" ] , fontSizeSelection : ! 1 , fontSizeDefaultSelection : "12" , fontSizeUnit : "px" } ) , f . FE . PLUGINS . fontSize = function ( r ) { return { apply : function ( e ) { r . format . applyStyle ( "font-size" , e ) } , refreshOnShow : function ( e , t ) { var n = f ( r . selection . element ( ) ) . css ( "font-size" ) ; "pt" === r . opts . fontSizeUnit && ( n = Math . round ( 72 * parseFloat ( n , 10 ) / 96 ) + "pt" ) , t . find ( ".fr-command.fr-active" ) . removeClass ( "fr-active" ) . attr ( "aria-selected" , ! 1 ) , t . find ( '.fr-command[data-param1="' + n + '"]' ) . addClass ( "fr-active" ) . attr ( "aria-selected" , ! 0 ) ; var o = t . find ( ".fr-dropdown-list" ) , i = t . find ( ".fr-active" ) . parent ( ) ; i . length ? o . parent ( ) . scrollTop ( i . offset ( ) . top - o . offset ( ) . top - ( o . parent ( ) . outerHeight ( ) / 2 - i . outerHeight ( ) / 2 ) ) : o . parent ( ) . scrollTop ( 0 ) } , refresh : function ( e ) { if ( r . opts . fontSizeSelection ) { var t = r . helpers . getPX ( f ( r . selection . element ( ) ) . css ( "font-size" ) ) ; "pt" === r . opts . fontSizeUnit && ( t = Math . round ( 72 * parseFloat ( t , 10 ) / 96 ) + "pt" ) , e . find ( "> span" ) . text ( t ) } } } } , f . FE . RegisterCommand ( "fontSize" , { type : "dropdown" , title : "Font Size" , displaySelection : function ( e ) { return e . opts . fontSizeSelection } , displaySelectionWidth : 30 , defaultSelection : function ( e ) { return e . opts . fontSizeDefaultSelection } , html : function ( ) { for ( var e = '<ul class="fr-dropdown-list" role="presentation">' , t = this . opts . fontSize , n = 0 ; n < t . length ; n ++ ) { var o = t [ n ] ; e += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="fontSize" data-param1="' + o + this . opts . fontSizeUnit + '" title="' + o + '">' + o + "</a></li>" } return e += "</ul>" } , callback : function ( e , t ) { this . fontSize . apply ( t ) } , refresh : function ( e ) { this . fontSize . refresh ( e ) } , refreshOnShow : function ( e , t ) { this . fontSize . refreshOnShow ( e , t ) } , plugin : "fontSize" } ) , f . FE . DefineIcon ( "fontSize" , { NAME : "text-height" } ) } ) ; ! function ( n ) { "function" == typeof define && define . amd ? define ( [ "jquery" ] , n ) : "object" == typeof module &&