| [ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /** 2 * PubSub 3 * 4 * A lightweight publish/subscribe implementation. 5 * Private use only! 6 */ 7 var PubSub, fullscreen, wptitlehint; 8 9 PubSub = function() { 10 this.topics = {}; 11 }; 12 13 PubSub.prototype.subscribe = function( topic, callback ) { 14 if ( ! this.topics[ topic ] ) 15 this.topics[ topic ] = []; 16 17 this.topics[ topic ].push( callback ); 18 return callback; 19 }; 20 21 PubSub.prototype.unsubscribe = function( topic, callback ) { 22 var i, l, 23 topics = this.topics[ topic ]; 24 25 if ( ! topics ) 26 return callback || []; 27 28 // Clear matching callbacks 29 if ( callback ) { 30 for ( i = 0, l = topics.length; i < l; i++ ) { 31 if ( callback == topics[i] ) 32 topics.splice( i, 1 ); 33 } 34 return callback; 35 36 // Clear all callbacks 37 } else { 38 this.topics[ topic ] = []; 39 return topics; 40 } 41 }; 42 43 PubSub.prototype.publish = function( topic, args ) { 44 var i, l, broken, 45 topics = this.topics[ topic ]; 46 47 if ( ! topics ) 48 return; 49 50 args = args || []; 51 52 for ( i = 0, l = topics.length; i < l; i++ ) { 53 broken = ( topics[i].apply( null, args ) === false || broken ); 54 } 55 return ! broken; 56 }; 57 58 /** 59 * Distraction Free Writing 60 * (wp-fullscreen) 61 * 62 * Access the API globally using the fullscreen variable. 63 */ 64 65 (function($){ 66 var api, ps, bounder, s; 67 68 // Initialize the fullscreen/api object 69 fullscreen = api = {}; 70 71 // Create the PubSub (publish/subscribe) interface. 72 ps = api.pubsub = new PubSub(); 73 timer = 0; 74 block = false; 75 76 s = api.settings = { // Settings 77 visible : false, 78 mode : 'tinymce', 79 editor_id : 'content', 80 title_id : '', 81 timer : 0, 82 toolbar_shown : false 83 } 84 85 /** 86 * Bounder 87 * 88 * Creates a function that publishes start/stop topics. 89 * Used to throttle events. 90 */ 91 bounder = api.bounder = function( start, stop, delay, e ) { 92 var y, top; 93 94 delay = delay || 1250; 95 96 if ( e ) { 97 y = e.pageY || e.clientY || e.offsetY; 98 top = $(document).scrollTop(); 99 100 if ( !e.isDefaultPrevented ) // test if e ic jQuery normalized 101 y = 135 + y; 102 103 if ( y - top > 120 ) 104 return; 105 } 106 107 if ( block ) 108 return; 109 110 block = true; 111 112 setTimeout( function() { 113 block = false; 114 }, 400 ); 115 116 if ( s.timer ) 117 clearTimeout( s.timer ); 118 else 119 ps.publish( start ); 120 121 function timed() { 122 ps.publish( stop ); 123 s.timer = 0; 124 } 125 126 s.timer = setTimeout( timed, delay ); 127 }; 128 129 /** 130 * on() 131 * 132 * Turns fullscreen on. 133 * 134 * @param string mode Optional. Switch to the given mode before opening. 135 */ 136 api.on = function() { 137 if ( s.visible ) 138 return; 139 140 // Settings can be added or changed by defining "wp_fullscreen_settings" JS object. 141 if ( typeof(wp_fullscreen_settings) == 'object' ) 142 $.extend( s, wp_fullscreen_settings ); 143 144 s.editor_id = wpActiveEditor || 'content'; 145 146 if ( $('input#title').length && s.editor_id == 'content' ) 147 s.title_id = 'title'; 148 else if ( $('input#' + s.editor_id + '-title').length ) // the title input field should have [editor_id]-title HTML ID to be auto detected 149 s.title_id = s.editor_id + '-title'; 150 else 151 $('#wp-fullscreen-title, #wp-fullscreen-title-prompt-text').hide(); 152 153 s.mode = $('#' + s.editor_id).is(':hidden') ? 'tinymce' : 'html'; 154 s.qt_canvas = $('#' + s.editor_id).get(0); 155 156 if ( ! s.element ) 157 api.ui.init(); 158 159 s.is_mce_on = s.has_tinymce && typeof( tinyMCE.get(s.editor_id) ) != 'undefined'; 160 161 api.ui.fade( 'show', 'showing', 'shown' ); 162 }; 163 164 /** 165 * off() 166 * 167 * Turns fullscreen off. 168 */ 169 api.off = function() { 170 if ( ! s.visible ) 171 return; 172 173 api.ui.fade( 'hide', 'hiding', 'hidden' ); 174 }; 175 176 /** 177 * switchmode() 178 * 179 * @return string - The current mode. 180 * 181 * @param string to - The fullscreen mode to switch to. 182 * @event switchMode 183 * @eventparam string to - The new mode. 184 * @eventparam string from - The old mode. 185 */ 186 api.switchmode = function( to ) { 187 var from = s.mode; 188 189 if ( ! to || ! s.visible || ! s.has_tinymce ) 190 return from; 191 192 // Don't switch if the mode is the same. 193 if ( from == to ) 194 return from; 195 196 ps.publish( 'switchMode', [ from, to ] ); 197 s.mode = to; 198 ps.publish( 'switchedMode', [ from, to ] ); 199 200 return to; 201 }; 202 203 /** 204 * General 205 */ 206 207 api.save = function() { 208 var hidden = $('#hiddenaction'), old = hidden.val(), spinner = $('#wp-fullscreen-save img'), 209 message = $('#wp-fullscreen-save span'); 210 211 spinner.show(); 212 api.savecontent(); 213 214 hidden.val('wp-fullscreen-save-post'); 215 216 $.post( ajaxurl, $('form#post').serialize(), function(r){ 217 spinner.hide(); 218 message.show(); 219 220 setTimeout( function(){ 221 message.fadeOut(1000); 222 }, 3000 ); 223 224 if ( r.last_edited ) 225 $('#wp-fullscreen-save input').attr( 'title', r.last_edited ); 226 227 }, 'json'); 228 229 hidden.val(old); 230 } 231 232 api.savecontent = function() { 233 var ed, content; 234 235 if ( s.title_id ) 236 $('#' + s.title_id).val( $('#wp-fullscreen-title').val() ); 237 238 if ( s.mode === 'tinymce' && (ed = tinyMCE.get('wp_mce_fullscreen')) ) { 239 content = ed.save(); 240 } else { 241 content = $('#wp_mce_fullscreen').val(); 242 } 243 244 $('#' + s.editor_id).val( content ); 245 $(document).triggerHandler('wpcountwords', [ content ]); 246 } 247 248 set_title_hint = function( title ) { 249 if ( ! title.val().length ) 250 title.siblings('label').css( 'visibility', '' ); 251 else 252 title.siblings('label').css( 'visibility', 'hidden' ); 253 } 254 255 api.dfw_width = function(n) { 256 var el = $('#wp-fullscreen-wrap'), w = el.width(); 257 258 if ( !n ) { // reset to theme width 259 el.width( $('#wp-fullscreen-central-toolbar').width() ); 260 deleteUserSetting('dfw_width'); 261 return; 262 } 263 264 w = n + w; 265 266 if ( w < 200 || w > 1200 ) // sanity check 267 return; 268 269 el.width( w ); 270 setUserSetting('dfw_width', w); 271 } 272 273 ps.subscribe( 'showToolbar', function() { 274 s.toolbars.removeClass('fade-1000').addClass('fade-300'); 275 api.fade.In( s.toolbars, 300, function(){ ps.publish('toolbarShown'); }, true ); 276 $('#wp-fullscreen-body').addClass('wp-fullscreen-focus'); 277 s.toolbar_shown = true; 278 }); 279 280 ps.subscribe( 'hideToolbar', function() { 281 s.toolbars.removeClass('fade-300').addClass('fade-1000'); 282 api.fade.Out( s.toolbars, 1000, function(){ ps.publish('toolbarHidden'); }, true ); 283 $('#wp-fullscreen-body').removeClass('wp-fullscreen-focus'); 284 }); 285 286 ps.subscribe( 'toolbarShown', function() { 287 s.toolbars.removeClass('fade-300'); 288 }); 289 290 ps.subscribe( 'toolbarHidden', function() { 291 s.toolbars.removeClass('fade-1000'); 292 s.toolbar_shown = false; 293 }); 294 295 ps.subscribe( 'show', function() { // This event occurs before the overlay blocks the UI. 296 var title; 297 298 if ( s.title_id ) { 299 title = $('#wp-fullscreen-title').val( $('#' + s.title_id).val() ); 300 set_title_hint( title ); 301 } 302 303 $('#wp-fullscreen-save input').attr( 'title', $('#last-edit').text() ); 304 305 s.textarea_obj.value = s.qt_canvas.value; 306 307 if ( s.has_tinymce && s.mode === 'tinymce' ) 308 tinyMCE.execCommand('wpFullScreenInit'); 309 310 s.orig_y = $(window).scrollTop(); 311 }); 312 313 ps.subscribe( 'showing', function() { // This event occurs while the DFW overlay blocks the UI. 314 $( document.body ).addClass( 'fullscreen-active' ); 315 api.refresh_buttons(); 316 317 $( document ).bind( 'mousemove.fullscreen', function(e) { bounder( 'showToolbar', 'hideToolbar', 2000, e ); } ); 318 bounder( 'showToolbar', 'hideToolbar', 2000 ); 319 320 api.bind_resize(); 321 setTimeout( api.resize_textarea, 200 ); 322 323 // scroll to top so the user is not disoriented 324 scrollTo(0, 0); 325 326 // needed it for IE7 and compat mode 327 $('#wpadminbar').hide(); 328 }); 329 330 ps.subscribe( 'shown', function() { // This event occurs after the DFW overlay is shown 331 var interim_init; 332 333 s.visible = true; 334 335 // init the standard TinyMCE instance if missing 336 if ( s.has_tinymce && ! s.is_mce_on ) { 337 338 interim_init = function(mce, ed) { 339 var el = ed.getElement(), old_val = el.value, settings = tinyMCEPreInit.mceInit[s.editor_id]; 340 341 if ( settings && settings.wpautop && typeof(switchEditors) != 'undefined' ) 342 el.value = switchEditors.wpautop( el.value ); 343 344 ed.onInit.add(function(ed) { 345 ed.hide(); 346 ed.getElement().value = old_val; 347 tinymce.onAddEditor.remove(interim_init); 348 }); 349 }; 350 351 tinymce.onAddEditor.add(interim_init); 352 tinyMCE.init(tinyMCEPreInit.mceInit[s.editor_id]); 353 354 s.is_mce_on = true; 355 } 356 357 wpActiveEditor = 'wp_mce_fullscreen'; 358 }); 359 360 ps.subscribe( 'hide', function() { // This event occurs before the overlay blocks DFW. 361 var htmled_is_hidden = $('#' + s.editor_id).is(':hidden'); 362 // Make sure the correct editor is displaying. 363 if ( s.has_tinymce && s.mode === 'tinymce' && !htmled_is_hidden ) { 364 switchEditors.go(s.editor_id, 'tmce'); 365 } else if ( s.mode === 'html' && htmled_is_hidden ) { 366 switchEditors.go(s.editor_id, 'html'); 367 } 368 369 // Save content must be after switchEditors or content will be overwritten. See #17229. 370 api.savecontent(); 371 372 $( document ).unbind( '.fullscreen' ); 373 $(s.textarea_obj).unbind('.grow'); 374 375 if ( s.has_tinymce && s.mode === 'tinymce' ) 376 tinyMCE.execCommand('wpFullScreenSave'); 377 378 if ( s.title_id ) 379 set_title_hint( $('#' + s.title_id) ); 380 381 s.qt_canvas.value = s.textarea_obj.value; 382 }); 383 384 ps.subscribe( 'hiding', function() { // This event occurs while the overlay blocks the DFW UI. 385 386 $( document.body ).removeClass( 'fullscreen-active' ); 387 scrollTo(0, s.orig_y); 388 $('#wpadminbar').show(); 389 }); 390 391 ps.subscribe( 'hidden', function() { // This event occurs after DFW is removed. 392 s.visible = false; 393 $('#wp_mce_fullscreen, #wp-fullscreen-title').removeAttr('style'); 394 395 if ( s.has_tinymce && s.is_mce_on ) 396 tinyMCE.execCommand('wpFullScreenClose'); 397 398 s.textarea_obj.value = ''; 399 api.oldheight = 0; 400 wpActiveEditor = s.editor_id; 401 }); 402 403 ps.subscribe( 'switchMode', function( from, to ) { 404 var ed; 405 406 if ( !s.has_tinymce || !s.is_mce_on ) 407 return; 408 409 ed = tinyMCE.get('wp_mce_fullscreen'); 410 411 if ( from === 'html' && to === 'tinymce' ) { 412 413 if ( tinyMCE.get(s.editor_id).getParam('wpautop') && typeof(switchEditors) != 'undefined' ) 414 s.textarea_obj.value = switchEditors.wpautop( s.textarea_obj.value ); 415 416 if ( 'undefined' == typeof(ed) ) 417 tinyMCE.execCommand('wpFullScreenInit'); 418 else 419 ed.show(); 420 421 } else if ( from === 'tinymce' && to === 'html' ) { 422 if ( ed ) 423 ed.hide(); 424 } 425 }); 426 427 ps.subscribe( 'switchedMode', function( from, to ) { 428 api.refresh_buttons(true); 429 430 if ( to === 'html' ) 431 setTimeout( api.resize_textarea, 200 ); 432 }); 433 434 /** 435 * Buttons 436 */ 437 api.b = function() { 438 if ( s.has_tinymce && 'tinymce' === s.mode ) 439 tinyMCE.execCommand('Bold'); 440 } 441 442 api.i = function() { 443 if ( s.has_tinymce && 'tinymce' === s.mode ) 444 tinyMCE.execCommand('Italic'); 445 } 446 447 api.ul = function() { 448 if ( s.has_tinymce && 'tinymce' === s.mode ) 449 tinyMCE.execCommand('InsertUnorderedList'); 450 } 451 452 api.ol = function() { 453 if ( s.has_tinymce && 'tinymce' === s.mode ) 454 tinyMCE.execCommand('InsertOrderedList'); 455 } 456 457 api.link = function() { 458 if ( s.has_tinymce && 'tinymce' === s.mode ) 459 tinyMCE.execCommand('WP_Link'); 460 else 461 wpLink.open(); 462 } 463 464 api.unlink = function() { 465 if ( s.has_tinymce && 'tinymce' === s.mode ) 466 tinyMCE.execCommand('unlink'); 467 } 468 469 api.atd = function() { 470 if ( s.has_tinymce && 'tinymce' === s.mode ) 471 tinyMCE.execCommand('mceWritingImprovementTool'); 472 } 473 474 api.help = function() { 475 if ( s.has_tinymce && 'tinymce' === s.mode ) 476 tinyMCE.execCommand('WP_Help'); 477 } 478 479 api.blockquote = function() { 480 if ( s.has_tinymce && 'tinymce' === s.mode ) 481 tinyMCE.execCommand('mceBlockQuote'); 482 } 483 484 api.medialib = function() { 485 if ( s.has_tinymce && 'tinymce' === s.mode ) { 486 tinyMCE.execCommand('WP_Medialib'); 487 } else { 488 var href = $('#wp-' + s.editor_id + '-media-buttons a.thickbox').attr('href') || ''; 489 490 if ( href ) 491 tb_show('', href); 492 } 493 } 494 495 api.refresh_buttons = function( fade ) { 496 fade = fade || false; 497 498 if ( s.mode === 'html' ) { 499 $('#wp-fullscreen-mode-bar').removeClass('wp-tmce-mode').addClass('wp-html-mode'); 500 501 if ( fade ) 502 $('#wp-fullscreen-button-bar').fadeOut( 150, function(){ 503 $(this).addClass('wp-html-mode').fadeIn( 150 ); 504 }); 505 else 506 $('#wp-fullscreen-button-bar').addClass('wp-html-mode'); 507 508 } else if ( s.mode === 'tinymce' ) { 509 $('#wp-fullscreen-mode-bar').removeClass('wp-html-mode').addClass('wp-tmce-mode'); 510 511 if ( fade ) 512 $('#wp-fullscreen-button-bar').fadeOut( 150, function(){ 513 $(this).removeClass('wp-html-mode').fadeIn( 150 ); 514 }); 515 else 516 $('#wp-fullscreen-button-bar').removeClass('wp-html-mode'); 517 } 518 } 519 520 /** 521 * UI Elements 522 * 523 * Used for transitioning between states. 524 */ 525 api.ui = { 526 init: function() { 527 var topbar = $('#fullscreen-topbar'), txtarea = $('#wp_mce_fullscreen'), last = 0; 528 529 s.toolbars = topbar.add( $('#wp-fullscreen-status') ); 530 s.element = $('#fullscreen-fader'); 531 s.textarea_obj = txtarea[0]; 532 s.has_tinymce = typeof(tinymce) != 'undefined'; 533 534 if ( !s.has_tinymce ) 535 $('#wp-fullscreen-mode-bar').hide(); 536 537 if ( wptitlehint && $('#wp-fullscreen-title').length ) 538 wptitlehint('wp-fullscreen-title'); 539 540 $(document).keyup(function(e){ 541 var c = e.keyCode || e.charCode, a, data; 542 543 if ( !fullscreen.settings.visible ) 544 return true; 545 546 if ( navigator.platform && navigator.platform.indexOf('Mac') != -1 ) 547 a = e.ctrlKey; // Ctrl key for Mac 548 else 549 a = e.altKey; // Alt key for Win & Linux 550 551 if ( 27 == c ) { // Esc 552 data = { 553 event: e, 554 what: 'dfw', 555 cb: fullscreen.off, 556 condition: function(){ 557 if ( $('#TB_window').is(':visible') || $('.wp-dialog').is(':visible') ) 558 return false; 559 return true; 560 } 561 }; 562 563 if ( ! jQuery(document).triggerHandler( 'wp_CloseOnEscape', [data] ) ) 564 fullscreen.off(); 565 } 566 567 if ( a && (61 == c || 107 == c || 187 == c) ) // + 568 api.dfw_width(25); 569 570 if ( a && (45 == c || 109 == c || 189 == c) ) // - 571 api.dfw_width(-25); 572 573 if ( a && 48 == c ) // 0 574 api.dfw_width(0); 575 576 return false; 577 }); 578 579 // word count in HTML mode 580 if ( typeof(wpWordCount) != 'undefined' ) { 581 582 txtarea.keyup( function(e) { 583 var k = e.keyCode || e.charCode; 584 585 if ( k == last ) 586 return true; 587 588 if ( 13 == k || 8 == last || 46 == last ) 589 $(document).triggerHandler('wpcountwords', [ txtarea.val() ]); 590 591 last = k; 592 return true; 593 }); 594 } 595 596 topbar.mouseenter(function(e){ 597 s.toolbars.addClass('fullscreen-make-sticky'); 598 $( document ).unbind( '.fullscreen' ); 599 clearTimeout( s.timer ); 600 s.timer = 0; 601 }).mouseleave(function(e){ 602 s.toolbars.removeClass('fullscreen-make-sticky'); 603 604 if ( s.visible ) 605 $( document ).bind( 'mousemove.fullscreen', function(e) { bounder( 'showToolbar', 'hideToolbar', 2000, e ); } ); 606 }); 607 }, 608 609 fade: function( before, during, after ) { 610 if ( ! s.element ) 611 api.ui.init(); 612 613 // If any callback bound to before returns false, bail. 614 if ( before && ! ps.publish( before ) ) 615 return; 616 617 api.fade.In( s.element, 600, function() { 618 if ( during ) 619 ps.publish( during ); 620 621 api.fade.Out( s.element, 600, function() { 622 if ( after ) 623 ps.publish( after ); 624 }) 625 }); 626 } 627 }; 628 629 api.fade = { 630 transitionend: 'transitionend webkitTransitionEnd oTransitionEnd', 631 632 // Sensitivity to allow browsers to render the blank element before animating. 633 sensitivity: 100, 634 635 In: function( element, speed, callback, stop ) { 636 637 callback = callback || $.noop; 638 speed = speed || 400; 639 stop = stop || false; 640 641 if ( api.fade.transitions ) { 642 if ( element.is(':visible') ) { 643 element.addClass( 'fade-trigger' ); 644 return element; 645 } 646 647 element.show(); 648 element.first().one( this.transitionend, function() { 649 callback(); 650 }); 651 setTimeout( function() { element.addClass( 'fade-trigger' ); }, this.sensitivity ); 652 } else { 653 if ( stop ) 654 element.stop(); 655 656 element.css( 'opacity', 1 ); 657 element.first().fadeIn( speed, callback ); 658 659 if ( element.length > 1 ) 660 element.not(':first').fadeIn( speed ); 661 } 662 663 return element; 664 }, 665 666 Out: function( element, speed, callback, stop ) { 667 668 callback = callback || $.noop; 669 speed = speed || 400; 670 stop = stop || false; 671 672 if ( ! element.is(':visible') ) 673 return element; 674 675 if ( api.fade.transitions ) { 676 element.first().one( api.fade.transitionend, function() { 677 if ( element.hasClass('fade-trigger') ) 678 return; 679 680 element.hide(); 681 callback(); 682 }); 683 setTimeout( function() { element.removeClass( 'fade-trigger' ); }, this.sensitivity ); 684 } else { 685 if ( stop ) 686 element.stop(); 687 688 element.first().fadeOut( speed, callback ); 689 690 if ( element.length > 1 ) 691 element.not(':first').fadeOut( speed ); 692 } 693 694 return element; 695 }, 696 697 transitions: (function() { // Check if the browser supports CSS 3.0 transitions 698 var s = document.documentElement.style; 699 700 return ( typeof ( s.WebkitTransition ) == 'string' || 701 typeof ( s.MozTransition ) == 'string' || 702 typeof ( s.OTransition ) == 'string' || 703 typeof ( s.transition ) == 'string' ); 704 })() 705 }; 706 707 /** 708 * Resize API 709 * 710 * Automatically updates textarea height. 711 */ 712 713 api.bind_resize = function() { 714 $(s.textarea_obj).bind('keypress.grow click.grow paste.grow', function(){ 715 setTimeout( api.resize_textarea, 200 ); 716 }); 717 } 718 719 api.oldheight = 0; 720 api.resize_textarea = function() { 721 var txt = s.textarea_obj, newheight; 722 723 newheight = txt.scrollHeight > 300 ? txt.scrollHeight : 300; 724 725 if ( newheight != api.oldheight ) { 726 txt.style.height = newheight + 'px'; 727 api.oldheight = newheight; 728 } 729 }; 730 731 })(jQuery);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Fri May 25 03:56:23 2012 | Hosted by follow the white rabbit. |