///
import { translate } from 'translator';
import { insertIntoTextarea, updateTextareaSelection } from 'composer/controls';
import { apply as applyScrollStop } from 'scrollStop';
import { buster, base, table, buildEmoji, init as initEmoji, search } from 'emoji';
const $html = $('html');
export const dialogActions = {
open(dialog: JQuery) {
$html.addClass('emoji-insert');
dialog.addClass('open');
dialog.find('.emoji-dialog-search').focus();
return dialog;
},
close(dialog: JQuery) {
$html.removeClass('emoji-insert');
return dialog.removeClass('open');
},
};
const priorities: {
[name: string]: number,
} = {
people: 10,
nature: 9,
food: 8,
activity: 7,
travel: 6,
objects: 5,
symbols: 4,
flags: 3,
regional: 2,
modifier: 1,
other: 0,
};
// create modal
export function init(callback: Callback) {
Promise.all([
$.getJSON(`${base}/emoji/categories.json?${buster}`),
$.getJSON(`${base}/emoji/packs.json?${buster}`),
new Promise(resolve => initEmoji(resolve)),
]).then(([categoriesInfo, packs]: [MetaData.categories, MetaData.packs, undefined]) => {
const categories = Object.keys(categoriesInfo).map((category) => {
const emojis = categoriesInfo[category].map(name => table[name]);
return {
name: category,
emojis: emojis.map(emoji => ({
name: emoji.name,
html: buildEmoji(emoji, true),
})),
};
}).sort((a, b) => {
const aPriority = priorities[a.name] || 0;
const bPriority = priorities[b.name] || 0;
return bPriority - aPriority;
});
window.templates.parse('partials/emoji-dialog', {
categories,
packs,
}, (result) => {
translate(result, (html: string) => {
const dialog = $(html).appendTo('body');
dialog.find('.emoji-dialog-search').on('input', (e) => {
const value = (e.target as HTMLInputElement).value;
if (!value) {
dialog.find('.emoji-dialog-search-results').addClass('hidden');
dialog.find('.nav-tabs .emoji-dialog-search-results').next().find('a').tab('show');
return;
}
const html = search(value)
.slice(0, 100)
.map(emoji =>
`${buildEmoji(emoji, false)}`)
.join('\n');
dialog.find('.tab-pane.emoji-dialog-search-results').html(html);
dialog.find('.emoji-dialog-search-results').removeClass('hidden');
dialog.find('.nav-tabs .emoji-dialog-search-results a').tab('show');
});
dialog.find('.emoji-tabs .nav-tabs a').click((e) => {
e.preventDefault();
$(e.target).tab('show');
}).on('show.bs.tab', (e) => {
$(e.target.getAttribute('href'))
.find('.emoji-link img.defer')
.removeClass('defer')
.each((i, elem) => {
const $elem = $(elem);
const src = $elem.attr('data-src');
$elem.attr('src', src);
});
}).eq(1).trigger('show.bs.tab');
applyScrollStop(dialog.find('.tab-content')[0]);
const close = () => dialogActions.close(dialog);
$(window).on('action:composer.discard action:composer.submit', close);
dialog.find('.close').click(close);
if (dialog.draggable) {
dialog.draggable({
handle: '.top-bar',
});
}
callback(dialog);
});
});
});
}
export function toggle(
opener: HTMLElement,
onClick: (e: JQuery.Event, name: string, dialog: JQuery) => void,
) {
function after(dialog: JQuery) {
if (dialog.hasClass('open')) {
dialogActions.close(dialog);
return;
}
dialog.off('click').on('click', '.emoji-link', (e) => {
e.preventDefault();
const name = (e.currentTarget as HTMLAnchorElement).name;
onClick(e, name, dialog);
});
const buttonRect = opener.getBoundingClientRect();
const position = {
bottom: 'auto',
top: 'auto',
right: 'auto',
left: 'auto',
};
if (buttonRect.top > 440) {
position.top = `${buttonRect.top - 400}px`;
} else {
position.top = `${buttonRect.top + 40}px`;
}
if (buttonRect.left < window.innerWidth / 2) {
position.left = `${buttonRect.left + 40}px`;
} else {
position.left = `${buttonRect.left - 400}px`;
}
dialog.css(position);
dialogActions.open(dialog);
}
const dialog = $('#emoji-dialog');
if (dialog.length) {
after(dialog);
} else {
init(after);
}
}
export function toggleForInsert(textarea: HTMLTextAreaElement) {
toggle($('[data-format="emoji-add-emoji"]').filter(':visible')[0], (e, name) => {
const text = `:${name}: `;
const { selectionStart, selectionEnd } = textarea;
const end = selectionEnd + text.length;
const start = selectionStart === selectionEnd ? end : selectionStart;
insertIntoTextarea(textarea, text);
updateTextareaSelection(textarea, start, end);
$(textarea).trigger('input');
});
}