Add option to toggle between editor & preview
This commit is contained in:
parent
724d633905
commit
455a039efb
5 changed files with 200 additions and 20 deletions
|
@ -41,7 +41,9 @@ placeholders Silences some warrnings, e.g. warrnings about missing ur
|
||||||
This param is useful when your bot allows having placeholders in place of a URL eg. `{ server.url }`
|
This param is useful when your bot allows having placeholders in place of a URL eg. `{ server.url }`
|
||||||
placeholders=errors This also disables automatic insertion of 'http' for urls without a protocol.
|
placeholders=errors This also disables automatic insertion of 'http' for urls without a protocol.
|
||||||
Except, warnings won't be silenced. The user will still see a warning that a url or timestamp (etc.) is incorrect for 5 seconds.
|
Except, warnings won't be silenced. The user will still see a warning that a url or timestamp (etc.) is incorrect for 5 seconds.
|
||||||
|
hideditor Hides the editor.
|
||||||
|
hidepreview Hides the preview.
|
||||||
|
hidemenu Hides the three dotted menu.
|
||||||
```
|
```
|
||||||
<small>Case matters, all parameters should be lowercase.</small>
|
<small>Case matters, all parameters should be lowercase.</small>
|
||||||
### Example URL with all* the above parameters:
|
### Example URL with all* the above parameters:
|
||||||
|
@ -53,7 +55,7 @@ This will only work through iframe or a cloned repo of the builder: Have a JavaS
|
||||||
>## Intergretting into your website
|
>## Intergretting into your website
|
||||||
>You are free to use this in your website. Intergretting into your websites allows sending the embed to Discord with a few changes, and using 'formatters' eg. '{ server.name }' or '{ user.name }' etc. A (not so bad) downside would be that you'd probably have to keep up with fixes and updates.
|
>You are free to use this in your website. Intergretting into your websites allows sending the embed to Discord with a few changes, and using 'formatters' eg. '{ server.name }' or '{ user.name }' etc. A (not so bad) downside would be that you'd probably have to keep up with fixes and updates.
|
||||||
<br>
|
<br>
|
||||||
To over come that, and if all you want is to have an embed builder in your website with no additional features and maybe using your own bot name and avatar, etc., then you might iframe https://glitchii.github.io/embedbuilder into your website with a few of the parameters above if needed instead. The downside to this is that due to security reasons, browsers won't allow features like updating URL parameter to work through iframes, whoever URL options will still be read from the top holder of the iframe, those are probably the only features that won't work and thus are removed from the GUI menu when embeded in iframe.
|
To over come that, and if all you want is to have an embed builder in your website with no additional features and maybe using your own bot name and avatar, etc., then you might iframe https://glitchii.github.io/embedbuilder into your website with a few of the parameters above if needed instead. The downside to this is that due to security reasons, browsers won't allow features like updating URL parameter to work through iframes, whoever URL options will still be read from the top holder of the iframe, those are probably the only features that won't work and thus are removed from the GUI menu when embeded in iframe. `builder.config.js` also won't be seen in iframe
|
||||||
|
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
|
@ -79,6 +79,10 @@ body.no-user .msgEmbed>.contents {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -86,7 +90,7 @@ body.no-user .msgEmbed>.contents {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
body:not(.only-embed) .main {
|
body:not(.no-preview):not(.no-editor) .main {
|
||||||
grid-template-columns: 45% 55%;
|
grid-template-columns: 45% 55%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,7 +1147,7 @@ body:not(.gui) .chooser>.back {
|
||||||
|
|
||||||
.bottom .colrs {
|
.bottom .colrs {
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
animation: colrsAn .5s ease-out;
|
animation: colrsAn .25s ease-out;
|
||||||
background: #212226;
|
background: #212226;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
@ -1801,7 +1805,6 @@ body {
|
||||||
--bgc: #27282e;
|
--bgc: #27282e;
|
||||||
left: 140px;
|
left: 140px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
transform: translate(0, -5px);
|
transform: translate(0, -5px);
|
||||||
padding: 8.5px;
|
padding: 8.5px;
|
||||||
|
@ -1812,6 +1815,10 @@ body {
|
||||||
transition: .5s ease;
|
transition: .5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-btn:not(.active) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.top-btn.copy {
|
.top-btn.copy {
|
||||||
left: 190px;
|
left: 190px;
|
||||||
}
|
}
|
||||||
|
@ -1881,8 +1888,9 @@ body {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-btn.menu>.box .item:hover {
|
.top-btn.menu>.box .item.normal:hover {
|
||||||
background: #35373f;
|
background: #35373f;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs {
|
.vs {
|
||||||
|
@ -1895,13 +1903,42 @@ body {
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-btn.menu>.box .item> :is(*, *>svg) {
|
.top-btn.menu>.box .item.normal> :is(*, *>svg) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-btn.menu>.box .item>input {
|
.item.toggle {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.toggle .inner .toggles {
|
||||||
|
display: flex;
|
||||||
|
gap: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.toggle .inner .toggles .item {
|
||||||
|
align-items: center;
|
||||||
|
background: #35363e;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.toggle .inner .toggles .item * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.toggle .inner .title {
|
||||||
|
text-align: left;
|
||||||
|
margin: 10px 0;
|
||||||
|
opacity: .5;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 79%;
|
||||||
|
font-weight: bold;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item.toggle .item.toggle .item.toggle .item.toggle .top-btn.menu>.box .item>input {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1995,6 +2032,96 @@ body.emptyEmbed.emptyContent .emptyTxt {
|
||||||
top: 800%;
|
top: 800%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.no-editor.no-preview .side1 .chooser {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .side1 :not(.needed):not(.needed *) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .main .side1,
|
||||||
|
body.no-preview .main .side2 {
|
||||||
|
height: auto;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:is(.no-preview, .no-editor) .main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .side1 .chooser :is(.back, .opt) {
|
||||||
|
/* display: none; */
|
||||||
|
opacity: .25;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .side1 .chooser.needed> :not(.menu) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .side1 {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* body.no-editor .side1 .chooser {
|
||||||
|
background: transparent;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* body.no-editor .side1 {
|
||||||
|
display: none !important;
|
||||||
|
} */
|
||||||
|
|
||||||
|
body.no-preview .side2 {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* body.no-editor .bottom .colrs {
|
||||||
|
left: 20px;
|
||||||
|
top: 90px;
|
||||||
|
bottom: 0;
|
||||||
|
} */
|
||||||
|
|
||||||
|
body.no-editor .bottom .colrs {
|
||||||
|
left: 20px;
|
||||||
|
top: 90px;
|
||||||
|
bottom: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body.no-editor .pickerToggle {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 5;
|
||||||
|
left: 226px;
|
||||||
|
border-left: 2px solid #4c5057;
|
||||||
|
padding-left: 15px;
|
||||||
|
bottom: auto;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .pickerToggle>svg {
|
||||||
|
width: 17px;
|
||||||
|
transform: translateY(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .main .side1 {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .side1 .item.top {
|
||||||
|
padding-top: 10px;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-editor .bottom .colrs.display {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
background: #292b2f00;
|
background: #292b2f00;
|
||||||
|
@ -2049,7 +2176,8 @@ body.emptyEmbed.emptyContent .emptyTxt {
|
||||||
.bottom .colrs {
|
.bottom .colrs {
|
||||||
bottom: 40px;
|
bottom: 40px;
|
||||||
top: 100px;
|
top: 100px;
|
||||||
left: 10px;
|
top: 90px;
|
||||||
|
left: 20px;
|
||||||
display: none;
|
display: none;
|
||||||
animation: colrsAn .1s ease-out;
|
animation: colrsAn .1s ease-out;
|
||||||
box-shadow: 0px 5px 15px 0px #0000004f;
|
box-shadow: 0px 5px 15px 0px #0000004f;
|
||||||
|
@ -2066,7 +2194,7 @@ body.emptyEmbed.emptyContent .emptyTxt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom {
|
body:not(.no-editor) .bottom {
|
||||||
margin: 40px 0 0 0 !important;
|
margin: 40px 0 0 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
options = window.options || {};
|
options = window.options || {};
|
||||||
inIframe = window.inIframe || top !== self;
|
inIframe = window.inIframe || top !== self;
|
||||||
currentURL = () => new URL(inIframe ? /(https?:\/\/(?:[\d\w]+\.)?[\d\w\.]+(?::\d+)?)/g.exec(document.referrer)[0] : location.href);
|
currentURL = () => new URL(inIframe ? /(https?:\/\/(?:[\d\w]+\.)?[\d\w\.]+(?::\d+)?)/g.exec(document.referrer)?.[0] || location.href : location.href);
|
||||||
|
|
||||||
var params = currentURL().searchParams,
|
var params = currentURL().searchParams,
|
||||||
hasParam = param => params.get(param) !== null,
|
hasParam = param => params.get(param) !== null,
|
||||||
|
@ -20,6 +20,9 @@ var params = currentURL().searchParams,
|
||||||
allowPlaceholders = hasParam('placeholders') || options.allowPlaceholders,
|
allowPlaceholders = hasParam('placeholders') || options.allowPlaceholders,
|
||||||
autoUpdateURL = localStorage.getItem('autoUpdateURL') || options.autoUpdateURL,
|
autoUpdateURL = localStorage.getItem('autoUpdateURL') || options.autoUpdateURL,
|
||||||
autoParams = localStorage.getItem('autoParams') || hasParam('autoparams') || options.autoParams,
|
autoParams = localStorage.getItem('autoParams') || hasParam('autoparams') || options.autoParams,
|
||||||
|
hideEditor = localStorage.getItem('hideeditor') || hasParam('hideeditor') || options.hideEditor,
|
||||||
|
hidePreview = localStorage.getItem('hidepreview') || hasParam('hidepreview') || options.hidePreview,
|
||||||
|
hideMenu = localStorage.getItem('hideMenu') || hasParam('hidemenu') || options.hideMenu,
|
||||||
activeFields, colNum = 1, num = 0, validationError,
|
activeFields, colNum = 1, num = 0, validationError,
|
||||||
toggleStored = item => {
|
toggleStored = item => {
|
||||||
const found = localStorage.getItem(item);
|
const found = localStorage.getItem(item);
|
||||||
|
@ -75,7 +78,7 @@ var params = currentURL().searchParams,
|
||||||
},
|
},
|
||||||
mainKeys = ["author", "footer", "color", "thumbnail", "image", "fields", "title", "description", "url", "timestamp"],
|
mainKeys = ["author", "footer", "color", "thumbnail", "image", "fields", "title", "description", "url", "timestamp"],
|
||||||
jsonKeys = ["embed", "content", ...mainKeys],
|
jsonKeys = ["embed", "content", ...mainKeys],
|
||||||
json = {
|
json = window.json || {
|
||||||
content: "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~",
|
content: "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~",
|
||||||
embed: {
|
embed: {
|
||||||
title: "Hello ~~people~~ world :wave:",
|
title: "Hello ~~people~~ world :wave:",
|
||||||
|
@ -160,9 +163,19 @@ addEventListener('DOMContentLoaded', () => {
|
||||||
if (autoParams)
|
if (autoParams)
|
||||||
document.querySelector('.auto-params > input').checked = true;
|
document.querySelector('.auto-params > input').checked = true;
|
||||||
if (inIframe)
|
if (inIframe)
|
||||||
// Remove menu options that that don't work in iframe.
|
// Remove menu options that don't work in iframe.
|
||||||
for (const e of document.querySelectorAll('.top-btn.menu :is(.item.auto, .item.auto-params, .vs.auto-url)'))
|
for (const e of document.querySelectorAll('.no-frame'))
|
||||||
e.remove();
|
e.remove();
|
||||||
|
if (hideMenu)
|
||||||
|
document.querySelector('.top-btn.menu').remove();
|
||||||
|
if (hideEditor) {
|
||||||
|
document.body.classList.add('no-editor');
|
||||||
|
document.querySelector('.toggle .toggles .editor input').checked = false;
|
||||||
|
}
|
||||||
|
if (hidePreview) {
|
||||||
|
document.body.classList.add('no-preview');
|
||||||
|
document.querySelector('.toggle .toggles .preview input').checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.clickable > img')
|
document.querySelectorAll('.clickable > img')
|
||||||
.forEach(e => e.parentElement.addEventListener('mouseup', el => window.open(el.target.src)));
|
.forEach(e => e.parentElement.addEventListener('mouseup', el => window.open(el.target.src)));
|
||||||
|
@ -955,7 +968,7 @@ addEventListener('DOMContentLoaded', () => {
|
||||||
content.focus();
|
content.focus();
|
||||||
})
|
})
|
||||||
|
|
||||||
document.querySelector('.top-btn.menu').addEventListener('click', e => {
|
document.querySelector('.top-btn.menu')?.addEventListener('click', e => {
|
||||||
if (e.target.closest('.item.dataLink'))
|
if (e.target.closest('.item.dataLink'))
|
||||||
return prompt('Here\'s the current URL with base64 embed data:', jsonToBase64(json, true));
|
return prompt('Here\'s the current URL with base64 embed data:', jsonToBase64(json, true));
|
||||||
|
|
||||||
|
@ -979,6 +992,15 @@ addEventListener('DOMContentLoaded', () => {
|
||||||
if (input.checked) localStorage.setItem('autoParams', true);
|
if (input.checked) localStorage.setItem('autoParams', true);
|
||||||
else localStorage.removeItem('autoParams');
|
else localStorage.removeItem('autoParams');
|
||||||
autoParams = input.checked;
|
autoParams = input.checked;
|
||||||
|
} else if (e.target.closest('.toggles>.item')) {
|
||||||
|
const win = input.closest('.item').classList[2];
|
||||||
|
if (input.checked) {
|
||||||
|
document.body.classList.remove(`no-${win}`);
|
||||||
|
localStorage.removeItem(`hide${win}`);
|
||||||
|
} else {
|
||||||
|
document.body.classList.add(`no-${win}`);
|
||||||
|
localStorage.setItem(`hide${win}`, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e.target.closest('.top-btn').classList.toggle('active')
|
e.target.closest('.top-btn').classList.toggle('active')
|
||||||
})
|
})
|
||||||
|
|
|
@ -13,8 +13,20 @@ options = {
|
||||||
allowPlaceholders: false,
|
allowPlaceholders: false,
|
||||||
autoUpdateURL: false,
|
autoUpdateURL: false,
|
||||||
autoParams: false,
|
autoParams: false,
|
||||||
|
hideEditor: false,
|
||||||
|
hidePreview: false,
|
||||||
|
hideMenu: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Default JSON object
|
||||||
|
// json = {
|
||||||
|
// content: "Hello world",
|
||||||
|
// embed: {
|
||||||
|
// title: "A title",
|
||||||
|
// description: "A description",
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
onload = () => {
|
onload = () => {
|
||||||
// console.log('Salut 👋');
|
// console.log('Salut 👋');
|
||||||
}
|
}
|
||||||
|
|
26
index.html
26
index.html
|
@ -40,7 +40,7 @@
|
||||||
<body class="gui emptyEmbed">
|
<body class="gui emptyEmbed">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<section class="side1 noDisplay">
|
<section class="side1 noDisplay">
|
||||||
<div class="chooser">
|
<div class="chooser needed">
|
||||||
<div class="back"></div>
|
<div class="back"></div>
|
||||||
<div class="gui opt">
|
<div class="gui opt">
|
||||||
<p>GUI</p>
|
<p>GUI</p>
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div>Get data link</div>
|
<div>Get data link</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item normal auto">
|
<div class="item normal auto no-frame">
|
||||||
<!-- <input type="checkbox" id="auto" name="auto" autocomplete="off" class="hidden"> -->
|
<!-- <input type="checkbox" id="auto" name="auto" autocomplete="off" class="hidden"> -->
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" x="0" y="0" viewBox="0 0 48 48" xml:space="preserve" width="16" height="16">
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" x="0" y="0" viewBox="0 0 48 48" xml:space="preserve" width="16" height="16">
|
||||||
|
@ -158,8 +158,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div>Hide username and avatar</div>
|
<div>Hide username and avatar</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vs auto-url"></div>
|
<div class="vs no-frame"></div>
|
||||||
<div class="item auto-params">
|
<div class="item normal auto-params no-frame">
|
||||||
<input id="auto" name="auto" autocomplete="off" type="checkbox">
|
<input id="auto" name="auto" autocomplete="off" type="checkbox">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" x="0" y="0" viewBox="0 0 512 512" xml:space="preserve" width="16" height="16" fill="currentColor" style="display: none;">
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" x="0" y="0" viewBox="0 0 512 512" xml:space="preserve" width="16" height="16" fill="currentColor" style="display: none;">
|
||||||
<g>
|
<g>
|
||||||
|
@ -168,6 +168,22 @@
|
||||||
</svg>
|
</svg>
|
||||||
<div>Auto-update URL options</div>
|
<div>Auto-update URL options</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="vs no-frame"></div>
|
||||||
|
<div class="item toggle">
|
||||||
|
<div class="inner">
|
||||||
|
<div class="title">Toggle on or off</div>
|
||||||
|
<div class="toggles">
|
||||||
|
<div class="item pointer editor">
|
||||||
|
<input autocomplete="off" type="checkbox" checked>
|
||||||
|
<span>Editor</span>
|
||||||
|
</div>
|
||||||
|
<div class="item pointer preview">
|
||||||
|
<input autocomplete="off" type="checkbox" checked>
|
||||||
|
<span>Preview</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -175,7 +191,7 @@
|
||||||
<div class="gui"></div>
|
<div class="gui"></div>
|
||||||
<div class="editorHolder"></div>
|
<div class="editorHolder"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom item">
|
<div class="bottom item needed">
|
||||||
<div class="colrs high">
|
<div class="colrs high">
|
||||||
<div class="hex">
|
<div class="hex">
|
||||||
<div>
|
<div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue