mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-30 20:10:28 +00:00
286 lines
7.1 KiB
JavaScript
286 lines
7.1 KiB
JavaScript
|
//--
|
||
|
//-- TiddlyWiki-specific utility functions
|
||
|
//--
|
||
|
|
||
|
// Returns TiddlyWiki version string
|
||
|
function formatVersion(v)
|
||
|
{
|
||
|
v = v || version;
|
||
|
return v.major + "." + v.minor + "." + v.revision +
|
||
|
(v.alpha ? " (alpha " + v.alpha + ")" : "") +
|
||
|
(v.beta ? " (beta " + v.beta + ")" : "");
|
||
|
}
|
||
|
|
||
|
//# Compares two TiddlyWiki version objects
|
||
|
//# Returns +1 if v2 is later than v1
|
||
|
//# 0 if v2 is the same as v1
|
||
|
//# -1 if v2 is earlier than v1
|
||
|
//# version without a beta number is later than a version with a beta number
|
||
|
function compareVersions(v1,v2)
|
||
|
{
|
||
|
var x1,x2,i,a = ["major","minor","revision"];
|
||
|
for(i = 0; i<a.length; i++) {
|
||
|
x1 = v1[a[i]] || 0;
|
||
|
x2 = v2[a[i]] || 0;
|
||
|
if(x1<x2)
|
||
|
return 1;
|
||
|
if(x1>x2)
|
||
|
return -1;
|
||
|
}
|
||
|
x1 = v1.beta || 9999;
|
||
|
x2 = v2.beta || 9999;
|
||
|
if(x1<x2)
|
||
|
return 1;
|
||
|
return x1 > x2 ? -1 : 0;
|
||
|
}
|
||
|
|
||
|
function merge(dst,src,preserveExisting)
|
||
|
{
|
||
|
var i;
|
||
|
for(i in src) {
|
||
|
if(!preserveExisting || dst[i] === undefined)
|
||
|
dst[i] = src[i];
|
||
|
}
|
||
|
return dst;
|
||
|
}
|
||
|
|
||
|
// Resolve the target object of an event
|
||
|
function resolveTarget(e)
|
||
|
{
|
||
|
var obj;
|
||
|
if(e.target)
|
||
|
obj = e.target;
|
||
|
else if(e.srcElement)
|
||
|
obj = e.srcElement;
|
||
|
if(obj.nodeType == 3) // defeat Safari bug
|
||
|
obj = obj.parentNode;
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
// Returns a string containing the description of an exception, optionally prepended by a message
|
||
|
function exceptionText(e,message)
|
||
|
{
|
||
|
var s = e.description || e.toString();
|
||
|
return message ? "%0:\n%1".format([message,s]) : s;
|
||
|
}
|
||
|
|
||
|
// Displays an alert of an exception description with optional message
|
||
|
function showException(e,message)
|
||
|
{
|
||
|
alert(exceptionText(e,message));
|
||
|
}
|
||
|
|
||
|
function alertAndThrow(m)
|
||
|
{
|
||
|
alert(m);
|
||
|
throw(m);
|
||
|
}
|
||
|
|
||
|
function glyph(name)
|
||
|
{
|
||
|
var g = config.glyphs;
|
||
|
var b = g.currBrowser;
|
||
|
if(b == null) {
|
||
|
b = 0;
|
||
|
while(b < g.browsers.length-1 && !g.browsers[b]())
|
||
|
b++;
|
||
|
g.currBrowser = b;
|
||
|
}
|
||
|
if(!g.codes[name])
|
||
|
return "";
|
||
|
return g.codes[name][b];
|
||
|
}
|
||
|
|
||
|
function createTiddlyText(parent,text)
|
||
|
{
|
||
|
return parent.appendChild(document.createTextNode(text));
|
||
|
}
|
||
|
|
||
|
function createTiddlyCheckbox(parent,caption,checked,onChange)
|
||
|
{
|
||
|
var cb = document.createElement("input");
|
||
|
cb.setAttribute("type","checkbox");
|
||
|
cb.onclick = onChange;
|
||
|
parent.appendChild(cb);
|
||
|
cb.checked = checked;
|
||
|
cb.className = "chkOptionInput";
|
||
|
if(caption)
|
||
|
wikify(caption,parent);
|
||
|
return cb;
|
||
|
}
|
||
|
|
||
|
function createTiddlyElement(parent,element,id,className,text,attribs)
|
||
|
{
|
||
|
var n,e = document.createElement(element);
|
||
|
if(className != null)
|
||
|
e.className = className;
|
||
|
if(id != null)
|
||
|
e.setAttribute("id",id);
|
||
|
if(text != null)
|
||
|
e.appendChild(document.createTextNode(text));
|
||
|
if(attribs) {
|
||
|
for(n in attribs) {
|
||
|
e.setAttribute(n,attribs[n]);
|
||
|
}
|
||
|
}
|
||
|
if(parent != null)
|
||
|
parent.appendChild(e);
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
function createTiddlyButton(parent,text,tooltip,action,className,id,accessKey,attribs)
|
||
|
{
|
||
|
var i,btn = document.createElement("a");
|
||
|
btn.setAttribute("href","javascript:;");
|
||
|
if(action) {
|
||
|
btn.onclick = action;
|
||
|
}
|
||
|
if(tooltip)
|
||
|
btn.setAttribute("title",tooltip);
|
||
|
if(text)
|
||
|
btn.appendChild(document.createTextNode(text));
|
||
|
btn.className = className || "button";
|
||
|
if(id)
|
||
|
btn.id = id;
|
||
|
if(attribs) {
|
||
|
for(i in attribs) {
|
||
|
btn.setAttribute(i,attribs[i]);
|
||
|
}
|
||
|
}
|
||
|
if(parent)
|
||
|
parent.appendChild(btn);
|
||
|
if(accessKey)
|
||
|
btn.setAttribute("accessKey",accessKey);
|
||
|
return btn;
|
||
|
}
|
||
|
|
||
|
//# Create a link to an external resource
|
||
|
//# place - element where the link should be created
|
||
|
//# url - link target
|
||
|
//# label - link text (optional)
|
||
|
function createExternalLink(place,url,label)
|
||
|
{
|
||
|
var link = document.createElement("a");
|
||
|
link.className = "externalLink";
|
||
|
link.href = url;
|
||
|
var f = config.messages.externalLinkTooltip;
|
||
|
link.title = f ? f.format([url]) : url;
|
||
|
if(config.options.chkOpenInNewWindow)
|
||
|
link.target = "_blank";
|
||
|
place.appendChild(link);
|
||
|
if(label)
|
||
|
createTiddlyText(link, label);
|
||
|
return link;
|
||
|
}
|
||
|
|
||
|
function getTiddlyLinkInfo(title,currClasses)
|
||
|
{
|
||
|
var classes = currClasses ? currClasses.split(" ") : [];
|
||
|
classes.pushUnique("tiddlyLink");
|
||
|
var tiddler = store.fetchTiddler(title);
|
||
|
var subTitle;
|
||
|
if(tiddler) {
|
||
|
subTitle = tiddler.getSubtitle();
|
||
|
classes.pushUnique("tiddlyLinkExisting");
|
||
|
classes.remove("tiddlyLinkNonExisting");
|
||
|
classes.remove("shadow");
|
||
|
} else {
|
||
|
var f;
|
||
|
classes.remove("tiddlyLinkExisting");
|
||
|
classes.pushUnique("tiddlyLinkNonExisting");
|
||
|
if(store.isShadowTiddler(title)) {
|
||
|
f = config.messages.shadowedTiddlerToolTip;
|
||
|
classes.pushUnique("shadow");
|
||
|
} else {
|
||
|
f = config.messages.undefinedTiddlerToolTip;
|
||
|
classes.remove("shadow");
|
||
|
}
|
||
|
subTitle = f ? f.format([title]) : "";
|
||
|
}
|
||
|
if(typeof config.annotations[title]=="string")
|
||
|
subTitle = config.annotations[title];
|
||
|
return {classes: classes.join(" "),subTitle: subTitle};
|
||
|
}
|
||
|
|
||
|
// Event handler for clicking on a tiddly link
|
||
|
function onClickTiddlerLink(ev)
|
||
|
{
|
||
|
var e = ev || window.event;
|
||
|
var target = resolveTarget(e);
|
||
|
var link = target;
|
||
|
var title = null;
|
||
|
var fields = null;
|
||
|
var noToggle = null;
|
||
|
do {
|
||
|
title = link.getAttribute("tiddlyLink");
|
||
|
fields = link.getAttribute("tiddlyFields");
|
||
|
noToggle = link.getAttribute("noToggle");
|
||
|
link = link.parentNode;
|
||
|
} while(title == null && link != null);
|
||
|
if(!store.isShadowTiddler(title)) {
|
||
|
var f = fields ? fields.decodeHashMap() : {};
|
||
|
fields = String.encodeHashMap(merge(f,config.defaultCustomFields,true));
|
||
|
}
|
||
|
if(title) {
|
||
|
var toggling = e.metaKey || e.ctrlKey;
|
||
|
if(config.options.chkToggleLinks)
|
||
|
toggling = !toggling;
|
||
|
if(noToggle)
|
||
|
toggling = false;
|
||
|
if(store.getTiddler(title))
|
||
|
fields = null;
|
||
|
story.displayTiddler(target,title,null,true,null,fields,toggling);
|
||
|
}
|
||
|
clearMessage();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//# Create a link to a particular tiddler
|
||
|
//# place - element where the link should be created
|
||
|
//# title - title of target tiddler
|
||
|
//# includeText - flag for whether to include the title as the text of the link
|
||
|
//# className - custom CSS class for the link
|
||
|
//# linkedFromTiddler - tiddler from which to inherit extended fields
|
||
|
//# noToggle - flag to force the link to open the target, even if chkToggleLinks is on
|
||
|
function createTiddlyLink(place,title,includeText,className,isStatic,linkedFromTiddler,noToggle)
|
||
|
{
|
||
|
var title = jQuery.trim(title);
|
||
|
var text = includeText ? title : null;
|
||
|
var i = getTiddlyLinkInfo(title,className);
|
||
|
var btn = isStatic ? createExternalLink(place,store.getTiddlerText("SiteUrl",null) + "#" + title) : createTiddlyButton(place,text,i.subTitle,onClickTiddlerLink,i.classes);
|
||
|
if(isStatic)
|
||
|
btn.className += ' ' + className;
|
||
|
btn.setAttribute("refresh","link");
|
||
|
btn.setAttribute("tiddlyLink",title);
|
||
|
if(noToggle)
|
||
|
btn.setAttribute("noToggle","true");
|
||
|
if(linkedFromTiddler) {
|
||
|
var fields = linkedFromTiddler.getInheritedFields();
|
||
|
if(fields)
|
||
|
btn.setAttribute("tiddlyFields",fields);
|
||
|
}
|
||
|
return btn;
|
||
|
}
|
||
|
|
||
|
function refreshTiddlyLink(e,title)
|
||
|
{
|
||
|
var i = getTiddlyLinkInfo(title,e.className);
|
||
|
e.className = i.classes;
|
||
|
e.title = i.subTitle;
|
||
|
}
|
||
|
|
||
|
function createTiddlyDropDown(place,onchange,options,defaultValue)
|
||
|
{
|
||
|
var sel = createTiddlyElement(place,"select");
|
||
|
sel.onchange = onchange;
|
||
|
var t;
|
||
|
for(t=0; t<options.length; t++) {
|
||
|
var e = createTiddlyElement(sel,"option",null,null,options[t].caption);
|
||
|
e.value = options[t].name;
|
||
|
if(options[t].name == defaultValue)
|
||
|
e.selected = true;
|
||
|
}
|
||
|
return sel;
|
||
|
}
|
||
|
|