2015-08-17 17:00:26 -07:00
/ * *
* @ file
* Machine name functionality .
* /
( function ( $ , Drupal , drupalSettings ) {
2015-10-21 21:44:50 -07:00
'use strict' ;
2015-08-17 17:00:26 -07:00
/ * *
* Attach the machine - readable name form element behavior .
*
* @ type { Drupal ~ behavior }
* /
Drupal . behaviors . machineName = {
/ * *
* Attaches the behavior .
*
* @ param { Element } context
* @ param { object } settings
* @ param { object } settings . machineName
* A list of elements to process , keyed by the HTML ID of the form
* element containing the human - readable value . Each element is an object
* defining the following properties :
* - target : The HTML ID of the machine name form element .
* - suffix : The HTML ID of a container to show the machine name preview
* in ( usually a field suffix after the human - readable name
* form element ) .
* - label : The label to show for the machine name preview .
* - replace _pattern : A regular expression ( without modifiers ) matching
* disallowed characters in the machine name ; e . g . , '[^a-z0-9]+' .
* - replace : A character to replace disallowed characters with ; e . g . ,
* '_' or '-' .
* - standalone : Whether the preview should stay in its own element
* rather than the suffix of the source element .
* - field _prefix : The # field _prefix of the form element .
* - field _suffix : The # field _suffix of the form element .
* /
attach : function ( context , settings ) {
var self = this ;
var $context = $ ( context ) ;
var timeout = null ;
var xhr = null ;
function clickEditHandler ( e ) {
var data = e . data ;
data . $wrapper . removeClass ( 'visually-hidden' ) ;
data . $target . trigger ( 'focus' ) ;
data . $suffix . hide ( ) ;
data . $source . off ( '.machineName' ) ;
}
function machineNameHandler ( e ) {
var data = e . data ;
var options = data . options ;
var baseValue = $ ( e . target ) . val ( ) ;
var rx = new RegExp ( options . replace _pattern , 'g' ) ;
var expected = baseValue . toLowerCase ( ) . replace ( rx , options . replace ) . substr ( 0 , options . maxlength ) ;
// Abort the last pending request because the label has changed and it
// is no longer valid.
if ( xhr && xhr . readystate !== 4 ) {
xhr . abort ( ) ;
xhr = null ;
}
// Wait 300 milliseconds since the last event to update the machine name
// i.e., after the user has stopped typing.
if ( timeout ) {
clearTimeout ( timeout ) ;
timeout = null ;
}
timeout = setTimeout ( function ( ) {
if ( baseValue . toLowerCase ( ) !== expected ) {
xhr = self . transliterate ( baseValue , options ) . done ( function ( machine ) {
self . showMachineName ( machine . substr ( 0 , options . maxlength ) , data ) ;
} ) ;
}
else {
self . showMachineName ( expected , data ) ;
}
} , 300 ) ;
}
Object . keys ( settings . machineName ) . forEach ( function ( source _id ) {
var machine = '' ;
var eventData ;
var options = settings . machineName [ source _id ] ;
var $source = $context . find ( source _id ) . addClass ( 'machine-name-source' ) . once ( 'machine-name' ) ;
var $target = $context . find ( options . target ) . addClass ( 'machine-name-target' ) ;
var $suffix = $context . find ( options . suffix ) ;
2015-10-08 11:40:12 -07:00
var $wrapper = $target . closest ( '.js-form-item' ) ;
2015-08-17 17:00:26 -07:00
// All elements have to exist.
if ( ! $source . length || ! $target . length || ! $suffix . length || ! $wrapper . length ) {
return ;
}
// Skip processing upon a form validation error on the machine name.
if ( $target . hasClass ( 'error' ) ) {
return ;
}
// Figure out the maximum length for the machine name.
options . maxlength = $target . attr ( 'maxlength' ) ;
// Hide the form item container of the machine name form element.
$wrapper . addClass ( 'visually-hidden' ) ;
// Determine the initial machine name value. Unless the machine name
// form element is disabled or not empty, the initial default value is
// based on the human-readable form element value.
if ( $target . is ( ':disabled' ) || $target . val ( ) !== '' ) {
machine = $target . val ( ) ;
}
else if ( $source . val ( ) !== '' ) {
machine = self . transliterate ( $source . val ( ) , options ) ;
}
// Append the machine name preview to the source field.
var $preview = $ ( '<span class="machine-name-value">' + options . field _prefix + Drupal . checkPlain ( machine ) + options . field _suffix + '</span>' ) ;
$suffix . empty ( ) ;
if ( options . label ) {
$suffix . append ( '<span class="machine-name-label">' + options . label + ': </span>' ) ;
}
$suffix . append ( $preview ) ;
// If the machine name cannot be edited, stop further processing.
if ( $target . is ( ':disabled' ) ) {
return ;
}
eventData = {
$source : $source ,
$target : $target ,
$suffix : $suffix ,
$wrapper : $wrapper ,
$preview : $preview ,
options : options
} ;
// If it is editable, append an edit link.
var $link = $ ( '<span class="admin-link"><button type="button" class="link">' + Drupal . t ( 'Edit' ) + '</button></span>' ) . on ( 'click' , eventData , clickEditHandler ) ;
$suffix . append ( $link ) ;
// Preview the machine name in realtime when the human-readable name
// changes, but only if there is no machine name yet; i.e., only upon
// initial creation, not when editing.
if ( $target . val ( ) === '' ) {
$source . on ( 'formUpdated.machineName' , eventData , machineNameHandler )
// Initialize machine name preview.
. trigger ( 'formUpdated.machineName' ) ;
}
// Add a listener for an invalid event on the machine name input
// to show its container and focus it.
$target . on ( 'invalid' , eventData , clickEditHandler ) ;
} ) ;
} ,
showMachineName : function ( machine , data ) {
var settings = data . options ;
// Set the machine name to the transliterated value.
if ( machine !== '' ) {
if ( machine !== settings . replace ) {
data . $target . val ( machine ) ;
data . $preview . html ( settings . field _prefix + Drupal . checkPlain ( machine ) + settings . field _suffix ) ;
}
data . $suffix . show ( ) ;
}
else {
data . $suffix . hide ( ) ;
data . $target . val ( machine ) ;
data . $preview . empty ( ) ;
}
} ,
/ * *
* Transliterate a human - readable name to a machine name .
*
* @ param { string } source
* A string to transliterate .
* @ param { object } settings
* The machine name settings for the corresponding field .
* @ param { string } settings . replace _pattern
* A regular expression ( without modifiers ) matching disallowed characters
* in the machine name ; e . g . , '[^a-z0-9]+' .
* @ param { string } settings . replace
* A character to replace disallowed characters with ; e . g . , '_' or '-' .
* @ param { number } settings . maxlength
* The maximum length of the machine name .
*
* @ return { jQuery }
* The transliterated source string .
* /
transliterate : function ( source , settings ) {
return $ . get ( Drupal . url ( 'machine_name/transliterate' ) , {
text : source ,
langcode : drupalSettings . langcode ,
replace _pattern : settings . replace _pattern ,
replace : settings . replace ,
lowercase : true
} ) ;
}
} ;
} ) ( jQuery , Drupal , drupalSettings ) ;