在页面上查找文本(ISBN)并在JS中附加链接

时间:2016-11-10 09:09:33

标签: firefox dom

对于浏览器(Firefox)插件​​,我需要在某些页面上找到ISBN(例如:amazon.com,book.com)。

我需要找到那些包含ISBN的DOM元素并使用链接操作它们,该链接将ISBN发送到REST Web服务以获得进一步的逻辑。

由于我是JavaScript的新手,我不知道如何进入这一点,因为主页在显示ISBN方面有所不同。

这是当前的实施:

var self = require("sdk/self");

// a dummy function, to show how tests work.
// to see how to test this function, look at test/test-index.js
function dummy(text, callback) {
  callback(text);
}

exports.dummy = dummy;

var tag = "body"
var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var pageMod = require("sdk/page-mod");
var data = require("sdk/self").data;


var button = buttons.ActionButton({
  id: "mozilla-link",
  label: "Visit Mozilla",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onClick: handleClick
});

function handleClick(state) {
  //tabs.open("http://www.mozilla.org/");
  tabs.open("http://www.amazon.com");

}

pageMod.PageMod({
  include: "*",
  contentScriptFile: data.url("modify-content.js"),
  onAttach: function(worker) {
    worker.port.emit("getElements", tag);
    worker.port.on("gotElement", function(elementContent) {
      console.log(elementContent);
    });
  }
});

这是modify-content.js

self.port.on("getElements", function(tag) {

  var elements = document.getElementsByTagName(tag);
  for (var i = 0; i < elements.length; i++) {

    var isbn = elements[i].innerText.match("(ISBN[-]*(1[03])*[ ]*(: ){0,1})*(([0-9Xx][- ]*){13}|([0-9Xx][- ]*){10})");

    if(isbn != undefined){
        //self.port.emit("gotElement", elements[i].innerHTML);
        console.log(isbn);      
    }

    self.port.emit("gotElement", elements[i].innerHTML);
  }
});

找到了ISBN。但是如何操纵ISBN周围的DOM元素?

1 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,则无法将innerText正则表达式匹配(即字符串)转换回该匹配的最近 html元素。

困难的部分是DOM是一棵树。因此,如果<div>的{​​{1}}的{​​{1}}具有ISBN编号,则所有这些元素“<p>都将包含该ISBN编号。我们希望达到包含匹配的“最深”元素,忽略其所有父母。

一种(相当昂贵,蛮力)这样做的方法是逐层循环遍历你的元素。

  • 如果<span>中有匹配项,我们会查看每个子元素。
  • 如果没有孩子匹配,我们返回当前元素,因为它是 匹配的最后一个已知DOM元素

除了表现之外,我认为仍然存在不匹配的边缘情况。例如,如果innerText包含三个逗号分隔的ISBN号。您可能需要添加最后一个图层:在每个单独的字符串周围创建 new 元素的图层。

innerText
<span>
var isbnRegExp = new RegExp("(ISBN[-]*(1[03])*[ ]*(: ){0,1})*(([0-9Xx][- ]*){13}|([0-9Xx][- ]*){10})");

var start = document.body;

var findDeepestMatch = function(el, regexp, result) {
  result = result || [];

  if (regexp.test(el.innerHTML)) {
    var childMatches = Array.from(el.children)
      .filter(child => regexp.test(child.innerHTML));

    // Case 1: there's a match here, but not in any of the children: return el
    if (childMatches.length === 0) {
      result.push(el);
    } else {
      childMatches.forEach(child => findDeepestMatch(child, regexp, result));
    }
  }

  return result;
};

console.time("Find results")
var results = findDeepestMatch(start, isbnRegExp);
console.timeEnd("Find results")

var makeISBN = el => {
  el.classList.add("isbn");
  el.addEventListener("click", () => console.log(el.innerText));
};

results.forEach(makeISBN);