123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- /**
- * Created by hn on 14-3-19.
- */
- ( function () {
- var c = {
- start: function ( editor ) {
- kfEditor = editor;
- window.kfEditor = kfEditor;
- vCursor = createVCursor( kfEditor );
- inp = document.getElementById( "hiddenInput" );
- initClick();
- }
- },
- isShowCursor = false,
- inp = null,
- isAllowInput = false,
- vCursor = null,
- lastCount = -1,
- cursorIndex = -1,
- currentStartOffset = -1,
- currentStartContainer = null,
- currentEndContainer = null,
- currentEndOffset = -1,
- ctrlStartContainer = null,
- ctrlStartOffset = null,
- currentGroup = null,
- isDrag = false,
- isMousedown = false,
- mousedownPoint = { x: 0, y: 0 },
- MAX_COUNT = 1000,
- CALL_COUNT = 0,
- CURSOR_BLINKS = null,
- // 移动阀值
- dragThreshold = 10,
- kfEditor = null;
- // init click
- function initClick () {
- var evt = kfEditor.request( "ui.canvas.container.event" );
- evt.on( "mousedown", function ( e ) {
- e.preventDefault();
- if (e.which !== 1 ) {
- return;
- }
- isMousedown = true;
- isDrag = false;
- mousedownPoint = { x: e.clientX, y: e.clientY };
- hideCursor();
- cursorIndex = 0;
- var target = e.target,
- group = kfEditor.requestService( "position.get.group", target ),
- parentGroup = kfEditor.requestService( "position.get.parent.group", target );
- if ( !group ) {
- group = kfEditor.requestService( "syntax.get.group.content", "_kf_editor_1_1" );
- }
- if ( !parentGroup ) {
- parentGroup = group;
- }
- currentGroup = group;
- currentStartContainer = group;
- ctrlStartContainer = currentStartContainer;
- currentStartOffset = getIndex( currentStartContainer, e.clientX );
- ctrlStartOffset = currentStartOffset;
- if ( group ) {
- kfEditor.requestService( "render.select.group.content", group );
- kfEditor.requestService( "syntax.update.record.cursor", group.id, currentStartOffset );
- // group的选中
- var cursorInfo = kfEditor.requestService( "syntax.get.record.cursor" );
- var result = kfEditor.requestService( "syntax.get.latex.info" );
- updateInput( result );
- if ( cursorInfo.startOffset === cursorInfo.endOffset ) {
- // 点击的是占位符, 则进行着色
- if ( kfEditor.requestService( "syntax.valid.placeholder", parentGroup.id ) ) {
- kfEditor.requestService( "render.select.group", parentGroup.id );
- // 否则, 绘制光标
- } else {
- drawCursor( group, cursorInfo.startOffset );
- }
- }
- } else {
- kfEditor.requestService( "render.clear.select" );
- }
- } );
- evt.on( "dblclick", function ( e ) {
- e.preventDefault();
- isMousedown = false;
- isDrag = false;
- hideCursor();
- var target = e.target,
- group = kfEditor.requestService( "position.get.parent.group", target );
- if ( group ) {
- kfEditor.requestService( "render.select.group.all", group );
- var result = kfEditor.requestService( "syntax.update.selection", group );
- updateInput( result );
- } else {
- kfEditor.requestService( "render.clear.select" );
- }
- } );
- evt.on( "mouseup", function ( e ) {
- e.preventDefault();
- var _isDrag = isDrag;
- isDrag = false;
- isMousedown = false;
- if ( _isDrag ) {
- var result = kfEditor.requestService( "syntax.get.latex.info" );
- updateInput( result );
- }
- } );
- inp.addEventListener( "keydown", function ( e ) {
- isMousedown = false;
- isDrag = false;
- hideCursor();
- switch ( e.keyCode ) {
- // left
- case 37:
- e.preventDefault();
- kfEditor.requestService( "syntax.cursor.move.left" );
- update();
- return;
- // right
- case 39:
- e.preventDefault();
- kfEditor.requestService( "syntax.cursor.move.right" );
- update();
- return;
- }
- }, false );
- kfEditor.registerService( "control.insert.group", null, {
- insertGroup: insertGroup
- } );
- function insertGroup ( val ) {
- var latexStr = inp.value,
- startOffset = inp.selectionStart,
- endOffset = inp.selectionEnd,
- latexInfo = null;
- kfEditor.requestService( "syntax.insert.group", val );
- latexInfo = kfEditor.requestService( "syntax.get.latex.info" );
- updateInput( latexInfo );
- kfEditor.requestService( "render.draw", latexInfo.str );
- drawCursorService();
- //
- // val = "{" + val + "}"
- //
- // startOffset = latexStr.substring( 0, startOffset );
- // endOffset = latexStr.substring( endOffset );
- //
- // latexStr = startOffset + val + endOffset;
- //
- // updateInput( {
- // str: latexStr,
- // startOffset: ( startOffset + val ).length + 1,
- // endOffset: ( startOffset + val ).length + 1
- // } );
- //
- // kfEditor.requestService( "render.draw", latexStr );
- //
- // drawCursorService();
- }
- function update () {
- var cursorInfo = kfEditor.requestService( "syntax.get.record.cursor" ),
- group = kfEditor.requestService( "syntax.get.group.content", cursorInfo.groupId );
- kfEditor.requestService( "render.select.group.content", group );
- var result = kfEditor.requestService( "syntax.get.latex.info" );
- updateInput( result );
- if ( cursorInfo.startOffset === cursorInfo.endOffset && !kfEditor.requestService( "syntax.valid.placeholder", cursorInfo.groupId ) ) {
- drawCursor( group, cursorInfo.startOffset );
- }
- return result;
- }
- function updateLatexValue ( latexResult ) {
- kfEditor.requestService( "render.reselect" );
- updateInput( latexResult );
- drawCursorService();
- }
- evt.on( "mousemove", function ( e ) {
- var group = null;
- e.preventDefault();
- if ( isMousedown && !isDrag && ( Math.abs( e.clientX - mousedownPoint.x ) > dragThreshold || Math.abs( e.clientY - mousedownPoint.y ) > dragThreshold ) ) {
- isDrag = true;
- }
- if ( !isDrag ) {
- return;
- }
- hideCursor();
- var group = kfEditor.requestService( "position.get.group", e.target );
- if ( !group ) {
- group = kfEditor.requestService( "syntax.get.group.content", "_kf_editor_1_1" );
- }
- currentEndContainer = kfEditor.requestService( "syntax.get.group.content", group.id );
- currentEndOffset = getMoveIndex( currentEndContainer, e.clientX );
- kfEditor.requestService( "syntax.update.record.cursor", currentEndContainer.id, currentStartOffset, currentEndOffset );
- kfEditor.requestService( "render.select.current.cursor" );
- if ( currentStartOffset === currentEndOffset ) {
- // 起点是占位符, 则选中占位符
- if ( kfEditor.requestService( "syntax.valid.placeholder", group.id ) ) {
- kfEditor.requestService( "render.select.group", group.id );
- // 否则, 绘制光标
- } else {
- drawCursor( currentEndContainer, currentEndOffset );
- }
- }
- } );
- inp.oninput = function ( e ) {
- cursorIndex += inp.value.length - lastCount;
- kfEditor.requestService( "render.draw", inp.value );
- kfEditor.requestService( "render.reselect" );
- drawCursorService();
- };
- function drawCursorService () {
- var cursorInfo = kfEditor.requestService( "syntax.get.record.cursor" ),
- group = kfEditor.requestService( "syntax.get.group.content", cursorInfo.groupId );
- drawCursor( group, cursorInfo.startOffset );
- kfEditor.requestService( "render.select.group", cursorInfo.groupId );
- }
- function updateInput ( result ) {
- inp.value = result.str;
- inp.selectionStart = result.startOffset;
- inp.selectionEnd = result.endOffset;
- inp.focus();
- isAllowInput = true;
- }
- inp.onblur = function () {
- isAllowInput = false;
- hideCursor();
- };
- // 修正起始容器和结束容器指向不统一的情况
- function updateContainer ( startContainer, endContainer, offset ) {
- var parent = null,
- oldChild = null,
- startIsParent = false,
- child = null;
- if ( startContainer.groupObj.contains( endContainer.groupObj ) ) {
- startIsParent = true;
- parent = startContainer;
- child = endContainer;
- } else if ( endContainer.groupObj.contains( startContainer.groupObj ) ) {
- // 结束区域更大
- parent = endContainer;
- child = startContainer;
- } else {
- parent = endContainer;
- clearCount();
- while ( parent = kfEditor.requestService( "position.get.group", parent.groupObj ) ) {
- updateCount();
- if ( parent.groupObj.contains( startContainer.groupObj ) ) {
- break;
- }
- }
- child = startContainer;
- }
- oldChild = child;
- clearCount();
- while ( child = kfEditor.requestService( "position.get.parent.group", child.groupObj ) ) {
- updateCount();
- if ( child.id === parent.id ) {
- child = oldChild;
- break;
- }
- oldChild = child;
- }
- currentStartContainer = parent;
- currentEndContainer = parent;
- // 起点在大的区域内
- if ( startIsParent ) {
- currentStartOffset = ctrlStartOffset;
- currentEndOffset = parent.content.indexOf( child.groupObj );
- if ( currentEndOffset >= currentStartOffset ) {
- currentEndOffset += 1;
- }
- // 起点在小的区域内部
- } else {
- currentStartOffset = parent.content.indexOf( child.groupObj );
- currentEndOffset = getOffset( parent, offset );
- if ( offset < mousedownPoint.x ) {
- currentStartOffset += 1;
- } else {
- currentEndOffset += 1;
- }
- }
- }
- // 返回在索引指定的位置插入光标,也就是说该索引的位置是在当前元素“之前”
- function getIndex ( group, offset ) {
- var index = getOffset( group, offset ),
- overflow = -1,
- // 点击是否在前半段
- box = null;
- box = group.content[ index ].getBoundingClientRect();
- overflow = offset - box.left;
- if ( overflow > box.width / 2 ) {
- index += 1;
- }
- return index;
- }
- function getOffset ( group, offset ) {
- var index = -1,
- box = null;
- kity.Utils.each( group.content, function ( child, i ) {
- index = i;
- box = child.getBoundingClientRect();
- if ( box.left + box.width > offset ) {
- return false;
- }
- } );
- return index;
- }
- function getMoveIndex ( group, offset ) {
- currentStartContainer = ctrlStartContainer;
- currentStartOffset = ctrlStartOffset;
- // 直接更新
- if ( ctrlStartContainer.id !== group.id ) {
- updateContainer( ctrlStartContainer, group, offset );
- return currentEndOffset;
- }
- var index = -1,
- box = null,
- overflow = -1;
- kity.Utils.each( group.content, function ( child, i ) {
- index = i;
- box = child.getBoundingClientRect();
- if ( box.left + box.width > offset ) {
- return false;
- }
- } );
- box = group.content[ index ].getBoundingClientRect();
- overflow = offset - box.left;
- // 向后走
- if ( index >= ctrlStartOffset ) {
- if ( overflow > box.width / 3 ) {
- index += 1;
- }
- // 向前走
- } else {
- // 光标还在默认边界范围内
- if ( overflow > box.width / 3 * 2 ) {
- index += 1;
- }
- }
- return index;
- }
- function hideCursor () {
- isShowCursor = false;
- stopCursorBlinks();
- vCursor.node.style.display = 'none';
- }
- function drawCursor ( group, index ) {
- var target = null,
- isBefore = true,
- prevBox = null,
- box = null,
- cursorTransform = null;
- if ( !isAllowInput ) {
- return;
- }
- var paper = kfEditor.requestService( "render.get.paper" ),
- offset = paper.getViewPort().offset,
- offsetLeft = 0,
- canvasZoom = kfEditor.requestService( "render.get.canvas.zoom" ),
- formulaZoom = paper.getZoom();
- // 定位到最后
- if ( index === group.content.length ) {
- index -= 1;
- isBefore = false;
- }
- target = group.content[ index ];
- box = target.getBoundingClientRect();
- prevBox = group.content[ index - 1 ] || target;
- prevBox = prevBox.getBoundingClientRect();
- // 更新transform
- cursorTransform = vCursor.getTransform();
- if ( isBefore ) {
- offsetLeft = box.left - paper.container.node.getBoundingClientRect().left;
- } else {
- offsetLeft = box.left - paper.container.node.getBoundingClientRect().left + box.width;
- }
- cursorTransform.m.e = offsetLeft / canvasZoom/ formulaZoom;
- cursorTransform.m.f = ( prevBox.top - paper.container.node.getBoundingClientRect().top ) / canvasZoom / formulaZoom;
- vCursor.setHeight( prevBox.height / canvasZoom / formulaZoom );
- vCursor.setTransform( cursorTransform );
- vCursor.node.style.display = "block";
- isShowCursor = true;
- startCursorBlinks();
- }
- }
- function clearCount () {
- CALL_COUNT = 0;
- }
- function updateCount () {
- CALL_COUNT++;
- if ( CALL_COUNT > MAX_COUNT ) {
- throw new Error("stack overflow");
- }
- }
- function createVCursor ( editor ) {
- var paper = editor.execCommand( "getPaper" ),
- vCursor = new kity.Rect( 1, 27, 0, 0 ).fill( "black" );
- vCursor.node.style.display = "none";
- paper.addShape( vCursor );
- return vCursor;
- }
- function startCursorBlinks () {
- if ( CURSOR_BLINKS ) {
- window.clearInterval( CURSOR_BLINKS );
- }
- CURSOR_BLINKS = window.setInterval( toggleCursor, 800 );
- }
- function stopCursorBlinks () {
- window.clearInterval( CURSOR_BLINKS );
- }
- function toggleCursor () {
- vCursor.node.style.display = isShowCursor ? "none" : "block";
- isShowCursor = !isShowCursor;
- }
- window.c = c;
- } )();
|