Posts Tagged JavaScript

Sorting in JavaScript

Every now and then you need to sort something in JavaScript and though, it’s not all that hard to do, it is not the best-documented feature. Here is a quick little summary of how to do it.

You call the sort function of an array with your comparator. A JavaScript comparator is just a function that returns -1, 0, or 1 depending on whether a is less than b, a is equal to b, or a is greater than b:

1
2
3
4
5
6
7
8
9
myarray.sort(function(a,b){
    if(a < b){
        return -1;
    } else if(a == b){
        return 0;
    } else { // a > b
        return 1;
    }
});

This is just an example, your function can base the comparison on whatever you want, but it needs to return -1,0,1. Say you had a set of custom JavaScript objects that you want sorted by age:

1
var people = [{name:'Bob',age:21}, {name:'Fred',age:34}, {name:'Dan',age:19}];

You could easily sort them using

1
2
3
4
5
6
7
8
9
people.sort(function(a,b){
    if(a.age < b.age){
        return -1;
    } else if(a.age == b.age){
        return 0;
    } else { // a > b
        return 1;
    }
});

Not too hard to do. It’s actually very similar to the Java Comparator interface.

Popularity: 3% [?]

  • Share/Bookmark

Tags: ,

Collapsible Divs With JQuery

I coded up a nice little collapsible-group side bar thingy using JQuery and it was surprisingly easy. Say you have a sidebar with collapsible group content such as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="container">
    <div class="group">
        <div class="group-title">Group A</div>
        <div class="group-content">
            This is where you would put the content for Group A.
        </div>
    </div>
    <div class="group">
        <div class="group-title">Group B</div>
        <div class="group-content">
            This is where you would put the content for Group B.
        </div>
    </div>
    <div class="group">
        <div class="group-title">Group C</div>
        <div class="group-content">
            This is where you would put the content for Group C.
        </div>
    </div>
</div>

where you have group block titles and group content that you want to be able to toggle the visibility of. With a couple lines of JavaScript and JQuery it’s a sinch:

1
2
3
$('div.group-title').bind('click',function(evt){
    $(evt.target).parent().find('.group-content').slideToggle(500);
});

which will be put inside an onload handler (also using JQuery). When the group title is clicked, the group-content block will toggle by sliding up or down in about half a second. With this model you can also place any number of these “components” on a page without the concern about event collision since the event handling is based on the click location.

Add in a little CSS and you end up with:

Popularity: 8% [?]

  • Share/Bookmark

Tags: , , ,

Accessing Ajax Response Headers

One way to handle error responses with Ajax requests is to add an HTTP Response Header to the response, denoting the resulting command status, while still returning content or data related to the error in the response. Generally when using Ajax calls you don’t want a raw exception or server error to bubble up to your JavaScript handlers.

Let’s say we have a simple quote service at “blurb.jsp”:

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
<%@page import="java.util.Random"%>
<%!
    private static final Random rng = new Random();
    private static final String[] quotes = {
        "I regret that I have but one life to live for my country.",
        "To be or not to be, that is the question...",
        "I drank what?",
        "I am what I am and that's all I am"
    };
%>
<%
    try {
       // WARNING: intentional random error below
        final String quote = quotes[rng.nextInt(quotes.length+1)];
       
        response.setContentType("text/plain");
        response.setHeader("X-Status","OK");
        out.write(quote);
       
    } catch(Exception e){
        response.setHeader("X-Status","ERR");
        out.write("Something bad has happened: " + e.getMessage());
    } finally {
        out.close();
    }
%>

All this does is setup some simple quote strings and randomly provide one of them as a text response. I have added an error condition by allowing the random number generated to exceed the maximum index of the array so that we can get a random error response. In both cases, success or failure, the response header “X-Status” is given a value of “OK” or “ERR” respectively to denote the type of response being sent.

Handling this response with Prototype is pretty simple:

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
30
<html>
    <head>
        <script type="text/javascript"
           src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"></script>
        <script type="text/javascript">
            Event.observe(window,'load',function(){
                $('quote').observe('click',handleClick);
            });
           
            function handleClick(evt){
                new Ajax.Request('blurb.jsp', {
                    onSuccess: function(response) {
                        var quoteElt = $('quote');
                        if( 'ERR' == response.getHeader('X-G-Status') ){
                            quoteElt.setStyle({color:'red'});
                        } else {
                            quoteElt.setStyle({color:'black'});
                        }
                        quoteElt.update(response.responseText);
                    }
                });
            }
        </script>
    </head>
    <body>
   
        <blockquote id="quote" style="border:1px dashed green;padding:4px;">Click me for a quote...</blockquote>
   
    </body>
</html>

Basically, in your “onSuccess” handler function you just pull the header value out of the response object. You could conceivably do any kind of response handling you wanted for an “error” response. In the little demo, you will get a quote from the server each time you click on the quote box; successful quotes will be black, while errors will be in red text.

For the heck of it, I decided to try the same thing in JQuery (without making a whole separate post about it). I am just including the script sections, since they are the only difference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type="text/javascript"
   src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
    jQuery(function(){
        $('#quote').bind('click',handleClick);
    });
   
    function handleClick(evt){
        var jqr = jQuery.get(
            'blurb.jsp',
            function(text){
                var quoteElt = $('#quote');
                if( 'ERR' == jqr.getResponseHeader('X-Status') ){
                    quoteElt.css('color','red');
                } else {
                    quoteElt.css('color','black');
                }
                quoteElt.html(text);
            },
            'text'
        );
    }
</script>

Surprisingly enough, this was a bit more difficult (or convoluted) to do with JQuery since JQuery does not seem to provide any wrapper access to the response itself. You have to use the XMLHTTPRequest object, which works fine but as you can see in the Ajax callback it leads to some interesting code; the jqr varible contains the request object and is used inside the callback function. It just feels a lot less clean.

Maybe I am not clear on how to use the JQuery Ajax support yet and I am missing something simple… or the developers of JQuery decided that since the times you actually need the response object itself are pretty limited, they could get away without providing direct access. Ultimately though, the support is there and that’s what’s really important.

Popularity: 2% [?]

  • Share/Bookmark

Tags: , , , ,

Find Matching Ints with JavaScript

I realized that I had yet to come up with a JavaScript solution for my duplicate ints interview question, (see Interview Question: Find 2 Matching Ints) so I decide a quick implementation would be fun.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
    <head>
        <script type="text/javascript">
            function findDup(items){
                items.sort();
                for( var i=0; i<items.length-1; i++){
                   if( items[i] == items[i+1] ) return items[i];
               }
               throw "No duplicate values!";
           }
       </script>
    </head>
    <body onload="alert( findDup( new Array( 6, 9, 2, 5, 1, 6) ) )">
    </body>
</html>

There is not much to it, and nothing really exciting. I also worked up quick versions using Prototype and JQuery; however, neither one really provided any useful deviation from the standard JavaScript approach.

Popularity: 1% [?]

  • Share/Bookmark

Tags: , ,

Google Ajax APIs

I came across the Google Hosted Ajax Libraries recently and have since found them to be quite useful, especially in quick testing situations where you really don’t want to have to setup a project. You can do everything in one nice text file.

To use the library you want, simply link to it using the external script source link:

1
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

Google has them hosted, minimized and cached so they are nice and fast. Pretty handy.

I mentioned this quickly in my post about Highlighting Text With JavaScript, but I felt that it needed its own little post so that it doesn’t get lost.

Popularity: 1% [?]

  • Share/Bookmark

Tags: , , ,

Highlight Text With JavaScript: JQuery

In my recent post about Highlighting Text With JavaScript I suggested that I should try doing the same functionality with JQuery.

So I did, and I am really starting to like JQuery. Below are the modifications to the HTML shown in the previous posting; basically you just swap out the two script elements in the Prototype version with those shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
    jQuery(function(){
        $('#content').bind('click',highlight);
    });
   
    function highlight(){
        var htm = $('#content').html();
        var str = '';
       
        jQuery.each( htm.split(' '), function(){
           if(jQuery.trim(this) != ''){
            str += this.replace('pick','<span>pick</span>');
           }
           str += ' ';
        });
       
        $('#content').html(str);
    }
</script>

JQuery does on-load event handling and event-handling in general, from what I have seen, in a very similar way to how Prototype does it. The highlight() function is a bit more complex in this version as JQuery does not seem to have the same level of String manipulation support out of the box; however, maybe I missed it in the documentation or perhaps there is a good plugin that adds better string handling.

This post is not really meant to compare the two libraries overall; it was more to satisfy my curiousity and get some practice with JQuery when solving a problem I have already solved with Prototype.

Popularity: 2% [?]

  • Share/Bookmark

Tags: , ,

Highlight Text with JavaScript

A question arose recently about how to highlight a word or words in the text of a div element. It turns out that it’s actually pretty easy using Prototype.

The example below is the code needed to highlight each occurrance (up to ten of them) of the word ‘pick’ in the div. The operation will be performed when the content div is clicked.

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
<html>
    <head>
        <style type="text/css">
            #content span { background-color: yellow; }
        </style>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>
        <script type="text/javascript">
            Event.observe(window,'load',function(){
                $('content').observe('click',highlight);
            });
           
            function highlight(){
                $('content').innerHTML = $('content').innerHTML.sub('pick','<span>pick</span>',10);                
            }
        </script>
    </head>
    <body>
   
        <div id="content">
            Peter Piper picked a peck of pickeled peppers.
            How many peppers did Peter Piper pick?
        </div>
   
    </body>
</html>

Note: I used to Google-hosted version of the prototype library which is handy.

This could easily be refactored to do any sort of style operation to the selected text, or replace it altogether. I will have to give this a try with JQuery as a comparison.

Popularity: 9% [?]

  • Share/Bookmark

Tags: , ,

JavaScript Link Decoration

No, not decorating with pretty colors, decorating with additional functionality… specifically click-tracking and confirmation. With a little bit of JavaScript and a little help from Prototype you can add functionality to link clicks.

If you have the following links

1
2
3
<p><a href="http://dzone.com" class="track">DZone</a></p>
<p><a href="http://cnn.com">CNN</a></p>
<p><a href="http://thinkgeek.com" class="confirm track">Geek Porn</a></p>

noting that they are annotated with CSS classes. These classes are the key. You can use the following JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Event.observe(window,'load',function(evt){
    $$('a').each(function(it){
        it.observe('click',handleLinkClick);
    });
});

function handleLinkClick(evt){
    var elt = evt.element();

    var cont = true;
    if(elt.hasClassName('confirm')){
        cont = confirm("Are you sure?");
        if(!cont){
            Event.stop(evt);
        }
    }

    if(cont && elt.hasClassName('track')){
        var url = elt.readAttribute('href');
        new Ajax.Request('recorder.jsp?url=' + url,{method:'get'});
    }
}

The script will catch clicks on the appropriate link and add functionality to it. In the case of a links with the “track” class it will fire off an Ajax request to a request tracking service, while the “confirm” class adds a confirmation dialog which will stop the click event if confirmation is canceled.

You can put a simple dummy link tracker at “recorder.jsp”:

1
<% System.out.println( request.getParameter("url") ); %>

This decorating works in IE 6+ and in FireFox; however, it will not catch link following events generated by a right-click and “Open in New Tab” selection from the pop-up menu. This seems to be a browser issue that I was unable to find a work-around for. Personally, I tend to open external links that way to preserve the original page… meaning that this procedure will not track clicks from someone like me. Since external links are most likely the ones you want to track, this procedure is mostly useless. I will have to play around with it and see if there is another way.

If you do want to use it you could refactor this a bit and make it use a more object-oriented decorator pattern approach, but this is just to get the general idea out there as an alternative to the old link-modification way of click tracking.

Popularity: 1% [?]

  • Share/Bookmark

Tags: ,

Floating and Following Div

I needed one of those DIVs that appears on call and then stays in view even when you scroll, until you close it. For lack of a better name, I call it the floating following div, and it’s pretty easy to make. With a little help from Prototype we can even make it work across the major browsers.

First you need to put the div to be floated somewhere on your page. The page itself can be anything you want.

1
<div id="movable">This is my floating area</div>

and then you need to give it some initial style:

1
2
3
4
5
6
7
#movable {
    position: absolute;
    left: 100px;
    width: 200px;
    height: 200px;
    background-color: red;
}

Once all that is on the page, you will need some JavaScript to do the fancy stuff:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">          
    Event.observe(window,'load',function(evt){
        $('movable').hide();
           
        Event.observe('showme','click',showDiv);
             
        Event.observe(window,'scroll', function(evt){
            $('movable').setStyle({ top: 8 + document.viewport.getScrollOffsets().top + 'px' });
        });
    });
           
    function showDiv(evt){
        $('movable').show();
    }
</script>

This causes the “movable” element to be hidden. Once the button with an id of “showme” is clicked, the element will be shown and will then follow along with vertical scrolling, staying up near the top of the view port. The key to this following motion is the function mapped to the window scrolling event:

1
$('movable').setStyle({ top: 8 + document.viewport.getScrollOffsets().top + 'px' });

The document.viewport.getScrollOffsets() function is provided by Prototype.

It’s nothing exciting, but it works… just another thing posted here for future reference.

Popularity: 57% [?]

  • Share/Bookmark

Tags: , , ,

Calling Parent Code from IFrame

Every now and then I have needed to access the parent page enclosing an IFrame and I have never really found a good straight-forward example of how to do it, so I end up having to work it out each time I need it. So, for a parent (enclosing page) with an IFrame as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
    <head>
        <title>IFrame test</title>
        <script type="text/javascript">
        function closeIFrame(){
            if(confirm("Are you sure you want to close the iframe?")){
                document.getElementById("frame").style.display = 'none';
            }
        }
        </script>
    </head>
    <body>
        <iframe id="frame" src="visitor.html" width="200" height="200"></iframe>
    </body>
</html>

where the “visitor.html” page called by the IFrame is given as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
    <head>
        <title>Visitor</title>
        <script type="text/javascript">
        function closeMe(){
            parent.closeIFrame();
        }
        </script>
    </head>
    <body>
        <p>Hello, just visiting.</p>
        <button onclick="closeMe()">Close Me</button>
    </body>
</html>

When the “Close Me” button is clicked, the parent page will dispose of the IFrame, but the JavaScript function to do this actually resides in the parent page.

One thing to note, is that both pages must reside on the same domain (or sub-domain) or else the script will not work, due to security restrictions.

Popularity: 1% [?]

  • Share/Bookmark

Tags: , ,

Switch to our mobile site