Index: trunk/extensions/VisualEditor/contentEditable/main.js |
— | — | @@ -15,6 +15,13 @@ |
16 | 16 | } |
17 | 17 | }, |
18 | 18 | { |
| 19 | + 'type': 'textStyle/italic', |
| 20 | + 'range': { |
| 21 | + 'start': 10, |
| 22 | + 'end': 17 |
| 23 | + } |
| 24 | + }, |
| 25 | + { |
19 | 26 | 'type': 'object/template', |
20 | 27 | 'data': { |
21 | 28 | 'html': '<sup><small>[<a href="#">citation needed</a>]</small></sup>' |
— | — | @@ -38,7 +45,7 @@ |
39 | 46 | window.surfaceModel = new es.SurfaceModel( window.documentModel ); |
40 | 47 | window.surfaceView = new es.SurfaceView( $( '#es-editor' ), window.surfaceModel ); |
41 | 48 | |
42 | | - |
| 49 | + /* |
43 | 50 | $('#es-editor')[0].addEventListener("DOMSubtreeModified", function() { |
44 | 51 | var selection = rangy.getSelection(); |
45 | 52 | console.log(selection); |
— | — | @@ -51,6 +58,7 @@ |
52 | 59 | console.log(selection); |
53 | 60 | } |
54 | 61 | }); |
| 62 | + */ |
55 | 63 | |
56 | 64 | |
57 | 65 | /* |
Index: trunk/extensions/VisualEditor/contentEditable/views/es.SurfaceView.js |
— | — | @@ -13,34 +13,96 @@ |
14 | 14 | this.$.keydown( function(e) {
|
15 | 15 | return _this.onKeyDown( e );
|
16 | 16 | } );
|
17 | | -
|
| 17 | +
|
| 18 | + this.model.getDocument().on( 'update', function() {
|
| 19 | + _this.emit( 'update' );
|
| 20 | + } );
|
| 21 | +
|
18 | 22 | this.documentView.renderContent();
|
19 | 23 | };
|
20 | 24 |
|
21 | 25 | es.SurfaceView.prototype.onKeyDown = function( e ) {
|
22 | 26 | if ( e.which == 13 ) {
|
23 | 27 | e.preventDefault();
|
24 | | -
|
25 | | - console.log(this.getSelection());
|
| 28 | + var range = this.getSelection();
|
| 29 | + if ( range.start === range.end ) {
|
| 30 | + var tx = this.model.getDocument().prepareInsertion( range.start, [ { 'type': '/paragraph' }, { 'type': 'paragraph' } ]);
|
| 31 | + this.model.transact( tx );
|
| 32 | + }
|
26 | 33 | }
|
27 | 34 | };
|
28 | 35 |
|
29 | | -es.SurfaceView.prototype.getSelection = function() {
|
30 | | - var selection = rangy.getSelection();
|
31 | | -
|
32 | | - var node = selection.anchorNode;
|
33 | | - var $node = $( node );
|
| 36 | +es.SurfaceView.prototype.getOffset = function( localNode, localOffset ) {
|
| 37 | + var $node = $( localNode );
|
34 | 38 | while( !$node.hasClass( 'es-paragraphView' ) ) {
|
35 | 39 | $node = $node.parent();
|
36 | 40 | }
|
37 | | - var $contents = $node.contents();
|
38 | | - for( var i = 0; i < $contents.length; i++ ) {
|
39 | | - if ( $contents[i] == node ) {
|
40 | | - console.log(node);
|
| 41 | +
|
| 42 | + var traverse = function( data, callback ) {
|
| 43 | + var current = [ data, 0 ];
|
| 44 | + var stack = [ current ];
|
| 45 | +
|
| 46 | + while ( stack.length > 0 ) {
|
| 47 | + if ( current[1] >= current[0].length ) {
|
| 48 | + stack.pop();
|
| 49 | + current = stack[ stack.length - 1 ];
|
| 50 | + continue;
|
| 51 | + }
|
| 52 | + var item = current[0][current[1]];
|
| 53 | + var out = callback( item );
|
| 54 | + /*
|
| 55 | + * -1 = stop traversing
|
| 56 | + * 1 = deep traverse
|
| 57 | + * 0 = skip deep traverse |
| 58 | + */
|
| 59 | + if ( out === -1 ) {
|
| 60 | + return;
|
| 61 | + } else if ( out === 1 && item.nodeType === 1 ) {
|
| 62 | + stack.push( [ $(item).contents() , 0 ] );
|
| 63 | + current[1]++;
|
| 64 | + current = stack[stack.length-1];
|
| 65 | + continue;
|
| 66 | + }
|
| 67 | + current[1]++;
|
41 | 68 | }
|
| 69 | + };
|
| 70 | +
|
| 71 | + var offset = 0;
|
| 72 | +
|
| 73 | + traverse( $node.contents(), function( item ) {
|
| 74 | + if ( item.nodeType === 3 ) {
|
| 75 | + if ( item === localNode ) {
|
| 76 | + offset += localOffset;
|
| 77 | + return -1;
|
| 78 | + } else {
|
| 79 | + offset += item.textContent.length;
|
| 80 | +
|
| 81 | + }
|
| 82 | + } else {
|
| 83 | + if ( $( item ).attr('contentEditable') === "false" ) {
|
| 84 | + offset += 1;
|
| 85 | + return 0;
|
| 86 | + }
|
| 87 | + }
|
| 88 | + return 1;
|
| 89 | + } );
|
| 90 | +
|
| 91 | + return offset + 1 + this.documentView.getOffsetFromNode( $node.data('view') );
|
| 92 | +}
|
| 93 | +
|
| 94 | +es.SurfaceView.prototype.getSelection = function() {
|
| 95 | + var selection = rangy.getSelection();
|
| 96 | +
|
| 97 | + if ( selection.anchorNode === selection.focusNode && selection.anchorOffset === selection.focusOffset ) {
|
| 98 | + // only one offset
|
| 99 | + var offset = this.getOffset( selection.anchorNode, selection.anchorOffset );
|
| 100 | + return new es.Range( offset, offset );
|
| 101 | + } else {
|
| 102 | + // two offsets
|
| 103 | + var offset1 = this.getOffset( selection.anchorNode, selection.anchorOffset );
|
| 104 | + var offset2 = this.getOffset( selection.focusNode, selection.focusOffset );
|
| 105 | + return new es.Range( offset1, offset2 );
|
42 | 106 | }
|
43 | | -
|
44 | | - return 0;
|
45 | 107 | };
|
46 | 108 |
|
47 | 109 | /* Inheritance */
|
Index: trunk/extensions/VisualEditor/contentEditable/views/es.ContentView.js |
— | — | @@ -5,6 +5,14 @@ |
6 | 6 | // Properties
|
7 | 7 | this.$ = $container;
|
8 | 8 | this.model = model;
|
| 9 | +
|
| 10 | + if ( model ) {
|
| 11 | + // Events
|
| 12 | + var _this = this;
|
| 13 | + this.model.on( 'update', function( offset ) {
|
| 14 | + _this.render( offset || 0 );
|
| 15 | + } );
|
| 16 | + }
|
9 | 17 | }
|
10 | 18 |
|
11 | 19 |
|