<div>
First of all: Press `?´ for a list of available shortcuts.
The aim of this little script is to implement a part of emacs facilities of folding in the HTML-exported files.
Oh, no - not originaly. My first idea was to view some of my larger org files
without scrolling. I wanted to have them paged just like texinfo or linuxdoc
files. Two or three weeks ago I came across Carsten Dominiks ideas page
http://orgmode.org/todo.html. And I could not resist to write him some of my
thoughts about this great emacs mode including some little ideas and
drawbacks. I don't know how, but it somehow these guys made me, lazy bone that
I am, write this little script as an apetizer of web 3.0 in org-mode (Phil
Jackson) . It will for shure not work in all browsers. Espacially elder ones
since it relies entierly on DOM
. There is no browser selector included and
no sofisticated event handling due to my small JavaScript™ knowledge. But I
already love it and use it locally for all of my notes and documentations
written with org-mode
.
There are no external dependencies though. The script is quite small and fast
enough for larger files too. I tested it with the file
ORGWEBPAGE/Changes.org
in the org-mode
package which gave me 225 pages to
handle and on my old omnibook it still worked nicely.
Just in case you see this document split into section with a navigation bar on top:
Try it. Click on the small 'toggle view' link on the top right of the headline. A lot to scroll, right? But still seeing this section after clicking the link? Click the same link againg please. Still here and navigation bar back again? If so, drop me a mail and tell me your browser and its version so we can put it on list of supported browsers (sorry - internal links are on the TODO list).
BTW: you can activate the links using accesskeys. 'n
' for 'next', 'p
' for
previous section, 't
' to toggle the view, and 'i
' to go to the index.
To produce this HTML file I used a new version of the org HTML export. The
structure of the exported XHTML will change a little bit in the future to
support scripting an other tools that work on XML
. Carsten Dominik found
the time to modify the current export modul to produce the draft version of
the next generation XHTML.
To use this script and the new XHTML structure check out the git head from this location:
git://repo.or.cz/org-mode.git
The current version of this script will not work with the XHTML export as delivered with the current org-mode package anymore. I'm afraid there are good chances the new exporter is done before this thing here enters a usefull state :-)
First of all the script is included in the header as described in Usage. The document has to be exported with T.O.C. since the script depends on it (See Why Do I Need a T.O.C?). This could change in the future because of the better structured export.
When included, it creates a global JavaScript™ variable named
org_html_manager
, which is an instance of the class OrgHtmlManager
. The
class is meant as a singleton but there are no precautions for avoiding the
creation of an other instance. No one would need to create a new instance
anyway.
The org_html_manager::setup()
function, that you will have to call
yourself (see examples in Usage), sets up a timeout function calling it's init()
function after 50ms. After those 50 ms The init()
function starts it's first
attempt to scan the document, using the T.O.C. as a guide. During this scan
the org_html_manager
builds a tree of nodes, each caching some data for
later use. Once an element of the document is scanned it is marked by setting
a property scanned_for_org
to 1
. This way it will not be scanned a second
time in subsquent runs (it will be checked though, but no work will be done
for it).
If the document (or the T.O.C.) is not entirely loaded, org_html_manager
stops scanning, sets the timeout again to start an other scan 50 ms
later. Once the entire document is loaded and scanned no new timeout will be
set, and the document is displayed in the desired way (hopefully).
The number of attempts to scan the the document is limited to 5 runs. You can
change that value by editing the script or, better, adding this line to your
header before calling setup()
:
org_html_manager.set("MAX_RUNS", 10);But 5 runs will do for realy big files and a medium fast connection.
The org_html_manager
also changes the document a bit to make it react on
certain input events and follow your wishes. The old 'event handling' was
entirely based on the normal link functions using so called accesskeys
. This
has changed a little, but is still only in experimental state. The accesskeys
will stay cause there is no reason to remove them.
There is still the idea of a new emacs like keyboard handling to implement complex commands (which is still in the far future).
SHIFT+ESC
before pressing the
actual accesskey, in Firefox the Prefix is ???…. Icedove
version 2.0.0.12 does not react on accesskeys. This is a known bug and
fixed in the new version. Refer
to the documentation of your browser for information on how to use
accesskeys. The keys are
n
next page
p
previous page
t
toggle view mode
i
return to the index (T.O.C)
org-export-headline-levels
. Scanning the T.O.C. is a good way to get
around browser detection. An option to hide the T.O.C. by script will be
added soon.
org-export-headline-levels
. This
was done to get a more texinfo/linuxdoc kind of fell and a better
orientaton. Can be turned of (see Usage).
\markright
command in LaTeX
the Title of the current sections parent appears on top of each page. In
subsections this heading can be use as link up to start of the parent
section (see top of this page when you're in info view mode). You can move
to the parent section by pressing `u´ (up).
Currently the script depends on the table of contents in the resulting HTML. The T.O.C. can be hidden though.
The main reason is the behaviour of browsers. There is no safe way to detect
if the entire document is loaded at a certain point in time. Opera for example
returns true
if we ask it if(document.body)
. The init()
function of the
OrgHtmlManager
is aware of the possibility, that not even the T.O.C. might
be loaded when this function is called. Hence it should work for slow
connections too. There should be tons of other bugs though :)
The script has to be included in the header of the resulting HTML files. The
document has to be export with T.O.C. since the script depends on it.
You may pass options to the org_html_manager
by utilising it's set()
method. This is the code I used to set up this file:
<script type="text/javascript" language="JavaScript" src="org-info.js"></script> <script type="text/javascript" language="JavaScript"> /* <![CDATA[ */ org_html_manager.set("SUB_INDEXES", 1); org_html_manager.set("HIDE_TOC", 1); org_html_manager.set("INFO_SWITCH_ALWAYS", "true"); org_html_manager.set("FOLDING", "true"); org_html_manager.set("MOUSE_HINT", "underline"); // or background-color like '#eeeeee' org_html_manager.setup (); /* ]]> */ </script>
To just use the script with the defaults put this into the head section of the XHTML files:
<script type="text/javascript" language="JavaScript" src="org-info.js"></script> <script type="text/javascript" language="JavaScript"> /* <![CDATA[ */ org_html_manager.setup (); /* ]]> */ </script>
I recommend the use of
<script type="text/javascript" language="JavaScript" src="org-info.js"></script>instead of
<script type="text/javascript" language="JavaScript" src="org-info.js" />which is valid XHTML but not understood by all browsers. I'll use the first version throughout this document where ever the space allows to do so.
Before calling
org_html_manager.setup ();one may configure the script by using the
org_html_manager
's function
set(key, val)
. There is one important rule for all of these options. If
you set a string value containing single quotes, do it this way:
org_html_manager.set("key", "value with \\'single quotes\\'");
org_html_manager.INFO_VIEW
or
org_html_manager.PLAIN_VIEW
.
1
, hide the table of contents.
true
(1
or not empty string) value, create subindexes
for sections containing subsections. See sections 1 2, or 3.1 of this
document. The index below the headline (under 'Contents:') is generated
by the script.
true
, include the small 'toggle view' link above every headline in
plain view too. The visitor can toggle the view every where in the file
then. If false
, only at the top of the file such a link is displayed
when in plain view.
#ff0000
' or 'red
') or the keyword 'underline
'.
<a href="LINK_UP">Up</a>Command: '
h
' - homesubdir/index.org
and a homepage somwhere else.
<a href="LINK_TO_MAIN">Up</a>Command: '
H
' - HOMEsubdir/index.org
and a homepage somwhere else.
There is no need to do something you don't do occasionally in org-mode when it comes to HTML export. Just use one of the four ordinary ways to include something into the head of the resulting html file.
M-x org-insert-export-options-templateat the start of your org-file will insert, bet you know, this text:
#+TITLE: fancy-file.org #+AUTHOR: Your Name #+EMAIL: author@thinktank.tld #+LANGUAGE: de #+TEXT: Some descriptive text to be emitted. Several lines OK. #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ...Add this (in one line??):
#+STYLE: <script type=\"text/javascript\" language=\"JavaScript\" src="org-info.js\" /> <script type="text/javascript" language="JavaScript">/* <![CDATA[ */ org_html_manager.setup ();/* ]]> */</script>In this case I just include the script and drop the options to keep this line short. The next section will show how to pass startup options to script.
The second possibility to include the script is to add a special section to the end of your org file (multiple lines possible):
* COMMENT html style specifications # Local Variables: # org-export-html-style: "<link rel=\"stylesheet\" # type=\"text/css\" href=\"styles.css\" /> # <script type=\"text/javascript\" language=\"JavaScript\" src=\"org-info.js\"> # </script> # <script type=\"text/javascript\" language=\"JavaScript\"> # /* <![CDATA[ */ # org_html_manager.set(\"SUB_INDEXES\", 1); # org_html_manager.set(\"INFO_SWITCH_ALWAYS\", \"true\"); # org_html_manager.set(\"FOLDING\", \"true\"); # org_html_manager.set(\"MOUSE_HINT\", \"underline\"); # org_html_manager.setup (); # /* ]]> */ # </script> # End:
Ensure to precede all the verbatim double quotes with a backslash and
include the whole value of org-export-html-style
into double quotes
itself.
One could customize the option 'org-export-html-style
' globaly by
M-x cuomize-variable RET org-export-html-style RETand set it there.
"<script =\"text/javascript\" language=\"JavaScript\" src=\"org-info.js\"></script> <script type=\"text/javascript\" language=\"JavaScript\"> /* <![CDATA[ */ org_html_manager.set(\"SUB_INDEXES\", 1); org_html_manager.set(\"INFO_SWITCH_ALWAYS\", \"true\"); org_html_manager.set(\"FOLDING\", \"true\"); org_html_manager.set(\"MOUSE_HINT\", \"underline\"); org_html_manager.setup (); /* ]]> */ </script>"
This way all your files will be exported using the script in the future.
Last but not least and very handy is the possibility to setup the usage of the script per project. This is a taylor made passage of the org manual:
(setq org-publish-project-alist ’(("org" :base-directory "~/org/" :publishing-directory "~/public_html" :section-numbers nil :table-of-contents nil :style "<link rel=stylesheet href=\"../other/mystyle.css\" type=\"text/css\"> <script type=\"text/javascript\" language=\"JavaScript\" src=\"org-info.js\"></script> <script type=\"text/javascript\" language=\"JavaScript\"> /* <![CDATA[ */ org_html_manager.setup (); /* ]]> */ </script>")))
Don't forget to add an export target for the script itself ;-)
Once the script is included, the visitor of the resulting HTML file may use the mouse or the following keys to navigate the page:
Key | Action | Info | Plain |
---|---|---|---|
n | next section | y | y |
p | previous section | y | y |
i | goto T.O.C. | y | y |
u | one level up (parent section) | y | y |
s | prompt for section number | y | y |
t | toggle view mode | y | y |
v | scroll by 200 px | y | y |
V | scroll back 200 px | y | y |
? | show shortcuts | y | y |
h | follow the link 'UP' | y | y |
H | follow the link 'HOME' | y | y |
f | fold current section | y | |
g | fold globaly | y |
The script always tries to keep the last selected section visible. This is somewhat strange when scrolling, but really helpfull for keyboard navigation.
The functionality of the script is based on DOM
. This leads to some
incompatibility with legacy browsers. But hey, it's 2008, isn't it?
So what browsers are supported then? Well - I do not know for
shure. JavaScript™ 1.4 plus DOM
should make
I have written and tested the script only in current Firefox and Opera so far (lack of spare time, operation systems on my laptop, and installed browsers). The test results will go in the next section.
So let's gather the tested Browsers here. Problems are only listed, if they are Browser specific. Let me say it again: we don't wont to support legacy browsers, do we?
Browser | Version | ✔ | Problems |
---|---|---|---|
Opera | 9.26 | ✔ | - |
Iceweasel | 2.0.0.12 | ✔ | - |
If you manage to get this thingy working in any browser please let us know, so we can update the above table.
The 'toggle view' link next to the title does not work after toggling from info view mode to plain view mode. The link has to be hidden and shown again to make this work.
The link disappears when folding.
Done for absolute URLs. I think it rarely makes sense to compare the URL of
the current page with relative ones, since every subdirectory might contain
a file named index.html
.
TODO was:
The script needs to parse the URL of the current page itself to detect, if the 'Up' or 'HOME' lins point to the page itself. This is neccessary to avoid linking.
Fixed.
<div>
Footnotes are in the last container element. This is syntactically wrong, since Footnotes for all Sections go into the last parargraps container.
Moved regular expressions for triming of commands to the constructor.
TODO was:
Currently the regular expressions in OrgHtmlManager::getKey()
have to be
evaluated for each and every keypress. We should precompile them by defining
in the constructor or, better, setup if CONSOLE
is requested.
Console is not visible by default anymore.
TODO was:
When changing the view mode from info to plain and the console is on, the
current item is not visible. Hence we must scroll by 40px or so. The title
is only half visible either. Maybe put the console to the bottom of the
window. We could use a <div>
element with 100% height and verticle align
bottom to work around differences of browsers. It wont overlap other
clickable things if only 1px wide ;-)
Script will not start properly, when sections use h1 headline.
Please test. Could be solved by code cleanup on
.…to get a really plain view.
See section Why Do I Need a T.O.C? for the reasons.
So why not depend on TOC and add an option to hide it, show it or append it.
Text before first headline will show up on all pages above the navigation (not visible in info view though since we scroll the window to the navigation bar when in info view mode). Some will like that, most will say what I say: it's a bug. Pardon me.
The best solution for this IMHO would be:
OrgNode
OrgNode
too.
Internal links are not converted. So they do not work while in info view mode. Even worth: the document could become invisible when activating internal links while in info view mode.
This will force the parser to scan all links inside the document. But - so what? It just HAS to be done.
Actually they are not working in plain view mode either. The new toggling feature is working. What about that?
The navigation elements used should have distinct style class names so their appearance can be customized by the user. Currently they have no style classes but hard coded properties.
Add the possibility to NEVER show a toggeling link. The document would then
be viewable either in info view mode XOR in plain view mode. This would also
disable the 't
' command.
A nice thing to have. We need tests for the different settings of export
options concerning scripts like this one usable for other scripts too. Here
is a list of options in question and theire shorthands in the #+OPTIONS:
line. Some of them are not tested at all:
Shorthand | What it does |
---|---|
H: | Level of headslines |
toc: | T.O.C. |
@: | Turn on HTML-Tags (think of headlines containing HTML) |
f: | Footnotes |
skip: | Text before first headline |
Text before first headline is currently displayed on each and every page in info view mode. Footnotes are not tested at all. HTML-Tags should be no problem.
See Changelog of 2008-03-11.
TODO was:
Currently I still use comments to turn debugging output on/off :)
See Changelog of 2008-03-11.
TODO was:
This is not done yet. Maybe create a second script implementing folding only? One will have to decide between folding and toggling between these two view modes anyway.
Fixed for export with T.O.C.:
No try / catch / finaly
any more. The OrgHtmlManager
now simply stops
scanning when it can not find a element mentioned in table of
contents. Scanned elements are marked to avoid scanning them a second
time. The next scan starts 50 milliseconds later. If all elements mentioned
in TOC are successfully scanned, the interval function is removed from the
window object and the view gets initialised.
TODO was:
Currently the
org_html_manager
stops scanning when finding an item that is
null
by throwing an exeption. Then the it get's destroyed and is
created again. The new object starts, after 50 ms timeout, to scan the
document allover again. This is risky and could be optimized.
OrgHtmlManager
instance changes the T.O.C. and the new created object would not find the
expected content there.OrgHtmlManager
instance
and wake it up again after the timeout instead. The instance would save
the last valid state while being idle and waiting for the documents
contents to be created. This could speed up everythink even more (for
really big files).
The repeated scanning is neccessary to avoid browser detection. As an
example Opera says that if(window.document)
is true
, even if not the
whole thing is loaded yet (but we ask this question anyway. Firefox handles
this point as expected, as so some other browsers, thus scanning only once).
HIDE_TOC
. Hence the documents have to be exported with T.O.C., but may
be displayed without it.
document
itself. Still, the chars entered are appended to the
minibuffers contents, to keep the possibility to enter more complex
commands in the future. The minibuffer is still needed for commands to
work in firefox.
window.prompt()
<a href="LINK_UP">HOME</a>Command: '
h
' - home
<a href="LINK_TO_MAIN">Up</a>Command: '
H
' - HOME
This way we can link files into a tree, if all subdirectories in the
project follow the same conventions. Like containing some
subdir/index.org
and a homepage somwhere else.
?
' - show the little help screen.
n
' - go to next section.
p
' - go to previous section.
i
' - go to Index.
f
' - fold current section when in plain view mode.
g
' - fold globally when in plain view mode.
u
' - up to parent section.
t
' - toggle view mode.
v
' - scroll down.
V
' - scroll up.
help
' - show a little help screen. This done with alert()
and
thus a TODO.
t
' - toggle view mode.
k
' - kill the minibuffer.
N
' - where N
is a section number: goto section N
. This could be
working in both modes very easy, but currently also only in info view
mode implemented.
org_html_manager.set("WINDOW_BORDER", "true"); org_html_manager.set("DEBUG", org_html_manager.DEBUG_FATAL);
set(key, value)
function of the OrgHtmlManger
class like this:
org_html_manager.set ( "SUB_INDEXES", 0); org_html_manager.set ( "INFO_SWITCH_ALWAYS", "true"); org_html_manager.set ( "FOLDING", "true"); org_html_manager.set ( "MOUSE_HINT", "underline"); org_html_manager.set ( "CONSOLE", "true"); org_html_manager.setup ();
underline
' or any other
value. But if not 'underline
', it should be a valid value to set the
background-color
in CSS. So preferebly something like
'#eeeeee
'. In plain view mode with toggle feature turned on the
headline with mouse in it will be either hightlighted, if you pass a
color, or underlined.
k
'.
org_html_manager.PLAIN_VIEW
or
org_html_manager.INFO_VIEW
.
Note: not all options are documented here. These are the ones for
endusers. Developers! Look in the constructor function OrgHtmlManger ()
and OrgHtmlManager.set()
. It's really stupid and easy to
understand.
Write a similar script that strips all the surrounding body and puts all the
contents in one big <div>
. The document would be pageable like it is
now. Links in the content could be loaded dynamically into the same <div>
(Ajax). That way org files could serve as in-page website content and the
paging feature would be realy nice for big articles. No reload of sidebars
or header.
This way an article or tutorial could be spread over several files even. The deployment of those files is easy manageble through the already existing export infrastructure.
Ideas concerning org-mode in general.
1.) When switching a TODO item to the state STARTED
automatically add an
'assigned to' entry to the entry. In the example below I added a tag
':USERNAME:' to accomplish this but I could think of better ways. Maybe an
extra line like
ASSIGNED: USER TIMESTAMP
So no fiddling with the tags code.
2.) When switching a TODO item to the state DONE
automatically insert a
paragraph FIXES
to be filled with some ChangeLog message (something for
CONTRIB?).
This is what I mean:
Adding ChangeLog-like entries to TODO items when setting them to
DONE
.
STARTED
CLOCK
: --
Adding ChangeLog-like entries to TODO items when setting them to
DONE
.
DONE
CLOCK
: – => 2:10
org-export-headline-levels
if higher.
If org-ask-for-changelog-other-window
is not nil
offer input in
other window.
DONE
.
If we had the feature from the previous section we could have a function
org-sparse-tree-changelog
to just show the ChangeLog. We could also have a
function org-write-changelog
to prepend the current ChangeLog entry (or all
if prefix) to a file (_MTN/log
, ChangeLog
or what ever).
CLOCK:
When trying to create the example in last section I found it difficult to
include the :CLOCK
line. Why can't I export it?
Very special thanks to Carsten Dominik, Bastien Guerry and Phil Jackson who have encouraged me to write and publish this little piece of (unfinished) work and all the hundrets of hours they spent on this fantastic emacs mode called org-mode and the export modules.
Org is a new working experience for me and there is nothing comparable to working with emacs AND org-mode.
An other big kiss to Gabi (www.emma-stil.de) for being so patient while I was not working on our projects but playing with emacs.
What I think about licenses? Well - I think licences and patents are not far from each other. Poor people (and poor countries!!!) stay poor because of both of them. But since I know where I live, in a world made of licenses and patents, I have to apply some license to my work to protect it and stay unprotected.
Hence the script itself is provided under the GPL version 2. This document is subject to GFDL.
This document in emacs23 with org-mode v. 5.22a+. The visibilty of the
contents of a individual section or subsection can be toggled by clicking the
stars in front of the headlines or moving there and hitting TAB
. The
visibility of the entire document structure can be changed by pressing
SHIFT+TAB
anywhere. When on a headline, pressing ALT+UP/DOWN
moves the
entire subtree to different location in the tree, keeping it's level of
indentation. ALT+LEFT/RIGHT
promotes and demotes the subtree.
Date: 2008/03/23 01:21:40