nutools/legacy/twinc/base.js

986 lines
31 KiB
JavaScript
Raw Normal View History

2013-08-27 15:14:44 +04:00
// -*- coding: utf-8 -*-
//////////////////////////////////////////////////
// Outils divers et méthodes supplémentaires pour les classes de base
// Array
Array.prototype.indexOfItem = function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] == item) return i;
}
return -1;
}
Array.prototype.containsItem = function(item) {
return this.indexOfItem(item) != -1;
}
Array.prototype.sortBy = function(field, reverse) {
if (field == undefined) field = "title";
this.sort(function(a, b) {
if (a[field] == b[field]) {
return 0;
} else {
var result = a[field] < b[field]? -1 : +1;
if (reverse) result = -result;
return result;
}
});
}
// String
String.prototype.addText = function(item) {
var str = this;
if (str != "") str += " ";
str += item;
return str;
}
String.prototype.expandVars = function(vars, recursive) {
var text = this;
// remplacer les éléments de date
var now = vars && vars["now"]? Dat.valueOf(vars["now"]): new Date();
text = now.expandVars(text);
if (vars) {
// remplacer la valeurs des variables
var pos = 0;
var re_var = new RegExp("\\$(?:([a-zA-Z0-9_]+)|{([^}]+)})", "mg");
do {
re_var.lastIndex = pos;
var mo = re_var.exec(text);
if (mo) {
if (mo[1]) {
var name = mo[1];
var value = vars[name]? vars[name]: mo[0];
} else {
var name = mo[2];
try {
var value = vars.eval(name);
} catch(e) {
var value = e.toString();
}
}
text = text.substr(0, mo.index) + value + text.substr(mo.index + mo[0].length);
pos = mo.index;
if (!recursive) pos += new String(value).length;
}
} while(mo);
}
return text;
}
function expandVars(template, vars, recursive) {
return Str.valueOf(template).expandVars(vars, recursive);
}
String.prototype.firstLine = function() {
// obtenir la première ligne non vide d'une chaine
var text = this, line = "";
var start = 0, pos;
do {
pos = text.indexOf("\n", start);
if (pos == -1) {
line = text.substr(start);
break;
} else {
line = text.substring(start, pos);
if (new RegExp("\\S").test(line)) {
break;
}
}
start = pos + 1;
} while (pos != -1);
return line;
}
// Date
Date.parseFr = function(text) {
// créer une date à partir d'une chaine de la forme dd/mm/yyyy
var re_date = new RegExp("([0-9]+)/([0-9]+)/([0-9]+)");
var mo = re_date.exec(text);
if (mo) {
return new Date(parseInt(mo[3], 10), parseInt(mo[2], 10) - 1, parseInt(mo[1], 10));
} else {
return new Date(text);
}
}
var MMM = ["Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Jui", "Aoû", "Sep", "Oct", "Nov", "Déc"];
var MMMM = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
var D = ["L", "M", "M", "J", "V", "S", "D"];
var DD = ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"];
var DDD = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"];
Date.prototype.expandVars = function(text) {
text = text.replace(/%Y/g, this.getFullYear());
text = text.replace(/%4m/g, MMMM[this.getMonth()]);
text = text.replace(/%3m/g, MMM[this.getMonth()]);
text = text.replace(/%0m/g, String.zeroPad(this.getMonth() + 1, 2));
text = text.replace(/%m/g, this.getMonth());
text = text.replace(/%3d/g, DDD[this.getDow()]);
text = text.replace(/%2d/g, DD[this.getDow()]);
text = text.replace(/%1d/g, D[this.getDow()]);
text = text.replace(/%0d/g, String.zeroPad(this.getDate(), 2));
text = text.replace(/%d/g, this.getDate());
text = text.replace(/%H/g, this.getHours());
text = text.replace(/%M/g, this.getMinutes());
text = text.replace(/%S/g, this.getSeconds());
return text;
}
Date.prototype.formatFr = function() {
return this.expandVars("%0d/%0m/%Y");
}
Date.prototype.formatFrLong = function() {
return this.expandVars("%3d %0d/%0m/%Y");
}
Date.prototype.getWom = function() {
// obtenir le numéro de la semaine du mois: 0 - 4
var lundi = this.getMonday();
var day = lundi.getDate();
return Math.floor(day/7);
}
Date.prototype.getDow = function() {
// obtenir le jour de la semaine: 0(lundi) - 6(dimanche)
var dow = this.getDay();
dow = (dow + 6) % 7;
return dow;
}
Date.prototype.getMidnight = function() {
// obtenir la même date à minuit
return new Date(this.getFullYear(), this.getMonth(), this.getDate());
}
Date.prototype.addMonths = function(nb) {
// ajouter nb mois à la date, et retourner la date résultante à minuit
var y = this.getFullYear(), m = this.getMonth(), d = this.getDate();
m += nb;
while (m < 0) {
m += 12;
y--;
}
while (m > 11) {
m -= 12;
y++;
}
return new Date(y, m, d);
}
Date.prototype.addDays = function(nb) {
// ajouter nb jours à la date, et retourner la date résultante à minuit
var y = this.getFullYear(), m = this.getMonth(), d = this.getDate();
return new Date(y, m, d + nb);
}
Date.prototype.diffDays = function(date) {
return (date.getMidnight() - this.getMidnight()) / 86400000;
}
Date.prototype.getMonday = function() {
// obtenir le lundi de la semaine en cours
return this.addDays(-this.getDow());
}
Date.prototype.getFirstDay = function() {
// obtenir le premier jour du mois
return new Date(this.getFullYear(), this.getMonth(), 1);
}
var NUM_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
Date.prototype.getNumDays = function() {
// obtenir le nombre de jours de ce mois
var m = this.getMonth();
if (m == 1) {
var y = this.getFullYear();
var isleap = (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
return NUM_DAYS[m] + (isleap? 1: 0);
} else {
return NUM_DAYS[m];
}
}
Date.prototype.getLastDay = function() {
// obtenir le dernier jour du mois
return new Date(this.getFullYear(), this.getMonth(), this.getNumDays());
}
// ClickHandler
var ClickHandler = {};
ClickHandler.getEvent = function(e) {
if (!e) e = window.event;
return e;
}
ClickHandler.end = function(e) {
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return false;
}
// Str
var Str = {};
Str.valueOf = function(s) {
if (typeof(s) == "string") s = new String(s);
if (!(s instanceof String)) {
if (s == null || s == undefined) s = "";
s = new String(s);
}
return s;
}
// Dat
var Dat = {};
Dat.valueOf = function(d) {
if (d instanceof String || typeof(d) == "string") {
return Date.parseFr(d);
} else if (d instanceof Date) {
return d;
} else {
return new Date(d);
}
}
// Bool
var Bool = {};
Bool.valueOf = function(b) {
if (b instanceof String || typeof(b) == "string") {
var b = Str.valueOf(b).toLowerCase();
return ["oui", "o", "yes", "y", "vrai", "v", "true", "t", "1"].containsItem(b);
}
return Boolean(b).valueOf();
}
//////////////////////////////////////////////////
// Fonctions pour gérer les tags
Array.prototype.removeTag = function(tag) {
var pos = this.indexOfItem(tag);
if (pos != -1) {
this.splice(pos, 1);
}
return this;
}
Array.prototype.addTag = function(tag) {
this.pushUnique(tag);
return this;
}
Array.prototype.addTags = function(tags) {
if (tags instanceof String || typeof(tags) == "string") {
tags = new String(tags).splitTags();
}
for (var i = 0; i < tags.length; i++) {
this.addTag(tags[i]);
}
}
Array.prototype.containsTag = function(tag) {
return this.containsItem(tag);
}
Array.prototype.joinTags = function() {
var result = [];
for (var i = 0; i < this.length; i++) {
result.push(String.encodeTiddlyLink(this[i]));
}
return result.join(" ");
}
String.prototype.splitTags = function() {
return this.readBracketedList(true);
}
String.prototype.addTag = function(tag) {
var thistags = this.splitTags();
thistags.addTag(tag);
return thistags.joinTags();
}
String.prototype.addTags = function(tags) {
var thistags = this.splitTags();
thistags.addTags(tags);
return thistags.joinTags();
}
//////////////////////////////////////////////////
// Gestion des tiddlers et patches divers
// Tiddlers
var Tiddlers = {};
Tiddlers.valueOf = function(tiddler) {
if (!(tiddler instanceof Tiddler)) {
tiddler = store.tiddlers[tiddler];
}
return tiddler;
}
Tiddlers.getTags = function(tiddler) {
// obtenir la valeur de tags pour un tiddler
var tiddler = this.valueOf(tiddler);
if (tiddler) return tiddler.getTags();
return "";
}
Tiddlers.getSubtitle = function(tiddler) {
// obtenir la valeur de subtitle pour un title
var tiddler = this.valueOf(tiddler);
if (tiddler) return tiddler.getSubtitle();
return config.messages.subtitleUnknown;
}
Tiddlers.getFirstLine = function(tiddler) {
var tiddler = this.valueOf(tiddler);
if (tiddler) return tiddler.text.firstLine();
return "";
}
// patches divers
var createTiddlyButton_patchedByBase = window.createTiddlyButton;
window.createTiddlyButton = function(parent, text, tooltip, action, klass, id, accessKey) {
// afficher la touche de raccourci dans le title du bouton
if (accessKey) {
if (!tooltip) tooltip = "";
tooltip = Str.valueOf(tooltip).addText("(Alt + " + accessKey + ")");
}
return createTiddlyButton_patchedByBase(parent, text, tooltip, action, klass, id, accessKey);
}
closeTiddler_patchedByBase = window.closeTiddler;
window.closeTiddler = function(title, slowly) {
// patcher close pour désactiver l'animation sur la fermeture
var saveAnimate = config.options.chkAnimate;
config.options.chkAnimate = false;
closeTiddler_patchedByBase(title, slowly);
config.options.chkAnimate = saveAnimate;
}
displayTiddlers_patchedByBase = window.displayTiddlers;
window.displayTiddlers = function(src, titles, state, highlightText, highlightCaseSensitive, animate, slowly) {
// patcher displayTiddlers pour permettre l'affichage d'une liste de tiddlers générés par une macro.
// La macro doit implémenter textHandler pour être reconnue
if (titles.indexOf("<<") != -1) {
var pos = 0;
var re_macro = new RegExp("<<([^>\\s]+)(?:\\s*)([^>]*)>>", "mg");
do {
re_macro.lastIndex = pos;
var mo = re_macro.exec(titles);
if (mo) {
var macro = config.macros[mo[1]];
if (macro && macro.textHandler) {
var params = mo[2].readMacroParams();
var text = macro.textHandler(params);
titles = titles.substr(0, mo.index) + text + titles.substr(mo.index + mo[0].length);
pos = mo.index + new String(text).length;
} else {
pos = mo.index + mo[0].length;
}
}
} while (mo);
titles = titles.replace(/<<([^>\s]+)(?:\s*)([^>]*)>>/g, "");
}
displayTiddlers_patchedByBase(src, titles, state, highlightText,highlightCaseSensitive,animate,slowly);
}
// patcher createTiddlerToolbar pour que la liste des boutons à afficher soit dans un tableau modifiable
config.views.wikified.toolbarClose.onClick = onClickToolbarClose;
config.views.wikified.toolbarEdit.onClick = onClickToolbarEdit;
config.views.wikified.toolbarEdit.notReadOnly = true;
config.views.wikified.toolbarPermalink.onClick = onClickToolbarPermaLink;
config.views.wikified.toolbarReferences.onClick = onClickToolbarReferences;
config.views.wikified.toolbarButtons = [
config.views.wikified.toolbarClose,
config.views.wikified.toolbarEdit,
config.views.wikified.toolbarPermalink,
config.views.wikified.toolbarReferences];
config.views.editor.toolbarDone.onClick = onClickToolbarSave;
config.views.editor.toolbarDone.notReadOnly = true;
config.views.editor.toolbarCancel.onClick = onClickToolbarUndo;
config.views.editor.toolbarDelete.onClick = onClickToolbarDelete;
config.views.editor.toolbarDelete.notReadOnly = true;
config.views.editor.toolbarButtons = [
config.views.editor.toolbarDone,
config.views.editor.toolbarCancel,
config.views.editor.toolbarDelete];
// Create a tiddler toolbar according to whether it's an editor or not
createTiddlerToolbar = function(title, isEditor) {
var theToolbar = document.getElementById("toolbar" + title);
if(theToolbar) {
var lingo = config.views;
if (isEditor) lingo = lingo.editor;
else lingo = lingo.wikified;
removeChildren(theToolbar);
insertSpacer(theToolbar);
var toolbarButtons = lingo.toolbarButtons;
for (var i = 0; i < toolbarButtons.length; i++) {
var toolbarButton = toolbarButtons[i];
if (i > 0) insertSpacer(theToolbar);
if (!readOnly || !toolbarButton.notReadOnly) {
createTiddlyButton(theToolbar, toolbarButton.text, toolbarButton.tooltip, toolbarButton.onClick);
}
}
}
}
function installToolbarButton(toolbarButton, editor, before) {
// installer un bouton dans la vue wiki (par défaut) ou dans la vue éditeur (si editor==true), avant le bouton before
var lingo = config.views;
if (editor) lingo = lingo.editor;
else lingo = lingo.wikified;
var pos = -1;
if (before) {
pos = lingo.toolbarButtons.indexOfItem(before);
}
if (pos == -1) {
lingo.toolbarButtons.push(toolbarButton);
} else {
lingo.toolbarButtons.splice(pos, 0, toolbarButton);
}
}
function removeToolbarButton(toolbarButton, editor) {
var lingo = config.views;
if (editor) lingo = lingo.editor;
else lingo = lingo.wikified;
var pos = lingo.toolbarButtons.indexOfItem(toolbarButton);
if (pos != -1) {
lingo.toolbarButtons.splice(pos, 1);
}
}
//////////////////////////////////////////////////
// Gestion des paramètres
// Process a string list of macro parameters into an array. Parameters can be quoted
// with "", '', [[]] or left unquoted (and therefore space-separated)
// On reconnait aussi les paramètres de la forme name="value", name='value' ou name=value
String.prototype.readMacroParams = function() {
var regexpMacroParam = new RegExp("(?:\\s*)(?:" +
"(?:\"([^\"]*)\")|" +
"(?:'([^']*)')|" +
"(?:\\[\\[([^\\]]*)\\]\\])|" +
"([^\"'\\s]\\S*=(?:[^\"'\\s]\\S*|\"[^\"]*\"|'[^']*'))|" +
"([^\"'\\s]\\S*)" +
")","mg");
var params = [];
do {
var match = regexpMacroParam.exec(this);
if(match) {
if(match[1]) params.push(match[1]); // Double quoted
else if(match[2]) params.push(match[2]); // Single quoted
else if(match[3]) params.push(match[3]); // Double-square-bracket quoted
else if(match[4]) params.push(match[4]); // name=value, name="value" ou name='value'
else if(match[5]) params.push(match[5]); // Unquoted
}
} while(match);
return params;
}
function Options(params) {
// Dans un tableau de paramètre construit par String.readMacroParams, reconnaitre les options de la forme name=value
// L'objet retourné contient le tableau arg qui est une copie de params sans les options, et une propriété pour chaque option.
this.args = [];
var re_option = new RegExp("([^\"'\\s]\\S*)=(?:([^\"'\\s]\\S*)|\"([^\"]*)\"|'([^']*)')");
for (var i = 0; i < params.length; i++) {
var mo = re_option.exec(params[i]);
if (mo) {
var name = mo[1];
var value = mo[2]? mo[2]: mo[3]? mo[3]: mo[4]? mo[4]: "";
this[name] = value;
} else {
this.args.push(params[i]);
}
}
}
Options.prototype.get = function(name, def) {
// obtenir la valeur d'une option, avec une valeur par défaut
if (this[name]) return this[name];
return def;
}
Options.prototype.getArg = function(index, def) {
// obtenir la valeur d'un argument, avec une valeur par défaut
if (this.args[index]) return this.args[index];
return def;
}
Options.prototype.toParams = function() {
var params = "";
for (var i = 0; i < this.args.length; i++) {
var arg = this.args[i];
if (new RegExp("\\s").test(arg)) {
params = params + " \"" + arg + "\"";
} else {
params = params + " " + arg;
}
}
for (var prop in this) {
if (prop != "args" && prop != "get" && prop != "getArg" && prop != "toParams") {
params = params + " " + prop + "=";
var arg = new String(this[prop]);
if (new RegExp("\\s").test(arg)) {
params = params + "\"" + arg + "\"";
} else {
params = params + arg;
}
}
}
return params;
}
//////////////////////////////////////////////////
// La macro newTiddler
// arguments: title text= tooltip= tags=
config.macros.newTiddler.handler = function(place, macroName, params) {
// créer un nouveau tiddler avec le nom params[0] et les tags params[1..n]
if(!readOnly) {
var options = new Options(params);
var legacy = options.args[0]? false: true;
var tags = expandVars(options.get("tags", ""));
if (legacy) {
var title = config.macros.newTiddler.title;
var tooltip = options.get("tooltip", config.macros.newTiddler.prompt);
var text = options.get("text", config.macros.newTiddler.label);
} else {
var title = expandVars(options.args[0]);
var tooltip = options.get("tooltip", "Create a new tiddler named " + title);
var text = options.get("text", "new " + (tags? "tagged ": "") + "tiddler");
}
var onClick = function() {
displayTiddler(null, title, 2, null, null, false, false);
var tagsBox = document.getElementById("editorTags" + title);
if(tagsBox) tagsBox.value = tagsBox.value.addTags(tags);
if (legacy) {
var e = document.getElementById("editorTitle" + title);
e.focus();
e.select();
}
return false;
}
createTiddlyButton(place, text, tooltip, onClick, undefined, undefined, legacy? this.accessKey: undefined);
}
}
//////////////////////////////////////////////////
// Les macros de gestion d'événements
// La macro event
// arguments: date title nbDays= format=
config.macros.event = {
TODAY: "aujourd'hui",
TOMORROW: "demain",
YESTERDAY: "hier",
FUTURE_EVENT: "dans $remaining jours",
PAST_EVENT: "il y a ${-remaining} jours",
FORMAT: "$remainingDays: $title le $date"
};
config.macros.event.getRemainingDays = function(remaining) {
if (remaining == 0) remainingDays = this.TODAY;
else if (remaining == 1) remainingDays = this.TOMORROW;
else if (remaining == -1) remainingDays = this.YESTERDAY;
else if (remaining < 0) remainingDays = this.PAST_EVENT;
else remainingDays = this.FUTURE_EVENT;
return remainingDays;
}
config.macros.event.textHandler = function(params) {
var options = new Options(params);
var date = options.args[0]? Date.parseFr(options.args[0]): new Date();
var title = options.args[1]? options.args[1]: "Unnamed event";
var nbDays = parseInt(options.get("nbDays", "15"), 10);
var format = options.get("format", this.FORMAT);
var remaining = new Date().diffDays(date);
var remainingDays = this.getRemainingDays(remaining);
var vars = {remaining: remaining, remainingDays: remainingDays, title: title, date: date.formatFr()};
if (Math.abs(remaining) <= nbDays) return expandVars(format, vars, true);
}
config.macros.event.handler = function(place, macroName, params) {
var text = this.textHandler(params);
if (text && text != "") wikify(text, place);
}
// La macro showEvents
// arguments: nbDays= format= headerFormat= noEventsFormat=
config.macros.showEvents = {
NO_EVENTS_FORMAT: "Il n'y a pas d'événements en cours",
HEADER_FORMAT: "|Date|Evénement|",
FORMAT: "|$date|$title|"
};
config.macros.showEvents.textHandler = function(params) {
var options = new Options(params);
var noEventsFormat = options.get("noEventsFormat", this.NO_EVENTS_FORMAT);
var headerFormat = options.get("headerFormat", this.HEADER_FORMAT);
var format = options.get("format", this.FORMAT);
var vars = {}
var tiddlers = store.reverseLookup("tags", "event", true, "title");
if (tiddlers && tiddlers.length) {
var text = expandVars(headerFormat, vars) + "\n";
for (var i = 0; i < tiddlers.length; i++) {
var tags = tiddlers[i].getTags();
var re_date = new RegExp("\\s?@([0-9]+/[0-9]+/[0-9]+)\\s?", "g");
var mo = re_date.exec(tags);
if (mo) {
var date = Date.parseFr(mo[1]);
var title = tiddlers[i].title;
var remaining = new Date().diffDays(date);
var remainingDays = config.macros.event.getRemainingDays(remaining);
var vars = {remaining: remaining, remainingDays: remainingDays, title: title, date: date.formatFr()};
text += expandVars(format, vars, true) + "\n";
}
}
} else {
var text = expandVars(noEventsFormat, vars);
}
return text;
}
config.macros.showEvents.handler = function(place, macroName, params) {
var text = this.textHandler(params);
if (text && text != "") wikify(text, place);
}
// La macro calendar
// arguments:
var currentFirstDay;
config.macros.calendar = {};
config.macros.calendar.refresh = function(e) {
var target = resolveTarget(ClickHandler.getEvent(e));
var tiddler = findContainingTiddler(target);
if (tiddler) {
refreshTiddler(tiddler.id.substr(7));
} else {
while(target && target.id != "mainMenu") {
target = target.parentNode;
}
if (target) {
refreshMenu();
}
}
}
config.macros.calendar.handler = function(place, macroName, params) {
var now = new Date().getMidnight();
if (currentFirstDay) {
var firstDay = currentFirstDay;
} else {
var firstDay = now.getFirstDay();
}
var firstCalDay = firstDay.getMonday();
var table, tr, td;
buildModifiedTiddlers();
table = createTiddlyElement(place, "table");
table.setAttribute("class", "calendar");
var onClickPreviousMonth = function(e) {
currentFirstDay = currentFirstDay.addMonths(-1);
config.macros.calendar.refresh(e);
return false;
}
var onClickNextMonth = function(e) {
currentFirstDay = currentFirstDay.addMonths(1);
config.macros.calendar.refresh(e);
return false;
}
tr = createTiddlyElement(table, "tr");
tr.setAttribute("class", "navRow");
td = createTiddlyElement(tr, "td");
createTiddlyButton(td, "<", "mois précédent", onClickPreviousMonth);
td = createTiddlyElement(tr, "td");
td.colSpan = 5;
createTiddlyText(td, MMMM[firstDay.getMonth()] + " " + firstDay.getFullYear());
td = createTiddlyElement(tr, "td");
createTiddlyButton(td, ">", "mois suivant", onClickNextMonth);
tr = createTiddlyElement(table, "tr");
tr.setAttribute("class", "hdrRow");
for (var i = 0; i < D.length; i++) {
td = createTiddlyElement(tr, "td");
createTiddlyText(td, D[i]);
}
createCal(table, now, firstCalDay, firstDay);
currentFirstDay = firstDay;
}
function createCal(table, now, firstCalDay, firstDay) {
var td, tr;
var lastDay = firstDay.getLastDay();
var day = firstCalDay;
do {
tr = createTiddlyElement(table, "tr");
tr.setAttribute("class", "calRow");
for (var i = 0; i < 7; i++) {
td = createTiddlyElement(tr, "td");
createCalDay(td, day, firstDay, now, lastDay);
day = day.addDays(1);
}
} while (day <= lastDay);
}
function createCalDay(td, day, firstDay, now, lastDay) {
var modified = getModifiedTiddlers(day);
var events = getEvents(day);
var title = day.formatFr();
var klass = new String();
if (day.getTime() == now.getTime()) klass = klass.addText("calToday");
if (day < firstDay || day > lastDay) klass = klass.addText("calOther");
if ((modified && modified.length) ||(events && events.length)) {
klass = klass.addText("calEvent");
var a = [];
if (modified && modified.length) a.push("" + modified.length + " tiddler(s)");
if (events && events.length) a.push("" + events.length + " événements(s)");
title += ": " + a.join(",");
}
td.setAttribute("class", klass);
td.title = title;
td.onclick = function(e) {
e = ClickHandler.getEvent(e);
var popup = Popup.create(resolveTarget(e));
if (!readOnly) {
var tags = "event @" + day.formatFr();
wikify("<<newTiddler text=\"nouvel événement\" tooltip=\"nouvel événement le " + day.formatFr() + "\" tags=\"" + tags + "\">>", popup);
}
var addLinks = function(tiddlers, title, field) {
if (tiddlers && tiddlers.length) {
if (field) tiddlers.sortBy(field);
var div = createTiddlyElement(popup, "div", null, null, title);
for (var i = 0; i < tiddlers.length; i++) {
var div = createTiddlyElement(popup, "div");
var link = createTiddlyLink(div, tiddlers[i].title, false);
insertSpacer(link);
insertSpacer(link);
createTiddlyText(link, tiddlers[i].title);
}
}
}
addLinks(events, "événements:");
addLinks(modified, "modifiés:", "title");
Popup.show();
return ClickHandler.end(e);
}
createTiddlyText(td, day.getDate());
}
var modifiedTiddlers;
function buildModifiedTiddlers() {
modifiedTiddlers = {};
for (var t in store.tiddlers) {
var tiddler = store.tiddlers[t];
var date = tiddler.modified.formatFr();
if (!modifiedTiddlers[date]) {
modifiedTiddlers[date] = [];
}
modifiedTiddlers[date].push(tiddler);
}
}
function getModifiedTiddlers(date) {
return modifiedTiddlers[date.formatFr()];
}
function getEvents(date) {
return store.reverseLookup("tags", "@" + date.formatFr(), true, "modified");
}
setStylesheet("\
/** Le calendrier se divise en trois parties: nav (pour la navigation),\
hdr (pour les jours de la semaine), et cal (pour les jours du calendrier proprement dit)\
\
Chaque style est préfixé de nav, hdr ou cal.\
*/\
.calendar {\
margin: 0em;\
text-align: center;\
font-size: 9pt;\
}\
\
/** la barre de navigation */\
.navRow {\
}\
\
/** la ligne d'en-tête, qui contient les jours */\
.hdrRow {\
}\
\
/** une ligne du calendrier */\
.calRow {\
}\
\
.calToday { /* cellule de calendrier: date du jour */\
color: Blue;\
border: 1px solid black;\
}\
\
.calOther { /* cellule de calendrier: jour d'un autre mois */\
color: LightSteelBlue;\
font-size: 8pt;\
}\
\
.calEvent { /* cellule de calendrier: événement disponible */\
font-weight: bold;\
text-decoration: underline;\
}\
", "calendar");
//////////////////////////////////////////////////
// Gestion de l'autorefresh
function refreshAllTiddlersTaggedAutoRefresh(hint) {
// rafraichir tous les tiddlers ayant le tag "autoRefresh"
var tagged = store.getTaggedTiddlers("autoRefresh");
for (var i = 0; i < tagged.length; i++) {
refreshTiddler(tagged[i].title);
}
}
config.notifyTiddlers.push({name: null, notify: refreshAllTiddlersTaggedAutoRefresh});
//////////////////////////////////////////////////
// Le bouton keepThis
function keepTiddler(titleToKeep) {
var display = document.getElementById("tiddlerDisplay");
var tiddler = display.firstChild;
while(tiddler) {
var nextTiddler = tiddler.nextSibling;
if(tiddler.id) {
if(tiddler.id.substr(0,7) == "tiddler") {
var title = tiddler.id.substr(7);
if(titleToKeep != title && !document.getElementById("editorWrapper" + title))
display.removeChild(tiddler);
}
}
tiddler = nextTiddler;
}
}
var toolbarKeep = {text: "keep this", tooltip: "Close all other tiddlers"};
toolbarKeep.onClick = function(e) {
e = ClickHandler.getEvent(e);
if(this.parentNode.id) {
keepTiddler(this.parentNode.id.substr(7));
}
return ClickHandler.end(e);
}
//////////////////////////////////////////////////
// Les macros closeCurrent, editCurrent, saveCurrent
config.macros.closeCurrent = {label: "close", prompt: "Close current tiddler", accessKey: "W"};
config.macros.closeCurrent.handler = function(place, macroName, params) {
createTiddlyButton(place, this.label, this.prompt, this.onClick, null, null, this.accessKey);
}
config.macros.closeCurrent.onClick = function(e) {
e = ClickHandler.getEvent(e);
if (currentTiddler) {
// ne pas fermer un tiddler s'il est en cours d'édition
if(!document.getElementById("editorWrapper" + currentTiddler)) {
clearMessage();
closeTiddler(currentTiddler, e.shiftKey || e.altKey);
currentTiddler = null;
}
}
return ClickHandler.end(e);
}
config.macros.editCurrent = {label: "edit", prompt: "Edit current tiddler", accessKey: "E"};
config.macros.editCurrent.handler = function(place, macroName, params) {
if (!readOnly) {
createTiddlyButton(place, this.label, this.prompt, this.onClick, null, null, this.accessKey);
}
}
config.macros.editCurrent.onClick = function(e) {
e = ClickHandler.getEvent(e);
if (currentTiddler) {
clearMessage();
displayTiddler(null, currentTiddler, 2, null, null, false, false);
}
return ClickHandler.end(e);
}
config.macros.saveCurrent = {label: "save", prompt: "Save current tiddler", accessKey: "S"};
config.macros.saveCurrent.handler = function(place, macroName, params) {
if (!readOnly) {
createTiddlyButton(place, this.label, this.prompt, this.onClick, null, null, this.accessKey);
}
}
config.macros.saveCurrent.onClick = function(e) {
e = ClickHandler.getEvent(e);
if (currentTiddler) {
clearMessage();
saveTiddler(currentTiddler, e.shiftKey);
}
return ClickHandler.end(e);
}
// patcher les méthodes existantes pour supporter la notion de "current tiddler"
var currentTiddler = null;
var selectTiddler_patchedByBase = window.selectTiddler;
window.selectTiddler = function(title) {
// un tiddler sélectionné avec la souris devient le tiddler courant
selectTiddler_patchedByBase(title);
currentTiddler = title;
}
var displayTiddler_patchedByBase = window.displayTiddler;
window.displayTiddler = function(src, title, state, highlightText, highlightCaseSensitive, animate, slowly) {
displayTiddler_patchedByBase(src, title, state, highlightText, highlightCaseSensitive, animate, slowly);
// un tiddler que l'on affiche devient le tiddler courant
currentTiddler = title;
}
var deleteTiddler_patchedByBase = window.deleteTiddler;
window.deleteTiddler = function(title) {
deleteTiddler_patchedByBase(title);
if (title == currentTiddler) {
// si on supprimer le tiddler courant, il n'y a plus de tiddler courant
currentTiddler = null;
}
}