Twitter Bootstrap & JQuery Pagination – The missing JavaScript Example

Ok, so you can find the pagination tutorial in the bootstrap documentation, and it looks great, works great, but there is one thing that is missing, the JavaScript that actually links the pagination widget to the pages that you create in your application. This article will explain in detail how you can connect the pagination widget to a series of div’s that contain well, whatever you want them to.

First, you should go to the Bootstrap page http://twitter.github.io/bootstrap/components.html#pagination and take a look at the pagination example. The code from the page above is below.

<div class="pagination">
<ul>
<li class="disabled"><a href="#">&laquo;</a></li>
<li class="active"><a href="#">1</a></li>
</ul>
</div>

That’s all there is to building the widget that provides the pagination bar on your page, and admit it looks pretty cool out of the box, but this is just the UI, there is nothing on the page to show you how to use it. Now that you have taken a look let’s set up a real world working set of div’s and the corresponding li options.

<div class="pagination-container" >

   <div data-page="1" >
    	Content for Div Number 1
   </div>
   <div data-page="2" style="display:none;">
    	Content for Div Number 2
   </div>
   <div data-page="3" style="display:none;">
    	Content for Div Number 3
   </div>
   <div data-page="4" style="display:none;">
    	Content for Div Number 4
   </div>
   <div data-page="5" style="display:none;">
    	Content for Div Number 5
   </div>

   <div class="pagination pagination-centered pagination-large" style="position:absolute; bottom:0;">
       <ul class="page_control ">
            <li data-page="-" ><a href="#" >&lt;</a></li>
            <li class="active" data-page="1">
                <a href="#" >1</a>
            </li>
            <li data-page="2"><a href="#" >2</a></li>
            <li data-page="3"><a href="#" >3</a></li>
            <li data-page="4"><a href="#" >4</a></li>
            <li data-page="5"><a href="#" >5</a></li>
            <li data-page="+"><a href="#" >&gt;</a></li>
      </ul>
   </div>

</div>

Now, let me explain what has been added to the example code from the Bootstrap page. To start things off I wrapped the content div’s as well as the pagination widget in a div named pagination-container, this step is crucial as the JQuery JavaScript will later use this as a way to find the child div tags. Next, notice the inclusion of the div’s that will contain the content you would like to switch out. Inside these tags you will have noticed that there is an attribute named data-page and each div has a numerical value starting at 1. The data attribute is a new to HTML5 and allows you to store name, value pairs inside of any HTML tag. This tag is intended to be a custom data element that should store private data for which there are no more appropriate attributes or elements. You can read more about the data attribute at w3.org. JQuery happens to have a nice set of built in methods that allow you to access and use the values that can be found in the data attribute. For an in depth look at Jquery.data() take a look at the following resource (http://api.jquery.com/jQuery.data/). After looking at the content holders , you may have noticed the inclusion of the inline style attribute on the container that holds the bootstrap.

style="position:absolute; bottom:0;"

The CSS above just positions the paginator to the bottom of the pagination-container div. This is pretty important as you want to give the appearance that the paginator is static, and it would jump when the height of the content tags change otherwise.

The changes in the li tags that make up the bootstrap paginator’s ‘buttons’ include the addition of the data attributes. After careful inspection, you notice that the data element values and name matches with the data elements that can be found on in the top level div tags.

Now let’s take a look at the script that runs the paginator. We’ll add a function in the script tags named paginationHandler, the code for the function can be found below.

var paginationHandler = function(){
	$('.page_control li').unbind('click', paginationHandler);
	var currentPage		= $(this).data('page'),
	       activePage		= $(this).parent().find('.active').data('page'),
	       num_elements 	= $(this).parent().children().length,
// This equals the first data-page value after the < button.
	       start		= 1,
 // This is the end of the actual pages, remember it is offset by the < and > buttons.
	      end			= num_elements – 2;
	if(currentPage === '+' ){
	    (activePage < end) ? currentPage = activePage + 1 : currentPage = start;
	}

	if(currentPage === '-'){
	    (activePage > start) ? currentPage = activePage - 1 : currentPage = end;
	}
// Remove the active class to the li
	$(this).parent().find('.active').removeClass('active');

// Add the active class to the appropriate li taking
        	$(this).parent().find('li[data-page*=' + currentPage + ']').addClass('active');

// Add a fade out / in effect to the div holding the
// actual data. You must have a div with the data-page
// attribute for every li tag that contains the same
// data attribute or you will get unreliable
// results.

$(this).parents("div .pagination-container").find('div[data-page*=' + activePage + ']').fadeOut('fast', function(){
       $(this).parents("div .pagination-container").find('div[data-page*=' + currentPage + ']').fadeIn('fast');
	$('.page_control li').bind('click', paginationHandler);
	});
}

Next, we have to bind the function to the li tags that reside in the div with the class .page_control. The code to do so is below.

$('.page_control li').bind('click', paginationHandler );

Now let me explain. The first line in our function unbinds the event from the li tag. This is done because if the user decides to click repeatedly on say the ‘next’ button before the fade in animation has completed then all hell will break loose and you may have several div tags displayed at one.
$(this).data(‘page’) actually gets the value in the data attribute and stores it in the current page variable. The next line goes up to the parent tag of the li that was clicked, which is of course, the ul tag and finds the element that contains the active class, and gets the value in the data element of that li tag. This gives you the active page number. The next line gets the total length of the pagination elements, so say if you wanted to make this example work for ten elements instead of five just add the li tags and div tags, no need to modify the JavaScript. Start is always going to be one and remember we have two elements that are not actually pages, they are the next and previous buttons, so deduct two from the total number of elements to get the ending page.

The two if statements handle the user pressing the next and the previous button. One feature I added was the ability to go back to start so to speak if you page past the last element, you may need to modify the code here to 1) add more elements, or 2) just stop at the end, it’s your call.

The line below removes the active class from the pagination widget, and the second line adds the active class to the new current page of the widget.

// Remove the active class to the li
$(this).parent('ul').children('.active:first').removeClass('active');

// Add the active class to the appropriate li taking
$(this).parent().find('li[data-page*=' + currentPage + ']').addClass('active');

This next piece fades out the current content div and then fades in the new content div, and last but not least, we rebind the function to the li elements so that the user can once again click the li tags and change the content.

// Add a fade out / in effect to the div holding the
// actual data. You must have a div with the data-page
// attribute for every li tag that contains the same
// data attribute or you will get unreliable
// results.

$(this).parents("div .pagination-container").find('div[data-page*=' + activePage + ']').fadeOut('fast', function(){
$(this).parents("div .pagination-container").find('div[data-page*=' + currentPage + ']').fadeIn('fast');
$('.page_control li').bind('click', paginationHandler );
});

You will need:
http://twitter.github.io/bootstrap/index.html

Gridpanel editor not firing when using locked columns in Extjs4

I needed to use a locking grid and an editor in Extjs 4.1 today, and of course, there was a noted bug in the forums that mentioned that doing this would not be possible; the edit event would not fire. I really, really needed this as I had promised the customer that it could be done and to use those famous last words that it would be *easy*.

It works, but (maybe not how you want it to work) ….. Here’s what I found out:

Why it looks like the edit event is not firing:

The extjs locking grid feature actually works by splitting your single grid into two grids, one with the columns that are locked and one with the columns that are not. Now let’s think about the document object model and how extjs generates html elements for a moment, in a lot of cases you are probably using an ID property in your grid, but when the user locks a column and effectively creates two grids from the initial grid what’s left are two auto-generated IDs. You may have heard many developers preach the evils of hardcoded IDs and now finally, we have a really concrete example of these IDs causing problems.

Problem 1: You created a grid gave it an ID or action property and set up your reference and / or listener on that grid like this:

refs : [
{
    ref         :  'someGrid',
    selector    :  '#someGrid',
    autoCreate  :  true
}
]

Or  added a controller to the grid like this:

'grid[id=someGrid]':{
    edit:this.onSomeGridEdit
}

Your code will not work, this ID no longer exists in the DOM, so no events will ever be called. You WILL need to set up a controller on the grid to listen to the edit event but this controller will have to work for both grids and will have to work independent of any IDs, so here is how you do it:

'grid':{
    edit:this.onCellEdit
}

Notice that we used the xtype only so that the edit applies to both grids. Now you have to set up your onCellEdit function to handle the different columns that the user may edit, the code is below.

onSomeGridEdit: function( editor, e ){
   if(e.originalValue != e.value){
       switch(e.field){
            case 'col_header_one':
                  //do something            
            break;
            case 'col_header_two':
                 //do something   
            break;
        }
    }
}

Finally, I had a few cells that actually popped up a window and I needed to know the ID of the grid so I could *gasp* use Ext.getCmp(), ( admit it this is why you think this feature is broke :-) )to do this I just used:

this.up(‘grid’).getId();

Adding store events to your controller in Extjs 4.1

Ok so you set out to code your new extjs app using MVC and now you want to do something like add a ‘datachanged’ or ‘load’ event to your store. This is common stuff right, you know exception handlers, so you open up Google or stack overflow and start searching, but what you get is a whole lot of differing opinion on how to accomplish this trivial task. There are a few things that you already know; they are your ground rules so to say. Come hell or high water you will not add listeners to your store, you want all of the methods (or actions) to go in the controller.  So what are you to do?

First let’s look at our sample store:

Ext.define('sample.store.MainStore', {
    extend      : 'Ext.data.Store',
    model       : 'sample.model.MainStore',
    pageSize    : 100,
    remoteSort  : true,
    proxy: {
        type: 'ajax',
        extraParams: {
            start        : 0,
            limit        : 100
        },
        url: 'someurl.php',
        method: 'POST',
        reader: {
            type: 'json',
            root: 'data',
            totalProperty:'results'
        }
    },
    autoLoad: true
});

… and every store has a model, right …

Ext.define('sample.model.MainStore', {
    extend: 'Ext.data.Model',
    fields: [
        'some_primary_key',
        'some_data_element',
    ]
});

Now for the Pièce de résistance – our controller:

Ext.define('sample.controller.Main', {
    extend     :  'Ext.app.Controller',
    models    :  ['MainStore'],
    stores      :  [' MainStore '],
    views       :  ['Main'],
    requires  :  ['Ext.MessageBox'],
    init: function() {

        Ext.getStore('MainStore').addListener('load',
this.onMainStoreLoad,
 this);
        Ext.getStore('MainStore').addListener('datachanged',
this. onMainStoreDataChange,
 this);

        this.control({
               //  A sample combo box select function
            'combo[action=sampleSelect]':{
                select:this.onComboSelect
            },
	//  A sample button click function
            'button[action=sampleAction]':{
                click:this.onButtonClick
            }
        });
    },

// This is where all the functions go

    onComboSelect: function(combo) {
        	console.log('ComboBox Selected, the value is:' + combo.getValue()) ;
    },

    onButtonClick: function(me){
console.log('Button Clicked');
    },

    onMainStoreLoad: function(me,records,success){
if(!success){
     Ext.MessageBox.show({
        title   : 'Data Load Error',
        msg   : 'The data encountered a load error, please try again in a few minutes.'
                });
            }
    },

    onMainStoreDataChange: function(me){
console.log('Hey the store data just changed!');
    }

});

In closing there are a few things that I learned in this exercise that I would like to point out so you don’t repeat my mistakes.

  1. When you look at the API for the store, and you take one of the events (load for example is here http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-event-load ) you can pass the parameters in the function in the controller.

Lies, damn lies, and JavaScript statistics!

Ok I have been doing some statistical analysis of values in arrays lately (because it’s fun!) and wanted to pass on some of the more popular equations, along with what they mean, or what they mean to tell you.

Mean – Many of you no doubt know the mean as the average of a set of numbers, you calculate this by summing the values in the data set and dividing the sum by the number of values. This seems straight forward, and the concepts below rely on the mean so it is crucial that this be calculated. Ext.Array (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Array-method-mean) has a handy way of calculating the mean value of a dataset stored in what else – an array.

In the world of probability the mean is also known as the expected value, and provides a good idea of where the next value will fall.

Variance – Now that you have the mean value of the array, you can start to look for the variance in your dataset. The variance is the measure of how far the numbers in your dataset are spread out. The baseline for this is the mean, which is also known as the expected value! Variance is calculated by taking the mean and subtracting that number from the value, then squaring the difference (between the mean and the value) for each of the numbers in your dataset. Wait! You are only half way there! Once you complete that task you should have a new dataset comprise of squared differences, now to get the variance just calculate the mean of the dataset of squared differences.

Standard Deviation – OK, now that we have worked out the mean, and the variance, what is standard deviation, and what do we plan to do with it. Before I explain, let’s take a look at the chart below:

In this chart you see the greek symbols for mean (μ)  and standard deviation (σ) . The type of curve represented by the chart above is named the bell curve. So you may be asking yourself what standard deviation is right — well, it is the square root of the variance and shows how spread out a set of numbers is. In the bell curve you can see that 34.1% of the dataset falls within -1 standard deviation and 34.1% falls within +1 standard deviation of the mean. This dataset can be categorized as normalized.

Frequency – Now let’s talk about frequency, which is commonly expressed as a histogram, or a chart that contains ‘bins’ and the number of items per ‘bin’.

Now, how do you go about calculating the values above given a set of values in a JavaScript array?

Luckily, I stumbled across some handy JavaScript snippets from Larry Battle (http://bateru.com/news/2011/03/javascript-standard-deviation-variance-average-functions/ ), and of course when you couple that with some extjs Array singleton functions you get an easy to use list of stats functions.

Average (mean)

var avg = Ext.mean(yourArray);

Variance

// Function returns variance for an array of numbers
function  variance(arr){
	// Make sure that your input is of type array
if (!Ext.isArray(arr)) {
return false;
}
	var avg = Ext.mean(arr);
	i = arr.length,
	v = 0;

	while (i--){
		v+= Math.pow((arr[i] – avg), 2 );
	}
	V /= arr.length;
	return (v);
}

Standard Deviation

function stdev(arr){
	// Make sure that your input is of type array
if (!Ext.isArray(arr)) {
return false;
}
	var sd = Math.sqrt(variance(arr));
return sd;

}

Frequency

function histogram(arrayOfNumbers){
var bins = 10,
histogramDataValues = arrayOfNumbers, // Source Values
i = 0,
over = 0,
under = 0,
binContent = [],       // Becomes the data array
delta;

var lowestNumber = Ext.Array.min(histogramDataValues),
highestNumber = Ext.Array.max(histogramDataValues),
delta = Math.abs((lowestNumber - highestNumber) / bins);

// Set the initial value of all bins to zero
// and populate the categories data based on the deltas

for (; i <= bins; i++) {
binContent[i] = 0;
histogramDataValues[i] = lowestNumber + Math.round(100 * (i - 1) * delta) / 100;
}

// Populate the bins with the
for (i = 0; i < histogramDataValues.length; i++) {

if (histogramDataValues[i] < lowestNumber) {
under++;
}
else if (histogramDataValues[i] >= highestNumber) {
over++;
}
else {
var ndata = histogramDataValues[i] - lowestNumber,
thisBin = Math.floor(ndata / delta);

thisBin = Math.abs(thisBin);
binContent[thisBin]++;
}
}
return binContent;
}

Random thoughts on code errors after teaching two different languages in one semester

When I was a bit younger we used to play a game called Pitfall where you would guide your player across various obstacles, including chomping alligators, deadly quicksand, and rushing rivers. In programming there are also pitfalls, and they may not be as bad as an alligator pit, but they will consume your time and leave you drained at the end of the day.

Software errors will always happen, it comes down to how quickly you can identify them and correct them that make all the difference. Those that argue that code should be written error free the first time have obviously not written much code. We can all agree that production code should be error free, but to achieve error free code means you will have to identify and eliminate errors.

I wanted to share a few thoughts on how to cut down on errors in your code.

Use proper indentation, and formatting. This is almost never taught in class, and most of the books that I have seen even contain code that runs and is compact but is not really easy to read.  It’s important to write all your code as if you are going to spend the rest of your career maintaining it.

This sounds great but how can I implement it? Let’s take a look at some code.

I like to use a tab for each block of code. Look at the difference between block a and block b.

A

Ext.override(Ext.form.Radio, {
        setValue : function(v) {
            if (typeof v == 'boolean') {
                Ext.form.Radio.superclass.setValue.call(this, v);
            } else if (this.rendered) {
                var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
                els.each(function(el){
                    if (el.dom.value == v) {
                        Ext.getCmp(el.dom.id).setValue(true);
                    } else {
                        Ext.getCmp(el.dom.id).setValue(false);
                    }
                }, this);
            }
            return this;
        }
    });

B

Ext.override(Ext.form.Radio, { setValue : function(v) {
if (typeof v == 'boolean') {
Ext.form.Radio.superclass.setValue.call(this, v);
} else if (this.rendered) {
var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
els.each(function(el){
if (el.dom.value == v) {Ext.getCmp(el.dom.id).setValue(true);
 } else {Ext.getCmp(el.dom.id).setValue(false);
}}, this);}
return this;
} });

Hard to believe that’s the same code right? Now imagine this throughout a file containing a thousand, ten thousand, hundreds of thousands of lines of code.

Use curly braces even when you don’t have to. Wait won’t that bloat my code? I’ve been taught that I should keep things as compact as possible what’s up with this. Let me explain in code:

A

if (condition1)
{
    if (condition2)
    {
        statement1;
    } else {
        statement2;
    }
}

B

if (condition1)
if (condition2)
statement1;
else statement2;

To the compiler, both pieces of code above will achieve the same result; however, the top block is far easier to read for us humans. Which code would you like to maintain.

Don’t use variable names that have no meaning – remember comments in the code should not be used to explain what your variables are, let their names tell all. This rule needs no code explanation, just stay away from one letter variables like a, b, or c and try to spell them out like

A

        double    a;
        double    b;
a = (b - 32) * 0.555555556

 

B

 

        double    celsius;
        double    fahrenheit;
celsius = (fahrenheit - 32) * 0.555555556

Bet you didn’t know that example A did until you got a look at B, right.

Test often and test early. How many lines do you write before you stop and see if what you have compiles. Do you write test cases for all your functions when you code them and actually test them before connecting them to the user interface? This helps you tackle bugs close to the source without wading through hundreds of lines of code.

If your IDE does not have a nice auto save feature like Jet Brain’s WebStorm, then please remember to save early and save often. There is nothing more frustrating than losing hours of good code.

Nobody ever wanted an app that ran slower, keep that in mind and optimize, optimize, optimize. You can use tools like Page Speed, or Chrome’s Developer Tools to get your JavaScript on track. In addition Google and Yahoo have written detailed articles that are essentially a lessons learned document