Home » Tutorials Advanced Tutorial

Creating an Autosuggest Textbox with JavaScript, Part 2 - Page 2

2.1/5.0 (66 votes total)
Rate:

Nicholas C. Zakas
February 11, 2006


Nicholas C. Zakas
Nicholas C. Zakas is a professional Web designer who specializes in user interface design for Web applications using JavaScript, Dynamic HTML, CSS, XML, and XSLT.


http://www.nczonline.net
Nicholas C. Zakas has written 12 tutorials for JavaScriptSearch.
View all tutorials by Nicholas C. Zakas...

There are three event handlers that need to be assigned: onmouseover, onmousedown and onmouseup. The onmouseover event handler is simply used to highlight the current suggestion, the onmousedown is used to select the given suggestion (place the suggestion in the textbox and hide the dropdown list) and onmouseup is used to just to set focus back to the textbox after a selection has been made. Since all of these event handlers occur on the textbox, it's best just to use a single function for all of them, as seen below:

AutoSuggestControl.prototype.createDropDown = function () {

    this.layer = document.createElement("div");
    this.layer.className = "suggestions";
    this.layer.style.visibility = "hidden";
    this.layer.style.width = this.textbox.offsetWidth;
    document.body.appendChild(this.layer);

    var oThis = this;

    this.layer.onmousedown = this.layer.onmouseup =
    this.layer.onmouseover = function (oEvent) {
        oEvent = oEvent || window.event;
        oTarget = oEvent.target || oEvent.srcElement;

        if (oEvent.type == "mousedown") {
            oThis.textbox.value = oTarget.firstChild.nodeValue;
            oThis.hideSuggestions();
        } else if (oEvent.type == "mouseover") {
            oThis.highlightSuggestion(oTarget);
        } else {
            oThis.textbox.focus();
        }
    };


};

The first part of this section is the assignment of oThis equal to the this object. This is necessary so that a reference to the AutoSuggestControl object is accessible from within the event handler. Next, a compound assignment occurs, assigning the same function as an event handler for onmousedown, onmouseup, and onmouseover. Inside of the function, the first two lines are used to account for the different event models (DOM and IE). The event object is stored in oEvent and the target of the event is stored in oTarget (the target will always be a <div/> containing a suggestion).

If the event being handled is mousedown, then you set the value of the textbox equal to the text inside of the event target. The text is a text node, retrieved by the firstNode property, and the actual text is stored in the nodeValue of the text node. After the suggestion is placed into the textbox, the dropdown list is hidden.

When the event being handled is mouseover, the event target is passed into the highlightSuggestion() method to provide the hover effect. If the event is mouseup, then the focus is set back to the textbox (this fires immediately after mousedown).

Positioning the Dropdown List

In order to get the full effect of the dropdown list it's imperative that it appear immediately below the textbox. If the textbox were absolutely positioned, this wouldn't be much of an issue. In actual practice, textboxes are rarely absolutely positioned and more often are placed inline, which presents a problem in aligning the dropdown list. To do so accurately, you must calculate the location of the textbox using the offsetLeft, offsetTop, and offsetParent properties.

The offsetLeft and offsetTop properties tell you how many pixels away from the left and top of the offsetParent an element is placed. The offsetParent is usually, but not always, the parent node of the element, so to get the left position of the textbox, you need to add up the offsetLeft properties of the textbox and all of its ancestor elements (stopping at <body/>), as seen below:

AutoSuggestControl.prototype.getLeft = function () {

    var oNode = this.textbox;
    var iLeft = 0;

    while(oNode.tagName != "BODY") {
        iLeft += oNode.offsetLeft;
        oNode = oNode.offsetParent;
    }

    return iLeft;
};

The getLeft() method begins by pointing oNode at the textbox and defining iLeft with an initial value of 0. The while loop will continue to add oNode.offsetLeft to iLeft as it traverses up the DOM structure to the <body/> element. The same algorithm can be used to get the top of the textbox:

AutoSuggestControl.prototype.getTop = function () {

    var oNode = this.textbox;
    var iTop = 0;

    while(oNode.tagName != "BODY") {
        iTop += oNode.offsetTop;
        oNode = oNode.offsetParent;
    }

    return iTop;
};

These two methods will be used to place the dropdown list in the correct location.

Adding and Display Suggestions

The next step in this process is to create a method that adds the suggestions into the dropdown list and then displays it. The showSuggestions() method accepts an array of suggestions as an argument and then builds up the DOM necessary to display them. From there, the method positions the dropdown list and displays it to the user:

AutoSuggestControl.prototype.showSuggestions = function (aSuggestions) {

    var oDiv = null;
    this.layer.innerHTML = "";

    for (var i=0; i < aSuggestions.length; i++) {
        oDiv = document.createElement("div");
        oDiv.appendChild(document.createTextNode(aSuggestions[i]));
        this.layer.appendChild(oDiv);
    }

    this.layer.style.left = this.getLeft() + "px";
    this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
    this.layer.style.visibility = "visible";
};

The first line simply defines the variable oDiv for later use. The second line clears the contents of the dropdown list by setting the innerHTML property to an empty string. Then, the for loop creates a <div/> and a text node for each suggestion before adding it to the dropdown list layer.

The next section of code starts by setting the left position of the layer using the getLeft() method. To set the top position, you need to add the value from getTop() to the height of the textbox (retrieved by using the offsetHeight property). Lastly, the layer's visibility is set to "visible" to show it.

Next page


Add commentAdd comment (Comments: 0)  

Advertisement

Partners

Related Resources

Other Resources

arrow