- Carnegie Mellon University
- 5000 Forbes Avenue, Pittsburgh, PA 15213
A chrome extension can automate this functionality, you can further extend this skeleton functionality for all possibilities.
The following skeleton adds a context menu for right click event of mouse for selection event1
A Menu is added to chrome browser and is activated when a selection is made as shown in this screen shot
1- Selection context event fires when a selection of text is done by mouse click
Look at jsfiddle, after installation of chrome extension it annotates with user-defined tags
Select a <li>
text from output console of jsfiddle through context menu added to chrome browser,you can see DOM is also changed!
manifest file binds content script(s)
and background page(s)
to extension.
{
"name": "Annotation Tool",
"description": "http://stackoverflow.com/questions/14244498/web-page-source-annotation-tool",
"version": "1",
"manifest_version": 2,
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"myscript.js"
],
"all_frames": true
}
],
"permissions": [
"contextMenus",
"<all_urls>",
"tabs"
],
"background": {
"scripts": [
"background.js"
]
},
"icons": {
"16": "screen.png",
"48": "screen.png",
"128": "screen.png"
}
}
Create(s) Context menu and binds it to browser and activates context menu execution through message passing.
var _selection_univ = chrome.contextMenus.create({
"title": "Add <univ> tag for %s ",
"id": "_selection_univ",
"onclick": reportclick,
"contexts": ["selection"]
}, function () {
console.log("Context Menu 2 Created");
});
var _selection_address = chrome.contextMenus.create({
"title": "Add <address> tag for %s ",
"id": "_selection_address",
"onclick": reportclick,
"contexts": ["selection"]
}, function () {
console.log("Context Menu 2 Created");
});
//Add number of variables here for your functionality
function reportclick(info, tab) {
switch (info.menuItemId) {
case "_selection_univ":
chrome.tabs.sendMessage(tab.id, "univ");//Notify Content Script for univ
break;
case "_selection_address":
chrome.tabs.sendMessage(tab.id, "address");//Notify Content Script for address
break;
default:
console.log("Handle default case..");
}
}
//Handle DOM Changes here
chrome.extension.onMessage.addListener(function (message, sender, response) {
switch (message) {
//Hanlde [univ] tag
case "univ":
if (document.getSelection().baseNode != null) document.getSelection().baseNode.parentNode.innerHTML = "[univ]" + document.getSelection().baseNode.parentNode.innerHTML + "[/univ]";
break;
//Hanlde [address] tag
case "address":
if (document.getSelection().baseNode != null) document.getSelection().baseNode.parentNode.innerHTML = "[address]" + document.getSelection().baseNode.parentNode.innerHTML + "[/address]";
break;
default:
console.log("Handle default case..");
}
});
If you want to further add few more context menu(s)
1) create a variable for context menu as shown here in background.js
var _selection_Some_Tag = chrome.contextMenus.create({
"title": "Add [SOME TAG] tag for %s ",
"id": "_selection_univ",
"onclick": reportclick,
"contexts": ["selection"]
}, function () {
console.log("Context Menu for Some Tag Created");//In Call Back
});
2) add a case for switch in background page as shown here
case "_selection_your_case":
chrome.tabs.sendMessage(tab.id, "_your_tag_content"); //Notify Content Script for address
break;
3) handle your custom tag in content scripts by adding code as shown here
//Hanlde [your custom] tag
case "univ":
if (document.getSelection().baseNode != null) document.getSelection().baseNode.parentNode.innerHTML = "[your tag]" + document.getSelection().baseNode.parentNode.innerHTML + "[/your tag]";
break;
Check How to Load an Extension for testing and extending this script.
You can use following code of chrome extension for
To use this code use any of your fav icon(s) and put them in chrome directory for every tag [univ]
and use corresponding names in css file
here
background-image: url(chrome-extension://MSG_@@extension_id/YOUR_ICON_NAME.png);
Registering css and java script
for annotation tool
.
{
"name": "Annotation Tool",
"description": "http://stackoverflow.com/questions/14244498/web-page-source-annotation-tool",
"version": "1",
"manifest_version": 2,
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"css": [
"myscript.css"
],
"js": [
"jquery.js",
"myscript.js"
],
"all_frames": true
}
],
"permissions": [
"contextMenus",
"<all_urls>",
"tabs"
],
"icons": {
"16": "screen.png",
"48": "screen.png",
"128": "screen.png"
},
"web_accessible_resources": [
"icon1.png",
"icon2.png"
]
}
Binding Icons here.
#root #univ {
display: inline-block;
z-index: 100000;
height: 22px;
width: 26px;
background-image: url(chrome-extension://__MSG_@@extension_id__/icon1.png);
}
#root #addr {
display: inline-block;
z-index: 100000;
height: 22px;
width: 26px;
background-image: url(chrome-extension://__MSG_@@extension_id__/icon2.png);
}
Code for updating selected text with custom tags.
//Intialize counters to default values
clicking = false;
selecting = false;
//Set the toolbar to some invalid position so it will not appear unless a selection is made
var currentMousePos = {
x: -100,
y: -100
};
$(document).mousedown(function () {
//Click is started
clicking = true;
});
//Tool bar to add
$('body').append("<div id='root' style='position: absolute; left:" + currentMousePos.x + "px; top:" + currentMousePos.y + "px; display: block;'><a id='univ' href='javascript:void(0);'> </a><a id='addr' href='javascript:void(0);' > </a></div>");
$(document).mouseup(function (event) {
if (selecting) {
//He is selecting text
$("#root").attr("style", "position: absolute; left:" + currentMousePos.x + "px; top:" + currentMousePos.y + "px; display: block;");
} else {
//He just clicked
$("#root").attr("style", "display: none;");
}
//Reset counters
clicking = false;
selecting = false;
});
$(document).mousemove(function () {
if (clicking) {
//He did not simply click , but he is selecting some text
selecting = true;
//Track current position to put toolbar
currentMousePos.x = event.pageX;
currentMousePos.y = event.pageY;
}
});
$("div #addr").click(function () {
//Get Selected text
var selection = document.getSelection();
//Add your tags and prepare replacing content
var html = "[addr]" + selection + "[/addr]";
if (selection.getRangeAt && selection.rangeCount) {
//Chrome supports only one range fire fox supports multiple ranges
range = document.getSelection().getRangeAt(0);
//remove selection
range.deleteContents();
//Create a node
node = range.createContextualFragment(html);
//Add the custom node
range.insertNode(node);
}
});
$("div #univ").click(function () {
//Get Selected text
var selection = document.getSelection();
//Add your tags and prepare replacing content
var html = "[univ]" + selection + "[/univ]";
if (selection.getRangeAt && selection.rangeCount) {
//Chrome supports only one range fire fox supports multiple ranges
range = document.getSelection().getRangeAt(0);
//remove selection
range.deleteContents();
//Create a node
node = range.createContextualFragment(html);
//Add the custom node
range.insertNode(node);
}
});
Now You can replace any part of text
Replace any web page
It is possible to download the page using chrome.pageCapture API, but to a sand boxed
location.
{
"name": "Page Capture Demo",
"description": "This demos Page Capture MHTML Functionality",
"permissions": [
"pageCapture"
],
"browser_action": {
"default_icon": "screen.png",
"default_popup": "popup.html"
},
"manifest_version": 2,
"version": "1"
}
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
<div id="pushhere"></div>
</body>
</html>
function capture() {
chrome.tabs.query({
"active": true,
"currentWindow": true,
"status": "complete"
}, function (tabs) {
chrome.pageCapture.saveAsMHTML({
"tabId": tabs[0].id
}, function (data) {
var reader = new FileReader();
reader.onload = function (eventt) {
console.log(eventt.target.result);
document.getElementById('pushhere').innerHTML = eventt.target.result;
//window.open(eventt.target.result);
};
reader.readAsText(data);
//window.open(data);
});
});
}
window.onload = capture;
Test this code using steps above by picking your icons of choice, hope this helps :)
images
, js
and css
files is possible from chrome extensionA browser extension should be fine. A standalone application would need to utilize a full-fledged browser, which is cumbersome.
Only with a browser extension (in contrast to a bookmarklet) you would have the permission to save the results directly to the filesystem. You can add the "Annotate" button to the browser (G)UI as well.
However, storing thousands of HTML files on your harddisk might not be your aim. Instead, you could set up a simple database server to which you post the annotation results. A small bookmarklet with some ajax code would be enough on the clientside then.