Writing Your First Library in JavaScript

Writing a Library in Javascript can be a bit confusing (It was for me atleast when I started learning). It can be confusing because everything in JS is function, so for every particular requirement you can write a function. Having said that, if you are writing a function which serves a particular need, why not make it generic, so that it can be reused.

This post is all about creating a very basic library that simply generates an Excel sheet like layout in your browser with the given numbers of Rows and Columns. We are going to do this in pure JavaScript. We will not be using Jquery or any other JavaScript library, since the motive is to understand how to create a library and not to create an Excel sheet.

DEMO   DOWNLOAD

Task - Generate Excel Sheet in your Browser using Native JavaScript and HTML, CSS.
Approach - We will stick to Object oriented Paradigm for this task and will try to stick to it as much as possible.
Insights - A normal excel sheet will have following aspects -

  1. Numbering of the Rows and Columns in exact behavior found in Excel.
  2. Rows and Columns with Text Input Feature
  3. Option of Adding or Deleting any Specified Row Or Column.
  4. Ability to Sort the Element.

First thing first, Microsoft Excel has a very cool way of numbering Rows and Columns. Rows are generally numbered from 1 to some thousands and Columns are numbered from A till ZZZZZZZ... . Generating the row numbers is pretty easy, but generating the Column names is a bit tricky, since it involves Characters and the numbering is based on the 26 Alphabets.
After quite many iterations to my logic, I came up with this solution. (Comment if you can write a better logic)

function ColumnNames(n) {
    for(var i=0; i<n; i++) {
        var check = i;
        var cap = [];
        while(check>=0) {
            cap.unshift(String.fromCharCode(65 + (check%26)));
            check = check / 26 - 1;
       }
    console.log(cap.join(''));
}

Pretty simple, isn't it. Now lets create a global variable which will be our main point of creating the table. This variable is much like class in c++, which will simply have some members(Row and Column Counts) and some functions.

var table = {   
    rowcount        :0,
    columncount     :0,
    addNewRow : function () {
        this.rowcount++;
    },
    addNewColumn : function() {
        this.columncount++;
    },
    delNewRow : function () {
        this.rowcount--;
    },
    delNewColumn : function() {
        this.columncount--;
    },
    drawTable : function(a,b) {
        if(typeof a==='undefined') this.rowcount = 10;
        else this.rowcount=a;
        if(typeof b==='undefined') this.columncount = 15;
        else this.columncount=b;
        draw();
    }
    };  

This 'table' variable is globally available to us since we did not wrap it inside any function. SO if we call table variable, this should say it is an object with property variables being rowcount and columncount. Also, we have functions to increment and decrement the values and a function named drawTable, which is simply to draw the initialized table. If we put up the following syntax in our HTML document, you can simply call the function and do all the necessary work.

table.drawTable()

This function has optional parameters a and b which is if you need a custom table. Now, all we need to do is write a function draw which simply draws the table on the defined HTML ID. Very simple basic Javascript code of getting the Element Id and creating the Table Headers and Input field.

var draw = function() {
    var tableHead = document.createElement('th');
    tableHead.setAttribute('id','hid-');
    document.getElementById('heading').appendChild(tableHead);
    document.getElementById('hid').appendChild(document.createTextNode("Nos"));
    for (var i = 0; i < table.columncount; i++) {
        var tableHead = document.createElement('th');
        tableHead.setAttribute('id','hid-'+i);
        tableHead.setAttribute('onclick','sortData('+i+')');
        var check = i,cap = [];
        while(check>=0) {
            cap.unshift(String.fromCharCode(65 + (check%26)));
            check = (check/26) - 1;
        }
        textnode=document.createTextNode(cap.join(''));
        document.getElementById('heading').appendChild(tableHead);		
        document.getElementById('hid-'+i).appendChild(textnode);
    }
    for (var i= 0;i<table.rowcount;i++){
    addrowcode(i);
    }
};

This function determines how many rows to be built and calls add code for each row. Now we need simple individual functions that can add row/column etc.

var addrowcode = function(i) {
    var newRows = document.createElement('tr');
    newRows.setAttribute('id','id-'+i);
    document.getElementById('dynamictable').appendChild(newRows);
    var cell = document.createElement('td');
    cell.setAttribute('id','htdid-' + i);
    document.getElementById('id-'+i).appendChild(cell);
    document.getElementById('htdid-'+i).appendChild(document.createTextNode(i));
    for (var j = 0; j < table.columncount; j++) {
        var cell = document.createElement('td');
        cell.setAttribute('id','id-'+i+'-'+j);
        document.getElementById('id-'+i).appendChild(cell);
        var inputCell = document.createElement('input');
        inputCell.setAttribute('type','text');
        inputCell.setAttribute('onclick','this.select()');
        inputCell.setAttribute('class','form-control');
        document.getElementById('id-'+i+'-'+j).appendChild(inputCell);
    };
};	

Similarly, one can write Adding of Columns function, Deleting a row/column etc. One important part of this application is to be able to sort the data entered in each column. I'll show to sort the data in individual columns. One can follow the pattern and write how sorting happens in Datatables or any other Library.

var sortData = function(j){
    var tsort = [],len;
    for(var i =0;i<table.rowcount; i++) {
        var id = 'id-' + i + '-' + j;
        var data = document.getElementById(id).getElementsByTagName('input')[0].value;
        if(data != '') tsort.push(data);
    }
    len = tsort.length;
    if(len==0) {
        alert('Empty Column');
        return;
    }
    // Sort function called twice to erase the condition of
    // either only sorting a number or character.
    tsort = tsort.sort();
    tsort = tsort.sort(function(a,b){
        return a - b;
    });
    for(var i=0;i<table.rowcount;i++) {
        var id = 'id-' + i + '-' + j;
        if(i<len)
            document.getElementById(id).getElementsByTagName('input')[0].value = tsort[i];
        else 
            document.getElementById(id).getElementsByTagName('input')[0].value = '';
    }
 }

And that is it. Again, you can Demo the Application and Download it as well. I will appreciate any feedback for this.
DEMO  DOWNLOAD