menubook = {
settings: {
enabled: true,
menulimit: 32,
load: function () {
for (var name in menubook.settings) {
if (typeof menubook.settings[name] != 'function') {
var val = menubook.utils.readCookie('menubook_' + name);
if (val) {
switch (typeof menubook.settings[name]) {
case 'boolean':
menubook.settings[name] = (val == 'true');
break;
case 'number':
menubook.settings[name] = parseInt(val);
break;
default:
menubook.settings[name] = val.toString();
}
}
}
}
},
save: function () {
var cend = "; expires=Tue, 31-Dec-2030 23:59:59 GMT; path=/";
for (var name in menubook.settings) {
if (typeof menubook.settings[name] != 'function') {
document.cookie = 'menubook_' + name + '=' + menubook.settings[name].toString() + cend;
}
}
}
},
styles: {
stylesheet: null,
setMenubarRules: function (visible) {
var rules = [
/*ul {
line-height: 1.5em;
list-style-type: square;
margin: .3em 0 0 1.5em;
padding: 0;
list-style-image: url(bullet.gif);
}
ol {
line-height: 1.5em;
margin: .3em 0 0 3.2em;
padding: 0;
list-style-image: none;
}
li {
margin-bottom: .1em;
}
*/
'body {margin-top:2.5em;background-position:0 2.5em;}',
'#p-cactions, #p-personal, #p-logo {margin-top:2em;}',
'#menubar {position:fixed;top:0px;left:0px;width:100%;padding:0 1em;margin:0;line-height:2em;max-height:2em;font-size:1.2em;background-color:#f0f0f0;border-bottom:1px solid darkblue;z-index:10;white-space:nowrap;}',
'#menubar ul {float:left;position:relative;display:inline;line-height:2em;list-style:none;margin:0;padding:0;}',
'#menubar ul ul {position:absolute;display:block;line-height:1.8em;border:1px solid darkblue;background-color:#f0f0f0;overflow:auto;min-width:15em;min-height:1em;padding:0;margin:0;}',
'#menubar li {position:relative;display:inline;list-style:none;margin:0;padding:0;}',
'#menubar a.menuHeader {display:block;padding:0 .5em;margin:0;text-transform:none;text-decoration:none;font-weight:bold;color:darkblue;}',
'#menubar a.menuItem {display:block;padding:0 1.5em;margin:0;text-transform:none;text-decoration:none;line-height:1.8em;height:1.8em;color:darkblue}',
'#menubar a.menuHeader:hover, #menubar a.menuItem:hover, #menubar a.highlight {color:#f0f0f0;background-color:darkblue}',
'#menubar li.break {border-bottom:1px solid darkblue;}',
'#menubar li span.arrow {position:absolute;right:0.3em;}'];
for (i=0; i<rules.length; i++) {
menubook.styles.setRule(rules[i], visible);
}
},
setRule: function (rule, visible) {
if (!menubook.styles.stylesheet) {
var nod = document.createElement('style');
nod.type = 'text/css';
nod.rel = 'stylesheet';
nod.media = 'screen';
nod.title = 'menubar';
document.getElementsByTagName('head')[0].appendChild(nod);
for (var i=0; i<document.styleSheets.length; i++) {
if (document.styleSheets[i].title == 'menubar') {
menubook.styles.stylesheet = document.styleSheets[i];
break;
}
}
}
var found=false;
for (var i=0; i<menubook.styles.stylesheet.cssRules.length; i++) {
var r = menubook.styles.stylesheet.cssRules[i];
if (r.selectorText==rule.substring(0,rule.indexOf('{'))) {
found=true;
break;
}
}
if (!found && visible)
menubook.styles.stylesheet.insertRule(rule, i);
else if (found && !visible)
menubook.styles.stylesheet.deleteRule(i);
},
addRule: function (rule) {menubook.styles.setRule(rule, true)}
},
utils: {
readCookie: function(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') { c = c.substring(1,c.length); }
if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); }
}
return null;
},
getSingleNode: function (context, expression) {
var result = document.evaluate(expression, context, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return result.singleNodeValue;
},
isAncestor: function (node, ofNode) {
while(node.parentNode) {
if (node.parentNode == ofNode) {
return true;
}
node = node.parentNode;
}
return false;
}
},
Menubar: new function () {
this.divMenubar = null;
this.element = null;
this.menus = [];
this.topzindex = 10;
this.show = function () {
menubook.styles.setMenubarRules(true);
if (!this.divMenubar) {
this.divMenubar = document.createElement('div');
this.divMenubar.id = 'menubar';
this.divMenubar.object = this;
this.divMenubar.addEventListener('mousedown', function (event) {
if (this.style.zIndex < this.object.topzindex) {
this.style.zIndex += this.object.topzindex;
}
}, false);
document.body.appendChild(this.divMenubar);
this.element = document.createElement('ul');
this.divMenubar.appendChild(this.element);
} else {
this.divMenubar.style.display='';
}
}
this.hide = function () {
menubook.styles.setMenubarRules(false);
if (this.divMenubar) this.divMenubar.style.display='none';
}
this.addMenu = function (id, title, populateCallback, populateArgs) {
var mi = new menubook.MenuItem(this, true);
mi.anchor.textContent = title;
var menu = mi.addChildMenu(populateCallback, populateArgs);
this.menus[id] = mi;
return mi;
}
},
MenuItem: function (parentMenu, header) { //extends IMenuItem
this.parentMenu = parentMenu;
this.element = document.createElement('li');
this.element.object = this;
this.anchor = document.createElement('a');
this.anchor.className = header ? 'menuHeader' : 'menuItem';
this.anchor.href = '#';
//this.anchor.onclick = function () {return false};
this.anchor.object = this;
this.element.appendChild(this.anchor);
this.childMenu = null;
this.parentMenu.element.appendChild(this.element);
this.insertBreak = function () {
this.element.className+=' break';
}
this.addChildMenu = function (populateCallback, populateArgs) {
this.childMenu = new menubook.Menu(this, populateCallback, populateArgs)
return this.childMenu;
}
if (header) {
this.anchor.addEventListener('click', function (event) {
if (this.object && this.object.childMenu) {
if (!this.object.childMenu.visible) {
this.object.childMenu.show();
this.object.anchor.className += ' highlight';
} else {
this.object.childMenu.hide();
this.object.anchor.className = this.object.anchor.className.replace('highlight', '');
}
}
}, false);
}
},
Menu: function (parentItem, populateCallback, populateArgs) {
this.parentItem = parentItem;
this.element = document.createElement('ul');
this.element.style.display = 'none';
this.element.object = this;
this.parentItem.element.appendChild(this.element);
this.menuItems = [];
this.populateCallback = populateCallback;
this.populateArgs = populateArgs;
this.__defineGetter__("visible", function() { return this.element.style.display!='none'; });
this.__defineGetter__("name", function () { return this.parentItem.anchor.textContent; });
this.show = function () {
this.element.style.display='';
if (populateCallback) populateCallback(this, populateArgs);
}
this.hide = function () {
this.element.style.display='none';
}
this.addMenuItem = function () {
var mi = new menubook.MenuItem(this);
this.menuItems.push(mi);
return mi;
}
this.clear = function () {
while (this.menuItems.length) {
var mi = this.menuItems.pop();
mi.element.parentNode.removeChild(mi);
}
}
},
init: function () {
menubook.settings.load();
if (menubook.settings.enabled) {
for (var i=0; i<menubook.initHooks.length; i++) menubook.initHooks[i]();
menubook.init.done = true;
} else {
for (var i=0; i<menubook.hideHooks.length; i++) menubook.hideHooks[i]();
}
},
initHooks: [
function () {menubook.styles.setMenubarRules();}
],
addInitHook: function(f) {if (menubook.init.done) f(); else menubook.initHooks.push(f);},
load: function (reload) {
if (reload) menubook.init();
if (menubook.settings.enabled) {
for (var i=0; i<menubook.loadHooks.length; i++) menubook.loadHooks[i]();
menubook.load.done = true;
}
},
loadHooks: [
function () {menubook.Menubar.show();}
],
addLoadHook: function(f) {if (menubook.load.done) f(); else menubook.loadHooks.push(f);},
hideHooks: [
function () {menubook.Menubar.hide();},
function () {
addOnloadHook(function () {
mw.util.addPortletLink('p-personal', '#', 'Enable Menubook', 'enableMenubook', null, null, document.getElementById("pt-logout"));
with (document.getElementById('enableMenubook')) {
style.fontWeight = 'bold';
onclick = function () {
menubook.settings.enabled = true;
menubook.settings.save();
this.parentNode.removeChild(this);
menubook.load();
}
}
});
}
],
addHideHook: function(f) {menubook.hideHooks.push(f);}
}
menubook.init();
$(menubook.load);
//CLOCK
menubook.addLoadHook(function loadClock() {
menubook.settings.clock=false;
//menubook.settings.load();
if (menubook.settings.clock) {
menubook.styles.addRule('#menubar_clock {position:fixed;right:0em;top:0em;padding:0 .5em;display:block;font-size:larger;font-weight:bolder}');
var el = document.createElement('a');
el.id='menubar_clock';
el.href = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?title=' + encodeURIComponent(mw.config.get('wgPageName')) + '&action=purge';
menubook.Menubar.element.appendChild(el);
function updateClock() {
var now = new Date();
var hh = now.getUTCHours();
var mm = now.getUTCMinutes();
var ss = now.getUTCSeconds();
var time = ( hh < 10 ? '0' + hh : hh ) + ':' + ( mm < 10 ? '0' + mm : mm ) + ':' + ( ss < 10 ? '0' + ss : ss );
el.textContent = time;
window.setTimeout(updateClock, 1000);
}
updateClock();
}
});
//CONFIG MENU
menubook.addLoadHook(function loadConfig() {
menubook.Menubar.addMenu('config', '\u25BC', function (menu) {
menu.clear();
function addCheckbox (name, caption, indentlevel) {
with (menu.addMenuItem()) {
var label = document.createElement('label');
var input = document.createElement('input');
input.type = 'checkbox';
input.value = name;
input.checked = menubook.settings[name];
input.style.marginLeft = (indentlevel ? (indentlevel * 0.5) : 0) + 'em';
label.appendChild(input);
label.appendChild(document.createTextNode(caption));
anchor.appendChild(label);
input.addEventListener('click', function (event) {
menubook.settings[event.target.value] = event.target.checked ? true : false;
menubook.settings.save();
menubook.load(true);
}, false);
}
return element;
}
addCheckbox('enabled', 'Enable Menubook');
addCheckbox('clock', 'Show clock');
for (var name in menubook.Menubar.menus) {
if (name != menu.name) addCheckbox(name, menubook.Menubar.menus[name].anchor.textContent);
}
});
});
// CLICK HACK
HTMLElement.prototype.click = function() {
var evt = this.ownerDocument.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
this.dispatchEvent(evt);
}
// OUTERHTML HACK - for debugging purposes only
if(!document.documentElement.outerHTML){
Node.prototype.getAttributes = function(){
var attStr = "";
if(this && this.attributes.length > 0){
for(a = 0; a < this.attributes.length; a ++){
attStr += " " + this.attributes.item(a).nodeName + "=\"";
attStr += this.attributes.item(a).nodeValue + "\"";
}
}
return attStr;
}
Node.prototype.getInsideNodes = function(){
if(this){
var cNodesStr = "", i = 0;
var iEmpty = /^(img|embed|input|br|hr)$/i;
var cNodes = this.childNodes;
for(i = 0; i < cNodes.length; i ++){
switch(cNodes.item(i).nodeType){
case 1 :
cNodesStr += "<" + cNodes.item(i).nodeName.toLowerCase();
if(cNodes.item(i).attributes.length > 0){
cNodesStr += cNodes.item(i).getAttributes();
}
cNodesStr += (cNodes.item(i).nodeName.match(iEmpty))? "" : ">";
if(cNodes.item(i).childNodes.length > 0){
cNodesStr += cNodes.item(i).getInsideNodes();
}
if(cNodes.item(i).nodeName.match(iEmpty)){
cNodesStr += " />";
} else {
cNodesStr += "</" + cNodes.item(i).nodeName.toLowerCase() + ">";
}
break;
case 3 :
cNodesStr += cNodes.item(i).nodeValue;
break;
case 8 :
cNodesStr += "<!--" + cNodes.item(i).nodeValue + "-->";
break;
}
}
return cNodesStr;
}
}
HTMLElement.prototype.outerHTML getter = function(){
var strOuter = "";
var iEmpty = /^(img|embed|input|br|hr)$/i;
switch(this.nodeType){
case 1 :
strOuter += "<" + this.nodeName.toLowerCase();
strOuter += this.getAttributes();
if(this.nodeName.match(iEmpty)){
strOuter += " />";
} else {
strOuter += ">" + this.getInsideNodes();
strOuter += "</" + this.nodeName.toLowerCase() + ">";
}
break;
case 3 :
strOuter += this.nodeValue;
break;
case 8 :
cNodesStr += "<!--" + this.nodeValue + "-->";
break;
}
return strOuter;
}
HTMLElement.prototype.outerHTML setter = function(str){
var iRange = document.createRange();
iRange.setStartBefore(this);
var strFragment = iRange.createContextualFragment(str);
var sRangeNode = iRange.startContainer;
iRange.insertNode(strFragment);
sRangeNode.removeChild(this);
}
}