Замените только текст на веб-странице, чтобы создать ссылку - PullRequest
1 голос
/ 16 октября 2010

Я хотел бы изменить текст в документе в виде даты и заменить его ссылкой, чтобы добавить событие с этой датой в Календарь Google.У меня в основном это работает с одним предупреждением, он пытается добавить ссылку внутри уже существующих ссылок, в которых есть даты.

document.body.innerHTML = document.body.innerHTML.replace(arrayDates[i], arrayDates[i] + " <a href=\"http://www.google.com/calendar/event?action=TEMPLATE&text=someevent&dates=" + dateString + "&details=&location=&trp=false&sprop=&sprop= target=\"_blank\"> <img src=\"" + chrome.extension.getURL("Config-date-16.png") + "\" title=\"Add this event to your Google Calendar\"> </a> ");

Я думал о том, чтобы просто выполнить замену в строке innerHTML всех тегов pэлементы: например,

arrayP = document.body.getElementsByTagName("p");
for(i=0;i<arrayP.length:i++) {
    arrayP[i].innerHTML = arrayP[i].innerHTML.replace(arrayDates[i], arrayDates[i] + " <a href=\"http://www.google.com/calendar/event?action=TEMPLATE&text=someevent&dates=" + dateString + "&details=&location=&trp=false&sprop=&sprop= target=\"_blank\"> <img src=\"" + chrome.extension.getURL("Config-date-16.png") + "\" title=\"Add this event to your Google Calendar\"> </a> ");
}

, но это также относится и к дочерним элементам (например, связывает тег).Я не уверен, каким образом я могу заменить только innerHTML для элементов тега p без его дочерних элементов.

Кроме удаления всех элементов с тегом (он также будет искажать изображения и тому подобное, поэтому я должен сделатьто же самое с этими элементами), запуском замены и повторной вставкой элементов тега, я не могу придумать другого пути решения проблемы искажения уже существующих ссылок (идеи приветствуются).

К сожалению, у меня тоже проблемы сэтот.Я мог бы использовать регулярное выражение для сопоставления всех элементов в строке innerHTML, но я думаю, что было бы менее полезно использовать DOM.

Я пробовал следующее, но я не уверен, как обойти проблемуне зная, к какому дочернему элементу tobeReplacedNodes [i] принадлежит: ( edit: я мог бы, вероятно, вызвать .parent или что-нибудь подобное, чтобы выяснить, что это за родительский объект ... Я попробую это снова и сообщу, как это происходит )

tobeReplacedNodes = document.body.getElementsByTagName("a");
for(i=0;i<tobeReplacedNodes.length;i++) {
    tobeReplacedNodes[i] = document.body.replaceChild(element, tobeReplacedNodes[i]);
}

То, что у меня пока есть, есть здесь: http://code.google.com/p/calendar-event-adder/ (ветка тестирования наиболее актуальна)

Любые идеи / предложения приветствуются, спасибо!

Ответы [ 4 ]

2 голосов
/ 16 октября 2010

Вместо того, чтобы делать RegExp для всего документа, я бы попытался работать с DOM.

Используя jQuery, я сначала выбираю только узлы внутри, которые я хочу заменить текстовыми узлами.Это важно, потому что в противном случае вы бы также заменили контент в тегах типа <code> или событии <script>, которых вы действительно хотите избежать.Внутри них получают текстовые узлы и извлекают совпадения.Мой пример очень консервативен при выборе элементов для сканирования, YMMV.

// I used this code to execute on your stackoverflow question,
// thus I choose "this" . Try it in Firebug.
var re = /(this)/gi, split;
$('div,p').contents().each( function() {
    if (this.nodeType == Node.TEXT_NODE) {
        if (this.nodeValue.match( re ) ) {
            split = this.nodeValue.split( re );
            for (var i = 0, l = split.length; i < l; i++) {
                if (i % 2) {
                    // the re catches the match thus every
                    // odd index is the match
                    $('<a href="#destination">' + split[i] +
                        '</a>').insertBefore( this );
                } else {
                    $( document.createTextNode(split[i]) ).
                        insertBefore( this );
                }
            }
            $(this).remove();
        }
    }
});

Afaik, использующий Node.TEXT_NODE, не совместим с кросс-браузерным, используя собственное значение 3, если оно недоступнонеобходимо.Я также читал, что String # split может применяться не везде.Другими словами: требуется тщательное тестирование.

1 голос
/ 18 февраля 2011

Этот плагин обрабатывает все грязные дела для вас, и не мешает никаким нетекстовым элементам. http://benalman.com/projects/jquery-replacetext-plugin/

Например, вы можете заменить все вхождения слова «текст» в элементе #test на одну строку:

$('#test').find(':not(textarea)')
  .replaceText( /\b(text)\b/gi, '<a href="foo">$1<\/a>' );
1 голос
/ 16 октября 2010

Рекурсивно обходит DOM, пропускает ссылки (и их дочерние элементы) и обрабатывает только узлы, которые nodeType равны "text". У вас должен быть узел Text внутри всего, что имеет текст, включая <p>.

0 голосов
/ 17 октября 2010

Просто еще одна идея: в настоящее время вы сначала анализируете весь документ (что может занять время). Затем вы трансформируете документ, что может быть критичным (я, как пользователь, не был бы рад удалить некоторые ссылки)

так что моя идея: если вы щелкнете где-нибудь внутри документа, вы можете создать диапазон, который может дать вам TextNode, по которому вы щелкнули. Таким образом, вы должны иметь возможность проанализировать содержимое TextNode, посмотреть, соответствует ли оно вашему шаблону, и переслать соответствие в функцию, которая открывает URL. Плохая часть этой идеи: вы не сможете каким-либо образом пометить дату, пока пользователь не щелкнет по ней.

Но это всего лишь идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...