// mehrere js-files wegen performance in eines kombiniert: topazhelp.js, messagearea.js, navigationtree.js, passwordcheck.js

TopazHelp = {
active: false,

_defaults: {
text: 'Sample Help Text',
title: '',
className: 'default', // or your own class
closeButton: true,    // or true
duration: 0.3,        // duration of the effect, if used
delay: 0.1,           // seconds before tooltip appears
effect: 'appear',     // false, 'appear' or 'blind'
fixed: true,          // follow the mouse if false
hideAfter: false,     // hides after seconds of inactivity,
// not hovering the element or the tooltip
hideOn: 'closeButton',
// { element: 'element|target|tip|closeButton|.close',
//   event: 'click|mouseover|mousemove' }
hook: {target: 'topRight', tip: 'topLeft'},
// { target: 'topLeft|topRight|bottomLeft|bottomRight|
//     topMiddle|bottomMiddle|leftMiddle|rightMiddle',
//   tip: 'topLeft|topRight|bottomLeft|bottomRight|
//           topMiddle|bottomMiddle|leftMiddle|rightMiddle' }
offset: {x: 10, y: 0},   // or your own, example: {x: 30, y: 200}
showOn: 'auto',       // or any event;
// auto means focus for inputs, selects and textareas, mouseover for all other
// auto also means that hideOn will be set to {element: 'closeButton', event: counterEvent}
// with counterEvent being blur for form controls, mouseleave for all other
target: false,        // make the tooltip appear on another element
viewport: true        // keep within viewport, false when fixed or hooked
},

init: function() {
return true;
},

_refocusAfterClosing: function(evt) {
if (evt.memo.tip && evt.memo.tip.element.focus && evt.memo.originalEvent) {
if (evt.memo.originalEvent.type != 'blur') {
evt.memo.tip.element.focus();
}
}
},

add: function(element, options, activate) {
var e = $(element);
e = Object.isElement(e) ? e : $$('input[name=' + element + ']')[0];

if (!e) return;

if (activate) {
this.active = true
}

def = Object.clone(this._defaults);
options = options ? Object.extend(def, options) : def;

var observeHide = false;
var evtName;
if (options.showOn && options.showOn != 'auto') {
evtName = options.showOn.replace(/^on/, '');
} else {
var eTag = e.nodeName.toLowerCase();

if (['input', 'select', 'textarea'].include(eTag)) {
options.showOn = 'focus';
options.hideOn = {element: 'closeButton', event: 'blur'};
if (!options.title) {
if (e.up().nodeName.toLowerCase() == 'label') {
// TODO get the innerHTML without e
} else {
var label = '';
try {
label = $$('#' + e.up('form').identify() + ' label[for=' + e.identify() + ']')[0];
} catch(e) {}
options.title = label ? label.innerHTML : '';
}
}
observeHide = true;
} else {
options.showOn = 'mouseover';
options.hideOn = {element: 'closeButton', event: 'mouseleave'};
}
}
options.target = options.target ? options.target : e;

var t = new Tip(e.identify(), options.text ? options.text : '<!-- no text -->', options);

if (observeHide && !this._ontiphide) {
Event.observe(window, 'prototip:hide', this._refocusAfterClosing.bindAsEventListener(this));
this._ontiphide = true;
}

if (!this._ontipshow && options.ontipshow) {
Event.observe(window, 'prototip:show', options.ontipshow.bindAsEventListener(this));
this._ontipshow = true;
}

if (!e._tipped) {
e.remove = e.remove.wrap(
function (proceed) {
Tips.remove(this);
return proceed();
});
e._tipped = true;
}
return e;
}

}

MessageArea = {
node: false,
count: 0,
messages: {
error: [],
warning: [],
notice: []
},

init: function() {
if (this.node = $('messages')) {
$('messageControlShow').observe('click', this.show.bind(MessageArea));
$('messageControlHide').observe('click', this.hide.bind(MessageArea));
if (this.updateControl()) {
this.refresh();
}
}
},

highlight: function() {
var n = MessageArea.node;
if (n) {
if (MessageArea.count) {
n.show();
new Effect.Highlight(n, {duration: 5});
new Effect.Pulsate(n, {duration: 3, from: 0.2, pulses: 3});
} else {
n.hide();
}
}
return false;
},

hide: function() {
MessageArea.toggleControl() && $('additionalMessages').hide();
return false;
},

show: function() {
MessageArea.toggleControl() && $('additionalMessages').show();
return false
},

updateControl: function() {
var c = 0;
if (MessageArea.node) {
c = MessageArea.count;
if (c > 1) {
$('messageControlHide').hide();
$('messageControlShow').show();
$('messageControl').show();
} else {
$('messageControl').hide();
}
}
return c > 0;
},

toggleControl: function() {
if (MessageArea.node) {
$('messageControlHide').toggle();
$('messageControlShow').toggle();
return true;
}
return false;
},

clear: function() {
MessageArea.messages = {
error: [],
warning: [],
notice: []
};
MessageArea.count = 0;
MessageArea.node.hide();
},

/* Repaints the complete message area to reflect the current message queue */
refresh: function() {
if (MessageArea.node) {
/* MessageArea.updateControl(); */
var nodes = [$('firstMessage'), $('additionalMessages')];
nodes.each(function(n) {n.update(); n.hide()});

var template = new Template('<div class="#{cls}">#{txt}</div>');
var additional = false;
['error', 'warning', 'notice'].each(function(lvl) {
MessageArea.messages[lvl].each(function(msg) {
/*
if (additional) {
nodes[1].insert(template.evaluate({cls: lvl, txt: msg}));
} else {
additional = true;
nodes[0].update(template.evaluate({cls: lvl, txt: msg}));
nodes[0].show();
MessageArea.node.show();
}
*/
nodes[0].insert(template.evaluate({cls: lvl, txt: msg}));
nodes[0].show();
MessageArea.node.show();

});
});
MessageArea.highlight();
}
},

error: function(txt, clearAndShow) {
MessageArea.message(txt, 'error', clearAndShow);
},

warning: function(txt, clearAndShow) {
MessageArea.message(txt, 'warning', clearAndShow);
},

notice: function(txt, clearAndShow) {
MessageArea.message(txt, 'notice', clearAndShow);
},

message: function(txt, lvl, clearAndShow) {
if (clearAndShow) {
MessageArea.clear();
}
if (txt) {
MessageArea.count++;
MessageArea.messages[lvl].unshift(txt);
}
if (clearAndShow) {
MessageArea.refresh();
}
}

};

TopazApp.onload(MessageArea);

var NavigationTree = {
topWidth: 175,
offset: 10,
subWidth: 150,
active: null,
imgH: 'images/icons/navi_arrow_grey_right.jpg',
imgS: 'images/icons/navi_arrow_grey_down.jpg',

init: function(cls) {
if (Prototype.Browser.IE == 6) {
return; // not supported in ie6
}

var cls = Object.isString(cls) ? cls : '.sitemap-block.tree-block';
var navBlock = $('sidebar').down(cls);
navBlock.setStyle({height: navBlock.getDimensions().height});
navBlock.up().addClassName('advanced');

var n = navBlock.down('ul').setStyle({position: 'relative'});

// alle untergeordneten ebenen ausblenden
n.select('ul').invoke('hide');

var w = this.topWidth - this.offset + this.subWidth;

// mouseover auf der ersten ebene
n.childElements('li').each(function(li) {
if (li.down('ul')) {
li.setStyle({position: 'relative'}).addClassName('closed');
li.observe('mouseover', function(evt) {
var nt = NavigationTree;
li.addClassName('open').removeClassName('closed').down('ul').show();
if (nt.active && nt.active != li) {
nt.active.fire('tpz:mouseleave');
}
nt.active = li;
});
li.observe('tpz:mouseleave', function(evt) {
evt.element().addClassName('closed').removeClassName('open').down('ul').hide();
NavigationTree.active = null;
});
NavigationTree.addarrow(li);
}

});

n.observe('mouseout', function() {
var nt = NavigationTree;
if (nt.active) {
nt.active.fire('tpz:mouseleave');
}
});
},

adjustHeights: function() {
return;
// die höhe des content anpassen
var ch = $('container').getDimensions().height;
var sh = $('sidebar').getDimensions().height;
ch = ch < 400 ? 400 : ch;
if (sh < ch) {
sh = ch;
$('sidebar').setStyle({minHeight: sh + 'px'});
}
if (sh > ch) {
$('container').setStyle({minHeight: sh + 'px'});
}
},

addarrow: function(n) {
if (ul = n.down('ul')) {
var imgH = TopazApp.applicationuri + this.imgH;
var imgS = TopazApp.applicationuri + this.imgS;
ul.childElements().each(function(li) {
if (li.down('ul')) {
li.insert({top: '<span><img src="' + imgH + '" alt="" /></span>'});
var a = li.down('span').setStyle({cursor: 'pointer'});
a.observe('click', function(evt) {
var e = evt.element().up('li');
var img = e.down('span img');
if (img.src.endsWith(imgH)) {
var ul = e.addClassName('open').down('ul');
Effect.BlindDown(ul, {duration: 0.1});
img.src = imgS;
} else {
var ul = e.removeClassName('open').down('ul');
Effect.BlindUp(ul, {duration: 0.1});
img.src = imgH;
}
});
NavigationTree.addarrow(li);
}
});
}
}
};

passwordcheck = {
inputs: [],
output: null,
language: 'de',
initialised: false,
hackspersecond: 500,
lifetime: 365,
textNode: null,
barNode: null,
hidden: true,

init: function(options) {
var pwd = passwordcheck;
if (!options || !options.inputs) {
return false;
}
options.inputs.each(function (n, i) {n = $(n); if (n) {pwd.inputs[i] = n}});
if (options.inputs.length != 2) {
return false;
}

options.output = $(options.output);
if (!options.output) {
return false;
}
pwd.output = options.output;

// optional options
if (options.language && pwd.messages[options.language]) {
pwd.language = options.language;
}

if (options.hackspersecond) {
pwd.hackspersecond = options.hackspersecond;
}

if (options.lifetime) {
pwd.lifetime = options.lifetime;
}

try {
// create the box for the strenght meter
var outer = Builder.node('div', {style: 'display: none'});
var txt = Builder.node('div', {style: 'font-size: 10px; color: rgb(255,0,0)'});
var bar = Builder.node('div', {style: 'margin: -1px 0 0 1px; height: 2px; background-color: rgb(255,0,0); width: 0px'});

pwd.output.appendChild(outer);
outer.appendChild(txt);
outer.appendChild(bar);

pwd.barNode = bar;
pwd.textNode = txt;

pwd.inputs.each(function(n) {
Event.observe(n, 'keyup', pwd.compare);
Event.observe(n, 'blur', pwd.compare);
});
Event.observe(pwd.inputs[0], 'keyup', pwd.measure);

pwd.initialised = true;
} catch(e) {
// better safe than sorry
pwd.output.remove();
pwd.initialised = false;
}

},

compare: function(evt) {
var pwd = passwordcheck;
if (pwd.initialised) {
if (pwd.hidden) {
pwd.output.down('div').show();
pwd.hidden = false;
}
if (pwd.inputs[0].value == pwd.inputs[1].value) {
pwd.inputs[1].setStyle({borderColor: 'green'});
} else {
pwd.inputs[1].setStyle({borderColor: 'red'});
}
}
;
},

measure: function() {
var pwd = passwordcheck;
if (pwd.initialised) {
var score = pwd.getscore(pwd.inputs[0].value);
var w = score > 1 ? score : 1;
var r = Math.round(250 * (100 - score) / 100);
var g = Math.round(200 * score / 100);
var c = 'rgb(' + r + ',' + g + ',0)';
pwd.textNode.innerHTML = pwd.getmessage(score);
pwd.textNode.setStyle({color: c});
pwd.barNode.setStyle({backgroundColor: c, width: w + 'px'});
}
},

getscore: function(str) {
var base = Math.min(str.length, 15); // too long password will be written down anyhow...
var score = base > 5 ? 7.5 : base;
var combinations = 0;

if (/[0-9]/.test(str)) {
score += base * 0.5;
combinations += 10;
}

if (/[A-Z]/.test(str)) {
score += base * 1;
combinations += 26;
}

if (/[a-z]/.test(str)) {
score += base * 0.5;
combinations += 26;
}

if (/[^0-9A-Za-z]/.test(str)) {
score += base * 1.5;
combinations += 38; // = 100 - sum(previous combinations)
}

// score is now between 0 and 60;
// calculate how long this might take to brute force
// and make a percentage of lifetime the multiplier
var perday = 1 / (24 * 60 * 60);
var days = (Math.pow(combinations, base) / passwordcheck.hackspersecond) * perday;
var pct = days / passwordcheck.lifetime;
if (days >= passwordcheck.lifetime) {
pct = Math.min(1, pct);
}
score = 2 * score * pct;

score = Math.ceil(score > 100 ? 100 : score);
return score;
},

getmessage: function(score) {
var msgs = passwordcheck.messages[passwordcheck.language];
if (score < 20) {
return msgs.vw;
} else if (score < 40) {
return msgs.w;
} else if (score < 60) {
return msgs.ok;
} else if (score < 80) {
return msgs.s;
} else {
return msgs.vs;
}
return '';
},

getlabel: function() {
var m = passwordcheck.messages[passwordcheck.language];
return m.label;
},

messages: {
en: {label: 'Password Strength', vw: 'very weak', w: 'weak', ok: 'ok', s: 'strong', vs: 'unparalleled'},
de: {label: 'Passwortsicherheit', vw: 'sehr unsicher', w: 'unsicher', ok: 'in Ordnung', s: 'sicher', vs: 'sehr sicher'}
}

}
