diff options
-rw-r--r-- | IkiWiki/Plugin/attachment.pm | 7 | ||||
-rw-r--r-- | IkiWiki/Plugin/toggle.pm | 69 | ||||
-rw-r--r-- | debian/changelog | 9 | ||||
-rw-r--r-- | doc/plugins/write.mdwn | 29 | ||||
-rw-r--r-- | po/ikiwiki.pot | 16 | ||||
-rw-r--r-- | underlays/javascript/ikiwiki.js | 37 | ||||
-rw-r--r-- | underlays/javascript/toggle.js | 29 |
7 files changed, 129 insertions, 67 deletions
diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm index dcac3e820..6c1df488a 100644 --- a/IkiWiki/Plugin/attachment.pm +++ b/IkiWiki/Plugin/attachment.pm @@ -6,6 +6,7 @@ use strict; use IkiWiki 2.00; sub import { #{{{ + add_underlay("javascript"); hook(type => "getsetup", id => "attachment", call => \&getsetup); hook(type => "checkconfig", id => "attachment", call => \&checkconfig); hook(type => "formbuilder_setup", id => "attachment", call => \&formbuilder_setup); @@ -104,10 +105,10 @@ sub formbuilder_setup (@) { #{{{ $form->tmpl_param("field-upload" => '<input name="_submit" type="submit" value="Upload Attachment" />'); $form->tmpl_param("field-link" => '<input name="_submit" type="submit" value="Insert Links" />'); - # Add the javascript from the toggle plugin; - # the attachments interface uses it to toggle visibility. + # Add the toggle javascript; the attachments interface uses + # it to toggle visibility. require IkiWiki::Plugin::toggle; - $form->tmpl_param("javascript" => $IkiWiki::Plugin::toggle::javascript); + $form->tmpl_param("javascript" => IkiWiki::Plugin::toggle::include_javascript($params{page}, 1)); # Start with the attachments interface toggled invisible, # but if it was used, keep it open. if ($form->submitted ne "Upload Attachment" && diff --git a/IkiWiki/Plugin/toggle.pm b/IkiWiki/Plugin/toggle.pm index 610d38e3a..657d8d3c2 100644 --- a/IkiWiki/Plugin/toggle.pm +++ b/IkiWiki/Plugin/toggle.pm @@ -5,61 +5,8 @@ use warnings; use strict; use IkiWiki 2.00; -# Here's the javascript that makes this possible. A key feature is the use -# of css to hide toggleables, to avoid any flashing on page load. The css -# is only emitted after the javascript tests that it's going to be able to -# show the toggleables. -our $javascript=<<'EOF'; -<script type="text/javascript"> -<!-- -if (document.getElementById && document.getElementsByTagName && document.createTextNode) { - document.write('<style type="text/css">div.toggleable { display: none; }</style>'); - window.onload = inittoggle; -} - -function inittoggle() { - var as = getElementsByClass('toggle'); - for (var i = 0; i < as.length; i++) { - var id = as[i].href.match(/#(\w.+)/)[1]; - if (document.getElementById(id).className == "toggleable") - document.getElementById(id).style.display="none"; - as[i].onclick = function() { - toggle(this); - return false; - } - } -} - -function toggle(s) { - var id = s.href.match(/#(\w.+)/)[1]; - style = document.getElementById(id).style; - if (style.display == "none") - style.display = "block"; - else - style.display = "none"; -} - -function getElementsByClass(cls, node, tag) { - if (document.getElementsByClass) - return document.getElementsByClass(cls, node, tag); - if (! node) node = document; - if (! tag) tag = '*'; - var ret = new Array(); - var pattern = new RegExp("(^|\\s)"+cls+"(\\s|$)"); - var els = node.getElementsByTagName(tag); - for (i = 0; i < els.length; i++) { - if ( pattern.test(els[i].className) ) { - ret.push(els[i]); - } - } - return ret; -} - -//--> -</script> -EOF - sub import { #{{{ + add_underlay("javascript"); hook(type => "getsetup", id => "toggle", call => \&getsetup); hook(type => "preprocess", id => "toggle", call => \&preprocess_toggle); @@ -121,12 +68,22 @@ sub format (@) { #{{{ if ($params{content}=~s!(<div class="toggleable(?:-open)?" id="[^"]+">\s*)</div>!$1!g) { $params{content}=~s/<div class="toggleableend">//g; - if (! ($params{content}=~s!^<body>!<body>$javascript!m)) { + if (! ($params{content}=~s!^(<body>)!$1.include_javascript($params{page})!em)) { # no </body> tag, probably in preview mode - $params{content}=$javascript.$params{content}; + $params{content}=include_javascript($params{page}, 1).$params{content}; } } return $params{content}; } # }}} +sub include_javascript ($;$) { #{{{ + my $page=shift; + my $absolute=shift; + + return '<script src="'.urlto("ikiwiki.js", $page, $absolute). + '" type="text/javascript" charset="utf-8"></script>'."\n". + '<script src="'.urlto("toggle.js", $page, $absolute). + '" type="text/javascript" charset="utf-8"></script>'; +} #}}} + 1 diff --git a/debian/changelog b/debian/changelog index b93da0aae..66d108e9e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +ikiwiki (2.68) UNRELEASED; urgency=low + + * Add an underlay for javascript, and add ikiwiki.js containing some utility + code. + * toggle: Stop embedding the full toggle code on each page using it, and + move it to toggle.js in the javascript underlay. + + -- Joey Hess <joeyh@debian.org> Fri, 17 Oct 2008 20:11:02 -0400 + ikiwiki (2.67) unstable; urgency=low * remove: Avoid $_ breakage. (Stupid, stupid perl.) diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 1b78f5900..daf70c8e2 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -847,3 +847,32 @@ to a hash containing all the config items. They should also implement a By the way, to parse a ikiwiki setup file and populate `%config`, a program just needs to do something like: `use IkiWiki::Setup; IkiWiki::Setup::load($filename)` + +### Javascript + +Some plugins use javascript to make ikiwiki look a bit more web-2.0-ish. + +All javascript code should be put in `.js` files in the `javascript` +underlay, and plugins using those files can enable use of the underlay by +calling `add_underlay("javascript");` in their `import` function. + +You'll have to arrange for `<script>` tags to be added to the pages that +use your javascript. This can be done using a `format` hook. + +Ikiwiki provides some utility functions in `ikiwiki.js`, for use by other +javascript code. These include: + +#### `getElementsByClass(cls, node, tag)` + +Returns an array of elements with the given class. The node and tag are +optional and define what document node and element names to search. + +#### `hook(name, call)` + +The function `call` will be run as part of the hook named `name`. + +Note that to hook into `window.onload`, you can use the `onload' hook. + +#### `run_hooks(name)` + +Runs the hooks with the specified name. diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index 87898d285..6853df153 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-10-17 13:14-0400\n" +"POT-Creation-Date: 2008-10-17 20:11-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -48,7 +48,7 @@ msgstr "" msgid "You are banned." msgstr "" -#: ../IkiWiki/CGI.pm:385 ../IkiWiki/CGI.pm:386 ../IkiWiki.pm:1166 +#: ../IkiWiki/CGI.pm:385 ../IkiWiki/CGI.pm:386 ../IkiWiki.pm:1167 msgid "Error" msgstr "" @@ -150,20 +150,20 @@ msgstr "" msgid "Failed to delete file from S3: " msgstr "" -#: ../IkiWiki/Plugin/attachment.pm:48 +#: ../IkiWiki/Plugin/attachment.pm:49 #, perl-format msgid "there is already a page named %s" msgstr "" -#: ../IkiWiki/Plugin/attachment.pm:81 +#: ../IkiWiki/Plugin/attachment.pm:82 msgid "prohibited by allowed_attachments" msgstr "" -#: ../IkiWiki/Plugin/attachment.pm:189 +#: ../IkiWiki/Plugin/attachment.pm:190 msgid "bad attachment filename" msgstr "" -#: ../IkiWiki/Plugin/attachment.pm:231 +#: ../IkiWiki/Plugin/attachment.pm:232 msgid "attachment upload" msgstr "" @@ -926,12 +926,12 @@ msgstr "" msgid "failed to load external plugin needed for %s plugin: %s" msgstr "" -#: ../IkiWiki.pm:1149 +#: ../IkiWiki.pm:1150 #, perl-format msgid "preprocessing loop detected on %s at depth %i" msgstr "" -#: ../IkiWiki.pm:1658 +#: ../IkiWiki.pm:1659 msgid "yes" msgstr "" diff --git a/underlays/javascript/ikiwiki.js b/underlays/javascript/ikiwiki.js new file mode 100644 index 000000000..29de7ec6f --- /dev/null +++ b/underlays/javascript/ikiwiki.js @@ -0,0 +1,37 @@ +// ikiwiki's javascript utility function library + +var hooks = new Array; +window.onload = run_hooks_onload; + +function run_hooks_onload() { + run_hooks("onload"); +} + +function run_hooks(name) { + for (var i = 0; i < hooks.length; i++) { + if (hooks[i].name == name) { + hooks[i].call(); + } + } +} + +function hook(name, call) { + var h={name: name, call: call}; + hooks.push(h); +} + +function getElementsByClass(cls, node, tag) { + if (document.getElementsByClass) + return document.getElementsByClass(cls, node, tag); + if (! node) node = document; + if (! tag) tag = '*'; + var ret = new Array(); + var pattern = new RegExp("(^|\\s)"+cls+"(\\s|$)"); + var els = node.getElementsByTagName(tag); + for (i = 0; i < els.length; i++) { + if ( pattern.test(els[i].className) ) { + ret.push(els[i]); + } + } + return ret; +} diff --git a/underlays/javascript/toggle.js b/underlays/javascript/toggle.js new file mode 100644 index 000000000..d190b737a --- /dev/null +++ b/underlays/javascript/toggle.js @@ -0,0 +1,29 @@ +// Uses CSS to hide toggleables, to avoid any flashing on page load. The +// CSS is only emitted after it tests that it's going to be able +// to show the toggleables. +if (document.getElementById && document.getElementsByTagName && document.createTextNode) { + document.write('<style type="text/css">div.toggleable { display: none; }</style>'); + hook("onload", inittoggle); +} + +function inittoggle() { + var as = getElementsByClass('toggle'); + for (var i = 0; i < as.length; i++) { + var id = as[i].href.match(/#(\w.+)/)[1]; + if (document.getElementById(id).className == "toggleable") + document.getElementById(id).style.display="none"; + as[i].onclick = function() { + toggle(this); + return false; + } + } +} + +function toggle(s) { + var id = s.href.match(/#(\w.+)/)[1]; + style = document.getElementById(id).style; + if (style.display == "none") + style.display = "block"; + else + style.display = "none"; +} |