首页 > 网站 > WEB开发 > 正文

iframe从光标处插入图片(失去焦点后仍然可以在原位置插入)

2024-04-27 14:13:03
字体:
来源:转载
供稿:网友

iframe从光标处插入图片(失去焦点后仍然可以在原位置插入)

转载请注明:TheViperhttp://www.cnblogs.com/TheViper

改进版:更简单的 编辑器从光标处插入图片(失去焦点后仍然可以在原位置插入)

为什么会有这个需求?

当我们需要一个文本输入框(编辑器),它的功能定位介于专门的富文本编辑器和裸(原生)文本框之间。这时,如果用专门富文本编辑器,如kindeditor,ueditor,显的很大材小用,而且这两个的体积都不小,而体积小的富文本编辑器又是针对现代浏览器的。

贴吧发帖和知乎发问题的编辑器就是典型的这种需求

问题的出现

下面是这个问题的呈现,ie8下,知乎编辑器中插入图片

首先将光标移到已经输入文字的任意位置,然后让光标在编辑器中失去焦点。上传图片,最后看到图片并没有在光标最后在编辑器中的位置。

如果没有失去焦点,或者浏览器是现代浏览器,则不存在这个问题。

网上的解决方案

网上有很多方案,但至少到现在,我没有看到一个成功的。一般问题都出在编辑器失去焦点后,不能“智能”的在光标原位置插入图片。

最接近的方案就是很简单的win.document.execCommand("insertImage", '',data);,但这个只能针对现代浏览器。

我的成功解决方案

先看下效果

Firefox

ie8

注意到在kindeditor,ueditor中,都很好的解决了这个问题,那最简单的方法就是从源码中扒出那些代码。ueditor的源码复杂点,多点,就从kindeditor中扒。kindeditor的源码也就5000多行,还没jquery多.

kindeditor里面的思路是每次mouseup,keyup的时候,就重新锁定selection,range.

range的startContainer和endContainer一样,startOffset和endOffset也一样,也就是说创建的range实际上一个里面什么都没有的range,没有选中内容的range当然就是光标了。

self.afterChange(function(e) {    cmd.selection();});........    afterChange : function(fn) {        var self = this, doc = self.doc, body = doc.body;        K(doc).mouseup(fn);        return self;    }

这个就是最精华的地方,其他都没什么好说的,无非就是对selection,range的封装。

扒下来的代码

  1 define('editor', function() {  2     function _extend(child, parent, PRoto) {  3         if (!proto) {  4             proto = parent;  5             parent = null;  6         }  7         var childProto;  8         if (parent) {  9             var fn = function () {}; 10             fn.prototype = parent.prototype; 11             childProto = new fn(); 12             _each(proto, function(key, val) { 13                 childProto[key] = val; 14             }); 15         } else { 16             childProto = proto; 17         } 18         childProto.constructor = child; 19         child.prototype = childProto; 20         child.parent = parent ? parent.prototype : null; 21     } 22     function _iframeDoc(iframe) { 23         return iframe.contentDocument || iframe.contentWindow.document; 24     } 25     var _IERANGE = !window.getSelection; 26     function _updateCollapsed(range) { 27         range.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset); 28         return range; 29     } 30     function _moveToElementText(range, el) { 31         try { 32             range.moveToElementText(el); 33         } catch(e) {} 34     } 35     function _getStartEnd(rng, isStart) { 36         var doc = rng.parentElement().ownerDocument, 37         pointRange = rng.duplicate(); 38         pointRange.collapse(isStart); 39         var parent = pointRange.parentElement(), 40         nodes = parent.childNodes; 41         var startNode = doc, startPos = 0, cmp = -1; 42         var testRange = rng.duplicate(); 43         _moveToElementText(testRange, parent); 44         for (var i = 0, len = nodes.length; i < len; i++) { 45             var node = nodes[i]; 46             cmp = testRange.compareEndPoints('StartToStart', pointRange); 47             if (cmp === 0) { 48                 return {node: node.parentNode, offset: i}; 49             } 50             if (node.nodeType == 3) { 51                 testRange.moveStart('character', node.nodeValue.length); 52                 startPos += node.nodeValue.length; 53             } 54             if (cmp < 0) { 55                 startNode = node; 56             } 57         } 58         testRange = rng.duplicate(); 59         _moveToElementText(testRange, parent); 60         testRange.setEndPoint('StartToEnd', pointRange); 61         startPos -= testRange.text.replace(//r/n|/n|/r/g, '').length; 62         if (cmp > 0 && startNode.nodeType == 3) { 63             var prevNode = startNode.previousSibling; 64             while (prevNode && prevNode.nodeType == 3) { 65                 startPos -= prevNode.nodeValue.length; 66                 prevNode = prevNode.previousSibling; 67             } 68         } 69         return {node: startNode, offset: startPos}; 70     } 71     function _toRange(rng) { 72         var doc, range; 73         if (_IERANGE) { 74             if (rng.item) { 75                 doc = _getDoc(rng.item(0)); 76                 range = new KRange(doc); 77                 range.selectNode(rng.item(0)); 78                 return range; 79             } 80             doc = rng.parentElement().ownerDocument; 81             var start = _getStartEnd(rng, true), 82             end = _getStartEnd(rng, false); 83             range = new KRange(doc); 84             range.setStart(start.node, start.offset); 85             range.setEnd(end.node, end.offset); 86             return range; 87         } 88         var startContainer = rng.startContainer; 89         doc = startContainer.ownerDocument || startContainer; 90         range = new KRange(doc); 91         range.setStart(startContainer, rng.startOffset); 92         range.setEnd(rng.endContainer, rng.endOffset); 93         return range; 94     } 95     function KRange(doc) { 96         this.init(doc); 97     } 98     _extend(KRange,{ 99         init : function(doc) {100             var self = this;101             self.startContainer = doc;102             self.startOffset = 0;103             self.endContainer = doc;104             self.endOffset = 0;105             self.collapsed = true;106             self.doc = doc;107         },108         setStart : function(node, offset) {109             var self = this, doc = self.doc;110             self.startContainer = node;111             self.startOffset = offset;112             if (self.endContainer === doc) {113                 self.endContainer = node;114                 self.endOffset = offset;115             }116             return _updateCollapsed(this);117         },118         setEnd : function(node, offset) {119             var self = this, doc = self.doc;120             self.endContainer = node;121             self.endOffset = offset;122             if (self.startContainer === doc) {123                 self.startContainer = node;124                 self.startOffset = offset;125             }126             return _updateCollapsed(this);127         },128         setStartBefore : function(node) {129             return this.setStart(node.parentNode || this.doc, 0);130         },131         setEndAfter : function(node) {132             return this.setEnd(node.parentNode ||1);133         },134         selectNode : function(node) {135             return this.setStartBefore(node).setEndAfter(node);136         },137         selectNodeContents : function(node) {138             return this.setStart(node, 0).setEnd(node, 0);139         },140         collapse : function(toStart) {141             if (toStart) {142                 return this.setEnd(this.startContainer, this.startOffset);143             }144             return this.setStart(this.endContainer, this.endOffset);145         },146         cloneRange : function() {147             return new KRange(this.doc).setStart(this.startContainer, this.startOffset).setEnd(this.endContainer, this.endOffset);148         },149         toString : function() {150             var rng = this.get(), str = _IERANGE ? rng.text : rng.toString();151             return str.replace(//r/n|/n|/r/g, '');152         },153         insertNode : function(node) {154             var self = this,155             sc = self.startContainer, so = self.startOffset,156             ec = self.endContainer, eo = self.endOffset,157             firstChild, lastChild, c, nodeCount = 1;158             if (sc.nodeType == 1) {159                 c = sc.childNodes
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表