mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 15:23:29 -05:00
Fix setTextAlignment command
And make propagating native events more elegant (only adds observer to document when first function added).
This commit is contained in:
parent
75109c404e
commit
aa8b4b7ac6
1 changed files with 61 additions and 42 deletions
103
source/Editor.js
103
source/Editor.js
|
@ -48,23 +48,12 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
|
|
||||||
// --- Events ---
|
// --- Events ---
|
||||||
|
|
||||||
var events = {};
|
var events = {},
|
||||||
var addEventListener = function ( type, fn ) {
|
customEvents = {
|
||||||
var handlers = events[ type ] || ( events[ type ] = [] );
|
cut: 1, paste: 1, focus: 1, blur: 1,
|
||||||
handlers.push( fn );
|
pathChange: 1, select: 1, input: 1, undoStateChange: 1
|
||||||
};
|
};
|
||||||
var removeEventListener = function ( type, fn ) {
|
|
||||||
var handlers = events[ type ],
|
|
||||||
l;
|
|
||||||
if ( handlers ) {
|
|
||||||
l = handlers.length;
|
|
||||||
while ( l-- ) {
|
|
||||||
if ( handlers[l] === fn ) {
|
|
||||||
handlers.splice( l, 1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var fireEvent = function ( type, event ) {
|
var fireEvent = function ( type, event ) {
|
||||||
var handlers = events[ type ],
|
var handlers = events[ type ],
|
||||||
l, obj;
|
l, obj;
|
||||||
|
@ -93,6 +82,36 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
fireEvent( event.type, event );
|
fireEvent( event.type, event );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var addEventListener = function ( type, fn ) {
|
||||||
|
var handlers = events[ type ];
|
||||||
|
if ( !handlers ) {
|
||||||
|
handlers = events[ type ] = [];
|
||||||
|
if ( !customEvents[ type ] ) {
|
||||||
|
doc.addEventListener( type, propagateEvent, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handlers.push( fn );
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeEventListener = function ( type, fn ) {
|
||||||
|
var handlers = events[ type ],
|
||||||
|
l;
|
||||||
|
if ( handlers ) {
|
||||||
|
l = handlers.length;
|
||||||
|
while ( l-- ) {
|
||||||
|
if ( handlers[l] === fn ) {
|
||||||
|
handlers.splice( l, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !handlers.length ) {
|
||||||
|
delete events[ type ];
|
||||||
|
if ( !customEvents[ type ] ) {
|
||||||
|
doc.removeEventListener( type, propagateEvent, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// --- Selection and Path ---
|
// --- Selection and Path ---
|
||||||
|
|
||||||
var createRange = function ( range, startOffset, endContainer, endOffset ) {
|
var createRange = function ( range, startOffset, endContainer, endOffset ) {
|
||||||
|
@ -130,11 +149,11 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
var lastFocusNode;
|
var lastFocusNode;
|
||||||
var path = '';
|
var path = '';
|
||||||
|
|
||||||
var updatePath = function () {
|
var updatePath = function ( force ) {
|
||||||
var anchor = sel.anchorNode,
|
var anchor = sel.anchorNode,
|
||||||
focus = sel.focusNode,
|
focus = sel.focusNode,
|
||||||
newPath;
|
newPath;
|
||||||
if ( anchor !== lastAnchorNode || focus !== lastFocusNode ) {
|
if ( force || anchor !== lastAnchorNode || focus !== lastFocusNode ) {
|
||||||
lastAnchorNode = anchor;
|
lastAnchorNode = anchor;
|
||||||
lastFocusNode = focus;
|
lastFocusNode = focus;
|
||||||
newPath = ( anchor && focus ) ? ( anchor === focus ) ?
|
newPath = ( anchor && focus ) ? ( anchor === focus ) ?
|
||||||
|
@ -143,13 +162,13 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
path = newPath;
|
path = newPath;
|
||||||
fireEvent( 'pathChange', newPath );
|
fireEvent( 'pathChange', newPath );
|
||||||
}
|
}
|
||||||
if ( anchor !== focus ) {
|
}
|
||||||
fireEvent( 'select' );
|
if ( anchor !== focus ) {
|
||||||
}
|
fireEvent( 'select' );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
body.addEventListener( 'keyup', updatePath, false );
|
addEventListener( 'keyup', updatePath );
|
||||||
body.addEventListener( 'mouseup', updatePath, false );
|
addEventListener( 'mouseup', updatePath );
|
||||||
|
|
||||||
var setSelection = function ( range ) {
|
var setSelection = function ( range ) {
|
||||||
if ( range ) {
|
if ( range ) {
|
||||||
|
@ -592,18 +611,19 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
|
|
||||||
var root = range.commonAncestorContainer,
|
var start = range.getStartBlock(),
|
||||||
walker = doc.createTreeWalker( root, SHOW_ELEMENT,
|
end = range.getEndBlock();
|
||||||
function ( node ) {
|
if ( start && end ) {
|
||||||
return range.containsNode( node, true ) && node.isBlock() ?
|
while ( true ) {
|
||||||
FILTER_ACCEPT : FILTER_SKIP;
|
fn( start );
|
||||||
}, false ),
|
if ( start === end ) { break; }
|
||||||
block;
|
start = start.getNextBlock();
|
||||||
|
}
|
||||||
while ( block = walker.nextNode() ) {
|
|
||||||
fn( block );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Path may have changed
|
||||||
|
updatePath( true );
|
||||||
|
|
||||||
// We're not still in an undo state
|
// We're not still in an undo state
|
||||||
docWasChanged();
|
docWasChanged();
|
||||||
};
|
};
|
||||||
|
@ -969,7 +989,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
setTimeout( function () {
|
setTimeout( function () {
|
||||||
body.fixCursor();
|
body.fixCursor();
|
||||||
}, 0 );
|
}, 0 );
|
||||||
});
|
}, false );
|
||||||
|
|
||||||
doc.addEventListener( isIE ? 'beforepaste' : 'paste', function () {
|
doc.addEventListener( isIE ? 'beforepaste' : 'paste', function () {
|
||||||
var range = getSelection(),
|
var range = getSelection(),
|
||||||
|
@ -1129,7 +1149,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
|
|
||||||
if ( !block.textContent ) {
|
if ( !block.textContent ) {
|
||||||
// Break list
|
// Break list
|
||||||
if ( block.nearest( 'UL' ) ) {
|
if ( block.nearest( 'UL' ) || block.nearest( 'OL' ) ) {
|
||||||
return modifyBlocks( decreaseListLevel, range );
|
return modifyBlocks( decreaseListLevel, range );
|
||||||
}
|
}
|
||||||
// Break blockquote
|
// Break blockquote
|
||||||
|
@ -1193,7 +1213,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
// to break lists/blockquote.
|
// to break lists/blockquote.
|
||||||
else {
|
else {
|
||||||
// Break list
|
// Break list
|
||||||
if ( current.nearest( 'UL' ) ) {
|
if ( current.nearest( 'UL' ) || current.nearest( 'OL' ) ) {
|
||||||
return modifyBlocks( decreaseListLevel, range );
|
return modifyBlocks( decreaseListLevel, range );
|
||||||
}
|
}
|
||||||
// Break blockquote
|
// Break blockquote
|
||||||
|
@ -1240,7 +1260,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
'ctrl-shift-z': mapKeyTo( redo )
|
'ctrl-shift-z': mapKeyTo( redo )
|
||||||
};
|
};
|
||||||
|
|
||||||
body.addEventListener( 'keydown', function ( event ) {
|
addEventListener( 'keydown', function ( event ) {
|
||||||
// Ref: http://unixpapa.com/js/key.html
|
// Ref: http://unixpapa.com/js/key.html
|
||||||
var code = event.keyCode || event.which,
|
var code = event.keyCode || event.which,
|
||||||
key = keys[ code ] || String.fromCharCode( code ).toLowerCase(),
|
key = keys[ code ] || String.fromCharCode( code ).toLowerCase(),
|
||||||
|
@ -1262,9 +1282,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
} else {
|
} else {
|
||||||
fireEvent( 'keydown', event );
|
fireEvent( 'keydown', event );
|
||||||
}
|
}
|
||||||
}, false );
|
});
|
||||||
body.addEventListener( 'keypress', propagateEvent, false );
|
|
||||||
body.addEventListener( 'keyup', propagateEvent, false );
|
|
||||||
|
|
||||||
// --- Export ---
|
// --- Export ---
|
||||||
|
|
||||||
|
@ -1406,7 +1424,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
undo: chain( undo ),
|
undo: chain( undo ),
|
||||||
redo: chain( redo ),
|
redo: chain( redo ),
|
||||||
|
|
||||||
hasFormat: chain( hasFormat ),
|
hasFormat: hasFormat,
|
||||||
changeFormat: chain( changeFormat ),
|
changeFormat: chain( changeFormat ),
|
||||||
|
|
||||||
bold: command( changeFormat, { tag: 'B' } ),
|
bold: command( changeFormat, { tag: 'B' } ),
|
||||||
|
@ -1461,6 +1479,7 @@ document.addEventListener( 'DOMContentLoaded', function () {
|
||||||
},
|
},
|
||||||
setTextAlignment: function ( dir ) {
|
setTextAlignment: function ( dir ) {
|
||||||
forEachBlock( function ( block ) {
|
forEachBlock( function ( block ) {
|
||||||
|
block.className = 'align-' + dir;
|
||||||
block.style.textAlign = dir;
|
block.style.textAlign = dir;
|
||||||
});
|
});
|
||||||
focus();
|
focus();
|
||||||
|
|
Loading…
Reference in a new issue