Blog Customizations, Part 3: OO JavaScript

Blog Customizations, Part 3: OO JavaScript

  • Comments 7

Not satisfied by the search feature provided by Community Server I've again created some helpful JavaScript classes this time using object-oriented JavaScript to define a basic search provider and to subclass that for specialized providers like MSN Search.

I defined several private properties and several privileged methods that can access those private properties, unlike public methods in classical object-oriented languages. Thanks to closures those methods can access those private properties — defined as local variables — even after the constructor function has returned.

function SearchProvider(title, home, image, url) {
  // Private properties.
  var _title = title;
  var _home  = home;
  var _image = image;
  var _url   = url;
 
  // Privileged methods.
  this.getTitle = function() { return _title; }
  this.getHome  = function() { return _home; }
  this.getImage = function() { return _image; }
  this.getUrl   = function() { return _url; }
 
  this.getHomeHTML = function() {
    return '<a href="' + _home + '">' + _title + '</a>';
  }
 
  this.getImageHTML = function() {
    return '<img src="' + _image + '" alt="' + _title + '" />';
  }
 
  this.getLogoHTML = function() {
    return '<a href="' + _home + '">' + this.getImageHTML() + '</a>';
  }
 
  this.search = function(keywords) {
    location.href = _url + escape(keywords);
  }
}
 

To define a subclass we use the base class to the prototype property of the subclass. We must also assign a new function to the constructor otherwise when the subclass is instantiated the base class constructor is called.

// Specialized SearchProvider for MSN Search.
MsnSearchProvider.prototype = new SearchProvider();
MsnSearchProvider.prototype.constructor = MsnSearchProvider;
function MsnSearchProvider() {
  // Call base class constructor.
  SearchProvider.prototype.constructor.call(this,
    "MSN Search",
    "http://search.msn.com/",
    "http://search.msn.com/s/affillogo.gif",
    "http://search.msn.com/results.aspx?q=site%3Ablogs.msdn.com%2Fheaths+");
}

The constructor now creates an instance of the specialized MsnSearchProvider and to call the base class constructor by calling the call method on the constructor. All that's left to do is to replace property values and event handlers for the search-related elements. For this another class is created.

function Search(inputId, aId) {
    // Private properties.
    var _inputElem = document.getElementById(inputId);
    var _aElem = document.getElementById(aId);
    if (!_inputElem || !_aElem) {
        return null;
    }
  
    // Close 'this'.
    var self = this;
  
    // Public properties.
    this.provider = new MsnSearchProvider();
  
    // Change key handler for input.
    _inputElem.onkeydown = function() {
        if (event.keyCode == 13) {
            event.cancelBubble = true;
            event.returnValue = false;
            self.provider.search(_inputElem.value);
        }
    }
  
    // Change the href and add an onclick handler for the link.
    _aElem.href = "#";
    _aElem.onclick = function() {
        self.provider.search(_inputElem.value);
    }
  
    // Add the provider name under the intput.
    var _parent = _inputElem.parentNode;
    if (_parent) {
        var _divElem = document.createElement("div");
        _parent.appendChild(_divElem);
        _divElem.className = "provider";
        _divElem.innerHTML = "By " + this.provider.getHomeHTML();
    }
}

The this object must be closed so that the event handlers can access it; otherwise, when the event handler was called this would refer to the element on which the event was fired. Simply pass in the element IDs of the search textbox and link to perform the search.

While object-oriented JavaScript uses prototypal inheritance instead of classical inheritance, it is still a powerful tool. You can find lots of information about JavaScript inheritance and JavaScript closures that can help you learn more about object-oriented JavaScript.

Leave a Comment
  • Please add 8 and 8 and type the answer here:
  • Post
  • It's amazing how many "web developers" there who don't know any of this. It's incredible...

    EEK, you are using literal JavaScript output. That's about as taboo as a goto statement. That's what the DOM is for (or E4X). Gotta remember, this is all working with XML here. Think: nodes.
  • Nice job! Too bad you can't add an additional page, you could then take advantage of the RSS format MSN Search can provide. This is what I have done on my search page:

    http://developernotes.com/Search.aspx
  • David, I had considered that but since I don't need to manipulate the DOM with those nodes and am trying to reduce page size I choose literal output. I am considering some alterations to allow a user to choose whether to use the built-in search functionality for Community Server or MSN Search and that will most definitely manipulate the DOM via methods like createElement and appendChild.
  • Nick, I have seen that and it's nice. Unfortunately I don't have access to do anything with our Community Server. It would be nice to be able to upload a JavaScript file so I don't have to embed everything in the News section (the only place where certain markup is allowed), mainly because Community Server has some weird caching problem where many times updates won't "take hold", i.e. they either don't apply the first time or, if they do, with a forced refresh on the browser the recent markup disappears.
  • This is really cool, but has anyone noticed that pressing enter in the search box doesn't actually kick off the search? It just reloads the page, and you actually have to click on the "go" button to make the search happen.

    Neil
  • Neil, thanks for pointing that out. I have updated the code to correctly cancel the event.
  • The awesome Health Stewart has graciously let me plagiarise his custom CSS to help me make my blog look

Page 1 of 1 (7 items)