1 | import mediumZoom from 'medium-zoom'
|
2 |
|
3 | const camelCased = string =>
|
4 | string.replace(/-([a-z])/g, g => g[1].toUpperCase())
|
5 |
|
6 | const template = document.createElement('template')
|
7 | template.innerHTML = `
|
8 | <style>
|
9 | :host {
|
10 | display: block;
|
11 | }
|
12 | img {
|
13 | max-width: 100%;
|
14 | }
|
15 | .medium-zoom-image {
|
16 | cursor: zoom-in;
|
17 | }
|
18 | </style>
|
19 | <img />
|
20 | `
|
21 |
|
22 | export default class MediumZoom extends HTMLElement {
|
23 | static get observedOptions() {
|
24 | return [
|
25 | 'margin',
|
26 | 'background',
|
27 | 'scroll-offset',
|
28 | 'disable-metaclick',
|
29 | 'zoom-target'
|
30 | ]
|
31 | }
|
32 |
|
33 | static get observedAttributes() {
|
34 | return [
|
35 | ...MediumZoom.observedOptions,
|
36 | 'src',
|
37 | 'alt',
|
38 | 'width',
|
39 | 'height',
|
40 | 'style'
|
41 | ]
|
42 | }
|
43 |
|
44 | static getOptionName(value) {
|
45 | return value === 'disable-metaclick' ? 'metaClick' : camelCased(value)
|
46 | }
|
47 |
|
48 | constructor() {
|
49 | super()
|
50 |
|
51 | this.attachShadow({ mode: 'open' })
|
52 | this.shadowRoot.appendChild(template.content.cloneNode(true))
|
53 | this.image = this.shadowRoot.querySelector('img')
|
54 | this.zoom = mediumZoom(this.image)
|
55 |
|
56 |
|
57 | Object.keys(this.zoom).forEach(method => (this[method] = this.zoom[method]))
|
58 |
|
59 |
|
60 | this.setAttribute('role', 'img')
|
61 | this.setAttribute('aria-label', this.alt)
|
62 | }
|
63 |
|
64 | disconnectedCallback() {
|
65 | this.zoom.detach()
|
66 | }
|
67 |
|
68 | adoptedCallback() {
|
69 | this.zoom.hide()
|
70 | }
|
71 |
|
72 | attributeChangedCallback(name, oldValue, newValue) {
|
73 | if (MediumZoom.observedOptions.includes(name)) {
|
74 | if (name === 'zoom-target') {
|
75 | this.image.setAttribute('data-zoom-target', newValue)
|
76 | return
|
77 | }
|
78 |
|
79 | this.zoom.update({
|
80 | [MediumZoom.getOptionName(name)]: this[MediumZoom.getOptionName(name)]
|
81 | })
|
82 | } else {
|
83 |
|
84 | this.image.setAttribute(name, newValue)
|
85 | }
|
86 | }
|
87 |
|
88 | get src() {
|
89 | return this.getAttribute('src') || ''
|
90 | }
|
91 |
|
92 | set src(value) {
|
93 | this.setAttribute('src', value)
|
94 | }
|
95 |
|
96 | get alt() {
|
97 | return this.getAttribute('alt') || ''
|
98 | }
|
99 |
|
100 | set alt(value) {
|
101 | this.setAttribute('alt', value)
|
102 | }
|
103 |
|
104 | get zoomTarget() {
|
105 | return this.getAttribute('zoom-target') || ''
|
106 | }
|
107 |
|
108 | set zoomTarget(value) {
|
109 | value
|
110 | ? this.setAttribute('zoom-target', value)
|
111 | : this.removeAttribute('zoom-target')
|
112 | }
|
113 |
|
114 | get width() {
|
115 | return this.getAttribute('width') || ''
|
116 | }
|
117 |
|
118 | set width(value) {
|
119 | value ? this.setAttribute('width', value) : this.removeAttribute('width')
|
120 | }
|
121 |
|
122 | get height() {
|
123 | return this.getAttribute('height') || ''
|
124 | }
|
125 |
|
126 | set height(value) {
|
127 | value ? this.setAttribute('height', value) : this.removeAttribute('height')
|
128 | }
|
129 |
|
130 | get margin() {
|
131 | return Number(this.getAttribute('margin')) || ''
|
132 | }
|
133 |
|
134 | set margin(value) {
|
135 | value ? this.setAttribute('margin', value) : this.removeAttribute('margin')
|
136 | }
|
137 |
|
138 | get background() {
|
139 | return this.getAttribute('background') || ''
|
140 | }
|
141 |
|
142 | set background(value) {
|
143 | value
|
144 | ? this.setAttribute('background', value)
|
145 | : this.removeAttribute('background')
|
146 | }
|
147 |
|
148 | get scrollOffset() {
|
149 | return this.hasAttribute('scroll-offset')
|
150 | ? Number(this.getAttribute('scroll-offset'))
|
151 | : ''
|
152 | }
|
153 |
|
154 | set scrollOffset(value) {
|
155 | value !== null
|
156 | ? this.setAttribute('scroll-offset', Number(value))
|
157 | : this.removeAttribute('scroll-offset')
|
158 | }
|
159 |
|
160 | get metaClick() {
|
161 | return !this.hasAttribute('disable-metaclick')
|
162 | }
|
163 |
|
164 | set metaClick(value) {
|
165 | value
|
166 | ? this.setAttribute('disable-metaclick', value)
|
167 | : this.removeAttribute('disable-metaclick')
|
168 | }
|
169 | }
|
170 |
|
171 | window.customElements.define('medium-zoom', MediumZoom)
|