// -*- 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("<>", 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; } }