272 lines
8.8 KiB
JavaScript
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);
|