/* 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('http://sites.agricharts.com/data/include/lookup.php?func=selectSymbol' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1'); } function findRootSymbol(callback, multiple) { symSearchCallback = callback; window.open('http://sites.agricharts.com/data/include/lookup.php?func=selectSymbol&root=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1'); } function findCashSymbol(callback, multiple) { symSearchCallback = callback; window.open('http://sites.agricharts.com/data/include/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 + ' - change'; } } } } 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] + ' - remove'; 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 path = window.location.pathname; var page = ""; if(path.substring(path.length - 1, path.length) != '/') { 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].value = 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('http://sites.agricharts.com/data/include/lookup.php?func=selectSymbol&root=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1'); } function findCashSymbol(callback) { symSearchCallback = callback; window.open('http://sites.agricharts.com/data/include/lookup.php?func=selectSymbol&cash=1' + (multiple ? '&multiple=1' : ''), 'lookup', 'width=500,height=600,scrollbars=1'); } function findSymbol(callback, multiple) { symSearchCallback = callback; window.open('http://sites.agricharts.com/data/include/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 + ' - change'; } } } } function setSymbolPickerBehavior2(elt) { setSymbolPickerBehavior(elt, addSymbolCallback($('symbols_container'), 'message_params__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 = 'http://sites.agricharts.com/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 = ' ' + descs[i] + ' (' + symbols[i] + ')'; symcont.appendChild(input); symcont.appendChild(label); symcont.appendChild(document.createElement('br')); container.appendChild(symcont); } // Rebuild sortable