0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00
Squire/source/Clipboard.js
2015-07-11 19:22:46 +07:00

161 lines
5.3 KiB
JavaScript

/*jshint strict:false, undef:false, unused:false */
var onCut = function () {
// Save undo checkpoint
var range = this.getSelection();
var self = this;
this._recordUndoState( range );
this._getRangeAndRemoveBookmark( range );
this.setSelection( range );
setTimeout( function () {
try {
// If all content removed, ensure div at start of body.
self._ensureBottomLine();
} catch ( error ) {
self.didError( error );
}
}, 0 );
};
var onPaste = function ( event ) {
var clipboardData = event.clipboardData,
items = clipboardData && clipboardData.items,
fireDrop = false,
hasImage = false,
plainItem = null,
self = this,
l, item, type;
// Current HTML5 Clipboard interface
// ---------------------------------
// https://html.spec.whatwg.org/multipage/interaction.html
if ( items ) {
event.preventDefault();
l = items.length;
while ( l-- ) {
item = items[l];
type = item.type;
if ( type === 'text/html' ) {
/*jshint loopfunc: true */
item.getAsString( function ( html ) {
self.insertHTML( html, true );
});
/*jshint loopfunc: false */
return;
}
if ( type === 'text/plain' ) {
plainItem = item;
}
if ( /^image\/.*/.test( type ) ) {
hasImage = true;
}
}
// Treat image paste as a drop of an image file.
if ( hasImage ) {
this.fireEvent( 'dragover', {
dataTransfer: clipboardData,
/*jshint loopfunc: true */
preventDefault: function () {
fireDrop = true;
}
/*jshint loopfunc: false */
});
if ( fireDrop ) {
this.fireEvent( 'drop', {
dataTransfer: clipboardData
});
}
} else if ( plainItem ) {
item.getAsString( function ( text ) {
self.insertPlainText( text, true );
});
}
return;
}
// Old interface
// -------------
if ( clipboardData ) {
if ( indexOf.call( clipboardData.types, 'text/html' ) > -1 ) {
event.preventDefault();
this.insertHTML( clipboardData.getData( 'text/html' ), true );
return;
}
// Safari (and indeed many other OS X apps) copies stuff as text/rtf
// rather than text/html; even from a webpage in Safari. The only way
// to get an HTML version is to fallback to letting the browser insert
// the content. *Sigh*.
else if ( indexOf.call( clipboardData.types, 'text/rtf' ) === -1 ) {
event.preventDefault();
this.insertPlainText( clipboardData.getData( 'text/plain' ), true );
return;
}
}
// No interface :(
// ---------------
this._awaitingPaste = true;
var body = this._body,
range = this.getSelection(),
startContainer = range.startContainer,
startOffset = range.startOffset,
endContainer = range.endContainer,
endOffset = range.endOffset,
startBlock = getStartBlockOfRange( range );
// We need to position the pasteArea in the visible portion of the screen
// to stop the browser auto-scrolling.
var pasteArea = this.createElement( 'DIV', {
style: 'position: absolute; overflow: hidden; top:' +
( body.scrollTop +
( startBlock ? startBlock.getBoundingClientRect().top : 0 ) ) +
'px; right: 150%; width: 1px; height: 1px;'
});
body.appendChild( pasteArea );
range.selectNodeContents( pasteArea );
this.setSelection( range );
// A setTimeout of 0 means this is added to the back of the
// single javascript thread, so it will be executed after the
// paste event.
setTimeout( function () {
try {
// IE sometimes fires the beforepaste event twice; make sure it is
// not run again before our after paste function is called.
self._awaitingPaste = false;
// Get the pasted content and clean
var html = '',
next = pasteArea,
first, range;
// #88: Chrome can apparently split the paste area if certain
// content is inserted; gather them all up.
while ( pasteArea = next ) {
next = pasteArea.nextSibling;
detach( pasteArea );
// Safari and IE like putting extra divs around things.
first = pasteArea.firstChild;
if ( first && first === pasteArea.lastChild &&
first.nodeName === 'DIV' ) {
pasteArea = first;
}
html += pasteArea.innerHTML;
}
range = self._createRange(
startContainer, startOffset, endContainer, endOffset );
self.setSelection( range );
if ( html ) {
self.insertHTML( html, true );
}
} catch ( error ) {
self.didError( error );
}
}, 0 );
};