1/** 2 * @file layout.admin.js 3 * 4 * Behaviors for editing a layout. 5 */ 6 7(function ($) { 8 9"use strict"; 10 11/** 12 * Behavior for showing a list of layouts. 13 * 14 * Detect flexbox support for displaying our list of layouts with vertical 15 * height matching for each row of layout template icons. 16 */ 17Backdrop.behaviors.gridFloatFallback = { 18 attach: function() { 19 var $body = $('body'); 20 if (!$body.hasClass('grid-float-fallback-processed') && !Backdrop.featureDetect.flexbox()) { 21 $('head').append('<link rel="stylesheet" type="text/css" href="/core/modules/layout/css/grid-float.css">'); 22 $body.addClass('grid-float-fallback-processed'); 23 } 24 } 25}; 26 27})(jQuery); 28; 29(function ($) { 30 31/** 32 * Retrieves the summary for the first element. 33 */ 34$.fn.backdropGetSummary = function () { 35 var callback = this.data('summaryCallback'); 36 var returnValue = (this[0] && callback) ? callback(this[0]) : ''; 37 return typeof returnValue === 'string' ? returnValue.trim() : ''; 38}; 39 40/** 41 * Sets the summary for all matched elements. 42 * 43 * @param callback 44 * Either a function that will be called each time the summary is 45 * retrieved or a string (which is returned each time). 46 */ 47$.fn.backdropSetSummary = function (callback) { 48 var self = this; 49 50 // To facilitate things, the callback should always be a function. If it's 51 // not, we wrap it into an anonymous function which just returns the value. 52 if (typeof callback != 'function') { 53 var val = callback; 54 callback = function () { return val; }; 55 } 56 57 return this 58 .data('summaryCallback', callback) 59 // To prevent duplicate events, the handlers are first removed and then 60 // (re-)added. 61 .off('formUpdated.summary') 62 .on('formUpdated.summary', function () { 63 self.trigger('summaryUpdated'); 64 }) 65 // The actual summaryUpdated handler doesn't fire when the callback is 66 // changed, so we have to do this manually. 67 .trigger('summaryUpdated'); 68}; 69 70/** 71 * Sends a 'formUpdated' event each time a form element is modified. 72 */ 73Backdrop.behaviors.formUpdated = { 74 attach: function (context) { 75 // These events are namespaced so that we can remove them later. 76 var events = 'change.formUpdated click.formUpdated blur.formUpdated keyup.formUpdated'; 77 $(context) 78 // Since context could be an input element itself, it's added back to 79 // the jQuery object and filtered again. 80 .find(':input').addBack().filter(':input') 81 // To prevent duplicate events, the handlers are first removed and then 82 // (re-)added. 83 .off(events).on(events, function () { 84 $(this).trigger('formUpdated'); 85 }); 86 } 87}; 88 89/** 90 * Prevents consecutive form submissions of identical form values. 91 * 92 * Repetitive form submissions that would submit the identical form values are 93 * prevented, unless the form values are different from the previously 94 * submitted values. 95 * 96 * This is a simplified re-implementation of a user-agent behavior that should 97 * be natively supported by major web browsers, but at this time, only Firefox 98 * has a built-in protection. 99 * 100 * A form value-based approach ensures that the constraint is triggered for 101 * consecutive, identical form submissions only. Compared to that, a form 102 * button-based approach would (1) rely on [visible] buttons to exist where 103 * technically not required and (2) require more complex state management if 104 * there are multiple buttons in a form. 105 * 106 * This implementation is based on form-level submit events only, and relies on 107 * jQuery's serialize() method to determine submitted form values. As such, the 108 * following limitations exist: 109 * 110 * - Event handlers on form buttons that preventDefault() do not receive a 111 * double-submit protection. That is deemed to be fine, since such button 112 * events typically trigger reversible client-side or server-side operations 113 * that are local to the context of a form only. 114 * - Changed values in advanced form controls, such as file inputs, are not part 115 * of the form values being compared between consecutive form submits (due to 116 * limitations of jQuery.serialize()). That is deemed to be acceptable, 117 * because if the user forgot to attach a file, then the size of HTTP payload 118 * will most likely be small enough to be fully passed to the server endpoint 119 * within (milli)seconds. If a user mistakenly attached a wrong file and is
120 * technically versed enough to cancel the form submission (and HTTP payload) 121 * in order to attach a different file, then that edge-case is not supported 122 * here. 123 * 124 * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP 125 * standards, so excluded in this implementation. 126 */ 127Backdrop.behaviors.formSingleSubmit = { 128 attach: function () { 129 function onFormSubmit (e) { 130 // Prevent this from firing multiple times per request. 131 e.stopImmediatePropagation(); 132 if (e.isDefaultPrevented()) { 133 // Don't act on form submissions that have been prevented by other JS. 134 return; 135 } 136 var $form = $(e.currentTarget); 137 var formValues = $form.serialize(); 138 var previousValues = $form.attr('data-backdrop-form-submit-last'); 139 if (previousValues === formValues) { 140 e.preventDefault(); 141 } 142 else { 143 $form.attr('data-backdrop-form-submit-last', formValues); 144 } 145 } 146 147 $('body').once('form-single-submit') 148 .on('submit.singleSubmit', 'form:not([method~="GET"])', onFormSubmit); 149 150 } 151}; 152 153/** 154 * Prepopulate form fields with information from the visitor cookie. 155 */ 156Backdrop.behaviors.fillUserInfoFromCookie = { 157 attach: function (context, settings) { 158 $('form.user-info-from-cookie').once('user-info-from-cookie', function () { 159 var formContext = this; 160 $.each(['name', 'mail', 'homepage'], function () { 161 var $element = $('[name=' + this + ']', formContext); 162 var cookie = $.cookie('Backdrop.visitor.' + this); 163 if ($element.length && cookie) { 164 $element.val(cookie); 165 } 166 }); 167 }); 168 } 169}; 170 171})(jQuery); 172;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.