Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/key-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export const ARROW_RIGHT = 39;
export const ARROW_LEFT = 37;
export const SPACE = 32;
export const NUMBER_ONE = 49;
export const ENTER = 'Enter';
8 changes: 7 additions & 1 deletion lib/kits/core-ui/components/common/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,15 @@ const Header = ({
template,
shoppingListCounterTemplate,
el,
scriptEls
scriptEls,
destroy
}: {
publicationType?: 'incito' | 'paged';
template?: Element | null;
shoppingListCounterTemplate?: Element | null;
el: Element | null;
scriptEls: ReturnType<typeof transformScriptData>;
destroy?: () => void;
}) => {
let container: HTMLDivElement | null = null;
publicationType = publicationType || 'paged';
Expand Down Expand Up @@ -366,6 +368,10 @@ const Header = ({
[scriptEls.sectionIdParam]: null
});
location.hash = '';

if (destroy) {
destroy();
}
};

const removeHtmlClass = () => {
Expand Down
22 changes: 15 additions & 7 deletions lib/kits/core-ui/components/common/offer-overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ const defaultTemplate = `\
<img src="{{images.zoom}}" alt="{{heading}}">
</div>
<div class="sgn-offer-details-container">
<button class="sgn-modal-close">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/></svg>
</button>

{{#label}}
<div class="sgn-popup-header">
<div class="sgn-menu-popup-labels">
Expand All @@ -58,7 +56,7 @@ const defaultTemplate = `\
<div class="sgn-products-container">
<div class="sgn-products-texts-container">
{{#products}}
<div id="sgn-offer-product-{{id}}" data-offer-product-id="{{id}}" data-offer-product-quantity="{{quantity}}" class="sgn-product-details">
<div id="sgn-offer-product-{{id}}" data-offer-product-id="{{id}}" data-offer-product-quantity="{{quantity}}" class="sgn-product-details" aria-label="{{title}}">
<div class="sgn-product-image">
{{#image}}
<img src="{{#image}}{{image}}{{/image}}{{^image}}{{images.zoom}}{{/image}}" alt="{{heading}}" onError="this.onerror=null;this.replaceWith(document.createRange().createContextualFragment('<svg xmlns=&quot;http://www.w3.org/2000/svg&quot; class=&quot;no-product-image-icon&quot; viewBox=&quot;0 0 640 512&quot;><path fill=&quot;currentColor&quot; d=&quot;M13 1.7C9.5-1 4.5-.4 1.7 3S-.4 11.5 3 14.3l624 496c3.5 2.7 8.5 2.2 11.2-1.3s2.2-8.5-1.3-11.2L13 1.7zM467.3 464h-280L310.8 340.5l-12.6-10L288 340.7l-73.4-73.4c-12.5-12.5-32.8-12.5-45.3 0L80 356.7V158.3L64 145.6V416c0 35.3 28.7 64 64 64H487.5l-20.3-16zM512 32H152.5l20.3 16H512c26.5 0 48 21.5 48 48V292.7l-89.4-89.4c-12.5-12.5-32.8-12.5-45.3 0L400.7 228l12.6 10 23.3-23.3c6.2-6.2 16.4-6.2 22.6 0L560 315.3v38.4l16 12.6V96c0-35.3-28.7-64-64-64zM80 379.3L180.7 278.6c6.2-6.2 16.4-6.2 22.6 0L276.7 352l-112 112H128c-26.5 0-48-21.5-48-48V379.3z&quot;/></svg>'));">
Expand All @@ -84,11 +82,11 @@ const defaultTemplate = `\
{{#showQuantityButtons}}
<div id="sgn-offer-product-quantity-{{id}}" class="sgn-offer-product-quantity">
<div class="sgn-offer-product-quantity-content">
<button id="sgn-offer-product-quantity-minus-{{id}}" class="sgn-offer-product-quantity-minus">
<button id="sgn-offer-product-quantity-minus-{{id}}" class="sgn-offer-product-quantity-minus" aria-label="{{translations.decreaseQuantity}}">
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-minus-circle-fill" viewBox="0 0 448 512"><path d="M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"/></svg>
</button>
<input type="text" id="sgn-offer-product-quantity-text-{{id}}" class="sgn-offer-product-quantity-text" value="{{quantity}}" disabled/>
<button id="sgn-offer-product-quantity-plus-{{id}}" class="sgn-offer-product-quantity-plus">
<button id="sgn-offer-product-quantity-plus-{{id}}" class="sgn-offer-product-quantity-plus" aria-label="{{translations.increaseQuantity}}">
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-plus-circle-fill" viewBox="0 0 448 512"><path d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H48c-17.7 0-32 14.3-32 32s14.3 32 32 32H192V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H400c17.7 0 32-14.3 32-32s-14.3-32-32-32H256V80z"/></svg>
</button>
</div>
Expand All @@ -104,6 +102,9 @@ const defaultTemplate = `\
<span>{{translations.validFrom}}</span>
<span data-validity-state="{{status}}">{{dateRange}}</span>
</div>
<button class="sgn-modal-close" aria-label="{{translations.close}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/></svg>
</button>
</div>
{{/loader}}
</div>
Expand Down Expand Up @@ -133,7 +134,14 @@ const OfferOverview = ({
addToShoppingList: translate('publication_viewer_add_to_shopping_list'),
visitWebshopLink: translate('publication_viewer_visit_webshop_link'),
priceFrom: translate('publication_viewer_offer_price_from'),
validFrom: translate('publication_viewer_offer_valid_from')
validFrom: translate('publication_viewer_offer_valid_from'),
close: translate('publication_viewer_close_label'),
increaseQuantity: translate(
'publication_viewer_offer_increase_quantity'
),
decreaseQuantity: translate(
'publication_viewer_offer_decrease_quantity'
)
};

const render = async () => {
Expand Down
59 changes: 44 additions & 15 deletions lib/kits/core-ui/paged-publication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const PagedPublication = (
| Record<string, never> = {};
let sgnViewer: Viewer;
let sgnPageDecorations: V2PageDecoration[];
let controlDirectionObserver: MutationObserver | null = null;
let urlParamObserver: MutationObserver | null = null;

const scriptEls = transformScriptData(scriptEl, mainContainer);

const customTemplates = {
Expand Down Expand Up @@ -83,14 +86,22 @@ const PagedPublication = (
scriptEls
}).render();

const destroy = () => {
controlDirectionObserver?.disconnect();
urlParamObserver?.disconnect();
controlDirectionObserver = null;
urlParamObserver = null;
};

const header = Header({
publicationType: 'paged',
template: scriptEls.enableSidebar
? customTemplates.sidebarContainer
: customTemplates.headerContainer,
shoppingListCounterTemplate: customTemplates.shoppingListCounter,
el: document.querySelector(scriptEls.mainContainer),
scriptEls
scriptEls,
destroy: destroy
});
document
.querySelector('.sgn__header-container')
Expand Down Expand Up @@ -257,7 +268,7 @@ const PagedPublication = (
'.sgn-pp__control[data-direction=next]'
);

const controlDirectionObserver = new MutationObserver((mutations) => {
controlDirectionObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
const element = mutation.target as HTMLButtonElement;
Expand Down Expand Up @@ -311,20 +322,38 @@ const PagedPublication = (
'.sgn-pp__progress-label'
);

progressLabel?.addEventListener('DOMSubtreeModified', (e) => {
const pageNum = e.target.innerHTML
?.split(' ')?.[0]
?.split('-')?.[0];

if (scriptEls.displayUrlParams?.toLowerCase() === 'query') {
pushQueryParam({
[scriptEls.publicationIdParam]: options.id,
[scriptEls.pageIdParam]: pageNum
if (progressLabel) {
urlParamObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (
mutation.type === 'childList' ||
mutation.type === 'characterData'
) {
const pageNum = mutation.target.textContent
?.split(' ')?.[0]
?.split('-')?.[0];

if (
scriptEls.displayUrlParams?.toLowerCase() ===
'query'
) {
pushQueryParam({
[scriptEls.publicationIdParam]: options.id,
[scriptEls.pageIdParam]: pageNum
});
} else {
location.hash = `${scriptEls.publicationHash}/${options.id}/${pageNum}`;
}
}
});
} else {
location.hash = `${scriptEls.publicationHash}/${options.id}/${pageNum}`;
}
});
});

urlParamObserver.observe(progressLabel, {
childList: true,
characterData: true,
subtree: true
});
}
}
};

Expand Down
18 changes: 18 additions & 0 deletions lib/kits/paged-publication/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class PagedPublicationControls extends MicroEvent {
this.close = el.querySelector('.sgn-pp--close');

this.keyDownHandler = throttle(this.keyDown, 150, this);

if (this.options.keyboard === 'enabled') {
this.root.addEventListener('keydown', this.keyDownHandler, false);
} else if (this.options.keyboard === 'global') {
Expand Down Expand Up @@ -149,6 +150,23 @@ class PagedPublicationControls extends MicroEvent {
this.trigger('next', {duration: 0});
} else if (keyCodes.NUMBER_ONE === keyCode) {
this.trigger('first', {duration: 0});
} else if (keyCodes.ENTER === e.key) {
const focusedElement = document.activeElement as HTMLElement;
if (
focusedElement &&
focusedElement.classList.contains('sgn-pp__control') &&
focusedElement.getAttribute('data-direction') === 'next'
) {
this.trigger('next', {duration: 0});
} else if (
focusedElement &&
focusedElement.classList.contains('sgn-pp__control') &&
focusedElement.getAttribute('data-direction') === 'prev'
) {
this.trigger('prev', {duration: 0});
} else {
this.trigger('enterKeyPressed', focusedElement);
}
}
};
}
Expand Down
14 changes: 11 additions & 3 deletions lib/kits/paged-publication/hotspots.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import MicroEvent from '../../../vendor/microevent';
import PageSpread from '../../verso-browser/page_spread';
import * as translations from '../../translations';
import {V2Hotspot} from '../core';
import PagedPublicationPageSpread from './page-spread';
import {Page} from './page-spreads';
import {translate} from '../core-ui/components/helpers/component';

function getPosition(pages: Page[], ratio: number, hotspot: V2Hotspot) {
let minX: number | null = null;
Expand Down Expand Up @@ -49,7 +49,7 @@ function getPosition(pages: Page[], ratio: number, hotspot: V2Hotspot) {
}

function renderHotspot(hotspot, position, contentRect, boundingRect) {
const el = document.createElement('div');
const el = document.createElement('button');
let top = Math.round((contentRect.height / 100) * position.top);
let left = Math.round((contentRect.width / 100) * position.left);
const width = Math.round((contentRect.width / 100) * position.width);
Expand Down Expand Up @@ -98,10 +98,18 @@ function renderHotspot(hotspot, position, contentRect, boundingRect) {
el.style.height = `${height}px`;

if (hotspot.type === 'offer') {
const translations = {
for: translate('publication_viewer_offer_price_for')
};
const pieceCountFor =
hotspot.offer.quantity.pieces.from > 1
? `${hotspot.offer.quantity.pieces.from} ${translations.for} `
: '';

el.setAttribute('tabindex', '-1');
el.setAttribute(
'aria-label',
`${hotspot.offer.heading}; ${hotspot.offer.pricing.price} ${hotspot.offer.pricing.currency};`
`${hotspot.offer.heading}; ${pieceCountFor}${hotspot.offer.pricing.price} ${hotspot.offer.pricing.currency};`
);

const observer = new IntersectionObserver((entries) => {
Expand Down
14 changes: 14 additions & 0 deletions lib/kits/paged-publication/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class Viewer extends MicroEvent {
this._controls.bind('first', this.first);
this._controls.bind('last', this.last);
this._controls.bind('close', this.destroy);
this._controls.bind('enterKeyPressed', this.enterKeyPressed);
this._hotspots.bind('hotspotsRequested', (e) => {
this.trigger('hotspotsRequested', e);
});
Expand Down Expand Up @@ -443,6 +444,19 @@ class Viewer extends MicroEvent {
this.trigger('hotspotPressed', hotspot);
});
};

enterKeyPressed = (el) => {
const hotspots = this.hotspots;
if (!hotspots) {
return;
}

const hotspot = hotspots[el?.dataset?.id];

if (hotspot) {
this.trigger('hotspotClicked', hotspot);
}
};
}

export default Viewer;
5 changes: 4 additions & 1 deletion locales/da_DK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export default {
publication_viewer_visit_webshop_link: 'Besøg webshoplink',
publication_viewer_upcoming: 'Kommende',
publication_viewer_offer_price_from: 'Fra',
publication_viewer_offer_price_for: 'for',
publication_viewer_offer_valid_from: 'Gælder kun fra d. ',
publication_viewer_no_product_message: 'Ingen produkt detaljer'
publication_viewer_no_product_message: 'Ingen produkt detaljer',
publication_viewer_offer_increase_quantity: 'Øg antal',
publication_viewer_offer_decrease_quantity: 'Mindsk antal'
};
5 changes: 4 additions & 1 deletion locales/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export default {
publication_viewer_visit_webshop_link: 'Visit Webshop Link',
publication_viewer_upcoming: 'Upcoming',
publication_viewer_offer_price_from: 'From',
publication_viewer_offer_price_for: 'for',
publication_viewer_offer_valid_from: 'Valid from ',
publication_viewer_no_product_message: 'No product details'
publication_viewer_no_product_message: 'No product details',
publication_viewer_offer_increase_quantity: 'Increase quantity',
publication_viewer_offer_decrease_quantity: 'Decrease quantity'
};
5 changes: 4 additions & 1 deletion locales/nb_NO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export default {
publication_viewer_visit_webshop_link: 'Besøk nettbutikklink',
publication_viewer_upcoming: 'Påkommende',
publication_viewer_offer_price_from: 'Fra',
publication_viewer_offer_price_for: 'for',
publication_viewer_offer_valid_from: 'Gjelder kun fra ',
publication_viewer_no_product_message: 'Ingen produktdetalje'
publication_viewer_no_product_message: 'Ingen produktdetalje',
publication_viewer_offer_increase_quantity: 'Øk antall',
publication_viewer_offer_decrease_quantity: 'Minsk antall'
};
5 changes: 4 additions & 1 deletion locales/sv_SE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export default {
publication_viewer_visit_webshop_link: 'Besök webbshoplänk',
publication_viewer_upcoming: 'Kommende',
publication_viewer_offer_price_from: 'Från',
publication_viewer_offer_price_for: 'för',
publication_viewer_offer_valid_from: 'Gäller endast fr.o.m ',
publication_viewer_no_product_message: 'Inga produktdetaljer'
publication_viewer_no_product_message: 'Inga produktdetaljer',
publication_viewer_offer_increase_quantity: 'Öka antal',
publication_viewer_offer_decrease_quantity: 'Minska antal'
};