Я работаю над визуальным редактором как веб-приложение, в основном XML-редактор, записанный в JavaScript.
Мой код JavaScript должен перенести выбор узлов от contentEditable контейнера отделения. Я использую методы, описанные в MDC. Но так как я должен синхронизировать содержание контейнеров отделения со своим XML DOM, я хотел бы избежать частичных выборов, как описано в диапазонах w3c:
Blah xyz.Title
............^----------------^............
Этот выбор запускает внутреннего H1 и заканчивается в P, я хотел бы, чтобы он включал H1, P полностью.
Существует ли простой способ расширить выбор для покрытия частично выбранных детей полностью? В основном я хочу использовать range.surroundContents (), не сталкиваясь с исключением.
(Код не должен работать с оперой/IE),
Глядя на документацию MDC, я могу сделать что-то вроде этого:
Selection.prototype.coverAll = function() {
var ranges = [];
for(var i=0; i<this.rangeCount; i++) {
var range = this.getRangeAt(i);
while(range.startContainer.nodeType == 3
|| range.startContainer.childNodes.length == 1)
range.setStartBefore(range.startContainer);
while(range.endContainer.nodeType == 3
|| range.endContainer.childNodes.length == 1)
range.setEndAfter(range.endContainer);
ranges.push(range);
}
this.removeAllRanges();
for(var i=0; i<ranges.length; i++) {
this.addRange(ranges[i]);
}
return;
};
Вы можете попробовать это здесь: http://jsfiddle.net/GFuX6/9/
edit: Обновлено, чтобы браузер корректно отображал расширенный выбор. Это делает то, что вы просили, даже если выделение содержит несколько диапазонов (с Ctrl).
Чтобы сделать несколько частичных узлов Bold, вот решение:
Selection.prototype.boldinize = function() {
this.coverAll();
for(var i=0; i<this.rangeCount; i++) {
var range = this.getRangeAt(i);
var parent = range.commonAncestorContainer;
var b = document.createElement('b');
if(parent.nodeType == 3) {
range.surroundContents(b);
} else {
var content = range.extractContents();
b.appendChild(content);
range.insertNode(b);
}
}
};
Если вы имеете в виду, что хотите включить теги H1 и P (т.е. допустимую разметку), не беспокойтесь. Вы получаете это бесплатно. Если вы имеете в виду, что хотите, чтобы он включал все содержимое в (частичный) выбор, вам необходимо получить доступ к объекту Selection. Прочтите об этом в Введение Quirksmode в Range .
Благодаря Alsciende я наконец придумал код на http://jsfiddle.net/wesUV/21/ . Этот метод не такой жадный, как другой. После функции coverAll () функция SurroundContents () всегда должна работать.
Selection.prototype.coverAll = function() {
var ranges = [];
for(var i=0; i<this.rangeCount; i++) {
var range = this.getRangeAt(i);
var ancestor = range.commonAncestorContainer;
if (ancestor.nodeType == 1) {
if (range.startContainer.parentNode != ancestor && this.containsNode(range.startContainer.parentNode, true)) {
range.setStartBefore(range.startContainer.parentNode);
}
if (range.endContainer.parentNode != ancestor && this.containsNode(range.endContainer.parentNode, true)) {
range.setEndAfter(range.endContainer.parentNode);
}
}
ranges.push(range);
}
this.removeAllRanges();
for(var i=0; i<ranges.length; i++) {
this.addRange(ranges[i]);
}
return;
};
И функция жирного шрифта:
Selection.prototype.boldinize = function() {
for(var i=0; i<this.rangeCount; i++) {
var range = this.getRangeAt(i);
var b = document.createElement('b');
try {
range.surroundContents(b);
} catch (e) {
alert(e);
}
}
};