[docbook-css] <xref> support
David Holroyd
dave at badgers-in-foil.co.uk
Mon, 3 Jan 2005 01:33:46 +0000
--vtzGhvizbBRQ85DL
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
I've been playing with adding Mozilla support for internal links within
a document using the DocBook <xref> element. Getting clickable
links was fairly easy in the end, but I've come across a sticky problem
generating the content for the <xref>.
<xref> content is typically derived from the element targeted by the
element's 'linkend' attribute. I therefore implemented some code to
have Mozilla retrieve the referenced element for interrogation.
The JavaScript 'getElementById(...)' would normally be the thing to use
for this, so I was a bit surprised when it didn't work. It turns out,
however that the 'Id' in getElementById doesn't refer to an 'id'
attribute as I'd thought, but to attributes of type 'ID', as defined by
the document's DTD.
Mozilla doesn't inspect the DTD specified for XML documents, so the
current implementation can never find the target of an <xref>.
I've found that my testcase starts working if the ID attributes are
defined in an internal subset of the DOCTYPE, like this:
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
[
<!ATTLIST chapter id ID #IMPLIED>
<!ATTLIST section id ID #IMPLIED>
...etc...
]>
This is a nasty hack though, so I strongly recommend against it.
dave
--
http://david.holroyd.me.uk/
--vtzGhvizbBRQ85DL
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="xref_support-patch1.diff"
Index: db-bindings.xml
===================================================================
RCS file: /var/lib/cvs/docbook-css/db-bindings.xml,v
retrieving revision 1.5
diff -u -r1.5 db-bindings.xml
--- db-bindings.xml 16 Oct 2004 22:40:50 -0000 1.5
+++ db-bindings.xml 3 Jan 2005 00:43:53 -0000
@@ -1,6 +1,7 @@
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
+
<binding id="ulink">
<handlers>
<handler event="click" button="0"
@@ -10,6 +11,74 @@
<handler event="mouseout"
action="window.status=null;"/>
</handlers>
+ </binding>
+
+ <!--
+ Binding for <xref>
+
+ This binding both creates content for the <xref>, and defines its behaviour
+ as a UI element.
+
+ Current implementation relies on getElementById() for content genetration,
+ which will usually not work, since Mozilla browsers don't use the DTD.
+ -->
+ <binding id="xref">
+
+ <!-- This span is used to hold the content generated by the constructor -->
+ <content>
+ <html:span/>
+ </content>
+
+ <stylesheet src="plain-xref.css"/>
+
+ <handlers>
+ <!--
+ I had a complicated action for "click", implemented with
+ window.scrollTo(). This is *much* nicer, being simpler and making
+ the back button work as expected.
+ -->
+ <handler event="click" button="0"
+ action="window.location.hash = this.attributes.linkend.value"/>
+ <handler event="mouseover"
+ action="window.status=this.attributes.linkend.value;"/>
+ <handler event="mouseout"
+ action="window.status=null;"/>
+ </handlers>
+
+ <implementation>
+ <constructor><![CDATA[
+ var node = document.getAnonymousNodes(this)[0];
+ var child = document.createTextNode(generateXrefText());
+ var f = function() { node.appendChild(child); }
+ setTimeout(f, 0);
+ ]]></constructor>
+
+ <method name="generateXrefText">
+ <body><![CDATA[
+ if (this.attributes.endterm) {
+ var node = document.getElementById(this.attributes.endterm.value);
+ return node.textContent;
+ }
+ var targetNode = this.findLinkend();
+ if (targetNode == null) {
+ return this.attributes.linkend.value;
+ }
+ if (targetNode.attributes.xreflabel) {
+ return targetNode.attributes.xreflabel.value;
+ }
+ if (targetNode.getElementsByTagName('title')[0]) {
+ return targetNode.getElementsByTagName('title')[0].textContent;
+ }
+ return this.attributes.linkend.value;
+ ]]></body>
+ </method>
+
+ <method name="findLinkend">
+ <body><![CDATA[
+ return document.getElementById(this.attributes.linkend.value);
+ ]]></body>
+ </method>
+ </implementation>
</binding>
<binding id="image">
Index: mozilla.css
===================================================================
RCS file: /var/lib/cvs/docbook-css/mozilla.css,v
retrieving revision 1.6
diff -u -r1.6 mozilla.css
--- mozilla.css 21 Nov 2004 19:34:59 -0000 1.6
+++ mozilla.css 3 Jan 2005 00:43:53 -0000
@@ -17,6 +17,11 @@
/* make <ulink>s clickable */
ulink {
-moz-binding:url('db-bindings.xml#ulink');
+}
+xref {
+ -moz-binding:url('db-bindings.xml#xref');
+}
+ulink, xref {
cursor: pointer;
-moz-user-focus: normal;
}
Index: styles.css
===================================================================
RCS file: /var/lib/cvs/docbook-css/styles.css,v
retrieving revision 1.10
diff -u -r1.10 styles.css
--- styles.css 2 Jan 2005 23:52:32 -0000 1.10
+++ styles.css 3 Jan 2005 00:43:53 -0000
@@ -348,12 +348,20 @@
content: "]";
}
-xref:after {
- /* simple symbol - content: "#" attr(linkend);*/
- /* 'section' symbol */
- content: "\00a7" attr(linkend);
+/* TODO: group with other 'link' styles */
+xref {
color:#0000ff;
text-decoration: underline;
+}
+xref:before {
+ /*
+ * Generates a section symbol before the xref, to try and indicate
+ * that there is 'something' here (this will hopefully make
+ * surrounding text that refers to 'see ...' make sense). We could
+ * insert attr(linkend) too, but that would clash with the presentation
+ * in Mozilla, where we are able to generate better content text.
+ */
+ content: "\00a7";
}
blockquote {
--vtzGhvizbBRQ85DL--