viewerjs 1.3.3 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -307,13 +307,18 @@ export default {
307
307
  || this.viewing
308
308
  || this.hiding
309
309
 
310
- // No primary button (Usually the left button)
311
- // Note that touch events have no `buttons` or `button` property
312
- || (isNumber(buttons) && buttons !== 1)
313
- || (isNumber(button) && button !== 0)
314
-
315
- // Open context menu
316
- || event.ctrlKey
310
+ // Handle mouse event and pointer event and ignore touch event
311
+ || ((
312
+ event.type === 'mousedown'
313
+ || (event.type === 'pointerdown' && event.pointerType === 'mouse')
314
+ ) && (
315
+ // No primary button (Usually the left button)
316
+ (isNumber(buttons) && buttons !== 1)
317
+ || (isNumber(button) && button !== 0)
318
+
319
+ // Open context menu
320
+ || event.ctrlKey
321
+ ))
317
322
  ) {
318
323
  return;
319
324
  }
package/src/js/methods.js CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  addListener,
26
26
  assign,
27
27
  dispatchEvent,
28
+ escapeHTMLEntities,
28
29
  forEach,
29
30
  getData,
30
31
  getOffset,
@@ -148,10 +149,13 @@ export default {
148
149
  if (options.transition && !immediate) {
149
150
  const hidden = this.hidden.bind(this);
150
151
  const hide = () => {
151
- addListener(viewer, EVENT_TRANSITION_END, hidden, {
152
- once: true,
153
- });
154
- removeClass(viewer, CLASS_IN);
152
+ // XXX: It seems the `event.stopPropagation()` method does not work here
153
+ setTimeout(() => {
154
+ addListener(viewer, EVENT_TRANSITION_END, hidden, {
155
+ once: true,
156
+ });
157
+ removeClass(viewer, CLASS_IN);
158
+ }, 0);
155
159
  };
156
160
 
157
161
  this.transitioning = {
@@ -189,16 +193,16 @@ export default {
189
193
  view(index = this.options.initialViewIndex) {
190
194
  index = Number(index) || 0;
191
195
 
192
- if (!this.isShown) {
193
- this.index = index;
194
- return this.show();
195
- }
196
-
197
196
  if (this.hiding || this.played || index < 0 || index >= this.length
198
197
  || (this.viewed && index === this.index)) {
199
198
  return this;
200
199
  }
201
200
 
201
+ if (!this.isShown) {
202
+ this.index = index;
203
+ return this.show();
204
+ }
205
+
202
206
  if (this.viewing) {
203
207
  this.viewing.abort();
204
208
  }
@@ -258,9 +262,9 @@ export default {
258
262
  const { imageData } = this;
259
263
  const render = Array.isArray(options.title) ? options.title[1] : options.title;
260
264
 
261
- title.innerHTML = isFunction(render)
265
+ title.innerHTML = escapeHTMLEntities(isFunction(render)
262
266
  ? render.call(this, image, imageData)
263
- : `${alt} (${imageData.naturalWidth} × ${imageData.naturalHeight})`;
267
+ : `${alt} (${imageData.naturalWidth} × ${imageData.naturalHeight})`);
264
268
  };
265
269
  let onLoad;
266
270
 
package/src/js/render.js CHANGED
@@ -66,7 +66,10 @@ export default {
66
66
  const { element, options, list } = this;
67
67
  const items = [];
68
68
 
69
- forEach(this.images, (image, i) => {
69
+ // initList may be called in this.update, so should keep idempotent
70
+ list.innerHTML = '';
71
+
72
+ forEach(this.images, (image, index) => {
70
73
  const { src } = image;
71
74
  const alt = image.alt || getImageNameFromURL(src);
72
75
  let { url } = options;
@@ -78,22 +81,24 @@ export default {
78
81
  }
79
82
 
80
83
  if (src || url) {
81
- items.push('<li>'
82
- + '<img'
83
- + ` src="${src || url}"`
84
- + ' role="button"'
85
- + ' data-viewer-action="view"'
86
- + ` data-index="${i}"`
87
- + ` data-original-url="${url || src}"`
88
- + ` alt="${alt}"`
89
- + '>'
90
- + '</li>');
84
+ const item = document.createElement('li');
85
+ const img = document.createElement('img');
86
+
87
+ img.src = src || url;
88
+ img.alt = alt;
89
+ img.setAttribute('data-index', index);
90
+ img.setAttribute('data-original-url', url || src);
91
+ img.setAttribute('data-viewer-action', 'view');
92
+ img.setAttribute('role', 'button');
93
+ item.appendChild(img);
94
+ list.appendChild(item);
95
+ items.push(item);
91
96
  }
92
97
  });
93
98
 
94
- list.innerHTML = items.join('');
95
- this.items = list.getElementsByTagName('li');
96
- forEach(this.items, (item) => {
99
+ this.items = items;
100
+
101
+ forEach(items, (item) => {
97
102
  const image = item.firstElementChild;
98
103
 
99
104
  setData(image, 'filled', true);
@@ -145,6 +145,20 @@ export function setStyle(element, styles) {
145
145
  });
146
146
  }
147
147
 
148
+ /**
149
+ * Escape a string for using in HTML.
150
+ * @param {String} value - The string to escape.
151
+ * @returns {String} Returns the escaped string.
152
+ */
153
+ export function escapeHTMLEntities(value) {
154
+ return isString(value) ? value
155
+ .replace(/&(?!amp;|quot;|#39;|lt;|gt;)/g, '&amp;')
156
+ .replace(/"/g, '&quot;')
157
+ .replace(/'/g, '&#39;')
158
+ .replace(/</g, '&lt;')
159
+ .replace(/>/g, '&gt;') : value;
160
+ }
161
+
148
162
  /**
149
163
  * Check if the given element has a special class.
150
164
  * @param {Element} element - The element to check.
@@ -152,6 +166,10 @@ export function setStyle(element, styles) {
152
166
  * @returns {boolean} Returns `true` if the special class was found.
153
167
  */
154
168
  export function hasClass(element, value) {
169
+ if (!element || !value) {
170
+ return false;
171
+ }
172
+
155
173
  return element.classList
156
174
  ? element.classList.contains(value)
157
175
  : element.className.indexOf(value) > -1;
@@ -163,7 +181,7 @@ export function hasClass(element, value) {
163
181
  * @param {string} value - The classes to be added.
164
182
  */
165
183
  export function addClass(element, value) {
166
- if (!value) {
184
+ if (!element || !value) {
167
185
  return;
168
186
  }
169
187
 
@@ -194,7 +212,7 @@ export function addClass(element, value) {
194
212
  * @param {string} value - The classes to be removed.
195
213
  */
196
214
  export function removeClass(element, value) {
197
- if (!value) {
215
+ if (!element || !value) {
198
216
  return;
199
217
  }
200
218
 
@@ -499,7 +517,7 @@ export function getTransforms({
499
517
  * @returns {string} A string contains the image name.
500
518
  */
501
519
  export function getImageNameFromURL(url) {
502
- return isString(url) ? url.replace(/^.*\//, '').replace(/[?&#].*$/, '') : '';
520
+ return isString(url) ? decodeURIComponent(url.replace(/^.*\//, '').replace(/[?&#].*$/, '')) : '';
503
521
  }
504
522
 
505
523
  const IS_SAFARI = WINDOW.navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(WINDOW.navigator.userAgent);
@@ -578,7 +596,7 @@ export function getResponsiveClass(type) {
578
596
  * @returns {number} The result ratio.
579
597
  */
580
598
  export function getMaxZoomRatio(pointers) {
581
- const pointers2 = assign({}, pointers);
599
+ const pointers2 = { ...pointers };
582
600
  const ratios = [];
583
601
 
584
602
  forEach(pointers, (pointer, pointerId) => {
@@ -614,11 +632,12 @@ export function getPointer({ pageX, pageY }, endOnly) {
614
632
  endY: pageY,
615
633
  };
616
634
 
617
- return endOnly ? end : assign({
635
+ return endOnly ? end : ({
618
636
  timeStamp: Date.now(),
619
637
  startX: pageX,
620
638
  startY: pageY,
621
- }, end);
639
+ ...end,
640
+ });
622
641
  }
623
642
 
624
643
  /**