@@ -44,6 +44,51 @@ export const isComplete = (session, model, audioComplete, elementContext) => {
4444 return true ;
4545} ;
4646
47+ function getPlayerAttributes ( element ) {
48+ const player =
49+ element . closest ( 'pie-player' ) ||
50+ element . closest ( 'pie-item-player' ) ;
51+
52+ if ( ! player ) {
53+ return { baseHeadingLevel : undefined , includeSrHeading : true } ;
54+ }
55+
56+ const getRaw = ( camelCaseName , hyphenatedName , allLowerName ) => {
57+ let raw = player [ camelCaseName ] ;
58+
59+ // fallback in case someone sets via HTML attribute manually
60+ if ( raw == null ) {
61+ raw =
62+ player . getAttribute ( hyphenatedName ) ??
63+ player . getAttribute ( allLowerName ) ;
64+ }
65+
66+ return raw ;
67+ } ;
68+
69+ const levelRaw = getRaw ( 'baseHeadingLevel' , 'base-heading-level' , 'baseheadinglevel' ) ;
70+ const level = parseInt ( levelRaw , 10 ) ;
71+ const baseHeadingLevel = Number . isFinite ( level ) && level >= 1 && level <= 6 ? level : undefined ;
72+
73+ const srRaw = getRaw ( 'includeSrHeading' , 'include-sr-heading' , 'includesrheading' ) ;
74+ const includeSrHeading = srRaw == null ? true : srRaw !== false && srRaw !== 'false' ;
75+
76+ console . log ( 'getPlayerAttributes' , { baseHeadingLevel, includeSrHeading } ) ;
77+ return { baseHeadingLevel, includeSrHeading } ;
78+ }
79+
80+ // Resolves heading attributes for a custom element, preferring explicit instance
81+ // properties (set by a parent element such as EBSR) over player-level attributes.
82+ function resolveHeadingProps ( element ) {
83+ const fromPlayer = getPlayerAttributes ( element ) ;
84+
85+ console . log ( 'element._baseHeadingLevel' , element . _baseHeadingLevel , 'element._includeSrHeading' , element . _includeSrHeading ) ;
86+ return {
87+ baseHeadingLevel : element . _baseHeadingLevel !== undefined ? element . _baseHeadingLevel : fromPlayer . baseHeadingLevel ,
88+ includeSrHeading : element . _includeSrHeading !== undefined ? element . _includeSrHeading : fromPlayer . includeSrHeading ,
89+ } ;
90+ }
91+
4792export default class MultipleChoice extends HTMLElement {
4893 constructor ( ) {
4994 super ( ) ;
@@ -67,6 +112,7 @@ export default class MultipleChoice extends HTMLElement {
67112 options : this . _options ,
68113 onChoiceChanged : this . _onChange . bind ( this ) ,
69114 onShowCorrectToggle : this . onShowCorrectToggle . bind ( this ) ,
115+ ...resolveHeadingProps ( this ) ,
70116 } ) ;
71117
72118 //TODO: aria-label is set in the _rerender because we need to change it when the model.choiceMode is updated. Consider revisiting the placement of the aria-label setting in the _rerender
@@ -182,6 +228,16 @@ export default class MultipleChoice extends HTMLElement {
182228 this . _rerender ( ) ;
183229 }
184230
231+ set baseHeadingLevel ( level ) {
232+ this . _baseHeadingLevel = level ;
233+ this . _rerender ( ) ;
234+ }
235+
236+ set includeSrHeading ( value ) {
237+ this . _includeSrHeading = value ;
238+ this . _rerender ( ) ;
239+ }
240+
185241 set session ( s ) {
186242 this . _session = s ;
187243 this . _rerender ( ) ;
@@ -224,6 +280,7 @@ export default class MultipleChoice extends HTMLElement {
224280
225281 connectedCallback ( ) {
226282 this . _initMathObserver ( ) ;
283+ this . _initPlayerObserver ( ) ;
227284 this . _rerender ( ) ;
228285
229286 // Observation: audio in Chrome will have the autoplay attribute,
@@ -312,8 +369,29 @@ export default class MultipleChoice extends HTMLElement {
312369 }
313370 }
314371
372+ _initPlayerObserver ( ) {
373+ const player = this . closest ( 'pie-player' ) || this . closest ( 'pie-item-player' ) ;
374+ if ( ! player ) return ;
375+
376+ this . _playerObserver = new MutationObserver ( ( ) => {
377+ this . _rerender ( ) ;
378+ } ) ;
379+ this . _playerObserver . observe ( player , {
380+ attributes : true ,
381+ attributeFilter : [ 'base-heading-level' , 'baseheadinglevel' , 'include-sr-heading' , 'includesrheading' ] ,
382+ } ) ;
383+ }
384+
385+ _disconnectPlayerObserver ( ) {
386+ if ( this . _playerObserver ) {
387+ this . _playerObserver . disconnect ( ) ;
388+ this . _playerObserver = null ;
389+ }
390+ }
391+
315392 disconnectedCallback ( ) {
316393 this . _disconnectMathObserver ( ) ;
394+ this . _disconnectPlayerObserver ( ) ;
317395 if ( this . _keyboardEventsEnabled ) {
318396 window . removeEventListener ( 'keydown' , this . _boundHandleKeyDown ) ;
319397 this . _keyboardEventsEnabled = false ;
0 commit comments