@penskemediacorp/larva-js 1.19.0 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/video-showcase.js +7 -7
- package/package.json +2 -2
- package/src/__tests__/fixtures/markup.js +1 -1
- package/src/__tests__/utils/removeDesktopXlClasses.test.js +6 -4
- package/src/interface/Collapsible/Collapsible.js +31 -17
- package/src/interface/Collapsible/index.js +6 -2
- package/src/interface/EmailCapture/EmailCapture.js +17 -13
- package/src/interface/EmailCapture/index.js +6 -3
- package/src/interface/ExpandableSearch/ExpandableSearch.js +21 -21
- package/src/interface/ExpandableSearch/index.js +4 -4
- package/src/interface/Flickity/index.js +16 -11
- package/src/interface/MegaMenu/MegaMenu.js +22 -13
- package/src/interface/MegaMenu/index.js +12 -10
- package/src/interface/MobileHeightToggle/MobileHeightToggle.js +5 -4
- package/src/interface/MobileHeightToggle/MobileHeightToggle.test.js +22 -21
- package/src/interface/MobileHeightToggle/index.js +9 -8
- package/src/interface/Navigable/Navigable.js +29 -18
- package/src/interface/Navigable/index.js +1 -1
- package/src/interface/PopOver/PopOver.js +15 -15
- package/src/interface/PopOver/index.js +4 -4
- package/src/interface/ProfileFilter/ProfileFilter.js +40 -35
- package/src/interface/ProfileFilter/__test__/ProfileFilter.test.js +38 -31
- package/src/interface/ProfileFilter/index.js +2 -2
- package/src/interface/SelectNav/SelectNav.js +8 -6
- package/src/interface/SelectNav/index.js +2 -3
- package/src/interface/SideSkinAd/SideSkinAd.js +0 -2
- package/src/interface/SideSkinAd/index.js +10 -10
- package/src/interface/TabsManager/TabsManager.js +11 -6
- package/src/interface/TabsManager/index.js +1 -1
- package/src/interface/Tooltip/Tooltip.js +0 -1
- package/src/interface/VideoShowcase/VideoShowcase.js +77 -46
- package/src/interface/VideoShowcase/index.js +6 -2
- package/src/utils/ajaxIconSprite.js +4 -4
- package/src/utils/dom.js +6 -3
- package/src/utils/removeDesktopXlClasses.js +5 -7
- package/src/utils/webfontConfig.js +26 -40
|
@@ -30,34 +30,34 @@ describe( 'initProfileFilter', () => {
|
|
|
30
30
|
initProfileFilter();
|
|
31
31
|
|
|
32
32
|
it( 'initializes the class', () => {
|
|
33
|
-
|
|
33
|
+
const obj =
|
|
34
|
+
document.querySelector( '.js-ProfileFilter' ).pmcProfileFilter;
|
|
34
35
|
|
|
35
36
|
assert.equal( typeof obj, 'object' );
|
|
36
37
|
} );
|
|
37
|
-
|
|
38
38
|
} );
|
|
39
39
|
|
|
40
40
|
describe( 'ProfileFilter', () => {
|
|
41
|
-
|
|
41
|
+
const pf = new ProfileFilter(
|
|
42
|
+
document.querySelector( '.js-ProfileFilter' )
|
|
43
|
+
);
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
const allCheckboxes = [
|
|
46
|
+
...document.querySelectorAll( 'input[type="checkbox"]' ),
|
|
47
|
+
];
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
allCheckboxes[2], // top200location, new-york
|
|
47
|
-
allCheckboxes[4], // collectingarea, llamas
|
|
48
|
-
allCheckboxes[5]
|
|
49
|
+
const checkedBoxes = [
|
|
50
|
+
allCheckboxes[ 2 ], // top200location, new-york
|
|
51
|
+
allCheckboxes[ 4 ], // collectingarea, llamas
|
|
52
|
+
allCheckboxes[ 5 ], // collectingarea, coffee
|
|
49
53
|
];
|
|
50
54
|
|
|
51
55
|
it( 'gets initial query from url', () => {
|
|
52
|
-
|
|
53
56
|
// let obj = document.querySelector( '.js-ProfileFilter' ).pmcProfileFilter;
|
|
54
57
|
const windowLocationSearchMock = '?filter_top200year=2020%2C2019';
|
|
55
58
|
const expectedObject = {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
'2020',
|
|
59
|
-
'2019'
|
|
60
|
-
]
|
|
59
|
+
page: 1,
|
|
60
|
+
filter_top200year: [ '2020', '2019' ],
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
pf.setQueryObject( windowLocationSearchMock );
|
|
@@ -89,14 +89,9 @@ describe( 'ProfileFilter', () => {
|
|
|
89
89
|
|
|
90
90
|
it( 'creates an object with the names/values from checked boxes', () => {
|
|
91
91
|
const expectedObject = {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
'filter_collectingarea': [
|
|
96
|
-
'llamas',
|
|
97
|
-
'coffee'
|
|
98
|
-
],
|
|
99
|
-
'page': 1
|
|
92
|
+
filter_top200location: [ 'new-york' ],
|
|
93
|
+
filter_collectingarea: [ 'llamas', 'coffee' ],
|
|
94
|
+
page: 1,
|
|
100
95
|
};
|
|
101
96
|
|
|
102
97
|
pf.setQueryObject();
|
|
@@ -106,13 +101,16 @@ describe( 'ProfileFilter', () => {
|
|
|
106
101
|
} );
|
|
107
102
|
|
|
108
103
|
it( 'creates query string from the object', () => {
|
|
109
|
-
const expectedUrl =
|
|
104
|
+
const expectedUrl =
|
|
105
|
+
'filter_top200location=new-york&filter_collectingarea=llamas%2Ccoffee&page=1'; // comma is encoded
|
|
110
106
|
|
|
111
107
|
assert.equal( pf.createQueryStringFromObject(), expectedUrl );
|
|
112
108
|
} );
|
|
113
109
|
|
|
114
110
|
it( 'updates the action URL', () => {
|
|
115
|
-
const expectedUrl =
|
|
111
|
+
const expectedUrl =
|
|
112
|
+
pf.actionUrl +
|
|
113
|
+
'?filter_top200location=new-york&filter_collectingarea=llamas%2Ccoffee&page=1'; // comma is encoded
|
|
116
114
|
|
|
117
115
|
pf.updateActionAttr();
|
|
118
116
|
|
|
@@ -120,21 +118,25 @@ describe( 'ProfileFilter', () => {
|
|
|
120
118
|
} );
|
|
121
119
|
|
|
122
120
|
it( 'gets url to fetch from rest api', () => {
|
|
123
|
-
const expectedUrl =
|
|
121
|
+
const expectedUrl =
|
|
122
|
+
pf.restUrlBase +
|
|
123
|
+
'?top200location=new-york&collectingarea=llamas%2Ccoffee&page=1'; // comma is encoded
|
|
124
124
|
|
|
125
125
|
assert.equal( pf.getRestEndpointUrl(), expectedUrl );
|
|
126
126
|
} );
|
|
127
127
|
|
|
128
128
|
it( 'increments the paged value when clicked', () => {
|
|
129
|
-
|
|
130
129
|
pf.increasePage();
|
|
131
130
|
|
|
132
131
|
assert.equal( pf.page, 2 );
|
|
133
132
|
} );
|
|
134
133
|
|
|
135
134
|
it( 'updates the fetch url with new paged value', () => {
|
|
136
|
-
const expectedUrl =
|
|
137
|
-
|
|
135
|
+
const expectedUrl =
|
|
136
|
+
pf.restUrlBase +
|
|
137
|
+
'?top200location=new-york&collectingarea=llamas%2Ccoffee&page=2'; // comma is encoded
|
|
138
|
+
const searchUrlStub =
|
|
139
|
+
'?filter_top200location=new-york&filter_collectingarea=llamas%2Ccoffee&page=1';
|
|
138
140
|
|
|
139
141
|
pf.setQueryObject( searchUrlStub ); // This would be called by loadMoreClick
|
|
140
142
|
|
|
@@ -145,14 +147,19 @@ describe( 'ProfileFilter', () => {
|
|
|
145
147
|
pf.maxPages = 2; // this.queryObject.page is currently 2
|
|
146
148
|
pf.maybeHideLoadMore();
|
|
147
149
|
|
|
148
|
-
assert.equal(
|
|
150
|
+
assert.equal(
|
|
151
|
+
pf.loadMoreButton.classList.contains( 'a-hidden' ),
|
|
152
|
+
true
|
|
153
|
+
);
|
|
149
154
|
} );
|
|
150
155
|
|
|
151
156
|
it( 'shows load more if there are more pages', () => {
|
|
152
157
|
pf.maxPages = 6; // this.queryObject.page is currently 2
|
|
153
158
|
pf.maybeHideLoadMore();
|
|
154
159
|
|
|
155
|
-
assert.equal(
|
|
160
|
+
assert.equal(
|
|
161
|
+
pf.loadMoreButton.classList.contains( 'a-hidden' ),
|
|
162
|
+
false
|
|
163
|
+
);
|
|
156
164
|
} );
|
|
157
|
-
|
|
158
165
|
} );
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ProfileFilter from './ProfileFilter';
|
|
2
2
|
|
|
3
3
|
export default function initProfileFilter() {
|
|
4
|
-
const filters = [ ...
|
|
5
|
-
filters.forEach( el => el.ProfileFilter = new ProfileFilter( el ) );
|
|
4
|
+
const filters = [ ...document.querySelectorAll( '.js-ProfileFilter' ) ];
|
|
5
|
+
filters.forEach( ( el ) => ( el.ProfileFilter = new ProfileFilter( el ) ) );
|
|
6
6
|
}
|
|
@@ -10,25 +10,27 @@
|
|
|
10
10
|
* It is build to work with the patterns `o-select-nav` and `c-select-option`
|
|
11
11
|
*
|
|
12
12
|
* @since 11-22-2019
|
|
13
|
-
*/
|
|
13
|
+
*/
|
|
14
14
|
|
|
15
15
|
export default class SelectNav {
|
|
16
|
-
|
|
17
16
|
constructor( el ) {
|
|
18
|
-
|
|
19
17
|
this.el = el;
|
|
20
18
|
|
|
21
19
|
this.selectEl = el.querySelector( '.js-SelectNav-select' );
|
|
22
20
|
|
|
23
21
|
// If there is a class js-SelectNav-redirect, then only redirect.
|
|
24
22
|
if ( el.classList.contains( 'js-SelectNav-redirect' ) ) {
|
|
25
|
-
this.selectEl.addEventListener(
|
|
23
|
+
this.selectEl.addEventListener(
|
|
24
|
+
'change',
|
|
25
|
+
this.onChange.bind( this )
|
|
26
|
+
);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
onChange() {
|
|
31
|
-
const redirectTo =
|
|
31
|
+
const redirectTo =
|
|
32
|
+
this.selectEl.options[ this.selectEl.selectedIndex ].dataset
|
|
33
|
+
.selectUrl;
|
|
32
34
|
if ( redirectTo ) {
|
|
33
35
|
window.location.href = redirectTo;
|
|
34
36
|
}
|
|
@@ -2,8 +2,7 @@ import SelectNav from './SelectNav';
|
|
|
2
2
|
|
|
3
3
|
// Initialize all SelectNav.
|
|
4
4
|
export default function initSelectNav() {
|
|
5
|
+
const SelectNavs = [ ...document.querySelectorAll( '.js-SelectNav' ) ];
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
SelectNavs.forEach( el => new SelectNav( el ) );
|
|
7
|
+
SelectNavs.forEach( ( el ) => new SelectNav( el ) );
|
|
9
8
|
}
|
|
@@ -9,13 +9,11 @@
|
|
|
9
9
|
* Use a counter to ensure this script only runs one time.
|
|
10
10
|
**/
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
import removeDesktopXlClasses from '../../utils/removeDesktopXlClasses';
|
|
14
13
|
|
|
15
14
|
// TODO: Should refactor to follow our exporting classes pattern, and
|
|
16
15
|
// include the conditions from index.js in the class
|
|
17
16
|
export default function reflowForSideSkinAd() {
|
|
18
|
-
|
|
19
17
|
if ( undefined === window.pmc_side_skin_classes_removed ) {
|
|
20
18
|
document.documentElement.classList.add( 'has-side-skins' );
|
|
21
19
|
removeDesktopXlClasses();
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
// eslint-disable camelcase
|
|
2
2
|
import reflowForSideSkinAd from './SideSkinAd';
|
|
3
3
|
|
|
4
|
-
export default function initSideSkinAd
|
|
5
|
-
|
|
4
|
+
export default function initSideSkinAd( e ) {
|
|
6
5
|
const parametersMessagePattern = 'pmcadm:dfp:skinad:parameters';
|
|
7
6
|
let serializedParameters = '';
|
|
8
7
|
let atlasSkinObj = '';
|
|
9
8
|
|
|
10
9
|
if ( 'object' === typeof window.pmc_dfp_skin ) {
|
|
11
10
|
atlasSkinObj = window.pmc_dfp_skin;
|
|
12
|
-
} else {
|
|
13
|
-
|
|
14
|
-
atlasSkinObj = window.pmc.skinAds;
|
|
15
|
-
}
|
|
11
|
+
} else if ( undefined !== window.pmc && undefined !== window.pmc.skinAds ) {
|
|
12
|
+
atlasSkinObj = window.pmc.skinAds;
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
if ( 'string' === typeof e.data && 'object' === typeof atlasSkinObj ) {
|
|
19
|
-
if (
|
|
20
|
-
|
|
16
|
+
if (
|
|
17
|
+
parametersMessagePattern ===
|
|
18
|
+
e.data.substring( 0, parametersMessagePattern.length )
|
|
19
|
+
) {
|
|
20
|
+
serializedParameters = e.data.substring(
|
|
21
|
+
parametersMessagePattern.length
|
|
22
|
+
);
|
|
21
23
|
|
|
22
24
|
if ( serializedParameters ) {
|
|
23
|
-
|
|
24
25
|
reflowForSideSkinAd();
|
|
25
26
|
|
|
26
27
|
atlasSkinObj.refresh_skin_rails();
|
|
27
28
|
}
|
|
28
|
-
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* @todo Add hover support
|
|
5
5
|
* @see https://bitbucket.org/penskemediacorp/pmc-indiewire-2016/src/master/assets/src/js/modules/TabsManager/TabsManager.js
|
|
6
6
|
*
|
|
7
|
-
*/
|
|
7
|
+
*/
|
|
8
8
|
|
|
9
9
|
export default class TabsManager {
|
|
10
|
-
|
|
11
10
|
/**
|
|
12
11
|
* Initialize
|
|
13
12
|
*
|
|
@@ -17,17 +16,20 @@ export default class TabsManager {
|
|
|
17
16
|
this.el = el;
|
|
18
17
|
this.customInteraction = 'click';
|
|
19
18
|
this.toggleEl = this.el.querySelectorAll( '.js-TabsToggle' );
|
|
20
|
-
this.panels = [ ...
|
|
19
|
+
this.panels = [ ...this.el.querySelectorAll( '.js-TabsPanel' ) ];
|
|
21
20
|
|
|
22
21
|
this.onClick = this.onClick.bind( this );
|
|
23
22
|
this.toggle = this.toggle.bind( this );
|
|
24
23
|
this.deactivatePanels = this.deactivatePanels.bind( this );
|
|
25
24
|
|
|
26
|
-
this.toggleEl.forEach(
|
|
25
|
+
this.toggleEl.forEach( ( toggle ) =>
|
|
26
|
+
toggle.addEventListener( 'click', this.onClick )
|
|
27
|
+
);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Trigger Toggle event
|
|
32
|
+
*
|
|
31
33
|
* @param {event} event Triggered event
|
|
32
34
|
*/
|
|
33
35
|
onClick( event ) {
|
|
@@ -42,6 +44,7 @@ export default class TabsManager {
|
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
46
|
* Find and activate desired tab panel
|
|
47
|
+
*
|
|
45
48
|
* @param {event} event Previously triggered event
|
|
46
49
|
*/
|
|
47
50
|
toggle( event ) {
|
|
@@ -73,12 +76,14 @@ export default class TabsManager {
|
|
|
73
76
|
* Remove active status from all items
|
|
74
77
|
*/
|
|
75
78
|
deactivatePanels() {
|
|
76
|
-
const toggles = this.el.querySelectorAll(
|
|
79
|
+
const toggles = this.el.querySelectorAll(
|
|
80
|
+
'.js-TabsToggle.is-active, .js-TabsPanel.is-active'
|
|
81
|
+
);
|
|
77
82
|
|
|
78
83
|
if ( ! toggles || 0 === toggles.length ) {
|
|
79
84
|
return;
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
toggles.forEach( item => item.classList.remove( 'is-active' ) );
|
|
87
|
+
toggles.forEach( ( item ) => item.classList.remove( 'is-active' ) );
|
|
83
88
|
}
|
|
84
89
|
}
|
|
@@ -4,6 +4,6 @@ export default function initTabsManager() {
|
|
|
4
4
|
const tabs = [ ...document.querySelectorAll( '.js-Tabs' ) ];
|
|
5
5
|
|
|
6
6
|
if ( tabs.length ) {
|
|
7
|
-
tabs.forEach( el => el.pmcTabsManager = new TabsManager( el ) );
|
|
7
|
+
tabs.forEach( ( el ) => ( el.pmcTabsManager = new TabsManager( el ) ) );
|
|
8
8
|
}
|
|
9
9
|
}
|
|
@@ -21,18 +21,21 @@ import initCollapsibles from '../Collapsible';
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
export default class VideoShowcase {
|
|
24
|
-
|
|
25
24
|
constructor( el ) {
|
|
26
25
|
this.el = el;
|
|
27
26
|
|
|
28
27
|
// All triggers that contain video IDs to be played on click.
|
|
29
|
-
this.triggers = [
|
|
28
|
+
this.triggers = [
|
|
29
|
+
...el.querySelectorAll( '[data-video-showcase-trigger]' ),
|
|
30
|
+
];
|
|
30
31
|
|
|
31
32
|
// The main player that also, optionally may be a trigger. It should contain an iframe and #jwplayerContainer.
|
|
32
33
|
this.player = el.querySelector( '[data-video-showcase-player]' );
|
|
33
34
|
|
|
34
35
|
// Elements within the player that will be hidden after the first play.
|
|
35
|
-
this.elementsToHide = [
|
|
36
|
+
this.elementsToHide = [
|
|
37
|
+
...this.el.querySelectorAll( '.is-to-be-hidden' ),
|
|
38
|
+
];
|
|
36
39
|
|
|
37
40
|
// Attributes that will be removed from the player once it is initialized. Only relevant for players that are
|
|
38
41
|
// also triggers.
|
|
@@ -42,13 +45,13 @@ export default class VideoShowcase {
|
|
|
42
45
|
'data-video-showcase-dek',
|
|
43
46
|
'data-video-showcase-permalink',
|
|
44
47
|
'data-video-showcase-type',
|
|
45
|
-
'href'
|
|
48
|
+
'href',
|
|
46
49
|
];
|
|
47
50
|
|
|
48
51
|
/**
|
|
49
52
|
* State.
|
|
50
53
|
*
|
|
51
|
-
* @type {
|
|
54
|
+
* @type {Object}
|
|
52
55
|
* @property {boolean} isPlayerSetup - Whether or not the player has been setup or played. Set in onFirstTimePlay()
|
|
53
56
|
* @property {string} videoID - A Youtube or JWPlayer ID extracted from a `data-video-showcase-trigger` e.g. f1FX5wvC3DA
|
|
54
57
|
* @property {string} videoType - "youtube" or "jwplayer" from `data-video-showcase-type`
|
|
@@ -57,7 +60,7 @@ export default class VideoShowcase {
|
|
|
57
60
|
isPlayerSetup: false,
|
|
58
61
|
hasSocialShare: false,
|
|
59
62
|
videoID: '',
|
|
60
|
-
videoType: ''
|
|
63
|
+
videoType: '',
|
|
61
64
|
};
|
|
62
65
|
|
|
63
66
|
/**
|
|
@@ -65,7 +68,7 @@ export default class VideoShowcase {
|
|
|
65
68
|
*
|
|
66
69
|
* Note: the title and dek are using class selectors so they can be added to existing patterns.
|
|
67
70
|
*
|
|
68
|
-
* @type {
|
|
71
|
+
* @type {Object}
|
|
69
72
|
* @property {element} title - A anchor element that will receive both a permalink and heading text.
|
|
70
73
|
* @property {element} dek - An element containing a direct child paragraph that will support the dek text.
|
|
71
74
|
* @property {element} iframe - The iframe that will recieve an src when a trigger with the Youtube video type is clicked.
|
|
@@ -74,19 +77,30 @@ export default class VideoShowcase {
|
|
|
74
77
|
*/
|
|
75
78
|
this.playerUI = {
|
|
76
79
|
title: el.querySelector( '.js-VideoShowcase-title' ),
|
|
77
|
-
sponsoredBadge: el.querySelector(
|
|
80
|
+
sponsoredBadge: el.querySelector(
|
|
81
|
+
'.js-video-showcase-sponsored-badge'
|
|
82
|
+
),
|
|
78
83
|
dek: el.querySelector( '.js-VideoShowcase-dek' ),
|
|
79
84
|
iframe: el.querySelector( '[data-video-showcase-iframe]' ),
|
|
80
|
-
jwplayerContainer: el.querySelector(
|
|
81
|
-
|
|
85
|
+
jwplayerContainer: el.querySelector(
|
|
86
|
+
'[data-video-showcase-jwplayer], #jwplayerContainer'
|
|
87
|
+
),
|
|
88
|
+
social: el.querySelector(
|
|
89
|
+
'[data-video-showcase-player-social-share]'
|
|
90
|
+
),
|
|
82
91
|
};
|
|
83
92
|
|
|
84
93
|
this.init();
|
|
85
|
-
if (this.player.dataset.videoShowcaseAutoplay) {
|
|
86
|
-
this.handleTriggerClick(null, this.triggers[0]);
|
|
94
|
+
if ( this.player.dataset.videoShowcaseAutoplay ) {
|
|
95
|
+
this.handleTriggerClick( null, this.triggers[ 0 ] );
|
|
87
96
|
} else {
|
|
88
|
-
delegateEvent(
|
|
89
|
-
|
|
97
|
+
delegateEvent(
|
|
98
|
+
this.el,
|
|
99
|
+
'click',
|
|
100
|
+
'[data-video-showcase-trigger]',
|
|
101
|
+
this.handleTriggerClick.bind( this )
|
|
102
|
+
);
|
|
103
|
+
}
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
/**
|
|
@@ -111,7 +125,7 @@ export default class VideoShowcase {
|
|
|
111
125
|
*
|
|
112
126
|
* @param {element} el - A trigger.
|
|
113
127
|
*
|
|
114
|
-
* @return {
|
|
128
|
+
* @return {Object} - An object containing the data needed to update the player.
|
|
115
129
|
* @property {string} title - Title text from the `data-video-showcase-title`
|
|
116
130
|
* @property {string} dek - Dek text from the `data-video-showcase-dek`
|
|
117
131
|
* @property {string} permalink - Link from `data-video-showcase-permalink`
|
|
@@ -127,12 +141,14 @@ export default class VideoShowcase {
|
|
|
127
141
|
sponsored: el.dataset.videoShowcaseSponsored,
|
|
128
142
|
dek: el.dataset.videoShowcaseDek,
|
|
129
143
|
permalink: el.dataset.videoShowcasePermalink,
|
|
130
|
-
socialString: ( function( data ) {
|
|
144
|
+
socialString: ( function ( data ) {
|
|
131
145
|
if ( window.wp && hasSocialShare ) {
|
|
132
|
-
|
|
146
|
+
const template = wp.template(
|
|
147
|
+
`trigger-social-share-${ triggerID }`
|
|
148
|
+
);
|
|
133
149
|
return template( data );
|
|
134
150
|
}
|
|
135
|
-
}()
|
|
151
|
+
} )(),
|
|
136
152
|
};
|
|
137
153
|
}
|
|
138
154
|
|
|
@@ -142,14 +158,14 @@ export default class VideoShowcase {
|
|
|
142
158
|
* Apply the assembled data to the UI.
|
|
143
159
|
*
|
|
144
160
|
* @param {element} el - A trigger.
|
|
145
|
-
* @param {
|
|
161
|
+
* @param {Object} data - An object of data from getPlayerCardData.
|
|
146
162
|
*/
|
|
147
163
|
|
|
148
164
|
updatePlayerCardData( el, data ) {
|
|
149
165
|
if ( this.playerUI.title && data.title ) {
|
|
150
166
|
this.playerUI.title.innerText = data.title;
|
|
151
167
|
}
|
|
152
|
-
|
|
168
|
+
|
|
153
169
|
if ( this.playerUI.title && data.permalink ) {
|
|
154
170
|
this.playerUI.title.setAttribute( 'href', data.permalink );
|
|
155
171
|
}
|
|
@@ -172,7 +188,9 @@ export default class VideoShowcase {
|
|
|
172
188
|
}
|
|
173
189
|
|
|
174
190
|
updateCardSocialShare( html ) {
|
|
175
|
-
this.playerUI.social.removeChild(
|
|
191
|
+
this.playerUI.social.removeChild(
|
|
192
|
+
this.playerUI.social.querySelector( 'ul' )
|
|
193
|
+
);
|
|
176
194
|
|
|
177
195
|
// NOTE: html comes from JS template with escaped data.
|
|
178
196
|
this.playerUI.social.insertAdjacentHTML( 'beforeend', html );
|
|
@@ -189,17 +207,16 @@ export default class VideoShowcase {
|
|
|
189
207
|
* @param {string} type - "youtube" or "jwplayer"
|
|
190
208
|
*/
|
|
191
209
|
returnUrl( id, type ) {
|
|
192
|
-
|
|
193
210
|
if ( 'youtube' === type ) {
|
|
194
|
-
return `https://www.youtube.com/embed/${id}`;
|
|
211
|
+
return `https://www.youtube.com/embed/${ id }`;
|
|
195
212
|
}
|
|
196
213
|
|
|
197
214
|
if ( 'jwplayer' === type ) {
|
|
198
|
-
return `https://content.jwplatform.com/feeds/${id}.json`;
|
|
215
|
+
return `https://content.jwplatform.com/feeds/${ id }.json`;
|
|
199
216
|
}
|
|
200
217
|
|
|
201
218
|
if ( 'twitch' === type ) {
|
|
202
|
-
return `https://player.twitch.tv/?video=${id}`;
|
|
219
|
+
return `https://player.twitch.tv/?video=${ id }`;
|
|
203
220
|
}
|
|
204
221
|
}
|
|
205
222
|
|
|
@@ -210,7 +227,10 @@ export default class VideoShowcase {
|
|
|
210
227
|
*/
|
|
211
228
|
playYoutube( youtubeUrl ) {
|
|
212
229
|
this.playerUI.iframe.removeAttribute( 'hidden' );
|
|
213
|
-
this.playerUI.iframe.setAttribute(
|
|
230
|
+
this.playerUI.iframe.setAttribute(
|
|
231
|
+
'src',
|
|
232
|
+
`${ youtubeUrl }?rel=0&autoplay=1&showinfo=0&controls=2&rel=0&modestbranding=0`
|
|
233
|
+
);
|
|
214
234
|
}
|
|
215
235
|
|
|
216
236
|
/**
|
|
@@ -218,9 +238,12 @@ export default class VideoShowcase {
|
|
|
218
238
|
*
|
|
219
239
|
* @param {string} twitchUrl - A Twitch embed URL from returnUrl.
|
|
220
240
|
*/
|
|
221
|
-
|
|
241
|
+
playTwitch( twitchUrl ) {
|
|
222
242
|
this.playerUI.iframe.removeAttribute( 'hidden' );
|
|
223
|
-
this.playerUI.iframe.setAttribute(
|
|
243
|
+
this.playerUI.iframe.setAttribute(
|
|
244
|
+
'src',
|
|
245
|
+
`${ twitchUrl }&autoplay=true&parent=${ window.location.hostname }`
|
|
246
|
+
);
|
|
224
247
|
}
|
|
225
248
|
|
|
226
249
|
/**
|
|
@@ -232,21 +255,21 @@ export default class VideoShowcase {
|
|
|
232
255
|
* getPlaylist() first to retrieve an individual video, then play it, but this was working.
|
|
233
256
|
*
|
|
234
257
|
* @link https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#playlist
|
|
235
|
-
*
|
|
258
|
+
* @param playlistUrl
|
|
236
259
|
* @param {string} jwplayerUrl - A Youtube embed URL from returnUrl.
|
|
237
260
|
*/
|
|
238
261
|
playJW( playlistUrl ) {
|
|
239
|
-
|
|
240
262
|
this.playerUI.jwplayerContainer.removeAttribute( 'hidden' );
|
|
241
263
|
|
|
242
264
|
if ( window.pmc_jwplayer ) {
|
|
243
|
-
window
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
265
|
+
window
|
|
266
|
+
.pmc_jwplayer( this.playerUI.jwplayerContainer.id )
|
|
267
|
+
.setup( {
|
|
268
|
+
playlist: playlistUrl,
|
|
269
|
+
aspectratio: '16:9',
|
|
270
|
+
} )
|
|
271
|
+
.play();
|
|
248
272
|
}
|
|
249
|
-
|
|
250
273
|
}
|
|
251
274
|
|
|
252
275
|
/**
|
|
@@ -258,11 +281,11 @@ export default class VideoShowcase {
|
|
|
258
281
|
* @param {element} el - Clicked trigger element.
|
|
259
282
|
*/
|
|
260
283
|
handleTriggerClick( e, el ) {
|
|
261
|
-
if (e) {
|
|
284
|
+
if ( e ) {
|
|
262
285
|
e.preventDefault();
|
|
263
286
|
}
|
|
264
287
|
|
|
265
|
-
|
|
288
|
+
const previousVideoType = this.state.videoType;
|
|
266
289
|
|
|
267
290
|
this.state.videoType = el.dataset.videoShowcaseType;
|
|
268
291
|
this.state.videoID = el.dataset.videoShowcaseTrigger;
|
|
@@ -282,7 +305,7 @@ export default class VideoShowcase {
|
|
|
282
305
|
* @param {string} type - "youtube" or "jwplayer" or "twitch"
|
|
283
306
|
*/
|
|
284
307
|
playVideo( id, type ) {
|
|
285
|
-
|
|
308
|
+
const url = this.returnUrl( id, type );
|
|
286
309
|
|
|
287
310
|
if ( 'youtube' === type ) {
|
|
288
311
|
this.playYoutube( url );
|
|
@@ -300,8 +323,14 @@ export default class VideoShowcase {
|
|
|
300
323
|
// Remove any trigger-related data attributes and hide any elements that are not relevant for the player.
|
|
301
324
|
onFirstTimePlay() {
|
|
302
325
|
if ( false === this.state.isPlayerSetup ) {
|
|
303
|
-
this.
|
|
304
|
-
|
|
326
|
+
this.el.dispatchEvent( new CustomEvent( 'firstVideoPlay' ) );
|
|
327
|
+
|
|
328
|
+
this.elementsToHide.forEach( ( e ) =>
|
|
329
|
+
e.setAttribute( 'hidden', '' )
|
|
330
|
+
);
|
|
331
|
+
this.attributesToRemoveFromPlayer.forEach( ( attr ) =>
|
|
332
|
+
this.player.parentNode.removeAttribute( attr )
|
|
333
|
+
);
|
|
305
334
|
this.state.isPlayerSetup = true;
|
|
306
335
|
}
|
|
307
336
|
}
|
|
@@ -314,7 +343,9 @@ export default class VideoShowcase {
|
|
|
314
343
|
* @param {string} id - Youtube or JWplayer ID, should be from this.state.videoID, e.g. f1FX5wvC3DA
|
|
315
344
|
*/
|
|
316
345
|
updatePlayerUI( id ) {
|
|
317
|
-
const clickedTrigger = this.el.querySelector(
|
|
346
|
+
const clickedTrigger = this.el.querySelector(
|
|
347
|
+
`[data-video-showcase-trigger="${ id }"]`
|
|
348
|
+
);
|
|
318
349
|
const data = this.getPlayerCardData( clickedTrigger );
|
|
319
350
|
|
|
320
351
|
this.setActiveTrigger( id );
|
|
@@ -333,7 +364,6 @@ export default class VideoShowcase {
|
|
|
333
364
|
* @param {string} pastType - Youtube or JWplayer ID, should be from this.state.videoID, e.g. f1FX5wvC3DA
|
|
334
365
|
*/
|
|
335
366
|
resetPlayer( pastType ) {
|
|
336
|
-
|
|
337
367
|
if ( 'jwplayer' === pastType && window.pmc_jwplayer ) {
|
|
338
368
|
window.pmc_jwplayer( 'jwplayerContainer' ).remove();
|
|
339
369
|
this.playerUI.jwplayerContainer.setAttribute( 'hidden', '' );
|
|
@@ -347,7 +377,7 @@ export default class VideoShowcase {
|
|
|
347
377
|
|
|
348
378
|
// Remove `is-playing` class from all triggers.
|
|
349
379
|
resetAllTriggers() {
|
|
350
|
-
this.triggers.forEach( el => el.classList.remove( 'is-playing' ) );
|
|
380
|
+
this.triggers.forEach( ( el ) => el.classList.remove( 'is-playing' ) );
|
|
351
381
|
}
|
|
352
382
|
|
|
353
383
|
/**
|
|
@@ -356,7 +386,9 @@ export default class VideoShowcase {
|
|
|
356
386
|
* @param {string} id - Youtube or JWplayer ID, should be from this.state.videoID, e.g. f1FX5wvC3DA
|
|
357
387
|
*/
|
|
358
388
|
setActiveTrigger( id ) {
|
|
359
|
-
|
|
389
|
+
const trigger = this.el.querySelector(
|
|
390
|
+
`[data-video-showcase-trigger="${ id }"]`
|
|
391
|
+
);
|
|
360
392
|
|
|
361
393
|
this.resetAllTriggers();
|
|
362
394
|
|
|
@@ -364,5 +396,4 @@ export default class VideoShowcase {
|
|
|
364
396
|
trigger.classList.add( 'is-playing' );
|
|
365
397
|
}
|
|
366
398
|
}
|
|
367
|
-
|
|
368
399
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import VideoShowcase from './VideoShowcase';
|
|
2
2
|
|
|
3
3
|
export default function initVideoShowcase() {
|
|
4
|
-
const videoShowcases = [
|
|
4
|
+
const videoShowcases = [
|
|
5
|
+
...document.querySelectorAll( '[data-video-showcase]' ),
|
|
6
|
+
];
|
|
5
7
|
|
|
6
8
|
if ( videoShowcases.length ) {
|
|
7
|
-
videoShowcases.forEach(
|
|
9
|
+
videoShowcases.forEach(
|
|
10
|
+
( el ) => ( el.pmcVideoShowcase = new VideoShowcase( el ) )
|
|
11
|
+
);
|
|
8
12
|
}
|
|
9
13
|
}
|
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
* containing the responseText.
|
|
4
4
|
*
|
|
5
5
|
* @param {string} buildPath
|
|
6
|
+
* @param iconPath
|
|
6
7
|
*/
|
|
7
|
-
export default function( iconPath ) {
|
|
8
|
-
|
|
8
|
+
export default function ( iconPath ) {
|
|
9
9
|
const ajax = new XMLHttpRequest();
|
|
10
10
|
const div = document.createElement( 'div' );
|
|
11
11
|
|
|
12
12
|
ajax.open( 'GET', iconPath, true );
|
|
13
13
|
ajax.send();
|
|
14
14
|
|
|
15
|
-
ajax.onload = function() {
|
|
15
|
+
ajax.onload = function () {
|
|
16
16
|
div.id = 'icon-sprite';
|
|
17
17
|
|
|
18
18
|
// NOTE: Ignore WPCS WARNING for innerHTML, it's related to svg icon.
|
|
19
19
|
// As this must be handled by innerHTML only.
|
|
20
20
|
div.innerHTML = ajax.responseText; // @codingStandardsIgnoreLine
|
|
21
21
|
|
|
22
|
-
document.body.insertBefore( div, document.body.childNodes[0] );
|
|
22
|
+
document.body.insertBefore( div, document.body.childNodes[ 0 ] );
|
|
23
23
|
};
|
|
24
24
|
}
|