@@ -20,9 +20,6 @@ let sharedStrings = null
20
20
const entities = [ ]
21
21
const entityData = { }
22
22
23
- let readyResolver
24
- const ready = new Promise ( resolve => { readyResolver = resolve } )
25
-
26
23
/*********************************************************
27
24
* Widget Replacement logic
28
25
*********************************************************/
@@ -367,6 +364,22 @@ class DuckWidget {
367
364
}
368
365
}
369
366
367
+ /**
368
+ * Initialise the Click to Load feature, once the necessary details have been
369
+ * returned by the platform.
370
+ * @returns {Promise }
371
+ */
372
+ async function initCTL ( ) {
373
+ await replaceClickToLoadElements ( )
374
+
375
+ window . addEventListener ( 'ddg-ctp-replace-element' , ( { target } ) => {
376
+ replaceClickToLoadElements ( target )
377
+ } , { capture : true } )
378
+
379
+ // Inform surrogate scripts that CTP is ready
380
+ originalWindowDispatchEvent ( createCustomEvent ( 'ddg-ctp-ready' ) )
381
+ }
382
+
370
383
function replaceTrackingElement ( widget , trackingElement , placeholderElement , hideTrackingElement = false , currentPlaceholder = null ) {
371
384
widget . dispatchEvent ( trackingElement , 'ddg-ctp-tracking-element' )
372
385
@@ -479,14 +492,11 @@ async function replaceYouTubeCTL (trackingElement, widget, togglePlaceholder = f
479
492
}
480
493
481
494
// Show YouTube Preview for embedded video
482
- // TODO: Fix the hideTrackingElement option and reenable, or remove it. It's
483
- // disabled for YouTube videos so far since it caused multiple
484
- // placeholders to be displayed on the page.
485
495
if ( isYoutubePreviewsEnabled === true ) {
486
496
const { youTubePreview, shadowRoot } = await createYouTubePreview ( trackingElement , widget )
487
497
const currentPlaceholder = togglePlaceholder ? document . getElementById ( `yt-ctl-dialog-${ widget . widgetID } ` ) : null
488
498
replaceTrackingElement (
489
- widget , trackingElement , youTubePreview , /* hideTrackingElement= */ false , currentPlaceholder
499
+ widget , trackingElement , youTubePreview , /* hideTrackingElement= */ true , currentPlaceholder
490
500
)
491
501
showExtraUnblockIfShortPlaceholder ( shadowRoot , youTubePreview )
492
502
@@ -496,7 +506,7 @@ async function replaceYouTubeCTL (trackingElement, widget, togglePlaceholder = f
496
506
const { blockingDialog, shadowRoot } = await createYouTubeBlockingDialog ( trackingElement , widget )
497
507
const currentPlaceholder = togglePlaceholder ? document . getElementById ( `yt-ctl-preview-${ widget . widgetID } ` ) : null
498
508
replaceTrackingElement (
499
- widget , trackingElement , blockingDialog , /* hideTrackingElement= */ false , currentPlaceholder
509
+ widget , trackingElement , blockingDialog , /* hideTrackingElement= */ true , currentPlaceholder
500
510
)
501
511
showExtraUnblockIfShortPlaceholder ( shadowRoot , blockingDialog )
502
512
}
@@ -527,8 +537,6 @@ function showExtraUnblockIfShortPlaceholder (shadowRoot, placeholder) {
527
537
* in the document will be replaced instead.
528
538
*/
529
539
async function replaceClickToLoadElements ( targetElement ) {
530
- await ready
531
-
532
540
for ( const entity of Object . keys ( config ) ) {
533
541
for ( const widgetData of Object . values ( config [ entity ] . elementData ) ) {
534
542
const selector = widgetData . selectors . join ( )
@@ -1304,7 +1312,7 @@ async function createYouTubePreview (originalElement, widget) {
1304
1312
// Convention is that each function should be named the same as the sendMessage
1305
1313
// method we are calling into eg. calling `sendMessage('getClickToLoadState')`
1306
1314
// will result in a response routed to `updateHandlers.getClickToLoadState()`.
1307
- const messageResponseHandlers = {
1315
+ const updateHandlers = {
1308
1316
getClickToLoadState ( response ) {
1309
1317
devMode = response . devMode
1310
1318
isYoutubePreviewsEnabled = response . youtubePreviewsEnabled
@@ -1314,15 +1322,14 @@ const messageResponseHandlers = {
1314
1322
// first.
1315
1323
1316
1324
// Start Click to Load
1317
- window . addEventListener ( 'ddg-ctp-replace-element' , ( { target } ) => {
1318
- replaceClickToLoadElements ( target )
1319
- } , { capture : true } )
1320
-
1321
- // Inform surrogate scripts that CTP is ready
1322
- originalWindowDispatchEvent ( createCustomEvent ( 'ddg-ctp-ready' ) )
1323
-
1324
- // Mark the feature as ready, to allow placeholder replacements.
1325
- readyResolver ( )
1325
+ if ( document . readyState === 'complete' ) {
1326
+ initCTL ( )
1327
+ } else {
1328
+ // Content script loaded before page content, so wait for load.
1329
+ window . addEventListener ( 'load' , ( event ) => {
1330
+ initCTL ( )
1331
+ } )
1332
+ }
1326
1333
} ,
1327
1334
setYoutubePreviewsEnabled : function ( resp ) {
1328
1335
if ( resp ?. messageType && typeof resp ?. value === 'boolean' ) {
@@ -1339,8 +1346,6 @@ const messageResponseHandlers = {
1339
1346
}
1340
1347
}
1341
1348
1342
- const knownMessageResponseType = Object . prototype . hasOwnProperty . bind ( messageResponseHandlers )
1343
-
1344
1349
export function init ( args ) {
1345
1350
const websiteOwner = args ?. site ?. parentEntity
1346
1351
const settings = args ?. featureSettings ?. clickToPlay || { }
@@ -1406,32 +1411,17 @@ export function init (args) {
1406
1411
} )
1407
1412
1408
1413
// Request the current state of Click to Load from the platform.
1409
- // Note: When the response is received, the response handler finishes
1410
- // starting up the feature.
1414
+ // Note: When the response is received, initCTL() is then called by the
1415
+ // response handler to finish starting up the feature.
1411
1416
sendMessage ( 'getClickToLoadState' )
1412
1417
}
1413
1418
1414
- export function update ( message ) {
1415
- // TODO: Once all Click to Load messages include the feature property, drop
1416
- // messages that don't include the feature property too.
1417
- if ( message ?. feature && message ?. feature !== 'clickToLoad' ) return
1419
+ export function update ( args ) {
1420
+ const detail = args && args . detail
1421
+ if ( ! ( detail && detail . func ) ) { return }
1418
1422
1419
- const messageType = message ?. messageType
1420
- if ( ! messageType ) return
1423
+ const fn = updateHandlers [ detail . func ]
1424
+ if ( typeof fn !== 'function' ) { return }
1421
1425
1422
- // Message responses.
1423
- if ( messageType === 'response' ) {
1424
- const messageResponseType = message ?. responseMessageType
1425
- if ( messageResponseType && knownMessageResponseType ( messageResponseType ) ) {
1426
- return messageResponseHandlers [ messageResponseType ] ( message . response )
1427
- }
1428
- }
1429
-
1430
- // Other known update messages.
1431
- if ( messageType === 'displayClickToLoadPlaceholders' ) {
1432
- // TODO: Pass `message.options.ruleAction` through, that way only
1433
- // content corresponding to the entity for that ruleAction need to
1434
- // be replaced with a placeholder.
1435
- return replaceClickToLoadElements ( )
1436
- }
1426
+ fn ( detail . response )
1437
1427
}
0 commit comments