This repository has been archived by the owner on Nov 12, 2018. It is now read-only.
/
mention_menu.js
134 lines (115 loc) · 3.96 KB
/
mention_menu.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* Created by Zhongyi on 4/9/16.
*/
'use strict';
const Common = require('../common');
const pinyin = require('pinyin');
class MentionMenu {
static init() {
const $box = $('<div id="userSelectionBox"/>');
const $div = $('<div/>');
$div.html(Common.MENTION_MENU_HINT_TEXT);
$div.addClass('user_select_hint_text');
$box.append($div);
const $select = $('<select multiple/>');
$select.change(() => {
const $editArea = $('#editArea');
$editArea.focus();
const newMessage = $editArea.html().replace(/@\S*$/ig, `@${$select.val()} `);
$editArea.html('');
$editArea.scope().insertToEditArea(newMessage);
$box.css('display', 'none');
});
$box.append($select);
$('body').append($box);
}
static inject($event) {
const $editArea = $($event.currentTarget);
const $box = $('#userSelectionBox');
const $probe = $('<span id="probe"/>');
$editArea.append($probe);
const probePosition = $probe.position();
$probe.remove();
const menuPosition = MentionMenu.getMenuPosition($editArea, probePosition);
const delayInjection = () => {
const name = /@(\S*)$/.exec($editArea.html());
if (!name) {
$box.css('display', 'none');
return;
}
const $scope = angular.element('#chatArea').scope();
const $select = $box.children('select');
$select.html('');
$scope.currentContact.MemberList.map(m => {
if (!MentionMenu.isValidNameHint(name, m.NickName)) return;
const $option = MentionMenu.generateOptionFromMember($scope, m);
if ($option) $select.append($option);
});
const membersCount = Math.min($select.children().length, Common.MENTION_MENU_OPTION_DEFAULT_NUM);
if (membersCount > 0) {
$select.val('');
$box.css({
display: 'block',
height: `${(membersCount + 1) * Common.MENTION_MENU_OPTION_HEIGHT}px`,
});
if (name[1].length === 0) {
$box.css({
left: `${menuPosition.left}px`,
bottom: `${menuPosition.bottom}px`,
});
}
$select.css({
height: `${membersCount * Common.MENTION_MENU_OPTION_HEIGHT}px`,
});
$box.focus();
} else {
$box.css('display', 'none');
}
};
setTimeout(delayInjection, 0);
}
static getMenuPosition($editArea, probePosition) {
const menuPosition = {};
const mentionMenuRightBoundX = probePosition.left + Common.MENTION_MENU_WIDTH + Common.MENTION_MENU_OFFSET_X;
if (!probePosition.left) {
menuPosition.left = Common.MENTION_MENU_INITIAL_X + Common.MENTION_MENU_OFFSET_X;
} else if (mentionMenuRightBoundX > $editArea.width()) {
menuPosition.left = (Common.MENTION_MENU_INITIAL_X + $editArea.width()) - Common.MENTION_MENU_WIDTH;
} else {
menuPosition.left = probePosition.left + Common.MENTION_MENU_INITIAL_X;
}
menuPosition.bottom = (Common.MENTION_MENU_INITIAL_Y - probePosition.top) + Common.MENTION_MENU_OFFSET_Y;
return menuPosition;
}
static isValidNameHint(nameHint, userName) {
const pinyinRaw = pinyin(userName, {
style: pinyin.STYLE_FIRST_LETTER,
});
let pinyinName = '';
for (const py of pinyinRaw) {
if (py[0] && py[0] !== ' ') {
pinyinName += py[0];
}
}
const nameRe = new RegExp(nameHint[1], 'ig');
return nameRe.test(userName) || nameRe.test(pinyinName);
}
static generateOptionFromMember($scope, member) {
const displayName = `${member.NickName}`;
let actualName = displayName;
if (member.DisplayName.length > 0) {
actualName = member.DisplayName;
} else {
const userContact = $scope.getUserContact(member.UserName);
if (!userContact) return null;
if (userContact.NickName.length > 0) {
actualName = userContact.NickName;
}
}
const $option = $('<option/>');
$option.val(actualName);
$option.html(displayName);
return $option;
}
}
module.exports = MentionMenu;