Ticket #42022: 42022.4.diff
File 42022.4.diff, 43.1 KB (added by , 7 years ago) |
---|
-
src/wp-admin/css/customize-controls.css
diff --git src/wp-admin/css/customize-controls.css src/wp-admin/css/customize-controls.css index 09302a8a34..618619fcbd 100644
body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 148 148 } 149 149 150 150 #customize-controls .date-input:invalid { 151 border-color: red; 152 } 153 154 .date-time-fields .month-field { 155 width: 79px; 156 } 157 158 .date-time-fields .day-field, 159 .date-time-fields .hour-field, 160 .date-time-fields .minute-field { 161 width: 46px; 162 } 163 164 .date-time-fields .year-field { 165 width: 60px; 166 } 167 168 .date-time-fields .am-pm-field { 169 width: 53px; 151 border-color: #dc3232; 170 152 } 171 153 172 154 #customize-control-changeset_status label { … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 200 182 201 183 .customize-copy-preview-link:before, 202 184 .customize-copy-preview-link:after { 203 content: '';185 content: ""; 204 186 height: 28px; 205 187 position: absolute; 206 188 background: #ffffff; … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 225 207 border-left: none; 226 208 border-right: none; 227 209 text-indent: -999px; 228 color: white;210 color: #fff; 229 211 } 230 212 231 213 #customize-control-changeset_preview_link label { … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 233 215 display: block; 234 216 } 235 217 236 #customize-control-changeset_preview_link a .preview-control-element{218 #customize-control-changeset_preview_link a { 237 219 display: inline-block; 238 220 position: absolute; 239 221 white-space: nowrap; … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 244 226 text-decoration: none; 245 227 } 246 228 247 #customize-control-changeset_preview_link a. preview-control-element.disabled,248 #customize-control-changeset_preview_link a. preview-control-element.disabled:active,249 #customize-control-changeset_preview_link a. preview-control-element.disabled:focus,250 #customize-control-changeset_preview_link a. preview-control-element.disabled:visited {229 #customize-control-changeset_preview_link a.disabled, 230 #customize-control-changeset_preview_link a.disabled:active, 231 #customize-control-changeset_preview_link a.disabled:focus, 232 #customize-control-changeset_preview_link a.disabled:visited { 251 233 color: black; 252 234 opacity: 0.4; 253 235 cursor: default; … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 268 250 padding-bottom:10px; 269 251 } 270 252 271 . date-time-fields label,272 . date-time-fields .date-time-separator {253 .customize-control.customize-control-date_time .date-time-fields .date-input, 254 .customize-control.customize-control-date_time .date-time-fields .date-time-separator { 273 255 float: left; 274 margin-right:5px; 256 margin-right: 5px; 257 } 258 259 .date-time-fields .date-input.month { 260 width: auto; 261 margin: 0; 262 } 263 264 .date-time-fields .date-input.day, 265 .date-time-fields .date-input.hour, 266 .date-time-fields .date-input.minute { 267 width: 46px; 268 } 269 270 .date-time-fields .date-input.year { 271 width: 60px; 272 } 273 274 .date-time-fields .date-input.meridian { 275 width: auto; 276 margin: 0; 275 277 } 276 278 277 279 .date-time-fields .date-time-separator { … … body.outer-section-open .wp-full-overlay.expanded .wp-full-overlay-main { 279 281 } 280 282 281 283 .date-time-fields .time-row { 282 padding-top: 12px;284 margin-top: 12px; 283 285 } 284 286 285 287 .date-time-fields .date-timezone { … … p.customize-section-description { 1010 1012 } 1011 1013 1012 1014 .customize-control-dropdown-pages .new-content-item .create-item-input.invalid { 1013 border: 1px solid # f00;1015 border: 1px solid #dc3232; 1014 1016 } 1015 1017 1016 1018 .customize-control-dropdown-pages .add-new-toggle { … … p.customize-section-description { 1136 1138 margin-bottom: 0; 1137 1139 } 1138 1140 #customize-control-show_on_front.has-error .customize-control-notifications-container { 1139 margin-top: 12px;1141 margin-top: 12px; 1140 1142 } 1141 1143 1142 1144 /** … … p.customize-section-description { 1321 1323 content: ''; 1322 1324 position: absolute; 1323 1325 height: auto; 1324 top: 0; left: 0; bottom: 0; right: 0; 1326 top: 0; 1327 left: 0; 1328 bottom: 0; 1329 right: 0; 1325 1330 border: 4px solid #00a0d2; 1326 1331 border-radius: 2px; 1327 1332 } … … body.adding-widget .add-new-widget:before, 2659 2664 height: 39px; 2660 2665 } 2661 2666 2662 .date-time-fields . month-field{2667 .date-time-fields .date-input.month { 2663 2668 width: 79px; 2664 2669 } 2665 2670 2666 .date-time-fields .da y-field,2667 .date-time-fields . hour-field,2668 .date-time-fields . minute-field{2671 .date-time-fields .date-input.day, 2672 .date-time-fields .date-input.hour, 2673 .date-time-fields .date-input.minute { 2669 2674 width: 55px; 2670 2675 } 2671 2676 2672 .date-time-fields . year-field{2677 .date-time-fields .date-input.year { 2673 2678 width: 80px; 2674 2679 } 2675 2680 2681 .date-time-fields .date-time-separator, 2676 2682 .date-time-fields .date-timezone { 2677 2683 line-height: 3.2; 2678 2684 } 2685 2679 2686 .wp-core-ui.wp-customizer .button { 2680 2687 margin-top: 12px; 2681 2688 } -
src/wp-admin/css/customize-nav-menus.css
diff --git src/wp-admin/css/customize-nav-menus.css src/wp-admin/css/customize-nav-menus.css index f9d8f81703..36138ca2a3 100644
132 132 133 133 .customize-control input.menu-name-field { 134 134 width: 100%; /* Override the 98% default for customizer inputs, to align with the size of menu items. */ 135 margin: 12px 0;136 135 } 137 136 138 137 .wp-customizer .menu-item .item-edit { -
src/wp-admin/js/customize-controls.js
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js index 70dff7403d..d6a4fbc3f4 100644
4908 4908 */ 4909 4909 api.DateTimeControl = api.Control.extend({ 4910 4910 4911 dateInputs: {},4912 inputElements: {},4913 invalidDate: false,4914 4915 4911 /** 4916 4912 * Initialize behaviors. 4917 4913 * … … 4921 4917 ready: function ready() { 4922 4918 var control = this; 4923 4919 4924 _.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'updateMinutesForHour' ); 4920 control.inputElements = {}; 4921 control.invalidDate = false; 4925 4922 4926 control.dateInputs = control.container.find( '.date-input' );4923 _.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'updateMinutesForHour', 'populateDateInputs' ); 4927 4924 4928 4925 // @todo This needs https://core.trac.wordpress.org/ticket/37964 4929 4926 if ( ! control.setting ) { 4930 4927 control.setting = new api.Value(); 4931 4928 } 4932 4929 4930 // @todo Should this be? Default should be on client. The default value should be in the setting itself. 4933 4931 if ( ! control.setting.get() && control.params.defaultValue ) { 4934 4932 control.setting.set( control.params.defaultValue ); 4935 4933 } 4936 4934 4937 control. dateInputs.each( function() {4935 control.container.find( '.date-input' ).each( function() { 4938 4936 var input = $( this ), component, element; 4939 4937 component = input.data( 'component' ); 4940 4938 element = new api.Element( input ); 4941 element.validate = function( value ) { 4942 return _.contains( [ 'am', 'pm' ], value ) ? value : parseInt( value, 10 ); 4943 }; 4939 if ( 'meridian' === component ) { 4940 element.validate = function( value ) { 4941 if ( 'am' !== value && 'pm' !== value ) { 4942 return null; 4943 } 4944 return value; 4945 }; 4946 } else { 4947 element.validate = function( value ) { 4948 var val = parseInt( value, 10 ); 4949 if ( isNaN( val ) ) { 4950 return null; 4951 } 4952 return val; 4953 }; 4954 } 4955 element.bind( control.populateSetting ); 4944 4956 control.inputElements[ component ] = element; 4945 4957 control.elements.push( element ); 4946 4958 } ); 4947 4959 4948 control.dateInputs.on( 'input', control.populateSetting );4949 4960 control.inputElements.month.bind( control.updateDaysForMonth ); 4950 4961 control.inputElements.year.bind( control.updateDaysForMonth ); 4951 control.inputElements.hour.bind( control.updateMinutesForHour ); 4962 if ( control.params.includeTime ) { 4963 control.inputElements.hour.bind( control.updateMinutesForHour ); 4964 } 4952 4965 control.populateDateInputs(); 4966 control.setting.bind( control.populateDateInputs ); 4953 4967 }, 4954 4968 4955 4969 /** 4956 4970 * Parse datetime string. 4957 4971 * 4958 4972 * @since 4.9.0 4959 * @param {string} datetime Date/Time string. Accepts Y-m-d H:i:s format.4960 * @param { boolean} twelveHourFormat If twelve hour format array is required.4973 * 4974 * @param {string} datetime - Date/Time string. Accepts Y-m-d[ H:i[:s]] format. 4961 4975 * @returns {object|null} Returns object containing date components or null if parse error. 4962 4976 */ 4963 parseDateTime: function parseDateTime( datetime , twelveHourFormat) {4964 var matches, date, midDayHour = 12;4977 parseDateTime: function parseDateTime( datetime ) { 4978 var control = this, matches, date, midDayHour = 12; 4965 4979 4966 4980 if ( datetime ) { 4967 matches = datetime.match( /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/ );4981 matches = datetime.match( /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/ ); 4968 4982 } 4969 4983 4970 4984 if ( ! matches ) { … … 4977 4991 year: matches.shift(), 4978 4992 month: matches.shift(), 4979 4993 day: matches.shift(), 4980 hour: matches.shift() ,4981 minute: matches.shift() ,4982 second: matches.shift() 4994 hour: matches.shift() || '00', 4995 minute: matches.shift() || '00', 4996 second: matches.shift() || '00' 4983 4997 }; 4984 4998 4985 if ( twelveHourFormat ) {4999 if ( control.params.includeTime && control.params.twelveHourFormat ) { 4986 5000 date.hour = parseInt( date.hour, 10 ); 4987 date. ampm= date.hour >= midDayHour ? 'pm' : 'am';5001 date.meridian = date.hour >= midDayHour ? 'pm' : 'am'; 4988 5002 date.hour = date.hour % midDayHour ? String( date.hour % midDayHour ) : String( midDayHour ); 4989 delete date.second; 5003 delete date.second; // @todo Why only if twelveHourFormat? 4990 5004 } 4991 5005 4992 5006 return date; … … 4999 5013 * @return {boolean} If date input fields has error. 5000 5014 */ 5001 5015 validateInputs: function validateInputs() { 5002 var control = this, errorMessage ;5016 var control = this, errorMessage, components; 5003 5017 5004 5018 control.invalidDate = false; 5005 5019 5006 _.each( [ 'day', 'hour', 'year', 'minute' ], function( component ) { 5007 var element, el, max, min, maxLength, value; 5020 components = [ 'year', 'day' ]; 5021 if ( control.params.includeTime ) { 5022 components.push( 'hour', 'minute' ); 5023 } 5024 5025 _.each( components, function( component ) { 5026 var element, el, max, min, value; 5008 5027 5009 5028 if ( ! control.invalidDate ) { 5010 5029 element = control.inputElements[ component ]; 5011 5030 el = element.element.get( 0 ); 5012 5031 max = parseInt( element.element.attr( 'max' ), 10 ); 5013 5032 min = parseInt( element.element.attr( 'min' ), 10 ); 5014 maxLength = parseInt( element.element.attr( 'maxlength' ), 10 );5015 5033 value = element(); 5016 control.invalidDate = value > max || value < min || String( value ).length > maxLength;5034 control.invalidDate = value > max || value < min; 5017 5035 errorMessage = control.invalidDate ? api.l10n.invalid + ' ' + component : ''; 5018 5036 5019 5037 el.setCustomValidity( errorMessage ); 5020 _.result( el, 'reportValidity' ); 5038 if ( ! control.section() || api.section.has( control.section() ) && api.section( control.section() ).expanded() ) { 5039 _.result( el, 'reportValidity' ); 5040 } 5021 5041 } 5022 5042 } ); 5023 5043 … … 5056 5076 updateMinutesForHour: function updateMinutesForHour() { 5057 5077 var control = this, maxHours = 24, minuteEl; 5058 5078 5059 if ( control.inputElements. ampm) {5079 if ( control.inputElements.meridian ) { 5060 5080 return; 5061 5081 } 5062 5082 … … 5065 5085 if ( maxHours === control.inputElements.hour() ) { 5066 5086 control.inputElements.minute( 0 ); 5067 5087 minuteEl.data( 'default-max', minuteEl.attr( 'max' ) ); 5068 minuteEl.data( 'default-maxlength', minuteEl.attr( 'maxlength' ) );5069 5088 minuteEl.attr( 'max', '0' ); 5070 5089 } else if ( minuteEl.data( 'default-max' ) ) { 5071 5090 minuteEl.attr( 'max', minuteEl.data( 'default-max' ) ); 5072 minuteEl.attr( 'maxlength', minuteEl.data( 'maxlength' ) );5073 5091 } 5074 5092 }, 5075 5093 … … 5121 5139 return value; 5122 5140 }; 5123 5141 5124 hourInTwentyFourHourFormat = control.inputElements.ampm ? control.convertHourToTwentyFourHourFormat( control.inputElements.hour(), control.inputElements.ampm() ) : control.inputElements.hour(); 5125 dateFormat = [ 'year', '-', 'month', '-', 'day', ' ', pad( hourInTwentyFourHourFormat, 2 ), ':', 'minute', ':', '00' ]; 5142 dateFormat = [ 'year', '-', 'month', '-', 'day' ]; 5143 if ( control.params.includeTime ) { 5144 hourInTwentyFourHourFormat = control.inputElements.meridian ? control.convertHourToTwentyFourHourFormat( control.inputElements.hour(), control.inputElements.meridian() ) : control.inputElements.hour(); 5145 dateFormat = dateFormat.concat( [ ' ', pad( hourInTwentyFourHourFormat, 2 ), ':', 'minute', ':', '00' ] ); 5146 } 5126 5147 5127 5148 _.each( dateFormat, function( component ) { 5128 5149 date += control.inputElements[ component ] ? getElementValue( component ) : component; … … 5146 5167 * Convert hour in twelve hour format to twenty four hour format. 5147 5168 * 5148 5169 * @since 4.9.0 5149 * @param {string} hourInTwelveHourFormat Hour in twelve hour format.5150 * @param {string} ampm am/pm5151 * @return {string} Hour in twenty four hour format.5170 * @param {string} hourInTwelveHourFormat - Hour in twelve hour format. 5171 * @param {string} meridian - Either 'am' or 'pm'. 5172 * @returns {string} Hour in twenty four hour format. 5152 5173 */ 5153 convertHourToTwentyFourHourFormat: function convertHour( hourInTwelveHourFormat, ampm) {5174 convertHourToTwentyFourHourFormat: function convertHour( hourInTwelveHourFormat, meridian ) { 5154 5175 var hourInTwentyFourHourFormat, hour, midDayHour = 12; 5155 5176 5156 5177 hour = parseInt( hourInTwelveHourFormat, 10 ); 5178 if ( isNaN( hour ) ) { 5179 return ''; 5180 } 5157 5181 5158 if ( 'pm' === ampm&& hour < midDayHour ) {5182 if ( 'pm' === meridian && hour < midDayHour ) { 5159 5183 hourInTwentyFourHourFormat = hour + midDayHour; 5160 } else if ( 'am' === ampm&& midDayHour === hour ) {5184 } else if ( 'am' === meridian && midDayHour === hour ) { 5161 5185 hourInTwentyFourHourFormat = hour - midDayHour; 5162 5186 } else { 5163 5187 hourInTwentyFourHourFormat = hour; … … 5175 5199 populateDateInputs: function populateDateInputs() { 5176 5200 var control = this, parsed; 5177 5201 5178 parsed = control.parseDateTime( control.setting.get() , control.params.twelveHourFormat);5202 parsed = control.parseDateTime( control.setting.get() ); 5179 5203 5180 5204 if ( ! parsed ) { 5181 5205 return false; … … 5224 5248 */ 5225 5249 api.PreviewLinkControl = api.Control.extend({ 5226 5250 5227 previewElements: {},5228 5229 5251 /** 5230 5252 * Override the templateSelector before embedding the control into the page. 5231 5253 * … … 5245 5267 * @returns {void} 5246 5268 */ 5247 5269 ready: function ready() { 5248 var control = this, element, component, node, link, input, button;5270 var control = this, element, component, node, url, input, button; 5249 5271 5250 5272 _.bindAll( control, 'updatePreviewLink' ); 5251 5273 … … 5253 5275 control.setting = new api.Value(); 5254 5276 } 5255 5277 5278 control.previewElements = {}; 5279 5256 5280 control.container.find( '.preview-control-element' ).each( function() { 5257 5281 node = $( this ); 5258 5282 component = node.data( 'component' ); … … 5261 5285 control.elements.push( element ); 5262 5286 } ); 5263 5287 5264 link = control.previewElements.link;5288 url = control.previewElements.url; 5265 5289 input = control.previewElements.input; 5266 5290 button = control.previewElements.button; 5267 5291 5268 5292 input.link( control.setting ); 5269 link.link( control.setting );5293 url.link( control.setting ); 5270 5294 5271 link.bind( function( value ) { 5272 link.element.attr( 'href', value ); 5273 link.element.attr( 'target', api.settings.changeset.uuid ); 5295 url.bind( function( value ) { 5296 url.element.parent().attr( { 5297 href: value, 5298 target: api.settings.changeset.uuid 5299 } ); 5274 5300 } ); 5275 5301 5276 5302 api.bind( 'ready', control.updatePreviewLink ); 5277 api.bind( 'change', control.updatePreviewLink );5278 5303 api.state( 'saved' ).bind( control.updatePreviewLink ); 5304 api.state( 'changesetStatus' ).bind( control.updatePreviewLink ); 5279 5305 5280 5306 button.element.on( 'click', function( event ) { 5281 5307 event.preventDefault(); … … 5286 5312 } 5287 5313 } ); 5288 5314 5289 link.element.on( 'click', function( event ) {5290 if ( link.element.hasClass( 'disabled' ) ) {5315 url.element.parent().on( 'click', function( event ) { 5316 if ( $( this ).hasClass( 'disabled' ) ) { 5291 5317 event.preventDefault(); 5292 5318 } 5293 5319 } ); … … 5308 5334 updatePreviewLink: function updatePreviewLink() { 5309 5335 var control = this, unsavedDirtyValues; 5310 5336 5311 unsavedDirtyValues = ! _.isEmpty( api.dirtyValues( { 5312 unsaved: true 5313 } ) ); 5337 unsavedDirtyValues = ! api.state( 'saved' ).get() || '' === api.state( 'changesetStatus' ).get() || 'auto-draft' === api.state( 'changesetStatus' ).get(); 5314 5338 5315 5339 control.toggleSaveNotification( unsavedDirtyValues ); 5316 control.previewElements. link.element.toggleClass( 'disabled', unsavedDirtyValues );5340 control.previewElements.url.element.parent().toggleClass( 'disabled', unsavedDirtyValues ); 5317 5341 control.previewElements.button.element.prop( 'disabled', unsavedDirtyValues ); 5318 5342 control.setting.set( api.previewer.getFrontendPreviewUrl() ); 5319 5343 }, … … 6485 6509 } ); 6486 6510 } ); 6487 6511 6488 /** 6489 * Find all invalid setting less controls with notification type error. 6490 */ 6512 // Find all invalid setting less controls with notification type error. 6491 6513 api.control.each( function( control ) { 6492 6514 if ( ! control.setting || ! control.setting.id && control.active.get() ) { 6493 6515 control.notifications.each( function( notification ) { … … 7833 7855 }); 7834 7856 })(); 7835 7857 7836 /** 7837 * Publish settings section and controls. 7838 */ 7858 // Publish settings section and controls. 7839 7859 api.control( 'changeset_status', 'changeset_scheduled_date', function( statusControl, dateControl ) { 7840 7860 $.when( statusControl.deferred.embedded, dateControl.deferred.embedded ).done( function() { 7841 7861 var radioNodes, statusElement, toggleDateControl, publishWhenTime, pollInterval, updateTimeArrivedPoller, timeArrivedPollingInterval = 1000; -
src/wp-includes/class-wp-customize-manager.php
diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php index 95dfa794af..feaf4881d3 100644
final class WP_Customize_Manager { 3562 3562 </ul> 3563 3563 </script> 3564 3564 <script type="text/html" id="tmpl-customize-preview-link-control" > 3565 <span class="customize-control-title"> 3566 <label><?php esc_html_e( 'Share Preview Link' ); ?></label> 3567 </span> 3568 <span class="description customize-control-description"><?php esc_html_e( 'See how changes would look live on your website, and share the preview with people who can\'t access the Customizer.' ); ?></span> 3565 <# var elementPrefix = _.uniqueId( 'el' ) + '-' #> 3566 <p class="customize-control-title"> 3567 <?php esc_html_e( 'Share Preview Link' ); ?> 3568 </p> 3569 <p class="description customize-control-description"><?php esc_html_e( 'See how changes would look live on your website, and share the preview with people who can\'t access the Customizer.' ); ?></p> 3569 3570 <div class="customize-control-notifications-container"></div> 3570 3571 <div class="preview-link-wrapper"> 3571 <label> 3572 <span class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></span> 3573 <a class="preview-control-element" data-component="link" href="" target=""></a> 3574 <input readonly class="preview-control-element" data-component="input" value="test" > 3575 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button> 3576 </label> 3572 <label for="{{ elementPrefix }}customize-preview-link-input" class="screen-reader-text"><?php esc_html_e( 'Preview Link' ); ?></label> 3573 <a href="" target=""> 3574 <span class="preview-control-element" data-component="url"></span> 3575 <span class="screen-reader-text"><?php _e( '(opens in a new window)' ); ?></span> 3576 </a> 3577 <input id="{{ elementPrefix }}customize-preview-link-input" readonly class="preview-control-element" data-component="input"> 3578 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="<?php esc_attr_e( 'Copy' ); ?>" data-copied-text="<?php esc_attr_e( 'Copied' ); ?>" ><?php esc_html_e( 'Copy' ); ?></button> 3577 3579 </div> 3578 3580 </script> 3579 3581 <?php … … final class WP_Customize_Manager { 4171 4173 } else { 4172 4174 $initial_date = current_time( 'mysql', false ); 4173 4175 } 4176 4174 4177 $this->add_control( new WP_Customize_Date_Time_Control( $this, 'changeset_scheduled_date', array( 4175 4178 'section' => 'publish_settings', 4176 4179 'settings' => array(), 4177 4180 'type' => 'date_time', 4178 4181 'min_year' => date( 'Y' ), 4179 4182 'allow_past_date' => false, 4183 'include_time' => true, 4180 4184 'twelve_hour_format' => false !== stripos( get_option( 'time_format' ), 'a' ), 4181 4185 'description' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ), 4182 4186 'capability' => 'customize', -
src/wp-includes/class-wp-customize-nav-menus.php
diff --git src/wp-includes/class-wp-customize-nav-menus.php src/wp-includes/class-wp-customize-nav-menus.php index b2f91ceb5c..06228b2b74 100644
final class WP_Customize_Nav_Menus { 674 674 ) ) ); 675 675 676 676 $this->manager->add_control( 'new_menu_name', array( 677 'label' => '',677 'label' => __( 'New menu name' ), 678 678 'section' => 'add_menu', 679 679 'type' => 'text', 680 680 'settings' => array(), 681 681 'input_attrs' => array( 682 682 'class' => 'menu-name-field', 683 'placeholder' => __( 'New menu name' ),684 683 ), 685 684 ) ); 686 685 … … final class WP_Customize_Nav_Menus { 1017 1016 <?php $post_type_obj = get_post_type_object( $available_item_type['object'] ); ?> 1018 1017 <?php if ( current_user_can( $post_type_obj->cap->create_posts ) && current_user_can( $post_type_obj->cap->publish_posts ) ) : ?> 1019 1018 <div class="new-content-item"> 1020 <input type="text" class="create-item-input" placeholder="<?php echo esc_attr( $post_type_obj->labels->add_new_item ); ?>"> 1019 <label for="<?php echo esc_attr( 'create-item-input-' . $available_item_type['object'] ); ?>" class="screen-reader-text"><?php echo esc_html( $post_type_obj->labels->add_new_item ); ?></label> 1020 <input type="text" id="<?php echo esc_attr( 'create-item-input-' . $available_item_type['object'] ); ?>" class="create-item-input" placeholder="<?php echo esc_attr( $post_type_obj->labels->add_new_item ); ?>"> 1021 1021 <button type="button" class="button add-content"><?php _e( 'Add' ); ?></button> 1022 1022 </div> 1023 1023 <?php endif; ?> -
src/wp-includes/customize/class-wp-customize-date-time-control.php
diff --git src/wp-includes/customize/class-wp-customize-date-time-control.php src/wp-includes/customize/class-wp-customize-date-time-control.php index abcdc58833..9f36da0e68 100644
class WP_Customize_Date_Time_Control extends WP_Customize_Control { 48 48 */ 49 49 public $allow_past_date = true; 50 50 51 /** 52 * Whether hours, minutes, and meridian should be shown. 53 * 54 * @since 4.9.0 55 * @var boolean 56 */ 57 public $include_time = true; 58 51 59 /** 52 60 * If set to false the control will appear in 24 hour format, 53 61 * the value will still be saved in Y-m-d H:i:s format. … … class WP_Customize_Date_Time_Control extends WP_Customize_Control { 83 91 84 92 $data['maxYear'] = intval( $this->max_year ); 85 93 $data['minYear'] = intval( $this->min_year ); 86 $data['allowPastDate'] = $this->allow_past_date ? true : false; 87 $data['twelveHourFormat'] = $this->twelve_hour_format ? true : false; 94 $data['allowPastDate'] = (bool) $this->allow_past_date; 95 $data['twelveHourFormat'] = (bool) $this->twelve_hour_format; 96 $data['includeTime'] = (bool) $this->include_time; 88 97 $data['defaultValue'] = $this->default_value; 89 98 90 99 return $data; … … class WP_Customize_Date_Time_Control extends WP_Customize_Control { 101 110 ?> 102 111 103 112 <# _.defaults( data, <?php echo wp_json_encode( $data ); ?> ); #> 113 <# var idPrefix = _.uniqueId( 'el' ) + '-'; #> 104 114 105 115 <span class="customize-control-title"> 106 <label>{{ data.label }}</label>116 {{ data.label }} 107 117 </span> 108 118 <div class="customize-control-notifications-container"></div> 109 119 <span class="description customize-control-description">{{ data.description }}</span> 110 120 <div class="date-time-fields"> 111 < divclass="day-row">112 < span class="title-day"><?php esc_html_e( 'Day' ); ?></span>121 <fieldset class="day-row"> 122 <legend class="title-day"><?php esc_html_e( 'Date' ); ?></legend> 113 123 <div class="day-fields clear"> 114 <label class="month-field"> 115 <span class="screen-reader-text"><?php esc_html_e( 'Month' ); ?></span> 116 <select class="date-input month" data-component="month"> 117 <# _.each( data.month_choices, function( choice ) { 118 if ( _.isObject( choice ) && ! _.isUndefined( choice.text ) && ! _.isUndefined( choice.value ) ) { 119 text = choice.text; 120 value = choice.value; 121 } 122 #> 123 <option value="{{ value }}" > 124 {{ text }} 125 </option> 126 <# } ); #> 127 </select> 128 </label> 129 <label class="day-field"> 130 <span class="screen-reader-text"><?php esc_html_e( 'Day' ); ?></span> 131 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input day" data-component="day" min="1" max="31"" /> 132 </label> 124 <label for="{{ idPrefix }}date-time-month" class="screen-reader-text"><?php esc_html_e( 'Month' ); ?></label> 125 <select id="{{ idPrefix }}date-time-month" class="date-input month" data-component="month"> 126 <# _.each( data.month_choices, function( choice ) { 127 if ( _.isObject( choice ) && ! _.isUndefined( choice.text ) && ! _.isUndefined( choice.value ) ) { 128 text = choice.text; 129 value = choice.value; 130 } 131 #> 132 <option value="{{ value }}" > 133 {{ text }} 134 </option> 135 <# } ); #> 136 </select> 137 <label for="{{ idPrefix }}date-time-day" class="screen-reader-text"><?php esc_html_e( 'Day' ); ?></label> 138 <input id="{{ idPrefix }}date-time-day" type="number" size="2" autocomplete="off" class="date-input day" data-component="day" min="1" max="31" /> 133 139 <span class="time-special-char date-time-separator">,</span> 134 <label class="year-field"> 135 <span class="screen-reader-text"><?php esc_html_e( 'Year' ); ?></span> 136 <# var maxYearLength = String( data.maxYear ).length; #> 137 <input type="number" size="4" maxlength="{{ maxYearLength }}" autocomplete="off" class="date-input year" data-component="year" min="{{ data.minYear }}" max="{{ data.maxYear }}" /> 138 </label> 140 <label for="{{ idPrefix }}date-time-year" class="screen-reader-text"><?php esc_html_e( 'Year' ); ?></label> 141 <input id="{{ idPrefix }}date-time-year" type="number" size="4" autocomplete="off" class="date-input year" data-component="year" min="{{ data.minYear }}" max="{{ data.maxYear }}"> 139 142 </div> 140 </ div>141 < div class="time-row clear">142 < span class="title-time"><?php esc_html_e( 'Time' ); ?></span>143 <div class="time-fields clear">144 < label class="hour-field">145 < span class="screen-reader-text"><?php esc_html_e( 'Hour' ); ?></span>143 </fieldset> 144 <# if ( data.includeTime ) { #> 145 <fieldset class="time-row clear"> 146 <legend class="title-time"><?php esc_html_e( 'Time' ); ?></legend> 147 <div class="time-fields clear"> 148 <label for="{{ idPrefix }}date-time-hour" class="screen-reader-text"><?php esc_html_e( 'Hour' ); ?></label> 146 149 <# var maxHour = data.twelveHourFormat ? 12 : 24; #> 147 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}"" /> 148 </label> 149 <span class="time-special-char date-time-separator">:</span> 150 <label class="minute-field"> 151 <span class="screen-reader-text"><?php esc_html_e( 'Minute' ); ?></span> 152 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59" /> 153 </label> 154 <# if ( data.twelveHourFormat ) { #> 155 <label class="am-pm-field"> 156 <span class="screen-reader-text"><?php esc_html_e( 'AM / PM' ); ?></span> 157 <select class="date-input" data-component="ampm"> 158 <option value="am"><?php esc_html_e( 'AM' ); ?></option> 159 <option value="pm"><?php esc_html_e( 'PM' ); ?></option> 160 </select> 161 </label> 162 <# } #> 163 <abbr class="date-timezone" aria-label="<?php esc_attr_e( 'Timezone' ); ?>" title="<?php echo esc_attr( $timezone_info['description'] ); ?>"><?php echo esc_html( $timezone_info['abbr'] ); ?></abbr> 164 </div> 165 </div> 150 <input id="{{ idPrefix }}date-time-hour" type="number" size="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}"> 151 <span class="time-special-char date-time-separator">:</span> 152 <label for="{{ idPrefix }}date-time-minute" class="screen-reader-text"><?php esc_html_e( 'Minute' ); ?></label> 153 <input id="{{ idPrefix }}date-time-minute" type="number" size="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59"> 154 <# if ( data.twelveHourFormat ) { #> 155 <label for="{{ idPrefix }}date-time-meridian" class="screen-reader-text"><?php esc_html_e( 'Meridian' ); ?></label> 156 <select id="{{ idPrefix }}date-time-meridian" class="date-input meridian" data-component="meridian"> 157 <option value="am"><?php esc_html_e( 'AM' ); ?></option> 158 <option value="pm"><?php esc_html_e( 'PM' ); ?></option> 159 </select> 160 <# } #> 161 <abbr class="date-timezone" aria-label="<?php esc_attr_e( 'Timezone' ); ?>" title="<?php echo esc_attr( $timezone_info['description'] ); ?>"><?php echo esc_html( $timezone_info['abbr'] ); ?></abbr> 162 </div> 163 </fieldset> 164 <# } #> 166 165 </div> 167 166 <?php 168 167 } -
tests/qunit/index.html
diff --git tests/qunit/index.html tests/qunit/index.html index 5ed4c7a02d..ce0d98d76a 100644
872 872 </div> 873 873 <# } #> 874 874 </script> 875 <script type="text/html" id="tmpl-customize-control-date_time-content">875 <script type="text/html" id="tmpl-customize-control-date_time-content"> 876 876 877 <# _.defaults( data, {"settings":[],"type":"date_time","priority":10,"active":true,"section":"","content":"<li id=\"customize-control-temp\" class=\"customize-control customize-control-date_time\">\n\t\t\t\t\t<\/li>","label":"","description":"","instanceNumber":69,"maxYear":9999,"minYear":1000,"allowPastDate":true,"twelveHourFormat":true,"defaultValue":null,"month_choices":{"1":{"text":"1-Jan","value":1},"2":{"text":"2-Feb","value":2},"3":{"text":"3-Mar","value":3},"4":{"text":"4-Apr","value":4},"5":{"text":"5-May","value":5},"6":{"text":"6-Jun","value":6},"7":{"text":"7-Jul","value":7},"8":{"text":"8-Aug","value":8},"9":{"text":"9-Sep","value":9},"10":{"text":"10-Oct","value":10},"11":{"text":"11-Nov","value":11},"12":{"text":"12-Dec","value":12}}} ); #> 877 <# _.defaults( data, {"settings":[],"type":"date_time","priority":10,"active":true,"section":"","content":"<li id=\"customize-control-temp\" class=\"customize-control customize-control-date_time\">\n\t\t\t\t\t<\/li>","label":"","description":"","instanceNumber":73,"maxYear":9999,"minYear":1000,"allowPastDate":true,"twelveHourFormat":true,"includeTime":true,"defaultValue":null,"month_choices":{"1":{"text":"1-Jan","value":1},"2":{"text":"2-Feb","value":2},"3":{"text":"3-Mar","value":3},"4":{"text":"4-Apr","value":4},"5":{"text":"5-May","value":5},"6":{"text":"6-Jun","value":6},"7":{"text":"7-Jul","value":7},"8":{"text":"8-Aug","value":8},"9":{"text":"9-Sep","value":9},"10":{"text":"10-Oct","value":10},"11":{"text":"11-Nov","value":11},"12":{"text":"12-Dec","value":12}}} ); #> 878 <# var idPrefix = _.uniqueId( 'el' ) + '-'; #> 878 879 879 880 <span class="customize-control-title"> 880 <label>{{ data.label }}</label>881 {{ data.label }} 881 882 </span> 882 883 <div class="customize-control-notifications-container"></div> 883 884 <span class="description customize-control-description">{{ data.description }}</span> 884 885 <div class="date-time-fields"> 885 < divclass="day-row">886 < span class="title-day">Day</span>886 <fieldset class="day-row"> 887 <legend class="title-day">Date</legend> 887 888 <div class="day-fields clear"> 888 <label class="month-field"> 889 <span class="screen-reader-text">Month</span> 890 <select class="date-input month" data-component="month"> 891 <# _.each( data.month_choices, function( choice ) { 892 if ( _.isObject( choice ) && ! _.isUndefined( choice.text ) && ! _.isUndefined( choice.value ) ) { 893 text = choice.text; 894 value = choice.value; 895 } 896 #> 897 <option value="{{ value }}" > 898 {{ text }} 899 </option> 900 <# } ); #> 901 </select> 902 </label> 903 <label class="day-field"> 904 <span class="screen-reader-text">Day</span> 905 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input day" data-component="day" min="1" max="31"" /> 906 </label> 889 <label for="{{ idPrefix }}date-time-month" class="screen-reader-text">Month</label> 890 <select id="{{ idPrefix }}date-time-month" class="date-input month" data-component="month"> 891 <# _.each( data.month_choices, function( choice ) { 892 if ( _.isObject( choice ) && ! _.isUndefined( choice.text ) && ! _.isUndefined( choice.value ) ) { 893 text = choice.text; 894 value = choice.value; 895 } 896 #> 897 <option value="{{ value }}" > 898 {{ text }} 899 </option> 900 <# } ); #> 901 </select> 902 <label for="{{ idPrefix }}date-time-day" class="screen-reader-text">Day</label> 903 <input id="{{ idPrefix }}date-time-day" type="number" size="2" autocomplete="off" class="date-input day" data-component="day" min="1" max="31" /> 907 904 <span class="time-special-char date-time-separator">,</span> 908 <label class="year-field"> 909 <span class="screen-reader-text">Year</span> 910 <# var maxYearLength = String( data.maxYear ).length; #> 911 <input type="number" size="4" maxlength="{{ maxYearLength }}" autocomplete="off" class="date-input year" data-component="year" min="{{ data.minYear }}" max="{{ data.maxYear }}" /> 912 </label> 905 <label for="{{ idPrefix }}date-time-year" class="screen-reader-text">Year</label> 906 <input id="{{ idPrefix }}date-time-year" type="number" size="4" autocomplete="off" class="date-input year" data-component="year" min="{{ data.minYear }}" max="{{ data.maxYear }}"> 913 907 </div> 914 </ div>915 < div class="time-row clear">916 < span class="title-time">Time</span>917 <div class="time-fields clear">918 < label class="hour-field">919 < span class="screen-reader-text">Hour</span>908 </fieldset> 909 <# if ( data.includeTime ) { #> 910 <fieldset class="time-row clear"> 911 <legend class="title-time">Time</legend> 912 <div class="time-fields clear"> 913 <label for="{{ idPrefix }}date-time-hour" class="screen-reader-text">Hour</label> 920 914 <# var maxHour = data.twelveHourFormat ? 12 : 24; #> 921 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}"" /> 922 </label> 923 <span class="time-special-char date-time-separator">:</span> 924 <label class="minute-field"> 925 <span class="screen-reader-text">Minute</span> 926 <input type="number" size="2" maxlength="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59" /> 927 </label> 928 <# if ( data.twelveHourFormat ) { #> 929 <label class="am-pm-field"> 930 <span class="screen-reader-text">AM / PM</span> 931 <select class="date-input" data-component="ampm"> 915 <input id="{{ idPrefix }}date-time-hour" type="number" size="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}"> 916 <span class="time-special-char date-time-separator">:</span> 917 <label for="{{ idPrefix }}date-time-minute" class="screen-reader-text">Minute</label> 918 <input id="{{ idPrefix }}date-time-minute" type="number" size="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59"> 919 <# if ( data.twelveHourFormat ) { #> 920 <label for="{{ idPrefix }}date-time-meridian" class="screen-reader-text">Meridian</label> 921 <select id="{{ idPrefix }}date-time-meridian" class="date-input meridian" data-component="meridian"> 932 922 <option value="am">AM</option> 933 923 <option value="pm">PM</option> 934 924 </select> 935 </label>936 925 <# } #> 937 <abbr class="date-timezone" aria-label="Timezone" title="Timezone is Asia/Kolkata (IST), currently UTC+5:30.">IST</abbr> 938 </div> 939 </div> 926 <abbr class="date-timezone" aria-label="Timezone" title="Timezone is America/Los Angeles (PDT), currently UTC-7.">PDT</abbr> 927 </div> 928 </fieldset> 929 <# } #> 940 930 </div> 941 931 </script> 942 932 <script type="text/html" id="tmpl-customize-preview-link-control" > 943 < span class="customize-control-title">944 < label>Share Preview Link</label>945 </span>946 < span class="description customize-control-description">See how changes would look live on your website, and share the preview with people who can't access the Customizer.</span>933 <# var elementPrefix = _.uniqueId( 'el' ) + '-' #> 934 <p class="customize-control-title"> 935 Share Preview Link </p> 936 <p class="description customize-control-description">See how changes would look live on your website, and share the preview with people who can't access the Customizer.</p> 947 937 <div class="customize-control-notifications-container"></div> 948 938 <div class="preview-link-wrapper"> 949 <label> 950 <span class="screen-reader-text">Preview Link</span> 951 <a class="preview-control-element" data-component="link" href="" target=""></a> 952 <input readonly class="preview-control-element" data-component="input" value="test" > 953 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="Copy" data-copied-text="Copied" >Copy</button> 954 </label> 939 <label for="{{ elementPrefix }}customize-preview-link-input" class="screen-reader-text">Preview Link</label> 940 <a href="" target=""> 941 <span class="preview-control-element" data-component="url"></span> 942 <span class="screen-reader-text">(opens in a new window)</span> 943 </a> 944 <input id="{{ elementPrefix }}customize-preview-link-input" readonly class="preview-control-element" data-component="input"> 945 <button class="customize-copy-preview-link preview-control-element button button-secondary" data-component="button" data-copy-text="Copy" data-copied-text="Copied" >Copy</button> 955 946 </div> 956 947 </script> 957 948 <script type="text/html" id="tmpl-media-modal"> -
tests/qunit/wp-admin/js/customize-controls.js
diff --git tests/qunit/wp-admin/js/customize-controls.js tests/qunit/wp-admin/js/customize-controls.js index aaa8c069cc..32b48127a2 100644
jQuery( window ).load( function (){ 702 702 test( 'Test DateTimeControl creation and its methods', function( assert ) { 703 703 var control, controlId = 'date_time', section, sectionId = 'fixture-section', 704 704 datetime = '2599-08-06 18:12:13', dateTimeArray, dateTimeArrayInampm, timeString, 705 day, year, month, minute, ampm, hour;705 day, year, month, minute, meridian, hour; 706 706 707 707 section = wp.customize.section( sectionId ); 708 708 … … jQuery( window ).load( function (){ 710 710 params: { 711 711 section: section.id, 712 712 type: 'date_time', 713 includeTime: true, 713 714 content: '<li id="customize-control-' + controlId + '" class="customize-control"></li>', 714 715 defaultValue: datetime 715 716 } … … jQuery( window ).load( function (){ 728 729 year = control.inputElements.year; 729 730 minute = control.inputElements.minute; 730 731 hour = control.inputElements.hour; 731 ampm = control.inputElements.ampm;732 meridian = control.inputElements.meridian; 732 733 733 734 year( '23' ); 734 735 assert.equal( typeof year(), 'number', 'Should always return integer' ); 735 736 737 month( '8' ); 736 738 month( 'test' ); 737 assert. notOk(month(), 'Should not accept text' );739 assert.equal( 8, month(), 'Should not accept text' ); 738 740 739 741 // Test control.parseDateTime(); 742 control.params.twelveHourFormat = false; 740 743 dateTimeArray = control.parseDateTime( datetime ); 741 744 assert.deepEqual( dateTimeArray, { 742 745 year: '2599', … … jQuery( window ).load( function (){ 747 750 day: '06' 748 751 } ); 749 752 750 dateTimeArrayInampm = control.parseDateTime( datetime, true ); 753 control.params.twelveHourFormat = true; 754 dateTimeArrayInampm = control.parseDateTime( datetime ); 751 755 assert.deepEqual( dateTimeArrayInampm, { 752 756 year: '2599', 753 757 month: '08', 754 758 hour: '6', 755 759 minute: '12', 756 ampm: 'pm',760 meridian: 'pm', 757 761 day: '06' 758 762 } ); 759 763 … … jQuery( window ).load( function (){ 762 766 day( '18' ); 763 767 hour( '3' ); 764 768 minute( '44' ); 765 ampm( 'am' );769 meridian( 'am' ); 766 770 767 771 // Test control.convertInputDateToString(). 768 772 timeString = control.convertInputDateToString(); 769 773 assert.equal( timeString, '2010-12-18 03:44:00' ); 770 774 771 ampm( 'pm' );775 meridian( 'pm' ); 772 776 timeString = control.convertInputDateToString(); 773 777 assert.equal( timeString, '2010-12-18 15:44:00' ); 774 778 779 control.params.includeTime = false; 780 timeString = control.convertInputDateToString(); 781 assert.equal( timeString, '2010-12-18' ); 782 control.params.includeTime = true; 783 775 784 // Test control.updateDaysForMonth();. 776 785 year( 2017 ); 777 786 month( 2 ); … … jQuery( window ).load( function (){ 796 805 assert.notOk( control.notifications.has( 'not_future_date' ) ); 797 806 798 807 // Test control.populateDateInputs(); 808 control.setting._value = '2000-12-30 12:34:56'; 799 809 control.populateDateInputs(); 800 control.dateInputs.each( function() { 801 var node = jQuery( this ); 802 assert.equal( node.val(), control.inputElements[ node.data( 'component' ) ].get() ); 803 } ); 810 assert.equal( '2000', control.inputElements.year.get() ); 811 assert.equal( '12', control.inputElements.month.get() ); 812 assert.equal( '30', control.inputElements.day.get() ); 813 assert.equal( '12', control.inputElements.hour.get() ); 814 assert.equal( '34', control.inputElements.minute.get() ); 815 assert.equal( 'pm', control.inputElements.meridian.get() ); 804 816 805 817 // Test control.validateInputs(); 806 818 hour( 33 ); … … jQuery( window ).load( function (){ 818 830 year( 2018 ); 819 831 hour( 4 ); 820 832 minute( 20 ); 821 ampm( 'pm' );833 meridian( 'pm' ); 822 834 control.populateSetting(); 823 835 assert.equal( control.setting(), '2018-11-02 16:20:00' ); 824 836 … … jQuery( window ).load( function (){ 836 848 year( 2318 ); 837 849 hour( 4 ); 838 850 minute( 20 ); 839 ampm( 'pm' );851 meridian( 'pm' ); 840 852 assert.ok( control.isFutureDate() ); 841 853 842 854 year( 2016 ); … … jQuery( window ).load( function (){ 848 860 */ 849 861 hour( 24 ); 850 862 minute( 32 ); 851 control.inputElements. ampm= false; // Because it works only when the time is twenty four hour format.863 control.inputElements.meridian = false; // Because it works only when the time is twenty four hour format. 852 864 control.updateMinutesForHour(); 853 865 assert.deepEqual( minute(), 0 ); 854 866 … … jQuery( window ).load( function (){ 910 922 control.setting.set( newLink ); 911 923 912 924 assert.equal( control.previewElements.input(), newLink ); 913 assert.equal( control.previewElements. link(), newLink );914 assert.equal( control.previewElements. link.element.attr( 'href' ), newLink );915 assert.equal( control.previewElements. link.element.attr( 'target' ), wp.customize.settings.changeset.uuid );925 assert.equal( control.previewElements.url(), newLink ); 926 assert.equal( control.previewElements.url.element.parent().attr( 'href' ), newLink ); 927 assert.equal( control.previewElements.url.element.parent().attr( 'target' ), wp.customize.settings.changeset.uuid ); 916 928 917 929 // Test control.toggleSaveNotification(). 918 930 control.toggleSaveNotification( true );