Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/classic-editor/scripts/post.js

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + /**
2 + * @file Contains all dynamic functionality needed on post and term pages.
3 + *
4 + * @output wp-admin/js/post.js
5 + */
6 +
7 + /* global ajaxurl, wpAjax, postboxes, pagenow, tinymce, alert, deleteUserSetting, ClipboardJS */
8 + /* global theList:true, theExtraList:true, getUserSetting, setUserSetting, commentReply, commentsBox */
9 + /* global WPSetThumbnailHTML, wptitlehint */
10 +
11 + // Backward compatibility: prevent fatal errors.
12 + window.makeSlugeditClickable = window.editPermalink = function(){};
13 +
14 + // Make sure the wp object exists.
15 + window.wp = window.wp || {};
16 +
17 + ( function( $ ) {
18 + var titleHasFocus = false,
19 + __ = wp.i18n.__;
20 +
21 + /**
22 + * Control loading of comments on the post and term edit pages.
23 + *
24 + * @type {{st: number, get: commentsBox.get, load: commentsBox.load}}
25 + *
26 + * @namespace commentsBox
27 + */
28 + window.commentsBox = {
29 + // Comment offset to use when fetching new comments.
30 + st : 0,
31 +
32 + /**
33 + * Fetch comments using Ajax and display them in the box.
34 + *
35 + * @memberof commentsBox
36 + *
37 + * @param {number} total Total number of comments for this post.
38 + * @param {number} num Optional. Number of comments to fetch, defaults to 20.
39 + * @return {boolean} Always returns false.
40 + */
41 + get : function(total, num) {
42 + var st = this.st, data;
43 + if ( ! num )
44 + num = 20;
45 +
46 + this.st += num;
47 + this.total = total;
48 + $( '#commentsdiv .spinner' ).addClass( 'is-active' );
49 +
50 + data = {
51 + 'action' : 'get-comments',
52 + 'mode' : 'single',
53 + '_ajax_nonce' : $('#add_comment_nonce').val(),
54 + 'p' : $('#post_ID').val(),
55 + 'start' : st,
56 + 'number' : num
57 + };
58 +
59 + $.post(
60 + ajaxurl,
61 + data,
62 + function(r) {
63 + r = wpAjax.parseAjaxResponse(r);
64 + $('#commentsdiv .widefat').show();
65 + $( '#commentsdiv .spinner' ).removeClass( 'is-active' );
66 +
67 + if ( 'object' == typeof r && r.responses[0] ) {
68 + $('#the-comment-list').append( r.responses[0].data );
69 +
70 + theList = theExtraList = null;
71 + $( 'a[className*=\':\']' ).off();
72 +
73 + // If the offset is over the total number of comments we cannot fetch any more, so hide the button.
74 + if ( commentsBox.st > commentsBox.total )
75 + $('#show-comments').hide();
76 + else
77 + $('#show-comments').show().children('a').text( __( 'Show more comments' ) );
78 +
79 + return;
80 + } else if ( 1 == r ) {
81 + $('#show-comments').text( __( 'No more comments found.' ) );
82 + return;
83 + }
84 +
85 + $('#the-comment-list').append('<tr><td colspan="2">'+wpAjax.broken+'</td></tr>');
86 + }
87 + );
88 +
89 + return false;
90 + },
91 +
92 + /**
93 + * Load the next batch of comments.
94 + *
95 + * @memberof commentsBox
96 + *
97 + * @param {number} total Total number of comments to load.
98 + */
99 + load: function(total){
100 + this.st = jQuery('#the-comment-list tr.comment:visible').length;
101 + this.get(total);
102 + }
103 + };
104 +
105 + /**
106 + * Overwrite the content of the Featured Image postbox
107 + *
108 + * @param {string} html New HTML to be displayed in the content area of the postbox.
109 + *
110 + * @global
111 + */
112 + window.WPSetThumbnailHTML = function(html){
113 + $('.inside', '#postimagediv').html(html);
114 + };
115 +
116 + /**
117 + * Set the Image ID of the Featured Image
118 + *
119 + * @param {number} id The post_id of the image to use as Featured Image.
120 + *
121 + * @global
122 + */
123 + window.WPSetThumbnailID = function(id){
124 + var field = $('input[value="_thumbnail_id"]', '#list-table');
125 + if ( field.length > 0 ) {
126 + $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id);
127 + }
128 + };
129 +
130 + /**
131 + * Remove the Featured Image
132 + *
133 + * @param {string} nonce Nonce to use in the request.
134 + *
135 + * @global
136 + */
137 + window.WPRemoveThumbnail = function(nonce){
138 + $.post(
139 + ajaxurl, {
140 + action: 'set-post-thumbnail',
141 + post_id: $( '#post_ID' ).val(),
142 + thumbnail_id: -1,
143 + _ajax_nonce: nonce,
144 + cookie: encodeURIComponent( document.cookie )
145 + },
146 + /**
147 + * Handle server response
148 + *
149 + * @param {string} str Response, will be '0' when an error occurred otherwise contains link to add Featured Image.
150 + */
151 + function(str){
152 + if ( str == '0' ) {
153 + alert( __( 'Could not set that as the thumbnail image. Try a different attachment.' ) );
154 + } else {
155 + WPSetThumbnailHTML(str);
156 + }
157 + }
158 + );
159 + };
160 +
161 + /**
162 + * Heartbeat locks.
163 + *
164 + * Used to lock editing of an object by only one user at a time.
165 + *
166 + * When the user does not send a heartbeat in a heartbeat-time
167 + * the user is no longer editing and another user can start editing.
168 + */
169 + $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) {
170 + var lock = $('#active_post_lock').val(),
171 + post_id = $('#post_ID').val(),
172 + send = {};
173 +
174 + if ( ! post_id || ! $('#post-lock-dialog').length )
175 + return;
176 +
177 + send.post_id = post_id;
178 +
179 + if ( lock )
180 + send.lock = lock;
181 +
182 + data['wp-refresh-post-lock'] = send;
183 +
184 + }).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
185 + // Post locks: update the lock string or show the dialog if somebody has taken over editing.
186 + var received, wrap, avatar;
187 +
188 + if ( data['wp-refresh-post-lock'] ) {
189 + received = data['wp-refresh-post-lock'];
190 +
191 + if ( received.lock_error ) {
192 + // Show "editing taken over" message.
193 + wrap = $('#post-lock-dialog');
194 +
195 + if ( wrap.length && ! wrap.is(':visible') ) {
196 + if ( wp.autosave ) {
197 + // Save the latest changes and disable.
198 + $(document).one( 'heartbeat-tick', function() {
199 + wp.autosave.server.suspend();
200 + wrap.removeClass('saving').addClass('saved');
201 + $(window).off( 'beforeunload.edit-post' );
202 + });
203 +
204 + wrap.addClass('saving');
205 + wp.autosave.server.triggerSave();
206 + }
207 +
208 + if ( received.lock_error.avatar_src ) {
209 + avatar = $( '<img />', {
210 + 'class': 'avatar avatar-64 photo',
211 + width: 64,
212 + height: 64,
213 + alt: '',
214 + src: received.lock_error.avatar_src,
215 + srcset: received.lock_error.avatar_src_2x ?
216 + received.lock_error.avatar_src_2x + ' 2x' :
217 + undefined
218 + } );
219 + wrap.find('div.post-locked-avatar').empty().append( avatar );
220 + }
221 +
222 + wrap.show().find('.currently-editing').text( received.lock_error.text );
223 + wrap.find('.wp-tab-first').trigger( 'focus' );
224 + }
225 + } else if ( received.new_lock ) {
226 + $('#active_post_lock').val( received.new_lock );
227 + }
228 + }
229 + }).on( 'before-autosave.update-post-slug', function() {
230 + titleHasFocus = document.activeElement && document.activeElement.id === 'title';
231 + }).on( 'after-autosave.update-post-slug', function() {
232 +
233 + /*
234 + * Create slug area only if not already there
235 + * and the title field was not focused (user was not typing a title) when autosave ran.
236 + */
237 + if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) {
238 + $.post( ajaxurl, {
239 + action: 'sample-permalink',
240 + post_id: $('#post_ID').val(),
241 + new_title: $('#title').val(),
242 + samplepermalinknonce: $('#samplepermalinknonce').val()
243 + },
244 + function( data ) {
245 + if ( data != '-1' ) {
246 + $('#edit-slug-box').html(data);
247 + }
248 + }
249 + );
250 + }
251 + });
252 +
253 + }(jQuery));
254 +
255 + /**
256 + * Heartbeat refresh nonces.
257 + */
258 + (function($) {
259 + var check, timeout;
260 +
261 + /**
262 + * Only allow to check for nonce refresh every 30 seconds.
263 + */
264 + function schedule() {
265 + check = false;
266 + window.clearTimeout( timeout );
267 + timeout = window.setTimeout( function(){ check = true; }, 300000 );
268 + }
269 +
270 + $( function() {
271 + schedule();
272 + }).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
273 + var post_id,
274 + $authCheck = $('#wp-auth-check-wrap');
275 +
276 + if ( check || ( $authCheck.length && ! $authCheck.hasClass( 'hidden' ) ) ) {
277 + if ( ( post_id = $('#post_ID').val() ) && $('#_wpnonce').val() ) {
278 + data['wp-refresh-post-nonces'] = {
279 + post_id: post_id
280 + };
281 + }
282 + }
283 + }).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
284 + var nonces = data['wp-refresh-post-nonces'];
285 +
286 + if ( nonces ) {
287 + schedule();
288 +
289 + if ( nonces.replace ) {
290 + $.each( nonces.replace, function( selector, value ) {
291 + $( '#' + selector ).val( value );
292 + });
293 + }
294 +
295 + if ( nonces.heartbeatNonce )
296 + window.heartbeatSettings.nonce = nonces.heartbeatNonce;
297 + }
298 + });
299 + }(jQuery));
300 +
301 + /**
302 + * All post and postbox controls and functionality.
303 + */
304 + jQuery( function($) {
305 + var stamp, visibility, $submitButtons, updateVisibility, updateText,
306 + $textarea = $('#content'),
307 + $document = $(document),
308 + postId = $('#post_ID').val() || 0,
309 + $submitpost = $('#submitpost'),
310 + releaseLock = true,
311 + $postVisibilitySelect = $('#post-visibility-select'),
312 + $timestampdiv = $('#timestampdiv'),
313 + $postStatusSelect = $('#post-status-select'),
314 + isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false,
315 + copyAttachmentURLClipboard = new ClipboardJS( '.copy-attachment-url.edit-media' ),
316 + copyAttachmentURLSuccessTimeout,
317 + __ = wp.i18n.__, _x = wp.i18n._x;
318 +
319 + postboxes.add_postbox_toggles(pagenow);
320 +
321 + /*
322 + * Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post,
323 + * and the first post is still being edited, clicking Preview there will use this window to show the preview.
324 + */
325 + window.name = '';
326 +
327 + // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item.
328 + $('#post-lock-dialog .notification-dialog').on( 'keydown', function(e) {
329 + // Don't do anything when [Tab] is pressed.
330 + if ( e.which != 9 )
331 + return;
332 +
333 + var target = $(e.target);
334 +
335 + // [Shift] + [Tab] on first tab cycles back to last tab.
336 + if ( target.hasClass('wp-tab-first') && e.shiftKey ) {
337 + $(this).find('.wp-tab-last').trigger( 'focus' );
338 + e.preventDefault();
339 + // [Tab] on last tab cycles back to first tab.
340 + } else if ( target.hasClass('wp-tab-last') && ! e.shiftKey ) {
341 + $(this).find('.wp-tab-first').trigger( 'focus' );
342 + e.preventDefault();
343 + }
344 + }).filter(':visible').find('.wp-tab-first').trigger( 'focus' );
345 +
346 + // Set the heartbeat interval to 10 seconds if post lock dialogs are enabled.
347 + if ( wp.heartbeat && $('#post-lock-dialog').length ) {
348 + wp.heartbeat.interval( 10 );
349 + }
350 +
351 + // The form is being submitted by the user.
352 + $submitButtons = $submitpost.find( ':submit, a.submitdelete, #post-preview' ).on( 'click.edit-post', function( event ) {
353 + var $button = $(this);
354 +
355 + if ( $button.hasClass('disabled') ) {
356 + event.preventDefault();
357 + return;
358 + }
359 +
360 + if ( $button.hasClass('submitdelete') || $button.is( '#post-preview' ) ) {
361 + return;
362 + }
363 +
364 + // The form submission can be blocked from JS or by using HTML 5.0 validation on some fields.
365 + // Run this only on an actual 'submit'.
366 + $('form#post').off( 'submit.edit-post' ).on( 'submit.edit-post', function( event ) {
367 + if ( event.isDefaultPrevented() ) {
368 + return;
369 + }
370 +
371 + // Stop auto save.
372 + if ( wp.autosave ) {
373 + wp.autosave.server.suspend();
374 + }
375 +
376 + if ( typeof commentReply !== 'undefined' ) {
377 + /*
378 + * Warn the user they have an unsaved comment before submitting
379 + * the post data for update.
380 + */
381 + if ( ! commentReply.discardCommentChanges() ) {
382 + return false;
383 + }
384 +
385 + /*
386 + * Close the comment edit/reply form if open to stop the form
387 + * action from interfering with the post's form action.
388 + */
389 + commentReply.close();
390 + }
391 +
392 + releaseLock = false;
393 + $(window).off( 'beforeunload.edit-post' );
394 +
395 + $submitButtons.addClass( 'disabled' );
396 +
397 + if ( $button.attr('id') === 'publish' ) {
398 + $submitpost.find( '#major-publishing-actions .spinner' ).addClass( 'is-active' );
399 + } else {
400 + $submitpost.find( '#minor-publishing .spinner' ).addClass( 'is-active' );
401 + }
402 + });
403 + });
404 +
405 + // Submit the form saving a draft or an autosave, and show a preview in a new tab.
406 + $('#post-preview').on( 'click.post-preview', function( event ) {
407 + var $this = $(this),
408 + $form = $('form#post'),
409 + $previewField = $('input#wp-preview'),
410 + target = $this.attr('target') || 'wp-preview',
411 + ua = navigator.userAgent.toLowerCase();
412 +
413 + event.preventDefault();
414 +
415 + if ( $this.hasClass('disabled') ) {
416 + return;
417 + }
418 +
419 + if ( wp.autosave ) {
420 + wp.autosave.server.tempBlockSave();
421 + }
422 +
423 + $previewField.val('dopreview');
424 + $form.attr( 'target', target ).trigger( 'submit' ).attr( 'target', '' );
425 +
426 + // Workaround for WebKit bug preventing a form submitting twice to the same action.
427 + // https://bugs.webkit.org/show_bug.cgi?id=28633
428 + if ( ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1 ) {
429 + $form.attr( 'action', function( index, value ) {
430 + return value + '?t=' + ( new Date() ).getTime();
431 + });
432 + }
433 +
434 + $previewField.val('');
435 + });
436 +
437 + // Auto save new posts after a title is typed.
438 + if ( $( '#auto_draft' ).val() ) {
439 + $( '#title' ).on( 'blur', function() {
440 + var cancel;
441 +
442 + if ( ! this.value || $('#edit-slug-box > *').length ) {
443 + return;
444 + }
445 +
446 + // Cancel the auto save when the blur was triggered by the user submitting the form.
447 + $('form#post').one( 'submit', function() {
448 + cancel = true;
449 + });
450 +
451 + window.setTimeout( function() {
452 + if ( ! cancel && wp.autosave ) {
453 + wp.autosave.server.triggerSave();
454 + }
455 + }, 200 );
456 + });
457 + }
458 +
459 + $document.on( 'autosave-disable-buttons.edit-post', function() {
460 + $submitButtons.addClass( 'disabled' );
461 + }).on( 'autosave-enable-buttons.edit-post', function() {
462 + if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) {
463 + $submitButtons.removeClass( 'disabled' );
464 + }
465 + }).on( 'before-autosave.edit-post', function() {
466 + $( '.autosave-message' ).text( __( 'Saving Draft…' ) );
467 + }).on( 'after-autosave.edit-post', function( event, data ) {
468 + $( '.autosave-message' ).text( data.message );
469 +
470 + if ( $( document.body ).hasClass( 'post-new-php' ) ) {
471 + $( '.submitbox .submitdelete' ).show();
472 + }
473 + });
474 +
475 + /*
476 + * When the user is trying to load another page, or reloads current page
477 + * show a confirmation dialog when there are unsaved changes.
478 + */
479 + $( window ).on( 'beforeunload.edit-post', function( event ) {
480 + var editor = window.tinymce && window.tinymce.get( 'content' );
481 + var changed = false;
482 +
483 + if ( wp.autosave ) {
484 + changed = wp.autosave.server.postChanged();
485 + } else if ( editor ) {
486 + changed = ( ! editor.isHidden() && editor.isDirty() );
487 + }
488 +
489 + if ( changed ) {
490 + event.preventDefault();
491 + // The return string is needed for browser compat.
492 + // See https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event.
493 + return __( 'The changes you made will be lost if you navigate away from this page.' );
494 + }
495 + }).on( 'pagehide.edit-post', function( event ) {
496 + if ( ! releaseLock ) {
497 + return;
498 + }
499 +
500 + /*
501 + * Unload is triggered (by hand) on removing the Thickbox iframe.
502 + * Make sure we process only the main document unload.
503 + */
504 + if ( event.target && event.target.nodeName != '#document' ) {
505 + return;
506 + }
507 +
508 + var postID = $('#post_ID').val();
509 + var postLock = $('#active_post_lock').val();
510 +
511 + if ( ! postID || ! postLock ) {
512 + return;
513 + }
514 +
515 + var data = {
516 + action: 'wp-remove-post-lock',
517 + _wpnonce: $('#_wpnonce').val(),
518 + post_ID: postID,
519 + active_post_lock: postLock
520 + };
521 +
522 + if ( window.FormData && window.navigator.sendBeacon ) {
523 + var formData = new window.FormData();
524 +
525 + $.each( data, function( key, value ) {
526 + formData.append( key, value );
527 + });
528 +
529 + if ( window.navigator.sendBeacon( ajaxurl, formData ) ) {
530 + return;
531 + }
532 + }
533 +
534 + // Fall back to a synchronous POST request.
535 + // See https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
536 + $.post({
537 + async: false,
538 + data: data,
539 + url: ajaxurl
540 + });
541 + });
542 +
543 + // Multiple taxonomies.
544 + if ( $('#tagsdiv-post_tag').length ) {
545 + window.tagBox && window.tagBox.init();
546 + } else {
547 + $('.meta-box-sortables').children('div.postbox').each(function(){
548 + if ( this.id.indexOf('tagsdiv-') === 0 ) {
549 + window.tagBox && window.tagBox.init();
550 + return false;
551 + }
552 + });
553 + }
554 +
555 + // Handle categories.
556 + $('.categorydiv').each( function(){
557 + var this_id = $(this).attr('id'), catAddBefore, catAddAfter, taxonomyParts, taxonomy, settingName;
558 +
559 + taxonomyParts = this_id.split('-');
560 + taxonomyParts.shift();
561 + taxonomy = taxonomyParts.join('-');
562 + settingName = taxonomy + '_tab';
563 +
564 + if ( taxonomy == 'category' ) {
565 + settingName = 'cats';
566 + }
567 +
568 + // @todo Move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js.
569 + $('a', '#' + taxonomy + '-tabs').on( 'click', function( e ) {
570 + e.preventDefault();
571 + var t = $(this).attr('href');
572 + $(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
573 + $('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide();
574 + $(t).show();
575 + if ( '#' + taxonomy + '-all' == t ) {
576 + deleteUserSetting( settingName );
577 + } else {
578 + setUserSetting( settingName, 'pop' );
579 + }
580 + });
581 +
582 + if ( getUserSetting( settingName ) )
583 + $('a[href="#' + taxonomy + '-pop"]', '#' + taxonomy + '-tabs').trigger( 'click' );
584 +
585 + // Add category button controls.
586 + $('#new' + taxonomy).one( 'focus', function() {
587 + $( this ).val( '' ).removeClass( 'form-input-tip' );
588 + });
589 +
590 + // On [Enter] submit the taxonomy.
591 + $('#new' + taxonomy).on( 'keypress', function(event){
592 + if( 13 === event.keyCode ) {
593 + event.preventDefault();
594 + $('#' + taxonomy + '-add-submit').trigger( 'click' );
595 + }
596 + });
597 +
598 + // After submitting a new taxonomy, re-focus the input field.
599 + $('#' + taxonomy + '-add-submit').on( 'click', function() {
600 + $('#new' + taxonomy).trigger( 'focus' );
601 + });
602 +
603 + /**
604 + * Before adding a new taxonomy, disable submit button.
605 + *
606 + * @param {Object} s Taxonomy object which will be added.
607 + *
608 + * @return {Object}
609 + */
610 + catAddBefore = function( s ) {
611 + if ( !$('#new'+taxonomy).val() ) {
612 + return false;
613 + }
614 +
615 + s.data += '&' + $( ':checked', '#'+taxonomy+'checklist' ).serialize();
616 + $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', true );
617 + return s;
618 + };
619 +
620 + /**
621 + * Re-enable submit button after a taxonomy has been added.
622 + *
623 + * Re-enable submit button.
624 + * If the taxonomy has a parent place the taxonomy underneath the parent.
625 + *
626 + * @param {Object} r Response.
627 + * @param {Object} s Taxonomy data.
628 + *
629 + * @return {void}
630 + */
631 + catAddAfter = function( r, s ) {
632 + var sup, drop = $('#new'+taxonomy+'_parent');
633 +
634 + $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', false );
635 + if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) {
636 + drop.before(sup);
637 + drop.remove();
638 + }
639 + };
640 +
641 + $('#' + taxonomy + 'checklist').wpList({
642 + alt: '',
643 + response: taxonomy + '-ajax-response',
644 + addBefore: catAddBefore,
645 + addAfter: catAddAfter
646 + });
647 +
648 + // Add new taxonomy button toggles input form visibility.
649 + $('#' + taxonomy + '-add-toggle').on( 'click', function( e ) {
650 + e.preventDefault();
651 + $('#' + taxonomy + '-adder').toggleClass( 'wp-hidden-children' );
652 + $('a[href="#' + taxonomy + '-all"]', '#' + taxonomy + '-tabs').trigger( 'click' );
653 + $('#new'+taxonomy).trigger( 'focus' );
654 + });
655 +
656 + // Sync checked items between "All {taxonomy}" and "Most used" lists.
657 + $('#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop').on(
658 + 'click',
659 + 'li.popular-category > label input[type="checkbox"]',
660 + function() {
661 + var t = $(this), c = t.is(':checked'), id = t.val();
662 + if ( id && t.parents('#taxonomy-'+taxonomy).length ) {
663 + // Fixed for ticket #62504. See https://core.trac.wordpress.org/ticket/62504.
664 + $('input#in-' + taxonomy + '-' + id + ', input[id^="in-' + taxonomy + '-' + id + '-"]').prop('checked', c);
665 + $('input#in-popular-' + taxonomy + '-' + id).prop('checked', c);
666 + }
667 + }
668 + );
669 +
670 + }); // End cats.
671 +
672 + // Custom Fields postbox.
673 + if ( $('#postcustom').length ) {
674 + $( '#the-list' ).wpList( {
675 + /**
676 + * Add current post_ID to request to fetch custom fields
677 + *
678 + * @ignore
679 + *
680 + * @param {Object} s Request object.
681 + *
682 + * @return {Object} Data modified with post_ID attached.
683 + */
684 + addBefore: function( s ) {
685 + s.data += '&post_id=' + $('#post_ID').val();
686 + return s;
687 + },
688 + /**
689 + * Show the listing of custom fields after fetching.
690 + *
691 + * @ignore
692 + */
693 + addAfter: function() {
694 + $('table#list-table').show();
695 + }
696 + });
697 + }
698 +
699 + /*
700 + * Publish Post box (#submitdiv)
701 + */
702 + if ( $('#submitdiv').length ) {
703 + stamp = $('#timestamp').html();
704 + visibility = $('#post-visibility-display').html();
705 +
706 + /**
707 + * When the visibility of a post changes sub-options should be shown or hidden.
708 + *
709 + * @ignore
710 + *
711 + * @return {void}
712 + */
713 + updateVisibility = function() {
714 + // Show sticky for public posts.
715 + if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) {
716 + $('#sticky').prop('checked', false);
717 + $('#sticky-span').hide();
718 + } else {
719 + $('#sticky-span').show();
720 + }
721 +
722 + // Show password input field for password protected post.
723 + if ( $postVisibilitySelect.find('input:radio:checked').val() != 'password' ) {
724 + $('#password-span').hide();
725 + } else {
726 + $('#password-span').show();
727 + }
728 + };
729 +
730 + /**
731 + * Make sure all labels represent the current settings.
732 + *
733 + * @ignore
734 + *
735 + * @return {boolean} False when an invalid timestamp has been selected, otherwise True.
736 + */
737 + updateText = function() {
738 +
739 + if ( ! $timestampdiv.length )
740 + return true;
741 +
742 + var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'),
743 + optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(),
744 + mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val();
745 +
746 + attemptedDate = new Date( aa, mm - 1, jj, hh, mn );
747 + originalDate = new Date(
748 + $('#hidden_aa').val(),
749 + $('#hidden_mm').val() -1,
750 + $('#hidden_jj').val(),
751 + $('#hidden_hh').val(),
752 + $('#hidden_mn').val()
753 + );
754 + currentDate = new Date(
755 + $('#cur_aa').val(),
756 + $('#cur_mm').val() -1,
757 + $('#cur_jj').val(),
758 + $('#cur_hh').val(),
759 + $('#cur_mn').val()
760 + );
761 +
762 + // Catch unexpected date problems.
763 + if (
764 + attemptedDate.getFullYear() != aa ||
765 + (1 + attemptedDate.getMonth()) != mm ||
766 + attemptedDate.getDate() != jj ||
767 + attemptedDate.getMinutes() != mn
768 + ) {
769 + $timestampdiv.find('.timestamp-wrap').addClass('form-invalid');
770 + return false;
771 + } else {
772 + $timestampdiv.find('.timestamp-wrap').removeClass('form-invalid');
773 + }
774 +
775 + // Determine what the publish should be depending on the date and post status.
776 + if ( attemptedDate > currentDate ) {
777 + publishOn = __( 'Schedule for:' );
778 + $('#publish').val( _x( 'Schedule', 'post action/button label' ) );
779 + } else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' ) {
780 + publishOn = __( 'Publish on:' );
781 + $('#publish').val( __( 'Publish' ) );
782 + } else {
783 + publishOn = __( 'Published on:' );
784 + $('#publish').val( __( 'Update' ) );
785 + }
786 +
787 + // If the date is the same, set it to trigger update events.
788 + if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) {
789 + // Re-set to the current value.
790 + $('#timestamp').html(stamp);
791 + } else {
792 + $('#timestamp').html(
793 + '\n' + publishOn + ' <b>' +
794 + // translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute.
795 + __( '%1$s %2$s, %3$s at %4$s:%5$s' )
796 + .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) )
797 + .replace( '%2$s', parseInt( jj, 10 ) )
798 + .replace( '%3$s', aa )
799 + .replace( '%4$s', ( '00' + hh ).slice( -2 ) )
800 + .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) +
801 + '</b> '
802 + );
803 + }
804 +
805 + // Add "privately published" to post status when applies.
806 + if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) {
807 + $('#publish').val( __( 'Update' ) );
808 + if ( 0 === optPublish.length ) {
809 + postStatus.append('<option value="publish">' + __( 'Privately Published' ) + '</option>');
810 + } else {
811 + optPublish.html( __( 'Privately Published' ) );
812 + }
813 + $('option[value="publish"]', postStatus).prop('selected', true);
814 + $('#misc-publishing-actions .edit-post-status').hide();
815 + } else {
816 + if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) {
817 + if ( optPublish.length ) {
818 + optPublish.remove();
819 + postStatus.val($('#hidden_post_status').val());
820 + }
821 + } else {
822 + optPublish.html( __( 'Published' ) );
823 + }
824 + if ( postStatus.is(':hidden') )
825 + $('#misc-publishing-actions .edit-post-status').show();
826 + }
827 +
828 + // Update "Status:" to currently selected status.
829 + $('#post-status-display').text(
830 + // Remove any potential tags from post status text.
831 + wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() )
832 + );
833 +
834 + // Show or hide the "Save Draft" button.
835 + if (
836 + $('option:selected', postStatus).val() == 'private' ||
837 + $('option:selected', postStatus).val() == 'publish'
838 + ) {
839 + $('#save-post').hide();
840 + } else {
841 + $('#save-post').show();
842 + if ( $('option:selected', postStatus).val() == 'pending' ) {
843 + $('#save-post').show().val( __( 'Save as Pending' ) );
844 + } else {
845 + $('#save-post').show().val( __( 'Save Draft' ) );
846 + }
847 + }
848 + return true;
849 + };
850 +
851 + // Show the visibility options and hide the toggle button when opened.
852 + $( '#visibility .edit-visibility').on( 'click', function( e ) {
853 + e.preventDefault();
854 + if ( $postVisibilitySelect.is(':hidden') ) {
855 + updateVisibility();
856 + $postVisibilitySelect.slideDown( 'fast', function() {
857 + $postVisibilitySelect.find( 'input[type="radio"]' ).first().trigger( 'focus' );
858 + } );
859 + $(this).hide();
860 + }
861 + });
862 +
863 + // Cancel visibility selection area and hide it from view.
864 + $postVisibilitySelect.find('.cancel-post-visibility').on( 'click', function( event ) {
865 + $postVisibilitySelect.slideUp('fast');
866 + $('#visibility-radio-' + $('#hidden-post-visibility').val()).prop('checked', true);
867 + $('#post_password').val($('#hidden-post-password').val());
868 + $('#sticky').prop('checked', $('#hidden-post-sticky').prop('checked'));
869 + $('#post-visibility-display').html(visibility);
870 + $('#visibility .edit-visibility').show().trigger( 'focus' );
871 + updateText();
872 + event.preventDefault();
873 + });
874 +
875 + // Set the selected visibility as current.
876 + $postVisibilitySelect.find('.save-post-visibility').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels.
877 + var visibilityLabel = '', selectedVisibility = $postVisibilitySelect.find('input:radio:checked').val();
878 +
879 + $postVisibilitySelect.slideUp('fast');
880 + $('#visibility .edit-visibility').show().trigger( 'focus' );
881 + updateText();
882 +
883 + if ( 'public' !== selectedVisibility ) {
884 + $('#sticky').prop('checked', false);
885 + }
886 +
887 + switch ( selectedVisibility ) {
888 + case 'public':
889 + visibilityLabel = $( '#sticky' ).prop( 'checked' ) ? __( 'Public, Sticky' ) : __( 'Public' );
890 + break;
891 + case 'private':
892 + visibilityLabel = __( 'Private' );
893 + break;
894 + case 'password':
895 + visibilityLabel = __( 'Password Protected' );
896 + break;
897 + }
898 +
899 + $('#post-visibility-display').text( visibilityLabel );
900 + event.preventDefault();
901 + });
902 +
903 + // When the selection changes, update labels.
904 + $postVisibilitySelect.find('input:radio').on( 'change', function() {
905 + updateVisibility();
906 + });
907 +
908 + // Edit publish time click.
909 + $timestampdiv.siblings('a.edit-timestamp').on( 'click', function( event ) {
910 + if ( $timestampdiv.is( ':hidden' ) ) {
911 + $timestampdiv.slideDown( 'fast', function() {
912 + $( 'input, select', $timestampdiv.find( '.timestamp-wrap' ) ).first().trigger( 'focus' );
913 + } );
914 + $(this).hide();
915 + }
916 + event.preventDefault();
917 + });
918 +
919 + // Cancel editing the publish time and hide the settings.
920 + $timestampdiv.find('.cancel-timestamp').on( 'click', function( event ) {
921 + $timestampdiv.slideUp('fast').siblings('a.edit-timestamp').show().trigger( 'focus' );
922 + $('#mm').val($('#hidden_mm').val());
923 + $('#jj').val($('#hidden_jj').val());
924 + $('#aa').val($('#hidden_aa').val());
925 + $('#hh').val($('#hidden_hh').val());
926 + $('#mn').val($('#hidden_mn').val());
927 + updateText();
928 + event.preventDefault();
929 + });
930 +
931 + // Save the changed timestamp.
932 + $timestampdiv.find('.save-timestamp').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels.
933 + if ( updateText() ) {
934 + $timestampdiv.slideUp('fast');
935 + $timestampdiv.siblings('a.edit-timestamp').show().trigger( 'focus' );
936 + }
937 + event.preventDefault();
938 + });
939 +
940 + // Cancel submit when an invalid timestamp has been selected.
941 + $('#post').on( 'submit', function( event ) {
942 + if ( ! updateText() ) {
943 + event.preventDefault();
944 + $timestampdiv.show();
945 +
946 + if ( wp.autosave ) {
947 + wp.autosave.enableButtons();
948 + }
949 +
950 + $( '#publishing-action .spinner' ).removeClass( 'is-active' );
951 + }
952 + });
953 +
954 + // Post Status edit click.
955 + $postStatusSelect.siblings('a.edit-post-status').on( 'click', function( event ) {
956 + if ( $postStatusSelect.is( ':hidden' ) ) {
957 + $postStatusSelect.slideDown( 'fast', function() {
958 + $postStatusSelect.find('select').trigger( 'focus' );
959 + } );
960 + $(this).hide();
961 + }
962 + event.preventDefault();
963 + });
964 +
965 + // Save the Post Status changes and hide the options.
966 + $postStatusSelect.find('.save-post-status').on( 'click', function( event ) {
967 + $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' );
968 + updateText();
969 + event.preventDefault();
970 + });
971 +
972 + // Cancel Post Status editing and hide the options.
973 + $postStatusSelect.find('.cancel-post-status').on( 'click', function( event ) {
974 + $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' );
975 + $('#post_status').val( $('#hidden_post_status').val() );
976 + updateText();
977 + event.preventDefault();
978 + });
979 + }
980 +
981 + /**
982 + * Handle the editing of the post_name. Create the required HTML elements and
983 + * update the changes via Ajax.
984 + *
985 + * @global
986 + *
987 + * @return {void}
988 + */
989 + function editPermalink() {
990 + var i, slug_value, slug_label,
991 + $el, revert_e,
992 + c = 0,
993 + real_slug = $('#post_name'),
994 + revert_slug = real_slug.val(),
995 + permalink = $( '#sample-permalink' ),
996 + permalinkOrig = permalink.html(),
997 + permalinkInner = $( '#sample-permalink a' ).html(),
998 + buttons = $('#edit-slug-buttons'),
999 + buttonsOrig = buttons.html(),
1000 + full = $('#editable-post-name-full');
1001 +
1002 + // Deal with Twemoji in the post-name.
1003 + full.find( 'img' ).replaceWith( function() { return this.alt; } );
1004 + full = full.html();
1005 +
1006 + permalink.html( permalinkInner );
1007 +
1008 + // Save current content to revert to when cancelling.
1009 + $el = $( '#editable-post-name' );
1010 + revert_e = $el.html();
1011 +
1012 + buttons.html(
1013 + '<button type="button" class="save button button-small">' + __( 'OK' ) + '</button> ' +
1014 + '<button type="button" class="cancel button-link">' + __( 'Cancel' ) + '</button>'
1015 + );
1016 +
1017 + // Save permalink changes.
1018 + buttons.children( '.save' ).on( 'click', function() {
1019 + var new_slug = $el.children( 'input' ).val();
1020 +
1021 + if ( new_slug == $('#editable-post-name-full').text() ) {
1022 + buttons.children('.cancel').trigger( 'click' );
1023 + return;
1024 + }
1025 +
1026 + $.post(
1027 + ajaxurl,
1028 + {
1029 + action: 'sample-permalink',
1030 + post_id: postId,
1031 + new_slug: new_slug,
1032 + new_title: $('#title').val(),
1033 + samplepermalinknonce: $('#samplepermalinknonce').val()
1034 + },
1035 + function(data) {
1036 + var box = $('#edit-slug-box');
1037 + box.html(data);
1038 + if (box.hasClass('hidden')) {
1039 + box.fadeIn('fast', function () {
1040 + box.removeClass('hidden');
1041 + });
1042 + }
1043 +
1044 + buttons.html(buttonsOrig);
1045 + permalink.html(permalinkOrig);
1046 + real_slug.val(new_slug);
1047 + $( '.edit-slug' ).trigger( 'focus' );
1048 + wp.a11y.speak( __( 'Permalink saved' ) );
1049 + }
1050 + );
1051 + });
1052 +
1053 + // Cancel editing of permalink.
1054 + buttons.children( '.cancel' ).on( 'click', function() {
1055 + $('#view-post-btn').show();
1056 + $el.html(revert_e);
1057 + buttons.html(buttonsOrig);
1058 + permalink.html(permalinkOrig);
1059 + real_slug.val(revert_slug);
1060 + $( '.edit-slug' ).trigger( 'focus' );
1061 + });
1062 +
1063 + // If more than 1/4th of 'full' is '%', make it empty.
1064 + for ( i = 0; i < full.length; ++i ) {
1065 + if ( '%' == full.charAt(i) )
1066 + c++;
1067 + }
1068 + slug_value = ( c > full.length / 4 ) ? '' : full;
1069 + slug_label = __( 'URL Slug' );
1070 +
1071 + $el.html(
1072 + '<label for="new-post-slug" class="screen-reader-text">' + slug_label + '</label>' +
1073 + '<input type="text" id="new-post-slug" value="' + slug_value + '" autocomplete="off" spellcheck="false" />'
1074 + ).children( 'input' ).on( 'keydown', function( e ) {
1075 + var key = e.which;
1076 + // On [Enter], just save the new slug, don't save the post.
1077 + if ( 13 === key ) {
1078 + e.preventDefault();
1079 + buttons.children( '.save' ).trigger( 'click' );
1080 + }
1081 + // On [Esc] cancel the editing.
1082 + if ( 27 === key ) {
1083 + buttons.children( '.cancel' ).trigger( 'click' );
1084 + }
1085 + } ).on( 'keyup', function() {
1086 + real_slug.val( this.value );
1087 + }).trigger( 'focus' );
1088 + }
1089 +
1090 + $( '#titlediv' ).on( 'click', '.edit-slug', function() {
1091 + editPermalink();
1092 + });
1093 +
1094 + /**
1095 + * Adds screen reader text to the title label when needed.
1096 + *
1097 + * Use the 'screen-reader-text' class to emulate a placeholder attribute
1098 + * and hide the label when entering a value.
1099 + *
1100 + * @param {string} id Optional. HTML ID to add the screen reader helper text to.
1101 + *
1102 + * @global
1103 + *
1104 + * @return {void}
1105 + */
1106 + window.wptitlehint = function( id ) {
1107 + id = id || 'title';
1108 +
1109 + var title = $( '#' + id ), titleprompt = $( '#' + id + '-prompt-text' );
1110 +
1111 + if ( '' === title.val() ) {
1112 + titleprompt.removeClass( 'screen-reader-text' );
1113 + }
1114 +
1115 + title.on( 'input', function() {
1116 + if ( '' === this.value ) {
1117 + titleprompt.removeClass( 'screen-reader-text' );
1118 + return;
1119 + }
1120 +
1121 + titleprompt.addClass( 'screen-reader-text' );
1122 + } );
1123 + };
1124 +
1125 + wptitlehint();
1126 +
1127 + // Resize the WYSIWYG and plain text editors.
1128 + ( function() {
1129 + var editor, offset, mce,
1130 + $handle = $('#post-status-info'),
1131 + $postdivrich = $('#postdivrich');
1132 +
1133 + // If there are no textareas or we are on a touch device, we can't do anything.
1134 + if ( ! $textarea.length || 'ontouchstart' in window ) {
1135 + // Hide the resize handle.
1136 + $('#content-resize-handle').hide();
1137 + return;
1138 + }
1139 +
1140 + /**
1141 + * Handle drag event.
1142 + *
1143 + * @param {Object} event Event containing details about the drag.
1144 + */
1145 + function dragging( event ) {
1146 + if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) {
1147 + return;
1148 + }
1149 +
1150 + if ( mce ) {
1151 + editor.theme.resizeTo( null, offset + event.pageY );
1152 + } else {
1153 + $textarea.height( Math.max( 50, offset + event.pageY ) );
1154 + }
1155 +
1156 + event.preventDefault();
1157 + }
1158 +
1159 + /**
1160 + * When the dragging stopped make sure we return focus and do a confidence check on the height.
1161 + */
1162 + function endDrag() {
1163 + var height, toolbarHeight;
1164 +
1165 + if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) {
1166 + return;
1167 + }
1168 +
1169 + if ( mce ) {
1170 + editor.focus();
1171 + toolbarHeight = parseInt( $( '#wp-content-editor-container .mce-toolbar-grp' ).height(), 10 );
1172 +
1173 + if ( toolbarHeight < 10 || toolbarHeight > 200 ) {
1174 + toolbarHeight = 30;
1175 + }
1176 +
1177 + height = parseInt( $('#content_ifr').css('height'), 10 ) + toolbarHeight - 28;
1178 + } else {
1179 + $textarea.trigger( 'focus' );
1180 + height = parseInt( $textarea.css('height'), 10 );
1181 + }
1182 +
1183 + $document.off( '.wp-editor-resize' );
1184 +
1185 + // Confidence check: normalize height to stay within acceptable ranges.
1186 + if ( height && height > 50 && height < 5000 ) {
1187 + setUserSetting( 'ed_size', height );
1188 + }
1189 + }
1190 +
1191 + $handle.on( 'mousedown.wp-editor-resize', function( event ) {
1192 + if ( typeof tinymce !== 'undefined' ) {
1193 + editor = tinymce.get('content');
1194 + }
1195 +
1196 + if ( editor && ! editor.isHidden() ) {
1197 + mce = true;
1198 + offset = $('#content_ifr').height() - event.pageY;
1199 + } else {
1200 + mce = false;
1201 + offset = $textarea.height() - event.pageY;
1202 + $textarea.trigger( 'blur' );
1203 + }
1204 +
1205 + $document.on( 'mousemove.wp-editor-resize', dragging )
1206 + .on( 'mouseup.wp-editor-resize mouseleave.wp-editor-resize', endDrag );
1207 +
1208 + event.preventDefault();
1209 + }).on( 'mouseup.wp-editor-resize', endDrag );
1210 + })();
1211 +
1212 + // TinyMCE specific handling of Post Format changes to reflect in the editor.
1213 + if ( typeof tinymce !== 'undefined' ) {
1214 + // When changing post formats, change the editor body class.
1215 + $( '#post-formats-select input.post-format' ).on( 'change.set-editor-class', function() {
1216 + var editor, body, format = this.id;
1217 +
1218 + if ( format && $( this ).prop( 'checked' ) && ( editor = tinymce.get( 'content' ) ) ) {
1219 + body = editor.getBody();
1220 + body.className = body.className.replace( /\bpost-format-[^ ]+/, '' );
1221 + editor.dom.addClass( body, format == 'post-format-0' ? 'post-format-standard' : format );
1222 + $( document ).trigger( 'editor-classchange' );
1223 + }
1224 + });
1225 +
1226 + // When changing page template, change the editor body class.
1227 + $( '#page_template' ).on( 'change.set-editor-class', function() {
1228 + var editor, body, pageTemplate = $( this ).val() || '';
1229 +
1230 + pageTemplate = pageTemplate.substr( pageTemplate.lastIndexOf( '/' ) + 1, pageTemplate.length )
1231 + .replace( /\.php$/, '' )
1232 + .replace( /\./g, '-' );
1233 +
1234 + if ( pageTemplate && ( editor = tinymce.get( 'content' ) ) ) {
1235 + body = editor.getBody();
1236 + body.className = body.className.replace( /\bpage-template-[^ ]+/, '' );
1237 + editor.dom.addClass( body, 'page-template-' + pageTemplate );
1238 + $( document ).trigger( 'editor-classchange' );
1239 + }
1240 + });
1241 +
1242 + }
1243 +
1244 + // Save on pressing [Ctrl]/[Command] + [S] in the Text editor.
1245 + $textarea.on( 'keydown.wp-autosave', function( event ) {
1246 + // Key [S] has code 83.
1247 + if ( event.which === 83 ) {
1248 + if (
1249 + event.shiftKey ||
1250 + event.altKey ||
1251 + ( isMac && ( ! event.metaKey || event.ctrlKey ) ) ||
1252 + ( ! isMac && ! event.ctrlKey )
1253 + ) {
1254 + return;
1255 + }
1256 +
1257 + wp.autosave && wp.autosave.server.triggerSave();
1258 + event.preventDefault();
1259 + }
1260 + });
1261 +
1262 + // If the last status was auto-draft and the save is triggered, edit the current URL.
1263 + if ( $( '#original_post_status' ).val() === 'auto-draft' && window.history.replaceState ) {
1264 + var location;
1265 +
1266 + $( '#publish' ).on( 'click', function() {
1267 + location = window.location.href;
1268 + location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?';
1269 + location += 'wp-post-new-reload=true';
1270 +
1271 + window.history.replaceState( null, null, location );
1272 + });
1273 + }
1274 +
1275 + /**
1276 + * Copies the attachment URL in the Edit Media page to the clipboard.
1277 + *
1278 + * @since 5.5.0
1279 + *
1280 + * @param {MouseEvent} event A click event.
1281 + *
1282 + * @return {void}
1283 + */
1284 + copyAttachmentURLClipboard.on( 'success', function( event ) {
1285 + var triggerElement = $( event.trigger ),
1286 + successElement = $( '.success', triggerElement.closest( '.copy-to-clipboard-container' ) );
1287 +
1288 + // Clear the selection and move focus back to the trigger.
1289 + event.clearSelection();
1290 +
1291 + // Show success visual feedback.
1292 + clearTimeout( copyAttachmentURLSuccessTimeout );
1293 + successElement.removeClass( 'hidden' );
1294 +
1295 + // Hide success visual feedback after 3 seconds since last success.
1296 + copyAttachmentURLSuccessTimeout = setTimeout( function() {
1297 + successElement.addClass( 'hidden' );
1298 + }, 3000 );
1299 +
1300 + // Handle success audible feedback.
1301 + wp.a11y.speak( __( 'The file URL has been copied to your clipboard' ) );
1302 + } );
1303 + } );
1304 +
1305 + /**
1306 + * TinyMCE word count display
1307 + */
1308 + ( function( $, counter ) {
1309 + $( function() {
1310 + var $content = $( '#content' ),
1311 + $count = $( '#wp-word-count' ).find( '.word-count' ),
1312 + prevCount = 0,
1313 + contentEditor;
1314 +
1315 + /**
1316 + * Get the word count from TinyMCE and display it
1317 + */
1318 + function update() {
1319 + var text, count;
1320 +
1321 + if ( ! contentEditor || contentEditor.isHidden() ) {
1322 + text = $content.val();
1323 + } else {
1324 + text = contentEditor.getContent( { format: 'raw' } );
1325 + }
1326 +
1327 + count = counter.count( text );
1328 +
1329 + if ( count !== prevCount ) {
1330 + $count.text( count );
1331 + }
1332 +
1333 + prevCount = count;
1334 + }
1335 +
1336 + /**
1337 + * Bind the word count update triggers.
1338 + *
1339 + * When a node change in the main TinyMCE editor has been triggered.
1340 + * When a key has been released in the plain text content editor.
1341 + */
1342 + $( document ).on( 'tinymce-editor-init', function( event, editor ) {
1343 + if ( editor.id !== 'content' ) {
1344 + return;
1345 + }
1346 +
1347 + contentEditor = editor;
1348 +
1349 + editor.on( 'nodechange keyup', _.debounce( update, 1000 ) );
1350 + } );
1351 +
1352 + $content.on( 'input keyup', _.debounce( update, 1000 ) );
1353 +
1354 + update();
1355 + } );
1356 +
1357 + } )( jQuery, new wp.utils.WordCounter() );
1358 +