mirror of
https://github.com/fastmail/Squire.git
synced 2025-01-03 05:00:13 -05:00
Fix ZWS removal when Squire script not in iframe.
This commit is contained in:
parent
e7cef49818
commit
b944eb3b3b
7 changed files with 170 additions and 344 deletions
|
@ -3,8 +3,7 @@
|
||||||
( function ( doc, undefined ) {
|
( function ( doc, undefined ) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
/*global doc, navigator */
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var DOCUMENT_POSITION_PRECEDING = 2; // Node.DOCUMENT_POSITION_PRECEDING
|
var DOCUMENT_POSITION_PRECEDING = 2; // Node.DOCUMENT_POSITION_PRECEDING
|
||||||
var ELEMENT_NODE = 1; // Node.ELEMENT_NODE;
|
var ELEMENT_NODE = 1; // Node.ELEMENT_NODE;
|
||||||
|
@ -35,13 +34,13 @@ var ctrlKey = isMac ? 'meta-' : 'ctrl-';
|
||||||
var useTextFixer = isIE8or9or10 || isPresto;
|
var useTextFixer = isIE8or9or10 || isPresto;
|
||||||
var cantFocusEmptyTextNodes = isIE8or9or10 || isWebKit;
|
var cantFocusEmptyTextNodes = isIE8or9or10 || isWebKit;
|
||||||
var losesSelectionOnBlur = isIE8or9or10;
|
var losesSelectionOnBlur = isIE8or9or10;
|
||||||
var hasBuggySplit = ( function () {
|
var hasBuggySplit = function ( doc ) {
|
||||||
var div = doc.createElement( 'DIV' ),
|
var div = doc.createElement( 'DIV' ),
|
||||||
text = doc.createTextNode( '12' );
|
text = doc.createTextNode( '12' );
|
||||||
div.appendChild( text );
|
div.appendChild( text );
|
||||||
text.splitText( 2 );
|
text.splitText( 2 );
|
||||||
return div.childNodes.length !== 2;
|
return div.childNodes.length !== 2;
|
||||||
}() );
|
};
|
||||||
|
|
||||||
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
||||||
var notWS = /[^ \t\r\n]/;
|
var notWS = /[^ \t\r\n]/;
|
||||||
|
@ -137,20 +136,7 @@ TreeWalker.prototype.previousNode = function () {
|
||||||
current = node;
|
current = node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*global
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_ELEMENT,
|
|
||||||
win,
|
|
||||||
isOpera,
|
|
||||||
useTextFixer,
|
|
||||||
cantFocusEmptyTextNodes,
|
|
||||||
|
|
||||||
TreeWalker,
|
|
||||||
|
|
||||||
Text
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var inlineNodeNames = /^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|FN|EL)|EM|FONT|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TR(?:IKE|ONG)|MALL|AMP)?|U|VAR|WBR)$/;
|
var inlineNodeNames = /^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|FN|EL)|EM|FONT|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TR(?:IKE|ONG)|MALL|AMP)?|U|VAR|WBR)$/;
|
||||||
|
|
||||||
|
@ -282,6 +268,29 @@ function empty ( node ) {
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createElement ( doc, tag, props, children ) {
|
||||||
|
var el = doc.createElement( tag ),
|
||||||
|
attr, value, i, l;
|
||||||
|
if ( props instanceof Array ) {
|
||||||
|
children = props;
|
||||||
|
props = null;
|
||||||
|
}
|
||||||
|
if ( props ) {
|
||||||
|
for ( attr in props ) {
|
||||||
|
value = props[ attr ];
|
||||||
|
if ( value !== undefined ) {
|
||||||
|
el.setAttribute( attr, props[ attr ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( children ) {
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
el.appendChild( children[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
function fixCursor ( node ) {
|
function fixCursor ( node ) {
|
||||||
// In Webkit and Gecko, block level elements are collapsed and
|
// In Webkit and Gecko, block level elements are collapsed and
|
||||||
// unfocussable if they have no content. To remedy this, a <BR> must be
|
// unfocussable if they have no content. To remedy this, a <BR> must be
|
||||||
|
@ -289,7 +298,8 @@ function fixCursor ( node ) {
|
||||||
// cursor to appear.
|
// cursor to appear.
|
||||||
var doc = node.ownerDocument,
|
var doc = node.ownerDocument,
|
||||||
root = node,
|
root = node,
|
||||||
fixer, child;
|
fixer, child,
|
||||||
|
l, instance;
|
||||||
|
|
||||||
if ( node.nodeName === 'BODY' ) {
|
if ( node.nodeName === 'BODY' ) {
|
||||||
if ( !( child = node.firstChild ) || child.nodeName === 'BR' ) {
|
if ( !( child = node.firstChild ) || child.nodeName === 'BR' ) {
|
||||||
|
@ -315,8 +325,13 @@ function fixCursor ( node ) {
|
||||||
if ( !child ) {
|
if ( !child ) {
|
||||||
if ( cantFocusEmptyTextNodes ) {
|
if ( cantFocusEmptyTextNodes ) {
|
||||||
fixer = doc.createTextNode( '\u200B' );
|
fixer = doc.createTextNode( '\u200B' );
|
||||||
if ( win.editor ) {
|
// Find the relevant Squire instance and notify
|
||||||
win.editor._didAddZWS();
|
l = instances.length;
|
||||||
|
while ( l-- ) {
|
||||||
|
instance = instances[l];
|
||||||
|
if ( instance._doc === doc ) {
|
||||||
|
instance._didAddZWS();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fixer = doc.createTextNode( '' );
|
fixer = doc.createTextNode( '' );
|
||||||
|
@ -356,6 +371,42 @@ function fixCursor ( node ) {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recursively examine container nodes and wrap any inline children.
|
||||||
|
function fixContainer ( container ) {
|
||||||
|
var children = container.childNodes,
|
||||||
|
doc = container.ownerDocument,
|
||||||
|
wrapper = null,
|
||||||
|
i, l, child, isBR;
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
child = children[i];
|
||||||
|
isBR = child.nodeName === 'BR';
|
||||||
|
if ( !isBR && isInline( child ) ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
wrapper.appendChild( child );
|
||||||
|
i -= 1;
|
||||||
|
l -= 1;
|
||||||
|
} else if ( isBR || wrapper ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
fixCursor( wrapper );
|
||||||
|
if ( isBR ) {
|
||||||
|
container.replaceChild( wrapper, child );
|
||||||
|
} else {
|
||||||
|
container.insertBefore( wrapper, child );
|
||||||
|
i += 1;
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
wrapper = null;
|
||||||
|
}
|
||||||
|
if ( isContainer( child ) ) {
|
||||||
|
fixContainer( child );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( wrapper ) {
|
||||||
|
container.appendChild( fixCursor( wrapper ) );
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
function split ( node, offset, stopNode ) {
|
function split ( node, offset, stopNode ) {
|
||||||
var nodeType = node.nodeType,
|
var nodeType = node.nodeType,
|
||||||
parent, clone, next;
|
parent, clone, next;
|
||||||
|
@ -539,90 +590,7 @@ function mergeContainers ( node ) {
|
||||||
fixCursor( prev );
|
fixCursor( prev );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
// Recursively examine container nodes and wrap any inline children.
|
|
||||||
function fixContainer ( container ) {
|
|
||||||
var children = container.childNodes,
|
|
||||||
doc = container.ownerDocument,
|
|
||||||
wrapper = null,
|
|
||||||
i, l, child, isBR;
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
child = children[i];
|
|
||||||
isBR = child.nodeName === 'BR';
|
|
||||||
if ( !isBR && isInline( child ) ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
|
||||||
wrapper.appendChild( child );
|
|
||||||
i -= 1;
|
|
||||||
l -= 1;
|
|
||||||
} else if ( isBR || wrapper ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
|
||||||
fixCursor( wrapper );
|
|
||||||
if ( isBR ) {
|
|
||||||
container.replaceChild( wrapper, child );
|
|
||||||
} else {
|
|
||||||
container.insertBefore( wrapper, child );
|
|
||||||
i += 1;
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
wrapper = null;
|
|
||||||
}
|
|
||||||
if ( isContainer( child ) ) {
|
|
||||||
fixContainer( child );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( wrapper ) {
|
|
||||||
container.appendChild( fixCursor( wrapper ) );
|
|
||||||
}
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createElement ( doc, tag, props, children ) {
|
|
||||||
var el = doc.createElement( tag ),
|
|
||||||
attr, value, i, l;
|
|
||||||
if ( props instanceof Array ) {
|
|
||||||
children = props;
|
|
||||||
props = null;
|
|
||||||
}
|
|
||||||
if ( props ) {
|
|
||||||
for ( attr in props ) {
|
|
||||||
value = props[ attr ];
|
|
||||||
if ( value !== undefined ) {
|
|
||||||
el.setAttribute( attr, props[ attr ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( children ) {
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
el.appendChild( children[i] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
/*global
|
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_TEXT,
|
|
||||||
START_TO_START,
|
|
||||||
START_TO_END,
|
|
||||||
END_TO_END,
|
|
||||||
END_TO_START,
|
|
||||||
notWS,
|
|
||||||
indexOf,
|
|
||||||
|
|
||||||
TreeWalker,
|
|
||||||
|
|
||||||
isLeaf,
|
|
||||||
isInline,
|
|
||||||
isBlock,
|
|
||||||
getPreviousBlock,
|
|
||||||
getNextBlock,
|
|
||||||
getLength,
|
|
||||||
fixCursor,
|
|
||||||
split,
|
|
||||||
mergeWithBlock,
|
|
||||||
mergeContainers
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var getNodeBefore = function ( node, offset ) {
|
var getNodeBefore = function ( node, offset ) {
|
||||||
var children = node.childNodes;
|
var children = node.childNodes;
|
||||||
|
@ -1115,71 +1083,9 @@ var expandRangeToBlockBoundaries = function ( range ) {
|
||||||
range.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
range.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*global
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
DOCUMENT_POSITION_PRECEDING,
|
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_ELEMENT,
|
|
||||||
SHOW_TEXT,
|
|
||||||
win,
|
|
||||||
isIOS,
|
|
||||||
isMac,
|
|
||||||
isGecko,
|
|
||||||
isIE8or9or10,
|
|
||||||
isIE8,
|
|
||||||
isOpera,
|
|
||||||
ctrlKey,
|
|
||||||
useTextFixer,
|
|
||||||
cantFocusEmptyTextNodes,
|
|
||||||
losesSelectionOnBlur,
|
|
||||||
hasBuggySplit,
|
|
||||||
notWS,
|
|
||||||
indexOf,
|
|
||||||
|
|
||||||
TreeWalker,
|
var instances = [];
|
||||||
|
|
||||||
hasTagAttributes,
|
|
||||||
isLeaf,
|
|
||||||
isInline,
|
|
||||||
isBlock,
|
|
||||||
isContainer,
|
|
||||||
getBlockWalker,
|
|
||||||
getPreviousBlock,
|
|
||||||
getNextBlock,
|
|
||||||
getNearest,
|
|
||||||
getPath,
|
|
||||||
getLength,
|
|
||||||
detach,
|
|
||||||
replaceWith,
|
|
||||||
empty,
|
|
||||||
fixCursor,
|
|
||||||
split,
|
|
||||||
mergeInlines,
|
|
||||||
mergeWithBlock,
|
|
||||||
mergeContainers,
|
|
||||||
fixContainer,
|
|
||||||
createElement,
|
|
||||||
|
|
||||||
forEachTextNodeInRange,
|
|
||||||
getTextContentInRange,
|
|
||||||
insertNodeInRange,
|
|
||||||
extractContentsOfRange,
|
|
||||||
deleteContentsOfRange,
|
|
||||||
insertTreeFragmentIntoRange,
|
|
||||||
isNodeContainedInRange,
|
|
||||||
moveRangeBoundariesDownTree,
|
|
||||||
moveRangeBoundariesUpTree,
|
|
||||||
getStartBlockOfRange,
|
|
||||||
getEndBlockOfRange,
|
|
||||||
rangeDoesStartAtBlockBoundary,
|
|
||||||
rangeDoesEndAtBlockBoundary,
|
|
||||||
expandRangeToBlockBoundaries,
|
|
||||||
|
|
||||||
top,
|
|
||||||
console,
|
|
||||||
setTimeout
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
function Squire ( doc ) {
|
function Squire ( doc ) {
|
||||||
var win = doc.defaultView;
|
var win = doc.defaultView;
|
||||||
|
@ -1238,7 +1144,7 @@ function Squire ( doc ) {
|
||||||
// And even if the split is not at the end, the original node is removed
|
// And even if the split is not at the end, the original node is removed
|
||||||
// from the document and replaced by another, rather than just having its
|
// from the document and replaced by another, rather than just having its
|
||||||
// data shortened.
|
// data shortened.
|
||||||
if ( hasBuggySplit ) {
|
if ( hasBuggySplit( doc ) ) {
|
||||||
win.Text.prototype.splitText = function ( offset ) {
|
win.Text.prototype.splitText = function ( offset ) {
|
||||||
var afterSplit = this.ownerDocument.createTextNode(
|
var afterSplit = this.ownerDocument.createTextNode(
|
||||||
this.data.slice( offset ) ),
|
this.data.slice( offset ) ),
|
||||||
|
@ -1265,6 +1171,8 @@ function Squire ( doc ) {
|
||||||
doc.execCommand( 'enableObjectResizing', false, 'false' );
|
doc.execCommand( 'enableObjectResizing', false, 'false' );
|
||||||
doc.execCommand( 'enableInlineTableEditing', false, 'false' );
|
doc.execCommand( 'enableInlineTableEditing', false, 'false' );
|
||||||
} catch ( error ) {}
|
} catch ( error ) {}
|
||||||
|
|
||||||
|
instances.push( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
var proto = Squire.prototype;
|
var proto = Squire.prototype;
|
||||||
|
@ -1338,6 +1246,12 @@ proto.destroy = function () {
|
||||||
doc.removeEventListener( type, this, false );
|
doc.removeEventListener( type, this, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var l = instances.length;
|
||||||
|
while ( l-- ) {
|
||||||
|
if ( instances[l] === this ) {
|
||||||
|
instances.splice( l, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
proto.handleEvent = function ( event ) {
|
proto.handleEvent = function ( event ) {
|
||||||
|
@ -3501,7 +3415,6 @@ proto.removeList = command( 'modifyBlocks', removeList );
|
||||||
|
|
||||||
proto.increaseListLevel = command( 'modifyBlocks', increaseListLevel );
|
proto.increaseListLevel = command( 'modifyBlocks', increaseListLevel );
|
||||||
proto.decreaseListLevel = command( 'modifyBlocks', decreaseListLevel );
|
proto.decreaseListLevel = command( 'modifyBlocks', decreaseListLevel );
|
||||||
/*global top, win, doc, Squire */
|
|
||||||
|
|
||||||
if ( top !== win ) {
|
if ( top !== win ) {
|
||||||
win.editor = new Squire( doc );
|
win.editor = new Squire( doc );
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,4 @@
|
||||||
/*global doc, navigator */
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var DOCUMENT_POSITION_PRECEDING = 2; // Node.DOCUMENT_POSITION_PRECEDING
|
var DOCUMENT_POSITION_PRECEDING = 2; // Node.DOCUMENT_POSITION_PRECEDING
|
||||||
var ELEMENT_NODE = 1; // Node.ELEMENT_NODE;
|
var ELEMENT_NODE = 1; // Node.ELEMENT_NODE;
|
||||||
|
@ -30,13 +29,13 @@ var ctrlKey = isMac ? 'meta-' : 'ctrl-';
|
||||||
var useTextFixer = isIE8or9or10 || isPresto;
|
var useTextFixer = isIE8or9or10 || isPresto;
|
||||||
var cantFocusEmptyTextNodes = isIE8or9or10 || isWebKit;
|
var cantFocusEmptyTextNodes = isIE8or9or10 || isWebKit;
|
||||||
var losesSelectionOnBlur = isIE8or9or10;
|
var losesSelectionOnBlur = isIE8or9or10;
|
||||||
var hasBuggySplit = ( function () {
|
var hasBuggySplit = function ( doc ) {
|
||||||
var div = doc.createElement( 'DIV' ),
|
var div = doc.createElement( 'DIV' ),
|
||||||
text = doc.createTextNode( '12' );
|
text = doc.createTextNode( '12' );
|
||||||
div.appendChild( text );
|
div.appendChild( text );
|
||||||
text.splitText( 2 );
|
text.splitText( 2 );
|
||||||
return div.childNodes.length !== 2;
|
return div.childNodes.length !== 2;
|
||||||
}() );
|
};
|
||||||
|
|
||||||
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
||||||
var notWS = /[^ \t\r\n]/;
|
var notWS = /[^ \t\r\n]/;
|
||||||
|
|
|
@ -1,68 +1,6 @@
|
||||||
/*global
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
DOCUMENT_POSITION_PRECEDING,
|
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_ELEMENT,
|
|
||||||
SHOW_TEXT,
|
|
||||||
win,
|
|
||||||
isIOS,
|
|
||||||
isMac,
|
|
||||||
isGecko,
|
|
||||||
isIE8or9or10,
|
|
||||||
isIE8,
|
|
||||||
isOpera,
|
|
||||||
ctrlKey,
|
|
||||||
useTextFixer,
|
|
||||||
cantFocusEmptyTextNodes,
|
|
||||||
losesSelectionOnBlur,
|
|
||||||
hasBuggySplit,
|
|
||||||
notWS,
|
|
||||||
indexOf,
|
|
||||||
|
|
||||||
TreeWalker,
|
var instances = [];
|
||||||
|
|
||||||
hasTagAttributes,
|
|
||||||
isLeaf,
|
|
||||||
isInline,
|
|
||||||
isBlock,
|
|
||||||
isContainer,
|
|
||||||
getBlockWalker,
|
|
||||||
getPreviousBlock,
|
|
||||||
getNextBlock,
|
|
||||||
getNearest,
|
|
||||||
getPath,
|
|
||||||
getLength,
|
|
||||||
detach,
|
|
||||||
replaceWith,
|
|
||||||
empty,
|
|
||||||
fixCursor,
|
|
||||||
split,
|
|
||||||
mergeInlines,
|
|
||||||
mergeWithBlock,
|
|
||||||
mergeContainers,
|
|
||||||
fixContainer,
|
|
||||||
createElement,
|
|
||||||
|
|
||||||
forEachTextNodeInRange,
|
|
||||||
getTextContentInRange,
|
|
||||||
insertNodeInRange,
|
|
||||||
extractContentsOfRange,
|
|
||||||
deleteContentsOfRange,
|
|
||||||
insertTreeFragmentIntoRange,
|
|
||||||
isNodeContainedInRange,
|
|
||||||
moveRangeBoundariesDownTree,
|
|
||||||
moveRangeBoundariesUpTree,
|
|
||||||
getStartBlockOfRange,
|
|
||||||
getEndBlockOfRange,
|
|
||||||
rangeDoesStartAtBlockBoundary,
|
|
||||||
rangeDoesEndAtBlockBoundary,
|
|
||||||
expandRangeToBlockBoundaries,
|
|
||||||
|
|
||||||
top,
|
|
||||||
console,
|
|
||||||
setTimeout
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
function Squire ( doc ) {
|
function Squire ( doc ) {
|
||||||
var win = doc.defaultView;
|
var win = doc.defaultView;
|
||||||
|
@ -121,7 +59,7 @@ function Squire ( doc ) {
|
||||||
// And even if the split is not at the end, the original node is removed
|
// And even if the split is not at the end, the original node is removed
|
||||||
// from the document and replaced by another, rather than just having its
|
// from the document and replaced by another, rather than just having its
|
||||||
// data shortened.
|
// data shortened.
|
||||||
if ( hasBuggySplit ) {
|
if ( hasBuggySplit( doc ) ) {
|
||||||
win.Text.prototype.splitText = function ( offset ) {
|
win.Text.prototype.splitText = function ( offset ) {
|
||||||
var afterSplit = this.ownerDocument.createTextNode(
|
var afterSplit = this.ownerDocument.createTextNode(
|
||||||
this.data.slice( offset ) ),
|
this.data.slice( offset ) ),
|
||||||
|
@ -148,6 +86,8 @@ function Squire ( doc ) {
|
||||||
doc.execCommand( 'enableObjectResizing', false, 'false' );
|
doc.execCommand( 'enableObjectResizing', false, 'false' );
|
||||||
doc.execCommand( 'enableInlineTableEditing', false, 'false' );
|
doc.execCommand( 'enableInlineTableEditing', false, 'false' );
|
||||||
} catch ( error ) {}
|
} catch ( error ) {}
|
||||||
|
|
||||||
|
instances.push( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
var proto = Squire.prototype;
|
var proto = Squire.prototype;
|
||||||
|
@ -221,6 +161,12 @@ proto.destroy = function () {
|
||||||
doc.removeEventListener( type, this, false );
|
doc.removeEventListener( type, this, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var l = instances.length;
|
||||||
|
while ( l-- ) {
|
||||||
|
if ( instances[l] === this ) {
|
||||||
|
instances.splice( l, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
proto.handleEvent = function ( event ) {
|
proto.handleEvent = function ( event ) {
|
||||||
|
|
145
source/Node.js
145
source/Node.js
|
@ -1,17 +1,4 @@
|
||||||
/*global
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_ELEMENT,
|
|
||||||
win,
|
|
||||||
isOpera,
|
|
||||||
useTextFixer,
|
|
||||||
cantFocusEmptyTextNodes,
|
|
||||||
|
|
||||||
TreeWalker,
|
|
||||||
|
|
||||||
Text
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var inlineNodeNames = /^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|FN|EL)|EM|FONT|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TR(?:IKE|ONG)|MALL|AMP)?|U|VAR|WBR)$/;
|
var inlineNodeNames = /^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|FN|EL)|EM|FONT|HR|I(?:NPUT|MG|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:U[BP]|PAN|TR(?:IKE|ONG)|MALL|AMP)?|U|VAR|WBR)$/;
|
||||||
|
|
||||||
|
@ -143,6 +130,29 @@ function empty ( node ) {
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createElement ( doc, tag, props, children ) {
|
||||||
|
var el = doc.createElement( tag ),
|
||||||
|
attr, value, i, l;
|
||||||
|
if ( props instanceof Array ) {
|
||||||
|
children = props;
|
||||||
|
props = null;
|
||||||
|
}
|
||||||
|
if ( props ) {
|
||||||
|
for ( attr in props ) {
|
||||||
|
value = props[ attr ];
|
||||||
|
if ( value !== undefined ) {
|
||||||
|
el.setAttribute( attr, props[ attr ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( children ) {
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
el.appendChild( children[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
function fixCursor ( node ) {
|
function fixCursor ( node ) {
|
||||||
// In Webkit and Gecko, block level elements are collapsed and
|
// In Webkit and Gecko, block level elements are collapsed and
|
||||||
// unfocussable if they have no content. To remedy this, a <BR> must be
|
// unfocussable if they have no content. To remedy this, a <BR> must be
|
||||||
|
@ -150,7 +160,8 @@ function fixCursor ( node ) {
|
||||||
// cursor to appear.
|
// cursor to appear.
|
||||||
var doc = node.ownerDocument,
|
var doc = node.ownerDocument,
|
||||||
root = node,
|
root = node,
|
||||||
fixer, child;
|
fixer, child,
|
||||||
|
l, instance;
|
||||||
|
|
||||||
if ( node.nodeName === 'BODY' ) {
|
if ( node.nodeName === 'BODY' ) {
|
||||||
if ( !( child = node.firstChild ) || child.nodeName === 'BR' ) {
|
if ( !( child = node.firstChild ) || child.nodeName === 'BR' ) {
|
||||||
|
@ -176,8 +187,13 @@ function fixCursor ( node ) {
|
||||||
if ( !child ) {
|
if ( !child ) {
|
||||||
if ( cantFocusEmptyTextNodes ) {
|
if ( cantFocusEmptyTextNodes ) {
|
||||||
fixer = doc.createTextNode( '\u200B' );
|
fixer = doc.createTextNode( '\u200B' );
|
||||||
if ( win.editor ) {
|
// Find the relevant Squire instance and notify
|
||||||
win.editor._didAddZWS();
|
l = instances.length;
|
||||||
|
while ( l-- ) {
|
||||||
|
instance = instances[l];
|
||||||
|
if ( instance._doc === doc ) {
|
||||||
|
instance._didAddZWS();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fixer = doc.createTextNode( '' );
|
fixer = doc.createTextNode( '' );
|
||||||
|
@ -217,6 +233,42 @@ function fixCursor ( node ) {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recursively examine container nodes and wrap any inline children.
|
||||||
|
function fixContainer ( container ) {
|
||||||
|
var children = container.childNodes,
|
||||||
|
doc = container.ownerDocument,
|
||||||
|
wrapper = null,
|
||||||
|
i, l, child, isBR;
|
||||||
|
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||||
|
child = children[i];
|
||||||
|
isBR = child.nodeName === 'BR';
|
||||||
|
if ( !isBR && isInline( child ) ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
wrapper.appendChild( child );
|
||||||
|
i -= 1;
|
||||||
|
l -= 1;
|
||||||
|
} else if ( isBR || wrapper ) {
|
||||||
|
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||||
|
fixCursor( wrapper );
|
||||||
|
if ( isBR ) {
|
||||||
|
container.replaceChild( wrapper, child );
|
||||||
|
} else {
|
||||||
|
container.insertBefore( wrapper, child );
|
||||||
|
i += 1;
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
wrapper = null;
|
||||||
|
}
|
||||||
|
if ( isContainer( child ) ) {
|
||||||
|
fixContainer( child );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( wrapper ) {
|
||||||
|
container.appendChild( fixCursor( wrapper ) );
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
function split ( node, offset, stopNode ) {
|
function split ( node, offset, stopNode ) {
|
||||||
var nodeType = node.nodeType,
|
var nodeType = node.nodeType,
|
||||||
parent, clone, next;
|
parent, clone, next;
|
||||||
|
@ -400,62 +452,3 @@ function mergeContainers ( node ) {
|
||||||
fixCursor( prev );
|
fixCursor( prev );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively examine container nodes and wrap any inline children.
|
|
||||||
function fixContainer ( container ) {
|
|
||||||
var children = container.childNodes,
|
|
||||||
doc = container.ownerDocument,
|
|
||||||
wrapper = null,
|
|
||||||
i, l, child, isBR;
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
child = children[i];
|
|
||||||
isBR = child.nodeName === 'BR';
|
|
||||||
if ( !isBR && isInline( child ) ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
|
||||||
wrapper.appendChild( child );
|
|
||||||
i -= 1;
|
|
||||||
l -= 1;
|
|
||||||
} else if ( isBR || wrapper ) {
|
|
||||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
|
||||||
fixCursor( wrapper );
|
|
||||||
if ( isBR ) {
|
|
||||||
container.replaceChild( wrapper, child );
|
|
||||||
} else {
|
|
||||||
container.insertBefore( wrapper, child );
|
|
||||||
i += 1;
|
|
||||||
l += 1;
|
|
||||||
}
|
|
||||||
wrapper = null;
|
|
||||||
}
|
|
||||||
if ( isContainer( child ) ) {
|
|
||||||
fixContainer( child );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( wrapper ) {
|
|
||||||
container.appendChild( fixCursor( wrapper ) );
|
|
||||||
}
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createElement ( doc, tag, props, children ) {
|
|
||||||
var el = doc.createElement( tag ),
|
|
||||||
attr, value, i, l;
|
|
||||||
if ( props instanceof Array ) {
|
|
||||||
children = props;
|
|
||||||
props = null;
|
|
||||||
}
|
|
||||||
if ( props ) {
|
|
||||||
for ( attr in props ) {
|
|
||||||
value = props[ attr ];
|
|
||||||
if ( value !== undefined ) {
|
|
||||||
el.setAttribute( attr, props[ attr ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( children ) {
|
|
||||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
|
||||||
el.appendChild( children[i] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,28 +1,4 @@
|
||||||
/*global
|
/*jshint strict:false, undef:false, unused:false */
|
||||||
ELEMENT_NODE,
|
|
||||||
TEXT_NODE,
|
|
||||||
SHOW_TEXT,
|
|
||||||
START_TO_START,
|
|
||||||
START_TO_END,
|
|
||||||
END_TO_END,
|
|
||||||
END_TO_START,
|
|
||||||
notWS,
|
|
||||||
indexOf,
|
|
||||||
|
|
||||||
TreeWalker,
|
|
||||||
|
|
||||||
isLeaf,
|
|
||||||
isInline,
|
|
||||||
isBlock,
|
|
||||||
getPreviousBlock,
|
|
||||||
getNextBlock,
|
|
||||||
getLength,
|
|
||||||
fixCursor,
|
|
||||||
split,
|
|
||||||
mergeWithBlock,
|
|
||||||
mergeContainers
|
|
||||||
*/
|
|
||||||
/*jshint strict:false */
|
|
||||||
|
|
||||||
var getNodeBefore = function ( node, offset ) {
|
var getNodeBefore = function ( node, offset ) {
|
||||||
var children = node.childNodes;
|
var children = node.childNodes;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/*global top, win, doc, Squire */
|
|
||||||
|
|
||||||
if ( top !== win ) {
|
if ( top !== win ) {
|
||||||
win.editor = new Squire( doc );
|
win.editor = new Squire( doc );
|
||||||
|
|
Loading…
Reference in a new issue