Add an underlay for javascript, and add ikiwiki.js containing some utility code.

* 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.
master
Joey Hess 2008-10-17 20:28:18 -04:00
parent 16d51e67a7
commit 79b376f991
7 changed files with 129 additions and 67 deletions

View File

@ -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" &&

View File

@ -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

9
debian/changelog vendored
View File

@ -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.)

View File

@ -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.

View File

@ -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 ""

View File

@ -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;
}

View File

@ -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";
}