Skip to content

Commit

Permalink
Fix webkit unable to select content with ctrl+a if uneditable element…
Browse files Browse the repository at this point in the history
… is first or last in editable area
  • Loading branch information
Oliver Pulges committed Jul 31, 2015
1 parent f4740a2 commit ea97249
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/dom/remove_empty_text_nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ wysihtml5.dom.removeEmptyTextNodes = function(node) {
childNodes = wysihtml5.lang.array(node.childNodes).get(),
childNodesLength = childNodes.length,
i = 0;

for (; i<childNodesLength; i++) {
childNode = childNodes[i];
if (childNode.nodeType === wysihtml5.TEXT_NODE && childNode.data === "") {
if (childNode.nodeType === wysihtml5.TEXT_NODE && (/^[\n\r]*$/).test(childNode.data)) {
childNode.parentNode.removeChild(childNode);
}
}
Expand Down
90 changes: 90 additions & 0 deletions src/selection/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,50 @@
return ret;
}

function getWebkitSelectionFixNode(container) {
var blankNode = document.createElement('span');

var placeholderRemover = function(event) {
// Self-destructs the caret and keeps the text inserted into it by user
var lastChild;

container.removeEventListener('mouseup', placeholderRemover);
container.removeEventListener('keydown', placeholderRemover);
container.removeEventListener('touchstart', placeholderRemover);
container.removeEventListener('focus', placeholderRemover);
container.removeEventListener('blur', placeholderRemover);
container.removeEventListener('paste', delayedPlaceholderRemover);
container.removeEventListener('drop', delayedPlaceholderRemover);
container.removeEventListener('beforepaste', delayedPlaceholderRemover);

if (blankNode && blankNode.parentNode) {
blankNode.parentNode.removeChild(blankNode);
}
},
delayedPlaceholderRemover = function (event) {
if (blankNode && blankNode.parentNode) {
setTimeout(placeholderRemover, 0);
}
};

blankNode.appendChild(document.createTextNode(wysihtml5.INVISIBLE_SPACE));
blankNode.className = '_wysihtml5-temp-caret-fix';
blankNode.style.display = 'block';
blankNode.style.minWidth = '1px';
blankNode.style.height = '0px';

container.addEventListener('mouseup', placeholderRemover);
container.addEventListener('keydown', placeholderRemover);
container.addEventListener('touchstart', placeholderRemover);
container.addEventListener('focus', placeholderRemover);
container.addEventListener('blur', placeholderRemover);
container.addEventListener('paste', delayedPlaceholderRemover);
container.addEventListener('drop', delayedPlaceholderRemover);
container.addEventListener('beforepaste', delayedPlaceholderRemover);

return blankNode;
}

// Should fix the obtained ranges that cannot surrond contents normally to apply changes upon
// Being considerate to firefox that sets range start start out of span and end inside on doubleclick initiated selection
function expandRangeToSurround(range) {
Expand Down Expand Up @@ -1096,6 +1140,52 @@
return (selection && selection.anchorNode && selection.focusNode) ? selection : null;
},



// Webkit has an ancient error of not selecting all contents when uneditable block element is first or last in editable area
selectAll: function() {
var range = this.createRange(),
composer = this.composer,
that = this,
blankEndNode = getWebkitSelectionFixNode(this.composer.element),
blankStartNode = getWebkitSelectionFixNode(this.composer.element),
s;

var doSelect = function() {
range.setStart(composer.element, 0);
range.setEnd(composer.element, composer.element.childNodes.length);
s = that.setSelection(range);
};

var notSelected = function() {
return !s || (s.nativeSelection && s.nativeSelection.type && (s.nativeSelection.type === "Caret" || s.nativeSelection.type === "None"));
}

wysihtml5.dom.removeInvisibleSpaces(this.composer.element);
doSelect();

if (this.composer.element.firstChild && notSelected()) {
// Try fixing end
this.composer.element.appendChild(blankEndNode);
doSelect();

if (notSelected()) {
// Remove end fix
blankEndNode.parentNode.removeChild(blankEndNode);

// Try fixing beginning
this.composer.element.insertBefore(blankStartNode, this.composer.element.firstChild);
doSelect();

if (notSelected()) {
// Try fixing both
this.composer.element.appendChild(blankEndNode);
doSelect();
}
}
}
},

createRange: function() {
return rangy.createRange(this.doc);
},
Expand Down
7 changes: 7 additions & 0 deletions src/views/composer.observe.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,13 @@
command = shortcuts[keyCode],
target, parent;

// Select all (meta/ctrl + a)
if ((event.ctrlKey || event.metaKey) && keyCode === 65) {
this.selection.selectAll();
event.preventDefault();
return;
}

// Shortcut logic
if ((event.ctrlKey || event.metaKey) && !event.altKey && command) {
this.commands.exec(command);
Expand Down

0 comments on commit ea97249

Please sign in to comment.