run:R W Run
25.04 KB
2026-03-11 16:18:51
R W Run
11.78 KB
2026-03-11 16:18:51
R W Run
error_log
📄plugin.js
1/* global tinymce */
2tinymce.PluginManager.add( 'wpeditimage', function( editor ) {
3 var toolbar, serializer, touchOnImage, pasteInCaption,
4 each = tinymce.each,
5 trim = tinymce.trim,
6 iOS = tinymce.Env.iOS;
7
8 function isPlaceholder( node ) {
9 return !! ( editor.dom.getAttrib( node, 'data-mce-placeholder' ) || editor.dom.getAttrib( node, 'data-mce-object' ) );
10 }
11
12 editor.addButton( 'wp_img_remove', {
13 tooltip: 'Remove',
14 icon: 'dashicon dashicons-no',
15 onclick: function() {
16 removeImage( editor.selection.getNode() );
17 }
18 } );
19
20 editor.addButton( 'wp_img_edit', {
21 tooltip: 'Edit|button', // '|button' is not displayed, only used for context.
22 icon: 'dashicon dashicons-edit',
23 onclick: function() {
24 editImage( editor.selection.getNode() );
25 }
26 } );
27
28 each( {
29 alignleft: 'Align left',
30 aligncenter: 'Align center',
31 alignright: 'Align right',
32 alignnone: 'No alignment'
33 }, function( tooltip, name ) {
34 var direction = name.slice( 5 );
35
36 editor.addButton( 'wp_img_' + name, {
37 tooltip: tooltip,
38 icon: 'dashicon dashicons-align-' + direction,
39 cmd: 'alignnone' === name ? 'wpAlignNone' : 'Justify' + direction.slice( 0, 1 ).toUpperCase() + direction.slice( 1 ),
40 onPostRender: function() {
41 var self = this;
42
43 editor.on( 'NodeChange', function( event ) {
44 var node;
45
46 // Don't bother.
47 if ( event.element.nodeName !== 'IMG' ) {
48 return;
49 }
50
51 node = editor.dom.getParent( event.element, '.wp-caption' ) || event.element;
52
53 if ( 'alignnone' === name ) {
54 self.active( ! /\balign(left|center|right)\b/.test( node.className ) );
55 } else {
56 self.active( editor.dom.hasClass( node, name ) );
57 }
58 } );
59 }
60 } );
61 } );
62
63 editor.once( 'preinit', function() {
64 if ( editor.wp && editor.wp._createToolbar ) {
65 toolbar = editor.wp._createToolbar( [
66 'wp_img_alignleft',
67 'wp_img_aligncenter',
68 'wp_img_alignright',
69 'wp_img_alignnone',
70 'wp_img_edit',
71 'wp_img_remove'
72 ] );
73 }
74 } );
75
76 editor.on( 'wptoolbar', function( event ) {
77 if ( event.element.nodeName === 'IMG' && ! isPlaceholder( event.element ) ) {
78 event.toolbar = toolbar;
79 }
80 } );
81
82 function isNonEditable( node ) {
83 var parent = editor.$( node ).parents( '[contenteditable]' );
84 return parent && parent.attr( 'contenteditable' ) === 'false';
85 }
86
87 // Safari on iOS fails to select images in contentEditoble mode on touch.
88 // Select them again.
89 if ( iOS ) {
90 editor.on( 'init', function() {
91 editor.on( 'touchstart', function( event ) {
92 if ( event.target.nodeName === 'IMG' && ! isNonEditable( event.target ) ) {
93 touchOnImage = true;
94 }
95 });
96
97 editor.dom.bind( editor.getDoc(), 'touchmove', function() {
98 touchOnImage = false;
99 });
100
101 editor.on( 'touchend', function( event ) {
102 if ( touchOnImage && event.target.nodeName === 'IMG' && ! isNonEditable( event.target ) ) {
103 var node = event.target;
104
105 touchOnImage = false;
106
107 window.setTimeout( function() {
108 editor.selection.select( node );
109 editor.nodeChanged();
110 }, 100 );
111 } else if ( toolbar ) {
112 toolbar.hide();
113 }
114 });
115 });
116 }
117
118 function parseShortcode( content ) {
119 return content.replace( /(?:<p>)?\[(?:wp_)?caption([^\]]+)\]([\s\S]+?)\[\/(?:wp_)?caption\](?:<\/p>)?/g, function( a, b, c ) {
120 var id, align, classes, caption, img, width;
121
122 id = b.match( /id=['"]([^'"]*)['"] ?/ );
123 if ( id ) {
124 b = b.replace( id[0], '' );
125 }
126
127 align = b.match( /align=['"]([^'"]*)['"] ?/ );
128 if ( align ) {
129 b = b.replace( align[0], '' );
130 }
131
132 classes = b.match( /class=['"]([^'"]*)['"] ?/ );
133 if ( classes ) {
134 b = b.replace( classes[0], '' );
135 }
136
137 width = b.match( /width=['"]([0-9]*)['"] ?/ );
138 if ( width ) {
139 b = b.replace( width[0], '' );
140 }
141
142 c = trim( c );
143 img = c.match( /((?:<a [^>]+>)?<img [^>]+>(?:<\/a>)?)([\s\S]*)/i );
144
145 if ( img && img[2] ) {
146 caption = trim( img[2] );
147 img = trim( img[1] );
148 } else {
149 // Old captions shortcode style.
150 caption = trim( b ).replace( /caption=['"]/, '' ).replace( /['"]$/, '' );
151 img = c;
152 }
153
154 id = ( id && id[1] ) ? id[1].replace( /[<>&]+/g, '' ) : '';
155 align = ( align && align[1] ) ? align[1] : 'alignnone';
156 classes = ( classes && classes[1] ) ? ' ' + classes[1].replace( /[<>&]+/g, '' ) : '';
157
158 if ( ! width && img ) {
159 width = img.match( /width=['"]([0-9]*)['"]/ );
160 }
161
162 if ( width && width[1] ) {
163 width = width[1];
164 }
165
166 if ( ! width || ! caption ) {
167 return c;
168 }
169
170 width = parseInt( width, 10 );
171 if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) {
172 width += 10;
173 }
174
175 return '<div class="mceTemp"><dl id="' + id + '" class="wp-caption ' + align + classes + '" style="width: ' + width + 'px">' +
176 '<dt class="wp-caption-dt">'+ img +'</dt><dd class="wp-caption-dd">'+ caption +'</dd></dl></div>';
177 });
178 }
179
180 function getShortcode( content ) {
181 return content.replace( /(?:<div [^>]+mceTemp[^>]+>)?\s*(<dl [^>]+wp-caption[^>]+>[\s\S]+?<\/dl>)\s*(?:<\/div>)?/g, function( all, dl ) {
182 var out = '';
183
184 if ( dl.indexOf('<img ') === -1 || dl.indexOf('</p>') !== -1 ) {
185 // Broken caption. The user managed to drag the image out or type in the wrapper div?
186 // Remove the <dl>, <dd> and <dt> and return the remaining text.
187 return dl.replace( /<d[ldt]( [^>]+)?>/g, '' ).replace( /<\/d[ldt]>/g, '' );
188 }
189
190 out = dl.replace( /\s*<dl ([^>]+)>\s*<dt [^>]+>([\s\S]+?)<\/dt>\s*<dd [^>]+>([\s\S]*?)<\/dd>\s*<\/dl>\s*/gi, function( a, b, c, caption ) {
191 var id, classes, align, width;
192
193 width = c.match( /width="([0-9]*)"/ );
194 width = ( width && width[1] ) ? width[1] : '';
195
196 classes = b.match( /class="([^"]*)"/ );
197 classes = ( classes && classes[1] ) ? classes[1] : '';
198 align = classes.match( /align[a-z]+/i ) || 'alignnone';
199
200 if ( ! width || ! caption ) {
201 if ( 'alignnone' !== align[0] ) {
202 c = c.replace( /><img/, ' class="' + align[0] + '"><img' );
203 }
204 return c;
205 }
206
207 id = b.match( /id="([^"]*)"/ );
208 id = ( id && id[1] ) ? id[1] : '';
209
210 classes = classes.replace( /wp-caption ?|align[a-z]+ ?/gi, '' );
211
212 if ( classes ) {
213 classes = ' class="' + classes + '"';
214 }
215
216 caption = caption.replace( /\r\n|\r/g, '\n' ).replace( /<[a-zA-Z0-9]+( [^<>]+)?>/g, function( a ) {
217 // No line breaks inside HTML tags.
218 return a.replace( /[\r\n\t]+/, ' ' );
219 });
220
221 // Convert remaining line breaks to <br>.
222 caption = caption.replace( /\s*\n\s*/g, '<br />' );
223
224 return '[caption id="' + id + '" align="' + align + '" width="' + width + '"' + classes + ']' + c + ' ' + caption + '[/caption]';
225 });
226
227 if ( out.indexOf('[caption') === -1 ) {
228 // The caption html seems broken, try to find the image that may be wrapped in a link
229 // and may be followed by <p> with the caption text.
230 out = dl.replace( /[\s\S]*?((?:<a [^>]+>)?<img [^>]+>(?:<\/a>)?)(<p>[\s\S]*<\/p>)?[\s\S]*/gi, '<p>$1</p>$2' );
231 }
232
233 return out;
234 });
235 }
236
237 function extractImageData( imageNode ) {
238 var classes, extraClasses, metadata, captionBlock, caption, link, width, height,
239 captionClassName = [],
240 dom = editor.dom,
241 isIntRegExp = /^\d+$/;
242
243 // Default attributes.
244 metadata = {
245 attachment_id: false,
246 size: 'custom',
247 caption: '',
248 align: 'none',
249 extraClasses: '',
250 link: false,
251 linkUrl: '',
252 linkClassName: '',
253 linkTargetBlank: false,
254 linkRel: '',
255 title: ''
256 };
257
258 metadata.url = dom.getAttrib( imageNode, 'src' );
259 metadata.alt = dom.getAttrib( imageNode, 'alt' );
260 metadata.title = dom.getAttrib( imageNode, 'title' );
261
262 width = dom.getAttrib( imageNode, 'width' );
263 height = dom.getAttrib( imageNode, 'height' );
264
265 if ( ! isIntRegExp.test( width ) || parseInt( width, 10 ) < 1 ) {
266 width = imageNode.naturalWidth || imageNode.width;
267 }
268
269 if ( ! isIntRegExp.test( height ) || parseInt( height, 10 ) < 1 ) {
270 height = imageNode.naturalHeight || imageNode.height;
271 }
272
273 metadata.customWidth = metadata.width = width;
274 metadata.customHeight = metadata.height = height;
275
276 classes = tinymce.explode( imageNode.className, ' ' );
277 extraClasses = [];
278
279 tinymce.each( classes, function( name ) {
280
281 if ( /^wp-image/.test( name ) ) {
282 metadata.attachment_id = parseInt( name.replace( 'wp-image-', '' ), 10 );
283 } else if ( /^align/.test( name ) ) {
284 metadata.align = name.replace( 'align', '' );
285 } else if ( /^size/.test( name ) ) {
286 metadata.size = name.replace( 'size-', '' );
287 } else {
288 extraClasses.push( name );
289 }
290
291 } );
292
293 metadata.extraClasses = extraClasses.join( ' ' );
294
295 // Extract caption.
296 captionBlock = dom.getParents( imageNode, '.wp-caption' );
297
298 if ( captionBlock.length ) {
299 captionBlock = captionBlock[0];
300
301 classes = captionBlock.className.split( ' ' );
302 tinymce.each( classes, function( name ) {
303 if ( /^align/.test( name ) ) {
304 metadata.align = name.replace( 'align', '' );
305 } else if ( name && name !== 'wp-caption' ) {
306 captionClassName.push( name );
307 }
308 } );
309
310 metadata.captionClassName = captionClassName.join( ' ' );
311
312 caption = dom.select( 'dd.wp-caption-dd', captionBlock );
313 if ( caption.length ) {
314 caption = caption[0];
315
316 metadata.caption = editor.serializer.serialize( caption )
317 .replace( /<br[^>]*>/g, '$&\n' ).replace( /^<p>/, '' ).replace( /<\/p>$/, '' );
318 }
319 }
320
321 // Extract linkTo.
322 if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' ) {
323 link = imageNode.parentNode;
324 metadata.linkUrl = dom.getAttrib( link, 'href' );
325 metadata.linkTargetBlank = dom.getAttrib( link, 'target' ) === '_blank' ? true : false;
326 metadata.linkRel = dom.getAttrib( link, 'rel' );
327 metadata.linkClassName = link.className;
328 }
329
330 return metadata;
331 }
332
333 function hasTextContent( node ) {
334 return node && !! ( node.textContent || node.innerText ).replace( /\ufeff/g, '' );
335 }
336
337 // Verify HTML in captions.
338 function verifyHTML( caption ) {
339 if ( ! caption || ( caption.indexOf( '<' ) === -1 && caption.indexOf( '>' ) === -1 ) ) {
340 return caption;
341 }
342
343 if ( ! serializer ) {
344 serializer = new tinymce.html.Serializer( {}, editor.schema );
345 }
346
347 return serializer.serialize( editor.parser.parse( caption, { forced_root_block: false } ) );
348 }
349
350 function updateImage( $imageNode, imageData ) {
351 var classes, className, node, html, parent, wrap, linkNode, imageNode,
352 captionNode, dd, dl, id, attrs, linkAttrs, width, height, align,
353 $imageNode, srcset, src,
354 dom = editor.dom;
355
356 if ( ! $imageNode || ! $imageNode.length ) {
357 return;
358 }
359
360 imageNode = $imageNode[0];
361 classes = tinymce.explode( imageData.extraClasses, ' ' );
362
363 if ( ! classes ) {
364 classes = [];
365 }
366
367 if ( ! imageData.caption ) {
368 classes.push( 'align' + imageData.align );
369 }
370
371 if ( imageData.attachment_id ) {
372 classes.push( 'wp-image-' + imageData.attachment_id );
373 if ( imageData.size && imageData.size !== 'custom' ) {
374 classes.push( 'size-' + imageData.size );
375 }
376 }
377
378 width = imageData.width;
379 height = imageData.height;
380
381 if ( imageData.size === 'custom' ) {
382 width = imageData.customWidth;
383 height = imageData.customHeight;
384 }
385
386 attrs = {
387 src: imageData.url,
388 width: width || null,
389 height: height || null,
390 title: imageData.title || null,
391 'class': classes.join( ' ' ) || null
392 };
393
394 dom.setAttribs( imageNode, attrs );
395
396 // Preserve empty alt attributes.
397 $imageNode.attr( 'alt', imageData.alt || '' );
398
399 linkAttrs = {
400 href: imageData.linkUrl,
401 rel: imageData.linkRel || null,
402 target: imageData.linkTargetBlank ? '_blank': null,
403 'class': imageData.linkClassName || null
404 };
405
406 if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) {
407 // Update or remove an existing link wrapped around the image.
408 if ( imageData.linkUrl ) {
409 dom.setAttribs( imageNode.parentNode, linkAttrs );
410 } else {
411 dom.remove( imageNode.parentNode, true );
412 }
413 } else if ( imageData.linkUrl ) {
414 if ( linkNode = dom.getParent( imageNode, 'a' ) ) {
415 // The image is inside a link together with other nodes,
416 // or is nested in another node, move it out.
417 dom.insertAfter( imageNode, linkNode );
418 }
419
420 // Add link wrapped around the image.
421 linkNode = dom.create( 'a', linkAttrs );
422 imageNode.parentNode.insertBefore( linkNode, imageNode );
423 linkNode.appendChild( imageNode );
424 }
425
426 captionNode = editor.dom.getParent( imageNode, '.mceTemp' );
427
428 if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) {
429 node = imageNode.parentNode;
430 } else {
431 node = imageNode;
432 }
433
434 if ( imageData.caption ) {
435 imageData.caption = verifyHTML( imageData.caption );
436
437 id = imageData.attachment_id ? 'attachment_' + imageData.attachment_id : null;
438 align = 'align' + ( imageData.align || 'none' );
439 className = 'wp-caption ' + align;
440
441 if ( imageData.captionClassName ) {
442 className += ' ' + imageData.captionClassName.replace( /[<>&]+/g, '' );
443 }
444
445 if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) {
446 width = parseInt( width, 10 );
447 width += 10;
448 }
449
450 if ( captionNode ) {
451 dl = dom.select( 'dl.wp-caption', captionNode );
452
453 if ( dl.length ) {
454 dom.setAttribs( dl, {
455 id: id,
456 'class': className,
457 style: 'width: ' + width + 'px'
458 } );
459 }
460
461 dd = dom.select( '.wp-caption-dd', captionNode );
462
463 if ( dd.length ) {
464 dom.setHTML( dd[0], imageData.caption );
465 }
466
467 } else {
468 id = id ? 'id="'+ id +'" ' : '';
469
470 // Should create a new function for generating the caption markup.
471 html = '<dl ' + id + 'class="' + className +'" style="width: '+ width +'px">' +
472 '<dt class="wp-caption-dt"></dt><dd class="wp-caption-dd">'+ imageData.caption +'</dd></dl>';
473
474 wrap = dom.create( 'div', { 'class': 'mceTemp' }, html );
475
476 if ( parent = dom.getParent( node, 'p' ) ) {
477 parent.parentNode.insertBefore( wrap, parent );
478 } else {
479 node.parentNode.insertBefore( wrap, node );
480 }
481
482 editor.$( wrap ).find( 'dt.wp-caption-dt' ).append( node );
483
484 if ( parent && dom.isEmpty( parent ) ) {
485 dom.remove( parent );
486 }
487 }
488 } else if ( captionNode ) {
489 // Remove the caption wrapper and place the image in new paragraph.
490 parent = dom.create( 'p' );
491 captionNode.parentNode.insertBefore( parent, captionNode );
492 parent.appendChild( node );
493 dom.remove( captionNode );
494 }
495
496 $imageNode = editor.$( imageNode );
497 srcset = $imageNode.attr( 'srcset' );
498 src = $imageNode.attr( 'src' );
499
500 // Remove srcset and sizes if the image file was edited or the image was replaced.
501 if ( srcset && src ) {
502 src = src.replace( /[?#].*/, '' );
503
504 if ( srcset.indexOf( src ) === -1 ) {
505 $imageNode.attr( 'srcset', null ).attr( 'sizes', null );
506 }
507 }
508
509 if ( wp.media.events ) {
510 wp.media.events.trigger( 'editor:image-update', {
511 editor: editor,
512 metadata: imageData,
513 image: imageNode
514 } );
515 }
516
517 editor.nodeChanged();
518 }
519
520 function editImage( img ) {
521 var frame, callback, metadata, imageNode;
522
523 if ( typeof wp === 'undefined' || ! wp.media ) {
524 editor.execCommand( 'mceImage' );
525 return;
526 }
527
528 metadata = extractImageData( img );
529
530 // Mark the image node so we can select it later.
531 editor.$( img ).attr( 'data-wp-editing', 1 );
532
533 // Manipulate the metadata by reference that is fed into the PostImage model used in the media modal.
534 wp.media.events.trigger( 'editor:image-edit', {
535 editor: editor,
536 metadata: metadata,
537 image: img
538 } );
539
540 frame = wp.media({
541 frame: 'image',
542 state: 'image-details',
543 metadata: metadata
544 } );
545
546 wp.media.events.trigger( 'editor:frame-create', { frame: frame } );
547
548 callback = function( imageData ) {
549 editor.undoManager.transact( function() {
550 updateImage( imageNode, imageData );
551 } );
552 frame.detach();
553 };
554
555 frame.state('image-details').on( 'update', callback );
556 frame.state('replace-image').on( 'replace', callback );
557 frame.on( 'close', function() {
558 editor.focus();
559 frame.detach();
560
561 /*
562 * `close` fires first...
563 * To be able to update the image node, we need to find it here,
564 * and use it in the callback.
565 */
566 imageNode = editor.$( 'img[data-wp-editing]' )
567 imageNode.removeAttr( 'data-wp-editing' );
568 });
569
570 frame.open();
571 }
572
573 function removeImage( node ) {
574 var wrap = editor.dom.getParent( node, 'div.mceTemp' );
575
576 if ( ! wrap && node.nodeName === 'IMG' ) {
577 wrap = editor.dom.getParent( node, 'a' );
578 }
579
580 if ( wrap ) {
581 if ( wrap.nextSibling ) {
582 editor.selection.select( wrap.nextSibling );
583 } else if ( wrap.previousSibling ) {
584 editor.selection.select( wrap.previousSibling );
585 } else {
586 editor.selection.select( wrap.parentNode );
587 }
588
589 editor.selection.collapse( true );
590 editor.dom.remove( wrap );
591 } else {
592 editor.dom.remove( node );
593 }
594
595 editor.nodeChanged();
596 editor.undoManager.add();
597 }
598
599 editor.on( 'init', function() {
600 var dom = editor.dom,
601 captionClass = editor.getParam( 'wpeditimage_html5_captions' ) ? 'html5-captions' : 'html4-captions';
602
603 dom.addClass( editor.getBody(), captionClass );
604
605 // Prevent IE11 from making dl.wp-caption resizable.
606 if ( tinymce.Env.ie && tinymce.Env.ie > 10 ) {
607 // The 'mscontrolselect' event is supported only in IE11+.
608 dom.bind( editor.getBody(), 'mscontrolselect', function( event ) {
609 if ( event.target.nodeName === 'IMG' && dom.getParent( event.target, '.wp-caption' ) ) {
610 // Hide the thick border with resize handles around dl.wp-caption.
611 editor.getBody().focus(); // :(
612 } else if ( event.target.nodeName === 'DL' && dom.hasClass( event.target, 'wp-caption' ) ) {
613 // Trigger the thick border with resize handles...
614 // This will make the caption text editable.
615 event.target.focus();
616 }
617 });
618 }
619 });
620
621 editor.on( 'ObjectResized', function( event ) {
622 var node = event.target;
623
624 if ( node.nodeName === 'IMG' ) {
625 editor.undoManager.transact( function() {
626 var parent, width,
627 dom = editor.dom;
628
629 node.className = node.className.replace( /\bsize-[^ ]+/, '' );
630
631 if ( parent = dom.getParent( node, '.wp-caption' ) ) {
632 width = event.width || dom.getAttrib( node, 'width' );
633
634 if ( width ) {
635 width = parseInt( width, 10 );
636
637 if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) {
638 width += 10;
639 }
640
641 dom.setStyle( parent, 'width', width + 'px' );
642 }
643 }
644 });
645 }
646 });
647
648 editor.on( 'pastePostProcess', function( event ) {
649 // Pasting in a caption node.
650 if ( editor.dom.getParent( editor.selection.getNode(), 'dd.wp-caption-dd' ) ) {
651 // Remove "non-block" elements that should not be in captions.
652 editor.$( 'img, audio, video, object, embed, iframe, script, style', event.node ).remove();
653
654 editor.$( '*', event.node ).each( function( i, node ) {
655 if ( editor.dom.isBlock( node ) ) {
656 // Insert <br> where the blocks used to be. Makes it look better after pasting in the caption.
657 if ( tinymce.trim( node.textContent || node.innerText ) ) {
658 editor.dom.insertAfter( editor.dom.create( 'br' ), node );
659 editor.dom.remove( node, true );
660 } else {
661 editor.dom.remove( node );
662 }
663 }
664 });
665
666 // Trim <br> tags.
667 editor.$( 'br', event.node ).each( function( i, node ) {
668 if ( ! node.nextSibling || node.nextSibling.nodeName === 'BR' ||
669 ! node.previousSibling || node.previousSibling.nodeName === 'BR' ) {
670
671 editor.dom.remove( node );
672 }
673 } );
674
675 // Pasted HTML is cleaned up for inserting in the caption.
676 pasteInCaption = true;
677 }
678 });
679
680 editor.on( 'BeforeExecCommand', function( event ) {
681 var node, p, DL, align, replacement, captionParent,
682 cmd = event.command,
683 dom = editor.dom;
684
685 if ( cmd === 'mceInsertContent' || cmd === 'Indent' || cmd === 'Outdent' ) {
686 node = editor.selection.getNode();
687 captionParent = dom.getParent( node, 'div.mceTemp' );
688
689 if ( captionParent ) {
690 if ( cmd === 'mceInsertContent' ) {
691 if ( pasteInCaption ) {
692 pasteInCaption = false;
693 /*
694 * We are in the caption element, and in 'paste' context,
695 * and the pasted HTML was cleaned up on 'pastePostProcess' above.
696 * Let it be pasted in the caption.
697 */
698 return;
699 }
700
701 /*
702 * The paste is somewhere else in the caption DL element.
703 * Prevent pasting in there as it will break the caption.
704 * Make new paragraph under the caption DL and move the caret there.
705 */
706 p = dom.create( 'p' );
707 dom.insertAfter( p, captionParent );
708 editor.selection.setCursorLocation( p, 0 );
709
710 /*
711 * If the image is selected and the user pastes "over" it,
712 * replace both the image and the caption elements with the pasted content.
713 * This matches the behavior when pasting over non-caption images.
714 */
715 if ( node.nodeName === 'IMG' ) {
716 editor.$( captionParent ).remove();
717 }
718
719 editor.nodeChanged();
720 } else {
721 // Clicking Indent or Outdent while an image with a caption is selected breaks the caption.
722 // See #38313.
723 event.preventDefault();
724 event.stopImmediatePropagation();
725 return false;
726 }
727 }
728 } else if ( cmd === 'JustifyLeft' || cmd === 'JustifyRight' || cmd === 'JustifyCenter' || cmd === 'wpAlignNone' ) {
729 node = editor.selection.getNode();
730 align = 'align' + cmd.slice( 7 ).toLowerCase();
731 DL = editor.dom.getParent( node, '.wp-caption' );
732
733 if ( node.nodeName !== 'IMG' && ! DL ) {
734 return;
735 }
736
737 node = DL || node;
738
739 if ( editor.dom.hasClass( node, align ) ) {
740 replacement = ' alignnone';
741 } else {
742 replacement = ' ' + align;
743 }
744
745 node.className = trim( node.className.replace( / ?align(left|center|right|none)/g, '' ) + replacement );
746
747 editor.nodeChanged();
748 event.preventDefault();
749
750 if ( toolbar ) {
751 toolbar.reposition();
752 }
753
754 editor.fire( 'ExecCommand', {
755 command: cmd,
756 ui: event.ui,
757 value: event.value
758 } );
759 }
760 });
761
762 editor.on( 'keydown', function( event ) {
763 var node, wrap, P, spacer,
764 selection = editor.selection,
765 keyCode = event.keyCode,
766 dom = editor.dom,
767 VK = tinymce.util.VK;
768
769 if ( keyCode === VK.ENTER ) {
770 // When pressing Enter inside a caption move the caret to a new parapraph under it.
771 node = selection.getNode();
772 wrap = dom.getParent( node, 'div.mceTemp' );
773
774 if ( wrap ) {
775 dom.events.cancel( event ); // Doesn't cancel all :(
776
777 // Remove any extra dt and dd cleated on pressing Enter...
778 tinymce.each( dom.select( 'dt, dd', wrap ), function( element ) {
779 if ( dom.isEmpty( element ) ) {
780 dom.remove( element );
781 }
782 });
783
784 spacer = tinymce.Env.ie && tinymce.Env.ie < 11 ? '' : '<br data-mce-bogus="1" />';
785 P = dom.create( 'p', null, spacer );
786
787 if ( node.nodeName === 'DD' ) {
788 dom.insertAfter( P, wrap );
789 } else {
790 wrap.parentNode.insertBefore( P, wrap );
791 }
792
793 editor.nodeChanged();
794 selection.setCursorLocation( P, 0 );
795 }
796 } else if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) {
797 node = selection.getNode();
798
799 if ( node.nodeName === 'DIV' && dom.hasClass( node, 'mceTemp' ) ) {
800 wrap = node;
801 } else if ( node.nodeName === 'IMG' || node.nodeName === 'DT' || node.nodeName === 'A' ) {
802 wrap = dom.getParent( node, 'div.mceTemp' );
803 }
804
805 if ( wrap ) {
806 dom.events.cancel( event );
807 removeImage( node );
808 return false;
809 }
810 }
811 });
812
813 /*
814 * After undo/redo FF seems to set the image height very slowly when it is set to 'auto' in the CSS.
815 * This causes image.getBoundingClientRect() to return wrong values and the resize handles are shown in wrong places.
816 * Collapse the selection to remove the resize handles.
817 */
818 if ( tinymce.Env.gecko ) {
819 editor.on( 'undo redo', function() {
820 if ( editor.selection.getNode().nodeName === 'IMG' ) {
821 editor.selection.collapse();
822 }
823 });
824 }
825
826 editor.wpSetImgCaption = function( content ) {
827 return parseShortcode( content );
828 };
829
830 editor.wpGetImgCaption = function( content ) {
831 return getShortcode( content );
832 };
833
834 editor.on( 'beforeGetContent', function( event ) {
835 if ( event.format !== 'raw' ) {
836 editor.$( 'img[id="__wp-temp-img-id"]' ).removeAttr( 'id' );
837 }
838 });
839
840 editor.on( 'BeforeSetContent', function( event ) {
841 if ( event.format !== 'raw' ) {
842 event.content = editor.wpSetImgCaption( event.content );
843 }
844 });
845
846 editor.on( 'PostProcess', function( event ) {
847 if ( event.get ) {
848 event.content = editor.wpGetImgCaption( event.content );
849 }
850 });
851
852 ( function() {
853 var wrap;
854
855 editor.on( 'dragstart', function() {
856 var node = editor.selection.getNode();
857
858 if ( node.nodeName === 'IMG' ) {
859 wrap = editor.dom.getParent( node, '.mceTemp' );
860
861 if ( ! wrap && node.parentNode.nodeName === 'A' && ! hasTextContent( node.parentNode ) ) {
862 wrap = node.parentNode;
863 }
864 }
865 } );
866
867 editor.on( 'drop', function( event ) {
868 var dom = editor.dom,
869 rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint( event.clientX, event.clientY, editor.getDoc() );
870
871 // Don't allow anything to be dropped in a captioned image.
872 if ( rng && dom.getParent( rng.startContainer, '.mceTemp' ) ) {
873 event.preventDefault();
874 } else if ( wrap ) {
875 event.preventDefault();
876
877 editor.undoManager.transact( function() {
878 if ( rng ) {
879 editor.selection.setRng( rng );
880 }
881
882 editor.selection.setNode( wrap );
883 dom.remove( wrap );
884 } );
885 }
886
887 wrap = null;
888 } );
889 } )();
890
891 // Add to editor.wp.
892 editor.wp = editor.wp || {};
893 editor.wp.isPlaceholder = isPlaceholder;
894
895 // Back-compat.
896 return {
897 _do_shcode: parseShortcode,
898 _get_shcode: getShortcode
899 };
900});
901
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1