{"id":2643,"date":"2005-11-21T03:02:00","date_gmt":"2005-11-21T03:02:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/heaths\/2005\/11\/21\/blog-customizations-part-3-oo-javascript\/"},"modified":"2005-11-21T03:02:00","modified_gmt":"2005-11-21T03:02:00","slug":"blog-customizations-part-3-oo-javascript","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/setup\/blog-customizations-part-3-oo-javascript\/","title":{"rendered":"Blog Customizations, Part 3: OO JavaScript"},"content":{"rendered":"<p>Not satisfied by the search feature provided by <a href=\"http:\/\/www.communityserver.org\/\" rel=\"nofollow\">Community Server<\/a> I&#8217;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 <a href=\"http:\/\/search.msn.com\/\">MSN Search<\/a>.<\/p>\n<p>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 &mdash; defined as local variables &mdash; even after the constructor function has returned.<\/p>\n<pre><span>function<\/span><span> SearchProvider(title, home, image, url) {<\/span>\n<span>&nbsp; <span>\/\/ Private properties.<\/span><\/span>\n<span>&nbsp; <span>var<\/span> _title = title;<\/span>\n<span>&nbsp; <span>var<\/span> _home&nbsp; = home;<\/span>\n<span>&nbsp; <span>var<\/span> _image = image;<\/span>\n<span>&nbsp; <span>var<\/span> _url &nbsp; = url;<\/span>\n<span>&nbsp;<\/span>\n<span>&nbsp; <span>\/\/ Privileged methods.<\/span><\/span>\n<span>&nbsp; <span>this<\/span>.getTitle = <span>function<\/span>() { <span>return<\/span> _title; }<\/span>\n<span>&nbsp; <span>this<\/span>.getHome&nbsp; = <span>function<\/span>() { <span>return<\/span> _home; }<\/span>\n<span>&nbsp; <span>this<\/span>.getImage = <span>function<\/span>() { <span>return<\/span> _image; }<\/span>\n<span>&nbsp; <span>this<\/span>.getUrl   = <span>function<\/span>() { <span>return<\/span> _url; }<\/span>\n<span>&nbsp;<\/span>\n<span>&nbsp; <span>this<\/span>.getHomeHTML = <span>function<\/span>() {<\/span>\n<span>&nbsp; &nbsp; <span>return<\/span> <span>'&lt;a href=\"'<\/span> + _home + <span>'\"&gt;'<\/span> + _title + <span>'&lt;\/a&gt;'<\/span>;<\/span>\n<span>&nbsp; }<\/span>\n<span>&nbsp;<\/span>\n<span>&nbsp; <span>this<\/span>.getImageHTML = <span>function<\/span>() {<\/span>\n<span>&nbsp; &nbsp; <span>return<\/span> <span>'&lt;img src=\"'<\/span> + _image + <span>'\" alt=\"'<\/span> + _title + <span>'\" \/&gt;'<\/span>;<\/span>\n<span>&nbsp; }<\/span>\n<span>&nbsp;<\/span>\n<span>&nbsp; <span>this<\/span>.getLogoHTML = <span>function<\/span>() {<\/span>\n<span>&nbsp; &nbsp; <span>return<\/span> <span>'&lt;a href=\"'<\/span> + _home + <span>'\"&gt;'<\/span> + <span>this<\/span>.getImageHTML() + <span>'&lt;\/a&gt;'<\/span>;<\/span>\n<span>&nbsp; }<\/span>\n<span>&nbsp;<\/span>\n<span>&nbsp; <span>this<\/span>.search = <span>function<\/span>(keywords) {<\/span>\n<span>&nbsp; &nbsp; location.href = _url + escape(keywords);<\/span>\n<span>&nbsp; }<\/span>\n<span>}<\/span>\n<span>&nbsp;<\/span><\/pre>\n<p>To define a subclass we use the base class to the <code>prototype<\/code> property of the subclass. We must also assign a new function to the <code>constructor<\/code> otherwise when the subclass is instantiated the base class constructor is called.<\/p>\n<pre><span>\/\/ Specialized SearchProvider for MSN Search.<\/span>\n<span>MsnSearchProvider.prototype = <span>new<\/span> SearchProvider();<\/span>\n<span>MsnSearchProvider.prototype.constructor = MsnSearchProvider;<\/span>\n<span>function<\/span><span> MsnSearchProvider() {<\/span>\n<span>&nbsp; <span>\/\/ Call base class constructor.<\/span><\/span>\n<span>&nbsp; SearchProvider.prototype.constructor.call(<span>this<\/span>,<\/span>\n<span>&nbsp; &nbsp; <span>\"MSN Search\"<\/span>,<\/span>\n<span>&nbsp; &nbsp; <span>\"http:\/\/search.msn.com\/\"<\/span>,<\/span>\n<span>&nbsp; &nbsp; <span>\"http:\/\/search.msn.com\/s\/affillogo.gif\"<\/span>,<\/span>\n<span>&nbsp; &nbsp; <span>\"http:\/\/search.msn.com\/results.aspx?q=site%3Ablogs.msdn.com%2Fheaths+\"<\/span>);<\/span>\n<span>}<\/span><\/pre>\n<p>The constructor now creates an instance of the specialized <code>MsnSearchProvider<\/code> and to call the base class constructor by calling the <code>call<\/code> method on the <code>constructor<\/code>. All that&#8217;s left to do is to replace property values and event handlers for the search-related elements. For this another class is created.<\/p>\n<pre><span>function<\/span><span> Search(inputId, aId) {<\/span>\n<span>&nbsp; &nbsp; <span>\/\/ Private properties.<\/span><\/span>\n<span>&nbsp; &nbsp; <span>var<\/span> _inputElem = document.getElementById(inputId);<\/span>\n<span>&nbsp; &nbsp; <span>var<\/span> _aElem = document.getElementById(aId);<\/span>\n<span>&nbsp; &nbsp; <span>if<\/span> (!_inputElem || !_aElem) {<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; <span>return<\/span> <span>null<\/span>;<\/span>\n<span>&nbsp; &nbsp; }<\/span>\n<span>&nbsp;<\/span>&nbsp;\n<span>&nbsp; &nbsp; <span>\/\/ Close 'this'.<\/span><\/span>\n<span>&nbsp; &nbsp; <span>var<\/span> self = <span>this<\/span>;<\/span>\n<span>&nbsp;<\/span>&nbsp;\n<span>&nbsp; &nbsp; <span>\/\/ Public properties.<\/span><\/span>\n<span>&nbsp; &nbsp; <span>this<\/span>.provider = <span>new<\/span> MsnSearchProvider();<\/span>\n<span>&nbsp;<\/span>&nbsp;\n<span>&nbsp; &nbsp; <span>\/\/ Change key handler for input.<\/span><\/span>\n<span>&nbsp; &nbsp; _inputElem.onkeydown = <span>function<\/span>() {<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; <span>if<\/span> (event.keyCode == 13) {<\/span>\n<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; event.cancelBubble = <span>true<\/span>;<\/span>\n<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; event.returnValue = <span>false<\/span>;<\/span>\n<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.provider.search(_inputElem.value);<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; }<\/span>\n<span>&nbsp; &nbsp; }<\/span>\n<span>&nbsp;<\/span>&nbsp;\n<span>&nbsp; &nbsp; <span>\/\/ Change the href and add an onclick handler for the link.<\/span><\/span>\n<span>&nbsp; &nbsp; _aElem.href = <span>\"#\"<\/span>;<\/span>\n<span>&nbsp; &nbsp; _aElem.onclick = <span>function<\/span>() {<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; self.provider.search(_inputElem.value);<\/span>\n<span>&nbsp; &nbsp; }<\/span>\n<span>&nbsp;<\/span>&nbsp;\n<span>&nbsp; &nbsp; <span>\/\/ Add the provider name under the intput.<\/span><\/span>\n<span>&nbsp; &nbsp; <span>var<\/span> _parent = _inputElem.parentNode;<\/span>\n<span>&nbsp; &nbsp; <span>if<\/span> (_parent) {<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; <span>var<\/span> _divElem = document.createElement(<span>\"div\"<\/span>);<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; _parent.appendChild(_divElem);<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; _divElem.className = <span>\"provider\"<\/span>;<\/span>\n<span>&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; _divElem.innerHTML = <span>\"By \"<\/span> + <span>this<\/span>.provider.getHomeHTML();<\/span>\n<span>&nbsp; &nbsp; }<\/span>\n<span>}<\/span><\/pre>\n<p>The <code>this<\/code> object must be closed so that the event handlers can access it; otherwise, when the event handler was called <code>this<\/code> 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.<\/p>\n<p>While object-oriented JavaScript uses prototypal inheritance instead of classical inheritance, it is still a powerful tool. You can find lots of information about <a href=\"http:\/\/search.msn.com\/results.aspx?q=javascript+inheritance\">JavaScript inheritance<\/a> and <a href=\"http:\/\/search.msn.com\/results.aspx?q=javascript+closures\">JavaScript closures<\/a> that can help you learn more about object-oriented JavaScript.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not satisfied by the search feature provided by Community Server I&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":389,"featured_media":3843,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[11,14,29,34],"class_list":["post-2643","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-customizations","tag-development","tag-personal","tag-script"],"acf":[],"blog_post_summary":"<p>Not satisfied by the search feature provided by Community Server I&#8217;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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts\/2643","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/users\/389"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/comments?post=2643"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts\/2643\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/media\/3843"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/media?parent=2643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/categories?post=2643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/tags?post=2643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}