INPUT BOX
Algo que se echa mucho de menos en la web es el tipico INPUT BOX para recoger datos del usuario al pulsar sobre un boton. Para ello JAVASCRIPT nos otorga la funcion prompt() pero dependiendo del navegador tiene un formato diferente y no podemos controlar nada sobre la ventana, posicion, tamaño, color, forma... bla, bla, bla. Pero como siempre, navegando por internet podemos encontrar solicioines en JAVASCRIPT muy buenas, y yo he recogido una de ellas y os la presento aqui, con mi pequeño toque particular.
El autor es Jorge MG, que a su vez era sitado en este blog de KsesoCSS, muy bien explicado, le he dado mi toque, y a la hora de llamar a la ventana tienes directamente dos opciones, como input box o como messagebox. De esta forma, "simplificamos" un poco que opcion quieres usar.
MessageBox
A la utilidad la he llamado con en Microsost Visual Basic 6, MessageBox, y como funciones show() e inputbox(), asi el que esta acostumbrado puede usarlo mas pacilmente. Para crear el objeto debemos de pasarle un objeto de con la siguiente informacion.
config = {
ID : 'Message', //id de la ventana
panel : 'panel', //clase css para el panel
title : 'title', //clase css para el titulo
close : 'close', //clase css para el boton cerrar (X) predeterminado
content : 'content', //clase css para el contenido
footer : 'footer', //clase css para el pie
zindex : '9999' //posicion de la ventana
};
Como se ve puedes personalizar el nombre de las clases a utilizar, de esta forma puedes personalizar facilmente todo el CSS que va a controlar las ventanas. Pero el unico parametro obligatorio seria el ID. El resto se han escrito los nombres por defecto del objeto. Luego se crea el objeto y se le pasa la configuracion, y aqui es importante tener en cuenta que hay que declararlo DESPUES de la etiqueta body.
< body>
< script type="text/javascript">
config = {
ID: 'Message-input', //id de la ventana
panel: 'panel', //clase css para el panel
title: 'title', //clase css para el titulo
close: 'close', //clase css para el boton cerrar (X) predeterminado
content: 'content', //clase css para el contenido
footer: 'footer', //clase css para el pie
zindex: '999' //posicion
};
var test = messageWindow(config);
< /script>
< /body>
Mostrar un mensaje
Para mostrar una simple ventana con un mensaje, llamaremos a la funcion show(data, boton1, boton2), en la que podremos poner un maximo de dos (2) botones. Le tenemos que enviar de 1 a 3 parametros. El primero definira el titulo de la ventana, el mensaje a mostrar y el tamaño de ancho y alto de la ventana. Los otros dos son los botones, los dos son opcionales, ya que siempre se muestra el boton de cerrar (X) en la esquina superior derecha.
data = { title: 'Ventana modal', width: 400, height: 40, content: 'Mensaje de la ventana' };
boton1 = ['Aceptar', function () { alert('Has pulsado aceptar.'); }];
boton2 = ['Cancelar', '' }];
test.show(data, boton1, boton2);
Como se puede observar en la definicion del boton podemos pasarle una funcion a ejecutar despues de presionar el boton correspondiente.
Mostrar un input box
Si lo que necesitamos es que el usuario entre algun tipo de informacion, llamaremos a la funcion inputbox(data, boton, placeholder), todos los parametros son obigatorios, si no generara errores. Los dos primeros son exactamente igual que para mostrar un mensaje, con la salvedad de que la funcion asignada al boton va a recibir como parametro lo que esta escrito en la caja de texto. El ultimo parametro es el texto que se va a mostrar en el cuadreo de texto como ayuda.
data = { title: 'Ventana modal', width: 400, height: 40 };
boton = ['Aceptar', function (input) { alert('Bienvenido, ' + input); }];
test.inputbox(data, boton, 'escribre tu nombre');
Consideraciones
El objeto data es un JSON, que podria dejarte en blanco, o nulo, la ventana se creara con los valores por defecto. Sus parametros son:
- title: Titulo de la ventana, si no se suministra utilizara el nombre pasado para crear la ventana.
- content: Contenido de la ventana. Se puede pasar todo lo que se quiera en formato HTML, incluidos los IFRAME, o imagenes.
- width: el ancho en pixels.
- height: el alto en vh.
Para crear los botones es un array de dos dimensiones. la primera define el texto a mostrar y el segundo la funcion a ejecutar.
Por ultimo hay que hacer referencia al archivo JAVASCRIPT que podeis descargar en este blog, o hacer referencia directamente a mi servidor seguro
< script src="https://community-mall.com/js/messagewindow.js">< /script>
Ejemplo de uso
< body>
< script src="https://community-mall.com/js/messagewindow.js">< /script>
< script type="text/javascript">
config = {
ID: 'Message-input'
};
var test = messageWindow(config);
function TomaDatos() {
data = { title: 'Dime tu nombre', width: 400, height: 40 };
boton = ['Aceptar', function (input) { alert('Bienvenido, ' + input); }];
test.inputbox(data, boton, 'escribre tu nombre');
}
< /script>
< a href="javascript:void(0)" onclick="TomaDatos();">Dime quien eres< /a>
< /body>
Todo el código para que lo disfruten
Como siempre si alguien tiene alguna idea para mejorar es libre de comentar. Si lo que quieren es criticar, tambien es bien venido.
/**
* MessageWindow.js v2.2.5
* https://aprende-a-programar.com/b/InputBox-y-Message-Box-con-JAVASCRIPT/
*
* Autor: Jorge MG
* Modificado por: Sergi Ortiz Gomez (drualcman@msn.com)
* Kenneth Dimabuyo (bjergken06@gmail.com)
* CSS: Kenneth Dimabuyo
* Source Blog: https://escss.blogspot.com/2016/09/ventana-modal-javascript-puro.html
* La licencia de uso del script es Creative Commons Reconocimiento-NoComercial-CompartirIgual
*/
/* Create Object */
(function (root, factory) {
if (typeof exports === 'object') {
/* CommonJS*/
factory(exports);
} else if (typeof define === 'function' && define.amd) {
/* AMD. Register as an anonymous module.*/
define(['exports'], factory);
} else {
/* Browser globals*/
factory(root);
}
}
/* Create a MessageWindow */
(this, function (exports) {
/**
* GLOBALS VARIABLES
*/
var VERSION = '2.2.5';
var CONFIG; /* configure CSS and others */
/* Create default Object */
function MessageWindow(config) { /*https://escss.blogspot.com/2016/09/ventana-modal-javascript-puro.html */
//get the configuration for the defaul window
if (config === undefined || config === '') {
CONFIG = _MessageConfig(); /* Default Config */
} else {
CONFIG = _mergeOptions(_MessageConfig(), config);
}
CrearVentana();
}
/**
* Crear la ventana
*/
function CrearVentana() {
if (document.getElementById(CONFIG.ID) === null) {
//crear la ventana ya que no existe
var d = document.createElement("div");
//d.className = CONFIG.ID; // la clase para estilizarla vía CSS se llamara igual que la ventana
d.id = CONFIG.ID;
var s = document.createElement("div");
s.style.display = 'none'; //no hacer visible el div
s.innerHTML = Css(); //style
d.appendChild(s); //agregar el style
// creamos el panel interior
var p = document.createElement("div");
p.className = CONFIG.panel;
// create editing icon
var iconWp = document.createElement('div');
iconWp.className = CONFIG.icon;
var i = document.createElement('i');
i.className = 'fa fa-pencil-alt';
iconWp.appendChild(i);
// creamos los componentes de la cabecera: título y botón de cerrar
var t = document.createElement("div");
t.className = CONFIG.title;
var cl = document.createElement("div");
cl.className = CONFIG.close;
cl.innerHTML = '×';
// cerramos y eliminamos la modal al pulsar el botón X
cl.addEventListener('click', function (ev) {
ev.preventDefault();
// cerramos y vaciamos la modal al cerrar la ventana
var dTop = this.parentNode.parentNode;
dTop.classList.remove("visible");
dTop.querySelector(".panel .content").innerHTML = '';
});
// creamos la caja donde se mostrará el contenido
var ct = document.createElement("div");
ct.className = CONFIG.content;
// también añadimos un pie, para añadir los posibles botones
var f = document.createElement("div");
f.className = CONFIG.footer;
/* finalmente, añadimos "t", "cl", "ct" y "f"
(título, botón cerrar, div contenido y div footer)
a "p" (panel interior), éste lo añadimos a "d"
(div principal, para oscurecer el fondo), y "d"
lo añadimos al body de la página */
p.appendChild(iconWp); //icon wp
p.appendChild(t); //title
p.appendChild(cl); //close
p.appendChild(ct); //content
p.appendChild(f); //footer
d.appendChild(p); //panel
document.body.appendChild(d); //MessageWindow
}
}
/* Default Config CSS */
function _MessageConfig() {
return {
ID : 'Message-', //id de la ventana
icon : 'icon-wp', //clase css para el icon wrapper
panel : 'panel', //clase css para el panel
title : 'title', //clase css para el titulo
close : 'close', //clase css para el boton cerrar (X) predeterminado
content : 'content', //clase css para el contenido
footer : 'footer', //clase css para el pie
zindex : '9999' //posicion de la ventana
};
}
/* Default CSS */
function Css() {
var css = "";
return css;
}
/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
*
* @param {object} obj1 origin
* @param {object} obj2 new object to merge
* @returns {object} obj3 a new object based on obj1 and obj2
*/
function _mergeOptions(obj1, obj2) {
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname1 in obj2) { obj3[attrname1] = obj2[attrname1]; }
return obj3;
}
/* Create the global object */
var messageWindow = function (_config) {
if (typeof (_config) === undefined) {
/* need params show help to use */
return new MessageWindow();
} else {
/* Run With all parameters sended */
return new MessageWindow(_config);
}
};
/**
* Mostrar una ventana con 2 botones maximo
* @param {JSON} data {title: 'Titulo', width: en px, height: en vh, content: 'Contenido'}
* @param {Array} ok Array ['Captoin', function ([varble]) { }]
* @param {string} input Texto para el placeholder del input box
*/
function InputBox(data, ok, input) {
CrearVentana();
data = data || {}; // si no existe data, creamos un objeto vacío para evitar posteriores errores
// guardamos cada componente en una variable
var mod = document.getElementById(CONFIG.ID),
p=mod.querySelector("." + CONFIG.panel),
t=mod.querySelector("." + CONFIG.panel + " ." + CONFIG.title),
ct=mod.querySelector("." + CONFIG.panel + " ." + CONFIG.content),
f = mod.querySelector("." + CONFIG.panel + " ." + CONFIG.footer);
mod.className = "visible";
if (f===null) {
// puede ocurrir que el footer no exista, así que lo volvemos a crear
mod.classList.remove("nofooter");
f=document.createElement("div");
f.className="footer";
p.appendChild(f);
}
// rellenamos los datos
t.innerHTML=data.title || CONFIG.ID;
ct.innerHTML=data.content || '';
f.innerHTML='';
// comprobamos que el número es válido antes de añadirlo
if (!isNaN(data.width)) p.style.maxWidth=data.width+'px';
if (!isNaN(data.height)) p.style.maxHeight=data.height+'vh';
// si es necesario, creamos el botón "Aceptar"
if (ok && ok.length>1) {
// la variable "param" se usará para devolver el valor del input
// si no hubiera input, el valor será null
var param={value:null};
// si es necesario, creamos un párrafo nuevo con su input
var ph=document.createElement("p");
ph.className = "action";
if (data.label && data.label.trim() !== '') {
var label = document.createElement('label');
label.innerHTML = data.label;
ph.appendChild(label);
}
var txt=document.createElement("input");
txt.className="action";
txt.setAttribute("placeholder",input);
txt.addEventListener('keydown',function(ev) {
// pulsar "enter" es equivalente a pulsar "aceptar"
if (ev.keyCode===13 || ev.key==="Enter") {
ev.preventDefault();
mod.classList.remove("visible");
ok[1](param.value);
}
});
// añadimos el input al párrafo, y éste al contenido
ph.appendChild(txt);
ct.appendChild(ph);
// guardamos la referencia al input
param=ct.querySelector("p.action > input.action");
/* ponemos el foco al input, pero esperamos
unos milisegundos para que se genere */
setTimeout(function(){
param.focus();
},100);
// creamos el botón OK
var bOk=document.createElement("button");
bOk.className="action";
bOk.innerHTML=ok[0];
bOk.addEventListener('click',function(ev){
/* al pulsar en él, se cierra la ventana
y se ejecuta la función indicada, devolviendo
el valor del input (si existe) o null */
ev.preventDefault();
mod.classList.remove("visible");
ok[1](param.value);
});
// añadimos el botón al footer
f.appendChild(bOk);
}
}
/**
* Mostrar una ventana con 2 botones maximo
* @param {JSON} data {title: 'Titulo', width: en px, height: en vh, content: 'Contenido'}
* @param {Array} ok Array ['Captoin', function ([varble]) { }]
* @param {Array} cancel Array ['Captoin', function ([varble]) { }]
*/
function MessageBox(data, ok, cancel) {
CrearVentana();
data = data || {}; // si no existe data, creamos un objeto vacío para evitar posteriores errores
// guardamos cada componente en una variable
var mod = document.getElementById(CONFIG.ID),
p=mod.querySelector("." + CONFIG.panel),
t=mod.querySelector("." + CONFIG.panel + " ." + CONFIG.title),
ct=mod.querySelector("." + CONFIG.panel + " ." + CONFIG.content),
f = mod.querySelector("." + CONFIG.panel + " ." + CONFIG.footer);
mod.className = "visible";
if (f===null) {
// puede ocurrir que el footer no exista, así que lo volvemos a crear
mod.classList.remove("nofooter");
f=document.createElement("div");
f.className="footer";
p.appendChild(f);
}
// rellenamos los datos
t.innerHTML=data.title || CONFIG.ID;
ct.innerHTML=data.content || '';
f.innerHTML='';
// comprobamos que el número es válido antes de añadirlo
if (!isNaN(data.width)) p.style.maxWidth=data.width+'px';
if (!isNaN(data.height)) p.style.maxHeight = data.height + 'vh';
var param = { value: null };
// si es necesario, creamos el botón "Aceptar"
if (ok && ok.length>1) {
// creamos el botón OK
var bOk=document.createElement("button");
bOk.className="action";
bOk.innerHTML=ok[0];
bOk.addEventListener('click',function(ev){
/* al pulsar en él, se cierra la ventana
y se ejecuta la función indicada, devolviendo
el valor del input (si existe) o null */
ev.preventDefault();
mod.classList.remove("visible");
ok[1](param.value);
});
// añadimos el botón al footer
f.appendChild(bOk);
}
// hacemos lo mismo con el botón Cancelar, si existe
if (cancel && cancel.length>1) {
var bCancel=document.createElement("button");
bCancel.className="action";
bCancel.innerHTML=cancel[0];
bCancel.addEventListener('click', function (ev) {
/* al pulsar en él, se cierra la ventana
y se ejecuta la función indicada, devolviendo
el valor del input (si existe) o null */
ev.preventDefault();
mod.classList.remove("visible");
cancel[1](param.value);
});
f.appendChild(bCancel);
}
// si no hay ningún botón, se elimina el footer
if (f.innerHTML==='') {
p.removeChild(f);
mod.classList.add("nofooter");
}
/* esperamos unos milisegundos para que se genere,
y añadimos la clase .visible para mostrarla desde CSS */
setTimeout(function(){
mod.classList.add("visible");
},50);
}
/**
* Eliminar la sesion
*/
function Eliminar() {
var mod = document.getElementById(CONFIG.ID);
mod.classList.remove("visible");
}
/**
* Current MessageWindow version
*
* @property version
* @type String
*/
messageWindow.version = VERSION;
/*Prototype*/
messageWindow.fn = MessageWindow.prototype = {
clone: function () {
return new MessageWindow(CONFIG);
},
inputbox: function (data, ok, input) {
InputBox.call(this, data, ok, input);
return this;
},
show: function (data, ok, cancel) {
MessageBox.call(this, data, ok, cancel);
return this;
},
remove: function () {
Eliminar();
return this;
},
version: function () {
return VERSION;
}
};
exports.messageWindow = messageWindow;
return messageWindow;
})
);
Happy coding
#javascript #HTML #ASP
Historial de cambios
05 Junio 2019: Se cambia el CSS por defecto. Autor David Flores. Corregidos los == por === en algunas lineas.
21 Julio 2020: Nueva imagen del input CSS completamente renovado. Autor
Kenneth Dimabuyo.