<?xml version="1.0" encoding="ISO-8859-1" ?>
<Module>
<ModulePrefs title="ChemAlliance Glossary" title_url="http://www.chemalliance.org/" height="300" scrolling="true" scaling="true" render_inline="optional" description="This is a working code draft of Module 4 for the ChemAlliance module set." author="Nick Myers" author_email="wsu423@gmail.com" />
<Content type="html">
<![CDATA[ 
    <!-- load the NXSL library -->        
    <script src="http://www.google.com/js/nxsl.1.js" type="text/javascript"></script>
    
    <style type="text/css">
        .mainText
        {
             font-size:13px; font:Arial, Helvetica, sans-serif
        }
        .aboutBox 
        {
            BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; BACKGROUND: white; PADDING-BOTTOM: 4px; BORDER-LEFT: 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: 1px solid
        }            
    </style>
    
    
    
    <STYLE type=text/css>.suggestion_list {
        BORDER-RIGHT: 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: 1px solid; PADDING-LEFT: 4px; BACKGROUND: white; PADDING-BOTTOM: 4px; BORDER-LEFT: 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: 1px solid
    }
    .suggestion_list UL {
        PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
    }
    .suggestion_list A {
        COLOR: navy; TEXT-DECORATION: none
    }
    .suggestion_list .selected {
        BACKGROUND: navy; COLOR: white
    }
    .suggestion_list .selected A {
        COLOR: white
    }
    #autosuggest {
        DISPLAY: none
    }
    </STYLE>   


   
    <script>
    
        function AutoSuggest(elem, suggestions)
        {
        
            //The 'me' variable allow you to access the AutoSuggest object
            //from the elem's event handlers defined below.
            var me = this;
        
            //A reference to the element we're binding the list to.
            this.elem = elem;
        
            this.suggestions = suggestions;
        
            //Arrow to store a subset of eligible suggestions that match the user's input
            this.eligible = new Array();
        
            //The text input by the user.
            this.inputText = null;
        
            //A pointer to the index of the highlighted eligible item. -1 means nothing highlighted.
            this.highlighted = -1;
        
            //A div to use to create the dropdown.
            this.div = _gel("autosuggest");
        
        
            //Do you want to remember what keycode means what? Me neither.
            var TAB = 9;
            var ESC = 27;
            var KEYUP = 38;
            var KEYDN = 40;
            var SHIFT = 16;
            var ENTR = 13;
        
            //The browsers' own autocomplete feature can be problematic, since it will 
            //be making suggestions from the users' past input.
            //Setting this attribute should turn it off.
            elem.setAttribute("autocomplete","off");
        
            //We need to be able to reference the elem by id. If it doesn't have an id, set one.
            if(!elem.id)
            {
                var id = "autosuggest" + idCounter;
                idCounter++;
        
                elem.id = id;
            }
        
        
            /********************************************************
            onkeydown event handler for the input elem.
            Tab key = use the highlighted suggestion, if there is one.
            Esc key = get rid of the autosuggest dropdown
            Up/down arrows = Move the highlight up and down in the suggestions.
            ********************************************************/
            elem.onkeydown = function(ev)
            {
                var key = me.getKeyCode(ev);
        
                switch(key)
                {
                    case TAB:
                    me.useSuggestion();
                    break;
        
                    case ESC:
                    me.hideDiv();
                    break;
        
                    case KEYUP:
                    if (me.highlighted > 0)
                    {
                        me.highlighted--;
                    }
                    me.changeHighlight(key);
                    break;
        
                    case KEYDN:
                    if (me.highlighted < (me.eligible.length - 1))
                    {
                        me.highlighted++;
                    }
                    me.changeHighlight(key);
                    break;
                    
                    case ENTR:
                    me.hideDiv();
                    break;
                }
            };
        
            /********************************************************
            onkeyup handler for the elem
            If the text is of sufficient length, and has been changed, 
            then display a list of eligible suggestions.
            ********************************************************/
            elem.onkeyup = function(ev) 
            {
                var key = me.getKeyCode(ev);
                switch(key)
                {
                //The control keys were already handled by onkeydown, so do nothing.
                case TAB:
                case ESC:
                case KEYUP:
                case KEYDN:
                case SHIFT:
                case ENTR:
                    return;
                default:
        
                    if (this.value != me.inputText && this.value.length > 0)
                    {
                        me.inputText = this.value;
                        me.getEligible();
                        me.createDiv();
                        me.positionDiv();
                        me.showDiv();
                    }
                    else
                    {
                        me.hideDiv();
                    }
                }
            };
        
        
            /********************************************************
            Insert the highlighted suggestion into the input box, and 
            remove the suggestion dropdown.
            ********************************************************/
            this.useSuggestion = function()
            {
                if (this.highlighted > -1)
                {
                    this.elem.value = this.eligible[this.highlighted];
                    this.hideDiv();
                    //It's impossible to cancel the Tab key's default behavior. 
                    //So this undoes it by moving the focus back to our field right after
                    //the event completes.
                    setTimeout("document.getElementById('" + this.elem.id + "').focus()",0);
                }
            };
        
            /********************************************************
            Display the dropdown. Pretty straightforward.
            ********************************************************/
            this.showDiv = function()
            {
                this.div.style.display = 'block';
            };
        
            /********************************************************
            Hide the dropdown and clear any highlight.
            ********************************************************/
            this.hideDiv = function()
            {
                this.div.style.display = 'none';
                this.highlighted = -1;
            };
        
            /********************************************************
            Modify the HTML in the dropdown to move the highlight.
            ********************************************************/
            this.changeHighlight = function()
            {
                var lis = this.div.getElementsByTagName('LI');
                for (i in lis)
                {
                    var li = lis[i];
        
                    if (this.highlighted == i)
                    {
                        li.className = "selected";
                        this.elem.value = this.eligible[this.highlighted];
                    }
                    else
                    {
                        li.className = "";
                    }
                }
            };
        
            /********************************************************
            Position the dropdown div below the input text field.
            ********************************************************/
            this.positionDiv = function()
            {
                var el = this.elem;
                var x = 0;
                var y = el.offsetHeight;
            
                //Walk up the DOM and add up all of the offset positions.
                while (el.offsetParent && el.tagName.toUpperCase() != 'BODY')
                {
                    x += el.offsetLeft;
                    y += el.offsetTop;
                    el = el.offsetParent;
                }
        
                x += el.offsetLeft;
                y += el.offsetTop;
        
                this.div.style.left = x + 'px';
                this.div.style.top = y + 'px';
            };
        
            /********************************************************
            Build the HTML for the dropdown div
            ********************************************************/
            this.createDiv = function()
            {
                var ul = document.createElement('ul');
            
                //Create an array of LI's for the words.
                for (i in this.eligible)
                {
                    var word = this.eligible[i];
            
                    var li = document.createElement('li');
                    var a = document.createElement('a');
                    a.href="javascript:false";
                    a.innerHTML = word;
                    li.appendChild(a);
            
                    if (me.highlighted == i)
                    {
                        li.className = "selected";
                    }
            
                    ul.appendChild(li);
                }
            
                this.div.replaceChild(ul,this.div.childNodes[0]);
            
        
                /********************************************************
                mouseover handler for the dropdown ul
                move the highlighted suggestion with the mouse
                ********************************************************/
                ul.onmouseover = function(ev)
                {
                    //Walk up from target until you find the LI.
                    var target = me.getEventSource(ev);
                    while (target.parentNode && target.tagName.toUpperCase() != 'LI')
                    {
                        target = target.parentNode;
                    }
                
                    var lis = me.div.getElementsByTagName('LI');
                    
            
                    for (i in lis)
                    {
                        var li = lis[i];
                        if(li == target)
                        {
                            me.highlighted = i;
                            break;
                        }
                    }
                    me.changeHighlight();
                };
        
                /********************************************************
                click handler for the dropdown ul
                insert the clicked suggestion into the input
                ********************************************************/
                ul.onclick = function(ev)
                {
                    me.useSuggestion();
                    me.hideDiv();
                    me.cancelEvent(ev);
                    return false;
                };
            
                this.div.className="suggestion_list";
                this.div.style.position = 'absolute';
        
            };
        
            /********************************************************
            determine which of the suggestions matches the input
            ********************************************************/
            this.getEligible = function()
            {
                this.eligible = new Array();
                for (i in this.suggestions) 
                {
                    var suggestion = this.suggestions[i];
                    if(suggestion.toLowerCase().indexOf(this.inputText.toLowerCase()) == "0")
                    {
                        this.eligible[this.eligible.length]=suggestion;
                    }
                }
            };
        
            /********************************************************
            Helper function to determine the keycode pressed in a 
            browser-independent manner.
            ********************************************************/
            this.getKeyCode = function(ev)
            {
                if(ev)          //Moz
                {
                    return ev.keyCode;
                }
                if(window.event)    //IE
                {
                    return window.event.keyCode;
                }
            };
        
            /********************************************************
            Helper function to determine the event source element in a 
            browser-independent manner.
            ********************************************************/
            this.getEventSource = function(ev)
            {
                if(ev)          //Moz
                {
                    return ev.target;
                }
            
                if(window.event)    //IE
                {
                    return window.event.srcElement;
                }
            };
        
            /********************************************************
            Helper function to cancel an event in a 
            browser-independent manner.
            (Returning false helps too).
            ********************************************************/
            this.cancelEvent = function(ev)
            {
                if(ev)          //Moz
                {
                    ev.preventDefault();
                    ev.stopPropagation();
                }
                if(window.event)    //IE
                {
                    window.event.returnValue = false;
                }
            }
        }
        
        //counter to help create unique ID's
var idCounter = 0;
    
 
    function searchAcronym(searchString) 
    {
        
    _gel('content___MODULE_ID__').innerHTML = '<em><br>Loading...</em>';
    
    var c = searchString.charAt(0);
    while(c == ' ')
    {
        searchString = searchString.substr(1);
        c = searchString.charAt(0);
    }
    
    _gel('searchInput').value = searchString; 
    
    
    var search_url = 'http://www.chemalliance.org/webservices/glossary.asp?searchterm=' + searchString + '&page=0';
    var template_url = 'http://www.eecs.wsu.edu/~cs423/423spring06/PNNL-S/modules_beta/glossary39.xsl';
        
    _IG_FetchContent(search_url, 
        function (response) 
        {
            _IG_FetchContent(template_url, 
                function (template)
                {                       
                    var t = xmlParse(template);
                    var data = xsltProcess(xmlParse(response), t);  
                    _gel('content___MODULE_ID__').innerHTML = data;
                    //_gel('autosuggest').style.display='none';
                    
                });
        });
    return false;
    }
        
    </script>
    
    <!-- ///////////////////////////// HTML Content /////////////////////////// -->     

    <div id="mainForm___MODULE_ID__">
    <form name = "ChemAllianceGlossaryModule__MODULE_ID__" onsubmit="return searchAcronym(searchInput.value);"> 
    <input type="text" id="searchInput" name="searchInput" size="20" value="">    
    <input type="button" id="btnSearch" size="7" value="Define" onClick="return searchAcronym(searchInput.value);">    
    
    <a class="mainText" style="text-align:right; top:2px" href="." onclick="javascript:{_gel('aboutbox').style.display = 'block'; return false;}">About</a>
    


    </form>
    </div>
        <div id="aboutbox" class="aboutBox" style="position:absolute; left:15px; top:10px; display:none">
          
          <span class="mainText">          
          <p>This module is designed to allow users to look up an acronym in a database service provided by <a href="http://www.chemalliance.org" target="_blank">ChemAlliance.org</a>.  It includes an autosuggest feature (arrow keys to navigate, tab to place in the field, enter to submit) and a neatly formatted ouput.  Use a wildcard character * to denote all matches following the initial string of characters.  IE: ca* to match both CAA and CAP.  </p>
          <p>This module was developed as part of a suite of modules for the ChemAlliance site as part of a senior design project by seniors at <a href="http://eecs.wsu.edu/" target="_blank">Washington State University</a> in conjunction with <a href="http://www.pnl.gov" target="_blank">PNNL</a>.</p>
          <a style="text-align:right" href="." onclick="javascript:{_gel('aboutbox').style.display = 'none'; return false;}">Close</a>
          </span>
        </div>
        
        <DIV id=autosuggest>
        <UL></UL></DIV>
    <div id="content___MODULE_ID__" width="100%"></div>
    
        <script>
        var terms;
        var au;
        function modLoad()
            {    
            terms = new Array();
            
                var term_url = 'http://www.chemalliance.org/webservices/glossary.asp?searchTerm=*&method=1&page=0';
                var term_template_url = 'http://www.eecs.wsu.edu/~cs423/423spring06/PNNL-S/modules_beta/termlist8.xsl';
                      
            _IG_FetchContent(term_url,
                function (response)
                {
                    _IG_FetchContent(term_template_url, 
                    function (template)
                    {                       
                        var t = xmlParse(template);
                        var data = xsltProcess(xmlParse(response), t);  
                        terms = data.split(",");                 
                        au = new AutoSuggest(_gel('searchInput'),terms);                        
                        
                    });    
                });   
                return terms;
        }
        terms = modLoad();    
    </script>
    
    
    <script>
    /* Part of code for the autosuggest came from a javascript piece that another author had written and placed on the net under LGPL, thus making it free to use.
    Unfortunately I have lost the original site address and my original copies of his code.
    Soome aspects of the code he wrote I re-wrote to better serve my needs. -nick */
    /* If anyone finds the original (had something to do with States I think?) Please notify me wsu423@gmail.com so that I can give proper credit.*/
    
    </script>
	
    
]]> 
</Content>
</Module>

