2015-08-17 17:00:26 -07:00
/ * *
* @ file
* Extends the Drupal AJAX functionality to integrate the dialog API .
* /
( function ( $ , Drupal ) {
2015-10-21 21:44:50 -07:00
'use strict' ;
2015-08-17 17:00:26 -07:00
/ * *
* Initialize dialogs for Ajax purposes .
*
* @ type { Drupal ~ behavior }
* /
Drupal . behaviors . dialog = {
attach : function ( context , settings ) {
var $context = $ ( context ) ;
// Provide a known 'drupal-modal' DOM element for Drupal-based modal
// dialogs. Non-modal dialogs are responsible for creating their own
// elements, since there can be multiple non-modal dialogs at a time.
if ( ! $ ( '#drupal-modal' ) . length ) {
// Add 'ui-front' jQuery UI class so jQuery UI widgets like autocomplete
// sit on top of dialogs. For more information see
// http://api.jqueryui.com/theming/stacking-elements/.
$ ( '<div id="drupal-modal" class="ui-front"/>' ) . hide ( ) . appendTo ( 'body' ) ;
}
// Special behaviors specific when attaching content within a dialog.
// These behaviors usually fire after a validation error inside a dialog.
var $dialog = $context . closest ( '.ui-dialog-content' ) ;
if ( $dialog . length ) {
// Remove and replace the dialog buttons with those from the new form.
if ( $dialog . dialog ( 'option' , 'drupalAutoButtons' ) ) {
// Trigger an event to detect/sync changes to buttons.
$dialog . trigger ( 'dialogButtonsChange' ) ;
}
// Force focus on the modal when the behavior is run.
$dialog . dialog ( 'widget' ) . trigger ( 'focus' ) ;
}
var originalClose = settings . dialog . close ;
// Overwrite the close method to remove the dialog on closing.
settings . dialog . close = function ( event ) {
originalClose . apply ( settings . dialog , arguments ) ;
$ ( event . target ) . remove ( ) ;
} ;
} ,
/ * *
* Scan a dialog for any primary buttons and move them to the button area .
*
* @ param { jQuery } $dialog
* An jQuery object containing the element that is the dialog target .
*
* @ return { Array }
* An array of buttons that need to be added to the button area .
* /
prepareDialogButtons : function ( $dialog ) {
var buttons = [ ] ;
var $buttons = $dialog . find ( '.form-actions input[type=submit]' ) ;
$buttons . each ( function ( ) {
// Hidden form buttons need special attention. For browser consistency,
// the button needs to be "visible" in order to have the enter key fire
// the form submit event. So instead of a simple "hide" or
// "display: none", we set its dimensions to zero.
// See http://mattsnider.com/how-forms-submit-when-pressing-enter/
var $originalButton = $ ( this ) . css ( {
2015-08-27 12:03:05 -07:00
display : 'block' ,
2015-08-17 17:00:26 -07:00
width : 0 ,
height : 0 ,
padding : 0 ,
border : 0
} ) ;
buttons . push ( {
2015-09-04 13:20:09 -07:00
text : $originalButton . html ( ) || $originalButton . attr ( 'value' ) ,
class : $originalButton . attr ( 'class' ) ,
click : function ( e ) {
2015-08-17 17:00:26 -07:00
$originalButton . trigger ( 'mousedown' ) . trigger ( 'mouseup' ) . trigger ( 'click' ) ;
e . preventDefault ( ) ;
}
} ) ;
} ) ;
return buttons ;
}
} ;
/ * *
* Command to open a dialog .
*
* @ param { Drupal . Ajax } ajax
* @ param { object } response
* @ param { number } [ status ]
*
* @ return { bool | undefined }
* /
Drupal . AjaxCommands . prototype . openDialog = function ( ajax , response , status ) {
if ( ! response . selector ) {
return false ;
}
var $dialog = $ ( response . selector ) ;
if ( ! $dialog . length ) {
// Create the element if needed.
2015-08-27 12:03:05 -07:00
$dialog = $ ( '<div id="' + response . selector . replace ( /^#/ , '' ) + '" class="ui-front"/>' ) . appendTo ( 'body' ) ;
2015-08-17 17:00:26 -07:00
}
// Set up the wrapper, if there isn't one.
if ( ! ajax . wrapper ) {
ajax . wrapper = $dialog . attr ( 'id' ) ;
}
// Use the ajax.js insert command to populate the dialog contents.
response . command = 'insert' ;
response . method = 'html' ;
ajax . commands . insert ( ajax , response , status ) ;
// Move the buttons to the jQuery UI dialog buttons area.
if ( ! response . dialogOptions . buttons ) {
response . dialogOptions . drupalAutoButtons = true ;
response . dialogOptions . buttons = Drupal . behaviors . dialog . prepareDialogButtons ( $dialog ) ;
}
// Bind dialogButtonsChange.
$dialog . on ( 'dialogButtonsChange' , function ( ) {
var buttons = Drupal . behaviors . dialog . prepareDialogButtons ( $dialog ) ;
$dialog . dialog ( 'option' , 'buttons' , buttons ) ;
} ) ;
// Open the dialog itself.
response . dialogOptions = response . dialogOptions || { } ;
var dialog = Drupal . dialog ( $dialog . get ( 0 ) , response . dialogOptions ) ;
if ( response . dialogOptions . modal ) {
dialog . showModal ( ) ;
}
else {
dialog . show ( ) ;
}
// Add the standard Drupal class for buttons for style consistency.
$dialog . parent ( ) . find ( '.ui-dialog-buttonset' ) . addClass ( 'form-actions' ) ;
} ;
/ * *
* Command to close a dialog .
*
* If no selector is given , it defaults to trying to close the modal .
*
* @ param { Drupal . Ajax } [ ajax ]
* @ param { object } response
* @ param { string } response . selector
* @ param { bool } response . persist
* @ param { number } [ status ]
* /
Drupal . AjaxCommands . prototype . closeDialog = function ( ajax , response , status ) {
var $dialog = $ ( response . selector ) ;
if ( $dialog . length ) {
Drupal . dialog ( $dialog . get ( 0 ) ) . close ( ) ;
if ( ! response . persist ) {
$dialog . remove ( ) ;
}
}
// Unbind dialogButtonsChange.
$dialog . off ( 'dialogButtonsChange' ) ;
} ;
/ * *
* Command to set a dialog property .
*
* JQuery UI specific way of setting dialog options .
*
* @ param { Drupal . Ajax } [ ajax ]
* @ param { object } response
* @ param { string } response . selector
* @ param { string } response . optionsName
* @ param { string } response . optionValue
* @ param { number } [ status ]
* /
Drupal . AjaxCommands . prototype . setDialogOption = function ( ajax , response , status ) {
var $dialog = $ ( response . selector ) ;
if ( $dialog . length ) {
$dialog . dialog ( 'option' , response . optionName , response . optionValue ) ;
}
} ;
/ * *
* Binds a listener on dialog creation to handle the cancel link .
*
* @ param { jQuery . Event } e
* @ param { Drupal . dialog ~ dialogDefinition } dialog
* @ param { jQuery } $element
* @ param { object } settings
* /
$ ( window ) . on ( 'dialog:aftercreate' , function ( e , dialog , $element , settings ) {
$element . on ( 'click.dialog' , '.dialog-cancel' , function ( e ) {
dialog . close ( 'cancel' ) ;
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
} ) ;
} ) ;
/ * *
* Removes all 'dialog' listeners .
*
* @ param { jQuery . Event } e
* @ param { Drupal . dialog ~ dialogDefinition } dialog
* @ param { jQuery } $element
* /
$ ( window ) . on ( 'dialog:beforeclose' , function ( e , dialog , $element ) {
$element . off ( '.dialog' ) ;
} ) ;
} ) ( jQuery , Drupal ) ;