Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
2fc79646fb |
|||
|
fa59a916ca |
8 changed files with 169 additions and 347 deletions
|
|
@ -168,7 +168,7 @@ func render(b *strings.Builder, nodes []Node) {
|
|||
b.WriteString("</figure>")
|
||||
|
||||
case *Audio:
|
||||
b.WriteString(`<audio controls="" preload="metadata" src="`)
|
||||
b.WriteString(`<audio controls="" preload="metadata" src="/uploaded/`)
|
||||
b.WriteString(html.EscapeString(safeUrl(v.URL)))
|
||||
b.WriteString(`" type="audio/mpeg"></audio>`)
|
||||
case *Aside:
|
||||
|
|
|
|||
|
|
@ -326,99 +326,72 @@
|
|||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
align-items: start;
|
||||
gap: 10px;
|
||||
position: relative;
|
||||
form {
|
||||
max-width: unset;
|
||||
flex-basis: 50%;
|
||||
width: 100%;
|
||||
}
|
||||
article {
|
||||
flex-basis: 50%;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
textarea {
|
||||
max-width: unset;
|
||||
height: 80vh;
|
||||
}
|
||||
}
|
||||
|
||||
.media-preview-container {
|
||||
position: sticky;
|
||||
top: var(--margin-s);
|
||||
}
|
||||
|
||||
.toggle-preview-btn {
|
||||
position: static;
|
||||
margin: var(--margin-s) 0;
|
||||
}
|
||||
|
||||
.media-picker {
|
||||
display: none;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
padding-left:0;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
max-height: 60vh;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
max-height: 50vh;
|
||||
> *+* {
|
||||
margin-top: 1em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
li {
|
||||
padding:0;
|
||||
}
|
||||
}
|
||||
.media-picker__media {
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 150px 1fr;
|
||||
gap:1em;
|
||||
line-height: 1;
|
||||
img,
|
||||
audio,
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
width: 150px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.media-picker__buttons {
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
inset: 0;
|
||||
gap: 6px;
|
||||
button {
|
||||
flex: 0 1 32px;
|
||||
}
|
||||
margin-top:1em;
|
||||
gap: 0.5em;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.media-picker__media:hover .media-picker__buttons {
|
||||
visibility: visible;
|
||||
[theme="raw"] .media-picker__buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-preview {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: var(--padding-form);
|
||||
display: block;
|
||||
|
||||
overflow-y: scroll;
|
||||
max-height: 100vh;
|
||||
svg {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="false"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="gallery"] {
|
||||
.media-picker {
|
||||
display: grid;
|
||||
}
|
||||
.page-preview {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="preview"] {
|
||||
.media-picker {
|
||||
display: none;
|
||||
}
|
||||
.page-preview {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-footer {
|
||||
position: fixed;
|
||||
|
|
|
|||
|
|
@ -2,17 +2,13 @@
|
|||
<main>
|
||||
<h1>New page</h1>
|
||||
<div class="edit-footer">
|
||||
<div>
|
||||
<button data-small data-secondary onClick="toggleGallery()" id="mediasBtn">Medias</button>
|
||||
<button data-small onClick="togglePreview()" id="previewBtn">Preview</button>
|
||||
</div>
|
||||
<div>
|
||||
<form data-naked action='/files/upload' method='POST' class="media-form">
|
||||
<div>
|
||||
<input type="file" multiple="multiple" id="fileUpload" value="Upload file" />
|
||||
</div>
|
||||
<div>
|
||||
<button data-small type='submit' data-size="20" id="uploadMediaBtn" disabled>
|
||||
<button data-small type='submit' data-size="20" id="uploadMediaBtn" >
|
||||
Upload file
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -23,6 +19,15 @@
|
|||
<div class="edit-page">
|
||||
<form action='/page/create' method='POST'>
|
||||
<input type='hidden' id="csrf_token" name='csrf_token' value='{{.CSRFToken}}'>
|
||||
|
||||
<label for="bodyError">Content:</label>
|
||||
<textarea id="body" name='body' {{with .Form.FieldErrors.body}} aria-invalid aria-describedby="bodyError" {{end}}>{{.Form.Body}}</textarea>
|
||||
{{with .Form.FieldErrors.body}}
|
||||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
{{template "mediaselector" .}}
|
||||
|
||||
|
||||
<label for="name">Title:</label>
|
||||
<input autofocus type='text' id="name" name='name' value="{{.Form.Name}}" {{with .Form.FieldErrors.name}} aria-invalid
|
||||
aria-describedby="nameError" {{end}}>
|
||||
|
|
@ -37,11 +42,6 @@
|
|||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
|
||||
<label for="bodyError">Content:</label>
|
||||
<textarea id="body" name='body' {{with .Form.FieldErrors.body}} aria-invalid aria-describedby="bodyError" {{end}}>{{.Form.Body}}</textarea>
|
||||
{{with .Form.FieldErrors.body}}
|
||||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
|
||||
<div class="grouped">
|
||||
<div>
|
||||
|
|
@ -111,50 +111,11 @@
|
|||
<input type='submit' value='Publish page' data-size="20">
|
||||
</div>
|
||||
</form>
|
||||
<div class="media-preview-container" data-show="preview" >
|
||||
|
||||
<div class="media-picker">
|
||||
{{range $image := .Files}}
|
||||
{{if eq $image.Extension ".png" ".jpg" ".jpeg" ".gif" ".webp" ".avif"}}
|
||||
<div class="media-picker__media" id="{{$image.Filename}}">
|
||||
<img loading="lazy" src="{{$image.Slug}}" />
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Image</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp4"}}
|
||||
<div class="media-picker__media">
|
||||
<video src="{{$image.Slug}}" ></video>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Video</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp3"}}
|
||||
<div class="media-picker__media">
|
||||
<div style="text-align: center;">
|
||||
<strong>{{$image.Filename}}{{$image.Extension}}</strong>
|
||||
</div>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Aduio</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<article class="page-preview {{.Form.Category}}"></article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
autosize(document.querySelector('textarea'));
|
||||
|
||||
const formated = document.querySelector('article');
|
||||
const textarea = document.querySelector('textarea');
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@
|
|||
<main>
|
||||
<h1>Edit page</h1>
|
||||
<div class="edit-footer">
|
||||
<div>
|
||||
<button data-small data-secondary onClick="toggleGallery()" id="mediasBtn">Medias</button>
|
||||
<button data-small onClick="togglePreview()" id="previewBtn">Preview</button>
|
||||
</div>
|
||||
<div>
|
||||
<form data-naked action='/files/upload' method='POST' class="media-form">
|
||||
<div>
|
||||
|
|
@ -26,11 +22,17 @@
|
|||
<input type="hidden" value="{{.Form.Id}}" name="id"/>
|
||||
<input type="hidden" value="{{.Form.Slug}}" name="slug"/>
|
||||
|
||||
<img src="/og/{{.Form.Slug}}" />
|
||||
|
||||
<label for="bodyError">Content:</label>
|
||||
<textarea autofocus id="body" name='body' {{with .Form.FieldErrors.body}} aria-invalid aria-describedby="bodyError" {{end}}>{{.Form.Body}}</textarea>
|
||||
{{with .Form.FieldErrors.body}}
|
||||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
{{template "mediaselector" .}}
|
||||
|
||||
<label for="name">Title:</label>
|
||||
<span>Changing the title will also change the page url</span>
|
||||
<input autofocus type='text' id="name" name='name' value="{{.Form.Name}}" {{with .Form.FieldErrors.name}} aria-invalid
|
||||
<input type='text' id="name" name='name' value="{{.Form.Name}}" {{with .Form.FieldErrors.name}} aria-invalid
|
||||
aria-describedby="nameError" {{end}}>
|
||||
{{with .Form.FieldErrors.name}}
|
||||
<span id="nameError">{{.}}</span>
|
||||
|
|
@ -43,14 +45,6 @@
|
|||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
|
||||
<label for="bodyError">Content:</label>
|
||||
<textarea id="body" name='body' {{with .Form.FieldErrors.body}} aria-invalid aria-describedby="bodyError" {{end}}>{{.Form.Body}}</textarea>
|
||||
{{with .Form.FieldErrors.body}}
|
||||
<span id="summaryError">{{.}}</span>
|
||||
{{end}}
|
||||
|
||||
|
||||
|
||||
<div class="grouped">
|
||||
<div>
|
||||
{{ $host := .Form.Host }}
|
||||
|
|
@ -114,54 +108,21 @@
|
|||
<label for="menu">Show Sub Pages List</label>
|
||||
</fieldset>
|
||||
|
||||
<div>
|
||||
<details>
|
||||
<summary>OG Image Preview</summary>
|
||||
<img src="/og/{{.Form.Slug}}" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type='submit' data-size="20">Save changes</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="media-preview-container" data-show="preview" >
|
||||
|
||||
<div class="media-picker">
|
||||
{{range $image := .Files}}
|
||||
{{if eq $image.Extension ".png" ".jpg" ".jpeg" ".gif" ".webp" ".avif"}}
|
||||
<div class="media-picker__media" id="{{$image.Filename}}">
|
||||
<img loading="lazy" src="{{$image.Slug}}" />
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Image</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp4"}}
|
||||
<div class="media-picker__media">
|
||||
<video src="{{$image.Slug}}" ></video>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Video</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp3"}}
|
||||
<div class="media-picker__media">
|
||||
<div style="text-align: center;">
|
||||
<strong>{{$image.Filename}}{{$image.Extension}}</strong>
|
||||
</div>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true)">Insert Audio</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<article class="page-preview {{.Form.Category}}"></article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
autosize(document.querySelector('textarea'));
|
||||
|
||||
const formated = document.querySelector('article');
|
||||
const textarea = document.querySelector('textarea');
|
||||
|
|
|
|||
54
ui/html/partials/mediaselector.tmpl
Normal file
54
ui/html/partials/mediaselector.tmpl
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{{define "mediaselector"}}
|
||||
<div>
|
||||
<details>
|
||||
<summary>Medias</summary>
|
||||
<ul role="list" class="media-picker">
|
||||
{{range $image := .Files}}
|
||||
{{if eq $image.Extension ".png" ".jpg" ".jpeg" ".gif" ".webp" ".avif"}}
|
||||
<li class="media-picker__media" id="{{$image.Filename}}">
|
||||
<img loading="lazy" src="{{$image.Slug}}" />
|
||||
<span>
|
||||
<small><strong>{{$image.Filename}}{{$image.Extension}}</strong></small><br>
|
||||
<small><code>(image: {{$image.Filename}}{{$image.Extension}} alt: )</code></small>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true, event)">Insert</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}}, event)">Delete</button>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
</li>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp4"}}
|
||||
<li class="media-picker__media" id="{{$image.Filename}}">
|
||||
<video controls src="{{$image.Slug}}" ></video>
|
||||
<span>
|
||||
<small><strong>{{$image.Filename}}{{$image.Extension}}</strong></small><br>
|
||||
<small><code>(video: {{$image.Filename}}{{$image.Extension}})</code></small>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true, event)">Insert Video</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}}, event)">Delete</button>
|
||||
</div>
|
||||
</span>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if eq $image.Extension ".mp3"}}
|
||||
<li class="media-picker__media" id="{{$image.Filename}}">
|
||||
<audio controls src="{{$image.Slug}}"></audio>
|
||||
<span>
|
||||
<small><strong>{{$image.Filename}}{{$image.Extension}}</strong></small><br>
|
||||
<small><code>(audio: {{$image.Filename}}{{$image.Extension}})</code></small>
|
||||
<div class="media-picker__buttons">
|
||||
<button data-small onClick="insertMedia({{$image.Filename}}+{{$image.Extension}}, {{$image.Extension}}, true, event)">Insert audio</button>
|
||||
<button data-small data-secondary
|
||||
onClick="deleteMedia({{$image.Filename}}+{{$image.Extension}}, event)">Delete</button>
|
||||
</div>
|
||||
</span>
|
||||
</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</ul>
|
||||
</details>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -326,58 +326,16 @@ background: lightgrey;
|
|||
}
|
||||
textarea {
|
||||
max-width: unset;
|
||||
width:100%;
|
||||
height:30vh;
|
||||
}
|
||||
}
|
||||
|
||||
.media-preview-container {
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
.toggle-preview-btn {
|
||||
position: static;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.media-picker {
|
||||
display: none;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
max-height: 60vh;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.media-picker__media {
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
img,
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.media-picker__buttons {
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
inset: 0;
|
||||
gap: 6px;
|
||||
button {
|
||||
flex: 0 1 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.media-picker__media:hover .media-picker__buttons {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.page-preview {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
|
|
@ -389,40 +347,56 @@ background: lightgrey;
|
|||
}
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="false"] {
|
||||
display: none;
|
||||
|
||||
.media-picker {
|
||||
padding-left:0;
|
||||
overflow-y: scroll;
|
||||
max-height: 50vh;
|
||||
> *+* {
|
||||
margin-top: 1em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="gallery"] {
|
||||
.media-picker {
|
||||
li {
|
||||
padding:0;
|
||||
}
|
||||
}
|
||||
.media-picker__media {
|
||||
display: grid;
|
||||
}
|
||||
.page-preview {
|
||||
display: none;
|
||||
grid-template-columns: 150px 1fr;
|
||||
gap:1em;
|
||||
line-height: 1;
|
||||
img,
|
||||
audio,
|
||||
video {
|
||||
width: 150px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.media-preview-container[data-show="preview"] {
|
||||
.media-picker {
|
||||
.media-picker__buttons {
|
||||
display: flex;
|
||||
margin-top:1em;
|
||||
gap: 0.5em;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
[theme="raw"] .media-picker__buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-preview {
|
||||
display: block;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: var(--padding-form);
|
||||
overflow-y: scroll;
|
||||
max-height: 100vh;
|
||||
svg {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-footer {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: var(--background);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
padding: calc(20px / 2) 40px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: calc(20px / 4) calc(20px);
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
|
|
@ -443,5 +417,16 @@ background: lightgrey;
|
|||
}
|
||||
|
||||
|
||||
form > * {
|
||||
display: block;
|
||||
}
|
||||
|
||||
form > * + *, .grouped > *+*{
|
||||
margin-top: var(--margin-s);
|
||||
margin-top: 10px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
{{end}}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,5 @@
|
|||
// Focus-Aware Keystroke Pattern Detector with Redirects
|
||||
// This script detects keyboard shortcuts only when NOT focusing on input elements
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Variables to store keystroke history
|
||||
let keystrokeHistory = '';
|
||||
|
|
@ -70,117 +69,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
// Autosize
|
||||
!function (e, t) {
|
||||
"object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e || self).autosize = t()
|
||||
}(this, function () {
|
||||
var e = new Map;
|
||||
|
||||
function t(t) {
|
||||
var o = e.get(t);
|
||||
o && o.destroy()
|
||||
}
|
||||
|
||||
function o(t) {
|
||||
var o = e.get(t);
|
||||
o && o.update()
|
||||
}
|
||||
|
||||
var r = null;
|
||||
return "undefined" == typeof window ? ((r = function (e) {
|
||||
return e
|
||||
}).destroy = function (e) {
|
||||
return e
|
||||
}, r.update = function (e) {
|
||||
return e
|
||||
}) : ((r = function (t, o) {
|
||||
return t && Array.prototype.forEach.call(t.length ? t : [t], function (t) {
|
||||
return function (t) {
|
||||
if (t && t.nodeName && "TEXTAREA" === t.nodeName && !e.has(t)) {
|
||||
var o, r = null, n = window.getComputedStyle(t), i = (o = t.value, function () {
|
||||
s({
|
||||
testForHeightReduction: "" === o || !t.value.startsWith(o),
|
||||
restoreTextAlign: null
|
||||
}), o = t.value
|
||||
}), l = function (o) {
|
||||
t.removeEventListener("autosize:destroy", l), t.removeEventListener("autosize:update", a), t.removeEventListener("input", i), window.removeEventListener("resize", a), Object.keys(o).forEach(function (e) {
|
||||
return t.style[e] = o[e]
|
||||
}), e.delete(t)
|
||||
}.bind(t, {
|
||||
height: t.style.height,
|
||||
resize: t.style.resize,
|
||||
textAlign: t.style.textAlign,
|
||||
overflowY: t.style.overflowY,
|
||||
overflowX: t.style.overflowX,
|
||||
wordWrap: t.style.wordWrap
|
||||
});
|
||||
t.addEventListener("autosize:destroy", l), t.addEventListener("autosize:update", a), t.addEventListener("input", i), window.addEventListener("resize", a), t.style.overflowX = "hidden", t.style.wordWrap = "break-word", e.set(t, {
|
||||
destroy: l,
|
||||
update: a
|
||||
}), a()
|
||||
}
|
||||
|
||||
function s(e) {
|
||||
var o, i, l = e.restoreTextAlign, a = void 0 === l ? null : l, d = e.testForHeightReduction,
|
||||
u = void 0 === d || d, f = n.overflowY;
|
||||
if (0 !== t.scrollHeight && ("vertical" === n.resize ? t.style.resize = "none" : "both" === n.resize && (t.style.resize = "horizontal"), u && (o = function (e) {
|
||||
for (var t = []; e && e.parentNode && e.parentNode instanceof Element;) e.parentNode.scrollTop && t.push([e.parentNode, e.parentNode.scrollTop]), e = e.parentNode;
|
||||
return function () {
|
||||
return t.forEach(function (e) {
|
||||
var t = e[0], o = e[1];
|
||||
t.style.scrollBehavior = "auto", t.scrollTop = o, t.style.scrollBehavior = null
|
||||
})
|
||||
}
|
||||
}(t), t.style.height = ""), i = "content-box" === n.boxSizing ? t.scrollHeight - (parseFloat(n.paddingTop) + parseFloat(n.paddingBottom)) : t.scrollHeight + parseFloat(n.borderTopWidth) + parseFloat(n.borderBottomWidth), "none" !== n.maxHeight && i > parseFloat(n.maxHeight) ? ("hidden" === n.overflowY && (t.style.overflow = "scroll"), i = parseFloat(n.maxHeight)) : "hidden" !== n.overflowY && (t.style.overflow = "hidden"), t.style.height = i + "px", a && (t.style.textAlign = a), o && o(), r !== i && (t.dispatchEvent(new Event("autosize:resized", { bubbles: !0 })), r = i), f !== n.overflow && !a)) {
|
||||
var c = n.textAlign;
|
||||
"hidden" === n.overflow && (t.style.textAlign = "start" === c ? "end" : "start"), s({
|
||||
restoreTextAlign: c,
|
||||
testForHeightReduction: !0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function a() {
|
||||
s({ testForHeightReduction: !0, restoreTextAlign: null })
|
||||
}
|
||||
}(t)
|
||||
}), t
|
||||
}).destroy = function (e) {
|
||||
return e && Array.prototype.forEach.call(e.length ? e : [e], t), e
|
||||
}, r.update = function (e) {
|
||||
return e && Array.prototype.forEach.call(e.length ? e : [e], o), e
|
||||
}), r
|
||||
});
|
||||
|
||||
function toggleGallery(e) {
|
||||
const mediasBtn = document.querySelector("#mediasBtn")
|
||||
const previewBtn = document.querySelector("#previewBtn")
|
||||
const mediaPreviewContainer = document.querySelector(".media-preview-container")
|
||||
if (mediaPreviewContainer.dataset.show !== "gallery") {
|
||||
mediaPreviewContainer.dataset.show = "gallery"
|
||||
delete (mediasBtn.dataset.secondary)
|
||||
previewBtn.setAttribute("data-secondary", "");
|
||||
} else {
|
||||
mediaPreviewContainer.dataset.show = false
|
||||
mediasBtn.setAttribute("data-secondary", "");
|
||||
}
|
||||
}
|
||||
|
||||
function togglePreview(e) {
|
||||
const previewBtn = document.querySelector("#previewBtn")
|
||||
const mediasBtn = document.querySelector("#mediasBtn")
|
||||
const mediaPreviewContainer = document.querySelector(".media-preview-container")
|
||||
if (mediaPreviewContainer.dataset.show !== "preview") {
|
||||
mediaPreviewContainer.dataset.show = "preview"
|
||||
delete (previewBtn.dataset.secondary)
|
||||
mediasBtn.setAttribute("data-secondary", "");
|
||||
} else {
|
||||
mediaPreviewContainer.dataset.show = false
|
||||
previewBtn.setAttribute("data-secondary", "");
|
||||
}
|
||||
}
|
||||
|
||||
let debounceTimer;
|
||||
function triggerDemo() {
|
||||
clearTimeout(debounceTimer);
|
||||
|
|
@ -195,8 +83,8 @@ function triggerDemo() {
|
|||
}
|
||||
|
||||
// Insert text at saved cursor position (works even when not focused)
|
||||
function insertMedia(slug, extension, reposition) {
|
||||
console.log({ reposition })
|
||||
function insertMedia(slug, extension, reposition, event) {
|
||||
event.preventDefault()
|
||||
const value = textarea.value;
|
||||
let textInsert = ""
|
||||
|
||||
|
|
@ -222,15 +110,15 @@ function insertMedia(slug, extension, reposition) {
|
|||
textarea.setSelectionRange(savedCursor, savedCursor);
|
||||
}
|
||||
|
||||
togglePreview()
|
||||
// togglePreview()
|
||||
setTimeout(() => {
|
||||
triggerDemo()
|
||||
}, 100)
|
||||
}, 400)
|
||||
}
|
||||
|
||||
function deleteMedia(filename) {
|
||||
function deleteMedia(filename, event) {
|
||||
event.preventDefault()
|
||||
if (!confirm(`Delete "${filename}"?`)) return;
|
||||
|
||||
const csrfToken = document.querySelector('#csrf_token')?.value;
|
||||
|
||||
fetch(`/files/delete/${encodeURIComponent(filename)}`, {
|
||||
|
|
@ -242,7 +130,7 @@ function deleteMedia(filename) {
|
|||
const responseText = await response.text();
|
||||
|
||||
if (response.ok) {
|
||||
const mediaItem = document.querySelector(`#${filename.split('.').slice(0, -1)}`)
|
||||
const mediaItem = document.querySelector(`#${filename.split('.').slice(0, -1)[0]}`)
|
||||
if (mediaItem) {
|
||||
mediaItem.remove()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue