I have a problem when presenting the photo being displayed. The code below is a plain JS library (not JQuery), which is used to create modal windows. The HTML of the modal windows is created by this and it generates a "template". I am creating a modal window in which there is a system for uploading and viewing photos.
There is a function called " function m_postfoto () where that input code is stored and the area where the photo is displayed.
My problem is that it doesn't want to show the photo, it throws me an error in the console, but when I try to test that system on a page without using this modal window code, then it works.
/**
* Modal.js
* @author Joao Teixeira
* @version 1.0
* Copyright (c) Joao Teixeira
* https://github.com/jpntex
*
*/
var Modal = (function() {
function Modal(type, options) {
var defaults = {
title: '', // modal title
message: '', // modal message
autoOpen: true, // show modal when declared
closeOnEscape: true, // close when escape key pressed
closeOnBlur: true, // close when overlay is clicked
animated: true, // animate modal
// button options
buttonLbl: 'OK', // main button label
buttonClass: '', // main button class
cancelLbl: 'Cancel', // cancel button label
// callbacks
onConfirm: function() {}, // callback on confirm
onCancel: function() {}, // callback on cancel
onClose: function() {} // callback on close
};
this.type = type;
this.options = extend(defaults, options);
// animations not supported on IE9
if (navigator.appVersion.indexOf("MSIE 9") !== -1) {
this.options.animated = false;
}
this.init();
}
// modal templates
var templates = {
modal: '<div class="modal-box">' +
/* '<div class="modal-title">[[title]]<div class="close-modal" data-action="close">×</div></div>' +*/
'<div id="modal-message" class="styles">[[message]]</div>' +
'<div class="modal-buttons">[[buttons]]</div>' +
'</div>',
btn: '<div class="modal-btn" data-action="close">[[label]]</div>',
btnAlert: '<div class="modal-btn btn-alert" data-action="close">[[label]]</div>',
btnConfirm: '<div class="modal-btn btn-confirm [[classes]]" data-action="confirm">[[label]]</div>'
};
// generates the modal html from the templates given the modal's type and options
function buildModal(type, options) {
var modal = document.createElement('div');
modal.className = 'modal';
if (options.closeOnBlur) modal.setAttribute('data-action', 'close');
var modalTmplt = templates.modal;
// set modal animations
if (options.animated) {
modal.className += ' fadeIn';
}
modalTmplt = modalTmplt.replace('[[title]]', options.title);
modalTmplt = modalTmplt.replace('[[message]]', options.message);
// add buttons based on modal type
switch (type) {
case 'foto':
var buttons = templates.btn.replace('[[label]]', options.cancelLbl);
buttons += templates.btnConfirm.replace('[[label]]', options.buttonLbl).replace('[[classes]]', options.buttonClass);
modalTmplt = modalTmplt.replace('[[buttons]]', buttons);
break;
}
modal.innerHTML = modalTmplt;
return modal;
}
// handle modal events
Modal.prototype.handleEvent = function(event) {
var dataAction = event.target.getAttribute('data-action');
// animation ended callback
if (event.type === 'animationend') {
return this.onAnimationEnd(event);
}
// check if 'Esc' key was pressed and close modal if set
if (this.options.closeOnEscape) {
if (event.keyCode === 27) {
this.options.onCancel();
return this.close();
}
}
if (dataAction === 'close') {
this.options.onCancel();
return this.close();
}
if (dataAction === 'confirm') {
this.options.onConfirm();
return this.close();
}
};
// animation end event handler
Modal.prototype.onAnimationEnd = function(event) {
this.modal.removeEventListener('animationend', this);
document.body.removeChild(this.modal);
this.options.onClose();
return this;
};
// initialize modal creation
Modal.prototype.init = function() {
this.modal = buildModal(this.type, this.options);
if (this.options.autoOpen) this.open();
};
// open modal
Modal.prototype.open = function() {
// reset to fadeIn animation on open
if (this.options.animated) {
this.modal.className = 'modal fadeIn';
}
// append modal to the body
document.body.appendChild(this.modal);
// attach events listeners
this.modal.addEventListener('click', this);
document.onkeyup = this.handleEvent.bind(this);
return this;
};
// close modal
Modal.prototype.close = function() {
// clean events listeners
this.modal.removeEventListener('click', this);
document.onkeyup = null;
if (this.options.animated) {
this.modal.addEventListener('animationend', this);
this.modal.className = 'modal fadeOut';
} else {
document.body.removeChild(this.modal);
this.options.onClose();
}
return this;
};
// helper functions
function extend(obj1, obj2) {
for (var key in obj2)
if (obj2.hasOwnProperty(key))
obj1[key] = obj2[key];
return obj1;
}
function isFunction(fn) {
return typeof fn === 'function';
}
// modal interfaces
return {
confirm: function(options, onConfirm, onCancel, onClose) {
options = (typeof options === 'string') ? {
message: options
} : options;
if (isFunction(onClose)) options.onClose = onClose;
if (isFunction(onCancel)) options.onCancel = onCancel;
if (isFunction(onConfirm)) options.onConfirm = onConfirm;
return new Modal('confirm', options);
},
//PARA ALERTAS
alert: function(options, onClose) {
options = (typeof options === 'string') ? {
message: options
} : options;
if (isFunction(onClose)) options.onClose = onClose;
return new Modal('alert', options);
},
foto: function(options, onConfirm, onClose) {
options = (typeof options === 'string') ? {
message: options
} : options;
if (isFunction(onClose)) options.onClose = onClose;
if (isFunction(onConfirm)) options.onConfirm = onConfirm;
return new Modal('foto', options);
},
};
})();
/**************************************************************************************************************************************/
function m_postfoto() {
Modal.foto({
closeOnBlur: false,
message: '<div class="foto/container">' +
'<div id="drop-area">' +
'<form class="my-form">' +
'<p>Upload multiple files with the file dialog or by dragging and dropping images onto the dashed region</p>' +
'<input type="file" id="fileElem" multipleaccept="image/*" onchange="handleFiles(this.files)">' +
'<label class="button" for="fileElem">Select some files</label>' +
'</form>' +
'<progress id="progress-bar" max=100 value=0></progress>' +
'<div id="gallery" ></div>' +
'</div>' +
'</div>'
});
}
// ************************ Drag and drop ***************** //
let dropArea = document.getElementById("drop-area")
// Prevent default drag behaviors
;
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
document.body.addEventListener(eventName, preventDefaults, false)
})
// Highlight drop area when item is dragged over it
;
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false)
})
;
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false)
})
// Handle dropped files
dropArea.addEventListener('drop', handleDrop, false)
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
function highlight(e) {
dropArea.classList.add('highlight')
}
function unhighlight(e) {
dropArea.classList.remove('active')
}
function handleDrop(e) {
var dt = e.dataTransfer
var files = dt.files
handleFiles(files)
}
let uploadProgress = []
let progressBar = document.getElementById('progress-bar')
function initializeProgress(numFiles) {
progressBar.value = 0
uploadProgress = []
for (let i = numFiles; i > 0; i--) {
uploadProgress.push(0)
}
}
function updateProgress(fileNumber, percent) {
uploadProgress[fileNumber] = percent
let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
console.debug('update', fileNumber, percent, total)
progressBar.value = total
}
function handleFiles(files) {
files = [...files]
initializeProgress(files.length)
files.forEach(uploadFile)
files.forEach(previewFile)
}
function previewFile(file) {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = function() {
let img = document.createElement('img')
img.src = reader.result
document.getElementById('gallery').appendChild(img)
}
}
function uploadFile(file, i) {
var url = 'https://api.cloudinary.com/v1_1/joezimim007/image/upload'
var xhr = new XMLHttpRequest()
var formData = new FormData()
xhr.open('POST', url, true)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
// Update progress (can be used to show progress indicator)
xhr.upload.addEventListener("progress", function(e) {
updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
})
xhr.addEventListener('readystatechange', function(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
updateProgress(i, 100) // <- Add this
} else if (xhr.readyState == 4 && xhr.status != 200) {
// Error. Inform the user
}
})
formData.append('upload_preset', 'ujpu6gyk')
formData.append('file', file)
xhr.send(formData)
}
/**
* Modal.js
* @author Joao Teixeira
* @version 1.0
* Copyright (c) Joao Teixeira
* https://github.com/jpntex
*/
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(24, 26, 26, 0.7);
padding: 10px;
z-index: 99999;
-webkit-transform: translateZ(0);
transform: translateZ(0);
will-change: opacity;
}
.modal .modal-box {
margin: 50px auto;
color: #494c4c;
width: 400px;
max-width: 100%;
border: 1px solid #263545;
border-radius: 3px;
background-color: #fff;
box-shadow: 0 0 26px 4px rgba(0, 0, 0, 0.2);
}
.modal .modal-box .modal-title {
position: relative;
padding: 20px 55px 20px 30px;
border-bottom: 1px solid #e1e4e5;
background-color: #ffffff;
color: #181a1a;
text-overflow: ellipsis;
overflow: hidden;
}
.modal .modal-box .modal-title .close-modal {
padding: 8px;
position: absolute;
font-size: 18px;
line-height: 1;
top: 13px;
right: 22px;
font-weight: bold;
color: #aab2b2;
cursor: pointer;
}
.modal .modal-box .modal-title .close-modal:hover {
color: #828e8e;
}
.modal .modal-box .modal-message {
text-align: center;
padding: 45px 30px;
border-bottom: 1px solid #e1e4e5;
text-overflow: ellipsis;
overflow: hidden;
}
#modal-message {
background-color: #1a1c1c;
}
.modal .modal-box .modal-buttons {
font-size: 0.9em;
}
.modal .modal-box .modal-buttons:before,
.modal .modal-box .modal-buttons:after {
content: "";
display: table;
}
.modal .modal-box .modal-buttons:after {
clear: both;
}
.modal .modal-box .modal-buttons .modal-btn {
float: left;
width: 50%;
padding: 0 20px;
text-align: center;
cursor: pointer;
height: 60px;
line-height: 60px;
-webkit-transition: 0.2s ease-out;
transition: 0.2s ease-out;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.modal .modal-box .modal-buttons .modal-btn.btn-confirm {
font-weight: bold;
}
.modal .modal-box .modal-buttons .modal-btn.btn-alert {
width: 100%;
}
.modal .modal-box .modal-buttons .modal-btn+.modal-btn {
border-left: 1px solid #e1e4e5;
}
.modal .modal-box .modal-buttons .modal-btn:hover {
background-color: #e7ebed;
}
.modal .modal-box .modal-buttons .modal-btn.red {
color: #e34f4f;
}
.modal .modal-box .modal-buttons .modal-btn.red:hover {
color: #fff;
background-color: #e34f4f;
}
.modal .modal-box .modal-buttons .modal-btn.green {
color: #2faf45;
}
.modal .modal-box .modal-buttons .modal-btn.green:hover {
color: #fff;
background-color: #2faf45;
}
.modal.fadeIn {
-webkit-animation: fadeIn 0.3s ease;
animation: fadeIn 0.3s ease;
}
.modal.fadeOut {
-webkit-animation: fadeOut 0.2s forwards;
animation: fadeOut 0.2s forwards;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
body {
font-family: sans-serif;
}
a {
color: #369;
}
.note {
width: 500px;
margin: 50px auto;
font-size: 1.1em;
color: #333;
text-align: justify;
}
#drop-area {
border: 2px dashed #ccc;
border-radius: 20px;
width: 480px;
margin: 50px auto;
padding: 20px;
}
#drop-area.highlight {
border-color: purple;
}
p {
margin-top: 0;
}
.my-form {
margin-bottom: 10px;
}
#gallery {
margin-top: 10px;
}
#gallery img {
width: 150px;
margin-bottom: 10px;
margin-right: 10px;
vertical-align: middle;
}
.button {
display: inline-block;
padding: 10px;
background: #ccc;
cursor: pointer;
border-radius: 5px;
border: 1px solid #ccc;
}
.button:hover {
background: #ddd;
}
#fileElem {
display: none;
}
<div title="Publica una foto!" class="aligbtnposts">
<a href="#" id="uplapic" onclick="m_postfoto();" class="boton-otros">
<div>
<i style=" color: #337ab7;
" class="fa fa-picture-o" aria-hidden="true"></i>
</div>
<div>
<span class="sp_style">Foto</span>
</div>
</a>
</div>
El problema es que al cargar la página quieres obtener el elemento con id="drop-area", pero aún no existe, aparece hasta que muestras la ventana modal. Solo después de eso puedes acceder y crear los eventos necesarios.
Pasos a realizar:
Tengo la impresión de que modificaste el código de la librería "Modal" y eso es una muy mala idea, porque te verás en serios problemas para adaptar a actualizaciones o nuevas versiones.