Commit e3d55a0f authored by techird's avatar techird

merge multiline select

parents d87b85c6 9f8f1eeb
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
'src/module/select.js', 'src/module/select.js',
'src/module/history.js', 'src/module/history.js',
'src/module/editor.js', 'src/module/editor.js',
'src/module/editor.keyboard.js',
'src/module/editor.range.js', 'src/module/editor.range.js',
'src/module/editor.receiver.js', 'src/module/editor.receiver.js',
'src/module/editor.selection.js', 'src/module/editor.selection.js',
......
Subproject commit f83c5f109addefd4f89ba11b4dfa88c191809e77 Subproject commit fee45f69801839d897e5e6245be93eaefafd615a
describe("editor.range", function () {
var _div = document.createElement('div');
_div.setAttribute('contenteditable', true);
var range = new KM.Minder.Range(_div);
describe("getStartOffset",function(){
_div.innerHTML = 'xxx<br\/><br\/>xxx<br\/>';
it("选区在容器上", function () {
range.startContainer = _div;
range.startOffset = 2;
expect(range.getStartOffset()).toBe(4);
});
it("选区在文本节点上", function () {
range.startContainer = _div.childNodes[3];
range.startOffset = 2;
expect(range.getStartOffset()).toBe(7);
});
});
describe("setStartOffset",function(){
_div.innerHTML = 'sdfsdfsdfsdf<br><br>sdf3<br>23232<br>';
it("选区在容器上", function () {
range.container = _div;
debugger
range.setStartOffset(26);
expect(range.startContainer).toBe(_div);
});
// it("选区在文本节点上", function () {
//
// range.startContainer = _div.childNodes[3];
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(7);
// });
})
});
describe("editor.receiver", function () {
debugger
var _div = window.document.createElement('div');
_div.id ="testDiv";
var km = KM.getMinder('testDiv');
var sel = new KM.Minder.Selection();
var range = new KM.Minder.Range();
var receiver = new KM.Minder.Receiver(this,sel,range);
describe("getStartOffset",function(){
//
// _div.innerHTML = 'xxx<br\/><br\/>xxx<br\/>';
// it("选区在容器上", function () {
//
// range.startContainer = _div;
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(4);
// });
// it("选区在文本节点上", function () {
//
// range.startContainer = _div.childNodes[3];
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(7);
// });
})
});
...@@ -108,6 +108,9 @@ var MinderNode = KityMinder.MinderNode = kity.createClass('MinderNode', { ...@@ -108,6 +108,9 @@ var MinderNode = KityMinder.MinderNode = kity.createClass('MinderNode', {
* @param {String} text 文本数据 * @param {String} text 文本数据
*/ */
setText: function(text) { setText: function(text) {
if(utils.isArray(text)){
text = text.join('\n');
}
return this.setData('text', text); return this.setData('text', text);
}, },
...@@ -115,8 +118,14 @@ var MinderNode = KityMinder.MinderNode = kity.createClass('MinderNode', { ...@@ -115,8 +118,14 @@ var MinderNode = KityMinder.MinderNode = kity.createClass('MinderNode', {
* 获取节点的文本数据 * 获取节点的文本数据
* @return {String} * @return {String}
*/ */
getText: function() { getText: function(str2arr) {
return this.getData('text'); var text = this.getData('text');
if(str2arr){
text = text.split('\n');
}
return text;
}, },
/** /**
......
...@@ -271,8 +271,48 @@ var utils = Utils = KityMinder.Utils = { ...@@ -271,8 +271,48 @@ var utils = Utils = KityMinder.Utils = {
}, },
cloneArr:function(arr){ cloneArr:function(arr){
return [].concat(arr); return [].concat(arr);
},
clearWhitespace:function(str){
return str.replace(/[\u200b\t\r\n]/g, '');
},
getValueByIndex:function(data,index){
var initIndex = 0,result = 0;
utils.each(data,function(i,arr){
if(initIndex + arr.length >= index){
if(index - initIndex == arr.length){
result = {
x: arr[arr.length - 1].x + arr[arr.length - 1].width,
y: arr[arr.length - 1].y
};
}else{
result = arr[index - initIndex];
}
return false;
}else{
initIndex += arr.length + (arr.length == 1 && arr[0].width === 0 ? 0 : 1);
}
});
return result;
},
getNodeIndex:function (node, ignoreTextNode) {
var preNode = node,
i = 0;
while (preNode = preNode.previousSibling) {
if (ignoreTextNode && preNode.nodeType == 3) {
if(preNode.nodeType != preNode.nextSibling.nodeType ){
i++;
}
continue;
}
i++;
}
return i;
} }
}; };
Utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object'], function(i, v) { Utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object'], function(i, v) {
......
...@@ -5,11 +5,15 @@ KityMinder.registerModule('basestylemodule', function() { ...@@ -5,11 +5,15 @@ KityMinder.registerModule('basestylemodule', function() {
return node.getData(name) || node.getStyle(name); return node.getData(name) || node.getStyle(name);
} }
KityMinder.TextRenderer.registerStyleHook(function(node, text) { KityMinder.TextRenderer.registerStyleHook(function(node, textGroup) {
text.setFont({
weight: getNodeDataOrStyle(node, 'font-weight'), textGroup.eachItem(function(index,item){
style: getNodeDataOrStyle(node, 'font-style') item.setFont({
'weight': getNodeDataOrStyle(node,'font-weight'),
'style': getNodeDataOrStyle(node,'font-style')
});
}); });
}); });
return { return {
'commands': { 'commands': {
......
...@@ -5,14 +5,13 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -5,14 +5,13 @@ KityMinder.registerModule('TextEditModule', function() {
var sel = new Minder.Selection(); var sel = new Minder.Selection();
var range = new Minder.Range(); var range = new Minder.Range();
var receiver = new Minder.Receiver(this,sel,range); var receiver = new Minder.Receiver(this,sel,range);
var keyboarder = new Minder.keyboarder(receiver);
this.receiver = receiver; this.receiver = receiver;
//鼠标被点击,并未太抬起时为真 //鼠标被点击,并未太抬起时为真
var mouseDownStatus = false; var mouseDownStatus = false;
var lastEvtPosition, dir = 1;
//当前是否有选区存在 //当前是否有选区存在
var selectionReadyShow = false; var selectionReadyShow = false;
...@@ -24,17 +23,16 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -24,17 +23,16 @@ KityMinder.registerModule('TextEditModule', function() {
var color = node.getStyle('text-selection-color'); var color = node.getStyle('text-selection-color');
//准备输入状态 //准备输入状态
var textShape = node.getTextShape();
receiver.updateByMinderNode(node);
sel.setHide() sel.setHide()
.setStartOffset(0) .setStartOffset(0)
.setEndOffset(textShape.getContent().length) .setEndOffset(receiver.getTxtOfContainer().length)
.setColor(color); .setColor(color);
receiver receiver.updateContainerRangeBySel();
.setMinderNode(node)
.updateContainerRangeBySel();
if(browser.ie ){ if(browser.ie ){
var timer = setInterval(function(){ var timer = setInterval(function(){
...@@ -57,7 +55,7 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -57,7 +55,7 @@ KityMinder.registerModule('TextEditModule', function() {
km.textEditNode = function(node){ km.textEditNode = function(node){
inputStatusReady(node); inputStatusReady(node);
km.setStatus('textedit'); km.setStatus('textedit');
receiver.updateSelectionShow(); receiver.updateSelection();
}; };
return { return {
'events': { 'events': {
...@@ -92,27 +90,28 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -92,27 +90,28 @@ KityMinder.registerModule('TextEditModule', function() {
if(node){ if(node){
var textShape = node.getTextShape();
textShape.setStyle('cursor', 'default');
if (this.isSingleSelect() && node.isSelected()) { if (this.isSingleSelect() && node.isSelected()) {
var textGroup = node.getTextGroup();
textGroup.setStyle('cursor', 'default');
sel.collapse(true); sel.collapse(true);
sel.setColor(node.getStyle('text-selection-color')); sel.setColor(node.getStyle('text-selection-color'));
receiver receiver
.setMinderNode(node) .updateByMinderNode(node)
.setCurrentIndex(e.getPosition(this.getRenderContainer())) .updateIndexByMouse(e.getPosition(node.getRenderContainer()))
.setRange(range) .setRange(range)
.setReady(); .setReady();
lastEvtPosition = e.getPosition(this.getRenderContainer());
if(selectionReadyShow){ if(selectionReadyShow){
textShape.setStyle('cursor', 'text'); textGroup.setStyle('cursor', 'text');
sel.setShowStatus();
receiver.updateSelection();
setTimeout(function() { setTimeout(function() {
sel.setShow(); sel.collapse(true)
.updatePosition(receiver.getOffsetByIndex())
.setShow();
}, 200); }, 200);
km.setStatus('textedit'); km.setStatus('textedit');
...@@ -166,9 +165,8 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -166,9 +165,8 @@ KityMinder.registerModule('TextEditModule', function() {
node.getTextShape().setStyle('cursor', 'text'); // node.getTextShape().setStyle('cursor', 'text');
receiver.updateSelection();
//必须再次focus,要不不能呼出键盘 //必须再次focus,要不不能呼出键盘
if(browser.ipad){ if(browser.ipad){
...@@ -176,24 +174,22 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -176,24 +174,22 @@ KityMinder.registerModule('TextEditModule', function() {
} }
setTimeout(function() { setTimeout(function() {
sel.setShow(); sel.collapse(true)
.updatePosition(receiver.getOffsetByIndex())
.setShow();
}, 200); }, 200);
lastEvtPosition = e.getPosition(this.getRenderContainer());
km.setStatus('textedit'); km.setStatus('textedit');
return; return;
} }
//当选中节点后,输入状态准备 //当选中节点后,输入状态准备
if(sel.isHide()){ if(sel.isHide()){
inputStatusReady(e.getTargetNode()); inputStatusReady(e.getTargetNode());
}else { }else {
//当有光标时,要同步选区 //当有光标时,要同步选区
if(!sel.collapsed){ if(!sel.collapsed){
receiver.updateContainerRangeBySel(); receiver.updateContainerRangeBySel();
} }
...@@ -205,22 +201,21 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -205,22 +201,21 @@ KityMinder.registerModule('TextEditModule', function() {
}, },
'textedit.beforemousemove inputready.beforemousemove': function(e) { 'textedit.beforemousemove inputready.beforemousemove': function(e) {
if(browser.ipad){ if(browser.ipad){
return; return;
} }
//ipad下不做框选 //ipad下不做框选
if (mouseDownStatus && receiver.isReady() && selectionReadyShow) { if (mouseDownStatus && receiver.isReady() && selectionReadyShow) {
var node = e.getTargetNode();
e.stopPropagationImmediately(); e.stopPropagationImmediately();
var offset = e.getPosition(this.getRenderContainer()); var offset = e.getPosition(node.getRenderContainer());
dir = offset.x > lastEvtPosition.x ? 1 : (offset.x < lastEvtPosition.x ? -1 : dir);
receiver.updateSelectionByMousePosition(offset, dir) receiver.updateSelectionByMousePosition(offset)
.updateSelectionShow(dir) .updateSelection(offset)
.updateContainerRangeBySel(); .updateContainerRangeBySel();
lastEvtPosition = e.getPosition(this.getRenderContainer());
}else if(mouseDownStatus && !selectionReadyShow){ }else if(mouseDownStatus && !selectionReadyShow){
//第一次点中,第二次再次点中进行拖拽 //第一次点中,第二次再次点中进行拖拽
...@@ -231,12 +226,13 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -231,12 +226,13 @@ KityMinder.registerModule('TextEditModule', function() {
'normal.dblclick textedit.dblclick inputready.dblclick': function(e) { 'normal.dblclick textedit.dblclick inputready.dblclick': function(e) {
var node = e.getTargetNode(); var node = e.getTargetNode();
if(node){ if(node){
inputStatusReady(e.getTargetNode()); inputStatusReady(node);
km.setStatus('textedit'); km.setStatus('textedit');
receiver.updateSelectionShow(); receiver.updateSelection();
} }
}, },
...@@ -259,7 +255,7 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -259,7 +255,7 @@ KityMinder.registerModule('TextEditModule', function() {
}; };
if (cmds[e.commandName]) { if (cmds[e.commandName]) {
inputStatusReady(km.getSelectedNode()); inputStatusReady(km.getSelectedNode());
receiver.updateSelectionShow(); receiver.updateSelection();
return; return;
} }
...@@ -270,9 +266,7 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -270,9 +266,7 @@ KityMinder.registerModule('TextEditModule', function() {
}, },
'layoutfinish':function(e){ 'layoutfinish':function(e){
if (e.node === receiver.minderNode && (this.getStatus() == 'textedit' || this.getStatus() == 'inputready') ) {//&& selectionReadyShow if (e.node === receiver.minderNode && (this.getStatus() == 'textedit' || this.getStatus() == 'inputready') ) {//&& selectionReadyShow
receiver receiver.setContainerStyle();
.setBaseOffset()
.setContainerStyle();
} }
}, },
'selectionclear': function() { 'selectionclear': function() {
...@@ -287,13 +281,13 @@ KityMinder.registerModule('TextEditModule', function() { ...@@ -287,13 +281,13 @@ KityMinder.registerModule('TextEditModule', function() {
}, },
'blur': function() { 'blur': function() {
receiver.clear(); !/\?debug#?/.test(location.href) && receiver.clear();
}, },
'textedit.import': function() { 'textedit.import': function() {
km.setStatus('normal'); km.setStatus('normal');
receiver.clear(); receiver.clear();
}, },
'textedit.mousewheel': function() { 'inputready.mousewheel textedit.mousewheel': function() {
receiver.setContainerStyle(); receiver.setContainerStyle();
} }
......
//接收者
Minder.keyboarder = kity.createClass('keyboarder', function(){
return {
constructor: function(re) {
this.re = re;
this.container = re.container;
this.selection = re.selection;
this.range = re.range;
this.km = re.km;
this.lastMinderNode = null;
this.isTypeText = false;
this._initEvent();
},
//给接受容器绑定事件
_initEvent: function(){
var me = this;
if(browser.ipad) {
utils.listen(this.container, 'keydown keypress keyup input', function(e) {
me._handleEvents.call(me, new MinderEvent(e.type == 'keyup' ? 'beforekeyup' : e.type, e));
if(e.type == 'keyup'){
if(me.km.getStatus() == 'normal'){
me.km.fire( 'keyup', e);
}
}
});
}
this.km.on('inputready.beforekeyup ' +
'inputready.beforekeydown ' +
'textedit.beforekeyup ' +
'normal.keydown ' +
'normal.keyup ' +
'textedit.beforekeydown ' +
'textedit.keypress ' +
'textedit.paste',
utils.proxy(this._handleEvents, this));
},
_handleEvents:function(e){
switch (e.type) {
case 'input':
this._input(e);
break;
case 'beforekeydown':
this._beforeKeydown(e);
break;
case 'beforekeyup':
this._beforeKeyup(e);
break;
case 'keyup':
this._keyup(e);
}
},
_setTextToContainer : function(keyCode){
var me = this;
//同步节点
me.minderNode = me.re.minderNode;
clearTimeout(me.timer);
if (!me.range.hasNativeRange()) {
return;
}
if(keymap.controlKeys[keyCode]){
return;
}
//当第一次输入内容时进行保存
if(me.lastMinderNode !== me.minderNode && !keymap.notContentChange[keyCode]){
me.km.fire('saveScene',{
inputStatus:true
});
me.lastMinderNode = me.minderNode;
}
var text = me.re.getTxtOfContainer();
// //#46 修复在ff下定位到文字后方空格光标不移动问题
// if (browser.gecko && /\s$/.test(text)) {
// text += '\u200b';
// }
//重新渲染节点
me.minderNode.setText(text);
me.re.setContainerStyle();
me.minderNode.getRenderContainer().bringTop();
me.minderNode.render();
//移动光标不做layout
if(!keymap.notContentChange[keyCode]){
clearTimeout(me.inputTextTimer);
me.inputTextTimer = setTimeout(function(){
me.km.layout(300);
},250);
}
me.re.updateTextOffsetData()
.updateRange()
.updateSelectionByRange();
me.selection
.updateOffsetByTextData(me.re.textData)
.updatePosition()
.setHoldShow();
me.timer = setTimeout(function() {
if(me.selection.isShow()){
me.selection.setShow();
}
}, 200);
me.km.setStatus('textedit');
},
_input:function(e){
var me = this;
if (browser.ipad) {
setTimeout(function() {
me._setTextToContainer();
});
}
},
_beforeKeydown:function(e){
var me = this;
var orgEvt = e.originEvent;
var keyCode = orgEvt.keyCode;
this.isTypeText = keyCode == 229 || keyCode === 0;
switch (keyCode) {
case keymap.Enter:
if(e.originEvent.shiftKey){
me._handlerEnterkey();
e.preventDefault();
return false;
}
case keymap.Tab:
if(this.selection.isShow()){
this.re.clear();
this.km.setStatus('inputready');
clearTimeout(me.inputTextTimer);
e.preventDefault();
}else{
this.km.setStatus('normal');
this.km.fire('contentchange');
}
return;
case keymap.left:
case keymap.right:
case keymap.up:
case keymap.down:
case keymap.Backspace:
case keymap.Del:
case keymap['/']:
if(this.selection.isHide()){
this.km.setStatus('normal');
return;
}
break;
case keymap.Control:
case keymap.Alt:
case keymap.Cmd:
case keymap.F2:
if(this.selection.isHide() && this.km.getStatus() != 'textedit'){
this.km.setStatus('normal');
return;
}
}
if (e.originEvent.ctrlKey || e.originEvent.metaKey) {
//选中节点时的复制粘贴,要变成normal
if(this.selection.isHide() && {
86:1,
88:1,
67:1
}[keyCode]){
this.km.setStatus('normal');
return;
}
//粘贴
if (keyCode == keymap.v) {
setTimeout(function () {
me.range.updateNativeRange().insertNode($('<span>$$_kityminder_bookmark_$$</span>')[0]);
me.container.innerHTML = utils.unhtml(me.container.textContent.replace(/[\u200b\t\r\n]/g, ''));
var index = me.container.textContent.indexOf('$$_kityminder_bookmark_$$');
me.container.textContent = me.container.textContent.replace('$$_kityminder_bookmark_$$', '');
me.range.setStart(me.container.firstChild, index).collapse(true).select();
me._setTextToContainer(keyCode);
}, 100);
return;
}
//剪切
if (keyCode == keymap.x) {
setTimeout(function () {
me._setTextToContainer(keyCode);
}, 100);
return;
}
}
//针对不能连续删除做处理
if(keymap.Del == keyCode || keymap.Backspace == keyCode)
me._setTextToContainer(keyCode);
},
_beforeKeyup:function(e){
var me = this;
var orgEvt = e.originEvent;
var keyCode = orgEvt.keyCode;
switch (keyCode) {
case keymap.Enter:
case keymap.Tab:
case keymap.F2:
if(browser.ipad){
if(this.selection.isShow()){
this.clear();
this.km.setStatus('inputready');
clearTimeout(me.inputTextTimer);
e.preventDefault();
}else{
this.km.setStatus('normal');
this.km.fire('contentchange');
}
return;
}
if (keymap.Enter == keyCode && (this.isTypeText || browser.mac && browser.gecko)) {
me._setTextToContainer(keyCode);
}
if (this.keydownNode === this.minderNode) {
this.rollbackStatus();
this.clear();
}
e.preventDefault();
return;
case keymap.Del:
case keymap.Backspace:
case keymap.Spacebar:
if(browser.ipad){
if(this.selection.isHide()){
this.km.setStatus('normal');
return;
}
}
me._setTextToContainer(keyCode);
return;
}
if (this.isTypeText) {
me._setTextToContainer(keyCode);
return;
}
if (browser.mac && browser.gecko){
me._setTextToContainer(keyCode);
return;
}
me._setTextToContainer(keyCode);
return true;
},
_keyup:function(e){
var me = this;
var orgEvt = e.originEvent;
var keyCode = orgEvt.keyCode;
var node = this.km.getSelectedNode();
if(this.km.getStatus() == 'normal' && node && this.selection.isHide()){
if (node && this.km.isSingleSelect() && node.isSelected()) {
this.selection.setHide()
.setStartOffset(0)
.setEndOffset(this.re.getTxtOfContainer().length)
.setColor( node.getStyle('text-selection-color'));
this.re
.updateByMinderNode(node)
.updateContainerRangeBySel();
if(browser.ie ){
var timer = setInterval(function(){
var nativeRange = me.range.nativeSel.getRangeAt(0);
if(!nativeRange || nativeRange.collapsed){
me.range.select();
}else {
clearInterval(timer);
}
});
}
this.km.setStatus('inputready');
}
}
},
//处理软回车操作
_handlerEnterkey:function(){
var rng = this.range;
var br = document.createElement('br');
var me = this;
if(!rng.collapsed){
rng.deleteContents();
}
rng.insertNode(br);
rng.setStartAfter(br);
rng.collapse(true);
rng.select();
me._setTextToContainer(keymap.Enter);
}
};
}());
\ No newline at end of file
Minder.Range = kity.createClass('Range',{ Minder.Range = kity.createClass('Range',function(){
constructor : function(){
this.nativeRange = document.createRange();
this.nativeSel = window.getSelection();
},
hasNativeRange : function(){
return this.nativeSel.rangeCount !== 0 ;
},
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);
}
try{
this.nativeSel.removeAllRanges();
}catch(e){
function getOffset(rng,dir){
var node = rng[dir + 'Container'],
offset = rng[dir + 'Offset'],
rOffset = 0;
if(node.nodeType == 1){
//默认不会出现得不到子节点的情况
node = node.childNodes[offset];
if(node.nodeType == 3){
offset = 0;
}
} }
utils.each(rng.container.childNodes,function(index,n){
if(n === node){
if(n.nodeType == 1){
return false;
}else{
rOffset += offset;
return false;
}
}
rOffset += (n.nodeType == 1 ? 1 : utils.clearWhitespace(n.nodeValue).length);
});
return rOffset;
}
function setBoundary(rng,offset,dir){
var rOffset = 0,cont = rng.container;
utils.each(cont.childNodes,function(index,node){
if(node.nodeType == 1){
this.nativeSel.addRange(this.nativeRange); rOffset++;
return this; if(rOffset == offset){
},
setStart:function(node,index){
try{
this.nativeRange.setStart(node,index);
}catch(error){
console.log(error);
}
return this; rng['set' + dir](cont,index);
}, return false;
setEnd:function(node,index){ }
this.nativeRange.setEnd(node,index); return;
return this; }
},
getStart:function(){
var range = this.nativeSel.getRangeAt(0);
return {
startContainer:range.startContainer,
startOffset:range.startOffset
};
},
getStartOffset:function(){
return this.nativeRange.startOffset;
},
getEndOffset:function(){
return this.nativeRange.endOffset;
},
collapse:function(toStart){
this.nativeRange.collapse(toStart === true);
return this;
},
isCollapsed:function(){
return this.nativeRange.collapsed;
},
insertNode:function(node){
this.nativeRange.insertNode(node);
return this;
},
updateNativeRange:function(){
this.nativeRange = this.nativeSel.getRangeAt(0); var currentLength = utils.clearWhitespace(node.nodeValue).length;
return this; if(rOffset + currentLength >= offset){
rng['set' + dir](node,offset - rOffset);
return false;
}
rOffset += currentLength;
});
} }
return {
constructor : function(container){
this.nativeRange = document.createRange();
this.nativeSel = window.getSelection();
this.startContainer =
this.endContainer =
this.startOffset =
this.endOffset = null;
this.collapsed = false;
this.container = container || null;
},
hasNativeRange : function(){
return this.nativeSel.rangeCount !== 0 ;
},
deleteContents : function(){
this.nativeRange.deleteContents();
return this._updateBoundary();
},
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);
}
try{
this.nativeSel.removeAllRanges();
}catch(e){
}
this.nativeSel.addRange(this.nativeRange);
return this;
},
_updateBoundary : function(){
var nRange = this.nativeRange;
this.startContainer = nRange.startContainer;
this.endContainer = nRange.endContainer;
this.startOffset = nRange.startOffset;
this.endOffset = nRange.endOffset;
this.collapsed = nRange.collapsed;
return this;
},
setStartOffset:function(offset){
setBoundary(this,offset,'Start');
return this;
},
setEndOffset:function(offset){
setBoundary(this,offset,'End');
return this;
},
setStart:function(node,offset){
this.nativeRange.setStart(node,offset);
this._updateBoundary();
return this;
},
setStartAfter:function(node){
return this.setStart(node.parentNode,utils.getNodeIndex(node) + 1);
},
setEnd:function(node,offset){
this.nativeRange.setEnd(node,offset);
this._updateBoundary();
return this;
},
update:function(){
this.updateNativeRange()
._updateBoundary();
return this;
},
getStart:function(){
this.update();
return {
startContainer:this.startContainer,
startOffset:this.startOffset
};
},
getStartOffset:function(){
return getOffset(this,'start');
},
getEndOffset:function(){
return getOffset(this,'end');
},
collapse:function(toStart){
this.nativeRange.collapse(toStart === true);
this._updateBoundary();
return this;
},
isCollapsed:function(){
this._updateBoundary();
return this.collapsed;
},
insertNode:function(node){
this.nativeRange.insertNode(node);
return this._updateBoundary();
},
updateNativeRange:function(){
this.nativeRange = this.nativeSel.getRangeAt(0);
return this;
},
clear : function(){
this.nativeSel.removeAllRanges();
return this;
}
}); };
\ No newline at end of file }());
\ No newline at end of file
...@@ -6,49 +6,40 @@ Minder.Receiver = kity.createClass('Receiver', { ...@@ -6,49 +6,40 @@ Minder.Receiver = kity.createClass('Receiver', {
this.selection.setHide(); this.selection.setHide();
} }
if (this.range) { if (this.range) {
this.range.nativeSel.removeAllRanges(); this.range.clear();
} }
this.index = 0; this.index = 0;
this.isTypeText = false;
this.lastMinderNode = null;
return this; return this;
}, },
constructor: function(km,sel,range) { constructor: function(km,sel,range) {
var me = this; //初始化接收者
this.setKityMinder(km); this.setKityMinder(km);
//创建接收者容器
var _div = document.createElement('div'); var _div = document.createElement('div');
_div.setAttribute('contenteditable', true); _div.setAttribute('contenteditable', true);
_div.className = 'km_receiver'; _div.className = 'km_receiver';
this.container = _div; this.container = _div;
utils.addCssRule('km_receiver_css',
' .km_receiver{white-space:nowrap;position:absolute;padding:0;margin:0;word-wrap:break-word;'
+ (/\?debug#?/.test(location.href)?'':'clip:rect(1em 1em 1em 1em);'));
if(browser.ipad) {
utils.listen(this.container, 'keydown keypress keyup input', function(e) {
me.keyboardEvents.call(me, new MinderEvent(e.type == 'keyup' ? 'beforekeyup' : e.type, e));
if(e.type == 'keyup'){
if(me.km.getStatus() == 'normal'){
me.km.fire( 'keyup', e);
}
}
});
}
utils.addCssRule('km_receiver_css', ' .km_receiver{white-space:nowrap;position:absolute;padding:0;margin:0;word-wrap:break-word;' + (/\?debug#?/.test(location.href)?'':'clip:rect(1em 1em 1em 1em);'));
this.km.on('inputready.beforekeyup inputready.beforekeydown textedit.beforekeyup normal.keydown normal.keyup textedit.beforekeydown textedit.keypress textedit.paste', utils.proxy(this.keyboardEvents, this));
this.timer = null;
this.index = 0; this.index = 0;
this.selection = sel; this.selection = sel;
this.range = range; this.range = range;
this.range.container = _div;
}, },
setRange: function(range, index) { setRange: function(range, index) {
this.index = index || this.index; this.index = index || this.index;
var text = this.container.firstChild;
this.range = range; this.range = range;
range.setStart(text || this.container, this.index)
range.setStartOffset(this.index);
range.collapse(true); range.collapse(true);
var me = this; var me = this;
...@@ -58,39 +49,22 @@ Minder.Receiver = kity.createClass('Receiver', { ...@@ -58,39 +49,22 @@ Minder.Receiver = kity.createClass('Receiver', {
}); });
return this; return this;
}, },
setTextShape: function(textShape) { setTextGroup: function(textGroup) {
if (!textShape) { this.textGroup = textGroup;
textShape = new kity.Text();
}
this.textShape = textShape;
// techird: add cache
if (textShape._lastContent != textShape.getContent()) {
this.container.innerHTML = utils.unhtml(textShape.getContent());
textShape._lastContent = textShape.getContent();
}
return this;
},
setTextShapeSize: function(size) {
this.textShape.setSize(size);
return this; return this;
}, },
getTextShapeHeight: function() {
var height = this.textShape.getRenderBox().height;
return height || this.minderNode._lastTextShapeBox.height;
},
setKityMinder: function(km) { setKityMinder: function(km) {
this.km = km; this.km = km;
return this; return this;
}, },
setMinderNode: function(node) {
this.minderNode = node; updateByMinderNode:function(node){
this.setMinderNode(node);
//追加selection到节点 //追加selection到节点
this._addSelection(); this._addSelection();
//更新minderNode下的textshape //更新minderNode下的textGroup
this.setTextShape(node.getTextShape()); this.setTextGroup(node.getTextGroup());
//更新textshape的baseOffset
this.setBaseOffset();
//更新接受容器的样式 //更新接受容器的样式
this.setContainerStyle(); this.setContainerStyle();
//更新textOffsetData数据 //更新textOffsetData数据
...@@ -99,472 +73,215 @@ Minder.Receiver = kity.createClass('Receiver', { ...@@ -99,472 +73,215 @@ Minder.Receiver = kity.createClass('Receiver', {
this.setSelectionHeight(); this.setSelectionHeight();
//更新接收容器内容 //更新接收容器内容
this.setContainerTxt(); this.setContainerTxt();
return this;
},
setMinderNode: function(node) {
this.minderNode = node;
this.selection.setMinderNode(node);
return this; return this;
}, },
_addSelection:function(){ _addSelection:function(){
if (this.selection.container) this.selection.remove(); if (this.selection.container){
this.selection.remove();
}
this.minderNode.getRenderContainer().addShape(this.selection); this.minderNode.getRenderContainer().addShape(this.selection);
return this;
}, },
getMinderNode:function(){ getMinderNode:function(){
return this.minderNode; return this.minderNode;
}, },
keyboardEvents: function(e) {
var me = this;
var orgEvt = e.originEvent;
var keyCode = orgEvt.keyCode;
function setTextToContainer() {
clearTimeout(me.timer);
if (!me.range.hasNativeRange()) {
return;
}
if(keymap.controlKeys[keyCode]){
return;
}
//当第一次输入内容时进行保存
if(me.lastMinderNode !== me.minderNode && !keymap.notContentChange[keyCode]){
me.km.fire('saveScene',{
inputStatus:true
});
me.lastMinderNode = me.minderNode;
}
var text = me.container.textContent.replace(/[\u200b\t\r\n]/g, '');
//#46 修复在ff下定位到文字后方空格光标不移动问题
if (browser.gecko && /\s$/.test(text)) {
text += '\u200b';
}
me.minderNode.setText(text);
me.setContainerStyle();
me.minderNode.getRenderContainer().bringTop();
me.minderNode.render();
//移动光标不做layout
if(!keymap.notContentChange[keyCode]){
clearTimeout(me.inputTextTimer);
me.inputTextTimer = setTimeout(function(){
me.km.layout(300);
},250);
}
me.textShape = me.minderNode.getRenderer('TextRenderer').getRenderShape();
me.setBaseOffset();
me.updateTextOffsetData();
me.updateRange();
me.updateSelectionByRange();
me.updateSelectionShow();
me.timer = setTimeout(function() {
if(me.selection.isShow())
me.selection.setShow();
}, 200);
me.km.setStatus('textedit');
}
switch (e.type) {
case 'input':
if (browser.ipad) {
setTimeout(function() {
setTextToContainer();
});
}
break;
case 'beforekeydown':
this.isTypeText = keyCode == 229 || keyCode === 0;
switch (keyCode) {
case keymap.Enter:
case keymap.Tab:
if(this.selection.isShow()){
this.clear();
this.km.setStatus('inputready');
clearTimeout(me.inputTextTimer);
e.preventDefault();
this.km.fire('contentchange');
}else{
this.km.setStatus('normal');
}
return;
case keymap.left:
case keymap.right:
case keymap.up:
case keymap.down:
case keymap.Backspace:
case keymap.Del:
case keymap['/']:
if(this.selection.isHide()){
this.km.setStatus('normal');
return;
}
break;
case keymap.Control:
case keymap.Alt:
case keymap.Cmd:
case keymap.F2:
if(this.selection.isHide() && this.km.getStatus() != 'textedit'){
this.km.setStatus('normal');
return;
}
}
if (e.originEvent.ctrlKey || e.originEvent.metaKey) {
//选中节点时的复制粘贴,要变成normal
if(this.selection.isHide() && {
86:1,
88:1,
67:1
}[keyCode]){
this.km.setStatus('normal');
return;
}
//粘贴
if (keyCode == keymap.v) {
setTimeout(function () {
me.range.updateNativeRange().insertNode($('<span>$$_kityminder_bookmark_$$</span>')[0]);
me.container.innerHTML = utils.unhtml(me.container.textContent.replace(/[\u200b\t\r\n]/g, ''));
var index = me.container.textContent.indexOf('$$_kityminder_bookmark_$$');
me.container.textContent = me.container.textContent.replace('$$_kityminder_bookmark_$$', '');
me.range.setStart(me.container.firstChild, index).collapse(true).select();
setTextToContainer(keyCode);
}, 100);
return;
}
//剪切
if (keyCode == keymap.x) {
setTimeout(function () {
setTextToContainer(keyCode);
}, 100);
return;
}
}
//针对不能连续删除做处理
if(keymap.Del == keyCode || keymap.Backspace == keyCode)
setTextToContainer(keyCode);
break;
case 'beforekeyup':
switch (keyCode) {
case keymap.Enter:
case keymap.Tab:
case keymap.F2:
if(browser.ipad){
if(this.selection.isShow()){
this.clear();
this.km.setStatus('inputready');
clearTimeout(me.inputTextTimer);
e.preventDefault();
}else{
this.km.setStatus('normal');
}
return;
}
if (keymap.Enter == keyCode && (this.isTypeText || browser.mac && browser.gecko)) {
setTextToContainer(keyCode);
}
if (this.keydownNode === this.minderNode) {
this.rollbackStatus();
this.clear();
}
e.preventDefault();
return;
case keymap.Del:
case keymap.Backspace:
case keymap.Spacebar:
if(browser.ipad){
if(this.selection.isHide()){
this.km.setStatus('normal');
return;
}
}
setTextToContainer(keyCode);
return;
}
if (this.isTypeText) {
setTextToContainer(keyCode);
return;
}
if (browser.mac && browser.gecko){
setTextToContainer(keyCode);
return;
}
setTextToContainer(keyCode);
return true;
case 'keyup':
var node = this.km.getSelectedNode();
if(this.km.getStatus() == 'normal' && node && this.selection.isHide()){
if (node && this.km.isSingleSelect() && node.isSelected()) {
var color = node.getStyle('text-selection-color');
//准备输入状态
var textShape = node.getTextShape();
this.selection.setHide()
.setStartOffset(0)
.setEndOffset(textShape.getContent().length)
.setColor(color);
this
.setMinderNode(node)
.updateContainerRangeBySel();
if(browser.ie ){
var timer = setInterval(function(){
var nativeRange = this.range.nativeSel.getRangeAt(0);
if(!nativeRange || nativeRange.collapsed){
this.range.select();
}else {
clearInterval(timer);
}
});
}
this.km.setStatus('inputready');
}
}
}
},
updateIndex: function() { updateIndex: function() {
this.index = this.range.getStart().startOffset; this.index = this.range.getStartOffset();
return this;
},
updateTextOffsetData: function() {
this.getTextOffsetData();
return this; return this;
}, },
setSelection: function(selection) { setSelection: function(selection) {
this.selection = selection; this.selection = selection;
return this; return this;
}, },
updateSelection: function() { updateSelection: function(offset) {
this.selection.setShowHold(); this.selection.update(this.textData,offset);
this.selection.bringTop();
//更新模拟选区的范围
this.selection.setStartOffset(this.index).collapse(true);
if (this.index == this.textData.length) {
if (this.index === 0) {
this.selection.setPosition(this.getBaseOffset());
} else {
this.selection.setPosition({
x: this.textData[this.index - 1].x + this.textData[this.index - 1].width,
y: this.textData[this.index - 1].y
});
}
} else {
this.selection.setPosition(this.textData[this.index]);
}
return this; return this;
}, },
getBaseOffset: function(refer) { getOffsetByIndex:function(index){
return this.textShape.getRenderBox(refer || this.km.getRenderContainer()); return utils.getValueByIndex(this.textData, index !== undefined ? index : this.index);
}, },
setBaseOffset: function() { getBaseOffset: function() {
this.offset = this.textShape.getRenderBox(this.km.getRenderContainer()); return this.textGroup.getRenderBox('screen');
return this;
}, },
setContainerStyle: function() { setContainerStyle: function() {
var textShapeBox = this.getBaseOffset('screen'); var textGroupBox = this.getBaseOffset();
this.container.style.cssText = ';left:' + (browser.ipad ? '-' : '') + this.container.style.cssText = ';left:' + (browser.ipad ? '-' : '') +
textShapeBox.x + 'px;top:' + (textShapeBox.y + (/\?debug#?/.test(location.href)?30:0)) + textGroupBox.x + 'px;top:' + (textGroupBox.y + (/\?debug#?/.test(location.href)?this.textGroup.getItems().length * this.getlineHeight():0)) +
'px;width:' + textShapeBox.width + 'px;height:' + textShapeBox.height + 'px;'; 'px;width:' + textGroupBox.width + 'px;height:' + textGroupBox.height + 'px;';
return this; return this;
}, },
getTextOffsetData: function() { updateTextOffsetData: function() {
var text = this.textShape.getContent(); var me = this;
var lineHeight =
this.minderNode.getStyle('line-height') * (this.minderNode.getData('font-size') || this.minderNode.getStyle('font-size'));
var offsetHeight = (me.textGroup.getShapes().length * lineHeight)/2;
var box; var box;
this.textData = []; this.textData = [];
for (var i = 0, l = text.length; i < l; i++) { me.textGroup.eachItem(function(index,textShape){
try { me.textData[index] = [];
box = this.textShape.getExtentOfChar(i); var currentLineTop = index * lineHeight + 2;
} catch (e) { var text = textShape.getContent();
console.log(e);
}
this.textData.push({ for (var i = 0, l = text.length; i < l; i++) {
x: box.x , try {
y: box.y, box = textShape.getExtentOfChar(i);
width: box.width, } catch (e) {
height: box.height console.log(e);
}); }
} me.textData[index].push({
if(this.textData.length === 0){ x: box.x ,
var lastBox = this.minderNode._lastTextShapeBox; y: currentLineTop - offsetHeight,
this.textData.push({ width: box.width,
x: lastBox.x , height: box.height
y: lastBox.y, });
width: 0, }
height: lastBox.height if(text.length === 0){
}); me.textData[index].push({
} x: 0,
y: currentLineTop - offsetHeight,
width: 0,
height:lineHeight
});
}
});
return this; return this;
}, },
setCurrentIndex: function(offset) { getlineHeight:function(){
return this.minderNode.getStyle('line-height') * (this.minderNode.getData('font-size') || this.minderNode.getStyle('font-size'));
},
updateIndexByMouse : function(offset) {
var me = this; var me = this;
this.getTextOffsetData(); //更新文本字符坐标
var hadChanged = false; me.updateTextOffsetData();
//要剪掉基数
this._getRelativeValue(offset);
if(this.textData.length == 1 && this.textData[0].width === 0){
me.index = 0;
return this;
}
utils.each(this.textData, function(i, v) {
//点击开始之前
if (i === 0 && offset.x <= v.x) {
me.index = 0;
return false;
}
if (offset.x >= v.x && offset.x <= v.x + v.width) {
if (offset.x - v.x > v.width / 2) {
me.index = i + 1;
} else { this.index = 0;
me.index = i;
} var lineHeight = this.getlineHeight();
hadChanged = true;
return false;
} utils.each(this.textData,function(l,arr){
if (i == me.textData.length - 1 && offset.x >= v.x) {
me.index = me.textData.length; var first = arr[0];
//确定行号
if(first.y <= offset.y && first.y + lineHeight >= offset.y){
utils.each(arr,function(i,v){
//点击开始之前
if (i === 0 && offset.x <= v.x) {
return false;
}
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;
}
return false;
}
if (i == arr.length - 1 && offset.x >= v.x) {
me.index += arr.length;
return false;
}
});
return false; return false;
}else{
me.index += arr.length + (arr.length == 1 && arr[0].width === 0 ? 0 : 1);
return;
} }
}); });
this.selection.setStartOffset(this.index).collapse(true);
return this; return this;
}, },
setSelectionHeight: function() { setSelectionHeight: function() {
this.selection.setHeight(this.getTextShapeHeight());
this.selection.setHeight((this.minderNode.getData('font-size') || this.minderNode.getStyle('font-size')) * 1);
return this; return this;
}, },
_getRelativeValue:function(offset){ updateSelectionByMousePosition: function(offset,dir) {
offset.x = offset.x - this.offset.x;
offset.y = offset.y - this.offset.y;
},
updateSelectionByMousePosition: function(offset, dir) {
//要剪掉基数
this._getRelativeValue(offset);
var me = this; var me = this;
utils.each(this.textData, function(i, v) { var result = 0;
//点击开始之前 var lineHeight = this.getlineHeight();
if (i === 0 && offset.x <= v.x) { utils.each(this.textData,function(l,arr){
me.selection.setStartOffset(0); var first = arr[0];
return false; //确定行号
}
if(first.y <= offset.y && first.y + lineHeight >= offset.y){
utils.each(arr,function(i,v){
//点击开始之前
if (i === 0 && offset.x <= v.x) {
return false;
}
if (offset.x >= v.x && offset.x <= v.x + v.width) {
if (i == me.textData.length - 1 && offset.x >= v.x) { result += i;
me.selection.setEndOffset(me.textData.length); if (offset.x - v.x > v.width / 2) {
return false;
}
if (offset.x >= v.x && offset.x <= v.x + v.width) {
if (me.index == i) { result += 1;
if (i === 0) { }
me.selection.setStartOffset(i);
}
if (offset.x <= v.x + v.width / 2) {
me.selection.collapse(true);
} else {
me.selection.setEndOffset(i + ((me.selection.endOffset > i ||
dir == 1) && i != me.textData.length - 1 ? 1 : 0));
}
} else if (i > me.index) { return false;
me.selection.setStartOffset(me.index);
me.selection.setEndOffset(i + 1);
} else {
if (dir == 1) {
me.selection.setStartOffset(i + (offset.x >= v.x + v.width / 2 &&
i != me.textData.length - 1 ? 1 : 0));
} else {
me.selection.setStartOffset(i);
} }
if (i == arr.length - 1 && offset.x >= v.x) {
result += arr.length;
me.selection.setEndOffset(me.index); return false;
} }
});
return false; return false;
}else{
result += arr.length + (arr.length == 1 && arr[0].width === 0 ? 0 : 1);
return;
} }
}); });
return this; if(result < me.index){
}, this.selection.setStartOffset(result);
updateSelectionShow: function() { this.selection.setEndOffset(me.index);
var startOffset = this.textData[this.selection.startOffset],
endOffset = this.textData[this.selection.endOffset],
width = 0;
if (this.selection.collapsed) {
if(startOffset === undefined){
var tmpOffset = this.textData[this.textData.length - 1];
tmpOffset = utils.clone(tmpOffset);
tmpOffset.x = tmpOffset.x + tmpOffset.width;
startOffset = tmpOffset;
}
this.selection.updateShow(startOffset, 2);
return this;
}
if (!endOffset) {
try {
var lastOffset = this.textData[this.textData.length - 1];
width = lastOffset.x - startOffset.x + lastOffset.width;
} catch (e) {
console.log(e);
}
} else { }else if(result == me.index){
width = endOffset.x - startOffset.x;
}
this.selection.updateShow(startOffset, width); this.selection.setStartOffset(result).collapse(true);
}else{
this.selection.setStartOffset(me.index);
this.selection.setEndOffset(result);
}
return this; return this;
}, },
updateRange: function() { updateRange: function() {
this.range.updateNativeRange(); this.range.update();
return this; return this;
}, },
updateContainerRangeBySel:function(){ updateContainerRangeBySel:function(){
var me = this; var me = this;
var node = this.container.firstChild; this.range.setStartOffset(this.selection.startOffset);
if(!node){ this.range.setEndOffset(this.selection.endOffset);
node = this.container;
}
this.range.setStart(node, this.selection.startOffset);
this.range.setEnd(node, this.selection.endOffset);
if(browser.gecko){ if(browser.gecko){
this.container.focus(); this.container.focus();
setTimeout(function(){ setTimeout(function(){
...@@ -585,7 +302,17 @@ Minder.Receiver = kity.createClass('Receiver', { ...@@ -585,7 +302,17 @@ Minder.Receiver = kity.createClass('Receiver', {
return this; return this;
}, },
setContainerTxt: function(txt) { setContainerTxt: function(txt) {
this.container.textContent = txt || this.textShape.getContent();
if(txt){
txt = txt.replace(/[\n]/g,'<br\/>');
}else{
txt = '';
this.textGroup.eachItem(function(i,item){
txt += item.getContent() + '<br/>';
});
}
this.container.innerHTML = txt;
return this; return this;
}, },
setReady:function(){ setReady:function(){
...@@ -599,5 +326,17 @@ Minder.Receiver = kity.createClass('Receiver', { ...@@ -599,5 +326,17 @@ Minder.Receiver = kity.createClass('Receiver', {
}, },
focus:function(){ focus:function(){
this.container.focus(); this.container.focus();
},
getTxtOfContainer:function(){
var result = '',cont = this.container;
utils.each(cont.childNodes,function(i,n){
if(n.nodeType == 3){
result += n.nodeValue.replace(/[\u200b]/g, '');
}else{
if(n !== cont.lastChild)
result += '\n';
}
});
return result;
} }
}); });
\ No newline at end of file
//模拟光标 //模拟光标
Minder.Selection = kity.createClass( 'Selection', { Minder.Selection = kity.createClass( 'Selection', {
base: kity.Rect, base: kity.Group,
constructor: function ( height, color, width ) { constructor: function ( height, color, width ) {
this.callBase(); this.callBase();
this.height = height || 20; this.height = height || 20;
...@@ -14,14 +14,85 @@ Minder.Selection = kity.createClass( 'Selection', { ...@@ -14,14 +14,85 @@ Minder.Selection = kity.createClass( 'Selection', {
this.setOpacity(0.5); this.setOpacity(0.5);
this.setStyle('cursor','text'); this.setStyle('cursor','text');
this._show = false; this._show = false;
this.offset = [];
}, },
setMinderNode : function(node){
this.minderNode = node;
},
setColor:function(color){ setColor:function(color){
this.fill(color); this.fill(color);
}, },
updateOffsetByTextData:function(data,offset){
if(this.collapsed){
this.offset = utils.getValueByIndex(data,this.startOffset);
return this;
}else{
var arrOffset = [],tmpOffset = {},
startOffset = this.startOffset,
endOffset = this.endOffset,
cIndex = 0;
utils.each(data,function(l,arr){
tmpOffset = {
width:0,
x:0,
y:0
};
utils.each(arr,function(i,o){
if(cIndex >= startOffset && cIndex <= endOffset){
if(i === 0 || cIndex === startOffset){
tmpOffset.x = o.x;
tmpOffset.y = o.y;
tmpOffset.width = i === 0 && offset && offset.x <= o.x && cIndex != startOffset ? 0 : o.width;
}else if(cIndex < endOffset){
tmpOffset.width += o.width;
}else if(cIndex === endOffset){
return false;
}
}
cIndex++;
});
if(tmpOffset.x !== undefined) {
arrOffset.push(tmpOffset);
}
if(cIndex === endOffset) {
return false;
}
if(arr.length == 1 && arr[0].width === 0)
return;
cIndex++;
});
this.offset = arrOffset;
return this;
}
},
updatePosition:function(offset){
var me = this;
this.clear();
offset = offset || this.offset;
if(this.collapsed){
var rect = new kity.Rect().fill(null).stroke(null).setWidth(2).setHeight(this.height);
rect.setPosition(Math.round(offset.x) - 0.5,Math.round(offset.y) - 1.5);
this.addShape(rect);
}else{
utils.each(offset,function(i,v){
var rect = new kity.Rect().fill(null).stroke(null).setWidth(v.width).setHeight(me.height);
rect.setPosition(Math.round(v.x) - 0.5,Math.round(v.y) - 1.5);
me.addShape(rect);
});
}
return this;
},
collapse : function(toStart){ collapse : function(toStart){
this.setOpacity(1); this.setOpacity(1);
this.width = 2;
this.collapsed = true; this.collapsed = true;
if(toStart){ if(toStart){
this.endOffset = this.startOffset; this.endOffset = this.startOffset;
...@@ -52,24 +123,12 @@ Minder.Selection = kity.createClass( 'Selection', { ...@@ -52,24 +123,12 @@ Minder.Selection = kity.createClass( 'Selection', {
this.setOpacity(0.5); this.setOpacity(0.5);
return this; return this;
}, },
updateShow : function(offset,width){ update : function(data,offset){
if(width){ if(data){
this.setShowHold(); this.updateOffsetByTextData(data,offset);
}
this.setPosition(offset).setWidth(width);
this.bringTop();
return this;
},
setPosition: function ( offset ) {
try {
// 这两个是神奇的 0.5 —— SVG 要边缘锐利,你需要一些对齐
this.x = Math.round(offset.x) - 0.5;
this.y = Math.round(offset.y) - 1.5;
} catch ( e ) {
console.log(e);
} }
this.update(); this.updatePosition();
this.setShow();
return this; return this;
}, },
setHeight: function ( height ) { setHeight: function ( height ) {
...@@ -82,13 +141,13 @@ Minder.Selection = kity.createClass( 'Selection', { ...@@ -82,13 +141,13 @@ Minder.Selection = kity.createClass( 'Selection', {
this._show = false; this._show = false;
return this; return this;
}, },
setShowHold: function () { setHoldShow:function(){
clearInterval( this.timer ); this.setStyle('display','');
this.setStyle( 'display', '' ); clearInterval(this.timer);
this._show = true;
return this; return this;
}, },
setShow: function () { setShow: function () {
this.bringTop();
clearInterval( this.timer ); clearInterval( this.timer );
var me = this, var me = this,
state = ''; state = '';
...@@ -104,10 +163,15 @@ Minder.Selection = kity.createClass( 'Selection', { ...@@ -104,10 +163,15 @@ Minder.Selection = kity.createClass( 'Selection', {
} }
return this; return this;
}, },
setShowStatus:function(){
this._show = true;
return this;
},
isShow:function(){ isShow:function(){
return this._show; return this._show;
}, },
isHide:function(){ isHide:function(){
return !this._show; return !this._show;
} }
} ); } );
\ No newline at end of file
...@@ -3,16 +3,18 @@ KityMinder.registerModule("fontmodule", function() { ...@@ -3,16 +3,18 @@ KityMinder.registerModule("fontmodule", function() {
return node.getData(name) || node.getStyle(name); return node.getData(name) || node.getStyle(name);
} }
KityMinder.TextRenderer.registerStyleHook(function(node, text) { KityMinder.TextRenderer.registerStyleHook(function(node, textGroup) {
var dataColor = node.getData('color'); var dataColor = node.getData('color');
var selectedColor = node.getStyle('selected-color'); var selectedColor = node.getStyle('selected-color');
var styleColor = node.getStyle('color'); var styleColor = node.getStyle('color');
text.fill(dataColor || (node.isSelected() && selectedColor ? selectedColor : styleColor)); textGroup.fill(dataColor || (node.isSelected() && selectedColor ? selectedColor : styleColor));
text.setFont({ textGroup.eachItem(function(index,item){
family: getNodeDataOrStyle(node, 'font-family'), item.setFont({
size: getNodeDataOrStyle(node, 'font-size') 'family': getNodeDataOrStyle(node,'font-family'),
'size': getNodeDataOrStyle(node,'font-size')
});
}); });
}); });
......
...@@ -4,39 +4,61 @@ var TextRenderer = KityMinder.TextRenderer = kity.createClass('TextRenderer', { ...@@ -4,39 +4,61 @@ var TextRenderer = KityMinder.TextRenderer = kity.createClass('TextRenderer', {
base: Renderer, base: Renderer,
create: function() { create: function() {
return new kity.Text() return new kity.Group().setId(KityMinder.uuid('node_text'));
.setId(KityMinder.uuid('node_text'))
.setVerticalAlign('middle')
.setAttr('text-rendering', 'inherit');
}, },
update: function(text,node) { update: function(textGroup,node) {
var tmpText = node.getText(); var textArr = node.getText(true);
this.setTextStyle(node, text.setContent(tmpText)); var lineHeight = node.getStyle('line-height');
var fontSize = node.getData('font-size') || node.getStyle('font-size');
var height = textArr.length *
node.getStyle('line-height') * (node.getData('font-size') || node.getStyle('font-size')) / 2;
var rBox = new kity.Box(),
r = Math.round;
this.setTextStyle(node, textGroup);
for(var i= 0,text,textShape;
(text=textArr[i],textShape=textGroup.getItem(i),
text!==undefined||textShape!==undefined);i++){
if(text === undefined && textShape){
textGroup.removeItem(i);
}else{
if(text!==undefined&&!textShape){
textShape = new kity.Text()
.setVerticalAlign('top')
.setAttr('text-rendering', 'inherit');
textGroup.addItem(textShape);
}
textShape.setContent(text);
if(tmpText.length || !this._lastBox){
var box = text.getBoundaryBox();
var r = Math.round;
if (kity.Browser.ie) {
box.y += 1;
} }
this._lastBox = {
x : r(box.x),
y : r(box.y),
width : r(box.width),
height: r(box.height)
};
}else {
this._lastBox.width = 0;
} }
var lastBox = this._lastBox; this.setTextStyle(node, textGroup);
node._lastTextShapeBox = lastBox;
textGroup.eachItem(function(i,textShape){
var y = i * fontSize * lineHeight - height;
textShape.setY(y);
rBox = rBox.merge(new kity.Box(0, y, textShape.getBoundaryBox().width, fontSize));
});
var nBox = new kity.Box(r(rBox.x), r(rBox.y),r(rBox.width), r(rBox.height));
node._currentTextGroupBox = nBox;
return function() { return function() {
return new kity.Box(lastBox.x, lastBox.y,lastBox.width, lastBox.height); return nBox;
}; };
}, },
...@@ -58,7 +80,7 @@ utils.extend(TextRenderer, { ...@@ -58,7 +80,7 @@ utils.extend(TextRenderer, {
}); });
kity.extendClass(MinderNode,{ kity.extendClass(MinderNode,{
getTextShape : function() { getTextGroup : function() {
return this.getRenderer('TextRenderer').getRenderShape(); return this.getRenderer('TextRenderer').getRenderShape();
} }
}); });
......
...@@ -51,5 +51,6 @@ KityMinder.registerTheme('classic', { ...@@ -51,5 +51,6 @@ KityMinder.registerTheme('classic', {
'order-hint-path-color': '#0f0', 'order-hint-path-color': '#0f0',
'order-hint-path-width': 1, 'order-hint-path-width': 1,
'text-selection-color': 'rgb(27,171,255)' 'text-selection-color': 'rgb(27,171,255)',
'line-height':1.5
}); });
\ No newline at end of file
...@@ -54,7 +54,8 @@ ...@@ -54,7 +54,8 @@
'order-hint-path-color': hsl(h, 100, 25), 'order-hint-path-color': hsl(h, 100, 25),
'order-hint-path-width': 1, 'order-hint-path-width': 1,
'text-selection-color': hsl(h, 100, 20) 'text-selection-color': hsl(h, 100, 20),
'line-height':1.5
}; };
} }
......
...@@ -47,5 +47,6 @@ KityMinder.registerTheme('snow', { ...@@ -47,5 +47,6 @@ KityMinder.registerTheme('snow', {
'order-hint-path-color': '#0f0', 'order-hint-path-color': '#0f0',
'order-hint-path-width': 1, 'order-hint-path-width': 1,
'text-selection-color': 'rgb(27,171,255)' 'text-selection-color': 'rgb(27,171,255)',
'line-height':1.5
}); });
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment