adding all weblabels from weblabels.fsf.org
[weblabels.fsf.org.git] / defectivebydesign.org / 20130322 / files-new-min / modules / field_ui / field_ui.js
CommitLineData
5a920362 1/**
2 * @file
3 * Attaches the behaviors for the Field UI module.
4 */
5
6(function($) {
7
8Drupal.behaviors.fieldUIFieldOverview = {
9 attach: function (context, settings) {
10 $('table#field-overview', context).once('field-overview', function () {
11 Drupal.fieldUIFieldOverview.attachUpdateSelects(this, settings);
12 });
13 }
14};
15
16Drupal.fieldUIFieldOverview = {
17 /**
18 * Implements dependent select dropdowns on the 'Manage fields' screen.
19 */
20 attachUpdateSelects: function(table, settings) {
21 var widgetTypes = settings.fieldWidgetTypes;
22 var fields = settings.fields;
23
24 // Store the default text of widget selects.
25 $('.widget-type-select', table).each(function () {
26 this.initialValue = this.options[0].text;
27 });
28
29 // 'Field type' select updates its 'Widget' select.
30 $('.field-type-select', table).each(function () {
31 this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
32
33 $(this).bind('change keyup', function () {
34 var selectedFieldType = this.options[this.selectedIndex].value;
35 var options = (selectedFieldType in widgetTypes ? widgetTypes[selectedFieldType] : []);
36 this.targetSelect.fieldUIPopulateOptions(options);
37 });
38
39 // Trigger change on initial pageload to get the right widget options
40 // when field type comes pre-selected (on failed validation).
41 $(this).trigger('change', false);
42 });
43
44 // 'Existing field' select updates its 'Widget' select and 'Label' textfield.
45 $('.field-select', table).each(function () {
46 this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
47 this.targetTextfield = $('.label-textfield', $(this).parents('tr').eq(0));
48
49 $(this).bind('change keyup', function (e, updateText) {
50 var updateText = (typeof updateText == 'undefined' ? true : updateText);
51 var selectedField = this.options[this.selectedIndex].value;
52 var selectedFieldType = (selectedField in fields ? fields[selectedField].type : null);
53 var selectedFieldWidget = (selectedField in fields ? fields[selectedField].widget : null);
54 var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []);
55 this.targetSelect.fieldUIPopulateOptions(options, selectedFieldWidget);
56
57 if (updateText) {
58 $(this.targetTextfield).attr('value', (selectedField in fields ? fields[selectedField].label : ''));
59 }
60 });
61
62 // Trigger change on initial pageload to get the right widget options
63 // and label when field type comes pre-selected (on failed validation).
64 $(this).trigger('change', false);
65 });
66 }
67};
68
69/**
70 * Populates options in a select input.
71 */
72jQuery.fn.fieldUIPopulateOptions = function (options, selected) {
73 return this.each(function () {
74 var disabled = false;
75 if (options.length == 0) {
76 options = [this.initialValue];
77 disabled = true;
78 }
79
80 // If possible, keep the same widget selected when changing field type.
81 // This is based on textual value, since the internal value might be
82 // different (options_buttons vs. node_reference_buttons).
83 var previousSelectedText = this.options[this.selectedIndex].text;
84
85 var html = '';
86 jQuery.each(options, function (value, text) {
87 // Figure out which value should be selected. The 'selected' param
88 // takes precedence.
89 var is_selected = ((typeof selected != 'undefined' && value == selected) || (typeof selected == 'undefined' && text == previousSelectedText));
90 html += '<option value="' + value + '"' + (is_selected ? ' selected="selected"' : '') + '>' + text + '</option>';
91 });
92
93 $(this).html(html).attr('disabled', disabled ? 'disabled' : '');
94 });
95};
96
97Drupal.behaviors.fieldUIDisplayOverview = {
98 attach: function (context, settings) {
99 $('table#field-display-overview', context).once('field-display-overview', function() {
100 Drupal.fieldUIOverview.attach(this, settings.fieldUIRowsData, Drupal.fieldUIDisplayOverview);
101 });
102 }
103};
104
105Drupal.fieldUIOverview = {
106 /**
107 * Attaches the fieldUIOverview behavior.
108 */
109 attach: function (table, rowsData, rowHandlers) {
110 var tableDrag = Drupal.tableDrag[table.id];
111
112 // Add custom tabledrag callbacks.
113 tableDrag.onDrop = this.onDrop;
114 tableDrag.row.prototype.onSwap = this.onSwap;
115
116 // Create row handlers.
117 $('tr.draggable', table).each(function () {
118 // Extract server-side data for the row.
119 var row = this;
120 if (row.id in rowsData) {
121 var data = rowsData[row.id];
122 data.tableDrag = tableDrag;
123
124 // Create the row handler, make it accessible from the DOM row element.
125 var rowHandler = new rowHandlers[data.rowHandler](row, data);
126 $(row).data('fieldUIRowHandler', rowHandler);
127 }
128 });
129 },
130
131 /**
132 * Event handler to be attached to form inputs triggering a region change.
133 */
134 onChange: function () {
135 var $trigger = $(this);
136 var row = $trigger.parents('tr:first').get(0);
137 var rowHandler = $(row).data('fieldUIRowHandler');
138
139 var refreshRows = {};
140 refreshRows[rowHandler.name] = $trigger.get(0);
141
142 // Handle region change.
143 var region = rowHandler.getRegion();
144 if (region != rowHandler.region) {
145 // Remove parenting.
146 $('select.field-parent', row).val('');
147 // Let the row handler deal with the region change.
148 $.extend(refreshRows, rowHandler.regionChange(region));
149 // Update the row region.
150 rowHandler.region = region;
151 }
152
153 // Ajax-update the rows.
154 Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows);
155 },
156
157 /**
158 * Lets row handlers react when a row is dropped into a new region.
159 */
160 onDrop: function () {
161 var dragObject = this;
162 var row = dragObject.rowObject.element;
163 var rowHandler = $(row).data('fieldUIRowHandler');
164 if (rowHandler !== undefined) {
165 var regionRow = $(row).prevAll('tr.region-message').get(0);
166 var region = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
167
168 if (region != rowHandler.region) {
169 // Let the row handler deal with the region change.
170 refreshRows = rowHandler.regionChange(region);
171 // Update the row region.
172 rowHandler.region = region;
173 // Ajax-update the rows.
174 Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows);
175 }
176 }
177 },
178
179 /**
180 * Refreshes placeholder rows in empty regions while a row is being dragged.
181 *
182 * Copied from block.js.
183 *
184 * @param table
185 * The table DOM element.
186 * @param rowObject
187 * The tableDrag rowObject for the row being dragged.
188 */
189 onSwap: function (draggedRow) {
190 var rowObject = this;
191 $('tr.region-message', rowObject.table).each(function () {
192 // If the dragged row is in this region, but above the message row, swap
193 // it down one space.
194 if ($(this).prev('tr').get(0) == rowObject.group[rowObject.group.length - 1]) {
195 // Prevent a recursion problem when using the keyboard to move rows up.
196 if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
197 rowObject.swap('after', this);
198 }
199 }
200 // This region has become empty.
201 if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').length == 0) {
202 $(this).removeClass('region-populated').addClass('region-empty');
203 }
204 // This region has become populated.
205 else if ($(this).is('.region-empty')) {
206 $(this).removeClass('region-empty').addClass('region-populated');
207 }
208 });
209 },
210
211 /**
212 * Triggers Ajax refresh of selected rows.
213 *
214 * The 'format type' selects can trigger a series of changes in child rows.
215 * The #ajax behavior is therefore not attached directly to the selects, but
216 * triggered manually through a hidden #ajax 'Refresh' button.
217 *
218 * @param rows
219 * A hash object, whose keys are the names of the rows to refresh (they
220 * will receive the 'ajax-new-content' effect on the server side), and
221 * whose values are the DOM element in the row that should get an Ajax
222 * throbber.
223 */
224 AJAXRefreshRows: function (rows) {
225 // Separate keys and values.
226 var rowNames = [];
227 var ajaxElements = [];
228 $.each(rows, function (rowName, ajaxElement) {
229 rowNames.push(rowName);
230 ajaxElements.push(ajaxElement);
231 });
232
233 if (rowNames.length) {
234 // Add a throbber next each of the ajaxElements.
235 var $throbber = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
236 $(ajaxElements)
237 .addClass('progress-disabled')
238 .after($throbber);
239
240 // Fire the Ajax update.
241 $('input[name=refresh_rows]').val(rowNames.join(' '));
242 $('input#edit-refresh').mousedown();
243
244 // Disabled elements do not appear in POST ajax data, so we mark the
245 // elements disabled only after firing the request.
246 $(ajaxElements).attr('disabled', true);
247 }
248 }
249};
250
251
252/**
253 * Row handlers for the 'Manage display' screen.
254 */
255Drupal.fieldUIDisplayOverview = {};
256
257/**
258 * Constructor for a 'field' row handler.
259 *
260 * This handler is used for both fields and 'extra fields' rows.
261 *
262 * @param row
263 * The row DOM element.
264 * @param data
265 * Additional data to be populated in the constructed object.
266 */
267Drupal.fieldUIDisplayOverview.field = function (row, data) {
268 this.row = row;
269 this.name = data.name;
270 this.region = data.region;
271 this.tableDrag = data.tableDrag;
272
273 // Attach change listener to the 'formatter type' select.
274 this.$formatSelect = $('select.field-formatter-type', row);
275 this.$formatSelect.change(Drupal.fieldUIOverview.onChange);
276
277 return this;
278};
279
280Drupal.fieldUIDisplayOverview.field.prototype = {
281 /**
282 * Returns the region corresponding to the current form values of the row.
283 */
284 getRegion: function () {
285 return (this.$formatSelect.val() == 'hidden') ? 'hidden' : 'visible';
286 },
287
288 /**
289 * Reacts to a row being changed regions.
290 *
291 * This function is called when the row is moved to a different region, as a
292 * result of either :
293 * - a drag-and-drop action (the row's form elements then probably need to be
294 * updated accordingly)
295 * - user input in one of the form elements watched by the
296 * Drupal.fieldUIOverview.onChange change listener.
297 *
298 * @param region
299 * The name of the new region for the row.
300 * @return
301 * A hash object indicating which rows should be Ajax-updated as a result
302 * of the change, in the format expected by
303 * Drupal.displayOverview.AJAXRefreshRows().
304 */
305 regionChange: function (region) {
306
307 // When triggered by a row drag, the 'format' select needs to be adjusted
308 // to the new region.
309 var currentValue = this.$formatSelect.val();
310 switch (region) {
311 case 'visible':
312 if (currentValue == 'hidden') {
313 // Restore the formatter back to the default formatter. Pseudo-fields do
314 // not have default formatters, we just return to 'visible' for those.
315 var value = (this.defaultFormatter != undefined) ? this.defaultFormatter : 'visible';
316 }
317 break;
318
319 default:
320 var value = 'hidden';
321 break;
322 }
323 if (value != undefined) {
324 this.$formatSelect.val(value);
325 }
326
327 var refreshRows = {};
328 refreshRows[this.name] = this.$formatSelect.get(0);
329
330 return refreshRows;
331 }
332};
333
334})(jQuery);