mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-11 18:50:28 +00:00
313 lines
8.6 KiB
JavaScript
313 lines
8.6 KiB
JavaScript
|
//--
|
||
|
//-- Option handling
|
||
|
//--
|
||
|
|
||
|
config.optionHandlers = {
|
||
|
'txt': {
|
||
|
get: function(name) {return encodeCookie(config.options[name].toString());},
|
||
|
set: function(name,value) {config.options[name] = decodeCookie(value);}
|
||
|
},
|
||
|
'chk': {
|
||
|
get: function(name) {return config.options[name] ? 'true' : 'false';},
|
||
|
set: function(name,value) {config.options[name] = value == 'true';}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function setOption(name,value)
|
||
|
{
|
||
|
var optType = name.substr(0,3);
|
||
|
if(config.optionHandlers[optType] && config.optionHandlers[optType].set)
|
||
|
config.optionHandlers[optType].set(name,value);
|
||
|
}
|
||
|
|
||
|
// Gets the value of an option as a string. Most code should just read from config.options.* directly
|
||
|
function getOption(name)
|
||
|
{
|
||
|
var optType = name.substr(0,3);
|
||
|
return config.optionHandlers[optType] && config.optionHandlers[optType].get ? config.optionHandlers[optType].get(name) : null;
|
||
|
}
|
||
|
|
||
|
//# Loads config.options from cookies and SystemSettings
|
||
|
function loadOptions()
|
||
|
{
|
||
|
if(safeMode)
|
||
|
return;
|
||
|
loadCookies();
|
||
|
loadSystemSettings();
|
||
|
}
|
||
|
// @Deprecated; retained for backwards compatibility
|
||
|
var loadOptionsCookie = loadOptions;
|
||
|
|
||
|
function getCookies()
|
||
|
{
|
||
|
var cookieList = document.cookie.split(';');
|
||
|
var i,cookies = {};
|
||
|
for(i=0; i<cookieList.length; i++) {
|
||
|
var p = cookieList[i].indexOf('=');
|
||
|
if(p != -1) {
|
||
|
var name = cookieList[i].substr(0,p).trim();
|
||
|
var value = cookieList[i].substr(p+1).trim();
|
||
|
cookies[name] = value;
|
||
|
}
|
||
|
}
|
||
|
return cookies;
|
||
|
}
|
||
|
|
||
|
function loadCookies()
|
||
|
{
|
||
|
var i,cookies = getCookies();
|
||
|
if(cookies['TiddlyWiki']) {
|
||
|
cookies = cookies['TiddlyWiki'].decodeHashMap();
|
||
|
}
|
||
|
for(i in cookies) {
|
||
|
if(config.optionsSource[i] != 'setting') {
|
||
|
setOption(i,cookies[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function loadSystemSettings()
|
||
|
{
|
||
|
var key,settings = store.calcAllSlices('SystemSettings');
|
||
|
config.optionsSource = {};
|
||
|
for(key in settings) {
|
||
|
setOption(key,settings[key]);
|
||
|
config.optionsSource[key] = 'setting';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//# called back from SystemSettings notifier
|
||
|
function onSystemSettingsChange()
|
||
|
{
|
||
|
if(!startingUp) {
|
||
|
loadSystemSettings();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function saveOption(name)
|
||
|
{
|
||
|
if(safeMode)
|
||
|
return;
|
||
|
if(name.match(/[()\s]/g, '_')) {
|
||
|
alert(config.messages.invalidCookie.format([name]));
|
||
|
return;
|
||
|
}
|
||
|
saveCookie(name);
|
||
|
if(config.optionsSource[name] == 'setting') {
|
||
|
saveSystemSetting(name,true);
|
||
|
}
|
||
|
}
|
||
|
// @Deprecated; retained for backwards compatibility
|
||
|
var saveOptionCookie = saveOption;
|
||
|
|
||
|
function removeCookie(name)
|
||
|
{
|
||
|
document.cookie = name + '=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
|
||
|
}
|
||
|
|
||
|
function saveCookie(name)
|
||
|
{
|
||
|
var key,cookies = {};
|
||
|
for(key in config.options) {
|
||
|
var value = getOption(key);
|
||
|
value = value == null ? 'false' : value;
|
||
|
cookies[key] = value;
|
||
|
}
|
||
|
document.cookie = 'TiddlyWiki=' + String.encodeHashMap(cookies) + '; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/';
|
||
|
cookies = getCookies();
|
||
|
var c;
|
||
|
for(c in cookies) {
|
||
|
var optType = c.substr(0,3);
|
||
|
if(config.optionHandlers[optType])
|
||
|
removeCookie(c);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var systemSettingSave;
|
||
|
function commitSystemSettings(storeWasDirty)
|
||
|
{
|
||
|
if(systemSettingSave) {
|
||
|
window.clearTimeout(systemSettingSave);
|
||
|
}
|
||
|
systemSettingSave = window.setTimeout(function() {
|
||
|
var tiddler = store.getTiddler('SystemSettings');
|
||
|
if(storeWasDirty == false && story.areAnyDirty() == false) {
|
||
|
//# nothing has changed except the options, so we can force a save
|
||
|
saveChanges(null,[tiddler]);
|
||
|
} else {
|
||
|
autoSaveChanges(null,[tiddler]);
|
||
|
}
|
||
|
}, 1000);
|
||
|
}
|
||
|
|
||
|
function saveSystemSetting(name,saveFile)
|
||
|
{
|
||
|
var title = 'SystemSettings';
|
||
|
var slice = store.getTiddlerSlice(title,name);
|
||
|
if(readOnly || slice === getOption(name)) {
|
||
|
return; //# don't save if read-only or the option hasn't changed
|
||
|
}
|
||
|
var slices = store.calcAllSlices(title);
|
||
|
var key;
|
||
|
for(key in config.optionsSource) {
|
||
|
var value = getOption(key) || '';
|
||
|
if(slices[key] !== value) {
|
||
|
slices[key] = value;
|
||
|
}
|
||
|
}
|
||
|
var text = [];
|
||
|
for(key in slices) {
|
||
|
text.push('%0: %1'.format([key,slices[key]]));
|
||
|
}
|
||
|
text = text.sort().join('\n');
|
||
|
var storeWasDirty = store.isDirty();
|
||
|
var tiddler = store.getTiddler(title);
|
||
|
if(tiddler) {
|
||
|
tiddler.text = text;
|
||
|
tiddler = store.saveTiddler(tiddler);
|
||
|
} else {
|
||
|
tiddler = store.saveTiddler(title,title,text,'System',new Date(),['excludeLists'],config.defaultCustomFields);
|
||
|
}
|
||
|
if(saveFile) {
|
||
|
commitSystemSettings(storeWasDirty);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//# Flatten cookies to ANSI character set by substituting html character entities for non-ANSI characters
|
||
|
function encodeCookie(s)
|
||
|
{
|
||
|
return escape(convertUnicodeToHtmlEntities(s));
|
||
|
}
|
||
|
|
||
|
//# Decode any html character entities to their unicode equivalent
|
||
|
function decodeCookie(s)
|
||
|
{
|
||
|
s = unescape(s);
|
||
|
var re = /&#[0-9]{1,5};/g;
|
||
|
return s.replace(re,function($0) {return String.fromCharCode(eval($0.replace(/[&#;]/g,'')));});
|
||
|
}
|
||
|
|
||
|
config.macros.option.genericCreate = function(place,type,opt,className,desc)
|
||
|
{
|
||
|
var typeInfo = config.macros.option.types[type];
|
||
|
var c = document.createElement(typeInfo.elementType);
|
||
|
if(typeInfo.typeValue)
|
||
|
c.setAttribute('type',typeInfo.typeValue);
|
||
|
c[typeInfo.eventName] = typeInfo.onChange;
|
||
|
c.setAttribute('option',opt);
|
||
|
c.className = className || typeInfo.className;
|
||
|
if(config.optionsDesc[opt])
|
||
|
c.setAttribute('title',config.optionsDesc[opt]);
|
||
|
place.appendChild(c);
|
||
|
if(desc != 'no')
|
||
|
createTiddlyText(place,config.optionsDesc[opt] || opt);
|
||
|
c[typeInfo.valueField] = config.options[opt];
|
||
|
return c;
|
||
|
};
|
||
|
|
||
|
config.macros.option.genericOnChange = function(e)
|
||
|
{
|
||
|
var opt = this.getAttribute('option');
|
||
|
if(opt) {
|
||
|
var optType = opt.substr(0,3);
|
||
|
var handler = config.macros.option.types[optType];
|
||
|
if(handler.elementType && handler.valueField)
|
||
|
config.macros.option.propagateOption(opt,handler.valueField,this[handler.valueField],handler.elementType,this);
|
||
|
}
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
config.macros.option.types = {
|
||
|
'txt': {
|
||
|
elementType: 'input',
|
||
|
valueField: 'value',
|
||
|
eventName: 'onchange',
|
||
|
className: 'txtOptionInput',
|
||
|
create: config.macros.option.genericCreate,
|
||
|
onChange: config.macros.option.genericOnChange
|
||
|
},
|
||
|
'chk': {
|
||
|
elementType: 'input',
|
||
|
valueField: 'checked',
|
||
|
eventName: 'onclick',
|
||
|
className: 'chkOptionInput',
|
||
|
typeValue: 'checkbox',
|
||
|
create: config.macros.option.genericCreate,
|
||
|
onChange: config.macros.option.genericOnChange
|
||
|
}
|
||
|
};
|
||
|
|
||
|
config.macros.option.propagateOption = function(opt,valueField,value,elementType,elem)
|
||
|
{
|
||
|
config.options[opt] = value;
|
||
|
saveOption(opt);
|
||
|
var t,nodes = document.getElementsByTagName(elementType);
|
||
|
for(t=0; t<nodes.length; t++) {
|
||
|
var optNode = nodes[t].getAttribute('option');
|
||
|
if(opt == optNode && nodes[t]!=elem)
|
||
|
nodes[t][valueField] = value;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
config.macros.option.handler = function(place,macroName,params,wikifier,paramString)
|
||
|
{
|
||
|
params = paramString.parseParams('anon',null,true,false,false);
|
||
|
var opt = (params[1] && params[1].name == 'anon') ? params[1].value : getParam(params,'name',null);
|
||
|
var className = (params[2] && params[2].name == 'anon') ? params[2].value : getParam(params,'class',null);
|
||
|
var desc = getParam(params,'desc','no');
|
||
|
var type = opt.substr(0,3);
|
||
|
var h = config.macros.option.types[type];
|
||
|
if(h && h.create)
|
||
|
h.create(place,type,opt,className,desc);
|
||
|
};
|
||
|
|
||
|
config.macros.options.handler = function(place,macroName,params,wikifier,paramString)
|
||
|
{
|
||
|
params = paramString.parseParams('anon',null,true,false,false);
|
||
|
var showUnknown = getParam(params,'showUnknown','no');
|
||
|
var wizard = new Wizard();
|
||
|
wizard.createWizard(place,this.wizardTitle);
|
||
|
wizard.addStep(this.step1Title,this.step1Html);
|
||
|
var markList = wizard.getElement('markList');
|
||
|
var chkUnknown = wizard.getElement('chkUnknown');
|
||
|
chkUnknown.checked = showUnknown == 'yes';
|
||
|
chkUnknown.onchange = this.onChangeUnknown;
|
||
|
var listWrapper = document.createElement('div');
|
||
|
markList.parentNode.insertBefore(listWrapper,markList);
|
||
|
wizard.setValue('listWrapper',listWrapper);
|
||
|
this.refreshOptions(listWrapper,showUnknown == 'yes');
|
||
|
};
|
||
|
|
||
|
config.macros.options.refreshOptions = function(listWrapper,showUnknown)
|
||
|
{
|
||
|
var n,opts = [];
|
||
|
for(n in config.options) {
|
||
|
var opt = {};
|
||
|
opt.option = '';
|
||
|
opt.name = n;
|
||
|
opt.lowlight = !config.optionsDesc[n];
|
||
|
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
|
||
|
if(!opt.lowlight || showUnknown)
|
||
|
opts.push(opt);
|
||
|
}
|
||
|
opts.sort(function(a,b) {return a.name.substr(3) < b.name.substr(3) ? -1 : (a.name.substr(3) == b.name.substr(3) ? 0 : +1);});
|
||
|
ListView.create(listWrapper,opts,this.listViewTemplate);
|
||
|
for(n=0; n<opts.length; n++) {
|
||
|
var type = opts[n].name.substr(0,3);
|
||
|
var h = config.macros.option.types[type];
|
||
|
if(h && h.create) {
|
||
|
h.create(opts[n].colElements['option'],type,opts[n].name,null,'no');
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
config.macros.options.onChangeUnknown = function(e)
|
||
|
{
|
||
|
var wizard = new Wizard(this);
|
||
|
var listWrapper = wizard.getValue('listWrapper');
|
||
|
jQuery(listWrapper).empty();
|
||
|
config.macros.options.refreshOptions(listWrapper,this.checked);
|
||
|
return false;
|
||
|
};
|
||
|
|