Commit d8870acc by Luciano Barletta

added fields' style

1 parent c6611cf4
function ArmarForm(m) {
document.getElementById("ArmarFormContainer").style.display="none";
document.getElementById("FormularioResultante").style.display="block";
for (let n = 0; n < m; n++) {
let padreBotones = document.getElementById("BotonesContainer");
let padreTabs = document.getElementById("TabsContainer");
let boton = document.createElement("Button");
padreBotones.appendChild(boton);
boton.setAttribute("id", "Boton" + n);
boton.setAttribute("value", n);
boton.setAttribute("class", "Botones");
boton.setAttribute("onclick", "HabilitarTab(\
document.getElementById('BotonesContainer'),\
document.getElementById('TabsContainer'),\
parseInt(this.id[this.id.length - 1])\
)");
let ancho = ((100 - (0.2 * m)) / m) + "%";
boton.style.width = ancho;
let tab = document.createElement("div");
tab.innerHTML = document.getElementById('TabCardcontainer').innerHTML;
padreTabs.appendChild(tab);
tab.style.width=ancho * m;
tab.setAttribute("id", "Tab" + n);
tab.setAttribute("class", "Tabs");
}
HabilitarTab(
document.getElementById('BotonesContainer'),
document.getElementById('TabsContainer'),
0
)
}
function HabilitarTab(bc,tc,n){
if (typeof n != "number") return console.log("El entero es invalido");
for (let it = 0; it < bc.children.length && it < tc.children.length; it++) {
if (it == n) {
bc.children[it].classList.add("BotonesActive");
tc.children[it].style.display = "block";
} else {
bc.children[it].classList.remove("BotonesActive");
tc.children[it].style.display = "none";
}
}
}
html {
font-family: 'Montserrat', sans-serif;
}
h1,
h3 {
text-align: center;
}
h1 {
font-size: 40px;
}
body {
background-color: whitesmoke;
}
.TabCards {
background-color: white;
box-shadow: 2px 2px 5px #575757;
margin: 2% auto;
padding: 2%;
border-radius: 2px;
}
.TabTitle,
.TabNumber {
color: grey;
margin-bottom: 5%;
font-size: 30px;
width: 84%;
text-align: left;
border: none;
border-bottom: 1px solid grey;
}
.TabNumber {
width: 10%;
}
.InputContainer {
width: 100%;
text-align: center;
}
.InputNumber {
width: 5%;
}
.Input,
.InputNumber {
color: grey;
border: none;
border-bottom: 1px solid grey;
width: 25%;
margin: 1%;
font-size: 15px;
}
.InputNumber {
width: 5%;
}
.NewTabButton,
.NewInputButton,
.RemoveInputButton,
.RemoveTabButton {
text-align: center;
margin: auto;
color: whitesmoke;
border-radius: 50%;
}
.NewTabButton {
font-size: 45px;
width: 70px;
height: 70px;
border: 3px solid rgb(0, 88, 170);
background-color: rgb(0, 102, 255);
}
.NewInputButton {
font-size: 25px;
width: 40px;
height: 40px;
margin: 1%;
border: 3px solid rgb(1, 194, 120);
background-color: rgb(14, 211, 135);
}
.RemoveInputButton,
.RemoveTabButton {
width: 35px;
height: 35px;
margin: 1%;
font-size: 20px;
border: 3px solid rgb(230, 25, 25);
background-color: rgba(211, 14, 14, 0.788);
}
.RemoveTabButton {
width: 40px;
height: 40px;
}
#ContinuarText,
#ContinuarButton {
display: none;
}
#ContinuarButton {
font-size: 20px;
border: none;
background-color: rgb(1, 194, 120);
color: rgb(255, 255, 255);
margin: 2%;
text-align: center;
width: 96%;
height: 2.5em;
border-radius: 5px;
}
@media (max-width: 1050px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 80%;
}
}
@media (max-width: 600px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 75%;
}
.RemoveInputButton {
width: 30px;
height: 30px;
}
.RemoveTabButton {
width: 30px;
height: 30px;
}
.Input {
width: 16%;
margin: none;
}
}
@media (max-width: 400px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 70%;
}
.RemoveInputButton {
width: 25px;
height: 25px;
font-size: 15px;
}
.RemoveTabButton {
width: 30px;
height: 30px;
}
.Input {
width: 15%;
margin: 0%;
}
}
\ No newline at end of file
<html lang="en">
<head>
<script src="./Scripts/construct.js"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="./Style/Templates.css">
<link rel="stylesheet" href="./Style/ArmadoDeForm.css">
<script src="./Scripts/ArmadoDeForm.js"></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
<title>Generador de Formularios</title>
<link rel="icon" href="./Assets/ICONO ANACSOFT 48 SIN TRASNSF.png" type="image/png">
</head>
<body>
<section id="ArmarFormContainer">
<h1> Generador de Formularios</h1>
<h3>Para comenzar por favor cree un nuevo tab</h3>
<br>
<div id="tabs"></div>
<div style="text-align: center;">
<button class="NewTabButton"
onclick="let t = document.getElementById('tabs'); addTab(t, maxChild(t, accessNumber) + 1)">
+
</button>
</div>
<p id="ErrorMessage" style="font-weight: bold; text-align: center; color: red;"></p>
<h3 id="ContinuarText">Cuando se encuentre conforme con el formulario presione Continuar</h3>
<button id="ContinuarButton" onclick="ArmarForm( generate(document.getElementById('tabs')) )"> Continuar
</button>
</section>
<section id="FormularioResultante" style="display: none;">
<h1 style="margin: 2% 0% 2% 0;"> Su Formulario Ya Esta Listo!</h1>
<section id="BotonesContainer" class="BotonesContainer">
</section>
<section id="TabsContainer">
</section>
<div class="BotonesContainer BotonResultCont">
<button class="BotonFormResultante"> Editar </button>
<button class="BotonFormResultante" style="background-color: var(--Color);"> Continuar </button>
</div>
</section>
</body>
<!-- templates -->
<template id="tabTemplate">
<div class="TabCards">
<input type="number" class="TabNumber"
onchange="sortChildren(getAncestorByAttribute(this,'name','Tab').parentElement, accessNumber)">
<input class="TabTitle" placeholder="Titulo del Tab" type="text">
<button class="RemoveTabButton" onclick="removeTab(this)">
X
</button>
<br>
<div style="text-align: center;">
<button class="NewInputButton" onclick="addField(this, maxChild(this.parentElement,accessNumber) + 1)">
+
</button>
</div>
</div>
</template>
<template id="fieldTemplate">
<div class="InputContainer">
<input type="number" class="InputNumber"
onchange="sortChildren(getAncestorByAttribute(this,'name','Field').parentElement, accessNumber)">
<input type="text" id="Titulo" class="Input" placeholder="Título">
<select name="input" class="Input">
<option disabled selected value="">Input</option>
<option id="text" value="text">Texto</option>
<option id="number" value="number">Numero</option>
<option id="mail" value="mail">Mail</option>
<option id="password" value="password">Contraseña</option>
<option id="date" value="date">Fecha</option>
<option id="time" value="time">Hora</option>
<option id="textarea" value="textarea">Párrafo</option>
<option id="checkbox" value="checkbox">Selección</option>
</select>
Obligatorio : <input type="checkbox">
<button class="RemoveInputButton"
onclick="let f = getAncestorByAttribute(this,'name','Field'); f.parentElement.removeChild(f)">
-
</button>
</div>
</template>
<template id="TabCardcontainer">
<div class="TabCard">
</div>
</template>
</html>
\ No newline at end of file
function ArmarForm(data) {
document.getElementById("ArmarFormContainer").style.display="none";
document.getElementById("FormularioResultante").style.display="block";
let m = data.length;
for (let n = 0; n < m; n++) {
let padreBotones = document.getElementById("BotonesContainer");
let padreTabs = document.getElementById("TabsContainer");
let boton = document.createElement("Button");
padreBotones.appendChild(boton);
boton.setAttribute("id", "Boton" + n);
boton.setAttribute("value", n);
boton.setAttribute("class", "Botones");
//boton.setAttribute("onclick", HabilitarTab(this) );
let ancho = ((100 - (0.2 * m)) / m) + "%";
boton.style.width = ancho;
let tab = document.createElement("div");
padreTabs.appendChild(tab);
tab.style.width=ancho * m;
tab.setAttribute("id", "Tab" + n);
tab.setAttribute("class", "Tabs");
}
document.getElementById("Tab0").style.display="block";
}
/**
* Lambdas
*/
var accessNumber = e => {
if (e.childElementCount == 0) return 0;
if (e.children[0].childElementCount == 0) return 0;
return e.children[0].children[0];
}
var getAncestorByAttribute = (elem,attr,val) => {
while (elem.getAttribute(attr) != val || elem == null) elem = elem.parentElement;
return elem;
}
var getDescendantByAttribute = (elem,attr,val) => {
if (elem == null || elem.getAttribute(attr) == val) return elem;
return Array.from(elem.children).reduce( (a,b) => {
let x = getDescendantByAttribute(a,attr,val);
let y = getDescendantByAttribute(b,attr,val);
return x == null ? y : x;
}, null);
}
/**
* Armado de formulario
*/
function removeTab(button){
let tabs = document.getElementById('tabs')
tabs.removeChild(
getAncestorByAttribute(button,'name','Tab')
)
if (tabs.childElementCount == 0){
document.getElementById("ContinuarText").style.display = 'none';
document.getElementById("ContinuarButton").style.display = 'none';
}
}
function addField(b,n){
let newfield = document.createElement("div");
newfield.setAttribute("name","Field");
newfield.innerHTML = document.getElementById("fieldTemplate").innerHTML;
accessNumber(newfield).setAttribute("value",n);
// swap
let container = b.parentElement;
container.appendChild(newfield);
container.appendChild(b);
}
function addTab(t,n){
document.getElementById("ContinuarText").style.display = 'block';
document.getElementById("ContinuarButton").style.display = 'block';
let newtab = document.createElement("div");
newtab.setAttribute("name","Tab");
newtab.innerHTML = document.getElementById("tabTemplate").innerHTML;
accessNumber(newtab).setAttribute("value",n);
t.appendChild(newtab);
}
/**
* Lectura de información y formateado
*/
function processField(field){
let data = field.children[0];
return {
'Title' : data.children[1].value,
'Input' : data.children[2].selectedOptions[0].value,
'Required' : data.children[3].checked,
};
}
function processTab(tab){
let dict = [];
let container = getDescendantByAttribute(tab,"name","Field");
if (container == null) return dict;
container = container.parentElement;
for(let i = 0; i < container.children.length; i++){
if (container.children[i].getAttribute("name") == "Field") {
dict.push(processField(container.children[i]));
}
}
return dict;
}
function generate(tabs){
let dict = [];
for (let i = 0; i < tabs.children.length; i++) {
let c = tabs.children[i];
if (c.getAttribute("name") == "Tab") {
dict.push({
"Title" : getDescendantByAttribute(c,"class","TabTitle").value,
"Fields" : processTab(c),
});
}
}
console.log(JSON.stringify(dict));
return dict;
}
function sortChildren(container,number){
let fixinput = a => number(a).nodeName == "INPUT" && number(a).type == "number" ? parseInt(number(a).value) : Infinity;
Array.from(container.children).sort(
(a,b) => fixinput(a) < fixinput(b) ? -1 : fixinput(a) > fixinput(b) ? 1 : 0
).forEach(
c => container.appendChild(c)
)
}
function maxChild(container,number){
let fixinput = a => number(a).nodeName == "INPUT" && number(a).type == "number" ? parseInt(number(a).value) : 0;
if (container.childElementCount == 0) return 0;
let max = Array.from(container.children).reduce(
(a,b) => fixinput(a) > fixinput(b) ? a : b
);
return fixinput(max);
}
function validate(obj){
const internal = "Hubo un error en la generación del formulario";
if (typeof obj != "object") return triggerError(internal,"not object");
for (let t_it = 0; t_it < obj.length; t_it++) {
let tab = obj[t_it];
if ("Title" in tab && "Fields" in tab){
if (typeof tab.Title != "string") return triggerError(internal,"wrong type in tab title");
if (typeof tab.Fields != "object") return triggerError(internal,"wrong type in tab fields");
if (tab.Title == "") return triggerError("La tab " + (t_it + 1) + " necesita un título","empty tab title");
if (tab.Fields.length == 0) return triggerError("La tab " + (t_it + 1) + " requiere campos","empty tab fields");
for (let f_it = 0; f_it < tab.Fields.length; f_it++) {
let field = tab.Fields[f_it];
if ("Title" in field && "Input" in field && "Required" in field) {
if (typeof field.Title != "string") return triggerError(internal,"wrong type in field title");
if (typeof field.Input != "string") return triggerError(internal,"wrong type in field input");
if (typeof field.Required != "boolean") return triggerError(internal,"wrong type in field required");
if (field.Title == "") return triggerError("El campo " + (f_it + 1) + " del tab " + (t_it + 1) + " necesita un título","empty field title");
if (field.Input == "") return triggerError("El campo " + (f_it + 1) + " del tab " + (t_it + 1) + " necesita un input","empty field input");
} else { return triggerError(internal,"field lacks property") }
}
} else { return triggerError(internal,"tab lacks property") }
}
}
function triggerError(type,log){
let out = "triggerError => \nerror_message = " + type;
if (log) out += "\nlog_message = " + log;
console.log(out);
document.getElementById("ErrorMessage").innerText = type;
}
\ No newline at end of file
html {
--Color: rgb(1, 194, 120);
}
#FormularioResultante {
width: 98%;
margin: auto;
height: 100%;
}
.BotonesContainer {
width: 100%;
height: 5%;
text-align: center;
}
.BotonFormResultante {
font-size: 30px;
border: none;
color: white;
height: 90%;
width: 48%;
margin: 0.5%;
margin-top: 2%;
border-radius: 5px;
text-align: center;
background-color: rgb(151, 151, 151);
}
#TabsContainer {
width: 100%;
height: 82%;
}
.Botones {
border-radius: 5px 5px 0px 0px;
background-color: rgb(168, 168, 168);
border: none;
height: 100%;
margin: 0.1%;
}
.BotonesActive {
background-color: var(--Color);
border-bottom: none;
height: 6%;
border-bottom: none;
}
.Botones:hover {
background-color: rgb(53, 53, 53), 0.5;
}
.Tabs {
display: none;
height: 100%;
border: 3px solid var(--Color);
}
@media (max-width: 600px) {
.BotonResultCont {
margin: 1% auto;
height: 10%;
vertical-align: baseline;
align-content: center;
}
}
/*
@media (min-width: 1300px) {*/
\ No newline at end of file
html {
font-family: 'Montserrat', sans-serif;
}
h1,
h3 {
text-align: center;
}
h1 {
font-size: 40px;
}
body {
background-color: whitesmoke;
}
.TabCards {
background-color: white;
box-shadow: 2px 2px 5px #575757;
margin: 2% auto;
padding: 2%;
border-radius: 2px;
}
.TabTitle,
.TabNumber {
color: grey;
margin-bottom: 5%;
font-size: 30px;
width: 84%;
text-align: left;
border: none;
border-bottom: 1px solid grey;
}
.TabNumber {
width: 10%;
}
.InputContainer {
width: 100%;
text-align: center;
}
.InputNumber {
width: 5%;
}
.Input,
.InputNumber {
color: grey;
border: none;
border-bottom: 1px solid grey;
width: 25%;
margin: 1%;
font-size: 15px;
}
.InputNumber {
width: 5%;
}
.NewTabButton,
.NewInputButton,
.RemoveInputButton,
.RemoveTabButton {
text-align: center;
margin: auto;
color: whitesmoke;
border-radius: 50%;
}
.NewTabButton {
font-size: 45px;
width: 70px;
height: 70px;
border: 3px solid rgb(0, 88, 170);
background-color: rgb(0, 102, 255);
}
.NewInputButton {
font-size: 25px;
width: 40px;
height: 40px;
margin: 1%;
border: 3px solid rgb(1, 194, 120);
background-color: rgb(14, 211, 135);
}
.RemoveInputButton,
.RemoveTabButton {
width: 35px;
height: 35px;
margin: 1%;
font-size: 20px;
border: 3px solid rgb(230, 25, 25);
background-color: rgba(211, 14, 14, 0.788);
}
.RemoveTabButton {
width: 40px;
height: 40px;
}
#ContinuarText,
#ContinuarButton {
display: none;
}
#ContinuarButton {
font-size: 20px;
border: none;
background-color: rgb(1, 194, 120);
color: rgb(255, 255, 255);
margin: 2%;
text-align: center;
width: 96%;
height: 2.5em;
border-radius: 5px;
}
@media (max-width: 1050px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 80%;
}
}
@media (max-width: 600px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 75%;
}
.RemoveInputButton {
width: 30px;
height: 30px;
}
.RemoveTabButton {
width: 30px;
height: 30px;
}
.Input {
width: 16%;
margin: none;
}
}
@media (max-width: 400px) {
.TabNumber {
width: 10%;
}
.TabTitle {
width: 70%;
}
.RemoveInputButton {
width: 25px;
height: 25px;
font-size: 15px;
}
.RemoveTabButton {
width: 30px;
height: 30px;
}
.Input {
width: 15%;
margin: 0%;
}
}
\ No newline at end of file
{% macro tab(title,fields) %}
{{ title }}
<br>
{% from "field.html" import field %}
{% for f in fields %}
{{ field(title=f['title'], type=f['type'], placeholder=f['placeholder'], options=f['options'], required=f['required']) }}
<br>
{% endfor %}
<input type="button", value="Back">
<input type="button", value="Next">
{% endmacro %}
\ No newline at end of file
......@@ -61,12 +61,22 @@ def main():
"title" : "first",
"fields" : [
{
"title" : "first",
"type" : "number",
"title" : "1",
"type" : "mail",
"placeholder" : "example@example.com",
},
{
"title" : "2",
"type" : "file",
"placeholder" : "999",
},
{
"title" : "second",
"title" : "3",
"type" : "checkbox",
"placeholder" : "999",
},
{
"title" : "4",
"type" : "text",
"required" : True
}
......@@ -78,17 +88,32 @@ def main():
{
"title" : "first",
"type" : "select",
"placeholder" : "999",
"placeholder" : "nedea",
"options" : [
"first",
"second",
"third"
]
},
{
"title" : "second",
"type" : "number",
"placeholder" : "999",
"options" : [
"first",
"second",
"third"
],
"required" : True
}
]
},
{
"title" : "third",
"fields" : []
}
]
return render_template("form.html",tabs=data)
return render_template("form.html",tabs=data,title="Formulario de Prueba")
if __name__ == "__main__":
app.run("0.0.0.0")
\ No newline at end of file
function HabilitarTab(bc,tc,n){
if (typeof n != "number") return console.log("El entero es invalido");
for (let it = 0; it < bc.children.length && it < tc.children.length; it++) {
if (it == n) {
bc.children[it].classList.add("BotonesActive");
tc.children[it].style.display = "block";
} else {
bc.children[it].classList.remove("BotonesActive");
tc.children[it].style.display = "none";
}
}
}
\ No newline at end of file
html {
--Color: rgb(1, 194, 120);
font-family: 'Montserrat', sans-serif;
}
h1,
h3 {
text-align: center;
}
h1 {
font-size: 40px;
}
body {
background-color: whitesmoke;
}
#FormularioResultante {
......@@ -30,7 +43,7 @@ html {
#TabsContainer {
width: 100%;
height: 82%;
height: auto;
}
.Botones {
......@@ -53,20 +66,92 @@ html {
.Tabs {
display: none;
height: 100%;
height: auto;
background-color: var(--Color);
overflow: scroll;
}
.TabCard{
height: 90%;
.TabCard {
height: auto;
width: 90%;
background-color: white;
box-shadow: 2px 2px 5px #575757;
padding: 2%;
padding: 1%;
border-radius: 2px;
margin: auto;
margin-top: 2%;
margin-bottom: 2%;
min-height: 70%;
text-align: center;
}
.TabTitle {
text-align: center;
font-size: 5vw;
font-weight: bolder;
padding: inherit;
margin-bottom: 20px;
border-bottom: 5px solid rgb(114, 126, 119);
}
.FieldsContainer {
margin: auto;
display: flex;
justify-content: space-around;
width: 100%;
}
.FieldTitles{
width: 20%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
text-align: center;
margin: auto;
}
.FieldTitles div {
font-size: 2vw;
font-weight: bold;
text-align: center;
margin-top: 5vh;
margin-bottom: 5vh;
}
.FieldInputs {
width: 70%;
text-align: center;
font-weight: bold;
display: flex;
flex-direction: column;
justify-content: space-evenly;
margin: auto;
}
.FieldInputs input,
.FieldInputs select {
font-size: 2vw;
margin-top: 5vh;
margin-bottom: 5vh;
}
.FieldInputs select {
text-overflow: ellipsis;
}
.FieldInputs input[type='checkbox'] {
-webkit-appearance: none;
width: 2vw;
height: 2vw;
background: white;
border-radius: 5px;
border: 2px solid #555;
margin-top: 5vh;
margin-bottom: 5vh;
}
.FieldInputs input[type='checkbox']:checked {
background: rgb(91, 145, 255);
}
@media (max-width: 600px) {
.BotonResultCont {
......
{% macro field(title,type,placeholder="",options=[],required=False) %}
{{ title }}
{% if type == "select" %}
<select {% if required %} required {% endif %}>
<option selected disabled hidden value="">{{ placeholder }}</option>
......
......@@ -11,19 +11,30 @@
<title>Generador de Formularios</title>
<link rel="icon" href="{{url_for('static',filename='Assets/ICONO ANACSOFT 48 SIN TRASNSF.png')}}" type="image/png">
</head>
<body>
<h1 style="margin: 2% 0% 2% 0;"> Su Formulario Ya Esta Listo!</h1>
<body onload="HabilitarTab(
document.getElementById('BotonesContainer'),
document.getElementById('TabsContainer'),
0
)">
<h1 style="margin: 2% 0% 2% 0; font-size: 5vw;"> {{ title|title }}</h1>
<section id="BotonesContainer" class="BotonesContainer">
{% for i in range(2) %}
<input id="Boton{{i}}" type="button" class="Botones" style="width: {{ (100 - (0.2 * 2)) / 2 }}%;">
{% set m = tabs|length %}
{% for i in range(m) %}
<button id="Boton{{i}}" class="Botones" style="width: {{ (100 - (0.2 * m)) / m }}%;"
onclick="HabilitarTab(
document.getElementById('BotonesContainer'),
document.getElementById('TabsContainer'),
parseInt(this.id[this.id.length - 1])
)">
{% endfor %}
</section>
<section id="TabsContainer">
{% from "tab.html" import tab %}
{% for i in range(2) %}
{% for i in range(m) %}
<div id="Tab{{i}}" class="Tabs">
{{ tab(title=tabs[i]['title'], fields=tabs[i]['fields']) }}
<div class="TabCard">
{{ tab(title=tabs[i]['title']|title, fields=tabs[i]['fields']) }}
</div>
</div>
{% endfor %}
</section>
......
{% macro tab(title,fields) %}
<div class="TabTitle">
{{ title|title }}
</div>
{% from "field.html" import field %}
<div class="FieldsContainer">
<div class="FieldTitles">
{% for f in fields %}
<div>{{ f['title']|title }}</div>
{% endfor %}
</div>
<div class="FieldInputs">
{% for f in fields %}
{{ field(type=f['type'], placeholder=f['placeholder'], options=f['options'], required=f['required']) }}
{% endfor %}
</div>
</div>
<input type="button", value="Back">
<input type="button", value="Next">
{% endmacro %}
\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!