eddie32的KFOL表情插件的魔改分支
稳定版下载(基于喵拉分支):
度盘下载 (已过时,待更新)
测试版下载(基于eddie32最新5.2.1):
稳定版代码复制
// ==UserScript==
// @name 绯月表情增强插件*改
// @namespace https://github.com/HazukiKaguya/KFOL_Stickers
// @version 0.0.6
// @author HazukiKaguya
// @description KF论坛专用的回复表情,插图扩展插件,在发帖时快速输入自定义表情和论坛BBCODE
// @icon https://sticker.inari.site/favicon.ico
// @homepage https://mistakey.top/KFStickers
// @include http*://*2dkf.com/*
// @include http*://*9moe.com/*
// @include https://*kforz.com/*
// @include https://*kfmax.com/*
// @include http*://*kfgal.com/*
// @include https://*miaola.info/*
// @copyright 2020-2021, Hazukikaguya
// @grant none
// @license MIT
// @run-at document-end
// @updateURL https://github.com/HazukiKaguya/KFOL_Stickers/raw/master/es6_KfStickers.user.js
// ==/UserScript==
//eddie32大佬的KFOL助手的表情插件的分支,目前基于5.1.3版本的喵拉分支 @copyright 2014-2019, eddie32 https://greasyfork.org/users/5415
//0.0.6 表情贴纸旧域名替换为新域名的功能现在仅对<img>进行操作,避免因为修改innerHTML造成事件绑定失效
//0.0.5 更改表情贴纸域名,增加表情贴纸旧域名替换为新域名的功能
//历史更新:0.0.4 url添加kfmax,优化注释;0.0.3 贴纸更新贴吧,微博等;0.0.2 贴纸更新eddie32佬的伪中国语和流行(直接使用eddie32源);0.0.1 替换失效贴纸,常用替换为小日向雪花,bilibili替换为林大B
'use strict';
// 版本号
const version = '0.0.6';
// 网站是否为KfMobile
const isKfMobile = typeof Info !== 'undefined' && typeof Info.imgPath !== 'undefined';
// 表情贴纸旧域名替换为新域名
var x = document.getElementsByTagName("img");
var i;
for (i = 0; i < x.length; i++) {
x[i].src=x[i].src.replace(/mistake.tech\/emote/g, "sticker.inari.site");
x[i].src=x[i].src.replace(/http:\/\/o6smnd6uw.bkt.clouddn.com\/xds3\/akari/g, "https://sticker.inari.site/akarin/akarin");//实验性功能,此储存桶地址的表情贴纸很可能和修复后的表情贴纸并不能一一对应。
}
// 灰企鹅
const KfSmileList = [];
const KfSmileCodeList = [];
let kfImgPath = typeof imgpath !== 'undefined' ? imgpath : '';
if (isKfMobile) kfImgPath = Info.imgPath;
for (let i = 1; i < 49; i++) {
KfSmileList.push(`/${kfImgPath}/post/smile/em/em${(i) > 9 ? i : ('0' + i)}.gif`);
KfSmileCodeList.push(`[s:${i + 9}]`);
}
// 小日向雪花
const YukikaSmileList = [];
for (let i = 1; i < 7; i++) {
YukikaSmileList.push(`https://sticker.inari.site/yukika/${i}.jpg`);
}
for (let i = 21; i < 24; i++) {
YukikaSmileList.push(`https://sticker.inari.site/yukika/${i}.jpg`);
}
// AC娘表情
const AcSmileList = [];
for (let i = 1; i < 55; i++) {
AcSmileList.push(`https://sticker.inari.site/acfun/1/${i}.png`);
}
for (let i = 1001; i < 1041; i++) {
AcSmileList.push(`https://sticker.inari.site/acfun/2/${i}.png`);
}
for (let i = 2001; i < 2056; i++) {
AcSmileList.push(`https://sticker.inari.site/acfun/3/${i}.png`);
}
// 百度贴吧
const BaiduSmileList = [];
for(let i = 1; i < 10; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/face/i_f0${i}.png`);
}
for(let i = 10; i < 56; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/face/i_f${i}.png`);
}
for(let i = 1; i < 10; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/ali/ali_00${i}.gif`);
}
for(let i = 10; i < 71; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/ali/ali_0${i}.gif`);
}
// 微博
const WeiboSmileList = [];
for (let i = 0; i < 101; i++) {
WeiboSmileList.push(`https://sticker.inari.site/weibo/${i}.png`);
}
// 东方
const TouhouSmileList = [];
for (let i = 1; i < 46; i++) {
TouhouSmileList.push(`https://sticker.inari.site/touhou/reimu/${i}.jpg`);
}
// 阿卡林 from 摇曳百合
const AkarinSmileList = [];
for (let i = 1; i < 21; i++) {
AkarinSmileList.push(`https://sticker.inari.site/akarin/2/akarin (${i}).gif`);
}
for (let i = 1; i < 72; i++) {
AkarinSmileList.push(`https://sticker.inari.site/akarin/1/akarin (${i}).png`);
}
// 林大B
const lindaBSmileList = [];
for (let i = 1; i < 52; i++) {
lindaBSmileList.push(`https://sticker.inari.site/lindaB/lindaB (${i}).jpg`);
}
// lovelive表情
const LoveliveSmallSmileList = [];
for (let i = 1; i < 42; i++) {
LoveliveSmallSmileList.push(`https://sticker.inari.site/lovelive/2/ll (${i}).png`);
}
for (let i = 0; i < 38; i++) {
LoveliveSmallSmileList.push(`https://sticker.inari.site/lovelive/4/ll (${i}).jpg`);
}
// 少女歌剧
const RevstarSmileList = [];
for (let i = 1; i < 41; i++) {
RevstarSmileList.push(`https://sticker.inari.site/revstar/revstar (${i}).png`);
}
// BanG Dream
const BandoriSmileList = [];
for (let i = 1; i < 41; i++) {
BandoriSmileList.push(`https://sticker.inari.site/bangdream/bangdream (${i}).png`);
}
// 伪中国语(eddie32)
const FakeCHSSmileList = [];
for (let i = 49; i < 83; i++) {
FakeCHSSmileList.push(`https://ecs32.top/emotions/selected/2-20190811/sticker (${i}).png`);
}
// 流行(eddie32)
const PopularSmileList = [];
for (let i = 1; i < 48; i++) {
PopularSmileList.push(`https://ecs32.top/emotions/selected/1-20190811/sticker (${i}).png`);
}
/**
* 表情菜单
*/
const MenuList = {
KfSmile: {datatype: 'imageLink', title: 'KF自带', addr: KfSmileList, ref: KfSmileCodeList},
Shortcut: {
datatype: 'plain',
title: '快捷',
addr: [
'[sell=100][/sell]', '[quote][/quote]', '[hide=100][/hide]', '[code][/code]', '[strike][/strike]', '[fly][/fly]',
'[color=#00FF00][/color]', '[b][/b]', '[u][/u]', '[i][/i]', '[hr]', '[backcolor=][/backcolor]', '[url=][/url]', '[img][/img]'
],
ref: [
'出售贴sell=售价', '引用', '隐藏hide=神秘等级', '插入代码', '删除线', '跑马灯', '文字颜色', '粗体', '下划线', '斜体', '水平线', '背景色', '插入链接', '插入图片'
]
},
Emoji: {
datatype: 'plain',
title: '颜文字',
addr: [
'(●・ 8 ・●)', '╰(๑◕ ▽ ◕๑)╯', '(ゝω・)', '〜♪♪', '(゚Д゚≡゚Д゚)', '(^o^)ノ', '(|||゚Д゚)', '(`ε´ )', '(╬゚д゚)', '(|||゚д゚)', '( ̄∇ ̄)',
'( ̄3 ̄)', '( ̄ー ̄)', '( ̄ .  ̄)', '( ̄︿ ̄)', '( ̄︶ ̄)', '(*´ω`*)', '(・ω・)', '(⌒▽⌒)', '( ̄▽ ̄)', '(=・ω・=)', '(`・ω・´)',
'(〜 ̄△ ̄)〜', '(・∀・)', '(°∀°)ノ', '( ̄3 ̄)', '╮( ̄▽ ̄)╭', '( ´_ゝ`)', 'のヮの', '(ノ< ๑)诶嘿☆~', '(<_<)', '(>_>)',
'(;¬_¬)', '(▔□▔)/', '(゚Д゚≡゚д゚)!?', 'Σ(゚д゚;)', 'Σ(  ̄□ ̄||)', '(´;ω;`)', '(/TДT)/', '(^・ω・^ )', '(。・ω・。)', '(● ̄(エ) ̄●)',
'ε=ε=(ノ≧∇≦)ノ', '(´・_・`)', '(-_-#)', '( ̄へ ̄)', '( ̄ε(# ̄) Σ', 'ヽ(`Д´)ノ', '(╯°口°)╯(┴—┴', '(#-_-)┯━┯', '_(:3」∠)_', '(笑)',
'(汗)', '(泣)', '(苦笑)', '(´・ω・`)', '(╯°□°)╯︵ ┻━┻', '(╯‵□′)╯︵┻━┻', '( ´ρ`)', '( ゚ω゚)', '(o゚ω゚o)', '( ^ω^)', '(。◕∀◕。)',
'/( ◕‿‿◕ )\\', 'ε٩( º∀º )۶з', '( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)', '(●´3`)~♪', '_(:з」∠)_', 'хорошо!', '\(^o^)/', '(•̅灬•̅ )', '(゚Д゚)',
'まったく、小学生は最高だぜ!!', 'ε=ε=ε=┏(゜ロ゜;)┛', '(;°ほ°)', '⎝≧⏝⏝≦⎠', 'ヽ(✿゚▽゚)ノ', '焔に舞い上がるスパークよ、邪悪な異性交際に、天罰を与え!',
'|•ω•`)'
]
},
Yukika: {datatype: 'image', title: '小日向雪花', addr: YukikaSmileList},
Acfun: {datatype: 'image', title: 'ACFUN', addr: AcSmileList},
Akari: {datatype: 'image', title: 'Akari', addr: AkarinSmileList},
lindaB: {datatype: 'image', title: '林大B', addr: lindaBSmileList},
LoveLive: {datatype: 'image', title: 'LoveLive', addr: LoveliveSmallSmileList},
Revstar: {datatype: 'image', title: '少女歌剧', addr: RevstarSmileList},
Bandori: {datatype: 'image', title: '邦邦', addr: BandoriSmileList},
Touhou: {datatype: 'image', title: '东方', addr: TouhouSmileList},
Baidu: {datatype: 'image', title: '贴吧', addr: BaiduSmileList},
Weibo: {datatype: 'image', title: '微博', addr: WeiboSmileList},
FakeCHS: {datatype: 'image', title: '伪中国语', addr: FakeCHSSmileList},
Popular: {datatype: 'image', title: '流行', addr: PopularSmileList},
};
/**
* 添加BBCode
* @param textArea 文本框
* @param {string} code BBCode
* @param {string} selText 选择文本
*/
const addCode = function (textArea, code, selText = '') {
let startPos = !selText ? (code.indexOf('[img]') > -1 || code.indexOf(']') < 0 ? code.length : code.indexOf(']') + 1) : code.indexOf(selText);
if (typeof textArea.selectionStart !== 'undefined') {
let prePos = textArea.selectionStart;
textArea.value = textArea.value.substring(0, prePos) + code + textArea.value.substring(textArea.selectionEnd);
textArea.selectionStart = prePos + startPos;
textArea.selectionEnd = prePos + startPos + selText.length;
}
else {
textArea.value += code;
}
};
/**
* 显示放大的表情图片
* @param {jQuery} $img 表情图片对象
*/
const showZoomInImage = function ($img) {
if ($img.get(0).naturalWidth <= $img.height()) return;
let offset = $img.offset();
let $zoomIn = $(`<img class="kfe-zoom-in" src="${$img.attr('src')}" alt="[预览图片]">`).appendTo('body');
let windowWidth = $(window).width();
let zoomInWidth = $zoomIn.outerWidth();
let top = offset.top - $zoomIn.outerHeight() - 5;
let left = offset.left + $img.width() / 2 - zoomInWidth / 2;
if (left < 0) left = 0;
else if (left + zoomInWidth > windowWidth) left = windowWidth - zoomInWidth;
$zoomIn.css({top, left});
};
/**
* 获取表情面板的HTML代码
* @param {string} key 菜单关键字
* @returns {string} 表情面板内容
*/
const getSmilePanelHtml = function (key) {
let data = MenuList[key];
if (!data) return '';
let html = '';
for (let i = 0; i < data.addr.length; i++) {
if (data.datatype === 'image') {
html += `<img class="kfe-smile" src="${data.addr[i]}" alt="[表情]">`;
}
else if (data.datatype === 'imageLink') {
let ref = typeof data.ref !== 'undefined' && typeof data.ref[i] !== 'undefined' ? data.ref[i] : '';
html += `<img class="kfe-smile" data-code="${ref}" src="${data.addr[i]}" alt="[表情]">`;
}
else if (data.datatype === 'plain') {
let ref = typeof data.ref !== 'undefined' && typeof data.ref[i] !== 'undefined' ? data.ref[i] : data.addr[i];
html += `<a class="kfe-smile-text" data-code="${data.addr[i]}" href="#">${ref}</a>`;
}
}
return `<div class="kfe-smile-panel" data-key="${key}">${html}</div>`;
};
/**
* 获取子菜单的HTML代码
* @returns {string} 子菜单内容
*/
const getSubMenuHtml = function () {
let html = '';
$.each(MenuList, function (key, data) {
html += `<a class="kfe-sub-menu" data-key="${key}" href="#" title="${data.title}">${data.title}</a>`;
});
return html;
};
/**
* 创建容器
* @param textArea 文本框
*/
const createContainer = function (textArea) {
let $container = $(`
<div class="kfe-container">
<div class="kfe-menu">
<span title="本分支由mistakey维护,目前为eddie32佬插件的喵拉布丁分支的分支" style="cursor: pointer;"><b>:)</b></span>
${getSubMenuHtml()}
<span class="kfe-close-panel">[-]</span>
</div>
</div>
`).insertBefore($(textArea));
$container.on('click', '.kfe-sub-menu', function (e) {
e.preventDefault();
let $this = $(this);
let key = $this.data('key');
if (!key) return;
$container.find('.kfe-sub-menu').removeClass('kfe-sub-menu-active');
$this.addClass('kfe-sub-menu-active');
$container.find('.kfe-smile-panel').hide();
let $panel = $container.find(`.kfe-smile-panel[data-key="${key}"]`);
if ($panel.length > 0) $panel.show();
else $(getSmilePanelHtml(key)).appendTo($container).show();
}).on('click', '.kfe-smile, .kfe-smile-text', function (e) {
e.preventDefault();
let $this = $(this);
let code = $this.data('code');
if (!code) code = `[img]${$this.attr('src')}[/img]`;
addCode(textArea, code);
if (/(Mobile|MIDP)/i.test(navigator.userAgent)) textArea.blur();
else textArea.focus();
}).on('mouseenter', '.kfe-smile', function () {
$('.kfe-zoom-in').remove();
showZoomInImage($(this));
}).on('mouseleave', '.kfe-smile', function () {
$('.kfe-zoom-in').remove();
}).find('.kfe-close-panel').click(function () {
$container.find('.kfe-smile-panel').hide();
});
};
/**
* 添加CSS
*/
const appendCss = function () {
$('head').append(`
<style>
.kfe-container { padding: 5px; vertical-align: middle; font: 12px/1.7em "sans-serif"; }
.kfe-menu { margin-bottom: 5px; }
.kfe-sub-menu { margin: 0 7px; text-decoration: none; border-bottom: 2px solid transparent; }
.kfe-sub-menu:hover, .kfe-sub-menu:focus { text-decoration: none; border-color: deeppink; }
a.kfe-sub-menu-active { color: black }
.kfe-smile-panel { display: none; height: 120px; padding: 5px 3px; overflow-y: auto; border-top: 1px solid #ddd; }
.kfe-smile-panel[data-key="Shortcut"] { height: auto; }
.kfe-smile { display: inline-block; max-width: 60px; max-height: 60px; cursor: pointer; }
.kfe-smile-text { display: inline-block; padding: 3px 5px; }
.kfe-smile-text:hover { color: #fff !important; background-color: #2b2b2b; text-decoration: none; }
.kfe-close-panel { cursor: pointer; }
.kfe-zoom-in {
position: absolute; max-width: 150px; max-height: 150px; background-color: #fcfcfc; border: 3px solid rgba(242, 242, 242, 0.6);
border-radius: 2px; box-shadow: 0 0 3px rgb(102, 102, 102);
}
</style>
`);
if (isKfMobile) {
$('head').append(`
<style>
#readPage .kfe-container, #writeMessagePage .kfe-container { margin-top: -10px; }
.kfe-menu { white-space: nowrap; overflow-x: auto; }
</style>
`);
}
};
/**
* 初始化
*/
const init = function () {
let $textAreas = $('textarea');
if (!$textAreas.length) return;
appendCss();
$textAreas.each(function () {
createContainer(this);
});
};
init();
// ==UserScript==
// @name 绯月表情增强插件*改
// @namespace https://github.com/HazukiKaguya/KFOL_Stickers
// @version 0.0.4
// @author HazukiKaguya
// @description KF论坛专用的回复表情,插图扩展插件,在发帖时快速输入自定义表情和论坛BBCODE
// @icon https://mistake.tech/emote/favicon.ico
// @homepage https://mistakey.top/KFStickers
// @include http*://*2dkf.com/*
// @include http*://*9moe.com/*
// @include https://*kforz.com/*
// @include https://*kfmax.com/*
// @include http*://*kfgal.com/*
// @include https://*miaola.info/*
// @copyright 2020-2021, Hazukikaguya
// @grant none
// @license MIT
// @run-at document-end
// @updateURL https://github.com/HazukiKaguya/KFOL_Stickers/raw/master/es6_KfStickers.user.js
// ==/UserScript==
'use strict';
//eddie32大佬的KFOL助手的表情插件的分支,目前基于5.1.3.x版本 @copyright 2014-2019, eddie32 https://greasyfork.org/users/5415
//0.0.4 添加了kfmax站,优化了脚本相关信息
//0.0.3 表情更新了百度贴吧,新浪微博等
//0.0.2 表情更新了eddie32最新版的伪中国语和流行(直接使用了eddie32大佬的图片网址)
//0.0.1 替换了失效表情,常用替换为自截小日向雪花表情包,bilibili替换为林大B
// 版本号
const version = '0.0.4';
// 网站是否为KfMobile
const isKfMobile = typeof Info !== 'undefined' && typeof Info.imgPath !== 'undefined';
// 灰企鹅
const KfSmileList = [];
const KfSmileCodeList = [];
let kfImgPath = typeof imgpath !== 'undefined' ? imgpath : '';
if (isKfMobile) kfImgPath = Info.imgPath;
for (let i = 1; i < 49; i++) {
KfSmileList.push(`/${kfImgPath}/post/smile/em/em${(i) > 9 ? i : ('0' + i)}.gif`);
KfSmileCodeList.push(`[s:${i + 9}]`);
}
// 小日向雪花
const YukikaSmileList = [];
for (let i = 1; i < 7; i++) {
YukikaSmileList.push(`https://mistake.tech/emote/yukika/${i}.jpg`);
}
for (let i = 21; i < 24; i++) {
YukikaSmileList.push(`https://mistake.tech/emote/yukika/${i}.jpg`);
}
// AC娘表情
const AcSmileList = [];
for (let i = 1; i < 55; i++) {
AcSmileList.push(`https://mistake.tech/emote/acfun/1/${i}.png`);
}
for (let i = 1001; i < 1041; i++) {
AcSmileList.push(`https://mistake.tech/emote/acfun/2/${i}.png`);
}
for (let i = 2001; i < 2056; i++) {
AcSmileList.push(`https://mistake.tech/emote/acfun/3/${i}.png`);
}
// 百度贴吧
const BaiduSmileList = [];
for(let i = 1; i < 10; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/face/i_f0${i}.png`);
}
for(let i = 10; i < 56; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/face/i_f${i}.png`);
}
for(let i = 1; i < 10; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/ali/ali_00${i}.gif`);
}
for(let i = 10; i < 71; i++) {
BaiduSmileList.push(`http://tb2.bdstatic.com/tb/editor/images/ali/ali_0${i}.gif`);
}
// 微博
const WeiboSmileList = [];
for (let i = 0; i < 101; i++) {
WeiboSmileList.push(`https://mistake.tech/emote/weibo/${i}.png`);
}
// 东方
const TouhouSmileList = [];
for (let i = 1; i < 46; i++) {
TouhouSmileList.push(`https://mistake.tech/emote/touhou/reimu/${i}.jpg`);
}
// 阿卡林 from 摇曳百合
const AkarinSmileList = [];
for (let i = 1; i < 21; i++) {
AkarinSmileList.push(`https://mistake.tech/emote/akarin/2/akarin (${i}).gif`);
}
for (let i = 1; i < 72; i++) {
AkarinSmileList.push(`https://mistake.tech/emote/akarin/1/akarin (${i}).png`);
}
// 林大B
const lindaBSmileList = [];
for (let i = 1; i < 52; i++) {
lindaBSmileList.push(`https://mistake.tech/emote/lindaB/lindaB (${i}).jpg`);
}
// lovelive表情
const LoveliveSmallSmileList = [];
for (let i = 1; i < 42; i++) {
LoveliveSmallSmileList.push(`https://mistake.tech/emote/lovelive/2/ll (${i}).png`);
}
for (let i = 0; i < 38; i++) {
LoveliveSmallSmileList.push(`https://mistake.tech/emote/lovelive/4/ll (${i}).jpg`);
}
// 少女歌剧
const RevstarSmileList = [];
for (let i = 1; i < 41; i++) {
RevstarSmileList.push(`https://mistake.tech/emote/revstar/revstar (${i}).png`);
}
// BanG Dream
const BandoriSmileList = [];
for (let i = 1; i < 41; i++) {
BandoriSmileList.push(`https://mistake.tech/emote/bangdream/bangdream (${i}).png`);
}
// 伪中国语(eddie32)
const FakeCHSSmileList = [];
for (let i = 1; i < 83; i++) {
FakeCHSSmileList.push(`https://ecs32.top/emotions/selected/2-20190811/sticker (${i}).png`);
}
// 流行(eddie32)
const PopularSmileList = [];
for (let i = 1; i < 48; i++) {
PopularSmileList.push(`https://ecs32.top/emotions/selected/1-20190811/sticker (${i}).png`);
}
/**
* 表情菜单
*/
const MenuList = {
KfSmile: {datatype: 'imageLink', title: 'KF自带', addr: KfSmileList, ref: KfSmileCodeList},
Shortcut: {
datatype: 'plain',
title: '快捷',
addr: [
'[sell=100][/sell]', '[quote][/quote]', '[hide=100][/hide]', '[code][/code]', '[strike][/strike]', '[fly][/fly]',
'[color=#00FF00][/color]', '[b][/b]', '[u][/u]', '[i][/i]', '[hr]', '[backcolor=][/backcolor]', '[url=][/url]', '[img][/img]'
],
ref: [
'出售贴sell=售价', '引用', '隐藏hide=神秘等级', '插入代码', '删除线', '跑马灯', '文字颜色', '粗体', '下划线', '斜体', '水平线', '背景色', '插入链接', '插入图片'
]
},
Emoji: {
datatype: 'plain',
title: '颜文字',
addr: [
'(●・ 8 ・●)', '╰(๑◕ ▽ ◕๑)╯', '(ゝω・)', '〜♪♪', '(゚Д゚≡゚Д゚)', '(^o^)ノ', '(|||゚Д゚)', '(`ε´ )', '(╬゚д゚)', '(|||゚д゚)', '( ̄∇ ̄)',
'( ̄3 ̄)', '( ̄ー ̄)', '( ̄ .  ̄)', '( ̄︿ ̄)', '( ̄︶ ̄)', '(*´ω`*)', '(・ω・)', '(⌒▽⌒)', '( ̄▽ ̄)', '(=・ω・=)', '(`・ω・´)',
'(〜 ̄△ ̄)〜', '(・∀・)', '(°∀°)ノ', '( ̄3 ̄)', '╮( ̄▽ ̄)╭', '( ´_ゝ`)', 'のヮの', '(ノ< ๑)诶嘿☆~', '(<_<)', '(>_>)',
'(;¬_¬)', '(▔□▔)/', '(゚Д゚≡゚д゚)!?', 'Σ(゚д゚;)', 'Σ(  ̄□ ̄||)', '(´;ω;`)', '(/TДT)/', '(^・ω・^ )', '(。・ω・。)', '(● ̄(エ) ̄●)',
'ε=ε=(ノ≧∇≦)ノ', '(´・_・`)', '(-_-#)', '( ̄へ ̄)', '( ̄ε(# ̄) Σ', 'ヽ(`Д´)ノ', '(╯°口°)╯(┴—┴', '(#-_-)┯━┯', '_(:3」∠)_', '(笑)',
'(汗)', '(泣)', '(苦笑)', '(´・ω・`)', '(╯°□°)╯︵ ┻━┻', '(╯‵□′)╯︵┻━┻', '( ´ρ`)', '( ゚ω゚)', '(o゚ω゚o)', '( ^ω^)', '(。◕∀◕。)',
'/( ◕‿‿◕ )\\', 'ε٩( º∀º )۶з', '( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)', '(●´3`)~♪', '_(:з」∠)_', 'хорошо!', '\(^o^)/', '(•̅灬•̅ )', '(゚Д゚)',
'まったく、小学生は最高だぜ!!', 'ε=ε=ε=┏(゜ロ゜;)┛', '(;°ほ°)', '⎝≧⏝⏝≦⎠', 'ヽ(✿゚▽゚)ノ', '焔に舞い上がるスパークよ、邪悪な異性交際に、天罰を与え!',
'|•ω•`)'
]
},
Yukika: {datatype: 'image', title: '小日向雪花', addr: YukikaSmileList},
Acfun: {datatype: 'image', title: 'ACFUN', addr: AcSmileList},
Akari: {datatype: 'image', title: 'Akari', addr: AkarinSmileList},
lindaB: {datatype: 'image', title: '林大B', addr: lindaBSmileList},
LoveLive: {datatype: 'image', title: 'LoveLive', addr: LoveliveSmallSmileList},
Revstar: {datatype: 'image', title: '少女歌剧', addr: RevstarSmileList},
Bandori: {datatype: 'image', title: '邦邦', addr: BandoriSmileList},
Touhou: {datatype: 'image', title: '东方', addr: TouhouSmileList},
Baidu: {datatype: 'image', title: '贴吧', addr: BaiduSmileList},
Weibo: {datatype: 'image', title: '微博', addr: WeiboSmileList},
FakeCHS: {datatype: 'image', title: '伪中国语', addr: FakeCHSSmileList},
Popular: {datatype: 'image', title: '流行', addr: PopularSmileList},
};
/**
* 添加BBCode
* @param textArea 文本框
* @param {string} code BBCode
* @param {string} selText 选择文本
*/
const addCode = function (textArea, code, selText = '') {
let startPos = !selText ? (code.indexOf('[img]') > -1 || code.indexOf(']') < 0 ? code.length : code.indexOf(']') + 1) : code.indexOf(selText);
if (typeof textArea.selectionStart !== 'undefined') {
let prePos = textArea.selectionStart;
textArea.value = textArea.value.substring(0, prePos) + code + textArea.value.substring(textArea.selectionEnd);
textArea.selectionStart = prePos + startPos;
textArea.selectionEnd = prePos + startPos + selText.length;
}
else {
textArea.value += code;
}
};
/**
* 显示放大的表情图片
* @param {jQuery} $img 表情图片对象
*/
const showZoomInImage = function ($img) {
if ($img.get(0).naturalWidth <= $img.height()) return;
let offset = $img.offset();
let $zoomIn = $(`<img class="kfe-zoom-in" src="${$img.attr('src')}" alt="[预览图片]">`).appendTo('body');
let windowWidth = $(window).width();
let zoomInWidth = $zoomIn.outerWidth();
let top = offset.top - $zoomIn.outerHeight() - 5;
let left = offset.left + $img.width() / 2 - zoomInWidth / 2;
if (left < 0) left = 0;
else if (left + zoomInWidth > windowWidth) left = windowWidth - zoomInWidth;
$zoomIn.css({top, left});
};
/**
* 获取表情面板的HTML代码
* @param {string} key 菜单关键字
* @returns {string} 表情面板内容
*/
const getSmilePanelHtml = function (key) {
let data = MenuList[key];
if (!data) return '';
let html = '';
for (let i = 0; i < data.addr.length; i++) {
if (data.datatype === 'image') {
html += `<img class="kfe-smile" src="${data.addr[i]}" alt="[表情]">`;
}
else if (data.datatype === 'imageLink') {
let ref = typeof data.ref !== 'undefined' && typeof data.ref[i] !== 'undefined' ? data.ref[i] : '';
html += `<img class="kfe-smile" data-code="${ref}" src="${data.addr[i]}" alt="[表情]">`;
}
else if (data.datatype === 'plain') {
let ref = typeof data.ref !== 'undefined' && typeof data.ref[i] !== 'undefined' ? data.ref[i] : data.addr[i];
html += `<a class="kfe-smile-text" data-code="${data.addr[i]}" href="#">${ref}</a>`;
}
}
return `<div class="kfe-smile-panel" data-key="${key}">${html}</div>`;
};
/**
* 获取子菜单的HTML代码
* @returns {string} 子菜单内容
*/
const getSubMenuHtml = function () {
let html = '';
$.each(MenuList, function (key, data) {
html += `<a class="kfe-sub-menu" data-key="${key}" href="#" title="${data.title}">${data.title}</a>`;
});
return html;
};
/**
* 创建容器
* @param textArea 文本框
*/
const createContainer = function (textArea) {
let $container = $(`
<div class="kfe-container">
<div class="kfe-menu">
<span title="made by eddie32 version ${version}; modified by 喵拉布丁" style="cursor: pointer;"><b>囧⑨</b></span>
${getSubMenuHtml()}
<span class="kfe-close-panel">[-]</span>
</div>
</div>
`).insertBefore($(textArea));
$container.on('click', '.kfe-sub-menu', function (e) {
e.preventDefault();
let $this = $(this);
let key = $this.data('key');
if (!key) return;
$container.find('.kfe-sub-menu').removeClass('kfe-sub-menu-active');
$this.addClass('kfe-sub-menu-active');
$container.find('.kfe-smile-panel').hide();
let $panel = $container.find(`.kfe-smile-panel[data-key="${key}"]`);
if ($panel.length > 0) $panel.show();
else $(getSmilePanelHtml(key)).appendTo($container).show();
}).on('click', '.kfe-smile, .kfe-smile-text', function (e) {
e.preventDefault();
let $this = $(this);
let code = $this.data('code');
if (!code) code = `[img]${$this.attr('src')}[/img]`;
addCode(textArea, code);
if (/(Mobile|MIDP)/i.test(navigator.userAgent)) textArea.blur();
else textArea.focus();
}).on('mouseenter', '.kfe-smile', function () {
$('.kfe-zoom-in').remove();
showZoomInImage($(this));
}).on('mouseleave', '.kfe-smile', function () {
$('.kfe-zoom-in').remove();
}).find('.kfe-close-panel').click(function () {
$container.find('.kfe-smile-panel').hide();
});
};
/**
* 添加CSS
*/
const appendCss = function () {
$('head').append(`
<style>
.kfe-container { padding: 5px; vertical-align: middle; font: 12px/1.7em "sans-serif"; }
.kfe-menu { margin-bottom: 5px; }
.kfe-sub-menu { margin: 0 7px; text-decoration: none; border-bottom: 2px solid transparent; }
.kfe-sub-menu:hover, .kfe-sub-menu:focus { text-decoration: none; border-color: deeppink; }
a.kfe-sub-menu-active { color: black }
.kfe-smile-panel { display: none; height: 120px; padding: 5px 3px; overflow-y: auto; border-top: 1px solid #ddd; }
.kfe-smile-panel[data-key="Shortcut"] { height: auto; }
.kfe-smile { display: inline-block; max-width: 60px; max-height: 60px; cursor: pointer; }
.kfe-smile-text { display: inline-block; padding: 3px 5px; }
.kfe-smile-text:hover { color: #fff !important; background-color: #2b2b2b; text-decoration: none; }
.kfe-close-panel { cursor: pointer; }
.kfe-zoom-in {
position: absolute; max-width: 150px; max-height: 150px; background-color: #fcfcfc; border: 3px solid rgba(242, 242, 242, 0.6);
border-radius: 2px; box-shadow: 0 0 3px rgb(102, 102, 102);
}
</style>
`);
if (isKfMobile) {
$('head').append(`
<style>
#readPage .kfe-container, #writeMessagePage .kfe-container { margin-top: -10px; }
.kfe-menu { white-space: nowrap; overflow-x: auto; }
</style>
`);
}
};
/**
* 初始化
*/
const init = function () {
let $textAreas = $('textarea');
if (!$textAreas.length) return;
appendCss();
$textAreas.each(function () {
createContainer(this);
});
};
init();