[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/resources/src/jquery/ -> jquery.confirmable.js (source)

   1  /**
   2   * jQuery confirmable plugin
   3   *
   4   * Released under the MIT License.
   5   *
   6   * @author Bartosz Dziewoński
   7   *
   8   * @class jQuery.plugin.confirmable
   9   */
  10  ( function ( $ ) {
  11      var identity = function ( data ) {
  12          return data;
  13      };
  14  
  15      /**
  16       * Enable inline confirmation for given clickable element (like `<a />` or `<button />`).
  17       *
  18       * An additional inline confirmation step being shown before the default action is carried out on
  19       * click.
  20       *
  21       * Calling `.confirmable( { handler: function () { … } } )` will fire the handler only after the
  22       * confirmation step.
  23       *
  24       * The element will have the `jquery-confirmable-element` class added to it when it's clicked for
  25       * the first time, which has `white-space: nowrap;` and `display: inline-block;` defined in CSS.
  26       * If the computed values for the element are different when you make it confirmable, you might
  27       * encounter unexpected behavior.
  28       *
  29       * @param {Object} [options]
  30       * @param {string} [options.events='click'] Events to hook to.
  31       * @param {Function} [options.wrapperCallback] Callback to fire when preparing confirmable
  32       *     interface. Receives the interface jQuery object as the only parameter.
  33       * @param {Function} [options.buttonCallback] Callback to fire when preparing confirmable buttons.
  34       *     It is fired separately for the 'Yes' and 'No' button. Receives the button jQuery object as
  35       *     the first parameter and 'yes' or 'no' as the second.
  36       * @param {Function} [options.handler] Callback to fire when the action is confirmed (user clicks
  37       *     the 'Yes' button).
  38       * @param {string} [options.i18n] Text to use for interface elements.
  39       * @param {string} [options.i18n.space] Word separator to place between the three text messages.
  40       * @param {string} [options.i18n.confirm] Text to use for the confirmation question.
  41       * @param {string} [options.i18n.yes] Text to use for the 'Yes' button.
  42       * @param {string} [options.i18n.no] Text to use for the 'No' button.
  43       *
  44       * @chainable
  45       */
  46      $.fn.confirmable = function ( options ) {
  47          options = $.extend( true, {}, $.fn.confirmable.defaultOptions, options || {} );
  48  
  49          return this.on( options.events, function ( e ) {
  50              var $element, $text, $buttonYes, $buttonNo, $wrapper, $interface, $elementClone,
  51                  interfaceWidth, elementWidth, rtl, positionOffscreen, positionRestore, sideMargin;
  52  
  53              $element = $( this );
  54  
  55              if ( $element.data( 'jquery-confirmable-button' ) ) {
  56                  // We're running on a clone of this element that represents the 'Yes' or 'No' button.
  57                  // (This should never happen for the 'No' case unless calling code does bad things.)
  58                  return;
  59              }
  60  
  61              // Only prevent native event handling. Stopping other JavaScript event handlers
  62              // is impossible because they might have already run (we have no control over the order).
  63              e.preventDefault();
  64  
  65              rtl = $element.css( 'direction' ) === 'rtl';
  66              if ( rtl ) {
  67                  positionOffscreen = { position: 'absolute', right: '-9999px' };
  68                  positionRestore = { position: '', right: '' };
  69                  sideMargin = 'marginRight';
  70              } else {
  71                  positionOffscreen = { position: 'absolute', left: '-9999px' };
  72                  positionRestore = { position: '', left: '' };
  73                  sideMargin = 'marginLeft';
  74              }
  75  
  76              if ( $element.hasClass( 'jquery-confirmable-element' ) ) {
  77                  $wrapper = $element.closest( '.jquery-confirmable-wrapper' );
  78                  $interface = $wrapper.find( '.jquery-confirmable-interface' );
  79                  $text = $interface.find( '.jquery-confirmable-text' );
  80                  $buttonYes = $interface.find( '.jquery-confirmable-button-yes' );
  81                  $buttonNo = $interface.find( '.jquery-confirmable-button-no' );
  82  
  83                  interfaceWidth = $interface.data( 'jquery-confirmable-width' );
  84                  elementWidth = $element.data( 'jquery-confirmable-width' );
  85              } else {
  86                  $elementClone = $element.clone( true );
  87                  $element.addClass( 'jquery-confirmable-element' );
  88  
  89                  elementWidth = $element.width();
  90                  $element.data( 'jquery-confirmable-width', elementWidth );
  91  
  92                  $wrapper = $( '<span>' )
  93                      .addClass( 'jquery-confirmable-wrapper' );
  94                  $element.wrap( $wrapper );
  95  
  96                  // Build the mini-dialog
  97                  $text = $( '<span>' )
  98                      .addClass( 'jquery-confirmable-text' )
  99                      .text( options.i18n.confirm );
 100  
 101                  // Clone original element along with event handlers to easily replicate its behavior.
 102                  // We could fiddle with .trigger() etc., but that is troublesome especially since
 103                  // Safari doesn't implement .click() on <a> links and jQuery follows suit.
 104                  $buttonYes = $elementClone.clone( true )
 105                      .addClass( 'jquery-confirmable-button jquery-confirmable-button-yes' )
 106                      .data( 'jquery-confirmable-button', true )
 107                      .text( options.i18n.yes );
 108                  if ( options.handler ) {
 109                      $buttonYes.on( options.events, options.handler );
 110                  }
 111                  $buttonYes = options.buttonCallback( $buttonYes, 'yes' );
 112  
 113                  // Clone it without any events and prevent default action to represent the 'No' button.
 114                  $buttonNo = $elementClone.clone( false )
 115                      .addClass( 'jquery-confirmable-button jquery-confirmable-button-no' )
 116                      .data( 'jquery-confirmable-button', true )
 117                      .text( options.i18n.no )
 118                      .on( options.events, function ( e ) {
 119                          $element.css( sideMargin, 0 );
 120                          $interface.css( 'width', 0 );
 121                          e.preventDefault();
 122                      } );
 123                  $buttonNo = options.buttonCallback( $buttonNo, 'no' );
 124  
 125                  // Prevent memory leaks
 126                  $elementClone.remove();
 127  
 128                  $interface = $( '<span>' )
 129                      .addClass( 'jquery-confirmable-interface' )
 130                      .append( $text, options.i18n.space, $buttonYes, options.i18n.space, $buttonNo );
 131                  $interface = options.wrapperCallback( $interface );
 132  
 133                  // Render offscreen to measure real width
 134                  $interface.css( positionOffscreen );
 135                  // Insert it in the correct place while we're at it
 136                  $element.after( $interface );
 137                  interfaceWidth = $interface.width();
 138                  $interface.data( 'jquery-confirmable-width', interfaceWidth );
 139                  $interface.css( positionRestore );
 140  
 141                  // Hide to animate the transition later
 142                  $interface.css( 'width', 0 );
 143              }
 144  
 145              // Hide element, show interface. This triggers both transitions.
 146              // In a timeout to trigger the 'width' transition.
 147              setTimeout( function () {
 148                  $element.css( sideMargin, -elementWidth );
 149                  $interface.css( 'width', interfaceWidth );
 150              }, 1 );
 151          } );
 152      };
 153  
 154      /**
 155       * Default options. Overridable primarily for internationalisation handling.
 156       * @property {Object} defaultOptions
 157       */
 158      $.fn.confirmable.defaultOptions = {
 159          events: 'click',
 160          wrapperCallback: identity,
 161          buttonCallback: identity,
 162          handler: null,
 163          i18n: {
 164              space: ' ',
 165              confirm: 'Are you sure?',
 166              yes: 'Yes',
 167              no: 'No'
 168          }
 169      };
 170  }( jQuery ) );


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1