firefox - Find text (ISBN) on page and attach link on it in JS -
for browser (firefox) addon need find isbn's on pages (such as: amazon.com, book.com).
i need find dom elemets containing isbn , manipulate them link, sends isbn rest webservice further logic.
since i'm new javascript don't have idea how because homepages differ in how display isbn.
this current implementation:
var self = require("sdk/self"); // dummy function, show how tests work. // see how test function, @ 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); }); } });
this modify-content.js
self.port.on("getelements", function(tag) { var elements = document.getelementsbytagname(tag); (var = 0; < 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); } });
the isbn's found. how manipulate dom element surrounding isbn?
if understand question correctly, you're having trouble translating innertext
regexp match, string, nearest html element of match.
the difficult part dom tree. if <div>
has <p>
has <span>
has isbn number, of elements' innertext
contain isbn number. want reach "deepest" element contains match, ignoring of parents.
one (rather expensive, brute-force) way of doing this, recursively looping through elements, layer layer.
- when there match in
innertext
, we'll @ every child element. - if none of children has match, return current element because it's last known dom element had match
other performance, think there still edge cases won't match. example, if there's <span>
contains three, comma separated, isbn numbers. you'll have add 1 last layer: layer creates new elements around each individual string.
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 match here, not in of 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);
.isbn { color: green; border-radius: 3px; background: rgba(0,255,0,0.2); cursor: pointer; }
<div> <div> <ul> <li> book: <span>978-0451524935</span> </li> <li> nested book: <span><strong>isbn</strong>-978-0451524935</span> </li> <li> phone number: <span>0012-34-5678909</span> <code><-- regexp problem?</code> </li> <li> email: <span>abc@def.gh</span> </li> </ul> </div> <div> here no isbn numbers </div> here's 1 <a><strong>isbn</strong>-<em>978</em>-0451524935</a> </div>
Comments
Post a Comment