Ticket #38678: 38678.12.diff
| File 38678.12.diff, 16.0 KB (added by , 10 years ago) |
|---|
-
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 3aa7ebc..f6d77a6 100644
final class WP_Customize_Manager { 3590 3590 $this->add_setting( 'external_header_video', array( 3591 3591 'theme_supports' => array( 'custom-header', 'video' ), 3592 3592 'transport' => 'postMessage', 3593 'sanitize_callback' => 'esc_url ',3593 'sanitize_callback' => 'esc_url_raw', 3594 3594 'validate_callback' => array( $this, '_validate_external_header_video' ), 3595 3595 ) ); 3596 3596 -
src/wp-includes/js/wp-custom-header.js
diff --git src/wp-includes/js/wp-custom-header.js src/wp-includes/js/wp-custom-header.js index 08e2488..b7c2406 100644
1 (function( window, settings ) { 1 /* global YT */ 2 ( function( window, wp, settings ) { 2 3 4 var NativeHandler, YouTubeHandler; 5 6 // Fail gracefully in unsupported browsers. 3 7 if ( ! ( 'addEventListener' in window ) ) { 4 // Fail gracefully in unsupported browsers.5 8 return; 6 9 } 7 10 8 function wpCustomHeader() { 9 var handlers = { 10 nativeVideo: { 11 test: function( settings ) { 12 var video = document.createElement( 'video' ); 13 return video.canPlayType( settings.mimeType ); 14 }, 15 callback: nativeHandler 16 }, 17 youtube: { 18 test: function( settings ) { 19 return 'video/x-youtube' === settings.mimeType; 20 }, 21 callback: youtubeHandler 22 } 23 }; 11 /** 12 * Trigger an event. 13 * 14 * @param {Element} target HTML element to dispatch the event on. 15 * @param {string} name Event name. 16 */ 17 function trigger( target, name ) { 18 var evt; 24 19 25 function initialize() { 26 settings.container = document.getElementById( 'wp-custom-header' ); 20 if ( 'function' === typeof window.Event ) { 21 evt = new Event( name ); 22 } else { 23 evt = document.createEvent( 'Event' ); 24 evt.initEvent( name, true, true ); 25 } 27 26 28 if ( supportsVideo() ) { 29 for ( var id in handlers ) { 30 var handler = handlers[ id ]; 27 target.dispatchEvent( evt ); 28 } 31 29 32 if ( handlers.hasOwnProperty( id ) && handler.test( settings ) ) { 33 handler.callback( settings ); 30 /** 31 * Create a custom header instance. 32 * 33 * @class CustomHeader 34 */ 35 function CustomHeader() { 36 this.handlers = { 37 nativeVideo: new NativeHandler(), 38 youtube: new YouTubeHandler() 39 }; 40 } 34 41 35 // Set up and dispatch custom event when the video is loaded. 36 if ( 'dispatchEvent' in window ) { 37 var videoLoaded = new Event( 'wp-custom-header-video-loaded' ); 38 document.dispatchEvent( videoLoaded ); 39 } 42 CustomHeader.prototype = { 43 /** 44 * Initalize the custom header. 45 * 46 * If the environment supports video, loops through registered handlers 47 * until one is found that can handle the video. 48 */ 49 initialize: function() { 50 if ( this.supportsVideo() ) { 51 for ( var id in this.handlers ) { 52 var handler = this.handlers[ id ]; 53 54 if ( 'test' in handler && handler.test( settings ) ) { 55 this.activeHandler = handler.initialize.call( handler, settings ); 40 56 57 // Dispatch custom event when the video is loaded. 58 trigger( document, 'wp-custom-header-video-loaded' ); 41 59 break; 42 60 } 43 61 } 44 62 } 45 } 63 }, 46 64 47 function supportsVideo() { 65 /** 66 * Determines if the current environment supports video. 67 * 68 * Themes and plugins can override this method to change the criteria. 69 * 70 * @return {boolean} 71 */ 72 supportsVideo: function() { 48 73 // Don't load video on small screens. @todo: consider bandwidth and other factors. 49 if ( window.innerWidth < settings.minWidth || window.innerHeight < settings.minHeight ) {74 if ( window.innerWidth < settings.minWidth || window.innerHeight < settings.minHeight ) { 50 75 return false; 51 76 } 52 77 53 78 return true; 79 }, 80 81 /** 82 * Base handler for custom handlers to extend. 83 * 84 * @type {BaseHandler} 85 */ 86 BaseVideoHandler: BaseHandler 87 }; 88 89 /** 90 * Create a video handler instance. 91 * 92 * @class BaseHandler 93 */ 94 function BaseHandler() {} 95 96 BaseHandler.prototype = { 97 /** 98 * Initialize the video handler. 99 * 100 * @param {object} settings Video settings. 101 */ 102 initialize: function( settings ) { 103 var handler = this, 104 button = document.createElement( 'button' ); 105 106 this.settings = settings; 107 this.container = document.getElementById( 'wp-custom-header' ), 108 this.button = button; 109 110 button.setAttribute( 'type', 'button' ); 111 button.setAttribute( 'id', 'wp-custom-header-video-button' ); 112 button.setAttribute( 'class', 'wp-custom-header-video-button wp-custom-header-video-play' ); 113 button.innerHTML = settings.l10n.play; 114 115 // Toggle video playback when the button is clicked. 116 button.addEventListener( 'click', function() { 117 if ( handler.isPaused() ) { 118 handler.play(); 119 } else { 120 handler.pause(); 121 } 122 }); 123 124 // Update the button class and text when the video state changes. 125 this.container.addEventListener( 'play', function() { 126 button.className = 'wp-custom-header-video-button wp-custom-header-video-play'; 127 button.innerHTML = settings.l10n.pause; 128 wp.a11y.speak( settings.l10n.playSpeak); 129 }); 130 131 this.container.addEventListener( 'pause', function() { 132 button.className = 'wp-custom-header-video-button wp-custom-header-video-pause'; 133 button.innerHTML = settings.l10n.play; 134 wp.a11y.speak( settings.l10n.pauseSpeak); 135 }); 136 137 this.ready(); 138 }, 139 140 /** 141 * Ready method called after a handler is initialized. 142 * 143 * @abstract 144 */ 145 ready: function() {}, 146 147 /** 148 * Whether the video is paused. 149 * 150 * @abstract 151 * @return {boolean} 152 */ 153 isPaused: function() {}, 154 155 /** 156 * Pause the video. 157 * 158 * @abstract 159 */ 160 pause: function() {}, 161 162 /** 163 * Play the video. 164 * 165 * @abstract 166 */ 167 play: function() {}, 168 169 /** 170 * Append a video node to the header container. 171 * 172 * @param {Element} node HTML element. 173 */ 174 setVideo: function( node ) { 175 var editShortcutNode, 176 editShortcut = this.container.getElementsByClassName( 'customize-partial-edit-shortcut' ); 177 178 if ( editShortcut.length ) { 179 editShortcutNode = this.container.removeChild( editShortcut[0] ); 180 } 181 182 this.container.innerHTML = ''; 183 this.container.appendChild( node ); 184 185 if ( editShortcutNode ) { 186 this.container.appendChild( editShortcutNode ); 187 } 188 }, 189 190 /** 191 * Show the video controls. 192 * 193 * Appends a play/pause button to header container. 194 */ 195 showControls: function() { 196 if ( ! this.container.contains( this.button ) ) { 197 this.container.appendChild( this.button ); 198 } 199 }, 200 201 /** 202 * Whether the handler can process a video. 203 * 204 * @abstract 205 * @param {object} settings Video settings. 206 * @return {boolean} 207 */ 208 test: function() { 209 return false; 210 }, 211 212 /** 213 * Trigger an event on the header container. 214 * 215 * @param {string} name Event name. 216 */ 217 trigger: function( name ) { 218 trigger( this.container, name ); 54 219 } 220 }; 55 221 56 return { 57 handlers: handlers, 58 initialize: initialize, 59 supportsVideo: supportsVideo 60 }; 61 } 222 /** 223 * Create a custom handler. 224 * 225 * @param {object} protoProps Properties to apply to the prototype. 226 * @return CustomHandler The subclass. 227 */ 228 BaseHandler.extend = function( protoProps ) { 229 var prop; 230 231 function CustomHandler() { 232 var result = BaseHandler.apply( this, arguments ); 233 return result; 234 } 235 236 CustomHandler.prototype = Object.create( BaseHandler.prototype ); 237 CustomHandler.prototype.constructor = CustomHandler; 238 239 for ( prop in protoProps ) { 240 CustomHandler.prototype[ prop ] = protoProps[ prop ]; 241 } 242 243 return CustomHandler; 244 }; 245 246 /** 247 * Native video handler. 248 * 249 * @class NativeHandler 250 */ 251 NativeHandler = BaseHandler.extend({ 252 /** 253 * Whether the native handler supports a video. 254 * 255 * @param {object} settings Video settings. 256 * @return {boolean} 257 */ 258 test: function( settings ) { 259 var video = document.createElement( 'video' ); 260 return video.canPlayType( settings.mimeType ); 261 }, 262 263 /** 264 * Set up a native video element. 265 */ 266 ready: function() { 267 var handler = this, 268 video = document.createElement( 'video' ); 269 270 video.id = 'wp-custom-header-video'; 271 video.autoplay = 'autoplay'; 272 video.loop = 'loop'; 273 video.muted = 'muted'; 274 video.width = this.settings.width; 275 video.height = this.settings.height; 276 277 video.addEventListener( 'play', function() { 278 handler.trigger( 'play' ); 279 }); 280 281 video.addEventListener( 'pause', function() { 282 handler.trigger( 'pause' ); 283 }); 284 285 video.addEventListener( 'canplay', function() { 286 handler.showControls(); 287 }); 62 288 63 function nativeHandler( settings ) { 64 var video = document.createElement( 'video' ); 289 this.video = video; 290 handler.setVideo( video ); 291 video.src = this.settings.videoUrl; 292 }, 65 293 66 video.id = 'wp-custom-header-video'; 67 video.autoplay = 'autoplay'; 68 video.loop = 'loop'; 69 video.muted = 'muted'; 70 video.width = settings.width; 71 video.height = settings.height; 294 /** 295 * Whether the video is paused. 296 * 297 * @return {boolean} 298 */ 299 isPaused: function() { 300 return this.video.paused; 301 }, 72 302 73 video.addEventListener( 'click', function() { 74 if ( video.paused ) { 75 video.play(); 303 /** 304 * Pause the video. 305 */ 306 pause: function() { 307 this.video.pause(); 308 }, 309 310 /** 311 * Play the video. 312 */ 313 play: function() { 314 this.video.play(); 315 } 316 }); 317 318 /** 319 * YouTube video handler. 320 * 321 * @class YouTubeHandler 322 */ 323 YouTubeHandler = BaseHandler.extend({ 324 /** 325 * Whether the handler supports a video. 326 * 327 * @param {object} settings Video settings. 328 * @return {boolean} 329 */ 330 test: function( settings ) { 331 return 'video/x-youtube' === settings.mimeType; 332 }, 333 334 /** 335 * Set up a YouTube iframe. 336 * 337 * Loads the YouTube IFrame API if the 'YT' global doesn't exist. 338 */ 339 ready: function() { 340 var handler = this; 341 342 if ( 'YT' in window ) { 343 YT.ready( handler.loadVideo.bind( handler ) ); 76 344 } else { 77 video.pause(); 345 var tag = document.createElement( 'script' ); 346 tag.src = 'https://www.youtube.com/iframe_api'; 347 tag.onload = function () { 348 YT.ready( handler.loadVideo.bind( handler ) ); 349 }; 350 351 document.getElementsByTagName( 'head' )[0].appendChild( tag ); 78 352 } 79 } );353 }, 80 354 81 settings.container.innerHTML = ''; 82 settings.container.appendChild( video ); 83 video.src = settings.videoUrl; 84 } 355 /** 356 * Load a YouTube video. 357 */ 358 loadVideo: function() { 359 var handler = this, 360 video = document.createElement( 'div' ), 361 // @link http://stackoverflow.com/a/27728417 362 VIDEO_ID_REGEX = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/; 85 363 86 function youtubeHandler( settings ) { 87 // @link http://stackoverflow.com/a/27728417 88 var VIDEO_ID_REGEX = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/, 89 videoId = settings.videoUrl.match( VIDEO_ID_REGEX )[1]; 90 91 function loadVideo() { 92 var YT = window.YT || {}; 93 94 YT.ready(function() { 95 var video = document.createElement( 'div' ); 96 video.id = 'wp-custom-header-video'; 97 settings.container.innerHTML = ''; 98 settings.container.appendChild( video ); 99 100 new YT.Player( video, { 101 height: settings.height, 102 width: settings.width, 103 videoId: videoId, 104 events: { 105 onReady: function( e ) { 106 e.target.mute(); 107 }, 108 onStateChange: function( e ) { 109 if ( YT.PlayerState.ENDED === e.data ) { 110 e.target.playVideo(); 111 } 112 } 364 video.id = 'wp-custom-header-video'; 365 handler.setVideo( video ); 366 367 handler.player = new YT.Player( video, { 368 height: this.settings.height, 369 width: this.settings.width, 370 videoId: this.settings.videoUrl.match( VIDEO_ID_REGEX )[1], 371 events: { 372 onReady: function( e ) { 373 e.target.mute(); 374 handler.showControls(); 113 375 }, 114 playerVars: { 115 autoplay: 1, 116 controls: 0, 117 disablekb: 1, 118 fs: 0, 119 iv_load_policy: 3, 120 loop: 1, 121 modestbranding: 1, 122 //origin: '', 123 playsinline: 1, 124 rel: 0, 125 showinfo: 0 376 onStateChange: function( e ) { 377 if ( YT.PlayerState.PLAYING === e.data ) { 378 handler.trigger( 'play' ); 379 } else if ( YT.PlayerState.PAUSED === e.data ) { 380 handler.trigger( 'pause' ); 381 } else if ( YT.PlayerState.ENDED === e.data ) { 382 e.target.playVideo(); 383 } 126 384 } 127 }); 385 }, 386 playerVars: { 387 autoplay: 1, 388 controls: 0, 389 disablekb: 1, 390 fs: 0, 391 iv_load_policy: 3, 392 loop: 1, 393 modestbranding: 1, 394 playsinline: 1, 395 rel: 0, 396 showinfo: 0 397 } 128 398 }); 129 } 399 }, 130 400 131 if ( 'YT' in window ) { 132 loadVideo(); 133 } else { 134 var tag = document.createElement( 'script' ); 135 tag.src = 'https://www.youtube.com/player_api'; 136 tag.onload = function () { loadVideo(); }; 137 document.getElementsByTagName( 'head' )[0].appendChild( tag ); 401 /** 402 * Whether the video is paused. 403 * 404 * @return {boolean} 405 */ 406 isPaused: function() { 407 return YT.PlayerState.PAUSED === this.player.getPlayerState(); 408 }, 409 410 /** 411 * Pause the video. 412 */ 413 pause: function() { 414 this.player.pauseVideo(); 415 }, 416 417 /** 418 * Play the video. 419 */ 420 play: function() { 421 this.player.playVideo(); 138 422 } 139 } 423 }); 140 424 141 window.wp = window.wp || {};142 w indow.wp.customHeader = new wpCustomHeader();143 document.addEventListener( 'DOMContentLoaded', w indow.wp.customHeader.initialize, false );425 // Initialize the custom header when the DOM is ready. 426 wp.customHeader = new CustomHeader(); 427 document.addEventListener( 'DOMContentLoaded', wp.customHeader.initialize.bind( wp.customHeader ), false ); 144 428 145 if ( 'customize' in window.wp ) { 429 // Selective refresh support in the Customizer. 430 if ( 'customize' in wp ) { 146 431 wp.customize.selectiveRefresh.bind( 'render-partials-response', function( response ) { 147 432 if ( 'custom_header_settings' in response ) { 148 433 settings = response.custom_header_settings; … … 151 436 152 437 wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) { 153 438 if ( 'custom_header' === placement.partial.id ) { 154 w indow.wp.customHeader.initialize();439 wp.customHeader.initialize(); 155 440 } 156 441 }); 157 442 } 158 443 159 })( window, w indow._wpCustomHeaderSettings || {} );444 })( window, wp, window._wpCustomHeaderSettings || {} ); -
src/wp-includes/script-loader.php
diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php index fadfb28..e405b13 100644
function wp_default_scripts( &$scripts ) { 481 481 $scripts->add( 'customize-nav-menus', "/wp-admin/js/customize-nav-menus$suffix.js", array( 'jquery', 'wp-backbone', 'customize-controls', 'accordion', 'nav-menu' ), false, 1 ); 482 482 $scripts->add( 'customize-preview-nav-menus', "/wp-includes/js/customize-preview-nav-menus$suffix.js", array( 'jquery', 'wp-util', 'customize-preview', 'customize-selective-refresh' ), false, 1 ); 483 483 484 $scripts->add( 'wp-custom-header', "/wp-includes/js/wp-custom-header$suffix.js", array( ), false, 1 );484 $scripts->add( 'wp-custom-header', "/wp-includes/js/wp-custom-header$suffix.js", array( 'wp-a11y' ), false, 1 ); 485 485 486 486 $scripts->add( 'accordion', "/wp-admin/js/accordion$suffix.js", array( 'jquery' ), false, 1 ); 487 487 -
src/wp-includes/theme.php
diff --git src/wp-includes/theme.php src/wp-includes/theme.php index d892ea7..a3af51c 100644
function get_header_video_settings() { 1381 1381 'height' => absint( $header->height ), 1382 1382 'minWidth' => 900, 1383 1383 'minHeight' => 500, 1384 'l10n' => array( 1385 'pause' => __( 'Pause' ), 1386 'play' => __( 'Play' ), 1387 'pauseSpeak' => __( 'Video is paused.'), 1388 'playSpeak' => __( 'Video is playing.'), 1389 ), 1384 1390 ); 1385 1391 1386 1392 if ( preg_match( '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#', $video_url ) ) {
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)