<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<!-- 必须强制指定页面编码为 UTF-8 -->
|
|
<meta charset="utf-8">
|
|
|
|
<!-- Demo 的简要说明,必须要填写 -->
|
|
<meta name="description" content="Kity 实现模拟光标输入">
|
|
|
|
<!-- Demo 的作者,建议填写 -->
|
|
<meta name="author" content="kity@baidu.com">
|
|
|
|
<!-- Demo 的标题,必须填写 -->
|
|
<title>模拟光标</title>
|
|
|
|
<!-- Demo 开发过程中使用 CMD 引入 Kity 源码,方便调试 -->
|
|
<!-- dev start -->
|
|
<!-- 目录型的 Demo 注意修正源码引用路径 -->
|
|
<script src="../dev-lib/sea.js"></script>
|
|
<script>
|
|
// 设置好 kity 源代码目录
|
|
seajs.config( { base: '../src'} );
|
|
// 定义 Demo 模块
|
|
define('demo', function(require) { require('kity'); });
|
|
</script>
|
|
<script>
|
|
// 启动 Demo 模块
|
|
seajs.use('demo');
|
|
</script>
|
|
<!-- dev 版本 示例所需脚本文件 end -->
|
|
|
|
<script src="public/jquery.js"></script>
|
|
<style>
|
|
.editor-container{
|
|
|
|
}
|
|
.receiver{
|
|
position:absolute;
|
|
padding:0;
|
|
margin:0;
|
|
word-wrap:break-word;
|
|
clip:rect(1em 1em 1em 1em);
|
|
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<script>
|
|
var Cursor = kity.createClass('Cursor',{
|
|
base: kity.Line,
|
|
constructor: function(height, color, width) {
|
|
this.callBase();
|
|
this.height = height || 20;
|
|
this.stroke(color || 'blue', width || 1);
|
|
this.setHide();
|
|
this.timer = null;
|
|
},
|
|
setPosition: function(offset) {
|
|
try{
|
|
this.setPoint1(offset.x,offset.y);
|
|
this.setPoint2(offset.x,offset.y + this.height);
|
|
}catch(e){
|
|
debugger
|
|
}
|
|
|
|
return this;
|
|
},
|
|
setHeight:function(height){
|
|
this.height = height;
|
|
},
|
|
setHide:function(){
|
|
clearInterval(this.timer);
|
|
this.setStyle('display','none');
|
|
return this;
|
|
},
|
|
setShowHold : function(){
|
|
clearInterval(this.timer);
|
|
this.setStyle('display','');
|
|
return this;
|
|
},
|
|
setShow:function(){
|
|
clearInterval(this.timer);
|
|
var me = this,
|
|
state = '';
|
|
this.timer = setInterval(function(){
|
|
me.setStyle('display',state);
|
|
state = state ? '' : 'none';
|
|
},300);
|
|
return this;
|
|
},
|
|
setTextShape:function(text){
|
|
if(!text){
|
|
this.text = new kity.Text();
|
|
}else{
|
|
this.text = text;
|
|
}
|
|
return this
|
|
},
|
|
getTextShape:function(){
|
|
return this.text
|
|
},
|
|
setTxtContent : function(text){
|
|
this.text.setContent(text)
|
|
},
|
|
updatePosition:function(index){
|
|
|
|
}
|
|
});
|
|
var Receiver = kity.createClass('Receiver',{
|
|
clear : function(){
|
|
this.$container.html('');
|
|
this.index = 0;
|
|
return this;
|
|
},
|
|
constructor : function(){
|
|
this.$container = $('<div contenteditable="true" class="receiver"></div>');
|
|
this.$container.appendTo(document.body);
|
|
this.$container.on('keydown keypress keyup', $.proxy(this.keyboardEvents,this));
|
|
this.timer = null;
|
|
this.index = 0;
|
|
},
|
|
setPosition : function(textShapeOffset){
|
|
this.$container.css({
|
|
top:textShapeOffset.x,
|
|
left:textShapeOffset.y
|
|
});
|
|
this.textShape.setPosition(textShapeOffset.x, textShapeOffset.y);
|
|
return this;
|
|
},
|
|
setRange : function(range,index){
|
|
|
|
this.index = index || this.index;
|
|
|
|
var text = this.$container[0].firstChild;
|
|
console.log(text)
|
|
console.log(this.index)
|
|
range.setStart(text || this.$container[0], this.index).collapse(true);
|
|
setTimeout(function(){
|
|
range.select()
|
|
});
|
|
return this;
|
|
},
|
|
setTextShape:function(textShape){
|
|
if(!textShape){
|
|
textShape = new kity.Text();
|
|
}
|
|
this.textShape = textShape;
|
|
return this;
|
|
},
|
|
setTextShapeSize:function(size){
|
|
this.textShape.setSize(size);
|
|
return this;
|
|
},
|
|
getTextShapeHeight:function(){
|
|
return this.textShape.getRenderBox().height;
|
|
},
|
|
appendTextShapeToPaper:function(paper){
|
|
paper.addShape(this.textShape);
|
|
return this;
|
|
},
|
|
keyboardEvents : function(e){
|
|
clearTimeout(this.timer);
|
|
var me = this;
|
|
switch(e.type){
|
|
case 'keyup':
|
|
this.textShape.setContent(this.$container.text().replace(/\u200b/g,''));
|
|
this.updateTextData();
|
|
this.updateCursor();
|
|
this.timer = setTimeout(function(){
|
|
me.cursor.setShow()
|
|
},500);
|
|
break;
|
|
case 'keypress':
|
|
case 'keyup':
|
|
}
|
|
},
|
|
updateTextData : function(){
|
|
this.textShape.textData = this.getTextOffsetData();
|
|
this.index = this.index + 1;
|
|
},
|
|
setCursor : function(cursor){
|
|
this.cursor = cursor;
|
|
return this;
|
|
},
|
|
updateCursor : function(){
|
|
this.cursor.setShowHold();
|
|
if(this.index == this.textData.length){
|
|
|
|
this.cursor.setPosition({
|
|
x : this.textData[this.index-1].x + this.textData[this.index-1].width,
|
|
y : this.textData[this.index-1].y
|
|
})
|
|
}else if(this.index == 0){
|
|
this.cursor.setPosition({
|
|
x : this.textShape.getX(),
|
|
y : this.textData.getY()
|
|
})
|
|
}else{
|
|
if(this.index + 1 == this.textData.length){
|
|
var lastChar = this.textData[this.index];
|
|
this.cursor.setPosition({
|
|
x : lastChar.x + lastChar.width,
|
|
y : lastChar.y
|
|
})
|
|
}else{
|
|
this.cursor.setPosition(this.textData[this.index])
|
|
}
|
|
|
|
}
|
|
return this;
|
|
},
|
|
getTextOffsetData:function(){
|
|
var text = this.textShape.getContent();
|
|
this.textData = [];
|
|
// this.textShape.clearContent();
|
|
|
|
for(var i= 0,l = text.length;i<l;i++){
|
|
var box = this.textShape.getExtentOfChar(i);
|
|
this.textData.push({
|
|
x:box.x,
|
|
y:box.y,
|
|
width:box.width,
|
|
height:box.height
|
|
})
|
|
}
|
|
|
|
|
|
return this;
|
|
},
|
|
setCurrentIndex:function(offset){
|
|
var me = this;
|
|
this.getTextOffsetData();
|
|
var hadChanged = false;
|
|
$.each(this.textData,function(i,v){
|
|
if(offset.x >= v.x && offset.x <= v.x + v.width){
|
|
if(offset.x - v.x > v.width/2){
|
|
me.index = i + 1;
|
|
|
|
}else {
|
|
me.index = i
|
|
|
|
}
|
|
hadChanged = true;
|
|
return false;
|
|
}
|
|
})
|
|
return this;
|
|
|
|
},
|
|
setCursorHeight:function(){
|
|
this.cursor.setHeight(this.getTextShapeHeight())
|
|
return this;
|
|
}
|
|
});
|
|
|
|
var Range = kity.createClass('Range',{
|
|
constructor : function(){
|
|
this.nativeRange = document.createRange();
|
|
this.nativeSel = window.getSelection();
|
|
},
|
|
select:function(){
|
|
var start = this.nativeRange.startContainer;
|
|
if(start.nodeType == 1 && start.childNodes.length == 0){
|
|
var char = document.createTextNode('\u200b');
|
|
start.appendChild(char);
|
|
this.nativeRange.setStart(char,1);
|
|
this.nativeRange.collapse(true);
|
|
}
|
|
this.nativeSel.removeAllRanges();
|
|
this.nativeSel.addRange(this.nativeRange);
|
|
return this;
|
|
},
|
|
setStart:function(node,index){
|
|
this.nativeRange.setStart(node,index);
|
|
return this;
|
|
},
|
|
setEnd:function(node,index){
|
|
this.nativeRange.setEnd(node,index);
|
|
return this;
|
|
},
|
|
collapse:function(toStart){
|
|
this.nativeRange.collapse(toStart === true);
|
|
return this;
|
|
},
|
|
insertNode:function(node){
|
|
this.nativeRange.insertNode(node);
|
|
return this;
|
|
}
|
|
});
|
|
|
|
var cursor = new Cursor();
|
|
var receiver = new Receiver();
|
|
var range = new Range();
|
|
|
|
var paper = new kity.Paper(document.body).setHeight(500);
|
|
paper.addShape(cursor)
|
|
.setStyle('border','1px solid #ccc')
|
|
.setStyle('cursor','text')
|
|
.on('click',function(e){
|
|
var originEvent = e.originEvent;
|
|
var position = e.getPosition('top');
|
|
if(e.targetShape.getType() != 'Text'){
|
|
var offset = e.getPosition('top');
|
|
cursor.setShow().setPosition(offset);
|
|
receiver.clear()
|
|
.setTextShape()
|
|
.setTextShapeSize(cursor.height)
|
|
.appendTextShapeToPaper(paper)
|
|
.setPosition(position)
|
|
.setRange(range,0)
|
|
.setCursor(cursor)
|
|
}else{
|
|
receiver.setCursor(cursor)
|
|
.setTextShape(e.targetShape)
|
|
.setCursorHeight()
|
|
.setCurrentIndex(position)
|
|
.updateCursor()
|
|
.setRange(range)
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|