4in1_ws_web/htdocs/js/admin/11-write-form.js
2024-03-09 03:50:33 +00:00

272 lines
8.8 KiB
JavaScript

class AdminWriteEditForm {
constructor(opts = {}) {
this.opts = opts
this.form = document.forms[this.isPage() ? 'pageForm' : 'postForm']
this.isFixed = false
this.previewTimeout = null
this.previewRequest = null
this.tocByLang = {}
if (!this.isEditing() && this.isPost()) {
for (const l of opts.langs) {
this.tocByLang[l] = false
}
}
this.form.addEventListener('submit', this.onSubmit)
this.form.title.addEventListener('input', this.onInput)
this.form.text.addEventListener('input', this.onInput)
ge('toggle_wrap').addEventListener('click', this.onToggleWrapClick)
if (this.isPost()) {
ge('toc_cb').addEventListener('change', (e) => {
this.tocByLang[this.getCurrentLang()] = e.target.checked
})
}
let lang = 'en'
if (this.isPost()) {
lang = this.getCurrentLang()
this.form.lang.addEventListener('change', (e) => {
let newLang = e.target.options[e.target.selectedIndex].value
this.draft.setLang(newLang)
this.fillFromDraft({applyEvenEmpty: true})
ge('toc_cb').checked = this.tocByLang[newLang]
})
}
let draftId, draftType = !this.isPost() ? 'page' : 'post'
if (this.isEditing()) {
draftId = `edit_${draftType}${this.opts.id}`
} else {
draftId = `new_${draftType}`
}
this.draft = new Draft(draftId, lang);
if (this.isEditing()) {
if (this.isPost()) {
for (let l in opts.texts) {
this.draft.setLang(l)
this.draft.title = opts.texts[l].title
this.draft.text = opts.texts[l].md
this.tocByLang[l] = opts.texts[l].toc
}
this.draft.setLang(lang)
} else {
this.draft.title = opts.text.title
this.draft.text = opts.text.text
}
this.showPreview()
} else {
this.fillFromDraft()
}
// window.addEventListener('scroll', this.onScroll)
// window.addEventListener('resize', this.onResize)
}
getCurrentLang() { return this.form.lang.options[this.form.lang.selectedIndex].value }
isPost() { return !this.opts.pages }
isPage() { return !!this.opts.pages }
isEditing() { return !!this.opts.edit }
fillFromDraft({applyEvenEmpty} = {applyEvenEmpty: false}) {
for (const what of ['title', 'text']) {
if (this.draft[what] !== '' || applyEvenEmpty)
this.form[what].value = this.draft[what]
}
if (this.form.text.value !== '' || applyEvenEmpty)
this.showPreview()
}
showPreview() {
if (this.previewRequest !== null)
this.previewRequest.abort()
const params = {
md: this.form.elements.text.value,
use_image_previews: this.isPage() ? 1 : 0
}
if (this.isPost())
params.title = this.form.elements.title.value
this.previewRequest = ajax.post('/admin/markdown-preview.ajax', params, (err, response) => {
if (err)
return console.error(err)
ge('preview_html').innerHTML = response.html
})
}
showError(code, message) {
if (code) {
let el = ge('form-error')
let label = escape(lang(`err_blog_${code}`))
if (message)
label += ' (' + message + ')'
el.innerHTML = label
el.style.display = 'block'
} else if (message) {
alert(lang('error')+': '+message)
}
}
hideError() {
let el = ge('form-error')
el.style.display = 'none'
}
onSubmit = (evt) => {
const fields = []
try {
if (this.isEditing()) {
fields.push('new_short_name');
} else {
fields.push('short_name');
}
for (const field of fields) {
if (evt.target.elements[field].value.trim() === '')
throw 'no_'+field
}
const fd = new FormData()
for (const f of fields) {
console.log(`field: ${f}`)
fd.append(f, evt.target[f].value.trim())
}
// fd.append('lang', this.getCurrentLang())
if (this.isPost())
fd.append('visible', ge('visible_cb').checked ? 1 : 0)
// text-specific fields
let atLeastOneLangIsWritten = false
const writtenLangs = []
if (this.isPost()) {
for (const l of this.opts.langs) {
const title = this.draft.getForLang(l, 'title')
const text = this.draft.getForLang(l, 'text')
console.log(`lang: ${l}`, title, text)
if (title !== '' && text !== '')
atLeastOneLangIsWritten = true
fd.append(`title:${l}`, title)
fd.append(`text:${l}`, text)
fd.append(`toc:${l}`, this.tocByLang[l] ? 1 : 0)
writtenLangs.push(l)
}
} else {
const title = this.draft.title
const text = this.draft.text
if (title !== '' && text !== '') {
atLeastOneLangIsWritten = true
fd.append('title', title)
fd.append('text', text)
}
}
if (!atLeastOneLangIsWritten)
throw 'no_text'
fd.append('langs', writtenLangs.join(','))
// date field
if (this.isPost()) {
const dateInput = evt.target.elements.date;
if (!dateInput.value)
throw 'no_date'
fd.append('date', dateInput.value)
}
fd.append('token', this.opts.token)
cancelEvent(evt)
this.hideError();
ajax.post(evt.target.action, fd, (error, response) => {
if (error) {
this.showError(error.code, error.message)
return;
}
if (response.url) {
this.draft.reset(this.opts.langs);
window.location = response.url
}
})
} catch (e) {
const errorText = typeof e == 'string' ? lang('error')+': '+lang((this.isPage() ? 'err_pages_' : 'err_blog_')+e) : e.message;
alert(errorText);
console.error(e);
return cancelEvent(evt);
}
}
onToggleWrapClick = (e) => {
const textarea = this.form.elements.text
if (!hasClass(textarea, 'nowrap')) {
addClass(textarea, 'nowrap')
} else {
removeClass(textarea, 'nowrap')
}
return cancelEvent(e)
}
onInput = (e) => {
if (this.previewTimeout !== null)
clearTimeout(this.previewTimeout);
this.previewTimeout = setTimeout(() => {
this.previewTimeout = null;
this.showPreview();
const what = e.target.name === 'title' ? 'title' : 'text'
this.draft[what] = e.target.value
}, 300)
}
onScroll = () => {
var ANCHOR_TOP = 10;
var y = window.pageYOffset;
var form = this.form;
var td = ge('form_first_cell');
var ph = ge('form_placeholder');
var rect = td.getBoundingClientRect();
if (rect.top <= ANCHOR_TOP && !this.isFixed) {
ph.style.height = form.getBoundingClientRect().height+'px';
var w = (rect.width - (parseInt(getComputedStyle(td).paddingRight, 10) || 0));
form.style.display = 'block';
form.style.width = w+'px';
form.style.position = 'fixed';
form.style.top = ANCHOR_TOP+'px';
this.isFixed = true;
} else if (rect.top > ANCHOR_TOP && this.isFixed) {
form.style.display = '';
form.style.width = '';
form.style.position = '';
form.style.position = '';
ph.style.height = '';
this.isFixed = false;
}
}
onResize = () => {
if (!this.isFixed)
return
const form = this.form
const td = ge('form_first_cell')
const ph = ge('form_placeholder')
const rect = td.getBoundingClientRect()
const pr = parseInt(getComputedStyle(td).paddingRight, 10) || 0
ph.style.height = form.getBoundingClientRect().height+'px'
form.style.width = (rect.width - pr) + 'px'
}
}
// bindEventHandlers(AdminWriteForm);