700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 仿QQ空间的评论编辑器实现

仿QQ空间的评论编辑器实现

时间:2022-07-22 01:37:44

相关推荐

仿QQ空间的评论编辑器实现

为了给社区加上同样的功能,花了一点时间实现了QQ空间的评论框,有想学习编辑器的实现原理的朋友,可以认真阅读代码。需要包含jQuery。

这个编辑框可以在任意位置输入@时,弹出@人名的补全内容,并且只有@正确的人名,才会给服务器端生成数据。删除时,也是一次删掉人名,不会发生@joson 退格一下变成 @joso 这种。 可以给用户不会出错的愉快体验。

var commentEditor = function(id){ this.editorContainer = $('#'+id); this.editorPlaceholder = $('<div class="comment_editor_placeholder"></div>'); this.editor = $('<div class="comment_editor_main"></div>'); this.currentEl = null; this.currentOffset = null; this.offsetLeft = 0; this.editorStatus = 0; this.op = { placeholder : '在这里输入评论', padding : 5 }; this.editorPlaceholder.css({ width : this.editorContainer.width() - this.op.padding*2, height : this.editorContainer.height() - this.op.padding*2, position:'relative' }); this.editor.css({ overflow : 'auto', width : this.editorContainer.width() - this.op.padding*2, height : this.editorContainer.height() - this.op.padding*2, position:'relative', marginTop : -this.editorContainer.height() }); this.editor.attr('contenteditable',true); this.editorContainer.append(this.editorPlaceholder); this.editorContainer.append(this.editor); this.editorPlaceholder.text(this.op.placeholder); this.editorContainer.addClass('comment_editor'); if( this.getData() != '' ){ this.editorPlaceholder.text(''); } this.list = new commentEditor.downList(this); this._init(); this.listenAt();};

commentEditor.prototype = { _init : function(){ var self = this; this.listenChange(); $(document).bind('click',function(){ self.list.hide(); if( self.editorStatus == 1 ){ self.editorStatus = 0; self.editor.trigger('editor.close');} }); this.editor.bind('click',function(e){ e.stopPropagation(); }); this.editor.bind('editor.change',function(){ self.listenCursor(); }); this.editor.bind('mouseup',function(){ self.listenCursor(); }); this.editor.bind('focus',function(){ self.editorPlaceholder.text(''); if( self.editorStatus == 0 ){ self.editorStatus = 1; self.editor.trigger('editor.open');} }); this.editor.bind('blur',function(){ if( self.getData() == '' ){ self.editorPlaceholder.text(self.op.placeholder); }}); }, listenAt : function(){ var self = this,timeout=null,currentname=null; this.editor.bind('editor.at',function(e,data){ self.offsetLeft = String(data).length + 1 ; clearTimeout(timeout); if( currentname == data ){ self.list.show(); return ; } currentname = data; timeout = setTimeout(function(){$.post('/test_comment_exe.php',{action:'at',name:data},function(data){if( data != '' ){ self.list.show(); self.list.setData(data,function(data){ var op = $('<div><a href="javascript:">\ <div style="float:left;width:30px;height:30px;"><img src="/profile_image/'+data.ID+'/30" width="30" height="30" /></div>\ <div style="float:left; margin-left:10px;">'+data.user_nicename+'</div></a>\ </div>'); op.bind('click',function(){ self.insertHtml('<button contenteditable="false" class="comment_editor_element">@'+data.user_nicename+'</button>',true); self.list.hide(); }); return op; });}else{ self.list.hide();}}); },100); }); this.editor.bind('editor.at_close',function(){ clearTimeout(timeout); self.list.hide(); }); }, listenChange : function(){ var self = this,oldText=this.editor.html(); this.editor.bind('keyup',function(e){ var newText = self.editor.html(); if( newText != oldText ){ oldText = newText; self.editor.trigger('editor.change'); } }); }, getSelectionObject : function(){ if (window.getSelection){ // mozilla FF return window.getSelection(); }else if (document.getSelection){ return document.getSelection(); }else if (document.selection){ //IE return document.selection.createRange().text; } }, getRangeObject : function(selectionObject) { return selectionObject.getRangeAt(0); }, listenCursor : function(){ var userSelection = this.getSelectionObject(); if( !userSelection.anchorNode.data || userSelection.type == 'None' || userSelection.type == 'Range' ){ this.editor.trigger('editor.at_close'); return ; } this.currentOffset = userSelection.anchorOffset; this.currentEl = userSelection.anchorNode; var prevText = userSelection.anchorNode.data.substring( 0, userSelection.anchorOffset ); var lastDot = prevText.lastIndexOf('@'); if( lastDot != -1 ){ prevText = prevText.substring(lastDot); if( !prevText.match(/\s/) ){ this.editor.trigger('editor.at',[ prevText.substring(1)]); return ;}else if( prevText.match(/^[^\s]+\s$/) ){ this.editor.trigger('editor.at_apply',[prevText.substring(1,prevText.length-1)]); } } this.editor.trigger('editor.at_close'); }, insertHtml : function(html,lastspace){ var offsetLeft = this.offsetLeft; this.offsetLeft = 0; if( this.currentEl != null && this.currentOffset != null ){ this.editor.focus(); var userSelection = this.getSelectionObject(); var range = this.getRangeObject(userSelection); var el = $(html); var el_dom = el.get(0); if( !el_dom ){ el_dom = document.createTextNode(html); } range.setStart(this.currentEl,this.currentOffset - offsetLeft ); range.setEnd(this.currentEl,this.currentOffset ); range.deleteContents();range.insertNode( el_dom ); range.setStartAfter( el_dom, 0 ); range.setEndAfter( el_dom , 0 ); if(lastspace){ var space = document.createTextNode('\u00A0'); range.insertNode( space ); range.setStartAfter( space, 0 ); range.setEndAfter( space , 0 ); } if( navigator.userAgent.indexOf('Chrome') != -1 ){ if( el_dom.nextSibling == el_dom.parentNode.lastChild && el_dom.nextSibling.data==''){ range.insertNode($('<br/>').get(0)); } } if( userSelection.setPosition ) userSelection.setPosition(range.startContainer,range.startOffset); else{ var nrange = this.getRangeObject(userSelection); nrange.setStart(range.startContainer,range.startOffset); nrange.setEnd(range.startContainer,range.startOffset); userSelection.removeAllRanges(); userSelection.addRange(nrange); } this.currentOffset = range.startOffset; this.currentEl = range.startContainer;}else{ //console.log( $(html) ); this.editor.html( this.editor.html() + html ); this.editor.focus(); var userSelection = this.getSelectionObject(); var range = this.getRangeObject(userSelection); range.setStartAfter( this.editor.get(0).lastChild, 0 ); range.setEndAfter( this.editor.get(0).lastChild, 0 ); if( userSelection.setPosition ){ userSelection.setPosition(range.startContainer,range.startOffset); }else{ var nrange = this.getRangeObject(userSelection); nrange.setStart(range.startContainer,range.startOffset); nrange.setEnd(range.startContainer,range.startOffset); userSelection.removeAllRanges(); userSelection.addRange(nrange); } this.currentOffset = range.startOffset; this.currentEl = range.startContainer;} }, getData : function(){ return this.editor.html(); }, bind : function(eventName,callback){ this.editor.bind(eventName,callback); }};

commentEditor.downList = function(container){ this.container = container; this.list = $('<div class="comment_editor_list"></div>'); this.list.css({ position:'absolute', width: this.container.editor.width()+this.container.op.padding*2 - 2, top:this.container.editor.offset().top + this.container.editor.height()+this.container.op.padding*2, left:this.container.editor.offset().left }); this.status = 'show'; this.list.hide(); $(document.body).append(this.list); this.list.bind('click',function(e){ e.stopPropagation(); }); };

commentEditor.downList.prototype = { show : function(){ this.status = 'show'; this.list.show(); }, hide : function(){ this.list.hide(); }, setData : function(data,callback){ var self = this; this.list.find('*').remove(); var data = $.parseJSON(data); if(data){ $.each(data,function(i){ if(callback) self.list.append(callback(data[i])); }); } } };

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。