1
0
mirror of synced 2024-11-25 23:06:02 +03:00

Adds support for simple image previews on image uploads

This commit is contained in:
Justin Schroeder 2019-11-21 00:29:28 -05:00
parent 1095e33d4d
commit d868555be8
11 changed files with 289 additions and 52 deletions

71
dist/formulate.esm.js vendored
View File

@ -145,7 +145,9 @@ FileUpload.prototype.addFileList = function addFileList (fileList) {
name: file.name || 'file-upload', name: file.name || 'file-upload',
file: file, file: file,
uuid: uuid, uuid: uuid,
removeFile: removeFile.bind(this$1) path: false,
removeFile: removeFile.bind(this$1),
previewData: false
}); });
}; };
@ -249,6 +251,20 @@ FileUpload.prototype.removeFile = function removeFile (uuid) {
} }
}; };
/**
* load image previews for all uploads.
*/
FileUpload.prototype.loadPreviews = function loadPreviews () {
this.files.map(function (file) {
console.log(file.type);
if (!file.previewData && window && window.FileReader && /^image\//.test(file.file.type)) {
var reader = new FileReader();
reader.onload = function (e) { return Object.assign(file, { previewData: e.target.result }); };
reader.readAsDataURL(file.file);
}
});
};
/** /**
* Get the files. * Get the files.
*/ */
@ -939,7 +955,7 @@ var context = {
labelPosition: this.logicalLabelPosition, labelPosition: this.logicalLabelPosition,
attributes: this.elementAttributes, attributes: this.elementAttributes,
blurHandler: blurHandler.bind(this), blurHandler: blurHandler.bind(this),
showImage: this.showImage, imageBehavior: this.imageBehavior,
uploadUrl: this.uploadUrl, uploadUrl: this.uploadUrl,
uploader: this.uploader || this.$formulate.getUploader(), uploader: this.uploader || this.$formulate.getUploader(),
uploadBehavior: this.uploadBehavior, uploadBehavior: this.uploadBehavior,
@ -1233,9 +1249,9 @@ var script = {
type: Boolean, type: Boolean,
default: false default: false
}, },
showImage: { imageBehavior: {
type: Boolean, type: String,
default: true default: 'preview'
}, },
uploadUrl: { uploadUrl: {
type: [String, Boolean], type: [String, Boolean],
@ -1324,10 +1340,7 @@ var script = {
}) })
) )
.then(function (result) { return result.filter(function (result) { return result; }); }) .then(function (result) { return result.filter(function (result) { return result; }); })
.then(function (errorMessages) { .then(function (errorMessages) { this$1.validationErrors = errorMessages; });
console.log('setting validation errors');
this$1.validationErrors = errorMessages;
});
return this.pendingValidation return this.pendingValidation
}, },
hasValidationErrors: function hasValidationErrors () { hasValidationErrors: function hasValidationErrors () {
@ -2259,12 +2272,28 @@ var script$6 = {
files: { files: {
type: FileUpload, type: FileUpload,
required: true required: true
},
imagePreview: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
fileUploads: function fileUploads () { fileUploads: function fileUploads () {
return this.files.files || [] return this.files.files || []
} }
},
watch: {
files: function files () {
if (this.imagePreview) {
this.files.loadPreviews();
}
}
},
mounted: function mounted () {
if (this.imagePreview) {
this.files.loadPreviews();
}
} }
}; };
@ -2283,9 +2312,21 @@ var __vue_render__$6 = function() {
_vm._l(_vm.fileUploads, function(file) { _vm._l(_vm.fileUploads, function(file) {
return _c( return _c(
"li", "li",
{ key: file.uuid, attrs: { "data-has-error": !!file.error } }, {
key: file.uuid,
attrs: {
"data-has-error": !!file.error,
"data-has-preview": _vm.imagePreview && file.previewData
}
},
[ [
_c("div", { staticClass: "formulate-file" }, [ _c("div", { staticClass: "formulate-file" }, [
_vm.imagePreview && file.previewData
? _c("div", { staticClass: "formulate-file-image-preview" }, [
_c("img", { attrs: { src: file.previewData } })
])
: _vm._e(),
_vm._v(" "),
_c("div", { _c("div", {
staticClass: "formualte-file-name", staticClass: "formualte-file-name",
domProps: { textContent: _vm._s(file.name) } domProps: { textContent: _vm._s(file.name) }
@ -2417,7 +2458,6 @@ var script$7 = {
if (this.context.uploadBehavior === 'live' && if (this.context.uploadBehavior === 'live' &&
this.context.model instanceof FileUpload) { this.context.model instanceof FileUpload) {
this.context.hasValidationErrors().then(function (errors) { this.context.hasValidationErrors().then(function (errors) {
console.log('validation errors', errors);
if (!errors) { if (!errors) {
this$1.context.model.upload(); this$1.context.model.upload();
} }
@ -2490,7 +2530,14 @@ var __vue_render__$7 = function() {
}), }),
_vm._v(" "), _vm._v(" "),
_vm.hasFiles _vm.hasFiles
? _c("FormulateFiles", { attrs: { files: _vm.context.model } }) ? _c("FormulateFiles", {
attrs: {
files: _vm.context.model,
"image-preview":
_vm.context.type === "image" &&
_vm.context.imageBehavior === "preview"
}
})
: _vm._e() : _vm._e()
], ],
1 1

71
dist/formulate.min.js vendored
View File

@ -148,7 +148,9 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
name: file.name || 'file-upload', name: file.name || 'file-upload',
file: file, file: file,
uuid: uuid, uuid: uuid,
removeFile: removeFile.bind(this$1) path: false,
removeFile: removeFile.bind(this$1),
previewData: false
}); });
}; };
@ -252,6 +254,20 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
} }
}; };
/**
* load image previews for all uploads.
*/
FileUpload.prototype.loadPreviews = function loadPreviews () {
this.files.map(function (file) {
console.log(file.type);
if (!file.previewData && window && window.FileReader && /^image\//.test(file.file.type)) {
var reader = new FileReader();
reader.onload = function (e) { return Object.assign(file, { previewData: e.target.result }); };
reader.readAsDataURL(file.file);
}
});
};
/** /**
* Get the files. * Get the files.
*/ */
@ -942,7 +958,7 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
labelPosition: this.logicalLabelPosition, labelPosition: this.logicalLabelPosition,
attributes: this.elementAttributes, attributes: this.elementAttributes,
blurHandler: blurHandler.bind(this), blurHandler: blurHandler.bind(this),
showImage: this.showImage, imageBehavior: this.imageBehavior,
uploadUrl: this.uploadUrl, uploadUrl: this.uploadUrl,
uploader: this.uploader || this.$formulate.getUploader(), uploader: this.uploader || this.$formulate.getUploader(),
uploadBehavior: this.uploadBehavior, uploadBehavior: this.uploadBehavior,
@ -1236,9 +1252,9 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
type: Boolean, type: Boolean,
default: false default: false
}, },
showImage: { imageBehavior: {
type: Boolean, type: String,
default: true default: 'preview'
}, },
uploadUrl: { uploadUrl: {
type: [String, Boolean], type: [String, Boolean],
@ -1327,10 +1343,7 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
}) })
) )
.then(function (result) { return result.filter(function (result) { return result; }); }) .then(function (result) { return result.filter(function (result) { return result; }); })
.then(function (errorMessages) { .then(function (errorMessages) { this$1.validationErrors = errorMessages; });
console.log('setting validation errors');
this$1.validationErrors = errorMessages;
});
return this.pendingValidation return this.pendingValidation
}, },
hasValidationErrors: function hasValidationErrors () { hasValidationErrors: function hasValidationErrors () {
@ -2262,12 +2275,28 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
files: { files: {
type: FileUpload, type: FileUpload,
required: true required: true
},
imagePreview: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
fileUploads: function fileUploads () { fileUploads: function fileUploads () {
return this.files.files || [] return this.files.files || []
} }
},
watch: {
files: function files () {
if (this.imagePreview) {
this.files.loadPreviews();
}
}
},
mounted: function mounted () {
if (this.imagePreview) {
this.files.loadPreviews();
}
} }
}; };
@ -2286,9 +2315,21 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
_vm._l(_vm.fileUploads, function(file) { _vm._l(_vm.fileUploads, function(file) {
return _c( return _c(
"li", "li",
{ key: file.uuid, attrs: { "data-has-error": !!file.error } }, {
key: file.uuid,
attrs: {
"data-has-error": !!file.error,
"data-has-preview": _vm.imagePreview && file.previewData
}
},
[ [
_c("div", { staticClass: "formulate-file" }, [ _c("div", { staticClass: "formulate-file" }, [
_vm.imagePreview && file.previewData
? _c("div", { staticClass: "formulate-file-image-preview" }, [
_c("img", { attrs: { src: file.previewData } })
])
: _vm._e(),
_vm._v(" "),
_c("div", { _c("div", {
staticClass: "formualte-file-name", staticClass: "formualte-file-name",
domProps: { textContent: _vm._s(file.name) } domProps: { textContent: _vm._s(file.name) }
@ -2420,7 +2461,6 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
if (this.context.uploadBehavior === 'live' && if (this.context.uploadBehavior === 'live' &&
this.context.model instanceof FileUpload) { this.context.model instanceof FileUpload) {
this.context.hasValidationErrors().then(function (errors) { this.context.hasValidationErrors().then(function (errors) {
console.log('validation errors', errors);
if (!errors) { if (!errors) {
this$1.context.model.upload(); this$1.context.model.upload();
} }
@ -2493,7 +2533,14 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
}), }),
_vm._v(" "), _vm._v(" "),
_vm.hasFiles _vm.hasFiles
? _c("FormulateFiles", { attrs: { files: _vm.context.model } }) ? _c("FormulateFiles", {
attrs: {
files: _vm.context.model,
"image-preview":
_vm.context.type === "image" &&
_vm.context.imageBehavior === "preview"
}
})
: _vm._e() : _vm._e()
], ],
1 1

71
dist/formulate.umd.js vendored
View File

@ -151,7 +151,9 @@
name: file.name || 'file-upload', name: file.name || 'file-upload',
file: file, file: file,
uuid: uuid, uuid: uuid,
removeFile: removeFile.bind(this$1) path: false,
removeFile: removeFile.bind(this$1),
previewData: false
}); });
}; };
@ -255,6 +257,20 @@
} }
}; };
/**
* load image previews for all uploads.
*/
FileUpload.prototype.loadPreviews = function loadPreviews () {
this.files.map(function (file) {
console.log(file.type);
if (!file.previewData && window && window.FileReader && /^image\//.test(file.file.type)) {
var reader = new FileReader();
reader.onload = function (e) { return Object.assign(file, { previewData: e.target.result }); };
reader.readAsDataURL(file.file);
}
});
};
/** /**
* Get the files. * Get the files.
*/ */
@ -945,7 +961,7 @@
labelPosition: this.logicalLabelPosition, labelPosition: this.logicalLabelPosition,
attributes: this.elementAttributes, attributes: this.elementAttributes,
blurHandler: blurHandler.bind(this), blurHandler: blurHandler.bind(this),
showImage: this.showImage, imageBehavior: this.imageBehavior,
uploadUrl: this.uploadUrl, uploadUrl: this.uploadUrl,
uploader: this.uploader || this.$formulate.getUploader(), uploader: this.uploader || this.$formulate.getUploader(),
uploadBehavior: this.uploadBehavior, uploadBehavior: this.uploadBehavior,
@ -1239,9 +1255,9 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
showImage: { imageBehavior: {
type: Boolean, type: String,
default: true default: 'preview'
}, },
uploadUrl: { uploadUrl: {
type: [String, Boolean], type: [String, Boolean],
@ -1330,10 +1346,7 @@
}) })
) )
.then(function (result) { return result.filter(function (result) { return result; }); }) .then(function (result) { return result.filter(function (result) { return result; }); })
.then(function (errorMessages) { .then(function (errorMessages) { this$1.validationErrors = errorMessages; });
console.log('setting validation errors');
this$1.validationErrors = errorMessages;
});
return this.pendingValidation return this.pendingValidation
}, },
hasValidationErrors: function hasValidationErrors () { hasValidationErrors: function hasValidationErrors () {
@ -2265,12 +2278,28 @@
files: { files: {
type: FileUpload, type: FileUpload,
required: true required: true
},
imagePreview: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
fileUploads: function fileUploads () { fileUploads: function fileUploads () {
return this.files.files || [] return this.files.files || []
} }
},
watch: {
files: function files () {
if (this.imagePreview) {
this.files.loadPreviews();
}
}
},
mounted: function mounted () {
if (this.imagePreview) {
this.files.loadPreviews();
}
} }
}; };
@ -2289,9 +2318,21 @@
_vm._l(_vm.fileUploads, function(file) { _vm._l(_vm.fileUploads, function(file) {
return _c( return _c(
"li", "li",
{ key: file.uuid, attrs: { "data-has-error": !!file.error } }, {
key: file.uuid,
attrs: {
"data-has-error": !!file.error,
"data-has-preview": _vm.imagePreview && file.previewData
}
},
[ [
_c("div", { staticClass: "formulate-file" }, [ _c("div", { staticClass: "formulate-file" }, [
_vm.imagePreview && file.previewData
? _c("div", { staticClass: "formulate-file-image-preview" }, [
_c("img", { attrs: { src: file.previewData } })
])
: _vm._e(),
_vm._v(" "),
_c("div", { _c("div", {
staticClass: "formualte-file-name", staticClass: "formualte-file-name",
domProps: { textContent: _vm._s(file.name) } domProps: { textContent: _vm._s(file.name) }
@ -2423,7 +2464,6 @@
if (this.context.uploadBehavior === 'live' && if (this.context.uploadBehavior === 'live' &&
this.context.model instanceof FileUpload) { this.context.model instanceof FileUpload) {
this.context.hasValidationErrors().then(function (errors) { this.context.hasValidationErrors().then(function (errors) {
console.log('validation errors', errors);
if (!errors) { if (!errors) {
this$1.context.model.upload(); this$1.context.model.upload();
} }
@ -2496,7 +2536,14 @@
}), }),
_vm._v(" "), _vm._v(" "),
_vm.hasFiles _vm.hasFiles
? _c("FormulateFiles", { attrs: { files: _vm.context.model } }) ? _c("FormulateFiles", {
attrs: {
files: _vm.context.model,
"image-preview":
_vm.context.type === "image" &&
_vm.context.imageBehavior === "preview"
}
})
: _vm._e() : _vm._e()
], ],
1 1

21
dist/snow.css vendored
View File

@ -363,6 +363,8 @@
display: block; } display: block; }
.formulate-input[data-classification="file"] .formulate-files li[data-has-error] .formulate-file-progress { .formulate-input[data-classification="file"] .formulate-files li[data-has-error] .formulate-file-progress {
background-color: #dc2c2c; } background-color: #dc2c2c; }
.formulate-input[data-classification="file"] .formulate-files li[data-has-preview] .formualte-file-name:before {
display: none; }
.formulate-input[data-classification="file"] .formulate-files li + li { .formulate-input[data-classification="file"] .formulate-files li + li {
margin-top: .5em; } margin-top: .5em; }
.formulate-input[data-classification="file"] .formulate-files .formulate-file { .formulate-input[data-classification="file"] .formulate-files .formulate-file {
@ -382,7 +384,7 @@
display: block; display: block;
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: flex-start;
align-items: center; align-items: center;
position: relative; position: relative;
overflow: hidden; } overflow: hidden; }
@ -396,5 +398,22 @@
height: .5em; height: .5em;
border-radius: .5em; border-radius: .5em;
overflow: hidden; } overflow: hidden; }
.formulate-input[data-classification="file"] .formulate-files .formulate-file-image-preview {
width: 3em;
height: 3em;
position: relative;
z-index: 2;
left: -1px;
box-shadow: 0 0 0 1px #efefef; }
.formulate-input[data-classification="file"] .formulate-files .formulate-file-image-preview img {
display: block;
position: absolute;
width: 100%;
height: 100%;
left: 0;
right: 0;
bottom: 0;
top: 0;
object-fit: cover; }
.formulate-input[data-classification="file"] [data-type="image"] .formulate-input-upload-area .formulate-input-upload-area-mask::before { .formulate-input[data-classification="file"] [data-type="image"] .formulate-input-upload-area .formulate-input-upload-area-mask::before {
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 71.05"><path d="M82.89,0H7.1A7.12,7.12,0,0,0,0,7.11V64a7.11,7.11,0,0,0,7.1,7.1H82.9A7.11,7.11,0,0,0,90,64V7.11A7.12,7.12,0,0,0,82.89,0ZM69.28,39.35a5.44,5.44,0,0,0-8,0L50.58,50.74,32.38,30.88a5.31,5.31,0,0,0-7.92,0L4.74,52.4V7.11A2.37,2.37,0,0,1,7.11,4.74H82.9a2.37,2.37,0,0,1,2.36,2.37V56.3Z"/><circle cx="67.74" cy="22.26" r="8.53"/></svg>'); } mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 71.05"><path d="M82.89,0H7.1A7.12,7.12,0,0,0,0,7.11V64a7.11,7.11,0,0,0,7.1,7.1H82.9A7.11,7.11,0,0,0,90,64V7.11A7.12,7.12,0,0,0,82.89,0ZM69.28,39.35a5.44,5.44,0,0,0-8,0L50.58,50.74,32.38,30.88a5.31,5.31,0,0,0-7.92,0L4.74,52.4V7.11A2.37,2.37,0,0,1,7.11,4.74H82.9a2.37,2.37,0,0,1,2.36,2.37V56.3Z"/><circle cx="67.74" cy="22.26" r="8.53"/></svg>'); }

4
dist/snow.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,9 @@ class FileUpload {
name: file.name || 'file-upload', name: file.name || 'file-upload',
file, file,
uuid, uuid,
removeFile: removeFile.bind(this) path: false,
removeFile: removeFile.bind(this),
previewData: false
}) })
} }
} }
@ -134,6 +136,20 @@ class FileUpload {
} }
} }
/**
* load image previews for all uploads.
*/
loadPreviews () {
this.files.map(file => {
console.log(file.type)
if (!file.previewData && window && window.FileReader && /^image\//.test(file.file.type)) {
const reader = new FileReader()
reader.onload = e => Object.assign(file, { previewData: e.target.result })
reader.readAsDataURL(file.file)
}
})
}
/** /**
* Get the files. * Get the files.
*/ */

View File

@ -7,8 +7,17 @@
v-for="file in fileUploads" v-for="file in fileUploads"
:key="file.uuid" :key="file.uuid"
:data-has-error="!!file.error" :data-has-error="!!file.error"
:data-has-preview="imagePreview && file.previewData"
> >
<div class="formulate-file"> <div class="formulate-file">
<div
v-if="imagePreview && file.previewData"
class="formulate-file-image-preview"
>
<img
:src="file.previewData"
>
</div>
<div <div
class="formualte-file-name" class="formualte-file-name"
v-text="file.name" v-text="file.name"
@ -48,12 +57,28 @@ export default {
files: { files: {
type: FileUpload, type: FileUpload,
required: true required: true
},
imagePreview: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
fileUploads () { fileUploads () {
return this.files.files || [] return this.files.files || []
} }
},
watch: {
files () {
if (this.imagePreview) {
this.files.loadPreviews()
}
}
},
mounted () {
if (this.imagePreview) {
this.files.loadPreviews()
}
} }
} }
</script> </script>

View File

@ -137,9 +137,9 @@ export default {
type: Boolean, type: Boolean,
default: false default: false
}, },
showImage: { imageBehavior: {
type: Boolean, type: String,
default: true default: 'preview'
}, },
uploadUrl: { uploadUrl: {
type: [String, Boolean], type: [String, Boolean],
@ -225,10 +225,7 @@ export default {
}) })
) )
.then(result => result.filter(result => result)) .then(result => result.filter(result => result))
.then(errorMessages => { .then(errorMessages => { this.validationErrors = errorMessages })
console.log('setting validation errors')
this.validationErrors = errorMessages
})
return this.pendingValidation return this.pendingValidation
}, },
hasValidationErrors () { hasValidationErrors () {

View File

@ -25,6 +25,7 @@
<FormulateFiles <FormulateFiles
v-if="hasFiles" v-if="hasFiles"
:files="context.model" :files="context.model"
:image-preview="context.type === 'image' && context.imageBehavior === 'preview'"
/> />
</div> </div>
</div> </div>
@ -84,7 +85,6 @@ export default {
if (this.context.uploadBehavior === 'live' && if (this.context.uploadBehavior === 'live' &&
this.context.model instanceof FileUpload) { this.context.model instanceof FileUpload) {
this.context.hasValidationErrors().then(errors => { this.context.hasValidationErrors().then(errors => {
console.log('validation errors', errors)
if (!errors) { if (!errors) {
this.context.model.upload() this.context.model.upload()
} }

View File

@ -19,7 +19,7 @@ export default {
labelPosition: this.logicalLabelPosition, labelPosition: this.logicalLabelPosition,
attributes: this.elementAttributes, attributes: this.elementAttributes,
blurHandler: blurHandler.bind(this), blurHandler: blurHandler.bind(this),
showImage: this.showImage, imageBehavior: this.imageBehavior,
uploadUrl: this.uploadUrl, uploadUrl: this.uploadUrl,
uploader: this.uploader || this.$formulate.getUploader(), uploader: this.uploader || this.$formulate.getUploader(),
uploadBehavior: this.uploadBehavior, uploadBehavior: this.uploadBehavior,

View File

@ -405,7 +405,7 @@
width: .3em; width: .3em;
height: 100%; height: 100%;
right: 0; right: 0;
border-radius: 0; border-radius: 0 .23em .23em 0;
&::before { &::before {
@ -478,6 +478,14 @@
} }
} }
&[data-has-preview] {
.formualte-file-name {
&:before {
display: none;
}
}
}
& + li { & + li {
margin-top: .5em; margin-top: .5em;
} }
@ -488,10 +496,9 @@
display: block; display: block;
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: flex-start;
align-items: center; align-items: center;
position: relative; position: relative;
overflow: hidden;
@mixin progress { @mixin progress {
appearance: none; appearance: none;
@ -504,6 +511,38 @@
@include progress; @include progress;
} }
} }
.formulate-file-image-preview {
width: 3em;
height: 3em;
position: relative;
z-index: 2;
left: -1px;
box-shadow: 0 0 0 1px $formulate-gray;
transition: transform .25s, box-shadow .25s, background-color .25s;
@media (pointer: fine) {
&:hover {
transition-delay: .2s;
transform: scale(3);
background-color: $formulate-white;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, .1);
}
}
img {
display: block;
position: absolute;
width: 100%;
height: 100%;
left: 0;
right: 0;
bottom: 0;
top: 0;
object-fit: contain;
transition: all .25s;
}
}
} }