Преглед на файлове

Add Image rotation button action feature in thumbnail and zoom fixes #1785

Kartik Visweswaran преди 2 години
родител
ревизия
a2e00b9055
променени са 63 файла, в които са добавени 427 реда и са изтрити 117 реда
  1. 5 1
      CHANGE.md
  2. 22 2
      css/fileinput.css
  3. 0 0
      css/fileinput.min.css
  4. 251 103
      js/fileinput.js
  5. 0 0
      js/fileinput.min.js
  6. 2 0
      js/locales/LANG.js
  7. 2 0
      js/locales/ar.js
  8. 2 0
      js/locales/az.js
  9. 2 0
      js/locales/bg.js
  10. 2 0
      js/locales/ca.js
  11. 2 0
      js/locales/cr.js
  12. 2 0
      js/locales/cs.js
  13. 2 0
      js/locales/da.js
  14. 2 0
      js/locales/de.js
  15. 2 0
      js/locales/el.js
  16. 2 0
      js/locales/es.js
  17. 2 0
      js/locales/et.js
  18. 2 0
      js/locales/fa.js
  19. 2 0
      js/locales/fi.js
  20. 2 0
      js/locales/fr.js
  21. 2 0
      js/locales/gl.js
  22. 2 0
      js/locales/he.js
  23. 2 0
      js/locales/hu.js
  24. 2 0
      js/locales/id.js
  25. 2 0
      js/locales/it.js
  26. 2 0
      js/locales/ja.js
  27. 2 0
      js/locales/ka.js
  28. 2 0
      js/locales/kr.js
  29. 2 0
      js/locales/kz.js
  30. 2 0
      js/locales/lt.js
  31. 2 0
      js/locales/lv.js
  32. 2 0
      js/locales/nl.js
  33. 2 0
      js/locales/no.js
  34. 2 0
      js/locales/pl.js
  35. 2 0
      js/locales/pt-BR.js
  36. 2 0
      js/locales/pt.js
  37. 2 0
      js/locales/ro.js
  38. 2 0
      js/locales/ru.js
  39. 2 0
      js/locales/sk.js
  40. 2 0
      js/locales/sl.js
  41. 2 0
      js/locales/sr-latn.js
  42. 2 0
      js/locales/sv.js
  43. 2 0
      js/locales/th.js
  44. 2 0
      js/locales/tr.js
  45. 2 0
      js/locales/uk.js
  46. 2 0
      js/locales/uz-Cy.js
  47. 2 0
      js/locales/uz.js
  48. 2 0
      js/locales/vi.js
  49. 2 0
      js/locales/zh-TW.js
  50. 2 0
      js/locales/zh.js
  51. 37 1
      scss/fileinput.scss
  52. 3 1
      themes/bs5/theme.js
  53. 1 1
      themes/bs5/theme.min.js
  54. 3 1
      themes/explorer-fa/theme.js
  55. 0 0
      themes/explorer-fa/theme.min.js
  56. 3 1
      themes/explorer-fas/theme.js
  57. 0 0
      themes/explorer-fas/theme.min.js
  58. 3 1
      themes/fa/theme.js
  59. 1 1
      themes/fa/theme.min.js
  60. 3 1
      themes/fas/theme.js
  61. 1 1
      themes/fas/theme.min.js
  62. 3 1
      themes/gly/theme.js
  63. 1 1
      themes/gly/theme.min.js

+ 5 - 1
CHANGE.md

@@ -6,7 +6,6 @@ Change Log: `bootstrap-fileinput`
 **Date**: 19-Jun-2022
 
 - (enh #1792): Advanced file mime type detection for preview irrespective of file extension.
-   - New property `autoRenameExtension` which defaults to `true` - this will auto detect mime type and append the parsed new extension.
    - Load the following new plugin files before fileinput.min.js
 ```html
 <!-- buffer.min.js and filetype.min.js are necessary in the order listed for advanced mime type parsing and more correct
@@ -16,6 +15,11 @@ Change Log: `bootstrap-fileinput`
 <script src="https://cdn.jsdelivr.net/gh/kartik-v/[email protected]/js/plugins/buffer.min.js" type="text/javascript"></script>
 <script src="https://cdn.jsdelivr.net/gh/kartik-v/[email protected]/js/plugins/filetype.min.js" type="text/javascript"></script>
 ```   
+- (enh #1785): Image rotation button action feature in thumbnail and zoom.
+  - New property `rotatableFileExtensions` defaults to ['jpg', 'jpeg', 'png', 'gif'], 
+  - New properties in `fileActionSettings` (`rotateIcon`, `rotateTitle`, `rotateClass`)
+  - New properties `previewZoomButtonIcons.rotate`, `previewZoomButtonClasses.rotate`  and `previewZoomButtonTitles.rotate`
+
 - (enh #1788): Enhancements to `showUserError` method.
   - New 3rd parameter `retainErrorHistory` which allows you to retain previous errors (defaults to false) 
 ```js

+ 22 - 2
css/fileinput.css

@@ -329,7 +329,7 @@ input[type=file].file-loading {
     text-align: center;
     padding-top: 4px;
     font-size: 11px;
-    color: #777;
+    color: #999;
     margin-bottom: 30px;
 }
 
@@ -661,4 +661,24 @@ input[type=file].file-loading {
     display: flex;
     align-items: center;
     justify-content: center;
-}
+}
+
+.btn-kv-rotate,
+.kv-file-rotate {
+    display: none;
+}
+
+.rotatable .btn-kv-rotate,
+.rotatable .kv-file-rotate {
+    display: inline-block;
+}
+
+.rotatable .file-zoom-detail,
+.rotatable .kv-file-content,
+.rotatable .kv-file-content > :first-child {
+    transform-origin: top left;
+}
+
+.rotate-animate {
+    transition: transform 0.3s ease;
+}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
css/fileinput.min.css


+ 251 - 103
js/fileinput.js

@@ -426,6 +426,15 @@
             }
             return false;
         },
+        isPdf: function (str) {
+            if ($h.isEmpty(str)) {
+                return false;
+            }
+            str = str.toString().trim().replace(/\n/g, ' ');
+            if (str.length === 0) {
+                return false;
+            }
+        },
         isSvg: function (str) {
             if ($h.isEmpty(str)) {
                 return false;
@@ -1103,7 +1112,8 @@
                     return out;
                 },
                 exists: function (id) {
-                    return $.inArray(id, self.fileManager.getIdList()) !== -1;
+                    var list = self.fileManager.getIdList();
+                    return $.inArray(id, list) !== -1 && (!altId || $.inArray(altId, list) !== -1);
                 },
                 count: function () {
                     return self.fileManager.getIdList().length;
@@ -1691,7 +1701,7 @@
                 tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionDownload,
                 tActionZoom, tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage,
                 tText, tOffice, tGdocs, tVideo, tAudio, tFlash, tObject, tPdf, tOther, tStyle, tZoomCache, vDefaultDim,
-                tStats, tModalLabel, tDescClose, renderObject = function (type, mime) {
+                tActionRotate, tStats, tModalLabel, tDescClose, renderObject = function (type, mime) {
                     return '<object class="kv-preview-data file-preview-' + type + '" title="{caption}" ' +
                         'data="{data}" type="' + mime + '"' + tStyle + '>\n' + $h.DEFAULT_PREVIEW + '\n</object>\n';
                 }, defBtnCss1 = 'btn btn-sm btn-kv ' + $h.defaultButtonCss();
@@ -1738,7 +1748,7 @@
                 '  <div class="modal-content">\n' +
                 '    <div class="modal-header kv-zoom-header">\n' +
                 '      <h6 class="modal-title kv-zoom-title" id="' + tModalLabel + '"><span class="kv-zoom-caption"></span> <span class="kv-zoom-size"></span></h6>\n' +
-                '      <div class="kv-zoom-actions">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
+                '      <div class="kv-zoom-actions">{rotate}{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
                 '    </div>\n' +
                 '    <div class="floating-buttons"></div>\n' +
                 '    <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
@@ -1766,7 +1776,7 @@
                 '</div>';
             tActions = '<div class="file-actions">\n' +
                 '    <div class="file-footer-buttons">\n' +
-                '        {download} {upload} {delete} {zoom} {other}' +
+                '        {rotate} {download} {upload} {delete} {zoom} {other}' +
                 '    </div>\n' +
                 '</div>\n' +
                 '{drag}\n' +
@@ -1776,6 +1786,8 @@
                 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
             tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
                 '{uploadIcon}</button>';
+            tActionRotate = '<button type="button" class="kv-file-rotate {rotateClass}" title="{rotateTitle}">' +
+                '{rotateIcon}</button>';
             tActionDownload = '<a class="kv-file-download {downloadClass}" title="{downloadTitle}" ' +
                 'href="{downloadUrl}" download="{caption}" target="_blank">{downloadIcon}</a>';
             tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
@@ -1783,7 +1795,7 @@
             tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
             tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
             tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
-                ' data-fileid="{fileid}" data-template="{template}" data-zoom="{zoomData}"';
+                ' data-fileid="{fileid}" data-filename="{filename}" data-template="{template}" data-zoom="{zoomData}"';
             tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
             tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
             tTagAft = '</div>{footer}\n{zoomCache}</div>\n';
@@ -1830,6 +1842,7 @@
                     indicator: tIndicator,
                     actions: tActions,
                     actionDelete: tActionDelete,
+                    actionRotate: tActionRotate,
                     actionUpload: tActionUpload,
                     actionDownload: tActionDownload,
                     actionZoom: tActionZoom,
@@ -1951,6 +1964,7 @@
                     showDownload: true,
                     showZoom: true,
                     showDrag: true,
+                    showRotate: true,
                     removeIcon: '<i class="bi-trash"></i>',
                     removeClass: defBtnCss1,
                     removeErrorClass: 'btn btn-sm btn-kv btn-danger',
@@ -1958,11 +1972,14 @@
                     uploadIcon: '<i class="bi-upload"></i>',
                     uploadClass: defBtnCss1,
                     uploadTitle: 'Upload file',
-                    uploadRetryIcon: '<i class="bi-arrow-clockwise"></i>',
+                    uploadRetryIcon: '<i class="bi-cloud-arrow-up-fill"></i>',
                     uploadRetryTitle: 'Retry upload',
                     downloadIcon: '<i class="bi-download"></i>',
                     downloadClass: defBtnCss1,
                     downloadTitle: 'Download file',
+                    rotateIcon: '<i class="bi-arrow-clockwise"></i>',
+                    rotateClass: defBtnCss1,
+                    rotateTitle: 'Rotate 90 deg. clockwise',
                     zoomIcon: '<i class="bi-zoom-in"></i>',
                     zoomClass: defBtnCss1,
                     zoomTitle: 'View Details',
@@ -2045,7 +2062,7 @@
                                 id = self.previewInitId + '-' + ind,
                                 fileId = config && config.fileId || id;
                             /** @namespace config.zoomData */
-                            return self._generatePreviewTemplate(cat, dat, fname, ftype, id, fileId, false, null, fc,
+                            return self._generatePreviewTemplate(cat, dat, fname, ftype, id, fileId, false, null, null, fc,
                                 ftr, ind, t, a, config && config.zoomData || dat);
                         };
                     if (!content || !content.length) {
@@ -2199,12 +2216,13 @@
                         dFil = config.filename || config.caption || '',
                         initPreviewShowDwl = !!(dUrl),
                         sDel = $h.ifSet('showRemove', config, initPreviewShowDel),
+                        sRot = $h.ifSet('showRotate', config, $h.ifSet('showRotate', fs, true)),
                         sDwl = $h.ifSet('showDownload', config, $h.ifSet('showDownload', fs, initPreviewShowDwl)),
                         sZm = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
                         sDrg = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
                         dis = (url === false) && isDisabled;
                     sDwl = sDwl && config.downloadUrl !== false && !!dUrl;
-                    a = self._renderFileActions(config, false, sDwl, sDel, sZm, sDrg, dis, url, key, true, dUrl, dFil);
+                    a = self._renderFileActions(config, false, sDwl, sDel, sRot, sZm, sDrg, dis, url, key, true, dUrl, dFil);
                     return self._getLayoutTemplate('footer').setTokens({
                         'progress': self._renderThumbProgress(),
                         'actions': a,
@@ -2868,6 +2886,7 @@
                 'zoomFrameClass': self.frameClass,
                 'prev': self._getZoomButton('prev'),
                 'next': self._getZoomButton('next'),
+                'rotate': self._getZoomButton('rotate'),
                 'toggleheader': self._getZoomButton('toggleheader'),
                 'fullscreen': self._getZoomButton('fullscreen'),
                 'borderless': self._getZoomButton('borderless'),
@@ -2925,9 +2944,9 @@
             });
         },
         _initZoomButtons: function () {
-            var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
-                thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-kv-prev'),
-                $next = self.$modal.find('.btn-kv-next');
+            var self = this, $modal = self.$modal, previewId = $modal.data('previewId') || '', $first, $last,
+                thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = $modal.find('.btn-kv-prev'),
+                $next = $modal.find('.btn-kv-next'), $rotate = $modal.find('.btn-kv-rotate');
             if (thumbs.length < 2) {
                 $prev.hide();
                 $next.hide();
@@ -3126,17 +3145,33 @@
             });
         },
         _showModal: function ($frame) {
-            var self = this, $modal = self.$modal;
+            var self = this, $modal = self.$modal, $content, css, angle;
             if (!$frame || !$frame.length) {
                 return;
             }
             $h.initModal($modal);
             $h.setHtml($modal, self._getModalContent());
             self._setZoomContent($frame);
+            $modal.removeClass('rotatable');
             $modal.data({backdrop: false, fileinputPluginId: self.$element.attr('id')});
             $modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
+            $content = $frame.find('.kv-file-content > :first-child');
+            if ($content.length) {
+                css = $content.css('transform');
+                if (css) {
+                    $modal.find('.file-zoom-detail').css('transform', css);
+                }
+            }
+            if ($frame.hasClass('rotatable')) {
+                $modal.addClass('rotatable');
+            }
+            if ($frame.data('angle')) {
+                $modal.data('angle', $frame.data('angle'));
+            }
+            angle = ($frame.data('angle') || 0);
             $modal.modal('show');
             self._initZoomButtons();
+            self._initRotateZoom($frame, $content);
         },
         _zoomPreview: function ($btn) {
             var self = this, $frame;
@@ -3147,8 +3182,9 @@
             self._showModal($frame);
         },
         _zoomSlideShow: function (dir, previewId) {
-            var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-kv-' + dir), $targFrame, i, $thumb,
-                thumbsData = self.getFrames().toArray(), thumbs = [], len = thumbsData.length, out;
+            var self = this, $modal = self.$modal, $btn = $modal.find('.kv-zoom-actions .btn-kv-' + dir), $targFrame, i,
+                $thumb, thumbsData = self.getFrames().toArray(), thumbs = [], len = thumbsData.length, out, angle,
+                $content;
             if (self.reversePreviewOrder) {
                 dir = dir === 'prev' ? 'next' : 'prev';
             }
@@ -3176,6 +3212,14 @@
                 self._setZoomContent($targFrame, dir);
             }
             self._initZoomButtons();
+            if ($targFrame.length && $targFrame.hasClass('rotatable')) {
+                angle = $targFrame.data('angle') || 0;
+                $modal.addClass('rotatable').data('angle', angle);
+                $content = $targFrame.find('.kv-file-content > :first-child');
+                self._initRotateZoom($targFrame, $content);
+            } else {
+                $modal.removeClass('rotatable').removeData('angle');
+            }
             self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
         },
         _initZoomButton: function () {
@@ -4026,12 +4070,76 @@
                 }
             }, self.processDelay);
         },
+        _handleRotation: function ($el, $content, angle) {
+            var self = this, css, newCss, addCss = '', scale = 1, elContent = $content[0], quadrant, transform, h, w;
+            if (!$content.length) {
+                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);
+            }
+            angle = angle || 0;
+            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;
+            }
+            $content.addClass('rotate-animate').css('transform', css + addCss);
+            setTimeout(function () {
+                $content.removeClass('rotate-animate').css('transform', newCss + addCss);
+                $el.data('angle', quadrant);
+            }, self.fadeDelay);
+        },
+        _initRotateButton: function () {
+            var self = this;
+            self.getFrames('.rotatable .kv-file-rotate').each(function () {
+                var $el = $(this), $frame = $el.closest($h.FRAMES),
+                    $content = $frame.find('.kv-file-content > :first-child');
+                self._handler($el, 'click', function () {
+                    var angle = ($frame.data('angle') || 0) + 90;
+                    self._handleRotation($frame, $content, angle);
+                });
+            });
+        },
+        _initRotateZoom: function ($frame, $content) {
+            var self = this, $modal = self.$modal, $rotate = $modal.find('.btn-kv-rotate'),
+                angle = $frame.data('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;
+                        self._handleRotation($modal, $modal.find('.file-zoom-detail'), angle);
+                        self._handleRotation($frame, $content, angle);
+                    });
+                }
+            }
+        },
         _initFileActions: function () {
             var self = this;
             if (!self.showPreview) {
                 return;
             }
             self._initZoomButton();
+            self._initRotateButton();
             self.getFrames(' .kv-file-remove').each(function () {
                 var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
                     ind = $frame.attr('data-fileindex'), status, fm = self.fileManager;
@@ -4087,6 +4195,7 @@
                     }
                 };
             self._initZoomButton();
+            self._initRotateButton();
             $preview.find(btnRemove).each(function () {
                 var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key'), errMsg, fnBefore,
                     fnSuccess, fnError, op = self.ajaxOperations.deleteThumb;
@@ -4235,6 +4344,7 @@
             fileId,
             isError,
             size,
+            fnameUpdated,
             frameClass,
             foot,
             ind,
@@ -4243,11 +4353,12 @@
             zoomData
         ) {
             var self = this, caption = self.slug(fname), prevContent, zoomContent = '', styleAttribs = '',
+                filename = fnameUpdated || fname,
                 screenW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
-                config, title = caption, alt = caption, typeCss = 'type-default', getContent,
-                footer = foot || self._renderFileFooter(cat, caption, size, 'auto', isError),
+                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;
+                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) {
@@ -4292,6 +4403,7 @@
                     'type': self._getFileType(ftype),
                     'fileindex': ind,
                     'fileid': fileId || '',
+                    'filename': filename,
                     'typeCss': typeCss,
                     'footer': footer,
                     'data': zoom && vZoomData ? self.zoomPlaceholder + '{zoomData}' : vData,
@@ -4306,14 +4418,23 @@
                 return tmplt.setTokens(tokens);
             };
             ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
+            isRotatable = self.fileActionSettings.showRotate && $.inArray(ext, self.rotatableFileExtensions) !== -1;
             if (self.fileActionSettings.showZoom) {
-                zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb', zoomData);
+                addFrameCss = 'kv-zoom-thumb';
+                if (isRotatable && !forceZoomIcon) {
+                    addFrameCss += ' rotatable';
+                }
+                zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, addFrameCss, zoomData);
             }
             zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
             if (typeof self.sanitizeZoomCache === 'function') {
                 zoomContent = self.sanitizeZoomCache(zoomContent);
             }
-            prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb', zoomData);
+            addFrameCss = 'kv-preview-thumb';
+            if (isRotatable && !forcePrevIcon) {
+                addFrameCss += ' rotatable';
+            }
+            prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, addFrameCss, zoomData);
             return prevContent.setTokens({zoomCache: zoomContent});
         },
         _addToPreview: function ($preview, content) {
@@ -4344,12 +4465,12 @@
             if (!this.showPreview) {
                 return;
             }
-            var self = this, fname = fileInfo.filename || $h.getFileName(file), ftype = fileInfo.type, content,
+            var self = this, fname = $h.getFileName(file), ftype = fileInfo.type, content,
                 caption = fileInfo.name, cat = self._parseFileType(ftype, fname), $preview = self.$preview,
                 fsize = file.size || 0, iData = cat === 'image' ? theFile.target.result : data, fm = self.fileManager,
                 fileId = fm.getId(file), previewId = self._getThumbId(fileId);
             /** @namespace window.DOMPurify */
-            content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, fileId, false, fsize);
+            content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, fileId, false, fsize, fileInfo.filename);
             self._clearDefaultPreview();
             self._addToPreview($preview, content);
             var $thumb = self._getFrame(previewId);
@@ -4388,6 +4509,7 @@
                 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) : '_';
@@ -5037,7 +5159,7 @@
         },
         _renderFileFooter: function (cat, caption, size, width, isError) {
             var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
-                upl = config.showUpload, zoom = config.showZoom, out, params,
+                upl = config.showUpload, rot = config.showRotate, zoom = config.showZoom, out, params,
                 template = self._getLayoutTemplate('footer'), tInd = self._getLayoutTemplate('indicator'),
                 ind = isError ? config.indicatorError : config.indicatorNew,
                 title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
@@ -5046,9 +5168,9 @@
             params = {type: cat, caption: caption, size: size, width: width, progress: '', indicator: indicator};
             if (self.isAjaxUpload) {
                 params.progress = self._renderThumbProgress();
-                params.actions = self._renderFileActions(params, upl, false, rem, zoom, drg, false, false, false);
+                params.actions = self._renderFileActions(params, upl, false, rem, rot, zoom, drg, false, false, false);
             } else {
-                params.actions = self._renderFileActions(params, false, false, false, zoom, drg, false, false, false);
+                params.actions = self._renderFileActions(params, false, false, false, false, zoom, drg, false, false, false);
             }
             out = template.setTokens(params);
             out = $h.replaceTags(out, self.previewThumbTags);
@@ -5059,6 +5181,7 @@
             showUpl,
             showDwn,
             showDel,
+            showRot,
             showZoom,
             showDrag,
             disabled,
@@ -5091,10 +5214,13 @@
             if (typeof showDrag === 'function') {
                 showDrag = showDrag(cfg);
             }
-            if (!showUpl && !showDwn && !showDel && !showZoom && !showDrag) {
+            if (typeof showRot === 'function') {
+                showRot = showRot(cfg);
+            }
+            if (!showUpl && !showDwn && !showDel && !showRot && !showZoom && !showDrag) {
                 return '';
             }
-            var vUrl = url === false ? '' : ' data-url="' + url + '"', btnZoom = '', btnDrag = '', css,
+            var vUrl = url === false ? '' : ' data-url="' + url + '"', btnZoom = '', btnDrag = '', btnRotate = '', css,
                 vKey = key === false ? '' : ' data-key="' + key + '"', btnDelete = '', btnUpload = '', btnDownload = '',
                 template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
                 otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey, 'key': key}),
@@ -5109,6 +5235,13 @@
                     'key': key
                 });
             }
+            if (showRot) {
+                btnRotate = self._getLayoutTemplate('actionRotate').setTokens({
+                    'rotateClass': config.rotateClass,
+                    'rotateIcon': config.rotateIcon,
+                    'rotateTitle': config.rotateTitle
+                });
+            }
             if (showUpl) {
                 btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
                     'uploadClass': config.uploadClass,
@@ -5144,6 +5277,7 @@
                 'delete': btnDelete,
                 'upload': btnUpload,
                 'download': btnDownload,
+                'rotate': btnRotate,
                 'zoom': btnZoom,
                 'drag': btnDrag,
                 'other': otherButtons
@@ -5474,38 +5608,45 @@
                     return;
                 }
                 self.lock(true);
-                var file = files[i], id = self._getFileId(file), previewId = previewInitId + '-' + id,
+                var file = files[i], id, previewId, fileProcessed,
                     fSize = (file && file.size || 0), sizeHuman = self._getSize(fSize, true), j, msg,
-                    fnImage = settings.image, chk, typ, typ1, typ2, caption = self._getFileName(file, ''),
-                    fileSize = fSize / self.bytesToKB, fileExtExpr = '', previewData = $h.createObjectURL(file),
-                    fileCount = 0,
-                    strTypes = '', fileId, canLoad, fileReaderAborted = false,
-                    func, knownTypes = 0, isImage, processFileLoaded = function () {
-                        var isImageResized = !!fm.loadedImages[id], msg = msgProgress.setTokens({
-                            'index': i + 1,
-                            'files': numFiles,
-                            'percent': 50,
-                            'name': caption
-                        });
-                        setTimeout(function () {
-                            $status.html(msg);
-                            self._updateFileDetails(numFiles);
-                            readFile(i + 1);
-                        }, self.processDelay);
-                        if (self._raise('fileloaded', [file, previewId, id, i, reader]) && self.isAjaxUpload) {
-                            if (!isImageResized) {
-                                fm.add(file);
-                            }
-                        } else {
-                            if (isImageResized) {
-                                fm.removeFile(id);
-                            }
+                    fnImage = settings.image, chk, typ, typ1, typ2, caption, fileSize = fSize / self.bytesToKB,
+                    fileExtExpr = '', previewData, fileCount = 0, strTypes = '', fileId, canLoad,
+                    fileReaderAborted = false, func, knownTypes = 0, isImage, processFileLoaded, initFileData;
+                initFileData = function (dataSource) {
+                    dataSource = dataSource || file;
+                    id = fileId = self._getFileId(file);
+                    previewId = previewInitId + '-' + id;
+                    previewData = $h.createObjectURL(dataSource);
+                    caption = self._getFileName(file, '');
+                };
+                processFileLoaded = function () {
+                    var isImageResized = !!fm.loadedImages[id], msg = msgProgress.setTokens({
+                        'index': i + 1,
+                        'files': numFiles,
+                        'percent': 50,
+                        'name': caption
+                    });
+                    setTimeout(function () {
+                        $status.html(msg);
+                        self._updateFileDetails(numFiles);
+                        readFile(i + 1);
+                    }, self.processDelay);
+                    if (self._raise('fileloaded', [file, previewId, id, i, reader]) && self.isAjaxUpload) {
+                        if (!isImageResized) {
+                            fm.add(file);
                         }
-                    };
+                    } else {
+                        if (isImageResized) {
+                            fm.removeFile(id);
+                        }
+                    }
+                };
                 if (!file) {
                     return;
                 }
-                fileId = fm.getId(file);
+                initFileData();
+
                 if (typLen > 0) {
                     for (j = 0; j < typLen; j++) {
                         typ1 = fileTypes[j];
@@ -5612,55 +5753,59 @@
                     self._errorHandler(evt, caption);
                 };
                 reader.onload = function (theFile) {
-                    var hex, fileInfo, fileData, byte, bytes = [], contents, mime, processPreview = function (fType, ext) {
-                        if ($h.isEmpty(fType)) { // look for ascii text content
-                            contents = $h.arrayBuffer2String(reader.result);
-                            fType = $h.isSvg(contents) ? 'image/svg+xml' : $h.getMimeType(hex, contents, file.type);
-                        }
-                        fileInfo = {'name': caption, 'type': fType || ''};
-                        var chkExt = caption.split('.').pop().toLowerCase();
-                        if (ext && self.autoRenameExtension && chkExt !== ext) {
-                            caption = caption + '.' + ext;
-                            fileInfo.name = fileInfo.filename = caption;
-                        }
-                        isImage = fnImage(fType, '');
-                        if (isImage) {
-                            var newReader = new FileReader();
-                            newReader.onerror = function (theFileNew) {
-                                self._errorHandler(theFileNew, caption);
-                            };
-                            newReader.onload = function (theFileNew) {
-                                if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
-                                    fileReaderAborted = true;
-                                    self._resetCaption();
-                                    reader.abort();
-                                    $status.html('');
-                                    $container.removeClass('file-thumb-loading');
-                                    self._initCapStatus('valid');
-                                    self.enable();
-                                    return;
+                    var hex, fileInfo, fileData, byte, bytes = [], contents, mime,
+                        processPreview = function (fType, ext) {
+                            if ($h.isEmpty(fType)) { // look for ascii text content
+                                contents = $h.arrayBuffer2String(reader.result);
+                                fType = $h.isSvg(contents) ? 'image/svg+xml' : $h.getMimeType(hex, contents, file.type);
+                            }
+                            fileInfo = {'name': caption, 'type': fType || ''};
+                            if (ext && typeof File !== "undefined") {
+                                try {
+                                    var fName = fileInfo.filename = caption + '.' + ext;
+                                    fileProcessed = new File([file], fName, {type: fileInfo.type});
+                                    initFileData(fileProcessed);
+                                } catch (err) {
                                 }
-                                self._previewFile(i, file, theFileNew, previewData, fileInfo);
-                                self._initFileActions();
-                                processFileLoaded();
-                            };
-                            newReader.readAsDataURL(file);
-                            return;
-                        }
-                        if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
-                            fileReaderAborted = true;
-                            self._resetCaption();
-                            reader.abort();
-                            $status.html('');
-                            $container.removeClass('file-thumb-loading');
-                            self._initCapStatus('valid');
-                            self.enable();
-                            return;
-                        }
-                        self._previewFile(i, file, theFile, previewData, fileInfo);
-                        self._initFileActions();
-                        processFileLoaded();
-                    };
+                            }
+                            isImage = fnImage(fType, '');
+                            if (isImage) {
+                                var newReader = new FileReader();
+                                newReader.onerror = function (theFileNew) {
+                                    self._errorHandler(theFileNew, caption);
+                                };
+                                newReader.onload = function (theFileNew) {
+                                    if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
+                                        fileReaderAborted = true;
+                                        self._resetCaption();
+                                        reader.abort();
+                                        $status.html('');
+                                        $container.removeClass('file-thumb-loading');
+                                        self._initCapStatus('valid');
+                                        self.enable();
+                                        return;
+                                    }
+                                    self._previewFile(i, file, theFileNew, previewData, fileInfo);
+                                    self._initFileActions();
+                                    processFileLoaded();
+                                };
+                                newReader.readAsDataURL(file);
+                                return;
+                            }
+                            if (self.isAjaxUpload && !self._raise('filebeforeload', [file, i, reader])) {
+                                fileReaderAborted = true;
+                                self._resetCaption();
+                                reader.abort();
+                                $status.html('');
+                                $container.removeClass('file-thumb-loading');
+                                self._initCapStatus('valid');
+                                self.enable();
+                                return;
+                            }
+                            self._previewFile(i, file, theFile, previewData, fileInfo);
+                            self._initFileActions();
+                            processFileLoaded();
+                        };
                     mime = file.type;
                     fileInfo = {'name': caption, 'type': mime};
                     $.each(settings, function (k, f) {
@@ -5670,7 +5815,7 @@
                     });
                     if (typeof FileTypeParser !== "undefined") {
                         fileData = new Uint8Array(theFile.target.result);
-                        new FileTypeParser().parse(fileData).then(function (result){
+                        new FileTypeParser().parse(fileData).then(function (result) {
                             processPreview(result && result.mime || mime, result && result.ext || '');
                         });
                     } else {
@@ -6108,7 +6253,6 @@
         browseOnZoneClick: false,
         autoReplace: false,
         showDescriptionClose: true,
-        autoRenameExtension: true,
         autoOrientImage: function () { // applicable for JPEG images only and non ios safari
             var ua = window.navigator.userAgent, webkit = !!ua.match(/WebKit/i),
                 iOS = !!ua.match(/iP(od|ad|hone)/i), iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
@@ -6152,6 +6296,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="bi-chevron-left"></i>',
             next: '<i class="bi-chevron-right"></i>',
+            rotate: '<i class="bi-arrow-clockwise"></i>',
             toggleheader: '<i class="bi-arrows-expand"></i>',
             fullscreen: '<i class="bi-arrows-fullscreen"></i>',
             borderless: '<i class="bi-arrows-angle-expand"></i>',
@@ -6160,6 +6305,7 @@
         previewZoomButtonClasses: {
             prev: 'btn btn-default btn-outline-secondary btn-navigate',
             next: 'btn btn-default btn-outline-secondary btn-navigate',
+            rotate: defBtnCss1,
             toggleheader: defBtnCss1,
             fullscreen: defBtnCss1,
             borderless: defBtnCss1,
@@ -6339,6 +6485,7 @@
             'pdf': 'PDF',
             'object': 'object'
         },
+        rotatableFileExtensions: ['jpg', 'jpeg', 'png', 'gif'],
         msgUploadAborted: 'The file upload was aborted',
         msgUploadThreshold: 'Processing &hellip;',
         msgUploadBegin: 'Initializing &hellip;',
@@ -6377,6 +6524,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
js/fileinput.min.js


+ 2 - 0
js/locales/LANG.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Upload file',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'View details',
             dragTitle: 'Move / Rearrange',
             indicatorNewTitle: 'Not uploaded yet',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/ar.js

@@ -105,6 +105,7 @@
             uploadTitle: 'رفع الملف',
             uploadRetryTitle: 'إعادة محاولة التحميل',
             downloadTitle: 'تنزيل الملف',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'مشاهدة التفاصيل',
             dragTitle: 'نقل / إعادة ترتيب',
             indicatorNewTitle: 'لم يتم الرفع بعد',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'عرض الملف السابق',
             next: 'عرض الملف التالي',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'تبديل الرأسية',
             fullscreen: 'تبديل ملء الشاشة',
             borderless: 'تبديل وضع بلا حدود',

+ 2 - 0
js/locales/az.js

@@ -105,6 +105,7 @@
             uploadTitle: 'Faylı yüklə',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'məlumatlara bax',
             dragTitle: 'Yerini dəyiş və ya sırala',
             indicatorNewTitle: 'Davam edir',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'Əvvəlki fayla bax',
             next: 'Növbəti fayla bax',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Başlığı dəyiş',
             fullscreen: 'Tam ekranı dəyiş',
             borderless: 'Bölmələrsiz rejimi dəyiş',

+ 2 - 0
js/locales/bg.js

@@ -103,6 +103,7 @@
             uploadTitle: 'Качване на файл',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Вижте детайли',
             dragTitle: 'Move / Rearrange',
             indicatorNewTitle: 'Все още не е качил',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/ca.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Pujar arxiu',
             uploadRetryTitle: 'Tornar a pujar',
             downloadTitle: 'Descarregar arxiu',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Veure detalls',
             dragTitle: 'Moure / Ordenar',
             indicatorNewTitle: 'No pujat encara',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Veure arxiu previ',
             next: 'Veure arxiu següent',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Activar capçalera',
             fullscreen: 'Activar pantalla completa',
             borderless: 'Activar mode sense vora',

+ 2 - 0
js/locales/cr.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Postavi datoteku',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Pregledavati pojedinosti',
             dragTitle: 'Move / Rearrange',
             indicatorNewTitle: 'Još nije učitao',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/cs.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Nahrát soubor',
             uploadRetryTitle: 'Opakovat nahrávání',
             downloadTitle: 'Stáhnout soubor',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Zobrazit podrobnosti',
             dragTitle: 'Posunout / Přeskládat',
             indicatorNewTitle: 'Ještě nenahrál',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Zobrazit předchozí soubor',
             next: 'Zobrazit následující soubor',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Přepnout záhlaví',
             fullscreen: 'Přepnout celoobrazovkové zobrazení',
             borderless: 'Přepnout bezrámečkové zobrazení',

+ 2 - 0
js/locales/da.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Upload fil',
             uploadRetryTitle: 'Forsøg upload igen',
             downloadTitle: 'Download fil',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Se detaljer',
             dragTitle: 'Flyt / Omarranger',
             indicatorNewTitle: 'Ikke uploadet endnu',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Se forrige fil',
             next: 'Se næste fil',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Skift titel',
             fullscreen: 'Skift fuld skærm',
             borderless: 'Skift grænseløs mode',

+ 2 - 0
js/locales/de.js

@@ -102,6 +102,7 @@
             uploadTitle: 'Datei hochladen',
             uploadRetryTitle: 'Upload erneut versuchen',
             downloadTitle: 'Datei herunterladen',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Details anzeigen',
             dragTitle: 'Verschieben / Neuordnen',
             indicatorNewTitle: 'Noch nicht hochgeladen',
@@ -113,6 +114,7 @@
         previewZoomButtonTitles: {
             prev: 'Vorherige Datei anzeigen',
             next: 'Nächste Datei anzeigen',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Header umschalten',
             fullscreen: 'Vollbildmodus umschalten',
             borderless: 'Randlosen Modus umschalten',

+ 2 - 0
js/locales/el.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Μεταφορτώστε το αρχείο',
             uploadRetryTitle: 'Δοκιμή της φόρτωσης εκ νέου',
             downloadTitle: 'Μεταφόρτωση αρχείου',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Δείτε λεπτομέρειες',
             dragTitle: 'Μετακίνηση/Προσαρμογή',
             indicatorNewTitle: 'Δεν μεταφορτώθηκε ακόμα',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Προηγούμενο αρχείο',
             next: 'Επόμενο αρχείο',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Εμφάνιση/Απόκρυψη τίτλου',
             fullscreen: 'Εναλλαγή πλήρους οθόνης',
             borderless: 'Με ή χωρίς πλαίσιο',

+ 2 - 0
js/locales/es.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Subir archivo',
             uploadRetryTitle: 'Reintentar subir',
             downloadTitle: 'Descargar archivo',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Ver detalles',
             dragTitle: 'Mover / Reordenar',
             indicatorNewTitle: 'No subido todavía',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Anterior',
             next: 'Siguiente',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Mostrar encabezado',
             fullscreen: 'Pantalla completa',
             borderless: 'Modo sin bordes',

+ 2 - 0
js/locales/et.js

@@ -102,6 +102,7 @@
             removeTitle: 'Eemalda fail',
             uploadTitle: 'Salvesta fail',
             uploadRetryTitle: 'Retry upload',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Vaata detaile',
             dragTitle: 'Liiguta / Korralda',
             indicatorNewTitle: 'Pole veel salvestatud',
@@ -113,6 +114,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/fa.js

@@ -105,6 +105,7 @@
             uploadTitle: 'آپلود فایل',
             uploadRetryTitle: 'بارگیری مجدد',
             downloadTitle: 'دریافت فایل',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'دیدن جزئیات',
             dragTitle: 'جابجایی / چیدمان',
             indicatorNewTitle: 'آپلود نشده است',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'مشاهده فایل قبلی',
             next: 'مشاهده فایل بعدی',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'نمایش عنوان',
             fullscreen: 'نمایش تمام صفحه',
             borderless: 'نمایش حاشیه',

+ 2 - 0
js/locales/fi.js

@@ -91,6 +91,7 @@
             uploadTitle: 'Upload file',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Yksityiskohdat',
             dragTitle: 'Siirrä / Järjestele',
             indicatorNewTitle: 'Ei ladattu',
@@ -102,6 +103,7 @@
         previewZoomButtonTitles: {
             prev: 'Seuraava tiedosto',
             next: 'Edellinen tiedosto',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Näytä otsikko',
             fullscreen: 'Kokonäytön tila',
             borderless: 'Rajaton tila',

+ 2 - 0
js/locales/fr.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Transférer le fichier',
             uploadRetryTitle: 'Relancer le transfert',
             downloadTitle: 'Télécharger',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Voir les détails',
             dragTitle: 'Déplacer / Réarranger',
             indicatorNewTitle: 'Pas encore transféré',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Voir le fichier précédent',
             next: 'Voir le fichier suivant',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Masquer le titre',
             fullscreen: 'Mode plein écran',
             borderless: 'Mode cinéma',

+ 2 - 0
js/locales/gl.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Subir arquivo',
             uploadRetryTitle: 'Reintentar a subida',
             downloadTitle: 'Descargar arquivo',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Ver detalles',
             dragTitle: 'Mover / Reordenar',
             indicatorNewTitle: 'Non subido aínda',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Ver arquivo anterior',
             next: 'Ver arquivo seguinte',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Mostrar encabezado',
             fullscreen: 'Mostrar a pantalla completa',
             borderless: 'Activar o modo sen bordes',

+ 2 - 0
js/locales/he.js

@@ -99,6 +99,7 @@
         fileActionSettings: {
             removeTitle: 'הסרת קובץ',
             uploadTitle: 'טעינת קובץ',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'הצגת פרטים',
             dragTitle: 'העברה / סידור מחדש',
             indicatorNewTitle: 'עדיין לא הועלה',
@@ -110,6 +111,7 @@
         previewZoomButtonTitles: {
             prev: 'הצגת את הקובץ הקודם',
             next: 'הצגת את הקובץ הבא',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'שינוי כותרת',
             fullscreen: 'מעבר למסך מלא',
             borderless: 'שינוי המודל ללא שוליים',

+ 2 - 0
js/locales/hu.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Fájl feltöltése',
             uploadRetryTitle: 'Feltöltés újból',
             downloadTitle: 'Fájl letöltése',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Részletek megtekintése',
             dragTitle: 'Mozgatás / Átrendezés',
             indicatorNewTitle: 'Még fel nem töltött',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Előző fájl megnézése',
             next: 'Következő fájl megnézése',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Fejléc mutatása',
             fullscreen: 'Teljes képernyős mód bekapcsolása',
             borderless: 'Keret nélküli ablak mód bekapcsolása',

+ 2 - 0
js/locales/id.js

@@ -105,6 +105,7 @@
             uploadTitle: 'Unggah Berkas',
             uploadRetryTitle: 'Unggah Ulang',
             downloadTitle: 'Unduh Berkas',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Tampilkan Rincian',
             dragTitle: 'Pindah atau Atur Ulang',
             indicatorNewTitle: 'Belum diunggah',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'Lihat berkas sebelumnya',
             next: 'Lihat berkas selanjutnya',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Beralih ke tajuk',
             fullscreen: 'Beralih ke mode penuh',
             borderless: 'Beralih ke mode tanpa tepi',

+ 2 - 0
js/locales/it.js

@@ -106,6 +106,7 @@
             uploadTitle: 'Caricare un file',
             uploadRetryTitle: 'Riprova il caricamento',
             downloadTitle: 'Scarica file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Guarda i dettagli',
             dragTitle: 'Muovi / Riordina',
             indicatorNewTitle: 'Non ancora caricato',
@@ -117,6 +118,7 @@
         previewZoomButtonTitles: {
             prev: 'Vedi il file precedente',
             next: 'Vedi il file seguente',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Attiva header',
             fullscreen: 'Attiva full screen',
             borderless: 'Abilita modalità senza bordi',

+ 2 - 0
js/locales/ja.js

@@ -112,6 +112,7 @@
             removeTitle: 'ファイルを削除',
             uploadTitle: 'ファイルをアップロード',
             uploadRetryTitle: '再アップロード',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'プレビュー',
             dragTitle: '移動 / 再配置',
             indicatorNewTitle: 'まだアップロードされていません',
@@ -123,6 +124,7 @@
         previewZoomButtonTitles: {
             prev: '前のファイルを表示',
             next: '次のファイルを表示',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'ファイル情報の表示/非表示',
             fullscreen: 'フルスクリーン表示の開始/終了',
             borderless: 'フルウィンドウ表示の開始/終了',

+ 2 - 0
js/locales/ka.js

@@ -105,6 +105,7 @@
             uploadTitle: 'ფაილის ატვირთვა',
             uploadRetryTitle: 'ატვირთვის გამეორება',
             downloadTitle: 'ფაილის ჩამოტვირთვა',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'დეტალურად ნახვა',
             dragTitle: 'გადაადგილება / მიმდევრობის შეცვლა',
             indicatorNewTitle: 'ჯერ არ ატვირთულა',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'წინა ფაილის ნახვა',
             next: 'შემდეგი ფაილის ნახვა',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'სათაურის დამალვა',
             fullscreen: 'მთელ ეკრანზე გაშლა',
             borderless: 'მთელ გვერდზე გაშლა',

+ 2 - 0
js/locales/kr.js

@@ -103,6 +103,7 @@
             uploadTitle: '파일 업로드',
             uploadRetryTitle: '업로드 재시도',
             downloadTitle: '파일 다운로드',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: '세부 정보 보기',
             dragTitle: '옮기기 / 재배열하기',
             indicatorNewTitle: '아직 업로드 되지 않았습니다',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: '이전 파일',
             next: '다음 파일',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: '머릿글 토글',
             fullscreen: '전체화면 토글',
             borderless: '창 테두리 토글',

+ 2 - 0
js/locales/kz.js

@@ -91,6 +91,7 @@
             uploadTitle: 'Файлды жүктеу',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'мәліметтерді көру',
             dragTitle: 'Орнын ауыстыру',
             indicatorNewTitle: 'Жүктелген жоқ',
@@ -102,6 +103,7 @@
         previewZoomButtonTitles: {
             prev: 'Алдыңғы файлды қарау',
             next: 'Келесі файлды қарау',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Тақырыпты ауыстыру',
             fullscreen: 'Толық экран режимін қосу',
             borderless: 'Жиексіз режиміне ауысу',

+ 2 - 0
js/locales/lt.js

@@ -103,6 +103,7 @@
             removeTitle: 'Šalinti failą',
             uploadTitle: 'Įkelti failą',
             uploadRetryTitle: 'Bandyti įkelti vėl',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Peržiūrėti detales',
             dragTitle: 'Perstumti',
             indicatorNewTitle: 'Dar neįkelta',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: 'Peržiūrėti ankstesnį failą',
             next: 'Peržiūrėti kitą failą',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Perjungti viršutinę juostą',
             fullscreen: 'Perjungti pilno ekrano rėžimą',
             borderless: 'Perjungti berėmį režimą',

+ 2 - 0
js/locales/lv.js

@@ -94,6 +94,7 @@
             uploadTitle: 'Augšuplādēt failu',
             uploadRetryTitle: 'Atkārtot augšuplādēšanu',
             downloadTitle: 'Lejuplādēt failu',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Pārskatīt detaļas',
             dragTitle: 'Pārvietot / Mainīt secību',
             indicatorNewTitle: 'Vēl nav augšuplādēts',
@@ -104,6 +105,7 @@
         previewZoomButtonTitles: {
             prev: 'Skatīt iepriekšējo failu',
             next: 'Skatīt nākamo failu',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Skatīt nākamo failu',
             fullscreen: 'Pārslēgt pilnekrāna režīmu',
             borderless: 'Pārslēgt bez kontūrām',

+ 2 - 0
js/locales/nl.js

@@ -104,6 +104,7 @@
             uploadTitle: 'bestand uploaden',
             uploadRetryTitle: 'Opnieuw uploaden',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Bekijk details',
             dragTitle: 'Verplaatsen / herindelen',
             indicatorNewTitle: 'Nog niet geupload',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Toon vorig bestand',
             next: 'Toon volgend bestand',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle volledig scherm',
             borderless: 'Toggle randloze modus',

+ 2 - 0
js/locales/no.js

@@ -102,6 +102,7 @@
             removeTitle: 'Fjern fil',
             uploadTitle: 'Last opp fil',
             uploadRetryTitle: 'Retry upload',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Vis detaljer',
             dragTitle: 'Flytt / endre rekkefølge',
             indicatorNewTitle: 'Opplastning ikke fullført',
@@ -113,6 +114,7 @@
         previewZoomButtonTitles: {
             prev: 'Vis forrige fil',
             next: 'Vis neste fil',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Vis header',
             fullscreen: 'Åpne fullskjerm',
             borderless: 'Åpne uten kanter',

+ 2 - 0
js/locales/pl.js

@@ -94,6 +94,7 @@
             uploadTitle: 'Przesyłanie pliku',
             uploadRetryTitle: 'Ponów',
             downloadTitle: 'Pobierz plik',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Pokaż szczegóły',
             dragTitle: 'Przenies / Ponownie zaaranżuj',
             indicatorNewTitle: 'Jeszcze nie przesłany',
@@ -105,6 +106,7 @@
         previewZoomButtonTitles: {
             prev: 'Pokaż poprzedni plik',
             next: 'Pokaż następny plik',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Włącz / wyłącz nagłówek',
             fullscreen: 'Włącz / wyłącz pełny ekran',
             borderless: 'Włącz / wyłącz tryb bez ramek',

+ 2 - 0
js/locales/pt-BR.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Enviar arquivo',
             uploadRetryTitle: 'Repetir envio',
             downloadTitle: 'Baixar arquivo',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Ver detalhes',
             dragTitle: 'Mover / Reordenar',
             indicatorNewTitle: 'Ainda não enviado',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Visualizar arquivo anterior',
             next: 'Visualizar próximo arquivo',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Mostrar cabeçalho',
             fullscreen: 'Ativar tela cheia',
             borderless: 'Ativar modo sem borda',

+ 2 - 0
js/locales/pt.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Enviar ficheiro',
             uploadRetryTitle: 'Voltar a tentar o envio',
             downloadTitle: 'Transferir ficheiro',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Ver detalhes',
             dragTitle: 'Mover / Reorganizar',
             indicatorNewTitle: 'Ainda Não Enviado',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Ver ficheiro anterior',
             next: 'Ver próximo ficheiro',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Mostrar/esconder cabeçalho',
             fullscreen: 'Alternar entre ecrã completo',
             borderless: 'Alternar entre modo sem bordas',

+ 2 - 0
js/locales/ro.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Incarca fisier',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Vezi detalii',
             dragTitle: 'Move / Rearrange',
             indicatorNewTitle: 'Nu a încărcat încă',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/ru.js

@@ -105,6 +105,7 @@
             uploadTitle: 'Загрузить файл',
             uploadRetryTitle: 'Повторить загрузку',
             downloadTitle: 'Загрузить файл',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Посмотреть детали',
             dragTitle: 'Переместить / Изменить порядок',
             indicatorNewTitle: 'Еще не загружен',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'Посмотреть предыдущий файл',
             next: 'Посмотреть следующий файл',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Переключить заголовок',
             fullscreen: 'Переключить полноэкранный режим',
             borderless: 'Переключить режим без полей',

+ 2 - 0
js/locales/sk.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Nahrať súbor',
             uploadRetryTitle: 'Znova nahrať',
             downloadTitle: 'Stiahnuť súbor',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Zobraziť podrobnosti',
             dragTitle: 'Posunúť / Preskládať',
             indicatorNewTitle: 'Ešte nenahral',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Zobraziť predchádzajúci súbor',
             next: 'Zobraziť následujúci súbor',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Prepnúť záhlavie',
             fullscreen: 'Prepnúť zobrazenie na celú obrazovku',
             borderless: 'Prepnúť na bezrámikové zobrazenie',

+ 2 - 0
js/locales/sl.js

@@ -101,6 +101,7 @@
             uploadTitle: 'Naloži datoteko',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Poglej podrobnosti',
             dragTitle: 'Premaki / Razporedi',
             indicatorNewTitle: 'Še ni naloženo',
@@ -112,6 +113,7 @@
         previewZoomButtonTitles: {
             prev: 'Poglej prejšno datoteko',
             next: 'Poglej naslednjo datoteko',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Preklopi glavo',
             fullscreen: 'Preklopi celozaslonski način',
             borderless: 'Preklopi način brez robov',

+ 2 - 0
js/locales/sr-latn.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Pošalji dokument',
             uploadRetryTitle: 'Ponovi slanje',
             downloadTitle: 'Skini dokument',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Pregled detalja',
             dragTitle: 'Promeni redosled',
             indicatorNewTitle: 'Nije poslato',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Prethodni dokument',
             next: 'Sledeći dokument',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Isključi naslov',
             fullscreen: 'Raširi na ceo prozor',
             borderless: 'Isključi ivice',

+ 2 - 0
js/locales/sv.js

@@ -102,6 +102,7 @@
             removeTitle: 'Ta bort fil',
             uploadTitle: 'Ladda upp fil',
             uploadRetryTitle: 'Retry upload',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Visa detaljer',
             dragTitle: 'Flytta / Ändra ordning',
             indicatorNewTitle: 'Inte uppladdat ännu',
@@ -113,6 +114,7 @@
         previewZoomButtonTitles: {
             prev: 'Visa föregående fil',
             next: 'Visa nästa fil',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Rubrik',
             fullscreen: 'Fullskärm',
             borderless: 'Gränslös',

+ 2 - 0
js/locales/th.js

@@ -103,6 +103,7 @@
             uploadTitle: 'อัปโหลดไฟล์',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'ดูรายละเอียด',
             dragTitle: 'Move / Rearrange',
             indicatorNewTitle: 'ยังไม่ได้อัปโหลด',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: 'View previous file',
             next: 'View next file',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Toggle header',
             fullscreen: 'Toggle full screen',
             borderless: 'Toggle borderless mode',

+ 2 - 0
js/locales/tr.js

@@ -103,6 +103,7 @@
             removeTitle: 'Dosyayı kaldır',
             uploadTitle: 'Dosyayı yükle',
             uploadRetryTitle: 'Tekrar dene',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Ayrıntıları görüntüle',
             dragTitle: 'Taşı / Yeniden düzenle',
             indicatorNewTitle: 'Henüz yüklenmedi',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: 'Önceki dosyayı göster',
             next: 'Sonraki dosyayı göster',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Üst bilgi geçiş',
             fullscreen: 'Tam ekran geçiş',
             borderless: 'Çerçevesiz moda geçiş',

+ 2 - 0
js/locales/uk.js

@@ -105,6 +105,7 @@
             uploadTitle: 'Відвантажити файл',
             uploadRetryTitle: 'Повторити відвантаження',
             downloadTitle: 'Завантажити файл',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Подивитися деталі',
             dragTitle: 'Перенести / Переставити',
             indicatorNewTitle: 'Ще не відвантажено',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'Переглянути попередній файл',
             next: 'Переглянути наступний файл',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Перемкнути заголовок',
             fullscreen: 'Перемкнути повноекранний режим',
             borderless: 'Перемкнути режим без полів',

+ 2 - 0
js/locales/uz-Cy.js

@@ -103,6 +103,7 @@
             uploadTitle: 'Файлни юклаш',
             uploadRetryTitle: 'Қайта уруниш',
             downloadTitle: 'Файлни юклаб олиш',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Тафсилотларни кўриш',
             dragTitle: 'Кўчириш / қайта тартиблаш',
             indicatorNewTitle: 'Ҳали юкланмади',
@@ -114,6 +115,7 @@
         previewZoomButtonTitles: {
             prev: 'Олдинги файлни кўриш',
             next: 'Кейинги файлни кўриш',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Сарлавҳани яшириш',
             fullscreen: 'Тўлиқ экранга ўтиш',
             borderless: 'Чегарасиз режимга ўтиш',

+ 2 - 0
js/locales/uz.js

@@ -105,6 +105,7 @@
             uploadTitle: 'Faylni yuklash',
             uploadRetryTitle: 'Qayta yuklab olish',
             downloadTitle: 'Faylni yuklab olish',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Tafsilotlarni ko‘rish',
             dragTitle: 'Ko‘chirish / qayta tartiblash',
             indicatorNewTitle: 'Hali yuklanmagan',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: 'Oldingi faylni ko‘rish',
             next: 'Keyingi faylni ko‘rish',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Sarlavhani yashirish',
             fullscreen: 'To‘liq ekranga o‘tish',
             borderless: 'Chegarasiz rejimga o‘tish',

+ 2 - 0
js/locales/vi.js

@@ -104,6 +104,7 @@
             uploadTitle: 'Upload tập tin',
             uploadRetryTitle: 'Retry upload',
             downloadTitle: 'Download file',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: 'Phóng lớn',
             dragTitle: 'Di chuyển / Sắp xếp lại',
             indicatorNewTitle: 'Chưa được upload',
@@ -115,6 +116,7 @@
         previewZoomButtonTitles: {
             prev: 'Xem tập tin phía trước',
             next: 'Xem tập tin tiếp theo',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: 'Ẩn/hiện tiêu đề',
             fullscreen: 'Bật/tắt toàn màn hình',
             borderless: 'Bật/tắt chế độ không viền',

+ 2 - 0
js/locales/zh-TW.js

@@ -106,6 +106,7 @@
             uploadTitle: '上傳檔案',
             uploadRetryTitle: '重試',
             downloadTitle: '下載檔案',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: '詳細資料',
             dragTitle: '移動 / 重置',
             indicatorNewTitle: '尚未上傳',
@@ -117,6 +118,7 @@
         previewZoomButtonTitles: {
             prev: '預覽上壹個文件',
             next: '預覽下壹個文件',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: '縮放',
             fullscreen: '全屏',
             borderless: '無邊界模式',

+ 2 - 0
js/locales/zh.js

@@ -105,6 +105,7 @@
             uploadTitle: '上传文件',
             downloadTitle: '下载文件',
             uploadRetryTitle: '重试',
+            rotateTitle: 'Rotate 90 deg. clockwise',
             zoomTitle: '查看详情',
             dragTitle: '移动 / 重置',
             indicatorNewTitle: '没有上传',
@@ -116,6 +117,7 @@
         previewZoomButtonTitles: {
             prev: '预览上一个文件',
             next: '预览下一个文件',
+            rotate: 'Rotate 90 deg. clockwise',
             toggleheader: '缩放',
             fullscreen: '全屏',
             borderless: '无边界模式',

+ 37 - 1
scss/fileinput.scss

@@ -845,4 +845,40 @@ input[type=file].file-loading {
   display: flex;
   align-items: center;
   justify-content: center;
-}
+}
+
+.btn-kv-rotate {
+  display: none;
+}
+
+.kv-file-rotate {
+  display: none;
+}
+
+.rotatable {
+  .btn-kv-rotate {
+    display: inline-block;
+  }
+
+  .kv-file-rotate {
+    display: inline-block;
+  }
+
+  .file-zoom-detail {
+    transform-origin: top left;
+  }
+
+  .kv-file-content {
+    transform-origin: top left;
+
+    > {
+      &:first-child {
+        transform-origin: top left;
+      }
+    }
+  }
+}
+
+.rotate-animate {
+  transition: transform 0.3s ease;
+}

+ 3 - 1
themes/bs5/theme.js

@@ -27,8 +27,9 @@
         fileActionSettings: {
             removeIcon: '<i class="bi-trash"></i>',
             uploadIcon: '<i class="bi-upload"></i>',
-            uploadRetryIcon: '<i class="bi-arrow-clockwise"></i>',
+            uploadRetryIcon: '<i class="bi-cloud-arrow-up-fill"></i>',
             downloadIcon: '<i class="bi-download"></i>',
+            rotateIcon: '<i class="bi-arrow-clockwise"></i>',
             zoomIcon: '<i class="bi-zoom-in"></i>',
             dragIcon: '<i class="bi-arrows-move"></i>',
             indicatorNew: '<i class="bi-plus-lg text-warning"></i>',
@@ -43,6 +44,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="bi-chevron-left"></i>',
             next: '<i class="bi-chevron-right"></i>',
+            rotate: '<i class="bi-arrow-clockwise"></i>',
             toggleheader: '<i class="bi-arrows-expand"></i>',
             fullscreen: '<i class="bi-arrows-fullscreen"></i>',
             borderless: '<i class="bi-arrows-angle-expand"></i>',

+ 1 - 1
themes/bs5/theme.min.js

@@ -10,4 +10,4 @@
  *
  * Licensed under the BSD-3-Clause
  * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):i("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(i){"use strict";i.fn.fileinputBsVersion="5.x.x",i.fn.fileinputThemes.bs5={fileActionSettings:{removeIcon:'<i class="bi-trash"></i>',uploadIcon:'<i class="bi-upload"></i>',uploadRetryIcon:'<i class="bi-arrow-clockwise"></i>',downloadIcon:'<i class="bi-download"></i>',zoomIcon:'<i class="bi-zoom-in"></i>',dragIcon:'<i class="bi-arrows-move"></i>',indicatorNew:'<i class="bi-plus-lg text-warning"></i>',indicatorSuccess:'<i class="bi-check-lg-fill text-success"></i>',indicatorError:'<i class="bi-exclamation-lg text-danger"></i>',indicatorLoading:'<i class="bi-hourglass-bottom text-muted"></i>',indicatorPaused:'<i class="bi-pause-fill text-primary"></i>'},layoutTemplates:{fileIcon:'<i class="bi-file-earmark-arrow-up"></i>'},previewZoomButtonIcons:{prev:'<i class="bi-chevron-left"></i>',next:'<i class="bi-chevron-right"></i>',toggleheader:'<i class="bi-arrows-expand"></i>',fullscreen:'<i class="bi-arrows-fullscreen"></i>',borderless:'<i class="bi-arrows-angle-expand"></i>',close:'<i class="bi-x-lg"></i>'},previewFileIcon:'<i class="bi-file-earmark-fill"></i>',browseIcon:'<i class="bi-folder2-open"></i> ',removeIcon:'<i class="bi-trash"></i>',cancelIcon:'<i class="bi-slash-circle"></i>',pauseIcon:'<i class="bi-pause-fill"></i>',uploadIcon:'<i class="bi-upload"></i>',msgValidationErrorIcon:'<i class="bi-exclamation-circle-fill"></i> '}});
+ */!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):i("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(i){"use strict";i.fn.fileinputBsVersion="5.x.x",i.fn.fileinputThemes.bs5={fileActionSettings:{removeIcon:'<i class="bi-trash"></i>',uploadIcon:'<i class="bi-upload"></i>',uploadRetryIcon:'<i class="bi-cloud-arrow-up-fill"></i>',downloadIcon:'<i class="bi-download"></i>',rotateIcon:'<i class="bi-arrow-clockwise"></i>',zoomIcon:'<i class="bi-zoom-in"></i>',dragIcon:'<i class="bi-arrows-move"></i>',indicatorNew:'<i class="bi-plus-lg text-warning"></i>',indicatorSuccess:'<i class="bi-check-lg-fill text-success"></i>',indicatorError:'<i class="bi-exclamation-lg text-danger"></i>',indicatorLoading:'<i class="bi-hourglass-bottom text-muted"></i>',indicatorPaused:'<i class="bi-pause-fill text-primary"></i>'},layoutTemplates:{fileIcon:'<i class="bi-file-earmark-arrow-up"></i>'},previewZoomButtonIcons:{prev:'<i class="bi-chevron-left"></i>',next:'<i class="bi-chevron-right"></i>',rotate:'<i class="bi-arrow-clockwise"></i>',toggleheader:'<i class="bi-arrows-expand"></i>',fullscreen:'<i class="bi-arrows-fullscreen"></i>',borderless:'<i class="bi-arrows-angle-expand"></i>',close:'<i class="bi-x-lg"></i>'},previewFileIcon:'<i class="bi-file-earmark-fill"></i>',browseIcon:'<i class="bi-folder2-open"></i> ',removeIcon:'<i class="bi-trash"></i>',cancelIcon:'<i class="bi-slash-circle"></i>',pauseIcon:'<i class="bi-pause-fill"></i>',uploadIcon:'<i class="bi-upload"></i>',msgValidationErrorIcon:'<i class="bi-exclamation-circle-fill"></i> '}});

+ 3 - 1
themes/explorer-fa/theme.js

@@ -51,8 +51,9 @@
         fileActionSettings: {
             removeIcon: '<i class="fa fa-trash"></i>',
             uploadIcon: '<i class="fa fa-upload"></i>',
-            uploadRetryIcon: '<i class="fa fa-repeat"></i>',
+            uploadRetryIcon: '<i class="fa fa-cloud-upload"></i>',
             downloadIcon: '<i class="fa fa-download"></i>',
+            rotateIcon: '<i class="fa fa-rotate-right"></i>',
             zoomIcon: '<i class="fa fa-search-plus"></i>',
             dragIcon: '<i class="fa fa-arrows"></i>',
             indicatorNew: '<i class="fa fa-plus-circle text-warning"></i>',
@@ -64,6 +65,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="fa fa-chevron-left"></i>',
             next: '<i class="fa fa-chevron-right"></i>',
+            rotate: '<i class="fa fa-rotate-right"></i>',
             toggleheader: '<i class="fa fa-fw fa-arrows-v"></i>',
             fullscreen: '<i class="fa fa-fw fa-arrows-alt"></i>',
             borderless: '<i class="fa fa-fw fa-external-link"></i>',

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
themes/explorer-fa/theme.min.js


+ 3 - 1
themes/explorer-fas/theme.js

@@ -51,8 +51,9 @@
         fileActionSettings: {
             removeIcon: '<i class="fas fa-trash-alt"></i>',
             uploadIcon: '<i class="fas fa-upload"></i>',
-            uploadRetryIcon: '<i class="fas fa-redo-alt"></i>',
+            uploadRetryIcon: '<i class="fas fa-cloud-arrow-up"></i>',
             downloadIcon: '<i class="fas fa-download"></i>',
+            rotateIcon: '<i class="fas fa-rotate-right"></i>',
             zoomIcon: '<i class="fas fa-search-plus"></i>',
             dragIcon: '<i class="fas fa-arrows-alt"></i>',
             indicatorNew: '<i class="fas fa-plus-circle text-warning"></i>',
@@ -64,6 +65,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="fas fa-chevron-left"></i>',
             next: '<i class="fas fa-chevron-right"></i>',
+            rotate: '<i class="fas fa-rotate-right"></i>',
             toggleheader: '<i class="fas fa-fw fa-arrows-alt-v"></i>',
             fullscreen: '<i class="fas fa-fw fa-arrows-alt"></i>',
             borderless: '<i class="fas fa-fw fa-external-link-alt"></i>',

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
themes/explorer-fas/theme.min.js


+ 3 - 1
themes/fa/theme.js

@@ -26,8 +26,9 @@
         fileActionSettings: {
             removeIcon: '<i class="fa fa-trash"></i>',
             uploadIcon: '<i class="fa fa-upload"></i>',
-            uploadRetryIcon: '<i class="fa fa-repeat"></i>',
+            uploadRetryIcon: '<i class="fa fa-cloud-upload"></i>',
             downloadIcon: '<i class="fa fa-download"></i>',
+            rotateIcon: '<i class="fa fa-rotate-right"></i>',
             zoomIcon: '<i class="fa fa-search-plus"></i>',
             dragIcon: '<i class="fa fa-arrows"></i>',
             indicatorNew: '<i class="fa fa-plus-circle text-warning"></i>',
@@ -42,6 +43,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="fa fa-chevron-left"></i>',
             next: '<i class="fa fa-chevron-right"></i>',
+            rotate: '<i class="fa fa-rotate-right"></i>',
             toggleheader: '<i class="fa fa-fw fa-arrows-v"></i>',
             fullscreen: '<i class="fa fa-fw fa-arrows-alt"></i>',
             borderless: '<i class="fa fa-fw fa-external-link"></i>',

+ 1 - 1
themes/fa/theme.min.js

@@ -9,4 +9,4 @@
  *
  * Licensed under the BSD-3-Clause
  * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(a){"use strict";a.fn.fileinputThemes.fa={fileActionSettings:{removeIcon:'<i class="fa fa-trash"></i>',uploadIcon:'<i class="fa fa-upload"></i>',uploadRetryIcon:'<i class="fa fa-repeat"></i>',downloadIcon:'<i class="fa fa-download"></i>',zoomIcon:'<i class="fa fa-search-plus"></i>',dragIcon:'<i class="fa fa-arrows"></i>',indicatorNew:'<i class="fa fa-plus-circle text-warning"></i>',indicatorSuccess:'<i class="fa fa-check-circle text-success"></i>',indicatorError:'<i class="fa fa-exclamation-circle text-danger"></i>',indicatorLoading:'<i class="fa fa-hourglass text-muted"></i>',indicatorPaused:'<i class="fa fa-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="fa fa-file kv-caption-icon"></i> '},previewZoomButtonIcons:{prev:'<i class="fa fa-chevron-left"></i>',next:'<i class="fa fa-chevron-right"></i>',toggleheader:'<i class="fa fa-fw fa-arrows-v"></i>',fullscreen:'<i class="fa fa-fw fa-arrows-alt"></i>',borderless:'<i class="fa fa-fw fa-external-link"></i>',close:'<i class="fa fa-fw fa-remove"></i>'},previewFileIcon:'<i class="fa fa-file"></i>',browseIcon:'<i class="fa fa-folder-open"></i>',removeIcon:'<i class="fa fa-trash"></i>',cancelIcon:'<i class="fa fa-ban"></i>',pauseIcon:'<i class="fa fa-pause"></i>',uploadIcon:'<i class="fa fa-upload"></i>',msgValidationErrorIcon:'<i class="fa fa-exclamation-circle"></i> '}});
+ */!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(a){"use strict";a.fn.fileinputThemes.fa={fileActionSettings:{removeIcon:'<i class="fa fa-trash"></i>',uploadIcon:'<i class="fa fa-upload"></i>',uploadRetryIcon:'<i class="fa fa-cloud-upload"></i>',downloadIcon:'<i class="fa fa-download"></i>',rotateIcon:'<i class="fa fa-rotate-right"></i>',zoomIcon:'<i class="fa fa-search-plus"></i>',dragIcon:'<i class="fa fa-arrows"></i>',indicatorNew:'<i class="fa fa-plus-circle text-warning"></i>',indicatorSuccess:'<i class="fa fa-check-circle text-success"></i>',indicatorError:'<i class="fa fa-exclamation-circle text-danger"></i>',indicatorLoading:'<i class="fa fa-hourglass text-muted"></i>',indicatorPaused:'<i class="fa fa-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="fa fa-file kv-caption-icon"></i> '},previewZoomButtonIcons:{prev:'<i class="fa fa-chevron-left"></i>',next:'<i class="fa fa-chevron-right"></i>',rotate:'<i class="fa fa-rotate-right"></i>',toggleheader:'<i class="fa fa-fw fa-arrows-v"></i>',fullscreen:'<i class="fa fa-fw fa-arrows-alt"></i>',borderless:'<i class="fa fa-fw fa-external-link"></i>',close:'<i class="fa fa-fw fa-remove"></i>'},previewFileIcon:'<i class="fa fa-file"></i>',browseIcon:'<i class="fa fa-folder-open"></i>',removeIcon:'<i class="fa fa-trash"></i>',cancelIcon:'<i class="fa fa-ban"></i>',pauseIcon:'<i class="fa fa-pause"></i>',uploadIcon:'<i class="fa fa-upload"></i>',msgValidationErrorIcon:'<i class="fa fa-exclamation-circle"></i> '}});

+ 3 - 1
themes/fas/theme.js

@@ -26,8 +26,9 @@
         fileActionSettings: {
             removeIcon: '<i class="fas fa-trash-alt"></i>',
             uploadIcon: '<i class="fas fa-upload"></i>',
-            uploadRetryIcon: '<i class="fas fa-redo-alt"></i>',
+            uploadRetryIcon: '<i class="fas fa-cloud-arrow-up"></i>',
             downloadIcon: '<i class="fas fa-download"></i>',
+            rotateIcon: '<i class="fas fa-rotate-right"></i>',
             zoomIcon: '<i class="fas fa-search-plus"></i>',
             dragIcon: '<i class="fas fa-arrows-alt"></i>',
             indicatorNew: '<i class="fas fa-plus-circle text-warning"></i>',
@@ -42,6 +43,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="fas fa-chevron-left"></i>',
             next: '<i class="fas fa-chevron-right"></i>',
+            rotate: '<i class="fas fa-rotate-right"></i>',
             toggleheader: '<i class="fas fa-fw fa-arrows-alt-v"></i>',
             fullscreen: '<i class="fas fa-fw fa-arrows-alt"></i>',
             borderless: '<i class="fas fa-fw fa-external-link-alt"></i>',

+ 1 - 1
themes/fas/theme.min.js

@@ -9,4 +9,4 @@
  *
  * Licensed under the BSD-3-Clause
  * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(a){"use strict";a.fn.fileinputThemes.fas={fileActionSettings:{removeIcon:'<i class="fas fa-trash-alt"></i>',uploadIcon:'<i class="fas fa-upload"></i>',uploadRetryIcon:'<i class="fas fa-redo-alt"></i>',downloadIcon:'<i class="fas fa-download"></i>',zoomIcon:'<i class="fas fa-search-plus"></i>',dragIcon:'<i class="fas fa-arrows-alt"></i>',indicatorNew:'<i class="fas fa-plus-circle text-warning"></i>',indicatorSuccess:'<i class="fas fa-check-circle text-success"></i>',indicatorError:'<i class="fas fa-exclamation-circle text-danger"></i>',indicatorLoading:'<i class="fas fa-hourglass text-muted"></i>',indicatorPaused:'<i class="fa fa-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="fas fa-file kv-caption-icon"></i> '},previewZoomButtonIcons:{prev:'<i class="fas fa-chevron-left"></i>',next:'<i class="fas fa-chevron-right"></i>',toggleheader:'<i class="fas fa-fw fa-arrows-alt-v"></i>',fullscreen:'<i class="fas fa-fw fa-arrows-alt"></i>',borderless:'<i class="fas fa-fw fa-external-link-alt"></i>',close:'<i class="fas fa-fw fa-times"></i>'},previewFileIcon:'<i class="fas fa-file"></i>',browseIcon:'<i class="fas fa-folder-open"></i>',removeIcon:'<i class="fas fa-trash-alt"></i>',cancelIcon:'<i class="fas fa-ban"></i>',pauseIcon:'<i class="fas fa-pause"></i>',uploadIcon:'<i class="fas fa-upload"></i>',msgValidationErrorIcon:'<i class="fas fa-exclamation-circle"></i> '}});
+ */!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(a){"use strict";a.fn.fileinputThemes.fas={fileActionSettings:{removeIcon:'<i class="fas fa-trash-alt"></i>',uploadIcon:'<i class="fas fa-upload"></i>',uploadRetryIcon:'<i class="fas fa-cloud-arrow-up"></i>',downloadIcon:'<i class="fas fa-download"></i>',rotateIcon:'<i class="fas fa-rotate-right"></i>',zoomIcon:'<i class="fas fa-search-plus"></i>',dragIcon:'<i class="fas fa-arrows-alt"></i>',indicatorNew:'<i class="fas fa-plus-circle text-warning"></i>',indicatorSuccess:'<i class="fas fa-check-circle text-success"></i>',indicatorError:'<i class="fas fa-exclamation-circle text-danger"></i>',indicatorLoading:'<i class="fas fa-hourglass text-muted"></i>',indicatorPaused:'<i class="fa fa-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="fas fa-file kv-caption-icon"></i> '},previewZoomButtonIcons:{prev:'<i class="fas fa-chevron-left"></i>',next:'<i class="fas fa-chevron-right"></i>',rotate:'<i class="fas fa-rotate-right"></i>',toggleheader:'<i class="fas fa-fw fa-arrows-alt-v"></i>',fullscreen:'<i class="fas fa-fw fa-arrows-alt"></i>',borderless:'<i class="fas fa-fw fa-external-link-alt"></i>',close:'<i class="fas fa-fw fa-times"></i>'},previewFileIcon:'<i class="fas fa-file"></i>',browseIcon:'<i class="fas fa-folder-open"></i>',removeIcon:'<i class="fas fa-trash-alt"></i>',cancelIcon:'<i class="fas fa-ban"></i>',pauseIcon:'<i class="fas fa-pause"></i>',uploadIcon:'<i class="fas fa-upload"></i>',msgValidationErrorIcon:'<i class="fas fa-exclamation-circle"></i> '}});

+ 3 - 1
themes/gly/theme.js

@@ -26,7 +26,8 @@
         fileActionSettings: {
             removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
             uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
-            uploadRetryIcon: '<i class="glyphicon glyphicon-repeat"></i>',
+            uploadRetryIcon: '<i class="glyphicon glyphicon-cloud-upload"></i>',
+            rotateIcon: '<i class="glyphicon glyphicon-repeat"></i>',
             downloadIcon: '<i class="glyphicon glyphicon-download"></i>',
             zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
             dragIcon: '<i class="glyphicon glyphicon-move"></i>',
@@ -42,6 +43,7 @@
         previewZoomButtonIcons: {
             prev: '<i class="glyphicon glyphicon-menu-left"></i>',
             next: '<i class="glyphicon glyphicon-menu-right"></i>',
+            rotate: '<i class="glyphicon glyphicon-repeat"></i>',
             toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
             fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
             borderless: '<i class="glyphicon glyphicon-resize-full"></i>',

+ 1 - 1
themes/gly/theme.min.js

@@ -9,4 +9,4 @@
  *
  * Licensed under the BSD-3-Clause
  * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):i("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(i){"use strict";i.fn.fileinputThemes.gly={fileActionSettings:{removeIcon:'<i class="glyphicon glyphicon-trash"></i>',uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',uploadRetryIcon:'<i class="glyphicon glyphicon-repeat"></i>',downloadIcon:'<i class="glyphicon glyphicon-download"></i>',zoomIcon:'<i class="glyphicon glyphicon-zoom-in"></i>',dragIcon:'<i class="glyphicon glyphicon-move"></i>',indicatorNew:'<i class="glyphicon glyphicon-plus-sign text-warning"></i>',indicatorSuccess:'<i class="glyphicon glyphicon-ok-sign text-success"></i>',indicatorError:'<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',indicatorLoading:'<i class="glyphicon glyphicon-hourglass text-muted"></i>',indicatorPaused:'<i class="glyphicon glyphicon-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="glyphicon glyphicon-file kv-caption-icon"></i>'},previewZoomButtonIcons:{prev:'<i class="glyphicon glyphicon-menu-left"></i>',next:'<i class="glyphicon glyphicon-menu-right"></i>',toggleheader:'<i class="glyphicon glyphicon-resize-vertical"></i>',fullscreen:'<i class="glyphicon glyphicon-fullscreen"></i>',borderless:'<i class="glyphicon glyphicon-resize-full"></i>',close:'<i class="glyphicon glyphicon-remove"></i>'},previewFileIcon:'<i class="glyphicon glyphicon-file"></i>',browseIcon:'<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',removeIcon:'<i class="glyphicon glyphicon-trash"></i>',cancelIcon:'<i class="glyphicon glyphicon-ban-circle"></i>',pauseIcon:'<i class="glyphicon glyphicon-pause"></i>',uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',msgValidationErrorIcon:'<i class="glyphicon glyphicon-exclamation-sign"></i> '}});
+ */!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):i("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(i){"use strict";i.fn.fileinputThemes.gly={fileActionSettings:{removeIcon:'<i class="glyphicon glyphicon-trash"></i>',uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',uploadRetryIcon:'<i class="glyphicon glyphicon-cloud-upload"></i>',rotateIcon:'<i class="glyphicon glyphicon-repeat"></i>',downloadIcon:'<i class="glyphicon glyphicon-download"></i>',zoomIcon:'<i class="glyphicon glyphicon-zoom-in"></i>',dragIcon:'<i class="glyphicon glyphicon-move"></i>',indicatorNew:'<i class="glyphicon glyphicon-plus-sign text-warning"></i>',indicatorSuccess:'<i class="glyphicon glyphicon-ok-sign text-success"></i>',indicatorError:'<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',indicatorLoading:'<i class="glyphicon glyphicon-hourglass text-muted"></i>',indicatorPaused:'<i class="glyphicon glyphicon-pause text-info"></i>'},layoutTemplates:{fileIcon:'<i class="glyphicon glyphicon-file kv-caption-icon"></i>'},previewZoomButtonIcons:{prev:'<i class="glyphicon glyphicon-menu-left"></i>',next:'<i class="glyphicon glyphicon-menu-right"></i>',rotate:'<i class="glyphicon glyphicon-repeat"></i>',toggleheader:'<i class="glyphicon glyphicon-resize-vertical"></i>',fullscreen:'<i class="glyphicon glyphicon-fullscreen"></i>',borderless:'<i class="glyphicon glyphicon-resize-full"></i>',close:'<i class="glyphicon glyphicon-remove"></i>'},previewFileIcon:'<i class="glyphicon glyphicon-file"></i>',browseIcon:'<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',removeIcon:'<i class="glyphicon glyphicon-trash"></i>',cancelIcon:'<i class="glyphicon glyphicon-ban-circle"></i>',pauseIcon:'<i class="glyphicon glyphicon-pause"></i>',uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',msgValidationErrorIcon:'<i class="glyphicon glyphicon-exclamation-sign"></i> '}});

Някои файлове не бяха показани, защото твърде много файлове са промени