From 79b376f9912891a8748fcbb4580969e4dbf7fc75 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 17 Oct 2008 20:28:18 -0400 Subject: 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. --- underlays/javascript/ikiwiki.js | 37 +++++++++++++++++++++++++++++++++++++ underlays/javascript/toggle.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 underlays/javascript/ikiwiki.js create mode 100644 underlays/javascript/toggle.js (limited to 'underlays/javascript') 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(''); + 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"; +} -- cgit v1.2.3 From 7390a7a0721d9985c88efec1fd0e3a19d0368c82 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 17 Oct 2008 20:47:32 -0400 Subject: relativedate: New javascript-alicious plugin that makes all dates display relative, in a very nice way, if I say so myself. --- IkiWiki/Plugin/inline.pm | 2 ++ IkiWiki/Plugin/relativedate.pm | 41 +++++++++++++++++++++ IkiWiki/Render.pm | 2 ++ debian/changelog | 2 ++ doc/plugins/ddate.mdwn | 1 + doc/plugins/prettydate.mdwn | 2 +- doc/plugins/relativedate.mdwn | 16 +++++++++ doc/plugins/type/date.mdwn | 1 + po/ikiwiki.pot | 32 ++++++++--------- templates/inlinepage.tmpl | 8 ++--- templates/page.tmpl | 14 ++++---- underlays/javascript/relativedate.js | 70 ++++++++++++++++++++++++++++++++++++ 12 files changed, 163 insertions(+), 28 deletions(-) create mode 100644 IkiWiki/Plugin/relativedate.pm create mode 100644 doc/plugins/relativedate.mdwn create mode 100644 doc/plugins/type/date.mdwn create mode 100644 underlays/javascript/relativedate.js (limited to 'underlays/javascript') diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 6d88c2f15..536d7cd02 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -316,7 +316,9 @@ sub preprocess_inline (@) { #{{{ $template->param(pageurl => urlto(bestlink($params{page}, $page), $params{destpage})); $template->param(title => pagetitle(basename($page))); $template->param(ctime => displaytime($pagectime{$page}, $params{timeformat})); + $template->param(ctime_raw => scalar localtime($pagectime{$page})); $template->param(mtime => displaytime($pagemtime{$page}, $params{timeformat})); + $template->param(mtime_raw => scalar localtime($pagemtime{$page})); $template->param(first => 1) if $page eq $list[0]; $template->param(last => 1) if $page eq $list[$#list]; diff --git a/IkiWiki/Plugin/relativedate.pm b/IkiWiki/Plugin/relativedate.pm new file mode 100644 index 000000000..99265676b --- /dev/null +++ b/IkiWiki/Plugin/relativedate.pm @@ -0,0 +1,41 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::relativedate; + +use warnings; +use strict; +use IkiWiki 2.00; + +sub import { #{{{ + add_underlay("javascript"); + hook(type => "format", id => "relativedate", call => \&format); +} # }}} + +sub getsetup () { #{{{ + return + plugin => { + safe => 1, + rebuild => 1, + }, +} #}}} + +sub format (@) { #{{{ + my %params=@_; + + if (! ($params{content}=~s!^()!$1.include_javascript($params{page})!em)) { + # no tag, probably in preview mode + $params{content}=include_javascript($params{page}, 1).$params{content}; + } + return $params{content}; +} # }}} + +sub include_javascript ($;$) { #{{{ + my $page=shift; + my $absolute=shift; + + return ''."\n". + ''; +} #}}} + +1 diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index bc997ffb0..8385c1aff 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -109,7 +109,9 @@ sub genpage ($$) { #{{{ backlinks => $backlinks, more_backlinks => $more_backlinks, mtime => displaytime($pagemtime{$page}), + mtime_raw => scalar localtime($pagemtime{$page}), ctime => displaytime($pagectime{$page}), + ctime_raw => scalar localtime($pagectime{$page}), baseurl => baseurl($page), ); diff --git a/debian/changelog b/debian/changelog index 66d108e9e..908eb1f53 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,8 @@ ikiwiki (2.68) UNRELEASED; urgency=low code. * toggle: Stop embedding the full toggle code on each page using it, and move it to toggle.js in the javascript underlay. + * relativedate: New javascript-alicious plugin that makes all dates display + relative, in a very nice way, if I say so myself. -- Joey Hess Fri, 17 Oct 2008 20:11:02 -0400 diff --git a/doc/plugins/ddate.mdwn b/doc/plugins/ddate.mdwn index e82760d88..741606a6e 100644 --- a/doc/plugins/ddate.mdwn +++ b/doc/plugins/ddate.mdwn @@ -1,5 +1,6 @@ [[!template id=plugin name=ddate author="[[Joey]]"]] [[!tag type/fun]] +[[!tag type/date]] Enables use of Discordian dates. `--timeformat` can be used to change the date format; see `ddate(1)`. diff --git a/doc/plugins/prettydate.mdwn b/doc/plugins/prettydate.mdwn index 9a67f5dca..11ad4252f 100644 --- a/doc/plugins/prettydate.mdwn +++ b/doc/plugins/prettydate.mdwn @@ -1,5 +1,5 @@ [[!template id=plugin name=prettydate author="[[Joey]]"]] -[[!tag type/format]] +[[!tag type/date]] Enabling this plugin changes the dates displayed on pages in the wiki to a format that is nice and easy to read. Examples: "late Wednesday evening, diff --git a/doc/plugins/relativedate.mdwn b/doc/plugins/relativedate.mdwn new file mode 100644 index 000000000..ecbdf68bf --- /dev/null +++ b/doc/plugins/relativedate.mdwn @@ -0,0 +1,16 @@ +[[!template id=plugin name=prettydate author="[[Joey]]"]] +[[!tag type/date]] + +This plugin lets dates be displayed in relative form. Examples: "2 days ago", +"1 month and 3 days ago", "30 minutes ago". Hovering over the date will +cause a tooltip to pop up with the absolute date. + +This only works in browsers with javascript enabled; other browsers will +show the absolute date instead. Also, this plugin can be used with other +plugins like [[prettydate]] that change how the absolute date is displayed. + +If this plugin is enabled, you may also add relative dates to pages in the +wiki, by using html elements in the "date" class. For example, this will +display as a relative date: + + Fri Oct 17 18:36:13 EDT 2008 diff --git a/doc/plugins/type/date.mdwn b/doc/plugins/type/date.mdwn new file mode 100644 index 000000000..eae1226da --- /dev/null +++ b/doc/plugins/type/date.mdwn @@ -0,0 +1 @@ +These plugins control how ikiwiki displays dates. diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index 6853df153..2d213a799 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 20:11-0400\n" +"POT-Creation-Date: 2008-10-17 20:39-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -172,9 +172,9 @@ msgid "automatic index generation" msgstr "" #: ../IkiWiki/Plugin/brokenlinks.pm:33 ../IkiWiki/Plugin/editpage.pm:261 -#: ../IkiWiki/Plugin/inline.pm:327 ../IkiWiki/Plugin/opendiscussion.pm:26 +#: ../IkiWiki/Plugin/inline.pm:329 ../IkiWiki/Plugin/opendiscussion.pm:26 #: ../IkiWiki/Plugin/orphans.pm:37 ../IkiWiki/Render.pm:79 -#: ../IkiWiki/Render.pm:149 +#: ../IkiWiki/Render.pm:151 msgid "discussion" msgstr "" @@ -318,11 +318,11 @@ msgstr "" msgid "nonexistant template %s" msgstr "" -#: ../IkiWiki/Plugin/inline.pm:335 ../IkiWiki/Render.pm:83 +#: ../IkiWiki/Plugin/inline.pm:337 ../IkiWiki/Render.pm:83 msgid "Discussion" msgstr "" -#: ../IkiWiki/Plugin/inline.pm:572 +#: ../IkiWiki/Plugin/inline.pm:574 msgid "RPC::XML::Client not found, not pinging" msgstr "" @@ -780,59 +780,59 @@ msgstr "" msgid "

Error: %s exited nonzero (%s)" msgstr "" -#: ../IkiWiki/Render.pm:253 +#: ../IkiWiki/Render.pm:255 #, perl-format msgid "" "symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to " "allow this" msgstr "" -#: ../IkiWiki/Render.pm:277 ../IkiWiki/Render.pm:302 +#: ../IkiWiki/Render.pm:279 ../IkiWiki/Render.pm:304 #, perl-format msgid "skipping bad filename %s" msgstr "" -#: ../IkiWiki/Render.pm:284 +#: ../IkiWiki/Render.pm:286 #, perl-format msgid "%s has multiple possible source pages" msgstr "" -#: ../IkiWiki/Render.pm:360 +#: ../IkiWiki/Render.pm:362 #, perl-format msgid "removing old page %s" msgstr "" -#: ../IkiWiki/Render.pm:400 +#: ../IkiWiki/Render.pm:402 #, perl-format msgid "scanning %s" msgstr "" -#: ../IkiWiki/Render.pm:405 +#: ../IkiWiki/Render.pm:407 #, perl-format msgid "rendering %s" msgstr "" -#: ../IkiWiki/Render.pm:426 +#: ../IkiWiki/Render.pm:428 #, perl-format msgid "rendering %s, which links to %s" msgstr "" -#: ../IkiWiki/Render.pm:447 +#: ../IkiWiki/Render.pm:449 #, perl-format msgid "rendering %s, which depends on %s" msgstr "" -#: ../IkiWiki/Render.pm:486 +#: ../IkiWiki/Render.pm:488 #, perl-format msgid "rendering %s, to update its backlinks" msgstr "" -#: ../IkiWiki/Render.pm:498 +#: ../IkiWiki/Render.pm:500 #, perl-format msgid "removing %s, no longer rendered by %s" msgstr "" -#: ../IkiWiki/Render.pm:522 +#: ../IkiWiki/Render.pm:524 #, perl-format msgid "ikiwiki: cannot render %s" msgstr "" diff --git a/templates/inlinepage.tmpl b/templates/inlinepage.tmpl index ffcb897a8..3f640fcdd 100644 --- a/templates/inlinepage.tmpl +++ b/templates/inlinepage.tmpl @@ -5,9 +5,9 @@ - + - + @@ -28,14 +28,14 @@

-Posted +Posted Tags: - + diff --git a/templates/page.tmpl b/templates/page.tmpl index f2f9c34cc..7456e9e41 100644 --- a/templates/page.tmpl +++ b/templates/page.tmpl @@ -22,7 +22,7 @@ -/ +/ @@ -74,7 +74,7 @@
Tags: - +
@@ -83,13 +83,13 @@ Tags: - +
diff --git a/underlays/javascript/relativedate.js b/underlays/javascript/relativedate.js new file mode 100644 index 000000000..c5e62b3cc --- /dev/null +++ b/underlays/javascript/relativedate.js @@ -0,0 +1,70 @@ +// Causes html elements in the 'date' and 'pagedate' classes to be displayed +// as relative dates. The date is parsed from the title attribute, or from +// the element content. + +var dateElements; + +hook("onload", getDates); + +function getDates() { + dateElements = getElementsByClass('date'); + for (var i = 0; i < dateElements.length; i++) { + var elt = dateElements[i]; + var title = elt.attributes.title; + var d = new Date(title ? title.value : elt.innerHTML); + if (! isNaN(d)) { + dateElements[i].date=d; + elt.title=elt.innerHTML; + } + } + + showDates(); +} + +function showDates() { + for (var i = 0; i < dateElements.length; i++) { + var elt = dateElements[i]; + var d = elt.date; + if (! isNaN(d)) { + elt.innerHTML=relativeDate(d); + } + } + setTimeout(showDates,30000); // keep updating every 30s +} + +var timeUnits = new Array; +timeUnits['minute'] = 60; +timeUnits['hour'] = timeUnits['minute'] * 60; +timeUnits['day'] = timeUnits['hour'] * 24; +timeUnits['month'] = timeUnits['day'] * 30; +timeUnits['year'] = timeUnits['day'] * 364; +var timeUnitOrder = ['year', 'month', 'day', 'hour', 'minute']; + +function relativeDate(date) { + var now = new Date(); + var offset = date.getTime() - now.getTime(); + var seconds = Math.round(Math.abs(offset) / 1000); + + var ret = ""; + var shown = 0; + for (i = 0; i < timeUnitOrder.length; i++) { + var unit = timeUnitOrder[i]; + if (seconds >= timeUnits[unit]) { + var num = Math.floor(seconds / timeUnits[unit]); + seconds -= num * timeUnits[unit]; + if (ret) + ret += "and "; + ret += num + " " + unit + (num > 1 ? "s" : "") + " "; + + if (++shown == 2) + break; + } + else if (shown) + break; + } + + if (! ret) + ret = "less than a minute " + + return ret + (offset < 0 ? "ago" : "from now"); +} -- cgit v1.2.3 From 18806fa6b0f2afab703d558a499da8918214a1c7 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 18 Oct 2008 12:47:08 -0400 Subject: allow ikiwiki.js to be loaded twice w/o clobbering previous hooks Clearly it's suboptimal for it to be loaded twice, but this is a quick fix at least. --- underlays/javascript/ikiwiki.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'underlays/javascript') diff --git a/underlays/javascript/ikiwiki.js b/underlays/javascript/ikiwiki.js index 29de7ec6f..14ddd0745 100644 --- a/underlays/javascript/ikiwiki.js +++ b/underlays/javascript/ikiwiki.js @@ -1,6 +1,6 @@ // ikiwiki's javascript utility function library -var hooks = new Array; +var hooks; window.onload = run_hooks_onload; function run_hooks_onload() { @@ -8,16 +8,19 @@ function run_hooks_onload() { } function run_hooks(name) { - for (var i = 0; i < hooks.length; i++) { - if (hooks[i].name == name) { - hooks[i].call(); + if (typeof(hooks) != "undefined") { + 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); + if (typeof(hooks) == "undefined") + hooks = new Array; + hooks.push({name: name, call: call}); } function getElementsByClass(cls, node, tag) { -- cgit v1.2.3 From 002be0c87afd6c7310d2dd2babbb6a03dac8f881 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 19 Oct 2008 15:45:29 -0400 Subject: partial support for calling onload once the DOM is ready This adds support for gecko and newer versions of opera to call onload once the DOM is ready, rather than waiting for all images in the page to load. Makes relativedate behave somewhat better. Dealing with this means jumping into the browser incompatability waters that I prefer to avoid. Full solutions for most of the major browsers are listed here: http://dean.edwards.name/weblog/2006/06/again/ However, no *license* is listed there, so I can't use that code. Also, the more involved code appears to have various issues (such as the inline IE code not working via https). So I only added the simple call to a hook needed for gecko/opera. It seems that the only standards-compliant way to do this is using the `defer` attribute to a `script` tag, using an external script that will be loaded once the DOM is ready, and can call onload. However, that has browser compatability issues of its own, since not all browsers honor `defer`. Perhaps I should really just be using one of the javascript frameworks, that include code to solve this for the major browsers. But something about them still puts me off, and this issue is minor enough that I'm willing to live with incomplete support for now. --- underlays/javascript/ikiwiki.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'underlays/javascript') diff --git a/underlays/javascript/ikiwiki.js b/underlays/javascript/ikiwiki.js index 14ddd0745..1252f244f 100644 --- a/underlays/javascript/ikiwiki.js +++ b/underlays/javascript/ikiwiki.js @@ -1,9 +1,21 @@ // ikiwiki's javascript utility function library var hooks; + +// Run onload as soon as the DOM is ready, if possible. +// gecko, opera 9 +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", run_hooks_onload, false); +} +// other browsers window.onload = run_hooks_onload; function run_hooks_onload() { + // avoid firing twice + if (arguments.callee.done) + return; + arguments.callee.done = true; + run_hooks("onload"); } -- cgit v1.2.3 From ee1ccfa863b9d56cf7ec987f7fee89c98c484b0b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 20 Oct 2008 19:22:22 -0400 Subject: use relativedate as the css class for dates that should display relative --- IkiWiki/Plugin/relativedate.pm | 2 +- doc/plugins/relativedate.mdwn | 6 +++--- underlays/javascript/relativedate.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'underlays/javascript') diff --git a/IkiWiki/Plugin/relativedate.pm b/IkiWiki/Plugin/relativedate.pm index d9d8f7776..f4dba61a4 100644 --- a/IkiWiki/Plugin/relativedate.pm +++ b/IkiWiki/Plugin/relativedate.pm @@ -53,7 +53,7 @@ sub display ($;$) { #{{{ my $gmtime=decode_utf8(POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time))); - return ''. + return ''. IkiWiki::formattime($time, $format).''; } #}}} diff --git a/doc/plugins/relativedate.mdwn b/doc/plugins/relativedate.mdwn index 121bce477..32f8c798b 100644 --- a/doc/plugins/relativedate.mdwn +++ b/doc/plugins/relativedate.mdwn @@ -10,7 +10,7 @@ show the absolute date instead. Also, this plugin can be used with other plugins like [[prettydate]] that change how the absolute date is displayed. If this plugin is enabled, you may also add relative dates to pages in the -wiki, by using html elements in the "date" class. For example, this will -display as a relative date: +wiki, by using html elements in the "relativedate" class. For example, this +will display as a relative date: - Fri Oct 17 18:36:13 EDT 2008 + Fri Oct 17 18:36:13 EDT 2008 diff --git a/underlays/javascript/relativedate.js b/underlays/javascript/relativedate.js index c5e62b3cc..8e05d4065 100644 --- a/underlays/javascript/relativedate.js +++ b/underlays/javascript/relativedate.js @@ -1,4 +1,4 @@ -// Causes html elements in the 'date' and 'pagedate' classes to be displayed +// Causes html elements in the 'relativedate' class to be displayed // as relative dates. The date is parsed from the title attribute, or from // the element content. @@ -7,7 +7,7 @@ var dateElements; hook("onload", getDates); function getDates() { - dateElements = getElementsByClass('date'); + dateElements = getElementsByClass('relativedate'); for (var i = 0; i < dateElements.length; i++) { var elt = dateElements[i]; var title = elt.attributes.title; -- cgit v1.2.3