Получить родительский узел из выбора (диапазона) в Gecko и Webkit

Я пытаюсь добавить атрибут при использовании редактора wysiwyg, который использует команду «createLink». Я думал, что было бы тривиально вернуть узел, созданный после выполнения этой команды.

Оказывается, я могу захватить только что созданный узел в IE. Любые идеи?

Следующий код демонстрирует проблему (журналы отладки внизу показывают разные выходные данные в каждом браузере):

var getSelectedHTML = function() {
    if ($.browser.msie) {
        return this.getRange().htmlText;
    } else {
        var elem = this.getRange().cloneContents();
        return $("<p/>").append($(elem)).html();
    }
};

var getSelection = function() {
    if ($.browser.msie) {
        return this.editor.selection;
    } else {
        return this.iframe[0].contentDocument.defaultView.getSelection();
    }
};

var getRange = function() {
    var s = this.getSelection();
    return (s.getRangeAt) ? s.getRangeAt(0) : s.createRange();
};

var getSelectedNode = function() {
    var range = this.getRange();
    var parent = range.commonAncestorContainer ? range.commonAncestorContainer : 
                    range.parentElement ? range.parentElement(): 
                    range.item(0);
    return parent;
};


// **** INSIDE SOME EVENT HANDLER ****

if ($.browser.msie) {
    this.ec("createLink", true);
} else {
    this.ec("createLink", false, prompt("Link URL:", "http://"));
}

var linkNode = $(this.getSelectedNode());
linkNode.attr("rel", "external");

$.log(linkNode.get(0).tagName);
    // Gecko: "body"
    // IE: "a"
    // Webkit: "undefined"

$.log(this.getSelectedHTML());
    // Gecko: "<a href="http://site.com">foo</a>"
    // IE: "<A href="http://site.com" rel=external>foo</A>"
    // Webkit: "foo"

$.log(this.getSelection());
    // Gecko: "foo"
    // IE: [object Selection]
    // Webkit: "foo"

Спасибо за любую помощь в этом, я безуспешно просматривал связанные вопросы на SO!


person Jason    schedule 22.03.2010    source источник
comment
@jason - Что-то не так с моим ответом? Я еще не слышал от вас никаких отзывов...   -  person gnarf    schedule 01.04.2010
comment
Извините, ваш пример работает, и код почти такой же, как у меня, только более компактный. Тем не менее, это все еще не работает для моей реализации, мне интересно, может ли это быть как-то связано с вмешательством редактора iframe или браузера. Я обновлю, когда он полностью заработает. Спасибо за помощь!   -  person Jason    schedule 02.04.2010


Ответы (3)


Это код, который я использовал для получения «parentNode» текстового курсора:

var getSelectedNode = function() {
    var node,selection;
    if (window.getSelection) {
      selection = getSelection();
      node = selection.anchorNode;
    }
    if (!node && document.selection) {
        selection = document.selection
        var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
        node = range.commonAncestorContainer ? range.commonAncestorContainer :
               range.parentElement ? range.parentElement() : range.item(0);
    }
    if (node) {
      return (node.nodeName == "#text" ? node.parentNode : node);
    }
};

Я изменил свой метод IE, чтобы приблизить его к вашему. Протестированы и работают IE8, FF3.6, Safari4, Chrome5. Я установил предварительный просмотр jsbin, который вы можете протестировать.

person gnarf    schedule 26.03.2010
comment
@jason - См. также этот ответ: stackoverflow.com/questions/2459180/ может помочь... пожимает плечами - person gnarf; 04.05.2010

Я обнаружил, что выбор может быть сложным и содержать ошибки в разных браузерах. Добавьте магию редактирования документов в браузере, и станет еще хуже!

Я посмотрел, как TinyMCE реализует то, что я пытаюсь сделать, и применил тот же подход к изменению jHtmlArea.

По сути, ссылка создается с поддельным href. Затем он находит этот элемент dom путем поиска ссылок с этим конкретным href. Затем вы можете добавить любые желаемые атрибуты и обновить href фактическим URL-адресом.

Решение выше от gnarf — отличный пример получения выбранного узла, и он будет работать для большинства сценариев.

Ниже приведен код для моей работы:

var url = prompt("Link URL:", "http://");

if (!url) {
    return;
}

// Create a link, with a magic temp href
this.ec("createLink", false, "#temp_url#");

// Find the link in the editor using the magic temp href
var linkNode = $(this.editor.body).find("a[href='#temp_url#']");

linkNode.attr("rel", "external");

// Apply the actual desired url
linkNode.attr("href", url);
person Jason    schedule 04.05.2010

Это хакерский обходной путь, но он должен работать, если кто-то не сделает две одинаковые ссылки.

this.getSelection() кажется одинаковым в обоих необходимых браузерах, поэтому:

var link=prompt('gimme link');

//add the thing

var text=this.getSelection();

var whatYouNeed=$('a:contains("'+text+'")[href="'+link+'"');
person naugtur    schedule 26.03.2010