//-- //-- 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; };