mirror of
https://github.com/flarum/framework.git
synced 2025-04-24 21:54:04 +08:00
parent
e9ea22d591
commit
bd7a72911b
@ -3,5 +3,8 @@ var gulp = require('flarum-gulp');
|
||||
gulp({
|
||||
modules: {
|
||||
'flarum/emoji': 'src/**/*.js'
|
||||
}
|
||||
},
|
||||
files: [
|
||||
'bower_components/textarea-caret-position/index.js'
|
||||
]
|
||||
});
|
||||
|
6
extensions/emoji/js/forum/bower.json
Normal file
6
extensions/emoji/js/forum/bower.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "flarum-emoji",
|
||||
"devDependencies": {
|
||||
"textarea-caret-position": "~3.0.0"
|
||||
}
|
||||
}
|
456
extensions/emoji/js/forum/dist/extension.js
vendored
456
extensions/emoji/js/forum/dist/extension.js
vendored
File diff suppressed because one or more lines are too long
137
extensions/emoji/js/forum/src/addComposerAutocomplete.js
Normal file
137
extensions/emoji/js/forum/src/addComposerAutocomplete.js
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,95 @@
|
||||
import Component from 'flarum/Component';
|
||||
|
||||
export default class AutocompleteDropdown extends Component {
|
||||
init() {
|
||||
this.active = false;
|
||||
this.index = 0;
|
||||
this.keyWasJustPressed = false;
|
||||
}
|
||||
|
||||
view() {
|
||||
return (
|
||||
<ul className="Dropdown-menu EmojiDropdown">
|
||||
{this.props.items.map(item => <li>{item}</li>)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
show(left, top) {
|
||||
this.$().show().css({
|
||||
left: left + 'px',
|
||||
top: top + 'px'
|
||||
});
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.$().hide();
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
navigate(e) {
|
||||
if (!this.active) return;
|
||||
|
||||
switch (e.which) {
|
||||
case 40: case 38: // Down/Up
|
||||
this.keyWasJustPressed = true;
|
||||
this.setIndex(this.index + (e.which === 40 ? 1 : -1), true);
|
||||
clearTimeout(this.keyWasJustPressedTimeout);
|
||||
this.keyWasJustPressedTimeout = setTimeout(() => this.keyWasJustPressed = false, 500);
|
||||
e.preventDefault();
|
||||
break;
|
||||
|
||||
case 13: case 9: // Enter/Tab
|
||||
this.$('li').eq(this.index).find('button').click();
|
||||
e.preventDefault();
|
||||
break;
|
||||
|
||||
case 27: // Escape
|
||||
this.hide();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
// no default
|
||||
}
|
||||
}
|
||||
|
||||
setIndex(index, scrollToItem) {
|
||||
if (this.keyWasJustPressed && !scrollToItem) return;
|
||||
|
||||
const $dropdown = this.$();
|
||||
const $items = $dropdown.find('li');
|
||||
let rangedIndex = index;
|
||||
|
||||
if (rangedIndex < 0) {
|
||||
rangedIndex = $items.length - 1;
|
||||
} else if (rangedIndex >= $items.length) {
|
||||
rangedIndex = 0;
|
||||
}
|
||||
|
||||
this.index = rangedIndex;
|
||||
|
||||
const $item = $items.removeClass('active').eq(rangedIndex).addClass('active');
|
||||
|
||||
if (scrollToItem) {
|
||||
const dropdownScroll = $dropdown.scrollTop();
|
||||
const dropdownTop = $dropdown.offset().top;
|
||||
const dropdownBottom = dropdownTop + $dropdown.outerHeight();
|
||||
const itemTop = $item.offset().top;
|
||||
const itemBottom = itemTop + $item.outerHeight();
|
||||
|
||||
let scrollTop;
|
||||
if (itemTop < dropdownTop) {
|
||||
scrollTop = dropdownScroll - dropdownTop + itemTop - parseInt($dropdown.css('padding-top'), 10);
|
||||
} else if (itemBottom > dropdownBottom) {
|
||||
scrollTop = dropdownScroll - dropdownBottom + itemBottom + parseInt($dropdown.css('padding-bottom'), 10);
|
||||
}
|
||||
|
||||
if (typeof scrollTop !== 'undefined') {
|
||||
$dropdown.stop(true).animate({scrollTop}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
/*global twemoji, s9e*/
|
||||
|
||||
import { override } from 'flarum/extend';
|
||||
import app from 'flarum/app';
|
||||
import Post from 'flarum/models/Post';
|
||||
|
||||
app.initializers.add('flarum-emoji', () => {});
|
||||
import addComposerAutocomplete from 'flarum/emoji/addComposerAutocomplete';
|
||||
|
||||
app.initializers.add('flarum-emoji', () => {
|
||||
// After typing ':' in the composer, show a dropdown suggesting a bunch of
|
||||
// emoji that the user could use.
|
||||
addComposerAutocomplete();
|
||||
});
|
||||
|
@ -3,3 +3,38 @@ img.emoji {
|
||||
margin: 0 .05em 0 .1em;
|
||||
vertical-align: -0.3em;
|
||||
}
|
||||
|
||||
.EmojiDropdown {
|
||||
max-width: 500px;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
margin: 5px 0 !important;
|
||||
|
||||
> li > a {
|
||||
white-space: normal;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
> li > a:hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.PostPreview {
|
||||
color: @text-color;
|
||||
font-weight: bold;
|
||||
|
||||
.emoji {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.PostPreview-content {
|
||||
overflow: hidden;
|
||||
line-height: 1.7em;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ComposerBody-emojiWrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user