Wikipedia:WikiProject User scripts/preferences

A working example of a cookie based preference schema for MediaWiki's Gadgets extension (currently installed on Wikipedia). See the talk page for discussions. Edit the script on this page for now.
Ideally, this should be completely replaced by some sort of ajax based variable definition system?

Main module

edit

For example, could be placed at MediaWiki:Gadget-jsprefs.js

// array definitions
if(!window.jsprefsLoaded) {
  var jsprefsLoaded = true; //load once
  var jsPrefs = [];         //associative array
  var jsPrefsSettable = []; //indexed array of associative elements
  addOnloadHook(function() { addPortletLink('p-tb','javascript:jsPrefsPanel()','Script preferences','t-jsprefs','You are using scripts with settable preferences.'); });
}
 
// prefs panel (crude UI, needs rewriting and cross-browser checking)
function jsPrefsPanel() {
  if(jsPrefsSettable.length==0) return;
 
  var bod = document.getElementsByTagName('body')[0];
  var prefsdiv = document.createElement('div');
    prefsdiv.setAttribute('style','font-size:120%;position:absolute;top:0;left:0;width:50%;height:90%;border:2px solid black;z-index:10;background-color:#ffffff;padding:.5em;margin:2em;display:block;overflow:auto;');
    prefsdiv.setAttribute('id','jsPrefsWindow');
  var phead = document.createElement('h2');
    phead.setAttribute('style','border-bottom:1px solid black;text-align:center;margin:0;');
    var kill = document.createElement('a');
      kill.setAttribute('style','float:right;font-size:66%')
      kill.setAttribute('href','javascript:closePrefs();')
      kill.appendChild(document.createTextNode('Close'));
    phead.appendChild(kill);
    phead.appendChild(document.createTextNode('Javascript/Gadget User Preferences'));
  var caveat = document.createElement('div');
    caveat.setAttribute('style','border:1px solid black;font-style:italic;text-align:center;margin:8px;');
    caveat.appendChild(document.createTextNode('Note: These are cookie-settable user prefernces for various user scripts loaded via the MediaWiki gadgets extension. You can set these more permanently by editing your skin.js file. See [insert link] for more details. \n--example caveat--'))
  prefsdiv.appendChild(phead);
  prefsdiv.appendChild(caveat);
  bod.appendChild(prefsdiv);
 
  for (var i = 0; i < jsPrefsSettable.length; i++) {
    var pdiv = document.createElement('div');
    pdiv.appendChild(document.createTextNode(jsPrefsSettable[i].name));
    pdiv.setAttribute('style','border:1px solid black;margin:5px;background-color:#ddffdd;');
 
    var inp = document.createElement('input');
    inp.setAttribute('id','pref-' + jsPrefsSettable[i].name);
    inp.setAttribute('name','pref-' + jsPrefsSettable[i].name);
    if(getjsPref(jsPrefsSettable[i].name)) {
      inp.setAttribute('style','color:black;margin:1px 10px;');
    } else {
      inp.setAttribute('style','color:#888888;margin:1px 10px;');
    }
    var btn = document.createElement('input');
    btn.setAttribute('type','button');
    btn.setAttribute('value','Save');
    btn.setAttribute('style','margin-right:.5em;');
    switch (jsPrefsSettable[i].type) {
      case 'boolean':
        inp.setAttribute('type','checkbox');
        if(getjsPref(jsPrefsSettable[i].name)) inp.checked = 'true'
        btn.setAttribute('onclick','setjsPref("' + jsPrefsSettable[i].name + '",document.getElementById("' + 'pref-' + jsPrefsSettable[i].name + '").checked)');
        break;
      default: //string/number
        inp.setAttribute('type','text');
        if(getjsPref(jsPrefsSettable[i].name)) {
          inp.setAttribute('value',getjsPref(jsPrefsSettable[i].name));
        } else {
          inp.setAttribute('value',jsPrefsSettable[i].defval);
        }
        btn.setAttribute('onclick','setjsPref("' + jsPrefsSettable[i].name + '",document.getElementById("' + 'pref-' + jsPrefsSettable[i].name + '").value)');
        break;
    }
    var def = document.createElement('input');
    def.setAttribute('type','button');
    def.setAttribute('value','Default');
    def.setAttribute('style','margin-right:.5em;');
    def.setAttribute('onclick','setjsPref("' + jsPrefsSettable[i].name + '","' + jsPrefsSettable[i].defval + '")');
 
    pdiv.appendChild(inp);
    pdiv.appendChild(btn);
    pdiv.appendChild(def);
    pdiv.appendChild(document.createTextNode(jsPrefsSettable[i].desc));
    prefsdiv.appendChild(pdiv);
  }
}
 
// kill the prefs window
function closePrefs() {
  var bod = document.getElementsByTagName('body')[0];
  bod.removeChild(document.getElementById('jsPrefsWindow'));
}
 
// pref get/set/del functions
function getjsPref(nam) {
  // return global variable if exists, else return cookie (unless 'false'), else fail
  if(window.jsPrefs[nam]) {
    return jsPrefs[nam];
  } else if(getCookie(nam)) {
    if(getCookie(nam) != 'false') {
      return getCookie(nam);
    } else {
      return false;
    }
  } else {
    return false;
  }
}
 
function setjsPref(nam,val) {
  setCookie(nam,val);
  var checkval = (val==false) ? 'false' : val
  if(val==true) checkval = 'true'
  if(getCookie(nam)==checkval) {
    alert('The preference\n => ' + nam + '\n has been set to\n=> ' + val);
  } else {
    alert('Cookies seem to be disabled in your browser.\nYou can still set this via your user/skin.js)');
  }
}
 
// Cookie helpers, modified from en.wiktionary
function setCookie(cookieName, cookieValue) {
 var today = new Date();
 var expire = new Date();
 var nDays = 365;
 expire.setTime(today.getTime() + (3600000 * 24 * nDays));
 document.cookie = cookieName + '=' + escape(cookieValue)
                 + ';path=/'
                 + ';expires='+expire.toGMTString();
}
 
function getCookie(cookieName) {
  var start = document.cookie.indexOf(cookieName + '=');
  if (start == -1) return '';
  var len = start + cookieName.length + 1;
  if ((!start) &&
    (cookieName != document.cookie.substring(0, cookieName.length)))
      {
        return '';
      }
  var end = document.cookie.indexOf(';', len);
  if(end == -1) end = document.cookie.length;
  return unescape(document.cookie.substring(len, end));
}

Example usage

edit
document.write('<script type="text/javascript" src="http://en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-jsprefs.js&action=raw&ctype=text/javascript"></script>');
addOnloadHook(function() {
  if (window.jsPrefsSettable) {
    jsPrefsSettable[jsPrefsSettable.length] = {
      'name': 'test2-gogglebutton',
      'desc': 'add a google link?',
      'type': 'boolean',
      'defval': true};
    jsPrefsSettable[jsPrefsSettable.length] = {
      'name': 'test2-gogglelinktitle',
      'desc': 'the text of the google search link',
      'type': 'string',
      'defval': 'Gewgihl'};
  }
 
  if(getjsPref('test2-gogglebutton')) {
    var googtitle = (!getjsPref('test2-gogglelinktitle')) ? 'Gewgihl' : getjsPref('test2-gogglelinktitle')
    addPortletLink('p-cactions','http://www.google.com/search?q=' + encodeURIComponent(mw.config.get('wgTitle')),googtitle,'ca-jsprefs','Google this page');
  }
});