要件
1. @を入力すると、一致する友達メニューが表示されます
2.「@friend」を含むタグにカーソルが入ると、ポップアップメニュー
3. バックスペースを押して削除すると、カーソルの前に「@Friend」を含むタグがある場合、ポップアップメニューが表示されます
4. IE、Firefox と互換性があります。
具体的な方法
要件 1 については、イベントを入力ボックスにバインドすることを考えるのが自然です。ここでは、mouseup ではなく、mousedown をバインドする必要があります。これは、mouseup の場合、event.preventDefault() はキーボードによる @ の入力を防ぐことができないためです。さらに、イベント コールバックで return false を使用しても機能しません。
mousedown イベントをバインドした後、「@friend」を含むカスタム タグを挿入する必要があります。 Sina Weibo の入力ボックスは textarea で構成されていますが、内部でどのように処理されているかは Baidu Tieba を見てみないとわかりません。
ご覧のとおり、Tieba は タグを挿入しています。これは、正規表現を使用したバックグラウンド マッチングに便利です。
特定
vm.check_key=function(e){
var editor=$('editor'),range;
If(e.shiftKey&&e.keyCode==50){
If (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(" @ ");
}else{
document.execCommand("insertHtml", false," @ ");
}
e.preventDefault();
}
};
ここではカーソル位置に挿入する必要があるため、range を使用します。
次にメニューが表示されますが、それをどのように配置するかがポイントです。私のアプローチは非常にくだらないもので、挿入されたスパンにIDを追加し、スパンIDの位置に基づいてメニューを配置します。もっと良い方法があれば、ぜひ教えてください。
特定
関数 at_box_show(at){
var at_pos=avalon($(at)).position();
$('at_box').style.left=at_pos.left 'px';
$('at_box').style.top=at_pos.top 16 'px';
$('at_box').style.display='block';
}
var at_index=0,cur_index=0;
avalon.define('editor', function(vm) {
vm.item_click=function(){
$('at' cur_index).innerHTML="@" this.innerHTML;
$('at_box').style.display='none';
at_index ;
};
vm.check_key=function(e){
var editor=$('editor'),a=getCharacterPrecedingCaret(editor),range;
if(e.shiftKey&&e.keyCode==50){
if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(" @ ");
}その他{
document.execCommand("insertHtml", false," @ ");
}
at_box_show('at' at_index);
cur_index=at_index;
e.preventDefault();
}
};
});
at_show_box 新しく入力されたスパン ID に基づいて、at_box の位置になり、その後メニューが表示されます。cur_index は光が現在位置するスパン ID を示します。ユーザーが変更されたスパンを元に戻すことができるようにこの量を設定します。一方、at_index は連続的に増加します。ここでも量が必要です。
ユーザー ポイント メニュー内の好友名、at_index に好友名を innserHTML で追加します。
上はシフト @ で、次はバックスペース削除です。
复制代码代码如下:
function getTextBeforeCursor(containerEl) {
var先行Char = ""、sel、range、predictiveRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
範囲 = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
precedenceChar = range.cloneContents();
}
} else if ( (sel = document.selection)) {
範囲 = sel.createRange();
先行範囲 = range.duplicate();
PreviousRange.moveToElementText(containerEl);
precedentRange.setEndPoint("EndToStart", range);
precedenceChar =precedingRange.htmlText;
}
先行する文字を返します;
}
getTextBeforeCursor の機能は、光前のコンテンツを取得することです。互換性により、この関数は標準ブラウザ内で光前のすべてのコンテンツの DocumentFragment を取得できますが、つまり、文本 (ノードではない) だけを取得できます。この html 文字列は DocumentFragment に変換できます。avalon では parseHTML を使用して html 文字列をノードに変換できます。jquery で $(html)[0] を使用することもできます。
この関数により、再度 lastChild を使用して、光マークが光マーク前の html の lastChild エリアではなく、この lastChild がスパンであるかを判断できます。
具体的な
var a=getTextBeforeCursor($('editor'));
if(e.keyCode==8){
if(!-[1,]){
var b=avalon.parseHTML(a).lastChild;
}その他{
var b=a.lastChild;
}
if(b.nodeType==1&&b.nodeName=='SPAN'){
var id=b.id;
cur_index=b.id.substring(2);
at_box_show(b.id);
}その他
$('at_box').style.display='none';
}
最後は、マウスアップをここで設定し、マウスダウンを行うと、メニューを表示するためにマウスを再度ポイントする必要があります。上面差分は多くありません。
复制代码代码如下:
vm.check_mouse=function(e){
var editor=$('editor'),a=getTextBeforeCursor(editor);
if(!-[1,]){
var b=avalon.parseHTML(getTextBeforeCursor(editor)).lastChild;
}その他{
var b=a.lastChild;
}
If(b!=null&&b.nodeType==1&&b.nodeName=='SPAN'){
var id=b.id;
cur_index = b.id.substring(2);
at_box_show(b.id);
}else
$('at_box').style.display='none';
};
カーソルがスパン内にある場合は、その ID を取得し、この ID に基づいて at_box を配置し、cur_index をリセットする必要があることに注意してください。
ajax更新メニューに関しては、文字マッチングは行いません
効果
ファイアフォックス
ie8
ie7
ie6
ダウンロード
以上がこの記事で説明した内容のすべてです。皆さんが JavaScript を理解するのに役立つことを願っています。