[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-admin/js/ -> wp-fullscreen.js (source)

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


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu