1( function( $, editorSettings ) { 2 3 HappyForms.parts = HappyForms.parts || {}; 4 5 window._wpLink = {}; 6 7 var defaultOnPostRender = function( editor, settings, e ) { 8 e.target.$el.html( $( '#' + settings.icon ).html() ); 9 }; 10 11 var GetButton = function( editor, settings ) { 12 var onPostRender = settings.onPostRender || defaultOnPostRender; 13 14 var button = Object.assign( {}, settings, { 15 onClick: settings.onClick.bind( this, editor ), 16 onPostRender: onPostRender.bind( this, editor, settings ), 17 } ); 18 19 return button; 20 }; 21 22 var buttons = { 23 hfbold: { 24 icon: 'happyforms-rich-text-icon-bold', 25 stateSelector: 'strong', 26 27 onClick: function ( editor ) { 28 editor.execCommand( 'mceToggleFormat', false, 'bold' ); 29 }, 30 }, 31 hfitalic: { 32 icon: 'happyforms-rich-text-icon-italic', 33 stateSelector: 'em', 34 35 onClick: function ( editor ) { 36 editor.execCommand( 'mceToggleFormat', false, 'italic' ); 37 }, 38 }, 39 hful: { 40 icon: 'happyforms-rich-text-icon-ul', 41 stateSelector: 'ul', 42 43 onClick: function ( editor ) { 44 editor.execCommand( 'InsertUnorderedList' ); 45 }, 46 }, 47 hfol: { 48 icon: 'happyforms-rich-text-icon-ol', 49 stateSelector: 'ol', 50 51 onClick: function ( editor ) { 52 editor.execCommand( 'InsertOrderedList' ); 53 }, 54 }, 55 hfquote: { 56 icon: 'happyforms-rich-text-icon-quote', 57 stateSelector: 'blockquote', 58 59 onClick: function ( editor ) { 60 editor.execCommand( 'mceToggleFormat', false, 'blockquote' ); 61 }, 62 }, 63 hfcode: { 64 icon: 'happyforms-rich-text-icon-code', 65 stateSelector: 'pre', 66 67 onClick: function ( editor ) { 68 editor.execCommand( 'mceToggleFormat', false, 'pre' ); 69 }, 70 }, 71 hfstrike: { 72 icon: 'happyforms-rich-text-icon-strike', 73 stateSelector: 'del', 74 75 onClick: function ( editor ) { 76 editor.execCommand( 'mceToggleFormat', false, 'strikethrough' ); 77 }, 78 }, 79 hfunderline: { 80 icon: 'happyforms-rich-text-icon-underline', 81 82 onClick: function ( editor ) { 83 editor.execCommand( 'mceToggleFormat', false, 'underline' ); 84 }, 85 86 onPostRender: function( editor, settings, e ) { 87 defaultOnPostRender.apply( this, arguments ); 88 89 var self = e.target; 90 91 editor.on( 'NodeChange', function( e ) { 92 self.active( 'underline' === e.element.style.textDecoration ); 93 } ); 94 }, 95 }, 96 hfhr: { 97 icon: 'happyforms-rich-text-icon-hr', 98 99 onClick: function ( editor ) { 100 editor.execCommand( 'InsertHorizontalRule' ); 101 }, 102 }, 103 }; 104 105 HappyForms.parts.multi_line_text = { 106 init: function( options ) { 107 this.$form = options.form; 108 this.rich = this.$el.hasClass( 'happyforms-part--rich_text' ); 109 this.type = this.$el.data( 'happyforms-type' ); 110 this.$input = $( 'textarea', this.$el ); 111 this.$counter = $( '.happyforms-part__char-counter span.counter', this.$el ); 112 113 if ( ! this.rich ) { 114 this.$input.on( 'blur', this.onBlur.bind( this ) ); 115 this.$input.on( 'keyup', this.triggerChange.bind( this ) ); 116 this.$input.on( 'change', this.triggerChange.bind( this ) ); 117 this.$el.on( 'keyup', this.refreshCounter.bind( this ) ); 118 this.refreshCounter(); 119 } else { 120 this.editorId = this.$input.attr( 'id' ); 121 this.editor = null; 122 123 this.$el.on( 'happyforms.attach', this.editorCreate.bind( this ) ); 124 this.$el.on( 'happyforms.detach', this.editorDestroy.bind( this ) ); 125 this.$el.on( 'happyforms.formclass', this.onFormClassChange.bind( this ) ); 126 this.$el.on( 'happyforms.cssvar', this.onCSSVarChange.bind( this ) ); 127 128 this.editorCreate(); 129 } 130 this.initTooltip(); 131 }, 132 133 getValueLength: function() { 134 var mode = this.$input.attr( 'data-length-mode' ); 135 var value = this.$input.val(); 136 137 if ( this.rich ) { 138 value = this.editor.getContent( { format: 'text' } ); 139 } 140 141 var length = value.length; 142 143 if ( 'word' === mode ) { 144 var matches = value.match( /\w+/g ); 145 length = matches ? matches.length : 0; 146 } else { 147 if ( this.rich && '\n' === value ) { 148 length --; 149 } 150 } 151 152 return length; 153 }, 154 155 refreshCounter: function() { 156 var hasLength = parseInt( this.$input.attr( 'data-length' ), 10 ); 157 158 if ( hasLength < 1 ) { 159 return; 160 } 161 162 var length = this.getValueLength(); 163 this.$counter.text( length ); 164 }, 165 166 editorCreate: function() { 167 var self = this; 168 169 tinymce.init( { 170 selector: '#' + this.editorId, 171 branding: false, 172 menubar: false, 173 toolbar1: 'hfbold,hfitalic,hful,hfol,hfquote,link,unlink,hfcode,hfstrike,hfunderline,hfhr', 174 statusbar: true, 175 resize: true, 176 plugins: 'hr,paste', 177 content_css: editorSettings.contentCSS,
178 valid_elements: editorSettings.validElements, 179 paste_as_text: true, 180 inline_styles: false, 181 formats: { 182 underline: { inline: 'u', exact : true }, 183 strikethrough: { inline: 'del', exact : true }, 184 }, 185 186 setup: function( editor ) { 187 var wpAddButton = editor.addButton; 188 189 // Remove tooltips 190 editor.addButton = function( id, options ) { 191 switch ( id ) { 192 case 'link': 193 case 'unlink': 194 case 'wp_link_apply': 195 case 'wp_link_edit': 196 case 'wp_link_remove': 197 delete options.tooltip; 198 break; 199 default: 200 break; 201 } 202 203 return wpAddButton.apply( this, arguments ); 204 } 205 206 // Add custom buttons 207 for ( var button in buttons ) { 208 editor.addButton( button, GetButton( editor, buttons[button] ) ); 209 } 210 211 // Inherit form class, fonts and css-vars 212 editor.on( 'init', function() { 213 self.editor = editor; 214 215 self.inheritFormClass(); 216 self.inheritFonts(); 217 218 var target = self.editor.dom.doc.querySelector( 'body' ); 219 self.inheritCSSVars( editorSettings.cssVars, target ); 220 self.refreshCounter(); 221 } ); 222 223 // Custom main toolbar icons 224 editor.on( 'postrender', function() { 225 var $el = $( editor.container ); 226 227 $( 'i.mce-i-link', $el ).replaceWith( 228 $( '#happyforms-rich-text-icon-link' ).html() 229 ); 230 231 $( 'i.mce-i-unlink', $el ).replaceWith( 232 $( '#happyforms-rich-text-icon-unlink' ).html() 233 ); 234 235 self.editor = editor; 236 237 var target = self.editor.dom.doc.querySelector( 'body' ); 238 target.style.color = $( 'body' ).css( 'color' ); 239 } ); 240 241 editor.on( 'change', self.onEditorChange.bind( self ) ); 242 editor.on( 'focus', self.onFocus.bind( self ) ); 243 editor.on( 'blur', self.onBlur.bind( self ) ); 244 editor.on( 'keyup', self.refreshCounter.bind( self ) ); 245 }, 246 } ); 247 }, 248 249 editorDestroy: function() { 250 var editor = tinymce.get( this.editorId ); 251 252 if ( editor ) { 253 editor.remove(); 254 } 255 256 self.editor = null; 257 }, 258 259 onEditorChange: function() { 260 this.triggerChange(); 261 }, 262 263 onFocus: function() { 264 this.$el.addClass( 'focus' ); 265 }, 266 267 onBlur: function() { 268 this.$el.removeClass( 'focus' ); 269 }, 270 271 inheritFormClass: function() { 272 this.editor.dom.doc.documentElement.className = this.$form.attr( 'class' ); 273 }, 274 275 inheritCSSVars: function( vars, target ) { 276 var styles = getComputedStyle( this.$form[0] ); 277 278 if ( 'object' !== typeof vars ) { 279 return; 280 } 281 282 vars.forEach( function( variable ) { 283 var value = styles.getPropertyValue( variable ); 284 target.style.setProperty( variable, value ); 285 } ); 286 }, 287 288 inheritFonts: function() { 289 var formStyle = getComputedStyle( this.$form[0] ); 290 var stylesheets = [].slice.call( document.styleSheets ); 291 var editorDocument = this.editor.dom.doc; 292 293 // Append parent stylesheets to editor 294 stylesheets 295 .map( function( stylesheet ) { 296 return stylesheet.ownerNode.cloneNode(); 297 } ) 298 .forEach( function( node ) { 299 editorDocument.head.insertBefore( node, editorDocument.head.firstChild ); 300 } ); 301 302 // Apply font-family 303 editorDocument.body.style.setProperty( 'font-family', formStyle.getPropertyValue( 'font-family' ) ); 304 }, 305 306 onFormClassChange: function( e, classes ) { 307 if ( this.editor ) { 308 this.editor.dom.doc.documentElement.className = classes; 309 } 310 }, 311 312 onCSSVarChange: function( e, variable ) { 313 if ( this.editor ) { 314 this.editor.dom.doc.querySelector( 'body' ).style.setProperty( variable.name, variable.value ); 315 316 $( '.happyforms-editor-toolbar-link' ).each( function() { 317 this.style.setProperty( variable.name, variable.value ); 318 } ); 319 } 320 }, 321 322 isFilled: function() { 323 if ( this.rich ) { 324 var content = wp.editor.getContent( this.editorId ); 325 return '' !== content; 326 } 327 328 return '' !== this.$input.val(); 329 }, 330 331 serialize: function() { 332 var serialized = HappyForms.parts.base.serialize.apply( this, arguments ); 333 334 if ( this.rich ) { 335 serialized = [ { 336 name: this.$input.attr( 'name' ), 337 value: tinymce.get( this.editorId ).getContent(), 338 } ]; 339 } 340 341 return serialized; 342 } 343 }; 344 345} )( jQuery, _happyFormsRichTextSettings );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.