|
@ -12,38 +12,56 @@ import * as picmo from 'picmo'; |
|
|
|
|
|
|
|
|
export default class SiteComments { |
|
|
export default class SiteComments { |
|
|
|
|
|
|
|
|
constructor (app, rootElement) { |
|
|
constructor (app) { |
|
|
this.app = app; |
|
|
this.app = app; |
|
|
this.log = new DtpLog({ name: 'Site Comments', slug: 'comments' }); |
|
|
this.log = new DtpLog({ name: 'Site Comments', slug: 'comments' }); |
|
|
|
|
|
this.createEmojiPickers(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
createEmojiPickers ( ) { |
|
|
|
|
|
const pickerContainers = document.querySelectorAll('li.comment-emoji-picker:not([data-initialized])'); |
|
|
|
|
|
for (const container of pickerContainers) { |
|
|
|
|
|
const picker = { }; |
|
|
|
|
|
|
|
|
|
|
|
picker.drop = container.querySelector('.comment-emoji-picker-drop'); |
|
|
|
|
|
picker.ui = picker.drop.querySelector('.comment-emoji-picker-ui'); |
|
|
|
|
|
|
|
|
this.ui = { |
|
|
const formId = picker.drop.getAttribute('data-form-id'); |
|
|
input: rootElement.querySelector('#comment-content'), |
|
|
picker.form = document.querySelector(`form#${formId}`); |
|
|
emojiPicker: rootElement.querySelector('#comment-emoji-picker'), |
|
|
picker.input = picker.form.querySelector(`textarea[data-form-id=${formId}]`); |
|
|
characterCount: rootElement.querySelector('.comment-character-count'), |
|
|
picker.characterCount = picker.form.querySelector('span.comment-character-count'); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (this.ui.emojiPicker) { |
|
|
picker.picmo = picmo.createPicker({ |
|
|
this.ui.emojiPickerUI = this.ui.emojiPicker.querySelector('.comment-emoji-picker'); |
|
|
|
|
|
this.ui.picmo = picmo.createPicker({ |
|
|
|
|
|
emojisPerRow: 7, |
|
|
emojisPerRow: 7, |
|
|
rootElement: this.ui.emojiPickerUI, |
|
|
rootElement: picker.ui, |
|
|
theme: picmo.darkTheme, |
|
|
theme: picmo.darkTheme, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.ui.picmo.addEventListener('emoji:select', this.onEmojiSelected.bind(this)); |
|
|
picker.picmo.addEventListener('emoji:select', this.onEmojiSelected.bind(this, picker)); |
|
|
|
|
|
|
|
|
this.ui.emojiPickerDrop = UIkit.drop(this.ui.emojiPicker); |
|
|
picker.emojiPickerDrop = UIkit.drop(picker.drop); |
|
|
UIkit.util.on(this.ui.emojiPicker, 'show', ( ) => { |
|
|
UIkit.util.on(picker.drop, 'show', ( ) => { |
|
|
this.log.info('SiteComments', 'showing emoji picker'); |
|
|
this.log.info('SiteComments', 'showing emoji picker'); |
|
|
this.ui.picmo.reset(); |
|
|
picker.picmo.reset(); |
|
|
}); |
|
|
}); |
|
|
} else { |
|
|
|
|
|
UIkit.modal.alert('Comment section without an emoji picker defined'); |
|
|
container.setAttribute('data-initialized', true); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async onCommentInput (event) { |
|
|
async onCommentInput (event) { |
|
|
this.ui.characterCount.textContent = numeral(event.target.value.length).format('0,0'); |
|
|
const target = event.currentTarget || event.target; |
|
|
|
|
|
|
|
|
|
|
|
const formId = target.getAttribute('data-form-id'); |
|
|
|
|
|
if (!formId) { return; } |
|
|
|
|
|
|
|
|
|
|
|
const form = document.getElementById(formId); |
|
|
|
|
|
if (!form) { return; } |
|
|
|
|
|
|
|
|
|
|
|
const label = form.querySelector('span.comment-character-count'); |
|
|
|
|
|
if (!label) { return; } |
|
|
|
|
|
|
|
|
|
|
|
label.textContent = numeral(event.target.value.charCount()).format('0,0'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async showReportCommentForm (event) { |
|
|
async showReportCommentForm (event) { |
|
@ -177,6 +195,7 @@ export default class SiteComments { |
|
|
try { |
|
|
try { |
|
|
const response = await fetch(`/comment/${commentId}/replies`); |
|
|
const response = await fetch(`/comment/${commentId}/replies`); |
|
|
this.app.processResponse(response); |
|
|
this.app.processResponse(response); |
|
|
|
|
|
this.createEmojiPickers(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
UIkit.modal.alert(`Failed to load replies: ${error.message}`); |
|
|
UIkit.modal.alert(`Failed to load replies: ${error.message}`); |
|
|
} |
|
|
} |
|
@ -209,36 +228,38 @@ export default class SiteComments { |
|
|
try { |
|
|
try { |
|
|
const response = await fetch(`${rootUrl}?p=${nextPage}&buttonId=${buttonId}`); |
|
|
const response = await fetch(`${rootUrl}?p=${nextPage}&buttonId=${buttonId}`); |
|
|
await this.app.processResponse(response); |
|
|
await this.app.processResponse(response); |
|
|
|
|
|
this.createEmojiPickers(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
UIkit.modal.alert(`Failed to load more comments: ${error.message}`); |
|
|
UIkit.modal.alert(`Failed to load more comments: ${error.message}`); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async onEmojiSelected (event) { |
|
|
async onEmojiSelected (picker, event) { |
|
|
this.ui.emojiPickerDrop.hide(false); |
|
|
picker.emojiPickerDrop.hide(false); |
|
|
return this.insertContentAtCursor(event.emoji); |
|
|
await this.insertContentAtCursor(picker, event.emoji); |
|
|
|
|
|
picker.characterCount.textContent = numeral(picker.input.value.charCount()).format('0,0'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async insertContentAtCursor (content) { |
|
|
async insertContentAtCursor (picker, content) { |
|
|
this.ui.input.focus(); |
|
|
picker.input.focus(); |
|
|
|
|
|
|
|
|
if (document.selection) { |
|
|
if (document.selection) { |
|
|
let sel = document.selection.createRange(); |
|
|
let sel = document.selection.createRange(); |
|
|
sel.text = content; |
|
|
sel.text = content; |
|
|
} else if (this.ui.input.selectionStart || (this.ui.input.selectionStart === 0)) { |
|
|
} else if (picker.input.selectionStart || (picker.input.selectionStart === 0)) { |
|
|
let startPos = this.ui.input.selectionStart; |
|
|
let startPos = picker.input.selectionStart; |
|
|
let endPos = this.ui.input.selectionEnd; |
|
|
let endPos = picker.input.selectionEnd; |
|
|
|
|
|
|
|
|
let oldLength = this.ui.input.value.length; |
|
|
let oldLength = picker.input.value.length; |
|
|
this.ui.input.value = |
|
|
picker.input.value = |
|
|
this.ui.input.value.substring(0, startPos) + |
|
|
picker.input.value.substring(0, startPos) + |
|
|
content + |
|
|
content + |
|
|
this.ui.input.value.substring(endPos, this.ui.input.value.length); |
|
|
picker.input.value.substring(endPos, picker.input.value.length); |
|
|
|
|
|
|
|
|
this.ui.input.selectionStart = startPos + (this.ui.input.value.length - oldLength); |
|
|
picker.input.selectionStart = startPos + (picker.input.value.length - oldLength); |
|
|
this.ui.input.selectionEnd = this.ui.input.selectionStart; |
|
|
picker.input.selectionEnd = picker.input.selectionStart; |
|
|
} else { |
|
|
} else { |
|
|
this.ui.input.value += content; |
|
|
picker.input.value += content; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |