diff --git a/__tests__/fixtures/version-2/001.json b/__tests__/fixtures/version-2/001.json index 8301ee2656b2e5e0f2d8fec981a509ebc6dbad1b..8f8f3211a2db1237ffcc5f6cda18f14046dbf592 100644 --- a/__tests__/fixtures/version-2/001.json +++ b/__tests__/fixtures/version-2/001.json @@ -125,6 +125,7 @@ } }, "viewingHint": "individuals", + "viewingDirection": "left-to-right", "sequences": [ { "@id": "https://iiif.bodleian.ox.ac.uk/iiif/sequence/9cca8fdd-4a61-4429-8ac1-f648764b4d6d_default.json", diff --git a/__tests__/fixtures/version-2/015.json b/__tests__/fixtures/version-2/015.json index 1f8992139d733ef0fd0920c58defe3dd089c1f15..6e56f724b1d815346f49708e288c7d822d60f61f 100644 --- a/__tests__/fixtures/version-2/015.json +++ b/__tests__/fixtures/version-2/015.json @@ -5,11 +5,13 @@ "label": "Test 15 Manifest: ViewingHint: paged (Modified to be on sequence also)", "within": "http://iiif.io/api/presentation/2.0/example/fixtures/collection.json", "viewingHint": "individuals", + "viewingDirection": "right-to-left", "sequences": [ { "@type": "sc:Sequence", "label": "Test 15 Sequence 1", "viewingHint": "paged", + "viewingDirection": "left-to-right", "canvases": [ { "@id": "http://iiif.io/api/presentation/2.0/example/fixtures/canvas/15/c1.json", diff --git a/__tests__/integration/mirador/rtl.html b/__tests__/integration/mirador/rtl.html index 5f8a13cb9b715bf7737690016c15d6b327fc51c8..f90fb2fe09299db41e07d3a2a6ed278e61ece172 100644 --- a/__tests__/integration/mirador/rtl.html +++ b/__tests__/integration/mirador/rtl.html @@ -21,6 +21,11 @@ height: 600px; position: relative; } + #instanceThree { + width: 100%; + height: 50%; + position: relative; + } </style> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500"> </head> @@ -29,6 +34,8 @@ <div id="instanceOne" dir="rtl"></div> <h1>This is the second instance dir="ltr", viewingDirection="rtl"</h1> <div id="instanceTwo" dir="ltr"></div> + <h1>This is the third instance dir="rtl"</h1> + <div id="instanceThree" dir="rtl"></div> <script>document.write("<script type='text/javascript' src='../../../dist/mirador.min.js?v=" + Date.now() + "'><\/script>");</script> <script type="text/javascript"> var miradorInstance = Mirador.viewer({ @@ -46,6 +53,12 @@ manifestId: 'https://candra.dhii.jp/iiif/blackjacky/b001/manifest.json', }] }); + var miradorInstance = Mirador.viewer({ + id: 'instanceThree', + windows: [{ + manifestId: 'https://iiif.harvardartmuseums.org/manifests/object/299843', + }] + }); </script> </body> </html> diff --git a/__tests__/src/components/ViewerNavigation.test.js b/__tests__/src/components/ViewerNavigation.test.js index 9ff9e3ca16fb6fb8ac95983ae03a1f1bdc7a1ce7..d35bc109e648d796f96d1f2f4dad2ce85891bebe 100644 --- a/__tests__/src/components/ViewerNavigation.test.js +++ b/__tests__/src/components/ViewerNavigation.test.js @@ -1,5 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; +import NavigationIcon from '@material-ui/icons/PlayCircleOutlineSharp'; +import MiradorMenuButton from '../../../src/containers/MiradorMenuButton'; import { ViewerNavigation } from '../../../src/components/ViewerNavigation'; /** create wrapper */ @@ -76,4 +78,26 @@ describe('ViewerNavigation', () => { expect(setPreviousCanvas).not.toHaveBeenCalled(); }); }); + describe('when viewingDirection is right-to-left', () => { + beforeEach(() => { + wrapper = createWrapper({ + hasNextCanvas: true, + hasPreviousCanvas: true, + setNextCanvas, + setPreviousCanvas, + viewingDirection: 'right-to-left', + }); + }); + + it('changes the arrow styles', () => { + const previous = wrapper.find(MiradorMenuButton).first().children('PlayCircleOutlineSharpIcon').props(); + const next = wrapper.find(MiradorMenuButton).last().children('PlayCircleOutlineSharpIcon').props(); + expect(previous.style).toEqual({}); + expect(next.style).toEqual({ transform: 'rotate(180deg)' }); + }); + + it('sets the dir="rtl"', () => { + expect(wrapper.find('div').props().dir).toBe('rtl'); + }); + }); }); diff --git a/__tests__/src/selectors/manifests.test.js b/__tests__/src/selectors/manifests.test.js index 3e4b4d9415d55f0466914a976b3f252bea722525..da4460884ca402fe9b128248b39f7aa32f4d2ab1 100644 --- a/__tests__/src/selectors/manifests.test.js +++ b/__tests__/src/selectors/manifests.test.js @@ -24,6 +24,7 @@ import { getManifestRelatedContent, getManifestRenderings, getManifestUrl, + getManifestViewingDirection, getManifestViewingHint, getMetadataLocales, getRequiredStatement, @@ -491,6 +492,23 @@ describe('getManifestViewingHint', () => { }); }); +describe('getManifestViewingDirection', () => { + it('gets from the manifest', () => { + const state = { manifests: { x: { json: manifestFixture001 } } }; + expect(getManifestViewingDirection(state, { manifestId: 'x' })).toEqual('left-to-right'); + }); + + it('gets from the sequence', () => { + const state = { manifests: { x: { json: manifestFixture015 } } }; + expect(getManifestViewingDirection(state, { manifestId: 'x' })).toEqual('left-to-right'); + }); + + it('is null if no viewingDirection is specified', () => { + const state = { manifests: { x: { json: manifestFixture019 } } }; + expect(getManifestViewingDirection(state, { manifestId: 'x' })).toBeNull(); + }); +}); + describe('getManifestSearchService', () => { it('gets from the manifest', () => { const state = { manifests: { x: { json: manifestFixtureFg165hz3589 } } }; diff --git a/src/components/ViewerNavigation.js b/src/components/ViewerNavigation.js index 749245c63069de55b1b661d24465f6b846b0daab..07b82fa542c682264e184277b8948dfded63444d 100644 --- a/src/components/ViewerNavigation.js +++ b/src/components/ViewerNavigation.js @@ -13,18 +13,31 @@ export class ViewerNavigation extends Component { */ render() { const { - hasNextCanvas, hasPreviousCanvas, setNextCanvas, setPreviousCanvas, t, classes, + hasNextCanvas, hasPreviousCanvas, setNextCanvas, setPreviousCanvas, t, + classes, viewingDirection, } = this.props; + let htmlDir = 'ltr'; + let nextIconStyle = { transform: 'rotate(180deg)' }; + let previousIconStyle = {}; + if (viewingDirection === 'right-to-left') { + htmlDir = 'rtl'; + nextIconStyle = {}; + previousIconStyle = { transform: 'rotate(180deg)' }; + } + return ( - <div className={classNames(ns('osd-navigation'), classes.osdNavigation)}> + <div + className={classNames(ns('osd-navigation'), classes.osdNavigation)} + dir={htmlDir} + > <MiradorMenuButton aria-label={t('previousCanvas')} className={ns('previous-canvas-button')} disabled={!hasPreviousCanvas} onClick={() => { hasPreviousCanvas && setPreviousCanvas(); }} > - <NavigationIcon style={{ transform: 'rotate(180deg)' }} /> + <NavigationIcon style={nextIconStyle} /> </MiradorMenuButton> <MiradorMenuButton aria-label={t('nextCanvas')} @@ -32,7 +45,7 @@ export class ViewerNavigation extends Component { disabled={!hasNextCanvas} onClick={() => { hasNextCanvas && setNextCanvas(); }} > - <NavigationIcon /> + <NavigationIcon style={previousIconStyle} /> </MiradorMenuButton> </div> ); @@ -46,6 +59,7 @@ ViewerNavigation.propTypes = { setNextCanvas: PropTypes.func, setPreviousCanvas: PropTypes.func, t: PropTypes.func.isRequired, + viewingDirection: PropTypes.string, }; ViewerNavigation.defaultProps = { @@ -53,4 +67,5 @@ ViewerNavigation.defaultProps = { hasPreviousCanvas: false, setNextCanvas: () => {}, setPreviousCanvas: () => {}, + viewingDirection: '', }; diff --git a/src/containers/ViewerNavigation.js b/src/containers/ViewerNavigation.js index 8c68ec4a13fda89121d0137772af167b3893bfbb..943878f2158ae062852e6fcda5e5e349fa0e0b9b 100644 --- a/src/containers/ViewerNavigation.js +++ b/src/containers/ViewerNavigation.js @@ -4,13 +4,18 @@ import { withTranslation } from 'react-i18next'; import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; -import { getNextCanvasGrouping, getPreviousCanvasGrouping } from '../state/selectors'; +import { + getManifestViewingDirection, + getNextCanvasGrouping, + getPreviousCanvasGrouping, +} from '../state/selectors'; import { ViewerNavigation } from '../components/ViewerNavigation'; /** */ const mapStateToProps = (state, { windowId }) => ({ hasNextCanvas: !!getNextCanvasGrouping(state, { windowId }), hasPreviousCanvas: !!getPreviousCanvasGrouping(state, { windowId }), + viewingDirection: getManifestViewingDirection(state, { windowId }), }); /** diff --git a/src/state/selectors/manifests.js b/src/state/selectors/manifests.js index e6fe70f08dd523d433db09a495d8c8b4de2f7a8e..1af414a3b5f7e87cdca9d72c6c277c2c8e042074 100644 --- a/src/state/selectors/manifests.js +++ b/src/state/selectors/manifests.js @@ -408,6 +408,17 @@ export const getManifestViewingHint = createSelector( }, ); +export const getManifestViewingDirection = createSelector( + [getManifestoInstance], + (manifest) => { + if (!manifest) return null; + const viewingDirection = manifest.getSequences()[0].getViewingDirection() + || manifest.getViewingDirection(); + if (viewingDirection) return viewingDirection.value; + return null; + }, +); + /** */ export const getManifestSearchService = createSelector( [getManifestoInstance],