Input validation #86
8 changed files with 66 additions and 36 deletions
|
@ -119,6 +119,11 @@ table {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-error {
|
||||||
|
font-weight: bold;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1250px) {
|
@media (max-width: 1250px) {
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
|
@ -17,7 +17,6 @@ function toggleSection(event){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a progress animation
|
|
||||||
function createProgressBar(element, size){
|
function createProgressBar(element, size){
|
||||||
var x = 1;
|
var x = 1;
|
||||||
var adder = 1;
|
var adder = 1;
|
||||||
|
@ -54,4 +53,27 @@ function dataURItoBlob(dataURI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Blob([ia], {type:mimeString});
|
return new Blob([ia], {type:mimeString});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showError(elementId, errorMsg) {
|
||||||
|
var errorDisplay = document.getElementById(elementId);
|
||||||
|
errorDisplay.hidden = false;
|
||||||
|
errorDisplay.innerText = errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new error objects, that prototypically inherit from the Error constructor
|
||||||
|
function FileError(message) {
|
||||||
|
this.name = 'FileError';
|
||||||
|
this.message = message || 'Default Message';
|
||||||
|
this.stack = (new Error()).stack;
|
||||||
|
}
|
||||||
|
FileError.prototype = Object.create(Error.prototype);
|
||||||
|
FileError.prototype.constructor = FileError;
|
||||||
|
|
||||||
|
function NameError(message) {
|
||||||
|
this.name = 'NameError';
|
||||||
|
this.message = message || 'Default Message';
|
||||||
|
this.stack = (new Error()).stack;
|
||||||
|
}
|
||||||
|
NameError.prototype = Object.create(Error.prototype);
|
||||||
|
NameError.prototype.constructor = NameError;
|
|
@ -11,7 +11,13 @@ function publishSelectedImage(event) {
|
||||||
try {
|
try {
|
||||||
validateSubmission(stagedFiles, name);
|
validateSubmission(stagedFiles, name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error.message);
|
if (error.name === 'FileError'){
|
||||||
|
showError('input-error-file-selection', error.message);
|
||||||
|
} else if (error.name === 'NameError') {
|
||||||
|
showError('input-error-claim-name', error.message);
|
||||||
|
} else {
|
||||||
|
showError('input-error-publish-submit', error.message);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// make sure the name is available then start the upload
|
// make sure the name is available then start the upload
|
||||||
|
@ -20,7 +26,7 @@ function publishSelectedImage(event) {
|
||||||
uploader.submitFiles(stagedFiles); //note: must pass the file as part of an array.
|
uploader.submitFiles(stagedFiles); //note: must pass the file as part of an array.
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
alert(error);
|
showError('input-error-claim-name', error);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,19 +47,4 @@ socket.on('publish-complete', function(msg){
|
||||||
publishResults += '<a href="/meme-fodder/play"><button>Reload</button></a></p>';
|
publishResults += '<a href="/meme-fodder/play"><button>Reload</button></a></p>';
|
||||||
// update publish area
|
// update publish area
|
||||||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||||
// update the link holder
|
|
||||||
document.getElementById('direct-link-holder').innerText = 'https://spee.ch' + directUrl;
|
|
||||||
// enable copy-to-clipboard
|
|
||||||
var copyBtn = document.querySelector('.copy-button');
|
|
||||||
copyBtn.addEventListener('click', function(event) {
|
|
||||||
// select the text
|
|
||||||
var text = document.getElementById('direct-link-holder');
|
|
||||||
text.select();
|
|
||||||
try {
|
|
||||||
var successful = document.execCommand('copy');
|
|
||||||
var msg = successful ? 'successful' : 'unsuccessful';
|
|
||||||
} catch (err) {
|
|
||||||
alert('Oops, unable to copy');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
|
@ -29,16 +29,16 @@ function validateFile(file) {
|
||||||
function validateSubmission(stagedFiles, name){
|
function validateSubmission(stagedFiles, name){
|
||||||
// make sure only 1 file was selected
|
// make sure only 1 file was selected
|
||||||
if (!stagedFiles) {
|
if (!stagedFiles) {
|
||||||
throw new Error("Please select a file");
|
throw new FileError("Please select a file");
|
||||||
} else if (stagedFiles.length > 1) {
|
} else if (stagedFiles.length > 1) {
|
||||||
throw new Error("Only one file is allowed at a time");
|
throw new FileError("Only one file is allowed at a time");
|
||||||
}
|
}
|
||||||
// validate 'name' field
|
// validate 'name' field
|
||||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||||
if (invalidCharacters) {
|
if (invalidCharacters) {
|
||||||
throw new Error(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, and "-" only.');
|
throw new NameError(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, and "-" only.');
|
||||||
} else if (name.length < 1) {
|
} else if (name.length < 1) {
|
||||||
throw new Error("You must enter a name for your claim");
|
throw new NameError("You must enter a name for your claim");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ function previewAndStageFile(selectedFile){
|
||||||
try {
|
try {
|
||||||
validateFile(selectedFile);
|
validateFile(selectedFile);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error.message);
|
showError('input-error-file-selection', error.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// set the preview
|
// set the preview
|
||||||
|
@ -145,10 +145,10 @@ function stageAndPublish(file) {
|
||||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||||
// validate 'name'
|
// validate 'name'
|
||||||
if (invalidCharacters) {
|
if (invalidCharacters) {
|
||||||
alert(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
showError('input-error-claim-name', invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
||||||
return;
|
return;
|
||||||
} else if (name.length < 1) {
|
} else if (name.length < 1) {
|
||||||
alert("You must enter a name for your claim");
|
showError('input-error-claim-name', 'You must enter a name for your claim');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// stage files
|
// stage files
|
||||||
|
@ -157,7 +157,7 @@ function stageAndPublish(file) {
|
||||||
if (stagedFiles) {
|
if (stagedFiles) {
|
||||||
// make sure only 1 file was selected
|
// make sure only 1 file was selected
|
||||||
if (stagedFiles.length < 1) {
|
if (stagedFiles.length < 1) {
|
||||||
alert("A file is needed");
|
showError('input-error-file-selection', 'A file is needed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// make sure the content type is acceptable
|
// make sure the content type is acceptable
|
||||||
|
@ -169,10 +169,10 @@ function stageAndPublish(file) {
|
||||||
uploader.submitFiles(stagedFiles);
|
uploader.submitFiles(stagedFiles);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
alert("Only .png, .jpeg, .gif, and .mp4 files are currently supported");
|
showError('input-error-publish-submit', 'Only .png, .jpeg, .gif, and .mp4 files are currently supported');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert("Please select a file");
|
showError('input-error-file-selection', 'Please select a file');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,8 +6,9 @@
|
||||||
<h2 class="subheader">Links</h2>
|
<h2 class="subheader">Links</h2>
|
||||||
{{!--direct link to asset--}}
|
{{!--direct link to asset--}}
|
||||||
<a href="/{{fileInfo.name}}/{{fileInfo.claimId}}">Direct Link</a>
|
<a href="/{{fileInfo.name}}/{{fileInfo.claimId}}">Direct Link</a>
|
||||||
|
<div class="input-error" id="input-error-copy-direct-link" hidden="true"></div>
|
||||||
<br/>
|
<br/>
|
||||||
<input type="text" id="direct-link" class="link" readonly="true" spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
|
<input type="text" id="direct-link" class="link" readonly spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" onclick="select()"/>
|
||||||
<button class="copy-button" data-elementtocopy="direct-link" onclick="copyToClipboard(event)">copy</button>
|
<button class="copy-button" data-elementtocopy="direct-link" onclick="copyToClipboard(event)">copy</button>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -15,27 +16,30 @@
|
||||||
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
|
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
|
||||||
{{else}}
|
{{else}}
|
||||||
Markdown
|
Markdown
|
||||||
|
<div class="input-error" id="input-error-copy-markdown-text" hidden="true"></div>
|
||||||
<br/>
|
<br/>
|
||||||
<input type="text" id="markdown-text" class="link" readonly="true" spellcheck="false" value='![{{fileInfo.name}}](https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}})'/>
|
<input type="text" id="markdown-text" class="link" readonly onclick="select()" spellcheck="false" value='![{{fileInfo.name}}](https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}})'/>
|
||||||
<button class="copy-button" data-elementtocopy="markdown-text" onclick="copyToClipboard(event)">copy</button>
|
<button class="copy-button" data-elementtocopy="markdown-text" onclick="copyToClipboard(event)">copy</button>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
{{/ifConditional}}
|
{{/ifConditional}}
|
||||||
{{!-- html text for embedding asset--}}
|
{{!-- html text for embedding asset--}}
|
||||||
Embed HTML
|
Embed HTML
|
||||||
|
<div class="input-error" id="input-error-copy-embed-text" hidden="true"></div>
|
||||||
<br/>
|
<br/>
|
||||||
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
|
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
|
||||||
<input type="text" id="embed-text" class="link" readonly="true" spellcheck="false" value='<video autoplay controls><source src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" /></video>'/>
|
<input type="text" id="embed-text" class="link" readonly onclick="select()" spellcheck="false" value='<video autoplay controls><source src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" /></video>'/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<input type="text" id="embed-text" class="link" readonly="true" spellcheck="false" value='<img src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />'/>
|
<input type="text" id="embed-text" class="link" readonly onclick="select()" spellcheck="false" value='<img src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />'/>
|
||||||
{{/ifConditional}}
|
{{/ifConditional}}
|
||||||
<button class="copy-button" data-elementtocopy="embed-text" onclick="copyToClipboard(event)">copy</button>
|
<button class="copy-button" data-elementtocopy="embed-text" onclick="copyToClipboard(event)">copy</button>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
{{!-- link to show route for asset--}}
|
{{!-- link to show route for asset--}}
|
||||||
<a href="/show/{{fileInfo.name}}/{{fileInfo.claimId}}">Details Link</a>
|
<a href="/show/{{fileInfo.name}}/{{fileInfo.claimId}}">Details Link</a>
|
||||||
|
<div class="input-error" id="input-error-copy-show-link" hidden="true"></div>
|
||||||
</br>
|
</br>
|
||||||
<input type="text" id="show-link" class="link" readonly="true" spellcheck="false" value="https://spee.ch/show/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
|
<input type="text" id="show-link" class="link" readonly onclick="select()" spellcheck="false" value="https://spee.ch/show/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
|
||||||
<button class="copy-button" data-elementtocopy="show-link" onclick="copyToClipboard(event)">copy</button>
|
<button class="copy-button" data-elementtocopy="show-link" onclick="copyToClipboard(event)">copy</button>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<div class="col-left">
|
<div class="col-left">
|
||||||
<div id="drop-zone" ondrop="drop_handler(event);" ondragover="dragover_handler(event);" ondragend="dragend_handler(event)">
|
<div id="drop-zone" ondrop="drop_handler(event);" ondragover="dragover_handler(event);" ondragend="dragend_handler(event)">
|
||||||
<p>Drag and drop your file here, or choose your file below.</p>
|
<p>Drag and drop your file here, or choose your file below.</p>
|
||||||
|
<div class="input-error" id="input-error-file-selection" hidden="true"></div>
|
||||||
<input type="file" id="siofu_input" name="file" accept="video/*,image/*" onchange="previewAndStageFile(event.target.files[0])" enctype="multipart/form-data"/>
|
<input type="file" id="siofu_input" name="file" accept="video/*,image/*" onchange="previewAndStageFile(event.target.files[0])" enctype="multipart/form-data"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="asset-preview-holder">
|
<div id="asset-preview-holder">
|
||||||
|
@ -12,7 +13,7 @@
|
||||||
<div class="col-right">
|
<div class="col-right">
|
||||||
<textarea id="direct-link-holder" hidden="true">No URL yet</textarea>
|
<textarea id="direct-link-holder" hidden="true">No URL yet</textarea>
|
||||||
<div id="publish-active-area">
|
<div id="publish-active-area">
|
||||||
|
<div class="input-error" id="input-error-claim-name" hidden="true"></div>
|
||||||
<input type="text" id="publish-name" placeholder="Your claim name" class="form-control">
|
<input type="text" id="publish-name" placeholder="Your claim name" class="form-control">
|
||||||
<p>
|
<p>
|
||||||
<label for="publish-license">License:</label>
|
<label for="publish-license">License:</label>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
<label for="publish-nsfw">NSFW</label>
|
<label for="publish-nsfw">NSFW</label>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
<div class="input-error" id="input-error-publish-submit" hidden="true"></div>
|
||||||
<button id="publish-submit" onclick="publishSelectedImage(event)">Publish</button>
|
<button id="publish-submit" onclick="publishSelectedImage(event)">Publish</button>
|
||||||
<a href="/"><button id="publish-reset">Reset</button></a>
|
<a href="/"><button id="publish-reset">Reset</button></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -10,14 +10,20 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type ="text/javascript">
|
<script type ="text/javascript">
|
||||||
|
|
||||||
|
function focusThisInput(event){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function copyToClipboard(event){
|
function copyToClipboard(event){
|
||||||
var elementToCopy = event.target.dataset.elementtocopy;
|
var elementToCopy = event.target.dataset.elementtocopy;
|
||||||
var element = document.getElementById(elementToCopy);
|
var element = document.getElementById(elementToCopy);
|
||||||
|
var errorElement = 'input-error-copy-text' + elementToCopy;
|
||||||
element.select();
|
element.select();
|
||||||
try {
|
try {
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert('Oops, unable to copy');
|
showError(errorElement, 'Oops, unable to copy');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
Loading…
Reference in a new issue