whisper.cat/weboasis/text/base64/index.html

323 lines
11 KiB
HTML
Raw Permalink Normal View History

2023-10-05 23:28:32 +11:00
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, user-scalable=no">
<meta name="description" content="A fast and simple tool to convert to and from base64.">
<meta name="theme-color" content="#2196f3">
<link rel="manifest" href="manifest.json">
<link rel="icon" href="favicon.ico">
<meta http-equiv="cleartype" content="on">
<title>WebOasis - Base64 Converter</title>
<style>
html, body {
height: 100%;
margin: 0;
}
body {
background: #fafafa;
font-family: 'Roboto', 'Helvetica', 'Trebuchet MS1', sans-serif;
-webkit-font-smoothing: antialiased;
/* Disable rubber-band effect on scroll. */
-ms-touch-action: none;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.header {
background: #0078d4;
box-shadow: 0 2px 5px rgba(0,0,0,0.26);
color: #fff;
font-size: 20px;
font-weight: 400;
padding: 0.65em;
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
}
.topRight {
color: rgba(250,250,250,0.8);
float: right;
font-size: 14px;
/* This aligns the link when directly next to the header. */
padding-top: 4px;
}
.topRight:hover, .topRight:focus {
color: rgb(250,250,250);
}
.io {
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
min-height: 0;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}
.tile {
background: #fff;
border-radius: 2px;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
margin: 2em;
/* When squished (mobile landscape), have a minimum standard of readability. */
min-height: 7em;
display: -webkit-flex;
display: flex;
-webkit-flex: 1 0 auto;
flex: 1 0 auto;
-webkit-flex-direction: column;
flex-direction: column;
width: 0;
}
/* Ensure there's not twice the padding when side-by-side. */
#leftTile { margin-right: 1em; }
#rightTile { margin-left: 1em; }
.type {
border-bottom: 1px solid #dbdbdb;
color: rgba(0,0,0,0.87);
font-size: 18px;
font-weight: 500;
padding: 0.65em;
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
}
.content {
font-family: monospace;
font-size: 14px;
height: 100%;
margin: 0;
padding: 0;
position: relative;
/* Margins must equal the total padding on children to ensure scrollbars stay flush. */
margin-bottom: 2em;
margin-right: 2em;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
}
.textarea {
border: none;
font-family: inherit;
font-size: inherit;
height: 100%;
margin: 0;
/* Workaround to improve experience on browsers without new flexbox. */
min-height: 3em;
outline: none;
overflow: auto;
/* This padding must match the imagearea's padding. */
padding: 1em;
position: absolute;
resize: none;
width: 100%;
}
.textarea[readonly], .textarea[readonly='readonly'] {
background: #fff;
color: rgba(0,0,0,0.54);
}
.hidden {
display: none;
}
.errorSource {
background-color: #ffebee;
color: rgba(0,0,0,0.38);
}
.errorDestination {
color: rgba(0,0,0,0.38);
}
.imagearea {
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
font-family: inherit;
font-size: inherit;
height: 100%;
/* Workaround to improve experience on browsers without new flexbox. */
min-height: 3em;
margin: 0;
overflow: auto;
/* This padding must match the textarea's padding. */
padding: 1em;
position: absolute;
width: 100%;
}
/* Custom upload button to workaround multiple cross-browser issues. */
/* The basic approach is to hide an upload control on top of a button image. */
.customUpload {
bottom: 0;
height: 60px;
left: 0;
margin: auto;
overflow: hidden;
position: absolute;
right: 0;
top: 0;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
width: 60px;
}
/* When an image is present, move button to the top-left. */
.imagearea.containsImage .customUpload {
margin: 0;
position: relative;
}
.customUpload svg {
/* drop-shadow does not support the exact blur syntax so this has been approximated. */
-webkit-filter: drop-shadow(0 2px 1px rgba(0,0,0,0.14)) drop-shadow(0 1px 5px rgba(0,0,0,0.12)) drop-shadow(0 1px 1px rgba(0,0,0,0.1));
filter: drop-shadow(0 2px 1px rgba(0,0,0,0.14)) drop-shadow(0 1px 5px rgba(0,0,0,0.12)) drop-shadow(0 1px 1px rgba(0,0,0,0.1));
height: 100%;
width: 100%;
}
.customUpload svg path {
fill: #2196f3;
}
.customUpload:hover svg path {
fill: #1976d2;
}
.customUpload input {
cursor: pointer;
height: 200%;
left: 0;
opacity: 0;
position: absolute;
/* Disable blue glow on Chrome for Android due to cursor: pointer. */
-webkit-tap-highlight-color: transparent;
top: -100%;
width: 100%;
/* A filter on the svg will give it a stacking context, so ensure this stays on top. */
z-index: 99;
}
/* Drag and drop styles. */
#leftTile .dragover {
background-color: #e1f5fe;
}
/* On small screens, stack the areas without margin. */
@media (max-width: 1000px) {
.io {
-webkit-flex-direction: column;
flex-direction: column;
}
.tile {
border-radius: 0;
box-shadow: none;
margin: 0;
-webkit-flex: 1 0 auto;
flex: 1 0 auto;
height: 0;
width: 100%;
}
/* Remove side-by-side padding special-case. */
#leftTile { margin-right: 0; }
#rightTile { margin-left: 0; }
/* Workaround for crbug.com/586872 and Android 4.3 where the background is visible. */
body {
background: #fff;
}
}
/* Custom select box to workaround multiple cross-browser issues. */
/* The basic idea is to stack an invisible select above custom text and a dropdown icon. */
.customSelect {
border-bottom: 1px solid #dbdbdb;
display: inline-block;
margin: 0;
padding: 0;
position: relative;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
}
.customSelect svg {
display: inline-block;
height: 1em;
vertical-align: text-bottom;
width: 1em;
/* Hairline 2px adjustment just for aesthetics. */
margin-left: -2px;
}
.customSelect svg path {
fill: rgba(0,0,0,0.87);
}
.customSelect select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
box-shadow: none;
font: inherit;
/* Position at +/- 10% to increase hit-testable area. */
height: 120%;
left: -10%;
margin: 0;
opacity: 0;
padding: 0;
position: absolute;
top: -10%;
width: 120%;
}
.customSelect select:focus {
outline: none;
}
/* Custom focus support because we cannot use parent CSS selectors. */
.customSelect#focused {
border-bottom: 1px solid rgba(0,0,0,0.87);
}
</style>
</head>
<body>
<div class="header">WebOasis - Base64 Converter<a class="topRight" href="../">Go Back</a></div>
<div class="io">
<div id="leftTile" class="tile">
<div class="type">
<div class="customSelect">
<select id="leftTypeSelect">
<option value="text" selected="true">Text</option>
<option value="image">Image</option>
</select>
<span id="leftTypeText">Text</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-100 -100 300 300">
<path d="M0 0L100 0L50 80Z" />
</svg>
</div>
</div>
<div id="leftContent" class="content">
<textarea id="leftTextarea" class="textarea" spellcheck="false">Hello world</textarea>
<div id="leftImageArea" class="imagearea hidden">
<div class="customUpload">
<input id="leftImageInput" type="file" accept="image/*" title="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z" />
</svg>
</div>
</div>
</div>
</div>
<div id="rightTile" class="tile">
<div class="type">
<div class="customSelect">
<select id="rightTypeSelect">
<option value="base64utf8" selected="true">Base64 (utf8)</option>
<option value="base64ascii">Base64 (ascii)</option>
<option value="base64image" disabled="true">Base64 (image)</option>
</select>
<span id="rightTypeText">Base64</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-100 -100 300 300">
<path d="M0 0L100 0L50 80Z" />
</svg>
</div>
</div>
<div class="content">
<textarea id="rightTextarea" class="textarea" spellcheck="false">SGVsbG8gd29ybGQ=</textarea>
</div>
</div>
</div>
</body>
<script src="base64.js" inline></script>
<script src="index.js" inline></script>
</html>