diff --git a/js/hotgraphicPopupView.js b/js/hotgraphicPopupView.js index 6bc90465..2eedc641 100644 --- a/js/hotgraphicPopupView.js +++ b/js/hotgraphicPopupView.js @@ -63,41 +63,37 @@ class HotgraphicPopupView extends Backbone.View { const totalItems = this.model.getChildren().length; const canCycleThroughPagination = this.model.get('_canCycleThroughPagination'); - const isAtStart = index === 0; - const isAtEnd = index === totalItems - 1; + // When looping is enabled the buttons never disable and always wrap, + // so the active item is never treated as the start or end. + const isAtStart = !canCycleThroughPagination && index === 0; + const isAtEnd = !canCycleThroughPagination && index === totalItems - 1; const globals = Adapt.course.get('_globals'); const hotgraphicGlobals = globals._components._hotgraphic; - let prevTitle = isAtStart ? '' : this.model.getItem(index - 1).get('title'); - let nextTitle = isAtEnd ? '' : this.model.getItem(index + 1).get('title'); - - let backItem = isAtStart ? null : index; - let nextItem = isAtEnd ? null : index + 2; - - if (canCycleThroughPagination) { - if (isAtStart) { - prevTitle = this.model.getItem(totalItems - 1).get('title'); - backItem = totalItems; - } - if (isAtEnd) { - nextTitle = this.model.getItem(0).get('title'); - nextItem = 1; - } - } + const prevIndex = (index - 1 + totalItems) % totalItems; + const nextIndex = (index + 1) % totalItems; + + const prevTitle = isAtStart ? '' : this.model.getItem(prevIndex).get('title'); + const nextTitle = isAtEnd ? '' : this.model.getItem(nextIndex).get('title'); + + const backItem = isAtStart ? null : prevIndex + 1; + const nextItem = isAtEnd ? null : nextIndex + 1; const backLabel = compile(hotgraphicGlobals.previous, { _globals: globals, title: prevTitle, itemNumber: backItem, - totalItems + totalItems, + isAtStart }); const nextLabel = compile(hotgraphicGlobals.next, { _globals: globals, title: nextTitle, itemNumber: nextItem, - totalItems + totalItems, + isAtEnd }); this.model.set('backLabel', backLabel); diff --git a/migrations/v6.js b/migrations/v6.js index cf0e3446..e33f9d68 100644 --- a/migrations/v6.js +++ b/migrations/v6.js @@ -585,3 +585,70 @@ describe('Hot Graphic - v6.14.2 to v6.15.0', async () => { fromPlugins: [{ name: 'adapt-contrib-hotgraphic', version: '6.15.0' }] }); }); + +describe('Hot Graphic - @@CURRENT_VERSION to @@RELEASE_VERSION', async () => { + let hotgraphics, course, courseHotgraphicGlobals; + const originalPrevious = '{{#if title}}Back to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}}'; + const updatedPrevious = '{{#if isAtStart}}{{_globals._accessibility._ariaLabels.previous}}{{else}}{{#if title}}Back to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}'; + const originalNext = '{{#if title}}Forward to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}}'; + const updatedNext = '{{#if isAtEnd}}{{_globals._accessibility._ariaLabels.next}}{{else}}{{#if title}}Forward to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}'; + + whereFromPlugin('Hot Graphic - from @@CURRENT_VERSION', { name: 'adapt-contrib-hotgraphic', version: '<@@RELEASE_VERSION' }); + + whereContent('Hot Graphic - where hotgraphic', async content => { + hotgraphics = getComponents('hotgraphic'); + return hotgraphics.length; + }); + + mutateContent('Hot Graphic - update globals previous attribute', async content => { + course = getCourse(); + courseHotgraphicGlobals = course._globals?._components?._hotgraphic; + if (courseHotgraphicGlobals?.previous === originalPrevious) courseHotgraphicGlobals.previous = updatedPrevious; + return true; + }); + + mutateContent('Hot Graphic - update globals next attribute', async content => { + if (courseHotgraphicGlobals?.next === originalNext) courseHotgraphicGlobals.next = updatedNext; + return true; + }); + + checkContent('Hot Graphic - check globals previous attribute', async content => { + if (courseHotgraphicGlobals?.previous === originalPrevious) throw new Error('Hot Graphic - globals previous not updated'); + return true; + }); + + checkContent('Hot Graphic - check globals next attribute', async content => { + if (courseHotgraphicGlobals?.next === originalNext) throw new Error('Hot Graphic - globals next not updated'); + return true; + }); + + updatePlugin('Hot Graphic - update to @@RELEASE_VERSION', { name: 'adapt-contrib-hotgraphic', version: '@@RELEASE_VERSION', framework: '>=5.39.12' }); + + testSuccessWhere('hotgraphic component with original globals', { + fromPlugins: [{ name: 'adapt-contrib-hotgraphic', version: '@@CURRENT_VERSION' }], + content: [ + { _id: 'c-100', _component: 'hotgraphic' }, + { _type: 'course', _globals: { _components: { _hotgraphic: { previous: originalPrevious, next: originalNext } } } } + ] + }); + + testSuccessWhere('hotgraphic component with empty course._globals', { + fromPlugins: [{ name: 'adapt-contrib-hotgraphic', version: '@@CURRENT_VERSION' }], + content: [ + { _id: 'c-100', _component: 'hotgraphic' }, + { _type: 'course', _globals: { _components: { _hotgraphic: {} } } } + ] + }); + + testStopWhere('no hotgraphic components', { + fromPlugins: [{ name: 'adapt-contrib-hotgraphic', version: '@@CURRENT_VERSION' }], + content: [ + { _component: 'other' }, + { _type: 'course' } + ] + }); + + testStopWhere('incorrect version', { + fromPlugins: [{ name: 'adapt-contrib-hotgraphic', version: '@@RELEASE_VERSION' }] + }); +}); diff --git a/properties.schema b/properties.schema index de5310d1..92780622 100644 --- a/properties.schema +++ b/properties.schema @@ -23,14 +23,14 @@ "previous": { "type": "string", "title": "Previous", - "default": "{{#if title}}Back to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}}", + "default": "{{#if isAtStart}}{{_globals._accessibility._ariaLabels.previous}}{{else}}{{#if title}}Back to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}", "inputType": "Text", "translatable": true }, "next": { "type": "string", "title": "Next", - "default": "{{#if title}}Forward to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}}", + "default": "{{#if isAtEnd}}{{_globals._accessibility._ariaLabels.next}}{{else}}{{#if title}}Forward to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}", "inputType": "Text", "translatable": true }, diff --git a/schema/course.schema.json b/schema/course.schema.json index 0089f73c..b110bfef 100644 --- a/schema/course.schema.json +++ b/schema/course.schema.json @@ -41,7 +41,7 @@ "previous": { "type": "string", "title": "Previous", - "default": "{{#if title}}Back to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}}", + "default": "{{#if isAtStart}}{{_globals._accessibility._ariaLabels.previous}}{{else}}{{#if title}}Back to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.previous}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}", "_adapt": { "translatable": true } @@ -49,7 +49,7 @@ "next": { "type": "string", "title": "Next", - "default": "{{#if title}}Forward to {{{title}}} (item {{itemNumber}} of {{totalItems}}){{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}}", + "default": "{{#if isAtEnd}}{{_globals._accessibility._ariaLabels.next}}{{else}}{{#if title}}Forward to {{{title}}}{{else}}{{_globals._accessibility._ariaLabels.next}}{{/if}} (item {{itemNumber}} of {{totalItems}}){{/if}}", "_adapt": { "translatable": true }