浏览代码

Fix #1800: Styling enhancements for thumbnail content and rotatable images

Kartik Visweswaran 2 年之前
父节点
当前提交
48f71983ad
共有 8 个文件被更改,包括 110 次插入48 次删除
  1. 2 1
      CHANGE.md
  2. 6 2
      css/fileinput.css
  3. 0 0
      css/fileinput.min.css
  4. 37 24
      js/fileinput.js
  5. 0 0
      js/fileinput.min.js
  6. 57 17
      js/plugins/filetype.js
  7. 0 0
      js/plugins/filetype.min.js
  8. 8 4
      scss/fileinput.scss

+ 2 - 1
CHANGE.md

@@ -5,8 +5,9 @@ Change Log: `bootstrap-fileinput`
 
 **Major Release: BC Breaking**
 
-**Date**: 27-Jun-2022
+**Date**: 28-Jun-2022
 
+- (enh #1800): Styling enhancements for thumbnail content and rotatable images.
 - (enh #1799): Correct translations containing `{maxSize}, {minSize}, {size}`.
 - (enh #1796): Add two new Font Awesome 6.x themes.
   - `fa6`

+ 6 - 2
css/fileinput.css

@@ -657,7 +657,7 @@ input[type=file].file-loading {
     display: none;
 }
 
-.file-preview-other-frame, .file-preview-object, .kv-zoom-body {
+.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body {
     display: flex;
     align-items: center;
     justify-content: center;
@@ -676,9 +676,13 @@ input[type=file].file-loading {
 .rotatable .file-zoom-detail,
 .rotatable .kv-file-content,
 .rotatable .kv-file-content > :first-child {
-    transform-origin: top left;
+    transform-origin: center center;
 }
 
 .rotate-animate {
     transition: transform 0.3s ease;
 }
+
+.kv-overflow-hidden {
+    overflow: hidden;
+}

文件差异内容过多而无法显示
+ 0 - 0
css/fileinput.min.css


+ 37 - 24
js/fileinput.js

@@ -1112,8 +1112,7 @@
                     return out;
                 },
                 exists: function (id) {
-                    var list = self.fileManager.getIdList();
-                    return $.inArray(id, list) !== -1 && (!altId || $.inArray(altId, list) !== -1);
+                    return $.inArray(id, self.fileManager.getIdList()) !== -1;
                 },
                 count: function () {
                     return self.fileManager.getIdList().length;
@@ -2333,9 +2332,10 @@
         },
         _resetErrors: function (fade) {
             var self = this, $error = self.$errorContainer, history = self.resumableUploadOptions.retainErrorHistory;
-            if (self.isPersistentError || (self.enableResumableUpload && history)) {
+            if (self.isPersistentError || (self.enableResumableUpload && history && !self.clearInput)) {
                 return;
             }
+            self.clearInput = false;
             self.isError = false;
             self.$container.removeClass('has-error');
             self.$caption.removeClass('is-invalid is-valid file-processing');
@@ -2910,6 +2910,7 @@
                     self._raise('filezoom' + event, getParams(e));
                 }
                 if (event === 'shown') {
+                    self._handleRotation($modal, $modal.find('.file-zoom-detail'), $modal.data('angle'));
                     $btnBord.removeClass('active').attr('aria-pressed', 'false');
                     $btnFull.removeClass('active').attr('aria-pressed', 'false');
                     if ($modal.hasClass('file-zoom-fullscreen')) {
@@ -4070,17 +4071,21 @@
             }, self.processDelay);
         },
         _handleRotation: function ($el, $content, angle) {
-            var self = this, css, newCss, addCss = '', scale = 1, elContent = $content[0], quadrant, transform, h, w;
+            var self = this, css, newCss, addCss = '', scale = 1, elContent = $content[0], quadrant, transform, h, w,
+                wNew, $parent = $content.parent(), hParent, wParent, $body = $('body'), bodyExists = !!$body.length;
+            if (bodyExists) {
+                $body.addClass('kv-overflow-hidden');
+            }
             if (!$content.length || $el.hasClass('hide-rotate')) {
+                if (bodyExists) {
+                    $body.removeClass('kv-overflow-hidden');
+                }
                 return;
             }
             transform = $content.css('transform');
             if (transform) {
                 $content.css('transform', 'none');
             }
-            w = elContent.naturalWidth || $content.outerWidth() || 0;
-            h = elContent.naturalHeight || $content.outerHeight() || 0;
-            scale = w > h && w != 0 ? (h / w).toFixed(2) : 1;
             if (transform) {
                 $content.css('transform', transform);
             }
@@ -4088,21 +4093,29 @@
             quadrant = angle % 360;
             css = 'rotate(' + angle + 'deg)';
             newCss = 'rotate(' + quadrant + 'deg)';
-            switch (quadrant) {
-                case 90:
-                    addCss = ' translateY(-100%)' + (scale === 1 ? '' : ' scale(' + scale + ')');
-                    break;
-                case 180:
-                    addCss = ' translate(-100%,-100%)';
-                    break;
-                case 270:
-                    var x = scale * 100, y = 100 - x;
-                    addCss = scale === 1 ? ' translateX(-100%)' : ' translate(-' + x + '%, ' + y + '%) scale(' + scale + ')';
-                    break;
+            addCss = '';
+            if (quadrant === 90 || quadrant === 270) {
+                w = elContent.naturalWidth || $content.outerWidth() || 0;
+                h = elContent.naturalHeight || $content.outerHeight() || 0;
+                scale = w > h && w != 0 ? (h / w).toFixed(2) : 1;
+                if ($parent.length) {
+                    hParent = $parent.height();
+                    wParent = $parent.width();
+                    wNew = Math.min(w, wParent);
+                    if (hParent > scale * wNew) {
+                        scale = wNew > hParent && wNew != 0 ? (hParent / wNew).toFixed(2) : 1;
+                    }
+                }
+                if (scale !== 1) {
+                    addCss = ' scale(' + scale + ')';
+                }
             }
             $content.addClass('rotate-animate').css('transform', css + addCss);
             setTimeout(function () {
                 $content.removeClass('rotate-animate').css('transform', newCss + addCss);
+                if (bodyExists) {
+                    $body.removeClass('kv-overflow-hidden');
+                }
                 $el.data('angle', quadrant);
             }, self.fadeDelay);
         },
@@ -4120,12 +4133,13 @@
         _initRotateZoom: function ($frame, $content) {
             var self = this, $modal = self.$modal, $rotate = $modal.find('.btn-kv-rotate'),
                 angle = $frame.data('angle');
+            $modal.data('angle', angle);
             if ($rotate.length) {
                 $rotate.off('click');
                 if ($modal.hasClass('rotatable')) {
-                    self._handleRotation($modal, $modal.find('.file-zoom-detail'), angle);
                     $rotate.on('click', function () {
                         angle = ($modal.data('angle') || 0) + 90;
+                        $modal.data('angle', angle);
                         self._handleRotation($modal, $modal.find('.file-zoom-detail'), angle);
                         self._handleRotation($frame, $content, angle);
                         if ($frame.hasClass('hide-rotate')) {
@@ -4329,7 +4343,6 @@
                 if (newSize == sizeHuman) {
                     newSize = sizeHuman;
                 }
-                console.log('size ', size);
                 out = newSize + ' ' + sizeUnits[i];
             }
             return skipTemplate ? out : self._getLayoutTemplate('size').replace('{sizeText}', out);
@@ -4361,7 +4374,7 @@
                 config, title = caption, alt = caption, typeCss = 'type-default', getContent, addFrameCss,
                 footer = foot || self._renderFileFooter(cat, caption, size, 'auto', isError), isRotatable,
                 forcePrevIcon = self.preferIconicPreview, forceZoomIcon = self.preferIconicZoomPreview,
-                newCat = forcePrevIcon ? 'other' : cat, ext =  filename.split('.').pop().toLowerCase();
+                newCat = forcePrevIcon ? 'other' : cat, ext = filename.split('.').pop().toLowerCase();
             config = screenW < 400 ? (self.previewSettingsSmall[newCat] || self.defaults.previewSettingsSmall[newCat]) :
                 (self.previewSettings[newCat] || self.defaults.previewSettings[newCat]);
             if (config) {
@@ -4423,7 +4436,7 @@
             ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
             isRotatable = self.fileActionSettings.showRotate && $.inArray(ext, self.rotatableFileExtensions) !== -1;
             if (self.fileActionSettings.showZoom) {
-                addFrameCss = 'kv-zoom-thumb'
+                addFrameCss = 'kv-zoom-thumb';
                 if (isRotatable) {
                     addFrameCss += ' rotatable' + (forceZoomIcon ? ' hide-rotate' : '');
                 }
@@ -4512,7 +4525,6 @@
                 name = ($h.isIE(9) && $h.findFileName($el.val())) || ($el[0].files[0] && $el[0].files[0].name);
             if (!name && self.fileManager.count() > 0) {
                 file = self.fileManager.getFirstFile();
-                console.log('KV SAYS', file);
                 label = file.nameFmt;
             } else {
                 label = name ? self.slug(name) : '_';
@@ -5638,7 +5650,7 @@
                         $status.html(msg);
                         self._updateFileDetails(numFiles);
                         if (self.getFilesCount(true) > 0 && self.getFrames(':visible')) {
-                            self.$dropZone.find('.'+ self.dropZoneTitleClass).remove();
+                            self.$dropZone.find('.' + self.dropZoneTitleClass).remove();
                         }
                         readFile(i + 1);
                     }, self.processDelay);
@@ -6008,6 +6020,7 @@
             if (!self._raise('fileclear')) {
                 return;
             }
+            self.clearInput = true;
             self.$btnUpload.removeAttr('disabled');
             self._getThumbs().find('video,audio,img').each(function () {
                 $h.cleanMemory($(this));

文件差异内容过多而无法显示
+ 0 - 0
js/fileinput.min.js


+ 57 - 17
js/plugins/filetype.js

@@ -11,6 +11,33 @@
 var KrajeeFileTypeConfig = {
     minimumBytes: 4100, // A fair amount of file-types are detectable within this range,
     defaultMessages: 'End-Of-Stream',
+    tarHeaderChecksumMatches: function(buffer, offset = 0) {
+        var readSum = Number.parseInt(buffer.toString('utf8', 148, 154).replace(/\0.*$/, '').trim(), 8); // Read sum in header
+        if (Number.isNaN(readSum)) {
+            return false;
+        }
+
+        var sum = 8 * 0x20; // Initialize signed bit sum
+
+        for (let i = offset; i < offset + 148; i++) {
+            sum += buffer[i];
+        }
+
+        for (let i = offset + 156; i < offset + 512; i++) {
+            sum += buffer[i];
+        }
+
+        return readSum === sum;
+    },
+    uint32SyncSafeToken: {
+        get: function(buffer, offset) {
+            return (buffer[offset + 3] & 0x7F) | ((buffer[offset + 2]) << 7) | ((buffer[offset + 1]) << 14) | ((buffer[offset]) << 21);
+        },
+        len: 4,
+    },
+    dv: function(array) {
+        return new DataView(array.buffer, array.byteOffset);
+    },
     Token: {
         /**
          * 8-bit unsigned integer
@@ -18,10 +45,10 @@ var KrajeeFileTypeConfig = {
         UINT8: {
             len: 1,
             get: function(array, offset) {
-                return dv(array).getUint8(offset);
+                return KrajeeFileTypeConfig.dv(array).getUint8(offset);
             },
             put: function(array, offset, value) {
-                dv(array).setUint8(offset, value);
+                KrajeeFileTypeConfig.dv(array).setUint8(offset, value);
                 return offset + 1;
             }
         },
@@ -31,10 +58,10 @@ var KrajeeFileTypeConfig = {
         UINT16_LE: {
             len: 2,
             get: function(array, offset) {
-                return dv(array).getUint16(offset, true);
+                return KrajeeFileTypeConfig.dv(array).getUint16(offset, true);
             },
             put: function(array, offset, value) {
-                dv(array).setUint16(offset, value, true);
+                KrajeeFileTypeConfig.dv(array).setUint16(offset, value, true);
                 return offset + 2;
             }
         },
@@ -44,23 +71,36 @@ var KrajeeFileTypeConfig = {
         UINT16_BE: {
             len: 2,
             get: function(array, offset) {
-                return dv(array).getUint16(offset);
+                return KrajeeFileTypeConfig.dv(array).getUint16(offset);
             },
             put: function(array, offset, value) {
-                dv(array).setUint16(offset, value);
+                KrajeeFileTypeConfig.dv(array).setUint16(offset, value);
                 return offset + 2;
             }
         },
+        /**
+         * 32-bit unsigned integer, Big Endian byte order
+         */
+        INT32_BE: {
+            len: 4,
+            get: function(array, offset) {
+                return KrajeeFileTypeConfig.dv(array).getInt32(offset);
+            },
+            put: function(array, offset, value) {
+                KrajeeFileTypeConfig.dv(array).setInt32(offset, value);
+                return offset + 4;
+            }
+        },
         /**
          * 32-bit unsigned integer, Little Endian byte order
          */
         UINT32_LE: {
             len: 4,
             get: function(array, offset) {
-                return dv(array).getUint32(offset, true);
+                return KrajeeFileTypeConfig.dv(array).getUint32(offset, true);
             },
             put: function(array, offset, value) {
-                dv(array).setUint32(offset, value, true);
+                KrajeeFileTypeConfig.dv(array).setUint32(offset, value, true);
                 return offset + 4;
             }
         },
@@ -70,10 +110,10 @@ var KrajeeFileTypeConfig = {
         UINT32_BE: {
             len: 4,
             get: function(array, offset) {
-                return dv(array).getUint32(offset);
+                return KrajeeFileTypeConfig.dv(array).getUint32(offset);
             },
             put: function(array, offset, value) {
-                dv(array).setUint32(offset, value);
+                KrajeeFileTypeConfig.dv(array).setUint32(offset, value);
                 return offset + 4;
             }
         },
@@ -84,10 +124,10 @@ var KrajeeFileTypeConfig = {
         UINT64_LE: {
             len: 8,
             get: function(array, offset) {
-                return dv(array).getBigUint64(offset, true);
+                return KrajeeFileTypeConfig.dv(array).getBigUint64(offset, true);
             },
             put: function(array, offset, value) {
-                dv(array).setBigUint64(offset, value, true);
+                KrajeeFileTypeConfig.dv(array).setBigUint64(offset, value, true);
                 return offset + 8;
             }
         },
@@ -97,10 +137,10 @@ var KrajeeFileTypeConfig = {
         UINT64_BE: {
             len: 8,
             get: function(array, offset) {
-                return dv(array).getBigUint64(offset);
+                return KrajeeFileTypeConfig.dv(array).getBigUint64(offset);
             },
             put: function(array, offset, value) {
-                dv(array).setBigUint64(offset, value);
+                KrajeeFileTypeConfig.dv(array).setBigUint64(offset, value);
                 return offset + 8;
             }
         }
@@ -433,7 +473,7 @@ class FileTypeParser {
 
         if (this.checkString('ID3')) {
             await tokenizer.ignore(6); // Skip ID3 header until the header size
-            const id3HeaderLength = await tokenizer.readToken(uint32SyncSafeToken);
+            const id3HeaderLength = await tokenizer.readToken(KrajeeFileTypeConfig.uint32SyncSafeToken);
             if (tokenizer.position + id3HeaderLength > tokenizer.fileInfo.size) {
                 // Guess file type based on ID3 header for backward compatibility
                 return {
@@ -1200,7 +1240,7 @@ class FileTypeParser {
 
             async function readChunkHeader() {
                 return {
-                    length: await tokenizer.readToken(INT32_BE),
+                    length: await tokenizer.readToken(Token.INT32_BE),
                     type: await tokenizer.readToken(new StringType(4, 'binary')),
                 };
             }
@@ -1600,7 +1640,7 @@ class FileTypeParser {
         await tokenizer.peekBuffer(this.buffer, {length: Math.min(512, tokenizer.fileInfo.size), mayBeLess: true});
 
         // Requires a buffer size of 512 bytes
-        if (tarHeaderChecksumMatches(this.buffer)) {
+        if (KrajeeFileTypeConfig.tarHeaderChecksumMatches(this.buffer)) {
             return {
                 ext: 'tar',
                 mime: 'application/x-tar',

文件差异内容过多而无法显示
+ 0 - 0
js/plugins/filetype.min.js


+ 8 - 4
scss/fileinput.scss

@@ -840,7 +840,7 @@ input[type=file].file-loading {
   box-shadow: none;
 }
 
-.file-preview-other-frame, .file-preview-object, .kv-zoom-body {
+.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body {
   display: flex;
   align-items: center;
   justify-content: center;
@@ -864,13 +864,13 @@ input[type=file].file-loading {
     }
   }
   .file-zoom-detail {
-    transform-origin: top left;
+    transform-origin: center center;
   }
   .kv-file-content {
-    transform-origin: top left;
+    transform-origin: center center;
     > {
       &:first-child {
-        transform-origin: top left;
+        transform-origin: center center;
       }
     }
   }
@@ -878,4 +878,8 @@ input[type=file].file-loading {
 
 .rotate-animate {
   transition: transform 0.3s ease;
+}
+
+.kv-overflow-hidden {
+  overflow: hidden;
 }

部分文件因为文件数量过多而无法显示