Background;
I’ve been spending some time writing trivial XUL extension for my own needs.
XUL is a weird way of doing things – for me al least. I’ve been writing thick client applications using various toolkits ( Gtk/ Qt / Jambi ) for nearly 6 years now and using JavaScript , XML and CSS to write a desktop application seemed .. weird.
There are plus points to learning XUL:
- The “applications” themselves are lightweight and can be deployed using XULrunner as standalone applications – eg ChatZilla!
- The applications pretty much guaranteed to run on Windows, OS X and Linux ( and other OSes supported by Mozilla Firefox )n- as long as you dont use native code inside your applications.[1]
- This is great for building small utilities that you want – though full fledged applications like SongBird and Thunderbird have been built using XUL technology
- You can get a lot done using your web development skills
Using your web development skills to write desktop applications is cool in a weird way , IMO :)
Where XUL helps you:
XUL allows you to write simple desktop applications / firefox plugins just like you would write a web application. You use JavaScript for all the logic, XML for all the UI and CSS to theme it. If you are interested, going through the XUL Tutorial might be a good starting point. There are IRC channels and mailing lists to help you out , of course
Problem Statement:
I want to be able to extract rich text + markup from a web page so that I can put it into something else ( a Word document for example)
The Solution:
The code for that is simple, as long as you are familiar with Mozilla’s DOM API.
The code is pretty self-explanatory': I’ve hyperlinked some API calls with the documentation for your reference:
getSelectedRichText: function () {
//this method extracts out the rich text from the selection
// refer:https://ubiquity.mozilla.com/hg/ubiquity-f
var range = this.getFirstRange()
if (!range) return "";
var newNode = document.commandDispatcher.focusedWindow.d
newNode.appendChild(range.cloneContents());
range.detach();
return this.absolutifyUrlsInNode(newNode).inner
},
// A couple of helper methods
absolutifyUrlsInNode: function (node) {
var attrs = ["href", "src", "action"];
for each (let n in Array.slice(node.getElementsByTagName("*
for each (let a in attrs)
if (a in n) {
n.setAttribute(a, n[a]);
break;
}
return node;
},
//this method returns us the range of the selection
getFirstRange : function () {
var win = document.commandDispatcher.focusedWindow;
var sel = win && win.getSelection();
if (!sel || !sel.rangeCount) return null;
var range = sel.getRangeAt(0);
var newRange = win.document.createRange();
newRange.setStart(range.startContainer, range.startOffset);
newRange.setEnd(range.endContainer, range.endOffset);
return newRange;
},
Saving the selected text to a .doc file:
Create a simple xhtml file – fill out the sections in blue with your data.
<html xmlns:o="urn:schemas-microsoft-com:offic
<head>
<xml>
<o:DocumentProperties>
<o:Author>Your name</o:Author>
</o:DocumentProperties>
<w:WordDocument>
<w:View>Print</w:View>
<w:Zoom>100%</w:Zoom>
</w:WordDocument>
</head>
<body>
Your text goes here
<p> a new paragraph </p>`
</body>
</xml>
</html>
Save this with a .doc extension and voila! MS word can open this as a .doc file. This is very cool stuff.
Taking this into account lets write our saveToDoc() method:
SaveToDoc: function() {
//lets initialize a simple prompt here for debugging purposes
var prompts = Components.classes["@mozilla.org/embedco
.getService(Components.interfaces.nsIPro
//lets constuct the doc string here.
var initialSectionStr = "<html xmlns:o=\"urn:schemas-microsoft-com:offi
initialSectionStr += "<head>";
initialSectionStr += "<xml>";
initialSectionStr += "<o:DocumentProperties>";
initialSectionStr += "<o:Author>Your name</o:Author>";
initialSectionStr += "</o:DocumentProperties>";
initialSectionStr += "<w:WordDocument>";
initialSectionStr += "<w:View>Print</w:View>";
initialSectionStr += "<w:Zoom>100%</w:Zoom>";
initialSectionStr += "</w:WordDocument>";
initialSectionStr += "</head>";
var bodyStr = "<body>" + this.getSelectedRichText() + "</body></xml></html>";
var finalStr = initialSectionStr + bodyStr;
//prompts.alert(null, "foobar!", finalStr);
//writing the file
var file = Components.classes["@mozilla.org/file/lo
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath( "C:\\output.doc" );
file.createUnique( Components.interfaces.nsIFile.NORMAL_FIL
// file is nsIFile, data is a string
var foStream = Components.classes["@mozilla.org/network/f
createInstance(Components.interfaces.nsI
// use 0x02 | 0x10 to open file for appending.
foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
// write, create, truncate
// In a c file operation, we have no need to set file mode with or operation,
// directly using "r" or "w" usually.
// if you are sure there will never ever be any non-ascii text in data you can
// also call foStream.writeData directly
var converter = Components.classes["@mozilla.org/intl/co
createInstance(Components.interfaces.nsI
converter.init(foStream, "UTF-8", 0, 0);
converter.writeString(finalStr);
converter.close(); // this closes foStream
},
We plug this in and thus we have a firefox extension which can take stuff from any web page and render it almost exactly onto a word document. Cool isnt it?











