Input validation #86

Merged
bones7242 merged 3 commits from input-validation into master 2017-07-14 18:14:52 +02:00
8 changed files with 66 additions and 36 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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);
}) })
}; };

View file

@ -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');
}
});
}); });

View file

@ -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');
} }
} }

View 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='&lt;video autoplay controls>&lt;source src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />&lt;/video>'/> <input type="text" id="embed-text" class="link" readonly onclick="select()" spellcheck="false" value='&lt;video autoplay controls>&lt;source src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />&lt;/video>'/>
{{else}} {{else}}
<input type="text" id="embed-text" class="link" readonly="true" spellcheck="false" value='&lt;img src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />'/> <input type="text" id="embed-text" class="link" readonly onclick="select()" spellcheck="false" value='&lt;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/>

View file

@ -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>

View file

@ -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>