mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 07:13:08 -05:00
If all text in inline tag deleted, remove tag.
This commit is contained in:
parent
819ddb296e
commit
e4b5ea6ee8
5 changed files with 84 additions and 44 deletions
70
Demo.html
70
Demo.html
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>HTML Editor Test</title>
|
||||
<style type="text/css" media="screen">
|
||||
body {
|
||||
<meta charset="UTF-8">
|
||||
<title>HTML Editor Test</title>
|
||||
<style type="text/css" media="screen">
|
||||
body {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
padding: 50px;
|
||||
|
@ -15,33 +15,33 @@
|
|||
h1 {
|
||||
font-size: 1.95em;
|
||||
}
|
||||
iframe {
|
||||
border: 1px solid #888;
|
||||
}
|
||||
span {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
</style>
|
||||
<!--[if IE 8]>
|
||||
iframe {
|
||||
border: 1px solid #888;
|
||||
}
|
||||
span {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
</style>
|
||||
<!--[if IE 8]>
|
||||
<script type="text/javascript" src="build/ie8.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var editor;
|
||||
document.addEventListener( 'click', function ( e ) {
|
||||
var id = e.target.id,
|
||||
value;
|
||||
if ( id && editor && editor[ id ] ) {
|
||||
if ( e.target.className === 'prompt' ) {
|
||||
value = prompt( 'Value:' );
|
||||
}
|
||||
editor[ id ]( value );
|
||||
}
|
||||
}, false );
|
||||
</script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var editor;
|
||||
document.addEventListener( 'click', function ( e ) {
|
||||
var id = e.target.id,
|
||||
value;
|
||||
if ( id && editor && editor[ id ] ) {
|
||||
if ( e.target.className === 'prompt' ) {
|
||||
value = prompt( 'Value:' );
|
||||
}
|
||||
editor[ id ]( value );
|
||||
}
|
||||
}, false );
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HTML Editor Test</h1>
|
||||
|
@ -65,17 +65,17 @@
|
|||
<span id="makeLink" class="prompt">Link</span>
|
||||
</p>
|
||||
<p>
|
||||
<span id="increaseQuoteLevel">Quote</span>
|
||||
<span id="decreaseQuoteLevel">Dequote</span>
|
||||
<span id="increaseQuoteLevel">Quote</span>
|
||||
<span id="decreaseQuoteLevel">Dequote</span>
|
||||
|
||||
<span id="makeUnorderedList">List</span>
|
||||
<span id="removeList">Unlist</span>
|
||||
<span id="makeUnorderedList">List</span>
|
||||
<span id="removeList">Unlist</span>
|
||||
|
||||
<span id="insertImage" class="prompt">Insert image</span>
|
||||
<span id="setHTML" class="prompt">Set HTML</span>
|
||||
|
||||
<span id="undo">Undo</span>
|
||||
<span id="redo">Redo</span>
|
||||
<span id="undo">Undo</span>
|
||||
<span id="redo">Redo</span>
|
||||
</p>
|
||||
</header>
|
||||
<iframe src="build/document.html" onload="top.editor=this.contentWindow.editor" width="500" height="500"></iframe>
|
||||
|
|
|
@ -19,7 +19,7 @@ Unlike other HTML5 rich text editors, Squire was written as a component for writ
|
|||
|
||||
### Powerful ###
|
||||
|
||||
Squire provides an engine that handles the heavy work for you, making it easy to
|
||||
Squire provides an engine that handles the heavy work for you, making it easy to
|
||||
add extra features. With the `changeFormat` method you can easily add or remove any inline formatting you wish. And the `modifyBlocks` method can be used to make complicated block-level changes in a relatively easy manner.
|
||||
|
||||
If you need more commands than in the simple API, I suggest you check out the source code (it's not very long), and see how a lot of the other API methods are implemented in terms of these two methods.
|
||||
|
@ -37,7 +37,7 @@ Installation and usage
|
|||
4. In your JS, attach an event listener to the `load` event of the iframe. When
|
||||
this fires you can grab a reference to the editor object through
|
||||
`iframe.contentWindow.editor`.
|
||||
5. Use the API below with the `editor` object to set and get data and integrate
|
||||
5. Use the API below with the `editor` object to set and get data and integrate
|
||||
with your application or framework.
|
||||
|
||||
License
|
||||
|
@ -66,7 +66,7 @@ Attach an event listener to the editor. The handler can be either a function or
|
|||
#### Parameters ####
|
||||
|
||||
* **type**: The event to listen for. e.g. 'focus'.
|
||||
* **handler**: The callback function to invoke
|
||||
* **handler**: The callback function to invoke
|
||||
|
||||
#### Returns ####
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -354,7 +354,7 @@
|
|||
range.setStart( _range.startContainer, _range.startOffset );
|
||||
range.setEnd( _range.endContainer, _range.endOffset );
|
||||
collapsed = range.collapsed;
|
||||
|
||||
|
||||
range.moveBoundariesDownTree();
|
||||
if ( collapsed ) {
|
||||
range.collapse( true );
|
||||
|
@ -1235,7 +1235,7 @@
|
|||
while ( node = node.getNextBlock() ) {
|
||||
node.fixCursor();
|
||||
}
|
||||
|
||||
|
||||
fireEvent( 'willPaste', {
|
||||
fragment: frag,
|
||||
preventDefault: function () {
|
||||
|
@ -1288,6 +1288,38 @@
|
|||
};
|
||||
};
|
||||
|
||||
// If you delete the content inside a span with a font styling, Webkit will
|
||||
// replace it with a <font> tag (!). If you delete all the text inside a
|
||||
// link in Opera, it won't delete the link. Let's make things consistent. If
|
||||
// you delete all text inside an inline tag, remove the inline tag.
|
||||
var afterDelete = function () {
|
||||
var range = getSelection(),
|
||||
node = range.startContainer,
|
||||
parent;
|
||||
node = node.nodeType === TEXT_NODE ?
|
||||
node.length ? null : node.parentNode :
|
||||
node.isInline() && !node.textContent ? node : null;
|
||||
|
||||
// If focussed in empty inline element
|
||||
if ( node ) {
|
||||
do {
|
||||
parent = node.parentNode;
|
||||
} while ( parent.isInline() &&
|
||||
!parent.textContent && ( node = parent ) );
|
||||
range.setStart( parent,
|
||||
indexOf.call( parent.childNodes, node ) );
|
||||
range.collapse( true );
|
||||
parent.removeChild( node );
|
||||
if ( !parent.isBlock() ) {
|
||||
parent = parent.getPreviousBlock();
|
||||
}
|
||||
parent.fixCursor();
|
||||
range.moveBoundariesDownTree();
|
||||
setSelection( range );
|
||||
updatePath( range );
|
||||
}
|
||||
};
|
||||
|
||||
var keyHandlers = {
|
||||
enter: function ( event ) {
|
||||
// We handle this ourselves
|
||||
|
@ -1469,7 +1501,11 @@
|
|||
updatePath( range, true );
|
||||
}
|
||||
}
|
||||
// All other cases can be safely left to the browser (I hope!).
|
||||
// Otherwise, leave to browser but check afterwards whether it has
|
||||
// left behind an empty inline tag.
|
||||
else {
|
||||
setTimeout( afterDelete, 0 );
|
||||
}
|
||||
},
|
||||
'delete': function ( event ) {
|
||||
var range = getSelection();
|
||||
|
@ -1501,7 +1537,11 @@
|
|||
updatePath( range, true );
|
||||
}
|
||||
}
|
||||
// All other cases can be safely left to the browser (I hope!).
|
||||
// Otherwise, leave to browser but check afterwards whether it has
|
||||
// left behind an empty inline tag.
|
||||
else {
|
||||
setTimeout( afterDelete, 0 );
|
||||
}
|
||||
},
|
||||
space: function () {
|
||||
var range = getSelection();
|
||||
|
|
|
@ -31,7 +31,7 @@ var every = function ( nodeList, fn ) {
|
|||
var $False = function () { return false; };
|
||||
var $True = function () { return true; };
|
||||
|
||||
var inlineNodeNames = /^(?:A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:FN|EL)|EM|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TRONG|AMP)|U)$/;
|
||||
var inlineNodeNames = /^(?:A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:FN|EL)|EM|FONT|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TRONG|AMP)|U)$/;
|
||||
|
||||
var leafNodeNames = {
|
||||
BR: 1,
|
||||
|
|
Loading…
Reference in a new issue