327 rindas
11 KiB

<!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>