Animation framework using JS + Improvements in Quiz UX
This commit is contained in:
parent
452837cf55
commit
e973da1aa8
|
@ -32,7 +32,6 @@ input[type="radio"] {
|
||||||
height: 1.2em;
|
height: 1.2em;
|
||||||
margin-right: .4em;
|
margin-right: .4em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
}
|
}
|
||||||
fieldset {
|
fieldset {
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -138,6 +137,9 @@ main {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
.panel input.card-item {
|
||||||
|
padding: .5em !important;
|
||||||
|
}
|
||||||
|
|
||||||
.button span {
|
.button span {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@ -166,8 +168,8 @@ main {
|
||||||
}
|
}
|
||||||
#quizs .avatar.round.big,
|
#quizs .avatar.round.big,
|
||||||
#quiz .avatar.round.big {
|
#quiz .avatar.round.big {
|
||||||
width: 5em !important;
|
width: 5em;
|
||||||
height: 5em !important;
|
height: 5em;
|
||||||
}
|
}
|
||||||
#quizs .avatar img,
|
#quizs .avatar img,
|
||||||
#quiz .avatar img {
|
#quiz .avatar img {
|
||||||
|
@ -177,8 +179,8 @@ main {
|
||||||
}
|
}
|
||||||
#quizs .avatar.big img,
|
#quizs .avatar.big img,
|
||||||
#quiz .avatar.big img {
|
#quiz .avatar.big img {
|
||||||
width: 5em !important;
|
width: 5em;
|
||||||
height: 5em !important;
|
height: 5em;
|
||||||
}
|
}
|
||||||
#quizs .metadata .count {
|
#quizs .metadata .count {
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -208,11 +210,36 @@ main {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: right;
|
background-position: right;
|
||||||
}
|
}
|
||||||
|
#quiz .person.scrolled .not-visible-scroll,
|
||||||
|
#quiz .person:not(.scrolled) .visible-scroll {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#quiz .person.scrolled {
|
||||||
|
border-bottom: 5px solid #00000014;
|
||||||
|
}
|
||||||
|
#quiz .person.scrolled .avatar-container {
|
||||||
|
position: relative;
|
||||||
|
left: -1em;
|
||||||
|
}
|
||||||
|
#quiz .person.scrolled .avatar {
|
||||||
|
width: 3em !important;
|
||||||
|
height: 3em !important;
|
||||||
|
}
|
||||||
|
#quiz .person.scrolled .avatar img {
|
||||||
|
width: 3em !important;
|
||||||
|
height: 3em !important;
|
||||||
|
}
|
||||||
#quiz #questions {
|
#quiz #questions {
|
||||||
padding: 0 .8em;
|
padding: 0 .8em;
|
||||||
max-width: 32em;
|
max-width: 32em;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
#quiz #questions .type-options label {
|
||||||
|
padding: .5em 1em;
|
||||||
|
margin: .2em;
|
||||||
|
width: max-content;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
#quiz .quiz-content {
|
#quiz .quiz-content {
|
||||||
padding: 1.5em 1em;
|
padding: 1.5em 1em;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
|
@ -2,13 +2,6 @@ body {
|
||||||
font-family: system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,"mastodon-font-sans-serif",sans-serif;
|
font-family: system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,"mastodon-font-sans-serif",sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
|
||||||
border: 1px solid #00000026;
|
|
||||||
padding: .5em;
|
|
||||||
box-shadow: 0px 0px .5em #0000000f;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button, a[onclick],
|
.button, a[onclick],
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -20,6 +13,8 @@ input[type="text"] {
|
||||||
|
|
||||||
.flex { display: flex }
|
.flex { display: flex }
|
||||||
.flex > .center { margin: auto }
|
.flex > .center { margin: auto }
|
||||||
|
.flex > .center-v { margin: auto 0 }
|
||||||
|
.flex > .center-h { margin: 0 auto }
|
||||||
|
|
||||||
.width-max { width: 100% }
|
.width-max { width: 100% }
|
||||||
.height-max { height: 100% }
|
.height-max { height: 100% }
|
||||||
|
@ -63,9 +58,20 @@ input[type="text"] {
|
||||||
@media (max-width: 400px) { .media-max400 { display: none } }
|
@media (max-width: 400px) { .media-max400 { display: none } }
|
||||||
@media (max-width: 500px) { .media-max500 { display: none } }
|
@media (max-width: 500px) { .media-max500 { display: none } }
|
||||||
|
|
||||||
|
|
||||||
|
.slow { animation-duration: 2s !important }
|
||||||
|
.mid { animation-duration: 1s !important }
|
||||||
|
.slide-to-top {
|
||||||
|
position: relative !important;
|
||||||
|
animation: animate2top 0.1s;
|
||||||
|
}
|
||||||
|
.slide-from-top {
|
||||||
|
position: relative !important;
|
||||||
|
animation: animatetop 0.1s;
|
||||||
|
}
|
||||||
.slide-to-right {
|
.slide-to-right {
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
animation. animate2right 0.1s;
|
animation: animate2right 0.1s;
|
||||||
}
|
}
|
||||||
.slide-from-right {
|
.slide-from-right {
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
|
@ -79,6 +85,14 @@ input[type="text"] {
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
animation: animateleft 0.1s;
|
animation: animateleft 0.1s;
|
||||||
}
|
}
|
||||||
|
@keyframes animate2top {
|
||||||
|
from { top: 0; opacity: 1 }
|
||||||
|
to { top: -200px; opacity: .5 }
|
||||||
|
}
|
||||||
|
@keyframes animatetop {
|
||||||
|
from { top: -200px; opacity: .5 }
|
||||||
|
to { top: 0; opacity: 1 }
|
||||||
|
}
|
||||||
@keyframes animate2right {
|
@keyframes animate2right {
|
||||||
from { right: 0; opacity: 1 }
|
from { right: 0; opacity: 1 }
|
||||||
to { right: -200px; opacity: .5 }
|
to { right: -200px; opacity: .5 }
|
||||||
|
|
|
@ -447,6 +447,7 @@ app.toast = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function scriptPageHandler(modname, cfg) {
|
function scriptPageHandler(modname, cfg) {
|
||||||
|
cfg['module'] = modname
|
||||||
cfg['callback'] = function(args) {
|
cfg['callback'] = function(args) {
|
||||||
app.script(modname, function(ok) {
|
app.script(modname, function(ok) {
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
|
@ -505,10 +506,41 @@ window.onhashchange = function(e) {
|
||||||
for (var i = 0; i < app.hashHandlers.length; i++) {
|
for (var i = 0; i < app.hashHandlers.length; i++) {
|
||||||
const cfg = app.hashHandlers[i];
|
const cfg = app.hashHandlers[i];
|
||||||
if (cfg.exact !== undefined &&
|
if (cfg.exact !== undefined &&
|
||||||
cfg.exact === path)
|
cfg.exact === path) {
|
||||||
|
window._currentPage = cfg.module;
|
||||||
return cfg.callback(args);
|
return cfg.callback(args);
|
||||||
|
}
|
||||||
if (cfg.regex !== undefined &&
|
if (cfg.regex !== undefined &&
|
||||||
path.match(cfg.regex))
|
path.match(cfg.regex)) {
|
||||||
|
window._currentPage = cfg.module;
|
||||||
return cfg.callback(args);
|
return cfg.callback(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
window._currentPage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _currentPage = null;
|
||||||
|
function page() {
|
||||||
|
if (window._currentPage === null)
|
||||||
|
return null;
|
||||||
|
return eval(`app.${window._currentPage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scroll() { return Math.floor(window.scrollY) }
|
||||||
|
window.onscroll = function(e) {
|
||||||
|
if (page() === null || page().onScroll === undefined)
|
||||||
|
return;
|
||||||
|
if (scroll() % 10 !== 0)
|
||||||
|
return;
|
||||||
|
if (scroll() === 0)
|
||||||
|
setTimeout(async function() {
|
||||||
|
if (scroll() === 0) {
|
||||||
|
await page().onScroll(0, true);
|
||||||
|
window.scrollTo(0,0);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
else page().onScroll(scroll(), false);
|
||||||
|
}
|
||||||
|
// TODO: remove later, we suspect is not needed
|
||||||
|
//window.ontouchmove = window.onscroll;
|
||||||
|
//window.addEventListener('touchmove', window.onscroll);
|
||||||
|
|
|
@ -17,6 +17,14 @@ function dragElement(elmnt, options, onStopDrag) {
|
||||||
const isMobile = e.touches !== undefined;
|
const isMobile = e.touches !== undefined;
|
||||||
const cx = !isMobile ? e.clientX : e.touches[0].clientX * 1.3;
|
const cx = !isMobile ? e.clientX : e.touches[0].clientX * 1.3;
|
||||||
const cy = !isMobile ? e.clientY : e.touches[0].clientY * 1.3;
|
const cy = !isMobile ? e.clientY : e.touches[0].clientY * 1.3;
|
||||||
|
if (options.borderDetectPx !== undefined) {
|
||||||
|
const bleft = cx - elmnt.offsetLeft;
|
||||||
|
const bright = elmnt.offsetWidth - cx;
|
||||||
|
if (bright > options.borderDetectPx && options.right === false)
|
||||||
|
return;
|
||||||
|
if (bleft > options.borderDetectPx && options.left === false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
// get the mouse cursor position at startup:
|
// get the mouse cursor position at startup:
|
||||||
if (options.x === undefined || options.x === true)
|
if (options.x === undefined || options.x === true)
|
||||||
pos3 = cx;
|
pos3 = cx;
|
||||||
|
@ -88,9 +96,63 @@ function animateTimeout(elem, style, time) {
|
||||||
return;
|
return;
|
||||||
if (typeof elem === 'string')
|
if (typeof elem === 'string')
|
||||||
elem = document.querySelector(elem);
|
elem = document.querySelector(elem);
|
||||||
elem.classList.add(style);
|
if (style instanceof Array)
|
||||||
|
for (var i in style)
|
||||||
|
elem.classList.add(style[i]);
|
||||||
|
else elem.classList.add(style);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
elem.classList.remove(style) }, time);
|
if (style instanceof Array)
|
||||||
|
for (var i in style)
|
||||||
|
elem.classList.remove(style[i]);
|
||||||
|
else elem.classList.remove(style);
|
||||||
|
}, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function animateJS(elem, stages, removeAfter) {
|
||||||
|
if (typeof elem === 'string')
|
||||||
|
elem = document.querySelector(elem);
|
||||||
|
if (elem === undefined || elem === null)
|
||||||
|
return;
|
||||||
|
var countFin = 0;
|
||||||
|
for (var i = 0; i < stages.length; i++) {
|
||||||
|
const stage = stages[i];
|
||||||
|
const process = async function() {
|
||||||
|
if (stage.range !== undefined) {
|
||||||
|
const from = stage.range[0];
|
||||||
|
const to = stage.range[1];
|
||||||
|
var step = stage.step || 10;
|
||||||
|
step = Math.abs(step);
|
||||||
|
if (to < from)
|
||||||
|
step = step - (step * 2);
|
||||||
|
const diff = (to > from) ? to - from : from - to;
|
||||||
|
const times = Math.ceil(Math.abs(diff) / Math.abs(step));
|
||||||
|
const tpl = stage.value || '{}';
|
||||||
|
const slp = stage.sleep || 10;
|
||||||
|
for (var j = 1; j < times; j++) {
|
||||||
|
elem.style[stage.prop] = tpl
|
||||||
|
.replaceAll('{}', from + (j*step));
|
||||||
|
await sleep(slp);
|
||||||
|
}
|
||||||
|
elem.style[stage.prop] = tpl
|
||||||
|
.replaceAll('{}', to);
|
||||||
|
} else
|
||||||
|
elem.style[stage.prop] = stage.value;
|
||||||
|
countFin++;
|
||||||
|
};
|
||||||
|
if (stage.async) process();
|
||||||
|
else await process();
|
||||||
|
}
|
||||||
|
|
||||||
|
var rcp = true;
|
||||||
|
setTimeout(function() { rcp = false },10*1000);
|
||||||
|
while (rcp) {
|
||||||
|
if (countFin >= stages.length)
|
||||||
|
break;
|
||||||
|
await sleep(2);
|
||||||
|
}
|
||||||
|
if (removeAfter)
|
||||||
|
for (var i = 0; i < stages.length; i++)
|
||||||
|
elem.style.removeProperty(stages[i].prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fa(icon) { return `<i class="fa fa-${icon} fa-fw"></i>` }
|
function fa(icon) { return `<i class="fa fa-${icon} fa-fw"></i>` }
|
||||||
|
|
|
@ -19,11 +19,12 @@ app.pages.quiz = {
|
||||||
|
|
||||||
const onDataLoaded = async function(json) {
|
const onDataLoaded = async function(json) {
|
||||||
await app.template.loadMany(['quiz.index', 'quiz.item']);
|
await app.template.loadMany(['quiz.index', 'quiz.item']);
|
||||||
app.pages.quiz.data = json;
|
page().data = json;
|
||||||
app.pages.quiz.paint(json);
|
page().paint(json);
|
||||||
if (getNormalizedURI() === app.vars.app_dir &&
|
if (getNormalizedURI() === app.vars.app_dir &&
|
||||||
window.prevHash === '')
|
window.prevHash === '')
|
||||||
animateTimeout('#quiz', 'slide-from-right');
|
animateTimeout('#quiz', 'slide-from-right');
|
||||||
|
page().setDragEvent();
|
||||||
};
|
};
|
||||||
if (data === undefined)
|
if (data === undefined)
|
||||||
http.get(`/api/v1/me/quizs?id=${args[1]}`,
|
http.get(`/api/v1/me/quizs?id=${args[1]}`,
|
||||||
|
@ -31,7 +32,7 @@ app.pages.quiz = {
|
||||||
else onDataLoaded(data);
|
else onDataLoaded(data);
|
||||||
},
|
},
|
||||||
paint: function(json) {
|
paint: function(json) {
|
||||||
json = json || app.pages.quiz.data;
|
json = json || page().data;
|
||||||
if (json.from.props.age === undefined)
|
if (json.from.props.age === undefined)
|
||||||
json.from.props.age = '??';
|
json.from.props.age = '??';
|
||||||
if (json.from.props.gender === undefined)
|
if (json.from.props.gender === undefined)
|
||||||
|
@ -70,5 +71,74 @@ app.pages.quiz = {
|
||||||
document.querySelector(`#quiz #question-${i} .type-options`).remove();
|
document.querySelector(`#quiz #question-${i} .type-options`).remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
page().scrollInit();
|
||||||
|
},
|
||||||
|
setDragEvent: function() {
|
||||||
|
const element = document.querySelector('#quiz .content');
|
||||||
|
element.style.position = 'relative';
|
||||||
|
var options = {
|
||||||
|
y: false,
|
||||||
|
left: false,
|
||||||
|
rotate: true,
|
||||||
|
fadeOut: true,
|
||||||
|
return2start: true,
|
||||||
|
borderDetectPx: 30,
|
||||||
|
permitUserSelect: true,
|
||||||
|
};
|
||||||
|
dragElement(element, options, function(a1, a2) {
|
||||||
|
const ix = a1[0];
|
||||||
|
const fx = a2[0];
|
||||||
|
if (ix < fx && fx - ix > 200) {
|
||||||
|
animateTimeout(element, 'slide-to-right', 100);
|
||||||
|
window.history.back();
|
||||||
|
} else page().setDragEvent();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_scrollData: {},
|
||||||
|
scrollInit: function() {
|
||||||
|
const elem = document.querySelector('#quiz .person');
|
||||||
|
if (elem === null) return;
|
||||||
|
page()._scrollData.state1h = elem.offsetHeight;
|
||||||
|
elem.classList.add('scrolled');
|
||||||
|
page()._scrollData.state2h = elem.offsetHeight;
|
||||||
|
elem.classList.remove('scrolled');
|
||||||
|
},
|
||||||
|
onScroll: async function(scroll, isTop) {
|
||||||
|
// TODO: change to a isMobile function
|
||||||
|
if (document.body.offsetWidth < 610)
|
||||||
|
{
|
||||||
|
const elem = document.querySelector('#quiz .person');
|
||||||
|
if (elem === null) return;
|
||||||
|
|
||||||
|
const cfg = { sleep: 5, step: 5 }
|
||||||
|
if (!isTop) {
|
||||||
|
if (elem.classList.contains('scrolled'))
|
||||||
|
return;
|
||||||
|
const top1 = page()._scrollData.state1h - page()._scrollData.state2h;
|
||||||
|
await animateJS(elem, [
|
||||||
|
{ prop: 'position', value: 'fixed' },
|
||||||
|
{ prop: 'width', value: '100%' },
|
||||||
|
{ prop: 'top', range: [0,-top1], value: '{}px',
|
||||||
|
step: cfg.step, sleep: cfg.sleep },
|
||||||
|
], true);
|
||||||
|
elem.classList.add('scrolled');
|
||||||
|
} else {
|
||||||
|
if (!elem.classList.contains('scrolled'))
|
||||||
|
return;
|
||||||
|
const elemi = elem.querySelector('.visible-scroll');
|
||||||
|
const h1 = page()._scrollData.state2h - 5;
|
||||||
|
const h2 = page()._scrollData.state1h - 5;
|
||||||
|
elemi.style.height = '90%';
|
||||||
|
await animateJS(elem, [
|
||||||
|
{ prop: 'position', value: 'fixed' },
|
||||||
|
{ prop: 'width', value: '100%' },
|
||||||
|
{ prop: 'top', value: '0' },
|
||||||
|
{ prop: 'height', range: [h1,h2], value: '{}px',
|
||||||
|
step: cfg.step, sleep: cfg.sleep },
|
||||||
|
], true);
|
||||||
|
elemi.style.removeProperty('height');
|
||||||
|
elem.classList.remove('scrolled');
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,56 @@
|
||||||
<form id="quiz" style="padding: 0"
|
<form id="quiz" class="panel flex center item"
|
||||||
class="panel flex center item">
|
style="padding: 0; background: none; box-shadow: none">
|
||||||
<div class="content center">
|
<div class="content center">
|
||||||
<div class="person">
|
<div class="person">
|
||||||
<div class="lovebg flex">
|
<div class="lovebg flex not-visible-scroll">
|
||||||
<div class="width-max">
|
<div class="width-max">
|
||||||
<span class="bigname">{.from.name}</span>
|
<span class="bigname">{.from.name}</span>
|
||||||
<br>
|
<br>
|
||||||
<span class="acct" style="
|
<span class="acct" style="
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
">@{.from.acct}</span>
|
">@{.from.acct}</span>
|
||||||
<br><br>
|
<br><br>
|
||||||
<span>
|
|
||||||
<b>{.from.props.age}</b> {s:app.years_old},
|
<b>{.from.props.age}</b> {s:app.years_old},
|
||||||
<span style="opacity: .6">
|
<span style="opacity: .6">
|
||||||
<i class="fa fa-map-marker fa-fw">
|
<i class="fa fa-map-marker fa-fw">
|
||||||
</i> {.from.props.place}
|
</i> {.from.props.place}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="#profile/{.from._id}">
|
|
||||||
<div class="big avatar round">
|
|
||||||
<img class="round" src="{.from.avatar.url}"/>
|
|
||||||
</div>
|
</div>
|
||||||
</a>
|
<div class="avatar-container">
|
||||||
|
<a href="#profile/{.from._id}">
|
||||||
|
<div class="big avatar round">
|
||||||
|
<img class="round" src="{.from.avatar.url}"/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="lovebg flex visible-scroll"
|
||||||
|
style="padding: .5em 1em">
|
||||||
|
<div class="flex width-max">
|
||||||
|
<div class="flex width-max">
|
||||||
|
<span class="center-v bigname">{.from.name}</span>
|
||||||
|
</div>
|
||||||
|
<div class="avatar-container">
|
||||||
|
<div class="avatar round">
|
||||||
|
<img class="round" src="{.from.avatar.url}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="quiz-content">
|
<div class="quiz-content">
|
||||||
<h2 style="
|
<h2 style="
|
||||||
color: var(--clr_quiz);
|
color: var(--clr_quiz);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-right: .8em;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
">
|
">
|
||||||
<i class="fa fa-quote-right fa-fw">
|
<i class="fa fa-quote-right fa-fw">
|
||||||
</i>{s:app.fill_your_crush_quiz}
|
</i>{s:app.fill_your_crush_quiz}
|
||||||
</h2>
|
</h2>
|
||||||
<h3 class="text-center"
|
<h3 class="text-center" style="color: #0000005e"
|
||||||
>{.content.length} {s:app.questions}</h3>
|
>{.content.length} {s:app.questions}</h3>
|
||||||
<br><br>
|
<br>
|
||||||
<div id="questions"></div>
|
<div id="questions"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,21 +7,22 @@
|
||||||
</tr></tbody>
|
</tr></tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="type-freetext">
|
<div class="type-freetext">
|
||||||
<input class="width-max" type="text"
|
<input class="card-item width-max" type="text"
|
||||||
name="question_{.index}"/>
|
name="question_{.index}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-options">
|
<div class="type-options">
|
||||||
<fieldset class="flex">
|
<fieldset>
|
||||||
{loop:options}
|
{loop:options}
|
||||||
<label class="width-max">
|
<label class="card-item button rounder flex">
|
||||||
|
<div class="center">
|
||||||
<input type="radio" name="question_{.index}"
|
<input type="radio" name="question_{.index}"
|
||||||
value="{.item}">
|
value="{.item}">
|
||||||
<span>{.item_cap}</span>
|
<span>{.item_cap}</span>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
{/loop}
|
{/loop}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<br><br>
|
|
||||||
<hr style="max-width:100%">
|
|
||||||
<br>
|
<br>
|
||||||
|
<hr style="max-width:100%">
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue