Связать термины на странице со статьями Википедии на чистом JavaScript - PullRequest
5 голосов
/ 27 февраля 2010

При просмотре я наткнулся на это сообщение в блоге об использовании API Википедии из JavaScript , чтобы связать один поисковый термин с его определением. В конце поста в блоге автор упоминает возможные расширения, в том числе:

Плагин, который автоматически связывает термины со статьями Википедии.

Это идеально подходит для требований проекта, над которым я работаю, но, к сожалению, мне не хватает навыков программирования, чтобы расширить исходный исходный код . Мне бы хотелось, чтобы у меня был чистый фрагмент JavaScript, который я мог бы добавить на веб-страницу, которая связывает все термины на этой веб-странице со статьей из внутренней вики к этой вики.

Я знаю, что это может требовать многого, но код выглядит так, будто он уже почти готов, и я был бы готов добавить вознаграждение, если кто-нибудь выполнит оставшуюся работу за этот виртуальный кредит ...;) Я также подозреваю, что это может быть полезным для некоторых других, так как я видел похожие запросы, но не работала реализация (это просто библиотека JavaScript (и, следовательно, переносимая), включающая библиотеку / фрагмент).

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

<script type="text/javascript"><!--
var spellcheck = function (data) {
    var found = false; var url=''; var text = data [0];
    if (text != document.getElementById ('spellcheckinput').value)
        return;
    for (i=0; i<data [1].length; i++) {
        if (text.toLowerCase () == data [1] [i].toLowerCase ()) {
            found = true;
            url ='http://en.wikipedia.org/wiki/' + text;
            document.getElementById ('spellcheckresult').innerHTML = '<b style="color:green">Correct</b> - <a target="_top" href="' + url + '">link</a>';
        }
    }
    if (! found)
        document.getElementById ('spellcheckresult').innerHTML = '<b style="color:red">Incorrect</b>';
};

var getjs = function (value) {
    if (! value)
        return;
    url = 'http://en.wikipedia.org/w/api.php?action=opensearch&search='+value+'&format=json&callback=spellcheck';
    document.getElementById ('spellcheckresult').innerHTML = 'Checking ...';
    var elem = document.createElement ('script');
    elem.setAttribute ('src', url);
    elem.setAttribute ('type','text/javascript');
    document.getElementsByTagName ('head') [0].appendChild (elem);
};--></script>
<form action="#" method="get" onsubmit="return false"> 
<p>Enter a word - <input id="spellcheckinput" onkeyup="getjs (this.value);" type="text"> <span id="spellcheckresult"></span></p></form>

Update
Как отмечается в комментариях, мое отношение было связано как с тем, сколько времени потребуется, чтобы связать все слова, так и с тем, как обрабатывать названия статей, охватывающие несколько слов.

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

С другой стороны, все это будет на стороне клиента, и некоторая задержка в связывании терминов вполне приемлема.

В качестве альтернативы поиск терминов, над которыми мышь находится / выделена, также может быть приемлемым, но я не уверен, уменьшит ли это или увеличит сложность.


Обновление 2

'Pointy' объяснил ниже, что эта функциональность может быть достигнута путем изменения некоторых довольно стандартных сценариев подсветки после получения списка тем статей из api.php?action=query&list=allpages.
Для реинтеграции: мы используем внутреннюю вики, поэтому список статей, вероятно, ограничен, не является двусмысленным и достаточно специфичным для предметной области, чтобы преодолеть некоторые из ожидаемых проблем при подборе слов.

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

1 Ответ

5 голосов
/ 09 марта 2010

Возможно, что-то подобное может помочь:

Предполагается, что очень простой HTML / текст выглядит так:

<div id="theText">Testing the auto link system here...</div>

И два очень маленьких скрипта.

dictionary.js устанавливает ваш список условий. Я думал, что это может быть сгенерировано в php путем запроса базы данных статей, если вы хотите. Он также может быть загружен кросс-домен (как установлено window.termsRE). Если вам не нужно генерировать список из базы данных, вы также можете вручную добавить его с помощью termlinker.js.

Этот код, который генерирует RegExp, предполагает, что ваш массив terms содержит правильно отформатированные строки для сопоставления с использованием регулярных выражений, поэтому обязательно используйте \\ для экранирования []\.?*+|(){}^&

// dictionary.js - define some terms
var terms = ['testing', 'auto link'];
window.termsRE = new RegExp("\\b("+terms.join("|")+")\\b",'gi');

termlinker.js - это простая замена поиска по регулярному выражению на определенных терминах. Это также может быть встроенный <script>. требует, чтобы dictionary.js был загружен до его запуска.

// termlinker.js - add some tags
var element = document.getElementById("theText");

element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
  return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
}); 

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

Все вместе вы получите this (jsbin preview)


Использование API

Исходя из "минимального регистра", приведенного ранее, приведен пример кода для использования API для непосредственного получения списка слов и jsbin preview

// Utility Function
RegExp.escape = function(text) {
  if (!arguments.callee.sRE) {
    var specials = [
      '/', '.', '*', '+', '?', '|',
      '(', ')', '[', ']', '{', '}', '\\'
    ];
    arguments.callee.sRE = new RegExp(
      '(\\' + specials.join('|\\') + ')', 'g'
    );
  }
  return text.replace(arguments.callee.sRE, '\\$1');
};

// JSONP Callback for receiving the API
function receiveAPI(data) {
  var terms = [];
  if (!data || !data['query'] || !data['query']['allpages']) return false;  
  var pages = data.query.allpages
  for (var x in pages) {
    terms.push(RegExp.escape(pages[x].title));
  }
  window.termsRE = new RegExp("\\b("+terms.reverse().join("|")+")\\b",'gi');
  linkterms();
}  

function linkterms() {
  var element = document.getElementById("theText");

  element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
    return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
  });
}


// the apfrom=testing can be removed, it is only there so that
// we can get some useful terms near "testing" to work with.
// we are limited to 500 terms for the purpose of this demo:
url = 'http://en.wikipedia.org/w/api.php?action=query&list=allpages&aplimit=500&format=json&callback=receiveAPI' + '&apfrom=testing';
var elem = document.createElement('script');
elem.setAttribute('src', url);
elem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild (elem);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...