MacBook, defective by design banner

title:
Put the knife down and take a green herb, dude.


descrip:

One feller's views on the state of everyday computer science & its application (and now, OTHER STUFF) who isn't rich enough to shell out for www.myfreakinfirst-andlast-name.com

Using 89% of the same design the blog had in 2001.

FOR ENTERTAINMENT PURPOSES ONLY!!!
Back-up your data and, when you bike, always wear white.

As an Amazon Associate, I earn from qualifying purchases. Affiliate links in green.

x

MarkUpDown is the best Markdown editor for professionals on Windows 10.

It includes two-pane live preview, in-app uploads to imgur for image hosting, and MultiMarkdown table support.

Features you won't find anywhere else include...

You've wasted more than $15 of your time looking for a great Markdown editor.

Stop looking. MarkUpDown is the app you're looking for.

Learn more or head over to the 'Store now!

Thursday, April 07, 2011

If you use the Add-On Manager to create the foundation to your Firefox extension, you might see that your description is literally "description" even though you've got a different value in <em:description> in your install.rdf file.

You've probably got this line in overlay.properties:
extensions.zoteroplay@genreacrossborders.org.description=description
(where zoteroplay@genreacrossborders.org will be the id of your own extension)

That'll do it. /sigh The property "covers up" your longer description in install.rdf. Erase that line and your other description will show up.

Labels: , , ,


posted by ruffin at 4/07/2011 07:13:00 PM

More fun code! Note today's new lessons -- the OM for tree items, rows, children, and cells; the use of CDATA for encapsulating javascript in XUL files, which are picky XML files, especially when you use a <; and slightly more situation-specific code.

   1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin/" type"text/css" ?>
3 <!DOCTYPE page SYSTEM "chrome://zoteroplay/locale/overlay.dtd">
4 <page id="zoteroplaySidebar" title="&zoteroplaySidebar.label;"
5 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
6
7
8
9 <script src="ff-sidebar.js"/>
10 <script>
11 <![CDATA[
12 function hello() {
13 alert('Hello from ff-sidebar.xul!!');
14 }
15 function OnTreeDoubleClick(event) {
16 alert('doubleclick');
17 var objTree = document.getElementById('myTree');
18 var iIndex =
19 objTree.treeBoxObject.getRowAt(event.clientX,event.clientY);
20 alert(iIndex);
21 }
22
23 function addSource(bIsNewSource) {
24 // note that this is hard-coded to grab from the tree we make,
25 // using XUL, not javascript, below. The only reason I'm doing
26 // this (instead of having it passed in as a function
27 // parameter) is so that we don't have to navigate some DOM
28 // from another file to call this function. Just call from
29 // overlay.js or whatever and forget about sidebar refs.
30 var rootChild = null;
31 if (bIsNewSource) {
32 rootChild = document.getElementById("newRoot");
33 } else {
34 rootChild = document.getElementById("dupeRoot");
35 }
36
37
38
39 //========================================
40 // Create the parent row.
41 //========================================
42 // Now we're going to create a new TreeItem, which will also
43 // be a container for nested items.
44 // itemSourceHeader will have two items, one the field we're
45 // using to distinguish it (like Title, if it's got one) and
46 // the second is the value ("Moby-Dick; or, The Whale")
47
48 var itemSourceParent = document.createElement("treeitem");
49 itemSourceParent.setAttribute("container","true");
50 // create a new row with two cells for the new
51 // item, which will be attached to the rootChild.
52 var rowSourceHeader = document.createElement("treerow");
53
54 var cellField = document.createElement("treecell");
55 cellField.setAttribute("label","Title:");
56
57 var cellFieldValue = document.createElement("treecell");
58 cellFieldValue
59 .setAttribute("label","Moby-Dick; or, The Whale");
60
61 rowSourceHeader.appendChild(cellField);
62 rowSourceHeader.appendChild(cellFieldValue);
63 // attach the header values for this item (now in a treerow) to
64 // the item that'll hold it. That is, the source (like a
65 // book) parent has some title information to display.
66 itemSourceParent.appendChild(rowSourceHeader);
67
68
69
70 //========================================
71 // Now we create the nested row.
72 //========================================
73 var parentNested = document.createElement("treechildren");
74
75 // soon we'll put in actual value from an array
76 // rather than this dummy loop; this is just to
77 // show how to have more than one "child".
78 for (var j=1;j<=10;j++) {
79 var itemNested = document.createElement("treeitem");
80 var rowNested = document.createElement("treerow");
81 var cellNest1 = document.createElement("treecell");
82 cellNest1.setAttribute("label","Author:");
83
84 var cellNest2 = document.createElement("treecell");
85 cellNest2.setAttribute("label","Herman Melville");
86
87 rowNested.appendChild(cellNest1);
88 rowNested.appendChild(cellNest2);
89
90
91 itemNested.appendChild(rowNested);
92 parentNested.appendChild(itemNested);
93 }
94 // attach the detailed source information to
95 // the parent item.
96 itemSourceParent.appendChild(parentNested);
97
98
99 //========================================
100 // Now we add the parent item of all the
101 // source's detailed information to the
102 // root child of the tree.
103 //========================================
104 rootChild.appendChild(itemSourceParent);
105 }
106
107
108 ]]>
109 </script>
110
111
112
113 <vbox flex="1">
114 <label value="&zoteroplaySidebar.label;" />
115 <!-- put your GUI here -->
116
117
118 <tree ondblclick="OnTreeDoubleClick(event);" id="myTree" flex="1">
119 <treecols>
120 <treecol id="firstname" label="Field" flex="5"
121 primary="true"/>
122 <treecol id="lastname" label="Field Value" flex="5"/>
123 </treecols>
124
125 <treechildren>
126 <treeitem container="true" open="true">
127 <treerow>
128 <treecell label="Possible New Sources"/>
129 </treerow>
130 <treechildren id="newRoot">
131 </treechildren>
132
133 </treeitem>
134 <treeitem container="true" open="true">
135 <treerow>
136 <treecell
137 label="Likely Duplicate Sources"/>
138 </treerow>
139 <treechildren id="dupeRoot">
140 <treeitem>
141 <treerow>
142 <treecell
143 label="Title:"/>
144 <treecell
145 label="Already Got It"/>
146 </treerow>
147 </treeitem>
148
149 </treechildren>
150
151 </treeitem>
152 </treechildren>
153 </tree>
154 </vbox>
155 </page>
156


So this ends up looking like the following (after rows have been added to new and dupe sources several times):



It may also be useful to note that I made the sidebar open up apparently about as wide as Firefox is going to let it with this code in ff-sidebar.js:

   1 var mainWindow = null;
2
3 function startup() {
4 mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
5 .getInterface(Components.interfaces.nsIWebNavigation)
6 .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
7 .rootTreeItem
8 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
9 .getInterface(Components.interfaces.nsIDOMWindow);
10
11 // this spacebar needs a lot of space to display the info
12 // we're going to put there. Give it at least 400 pixels out of the box.
13 // TODO: I'm setting a check to see if it's already 400, but it seems there's
14 // an absolute max width for sidebars in Firefox by default which is less than
15 // (or about) 400.
16 if (mainWindow.document.getElementById("sidebar-box").width < 400) {
17 mainWindow.document.getElementById("sidebar-box").width = 400;
18 }
19 // Sidebar is loaded and mainwindow is ready
20 }
21
22 function shutdown() {
23 // Sidebar is unloading
24 }
25
26 window.addEventListener("load", startup, false);
27 window.addEventListener("unload", shutdown, false);
28

Labels: , , ,


posted by ruffin at 4/07/2011 01:18:00 PM
Tuesday, April 05, 2011

I hate to say that I'm not real impressed with the state of tutorials on building Firefox extensions, in part because that seems to imply some sort of incompetence of my own as a coder. I mean, come on, thousands of folks are building and releasing these danged things. It's obviously not rocket science.

But the bottom line is that much of the extension building process is still left in trial and error land where it could easily be put into tutorials. Lots of folk are banging their heads, as far as I can tell, on the same stuff, and there just isn't a large enough community to put all those individual lessons learned together for the collective to benefit from.

Anyhow, so I've struggled today with how to build and then programmatically access a sidebar made in XUL for a Firefox extension. I want to populate it with the results of a Zotero database installed within the same Firefox instance, but before I do that, I just want to be able to 1.) display the sidebar 2.) display a tree in the sidebar and 3.) add rows with information from my "main" javascript file that's sent over to the sidebar.

Here's some fun.

The best XUL and Firefox extension building code probably comes from Add-on Builder. Slap in your description, etc, and select it all. It'll create a toolbar, button for your main toolbar, a menu item in tools, even a context-menu (the one that's typically displayed when you right-click a web-page displayed in Firefox) for you. Voila. Perfect. 90% done.



Then we learn most of the important stuff from this thread at Mozillazine.

I pasted this into ff-sidebar.xul based mostly off of the info at the above link:

   1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin/" type"text/css" ?>
3 <!DOCTYPE page SYSTEM "chrome://zoteroplay/locale/overlay.dtd">
4 <page id="zoteroplaySidebar" title="&zoteroplaySidebar.label;"
5 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
6 <script src="ff-sidebar.js"/>
7 <script>
8 function hello() {
9 alert('Hello from ff-sidebar.xul!!');
10 }
11 function OnTreeDoubleClick(event) {
12 alert('doubleclick');
13 var objTree = document.getElementById('myTree');
14 var iIndex = objTree.treeBoxObject.getRowAt(event.clientX,event.clientY);
15 alert(iIndex);
16 }
17
18 function addRowMaybe() {
19 var oRootTreeChild = document.getElementById("children_root");
20 var oItem = document.createElement("treeitem");
21 var oRow = document.createElement("treerow");
22
23 var oCell = document.createElement("treecell");
24 oCell.setAttribute("label","Dynamic item");
25 oRow.appendChild(oCell);
26 oItem.appendChild(oRow);
27 oRootTreeChild.appendChild(oItem);
28 }
29
30 </script>
31
32 <vbox flex="1">
33 <label value="&zoteroplaySidebar.label;" />
34 <!-- put your GUI here -->
35
36
37 <tree ondblclick="OnTreeDoubleClick(event);" id="myTree" flex="1">
38 <treecols>
39 <treecol id="firstname" label="First Name" primary="true" flex="3"/>
40 <treecol id="lastname" label="Last Name" flex="7"/>
41 </treecols>
42
43 <treechildren id="children_root">
44 <treeitem container="true" open="true">
45 <treerow>
46 <treecell label="Guys"/>
47 </treerow>
48
49 <treechildren>
50 <treeitem>
51 <treerow>
52 <treecell label="Bob"/>
53 <treecell label="Carpenter"/>
54 </treerow>
55 </treeitem>
56 <treeitem>
57 <treerow>
58 <treecell label="Jerry"/>
59 <treecell label="Hodge"/>
60 </treerow>
61 </treeitem>
62 </treechildren>
63 </treeitem>
64 </treechildren>
65 </tree>
66
67
68 </vbox>
69 </page>
70


So that gets us a sidebar with a tree in it. To see it, you load up the extension that you've built (we're assuming you already know how to unzip an xpi and hack the files in it to install later -- or to have Firefox change live), and use code like this in your "main" javascript file (overlay.js in the Add-On Builder code) to call the functions in the sidebar. So one place would be to slap what's below into onToolbarButtonCommand in overlay.js to make the magic happen.

   1 // Get the sidebar that's currently displayed in the browser.
2 var sidebarWindow = document.getElementById("sidebar").contentWindow;
3
4 // Verify that your sidebar is open at this moment:
5 alert(sidebarWindow.location.href); // probably important to realize
6 // that if there's no sidebar being displayed, you'll get the
7 // URL of the open window instead of a sidebar chrome value.
8
9 if ("chrome://zoteroplay/content/ff-sidebar.xul" == sidebarWindow.location.href) {
10 // call "yourNotificationFunction" in the sidebar's context:
11 sidebarWindow.hello(); // this row calls a plain jane funct
12 sidebarWindow.addRowMaybe(); // this calls the funct that adds a row
13 }


So now we can access a javascript function inside of the sidebar code and have it add a row programmatically. Of course, the trick is that we're using that "children_root" id in the treechildren element, which really speeds things up and simplifies what we're doing. Now, honestly, the best way to add programmatic rows/rows at run time would be to write a Custom Tree View that has the info I want sitting in a giant array or something silly like that. With enough children (that is, I'm going to be displaying books with authors, titles, publishers, etc), this'll get downright messy, and I might end up cheating and using another control from the XUL periodic table (Note: That periodic table link doesn't work in Firefox 4+ without installing an extension that re-allows Remote XUL (this one should do it, I think); I'm using Camino to view the chart for now).



Ah, sweet proof of concept success.

But that's the start. And I thought I'd left behind the craptasticness of model building when I took a Java break. No such luck.

Labels: , , , ,


posted by ruffin at 4/05/2011 05:19:00 PM

<< Older | Newer >>


Support freedom
All posts can be accessed here:


Just the last year o' posts:

URLs I want to remember:
* Atari 2600 programming on your Mac
* joel on software (tip pt)
* Professional links: resume, github, paltry StackOverflow * Regular Expression Introduction (copy)
* The hex editor whose name I forget
* JSONLint to pretty-ify JSON
* Using CommonDialog in VB 6 * Free zip utils
* git repo mapped drive setup * Regex Tester
* Read the bits about the zone * Find column in sql server db by name
* Giant ASCII Textifier in Stick Figures (in Ivrit) * Quick intro to Javascript
* Don't [over-]sweat "micro-optimization" * Parsing str's in VB6
* .ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); (src) * Break on a Lenovo T430: Fn+Alt+B
email if ya gotta, RSS if ya wanna RSS, (?_?), ยข, & ? if you're keypadless


Powered by Blogger etree.org Curmudgeon Gamer badge
The postings on this site are [usually] my own and do not necessarily reflect the views of any employer, past or present, or other entity.