Inline Search

I’ve implemented a new feature on my blog, which I think is pretty cool. Over the the right is a new box labelled: Beta: Inline Search. Try typing something into it, and pressing return, or clicking the button. Wait a few seconds (depending on connection speed) and search results for this blog should appear underneath. It’s still fairly rudimentary - I plan to make a “working” indicator, plus the ability to search for more results. But I guess you want to see the code…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    function SearchBlog(){
        window.searchreq = new XMLHttpRequest();
        var s=document.getElementById("s").value.replace(/ /g,"+");
        searchreq.open("POST","/category/&s="+s);
        searchreq.onload = UpdateSearchResults
        searchreq.send("")
    }
    
    function UpdateSearchResults(){
        if (searchreq){
            if (searchreq.status==200) {
                data = searchreq.responseText.split("<body>")[1].split("</body>")[0];
                temp = document.createElement("div");
                temp.innerHTML = data;
                if (temp.getByClass) {
                    results = temp.getByClass("post-title");
                }
                var resList = "Results:<ul>";
                for (var i=0;i < results.length; i++){
                    resList = resList + "<li>"+results[i].innerHTML+"</li>";
                }
                resList = resList + "</ul>";
                document.getElementById("searchresults").innerHTML = resList;
                data = "";
                temp = "";
                resList = "";
            }
        }
    }

You will need to have a getByClass() function installed - if you don’t, it’s:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    /* 
        Thanks to Dustin Diaz for this one:
        http://www.dustindiaz.com/getelementsbyclass/
        */
    document.getByClass = function(searchClass,tag){
            var classElements = new Array();
            if (tag==undefined){tag="*";}
            var els = this.getElementsByTagName(tag); // use "*" for all elements
            var elsLen = els.length;
            var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)");
            for (i = 0,j = 0; i < elsLen; i++) {
                if ( pattern.test(els[i].className) ) {
                    classElements[j] = els[i];
                    j++;
                }
            }
            return classElements;
        }

Barbarella • Ferrante & Teicher • Ultra-Lounge, Vol. 16: Mondo Hollywood ★½

Ajax Search

This is very cool. Better than Live Search. I might be able to implement this, and even include the abililty to get multiple pages worth of results. And, it should be possible to do it so the search results appear in the sidebar, too. I’ll definitely look into this one. (Thanks Kreaper!)

JavaScript Submit Once

This is a cool idea - disable the Submit button via JavaScript when it’s pressed, so poeple can’t resubmit a comment multiple times. Not that it’s happened to me, but I like it anyway. Shamelessly stolen from Submit only once! Note to self: Implement this, or something like it.

Resizable Comment Area

I’ve already had resizable Textarea implemented in this blog - the two buttons that appear at the bottom of the comment box, next to Preview/Post Reply. However, today over on MacGeekery, I came across something even better. A resize widget, that can be dragged to resize the comment entry box. Getting this to work wasn’t quite as simple as just cutting and pasting code, however. Eventually, I rewrote the code from scratch, using some of my toolbox tools also. The script starts by finding every <textarea>, and then, if it has the class resizable, it adds an enclosing <div> tag, and a grippie <div> tag. This then allows for CSS to style the grippie tag.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    function ResizableComment(){
        textareas = document.getElementsByTagName('textarea');
        
        var textarea;
        for (var i=0; textarea = textareas[i]; i++){
            if (textarea.className.match(“resizable”)){
                // Insert resizable <div>
                ta = document.createElement('div');
                ta.className = “resizable-textarea”;
                textarea.parentNode.insertBefore(ta, textarea);
                ta.insertBefore(textarea,ta.firstChild);
                // Insert Grippie
                grippie = document.createElement('div');
                grippie.className = 'grippie';
                w = textarea.offsetWidth - 2;
                grippie.style.width = px(w);
                textarea.parentNode.insertBefore(grippie, textarea.nextSibling);
                grippie.onmousedown = beginResize;
                // Remove bottom border
                textarea.style.marginBottom = 0;
                textarea.style.borderBottom = 0;
            }
        }
    }

Notice also that it sets the onmousedown action for the grippie to a function called beginResize.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function beginResize(e){
        var coords = getMousePos(e);
        window.resizing = eventTarget(e).parentNode.firstChild; // Textarea.
        window.resizing.style.height = px(window.resizing.offsetHeight);
        window.start_resizer = coords[1];
        document.body.onmouseup = endResize;
        document.body.onmousemove = duringResize;
        return false;
    }
    
    function duringResize(e){
        var coords = getMousePos(e);
        window.end_resizer = coords[1];
        if (window.start_resizer == window.end_resizer) return;
        window.height_change = window.end_resizer - window.start_resizer;
        if (window.resizing.offsetHeight + height_change - 1 < 115) return;
        window.resizing.style.height = px(window.resizing.offsetHeight + height_change - 1); // Need the -1 to work!
        window.start_resizer = window.end_resizer;
    }
    
    function endResize(e){
        duringResize(e);
        document.body.onmouseup = null;
        document.body.onmousemove = null;
    }

The beginResize function in turn sets up a few things, including which element needs to be resized, and the functions that need to be called as it happens. These functions use another pair of functions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    function getMousePos(e) {
        var posx = 0; var posy = 0;
        if (!e) e = window.event;
        if (e.pageX || e.pageY){
            posx = e.pageX;
            posy = e.pageY;
        } else if (e.clientX || e.clientY){
            posx = e.clientX + document.body.scrollLeft;
            posy = e.clientY + document.body.scrollTop;
        }
    
        return new Array(posx, posy);
    }
    
    function px(val){return val + “px”;}

Don’t Believe Anymore • The Whitlams • Torch The Moon ★★½

Streamlining Script

I’ve got a heap of stuff in the toolbox script that does nothing anymore - at least on my site - so I think I might streamline it a bit by removing a large number of the functions that are no longer required. For instance, I don’t need to create Gravatars in JavaScript, since there’s a Smarty Plugin to do this - which also negates the need for the md5 stuff. At the moment, the script is 56k, which is a little too bulky.

Floating Window.

I’ve implemented a Floating Window in JavaScript. I’ve actually had it going for a while, I just hadn’t gotten around to finishing the writeup yet. See it at Floater.

Finally: Links in This Post

I’ve updated my toolbox.js script, so now it puts in a sidebar item called “Links in Current Post”. As described in the posts:

These links are really only here so you get to see it in action!

Whatever Tomorrow • David Lane • Put Me In A Taxi ★★★★½

JavaScript Snippet: Get Trackback URL

Here’s a nice little bit of JavaScript that grabs the Trackback URI of the current post. I’m not quite sure how to use it yet. It would be nice to be able to automatically add this to the BlogThis link, but there’s no way to do so, since cross-site scripting is disabled.

1
    document.body.innerHTML.split("trackback:ping=\"")[1].split("\"")[0];

The other thing that might be cool is to copy this to the clipboard, but I’m a bit loath to do things like that which are “invisible” to a user.

Changing Interests

It’s amazing how much and how quickly one can change their attitude towards things. Take the following comment (by me), posted on the Blogsome Forums on Sun Aug 07, 2005 10:28 am.

I try and avoid JavaScript where possible , and cannot tell you if that is valid code or not. What I would suggest is that that code does not belong in the StyleSheet - put it in the Main page template, and see how that goes.

I have become a full convert to the greatness that is JavaScript. Since that point in time I’ve developed quite a library of functions that control various features on this blog, from disallowing Spam comments, to making checkboxes appear as lovely images instead of the ugly normal checkbox. Perhaps my favourite component is my floating window. I’ve mentioned it briefly, but it basically allows for <div> tags to float over the top of other items on the page. They can also remain fixed while the page scrolls, yet be moved to another position, and stay on that point, relative to the window. (This is broken under IE, and others that do not support position="fixed"). I think the irony is that I was very opposed to JavaScript, but had to use it as there was no other way to really control stuff under Blogsome. But, as chance would have it, I discovered just how powerful a language it really is, and now most of my coding is done in JavaScript, with the remainer being PHP Smarty Tags. I can’t remember the last time I wrote a python script. In all honesty, I’d love to be able to supplant all of my JavaScript with python, but I don’t think that will happen. Browsers will always support JavaScript, and XMLHttpRequest() really is pretty cool, but I don’t think they’ll start inlcuding python any time soon.

Links in this Post

I blogged earlier about creating a sidebar entry with all of the links in the current post. The following code snippet will do this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    function createPostLinksBox(){
        if (!getCurrentPost()) return "not a single post page";
        content = getByClass("post-content")[0];
        links = content.getElementsByTagName("A");
        if (!links.length) return "no links in post";
        var placeholder;
        if (!(placeholder=getPlaceholder("outlinks"))) return "no location for outlinks";
        var outlinks = document.createElement('h2');
        outlinks.innerHTML = "Links in this Post";
        var ul = document.createElement('ul');
        for (i=0;i<links.length;i++){
            li = document.createElement('li');
            li.appendChild(links[i].cloneNode(true));
            ul.appendChild(li);
        }
        replaceNode(outlinks,placeholder);    
        outlinks.parentNode.insertAfter(ul,outlinks);
    }

Note that this must be run after the DOM tree is finalised, and relies on a couple of other functions. I’ve put <span id="outlinks">``</span> into my template, so that this will appear wherever that is, if it’s a single post page with any links in it. It will make it into the next update of my script.