Mercurial > hg > cmmr2012-drupal-site
comparison core/misc/machine-name.es6.js @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 /** | |
2 * @file | |
3 * Machine name functionality. | |
4 */ | |
5 | |
6 (function ($, Drupal, drupalSettings) { | |
7 /** | |
8 * Attach the machine-readable name form element behavior. | |
9 * | |
10 * @type {Drupal~behavior} | |
11 * | |
12 * @prop {Drupal~behaviorAttach} attach | |
13 * Attaches machine-name behaviors. | |
14 */ | |
15 Drupal.behaviors.machineName = { | |
16 | |
17 /** | |
18 * Attaches the behavior. | |
19 * | |
20 * @param {Element} context | |
21 * The context for attaching the behavior. | |
22 * @param {object} settings | |
23 * Settings object. | |
24 * @param {object} settings.machineName | |
25 * A list of elements to process, keyed by the HTML ID of the form | |
26 * element containing the human-readable value. Each element is an object | |
27 * defining the following properties: | |
28 * - target: The HTML ID of the machine name form element. | |
29 * - suffix: The HTML ID of a container to show the machine name preview | |
30 * in (usually a field suffix after the human-readable name | |
31 * form element). | |
32 * - label: The label to show for the machine name preview. | |
33 * - replace_pattern: A regular expression (without modifiers) matching | |
34 * disallowed characters in the machine name; e.g., '[^a-z0-9]+'. | |
35 * - replace: A character to replace disallowed characters with; e.g., | |
36 * '_' or '-'. | |
37 * - standalone: Whether the preview should stay in its own element | |
38 * rather than the suffix of the source element. | |
39 * - field_prefix: The #field_prefix of the form element. | |
40 * - field_suffix: The #field_suffix of the form element. | |
41 */ | |
42 attach(context, settings) { | |
43 const self = this; | |
44 const $context = $(context); | |
45 let timeout = null; | |
46 let xhr = null; | |
47 | |
48 function clickEditHandler(e) { | |
49 const data = e.data; | |
50 data.$wrapper.removeClass('visually-hidden'); | |
51 data.$target.trigger('focus'); | |
52 data.$suffix.hide(); | |
53 data.$source.off('.machineName'); | |
54 } | |
55 | |
56 function machineNameHandler(e) { | |
57 const data = e.data; | |
58 const options = data.options; | |
59 const baseValue = $(e.target).val(); | |
60 | |
61 const rx = new RegExp(options.replace_pattern, 'g'); | |
62 const expected = baseValue.toLowerCase().replace(rx, options.replace).substr(0, options.maxlength); | |
63 | |
64 // Abort the last pending request because the label has changed and it | |
65 // is no longer valid. | |
66 if (xhr && xhr.readystate !== 4) { | |
67 xhr.abort(); | |
68 xhr = null; | |
69 } | |
70 | |
71 // Wait 300 milliseconds for Ajax request since the last event to update | |
72 // the machine name i.e., after the user has stopped typing. | |
73 if (timeout) { | |
74 clearTimeout(timeout); | |
75 timeout = null; | |
76 } | |
77 if (baseValue.toLowerCase() !== expected) { | |
78 timeout = setTimeout(() => { | |
79 xhr = self.transliterate(baseValue, options).done((machine) => { | |
80 self.showMachineName(machine.substr(0, options.maxlength), data); | |
81 }); | |
82 }, 300); | |
83 } | |
84 else { | |
85 self.showMachineName(expected, data); | |
86 } | |
87 } | |
88 | |
89 Object.keys(settings.machineName).forEach((sourceId) => { | |
90 let machine = ''; | |
91 const options = settings.machineName[sourceId]; | |
92 | |
93 const $source = $context.find(sourceId).addClass('machine-name-source').once('machine-name'); | |
94 const $target = $context.find(options.target).addClass('machine-name-target'); | |
95 const $suffix = $context.find(options.suffix); | |
96 const $wrapper = $target.closest('.js-form-item'); | |
97 // All elements have to exist. | |
98 if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) { | |
99 return; | |
100 } | |
101 // Skip processing upon a form validation error on the machine name. | |
102 if ($target.hasClass('error')) { | |
103 return; | |
104 } | |
105 // Figure out the maximum length for the machine name. | |
106 options.maxlength = $target.attr('maxlength'); | |
107 // Hide the form item container of the machine name form element. | |
108 $wrapper.addClass('visually-hidden'); | |
109 // Determine the initial machine name value. Unless the machine name | |
110 // form element is disabled or not empty, the initial default value is | |
111 // based on the human-readable form element value. | |
112 if ($target.is(':disabled') || $target.val() !== '') { | |
113 machine = $target.val(); | |
114 } | |
115 else if ($source.val() !== '') { | |
116 machine = self.transliterate($source.val(), options); | |
117 } | |
118 // Append the machine name preview to the source field. | |
119 const $preview = $(`<span class="machine-name-value">${options.field_prefix}${Drupal.checkPlain(machine)}${options.field_suffix}</span>`); | |
120 $suffix.empty(); | |
121 if (options.label) { | |
122 $suffix.append(`<span class="machine-name-label">${options.label}: </span>`); | |
123 } | |
124 $suffix.append($preview); | |
125 | |
126 // If the machine name cannot be edited, stop further processing. | |
127 if ($target.is(':disabled')) { | |
128 return; | |
129 } | |
130 | |
131 const eventData = { | |
132 $source, | |
133 $target, | |
134 $suffix, | |
135 $wrapper, | |
136 $preview, | |
137 options, | |
138 }; | |
139 // If it is editable, append an edit link. | |
140 const $link = $(`<span class="admin-link"><button type="button" class="link">${Drupal.t('Edit')}</button></span>`).on('click', eventData, clickEditHandler); | |
141 $suffix.append($link); | |
142 | |
143 // Preview the machine name in realtime when the human-readable name | |
144 // changes, but only if there is no machine name yet; i.e., only upon | |
145 // initial creation, not when editing. | |
146 if ($target.val() === '') { | |
147 $source.on('formUpdated.machineName', eventData, machineNameHandler) | |
148 // Initialize machine name preview. | |
149 .trigger('formUpdated.machineName'); | |
150 } | |
151 | |
152 // Add a listener for an invalid event on the machine name input | |
153 // to show its container and focus it. | |
154 $target.on('invalid', eventData, clickEditHandler); | |
155 }); | |
156 }, | |
157 | |
158 showMachineName(machine, data) { | |
159 const settings = data.options; | |
160 // Set the machine name to the transliterated value. | |
161 if (machine !== '') { | |
162 if (machine !== settings.replace) { | |
163 data.$target.val(machine); | |
164 data.$preview.html(settings.field_prefix + Drupal.checkPlain(machine) + settings.field_suffix); | |
165 } | |
166 data.$suffix.show(); | |
167 } | |
168 else { | |
169 data.$suffix.hide(); | |
170 data.$target.val(machine); | |
171 data.$preview.empty(); | |
172 } | |
173 }, | |
174 | |
175 /** | |
176 * Transliterate a human-readable name to a machine name. | |
177 * | |
178 * @param {string} source | |
179 * A string to transliterate. | |
180 * @param {object} settings | |
181 * The machine name settings for the corresponding field. | |
182 * @param {string} settings.replace_pattern | |
183 * A regular expression (without modifiers) matching disallowed characters | |
184 * in the machine name; e.g., '[^a-z0-9]+'. | |
185 * @param {string} settings.replace_token | |
186 * A token to validate the regular expression. | |
187 * @param {string} settings.replace | |
188 * A character to replace disallowed characters with; e.g., '_' or '-'. | |
189 * @param {number} settings.maxlength | |
190 * The maximum length of the machine name. | |
191 * | |
192 * @return {jQuery} | |
193 * The transliterated source string. | |
194 */ | |
195 transliterate(source, settings) { | |
196 return $.get(Drupal.url('machine_name/transliterate'), { | |
197 text: source, | |
198 langcode: drupalSettings.langcode, | |
199 replace_pattern: settings.replace_pattern, | |
200 replace_token: settings.replace_token, | |
201 replace: settings.replace, | |
202 lowercase: true, | |
203 }); | |
204 }, | |
205 }; | |
206 }(jQuery, Drupal, drupalSettings)); |