/*
   Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
   of Simon Willison (see comments by Simon below).

   Description:
   	
   	Uses css selectors to apply javascript behaviours to enable
   	unobtrusive javascript in html documents.
   	
   Usage:   
   
	var myrules = {
		'b.someclass' : function(element){
			element.onclick = function(){
				alert(this.innerHTML);
			}
		},
		'#someid u' : function(element){
			element.onmouseover = function(){
				this.innerHTML = "BLAH!";
			}
		}
	};
	
	Behaviour.register(myrules);
	
	// Call Behaviour.apply() to re-apply the rules (if you
	// update the dom, etc).

   License:
   
   	This file is entirely BSD licensed.
   	
   More information:
   	
   	http://ripcord.co.nz/behaviour/
   
*/   

var Behaviour = {
	list : new Array,
	
	register : function(sheet){
		Behaviour.list.push(sheet);
	},
	
	start : function(){
		Behaviour.addLoadEvent(function(){
			Behaviour.apply();
		});
	},
	
	apply : function(){
		for (h=0;sheet=Behaviour.list[h];h++){
			for (selector in sheet){
				list = document.getElementsBySelector(selector);
				
				if (!list){
					continue;
				}

				for (i=0;element=list[i];i++){
					sheet[selector](element);
				}
			}
		}
	},
	
	addLoadEvent : function(func){
		var oldonload = window.onload;
		
		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				oldonload();
				func();
			}
		}
	}
}

Behaviour.start();

/*
   The following code is Copyright (C) Simon Willison 2004.

   document.getElementsBySelector(selector)
   - returns an array of element objects from the current document
     matching the CSS selector. Selectors can contain element names, 
     class names and ids and can be nested. For example:
     
       elements = document.getElementsBySelect('div#main p a.external')
     
     Will return an array of all 'a' elements with 'external' in their 
     class attribute that are contained inside 'p' elements that are 
     contained inside the 'div' element which has id="main"

   New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
   See http://www.w3.org/TR/css3-selectors/#attribute-selectors

   Version 0.4 - Simon Willison, March 25th 2003
   -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
   -- Opera 7 fails 
*/

function getAllChildren(e) {
  // Returns all children of element. Workaround required for IE5/Windows. Ugh.
  return e.all ? e.all : e.getElementsByTagName('*');
}

document.getElementsBySelector = function(selector) {
  // Attempt to fail gracefully in lesser browsers
  if (!document.getElementsByTagName) {
    return new Array();
  }
  // Split selector in to tokens
  var tokens = selector.split(' ');
  var currentContext = new Array(document);
  for (var i = 0; i < tokens.length; i++) {
    token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
    if (token.indexOf('#') > -1) {
      // Token is an ID selector
      var bits = token.split('#');
      var tagName = bits[0];
      var id = bits[1];
      var element = document.getElementById(id);
      if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) {
        // tag with that ID not found, return false
        return new Array();
      }
      // Set currentContext to contain just this element
      currentContext = new Array(element);
      continue; // Skip to next token
    }
    if (token.indexOf('.') > -1) {
      // Token contains a class selector
      var bits = token.split('.');
      var tagName = bits[0];
      var className = bits[1];
      if (!tagName) {
        tagName = '*';
      }
      // Get elements matching tag, filter them for class selector
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      continue; // Skip to next token
    }
    // Code to deal with attribute selectors
    if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
      var tagName = RegExp.$1;
      var attrName = RegExp.$2;
      var attrOperator = RegExp.$3;
      var attrValue = RegExp.$4;
      if (!tagName) {
        tagName = '*';
      }
      // Grab all of the tagName elements within current context
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      var checkFunction; // This function will be used to filter the elements
      switch (attrOperator) {
        case '=': // Equality
          checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
          break;
        case '~': // Match one of space seperated words 
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
          break;
        case '|': // Match start with value followed by optional hyphen
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
          break;
        case '^': // Match starts with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
          break;
        case '$': // Match ends with value - fails with "Warning" in Opera 7
          checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
          break;
        case '*': // Match ends with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
          break;
        default :
          // Just test for existence of attribute
          checkFunction = function(e) { return e.getAttribute(attrName); };
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (checkFunction(found[k])) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
      continue; // Skip to next token
    }
    
    if (!currentContext[0]){
    	return;
    }
    
    // If we get here, token is JUST an element (not a class or ID selector)
    tagName = token;
    var found = new Array;
    var foundCount = 0;
    for (var h = 0; h < currentContext.length; h++) {
      var elements = currentContext[h].getElementsByTagName(tagName);
      for (var j = 0; j < elements.length; j++) {
        found[foundCount++] = elements[j];
      }
    }
    currentContext = found;
  }
  return currentContext;
}

/* That revolting regular expression explained 
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
  \---/  \---/\-------------/    \-------/
    |      |         |               |
    |      |         |           The value
    |      |    ~,|,^,$,* or =
    |   Attribute 
   Tag
*/

function hasClass(elt, classname) {
	if (elt) {
		var classes = elt.className.split(' ');
		for (var i = 0; i < classes.length; ++i)
			if (classes[i] == classname)
				return true;
	}
	return false;
}

function addClass(elt, classname) {
	if (elt) {
		if (!hasClass(elt, classname)) {
			var classes = elt.className.split(' ');
			classes[classes.length] = classname;
			elt.className = classes.join(' ');
		}
	}
}

function removeClass(elt, classname) {
	if (elt) {
		var classes = elt.className.split(' ');
		var newclasses = new Array();
		for (var i = 0; i < classes.length; ++i) {
			if (classes[i] != classname)
				newclasses[newclasses.length] = classes[i];
		}
		elt.className = newclasses.join(' ');
	}
}

function replaceClass(elt, oldClass, newClass) {
	removeClass(elt, oldClass);
	addClass(elt, newClass);
}

function hide(elId) {
	elt = document.getElementById(elId);
	if (elt) {
		elt.style.display = 'none';
	}
}

function toggleLayer(elt) {
	//if (elt.style.display && elt.style.display != 'none')
	if (elt.offsetHeight)
		slideClosed(elt, .1);
	else
		slideOpen(elt, .1);
}

var timer;

function slideOpen(elt, seconds) {
	if (timer) clearTimeout(timer);
	if (!seconds) seconds = .1;
	elt.style.display = 'block';
	elt.style.visibility = 'visible';
	var height = elt.offsetHeight;
	elt.style.height = '0px';
	elt.style.overflow = 'hidden';
	var steps = seconds * 1000 / 25;
	var step = Math.floor(height / steps);
	slideTo(elt, height, step, 25);
}

function slideClosed(elt, seconds) {
	if (timer) clearTimeout(timer);
	if (!seconds) seconds = .1;
	var height = elt.offsetHeight;
	elt.style.overflow = 'hidden';
	var steps = seconds * 1000 / 25;
	var step = Math.floor(height / steps);
	slideTo(elt, 0, -step, 25);
}

function slideTo(elt, height, step, interval) {
	var currheight = elt.offsetHeight + step;
	if (step < 0) {
		if (currheight < 0) currheight = 0;
		elt.style.height = currheight + 'px';
		if (currheight > 0)
			timer = setTimeout(function() { slideTo(elt, height, step, interval) }, interval);
		else {
			timer = null;
			elt.style.display = 'none';
			elt.style.height = null;
		}
	} else {
		if (currheight > height) currheight = height;
		elt.style.height = currheight + 'px';
		if (currheight < height)
			timer = setTimeout(function() { slideTo(elt, height, step, interval) }, interval);
		else
			timer = null;
	}
}

var symSearchCallback = null;

function findSymbol(callback, multiple) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function findRootSymbol(callback, multiple) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol&root=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function findCashSymbol(callback, multiple) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol&cash=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function selectSymbol(symbol, name) {
	if (symSearchCallback)
		symSearchCallback(symbol, name);
}

// Some standard symbol search callbacks
function setSymbolByLabelCallback(labelid) {
	return function (symbol, name) {
		label = document.getElementById(labelid);
		if (label) {
			element = document.getElementById(label.htmlFor);
			if (element) {
				element.value = symbol;
				label.innerHTML = name + ' - <a href="#" onclick="findSymbol(setSymbolByLabelCallback(\'' + labelid + '\'));">change</a>';
			}
		}
	}
}

function addSymbolCallback(containerid, name) {
	var container = document.getElementById(containerid);
	return function(symbol, desc) {
		var symbols = typeof(symbol) == 'object' ? symbol : Array(symbol);
		var descs = typeof(desc) == 'object' ? desc : Array(desc);
		for (var i = 0; i < symbols.length; ++i) {
			var id = 'symbolinput_' + container.childNodes.length;

			var symcont = document.createElement('li');
			symcont.id = id + '_cont';
			setSortableItemBehavior(symcont, null);

			var input = document.createElement('input');
			input.type = 'hidden';
			input.name = name;
			input.id = id;
			input.value = symbols[i];

			var label = document.createElement('label');
			label.htmlFor = id;
			label.id = id + '_label';
			label.innerHTML = descs[i] + ' - <a href="#" onclick="removeElementById(\'' + id + '_cont\'); return false;">remove</a>';

			symcont.appendChild(input);
			symcont.appendChild(label);
			symcont.appendChild(document.createElement('br'));

			container.appendChild(symcont);
		}
	}
}

function removeElementById(id) {
	var elt = document.getElementById(id);
	if (elt)
		elt.parentNode.removeChild(elt)
}

function sendHTTPRequest(url, callback, method) {
	if (!method) method = 'GET';
	var ua = navigator.userAgent.toLowerCase();
	var request;
	if (!window.ActiveXObject)
		request = new XMLHttpRequest();
	else if (ua.indexOf('msie 5') == -1)
		request = new ActiveXObject('Msxml2.XMLHTTP');
	else
		request = new ActiveXObject('Microsoft.XMLHTTP');
	request.onreadystatechange = function() {
			if (request.readyState != 4)
				return;
			if (request.status == 200)
				callback(request);
		};
	request.open(method, url, true);
	request.send(null);
}

function sendJSONRequest(url, callback, method) {
	sendHTTPRequest(url, function(request) {
			callback(eval(request.responseText));
		}, method);
}

function sendXMLRequest(url, callback, method) {
	sendHTTPRequest(url, function(request) {
			callback(request.responseXML);
		}, method);
}

function arrayToString(ar, indent) {
	var ser = '';
	var pad = (indent ? indent : '');
	for (key in ar) {
		if (!ar[key] || ar[key].constructor != Function) {
			ser += pad + ' ' + key + ': ';
			if (ar[key] == null) {
				ser += 'null\n';
			} else if (typeof(ar[key]) == 'object') {
				ser += 'array()\n';
				ser += arrayToString(ar[key], pad + '--');
			} else {
				ser += ar[key] + '\n';
			}
		} else {
			ser += pad + ' ' + key + ': function()\n';
		}
	}
	return ser;
}

var rules = {
	'#menubar .menu': function(elt) {
		elt.onmouseover = function() {
			var items;
			for (i = 0; i < elt.childNodes.length; ++i) {
				if (elt.childNodes[i].nodeType == '1' && elt.childNodes[i].className.indexOf('menuitems') > -1) {
					items = elt.childNodes[i];
					break;
				}
			}
			if (items)
				items.style.display = 'block';
		};
		elt.onmouseout = function() {
			var items;
			for (i = 0; i < elt.childNodes.length; ++i) {
				if (elt.childNodes[i].nodeType == '1' && elt.childNodes[i].className.indexOf('menuitems') > -1) {
					items = elt.childNodes[i];
					break;
				}
			}
			if (items)
				items.style.display = 'none';
		};
	},
	'#menubar .menuitem a': function(elt) {
		elt.onmouseover = function() {
			addClass(elt, 'highlight_color');
			};
		elt.onmouseout = function() {
			removeClass(elt, 'highlight_color');
			};
	},
	/*
	'#sidebar .sideheading_color': function(elt) {
		elt.onmouseover = function() {
			addClass(elt, 'sideheadinghighlight_color');
			};
		elt.onmouseout = function() {
			removeClass(elt, 'sideheadinghighlight_color');
			};
	},
	*/
	'#sidebar li a': function(elt) {
		elt.onmouseover = function() {
			addClass(elt, 'sidehighlight_color');
			};
		elt.onmouseout = function() {
			removeClass(elt, 'sidehighlight_color');
			};
	},
	'ul.collapsible li a.selectable': function(elt) {
		elt.onclick = function() {
				var list = null;
				for (var i = 0; i < elt.parentNode.childNodes.length; ++i) {
					if (elt.parentNode.childNodes[i].nodeName == 'UL') {
						list = elt.parentNode.childNodes[i];
						break;
					}
				}
				if (list) {
					if (list.style.display) list.style.display = '';
					else list.style.display = 'block';
					return false;
				}
			};
	}
};

Behaviour.register(rules);

function replaceLink(link, text) {
	var textNode = document.createTextNode(text);
	link.parentNode.replaceChild(textNode, link);
}


function popUp(page,PWidth,PHeight,id) {
eval("designerwiz"+id+"=window.open('"+page+"','designerwiz1','toolbar=0,scrollbars=0,location=0,status=0,menubars=0,resizable=0,width="+PWidth+",height="+PHeight+"')")

}

function isArray(obj) {
	if (obj.constructor.toString().indexOf("Array") == -1)
		return false;
	else
		return true;
}

function submitForm(f) {

	var page = window.location.pathname.split(/\//).pop();
	f.action = page;
	if (f.onsubmit) f.onsubmit();
	f.submit();
}

function clearDefaults(f, def) {
	for (field in def) {
		if (f.elements[field]) { 
			if (f.elements[field].length) {
				for (var i = 0; i < f.elements[field].length; ++i)
					if (f.elements[field][i].value == def[field])
						f.elements[field][i].value = null;
			} else if (f.elements[field].value == def[field]) {
				f.elements[field] = null;
			}
		}
	}
}

function highlightChildren(elt) {
	for (var i = 0; i < elt.childNodes.length; ++i)
		new Effect.Highlight(elt.childNodes[i]);
}

function setSortableItemBehavior(elt, editPage) {
	var objId = elt.id.substring(elt.id.indexOf('_') + 1);
	Event.observe(elt, 'mousedown', function() {
			elt.style.backgroundColor = '#FFFF99';
		});
	Event.observe(elt, 'mouseup', function() {
			elt.style.backgroundColor = '#EEEEEE';
		});
	if (editPage)
		Event.observe(elt, 'dblclick', function() {
				window.location = editPage + '?id=' + objId;
			});
}

var symSearchCallback = null;

function findRootSymbol(callback, multiple) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol&root=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function findCashSymbol(callback) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol&cash=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function findSymbol(callback, multiple) {
	symSearchCallback = callback;
	window.open('/data/lookup.php?func=selectSymbol' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1');
}

function selectSymbol(symbol, name) {
	if (symSearchCallback)
		symSearchCallback(symbol, name);
}

// Some standard symbol search callbacks
function setSymbolByLabelCallback(labelid) {
	return function (symbol, name) {
		label = document.getElementById(labelid);
		if (label) {
			element = document.getElementById(label.htmlFor);
			if (element) {
				element.value = symbol;
				label.innerHTML = name + ' - <a href="#" onclick="findSymbol(setSymbolByLabelCallback(\'' + labelid + '\'));">change</a>';
			}
		}
	}
}

function setSymbolPickerBehavior2(elt) {
	setSymbolPickerBehavior(elt, addSymbolCallback($('symbols_container'), 'symbols[]'));
}

function setSymbolPickerBehavior(elt, callback) {
	if (elt.value == '') {
		elt.style.color = '#999999';
		elt.value = 'Symbol';
	}
	Event.observe(elt, 'focus', function() {
			if(elt.value == 'Symbol') {
				elt.value = '';
				elt.style.color = '';
			}
		});
	Event.observe(elt, 'blur', function() {
			if(elt.value == '') {
				elt.value = 'Symbol';
				elt.style.color = '#CCCCCC';
			}
		});
	if (elt.form)
		Event.observe(elt.form, 'submit', function(e) { if(elt.value == 'Symbol') elt.value = ''; });
	Event.observe(document, 'unload', function(e) { if(elt.value == 'Symbol') elt.value = ''; });
	var icon = document.createElement('img');
	icon.src = '/images/search.png';
	icon.title = 'Find symbol';
	icon.className = 'inputExtension';
	var topOffset = /MSIE/.test(navigator.userAgent) ? 2 : 0;
	Element.setStyle(icon, {'position': 'relative', 'left': '-21px', 'top': topOffset+'px'});
	Element.insertAfter(icon, elt);
	
	if (callback)
		Event.observe(elt, 'keydown', function(e) { if (e.keyCode == Event.KEY_RETURN) { callback(this.value, this.title); elt.value = ''; elt.title = ''; elt.blur(); Event.stop(e); return false; } }.bindAsEventListener(elt));

	Event.observe(icon, 'click', function(e) { findSymbol(function(s, n) { elt.value=s; elt.title = n; elt.style.color = ''; }.bind(this), false) }.bindAsEventListener(this));
}

function addSymbolCallback(containerid, name) {
	var container = $(containerid);
	return function(symbol, desc) {
		if (!symbol.length || symbol == 'Symbol') return;
		var symbols = typeof(symbol) == 'object' ? symbol : Array(symbol);
		if (!desc) desc = symbol;
		var descs = typeof(desc) == 'object' ? desc : Array(desc);
		for (var i = 0; i < symbols.length; ++i) {
			var id = 'symbolinput_' + container.childNodes.length;

			var symcont = document.createElement('li');
			symcont.id = id + '_cont';
			setSortableItemBehavior(symcont, null);

			var input = document.createElement('input');
			input.type = 'hidden';
			input.name = name;
			input.id = id;
			input.value = symbols[i];

			var label = document.createElement('label');
			label.htmlFor = id;
			label.id = id + '_label';
			label.innerHTML = '<a href="#" onclick="$(\'' + id + '_cont\').remove(); return false;"><img src="/images/red_delete.gif" style="vertical-align:middle;" /></a> ' + descs[i] + ' (' + symbols[i] + ')';

			symcont.appendChild(input);
			symcont.appendChild(label);
			symcont.appendChild(document.createElement('br'));

			container.appendChild(symcont);
		}

		// Rebuild sortable <ul> - messy
		/* And apparently doesn't work.
		var lastChanged = null;
		Sortable.create(container, {
			onChange: function(item) { lastChanged = item; },
			onUpdate: highlightChildren
			});
		*/
	}
}

function removeElementById(id) {
	var elt = document.getElementById(id);
	if (elt)
		elt.parentNode.removeChild(elt)
}

function setSortable(elt, handle) {
	Sortable.create(elt, {
		handle: (handle ? handle : null),
		onUpdate: highlightChildren
		});
}
