123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /**
- * @file
- * Attaches the behaviors for the Field UI module.
- */
-
- (function($) {
- Drupal.behaviors.fieldUIFieldOverview = {
- attach: function (context, settings) {
- $('table#field-overview', context).once('field-overview', function () {
- Drupal.fieldUIFieldOverview.attachUpdateSelects(this, settings);
- });
- }
- };
- Drupal.fieldUIFieldOverview = {
- /**
- * Implements dependent select dropdowns on the 'Manage fields' screen.
- */
- attachUpdateSelects: function(table, settings) {
- var widgetTypes = settings.fieldWidgetTypes;
- var fields = settings.fields;
- // Store the default text of widget selects.
- $('.widget-type-select', table).each(function () {
- this.initialValue = this.options[0].text;
- });
- // 'Field type' select updates its 'Widget' select.
- $('.field-type-select', table).each(function () {
- this.targetSelect = $('.widget-type-select', $(this).closest('tr'));
- $(this).bind('change keyup', function () {
- var selectedFieldType = this.options[this.selectedIndex].value;
- var options = (selectedFieldType in widgetTypes ? widgetTypes[selectedFieldType] : []);
- this.targetSelect.fieldUIPopulateOptions(options);
- });
- // Trigger change on initial pageload to get the right widget options
- // when field type comes pre-selected (on failed validation).
- $(this).trigger('change', false);
- });
- // 'Existing field' select updates its 'Widget' select and 'Label' textfield.
- $('.field-select', table).each(function () {
- this.targetSelect = $('.widget-type-select', $(this).closest('tr'));
- this.targetTextfield = $('.label-textfield', $(this).closest('tr'));
- this.targetTextfield
- .data('field_ui_edited', false)
- .bind('keyup', function (e) {
- $(this).data('field_ui_edited', $(this).val() != '');
- });
- $(this).bind('change keyup', function (e, updateText) {
- var updateText = (typeof updateText == 'undefined' ? true : updateText);
- var selectedField = this.options[this.selectedIndex].value;
- var selectedFieldType = (selectedField in fields ? fields[selectedField].type : null);
- var selectedFieldWidget = (selectedField in fields ? fields[selectedField].widget : null);
- var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []);
- this.targetSelect.fieldUIPopulateOptions(options, selectedFieldWidget);
- // Only overwrite the "Label" input if it has not been manually
- // changed, or if it is empty.
- if (updateText && !this.targetTextfield.data('field_ui_edited')) {
- this.targetTextfield.val(selectedField in fields ? fields[selectedField].label : '');
- }
- });
- // Trigger change on initial pageload to get the right widget options
- // and label when field type comes pre-selected (on failed validation).
- $(this).trigger('change', false);
- });
- }
- };
- /**
- * Populates options in a select input.
- */
- jQuery.fn.fieldUIPopulateOptions = function (options, selected) {
- return this.each(function () {
- var disabled = false;
- if (options.length == 0) {
- options = [this.initialValue];
- disabled = true;
- }
- // If possible, keep the same widget selected when changing field type.
- // This is based on textual value, since the internal value might be
- // different (options_buttons vs. node_reference_buttons).
- var previousSelectedText = this.options[this.selectedIndex].text;
- var html = '';
- jQuery.each(options, function (value, text) {
- // Figure out which value should be selected. The 'selected' param
- // takes precedence.
- var is_selected = ((typeof selected != 'undefined' && value == selected) || (typeof selected == 'undefined' && text == previousSelectedText));
- html += '<option value="' + value + '"' + (is_selected ? ' selected="selected"' : '') + '>' + text + '</option>';
- });
- $(this).html(html).attr('disabled', disabled ? 'disabled' : false);
- });
- };
- Drupal.behaviors.fieldUIDisplayOverview = {
- attach: function (context, settings) {
- $('table#field-display-overview', context).once('field-display-overview', function() {
- Drupal.fieldUIOverview.attach(this, settings.fieldUIRowsData, Drupal.fieldUIDisplayOverview);
- });
- }
- };
- Drupal.fieldUIOverview = {
- /**
- * Attaches the fieldUIOverview behavior.
- */
- attach: function (table, rowsData, rowHandlers) {
- var tableDrag = Drupal.tableDrag[table.id];
- // Add custom tabledrag callbacks.
- tableDrag.onDrop = this.onDrop;
- tableDrag.row.prototype.onSwap = this.onSwap;
- // Create row handlers.
- $('tr.draggable', table).each(function () {
- // Extract server-side data for the row.
- var row = this;
- if (row.id in rowsData) {
- var data = rowsData[row.id];
- data.tableDrag = tableDrag;
- // Create the row handler, make it accessible from the DOM row element.
- var rowHandler = new rowHandlers[data.rowHandler](row, data);
- $(row).data('fieldUIRowHandler', rowHandler);
- }
- });
- },
- /**
- * Event handler to be attached to form inputs triggering a region change.
- */
- onChange: function () {
- var $trigger = $(this);
- var row = $trigger.closest('tr').get(0);
- var rowHandler = $(row).data('fieldUIRowHandler');
- var refreshRows = {};
- refreshRows[rowHandler.name] = $trigger.get(0);
- // Handle region change.
- var region = rowHandler.getRegion();
- if (region != rowHandler.region) {
- // Remove parenting.
- $('select.field-parent', row).val('');
- // Let the row handler deal with the region change.
- $.extend(refreshRows, rowHandler.regionChange(region));
- // Update the row region.
- rowHandler.region = region;
- }
- // Ajax-update the rows.
- Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows);
- },
- /**
- * Lets row handlers react when a row is dropped into a new region.
- */
- onDrop: function () {
- var dragObject = this;
- var row = dragObject.rowObject.element;
- var rowHandler = $(row).data('fieldUIRowHandler');
- if (rowHandler !== undefined) {
- var regionRow = $(row).prevAll('tr.region-message').get(0);
- var region = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
- if (region != rowHandler.region) {
- // Let the row handler deal with the region change.
- refreshRows = rowHandler.regionChange(region);
- // Update the row region.
- rowHandler.region = region;
- // Ajax-update the rows.
- Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows);
- }
- }
- },
- /**
- * Refreshes placeholder rows in empty regions while a row is being dragged.
- *
- * Copied from block.js.
- *
- * @param table
- * The table DOM element.
- * @param rowObject
- * The tableDrag rowObject for the row being dragged.
- */
- onSwap: function (draggedRow) {
- var rowObject = this;
- $('tr.region-message', rowObject.table).each(function () {
- // If the dragged row is in this region, but above the message row, swap
- // it down one space.
- if ($(this).prev('tr').get(0) == rowObject.group[rowObject.group.length - 1]) {
- // Prevent a recursion problem when using the keyboard to move rows up.
- if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
- rowObject.swap('after', this);
- }
- }
- // This region has become empty.
- if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').length == 0) {
- $(this).removeClass('region-populated').addClass('region-empty');
- }
- // This region has become populated.
- else if ($(this).is('.region-empty')) {
- $(this).removeClass('region-empty').addClass('region-populated');
- }
- });
- },
- /**
- * Triggers Ajax refresh of selected rows.
- *
- * The 'format type' selects can trigger a series of changes in child rows.
- * The #ajax behavior is therefore not attached directly to the selects, but
- * triggered manually through a hidden #ajax 'Refresh' button.
- *
- * @param rows
- * A hash object, whose keys are the names of the rows to refresh (they
- * will receive the 'ajax-new-content' effect on the server side), and
- * whose values are the DOM element in the row that should get an Ajax
- * throbber.
- */
- AJAXRefreshRows: function (rows) {
- // Separate keys and values.
- var rowNames = [];
- var ajaxElements = [];
- $.each(rows, function (rowName, ajaxElement) {
- rowNames.push(rowName);
- ajaxElements.push(ajaxElement);
- });
- if (rowNames.length) {
- // Add a throbber next each of the ajaxElements.
- var $throbber = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber"> </div></div>');
- $(ajaxElements)
- .addClass('progress-disabled')
- .after($throbber);
- // Fire the Ajax update.
- $('input[name=refresh_rows]').val(rowNames.join(' '));
- $('input#edit-refresh').mousedown();
- // Disabled elements do not appear in POST ajax data, so we mark the
- // elements disabled only after firing the request.
- $(ajaxElements).attr('disabled', true);
- }
- }
- };
- /**
- * Row handlers for the 'Manage display' screen.
- */
- Drupal.fieldUIDisplayOverview = {};
- /**
- * Constructor for a 'field' row handler.
- *
- * This handler is used for both fields and 'extra fields' rows.
- *
- * @param row
- * The row DOM element.
- * @param data
- * Additional data to be populated in the constructed object.
- */
- Drupal.fieldUIDisplayOverview.field = function (row, data) {
- this.row = row;
- this.name = data.name;
- this.region = data.region;
- this.tableDrag = data.tableDrag;
- // Attach change listener to the 'formatter type' select.
- this.$formatSelect = $('select.field-formatter-type', row);
- this.$formatSelect.change(Drupal.fieldUIOverview.onChange);
- return this;
- };
- Drupal.fieldUIDisplayOverview.field.prototype = {
- /**
- * Returns the region corresponding to the current form values of the row.
- */
- getRegion: function () {
- return (this.$formatSelect.val() == 'hidden') ? 'hidden' : 'visible';
- },
- /**
- * Reacts to a row being changed regions.
- *
- * This function is called when the row is moved to a different region, as a
- * result of either :
- * - a drag-and-drop action (the row's form elements then probably need to be
- * updated accordingly)
- * - user input in one of the form elements watched by the
- * Drupal.fieldUIOverview.onChange change listener.
- *
- * @param region
- * The name of the new region for the row.
- * @return
- * A hash object indicating which rows should be Ajax-updated as a result
- * of the change, in the format expected by
- * Drupal.displayOverview.AJAXRefreshRows().
- */
- regionChange: function (region) {
- // When triggered by a row drag, the 'format' select needs to be adjusted
- // to the new region.
- var currentValue = this.$formatSelect.val();
- switch (region) {
- case 'visible':
- if (currentValue == 'hidden') {
- // Restore the formatter back to the default formatter. Pseudo-fields do
- // not have default formatters, we just return to 'visible' for those.
- var value = (this.defaultFormatter != undefined) ? this.defaultFormatter : 'visible';
- }
- break;
- default:
- var value = 'hidden';
- break;
- }
- if (value != undefined) {
- this.$formatSelect.val(value);
- }
- var refreshRows = {};
- refreshRows[this.name] = this.$formatSelect.get(0);
- return refreshRows;
- }
- };
- })(jQuery);
|