Translate

Saturday, 13 December 2014

Yo, l'il Marie!

Yo, l'il Marie!
See, if you don't talk to me,
that dirt truck gonna come mash me
and then you will see what you don't wanna see.

There will be no Rocky Balboa,
and in your eyes no glow
to say, " ****** creepo!"
so talk to me, even if only to say, "Oh!"

Yo, l'il Marie!
Don't talk to me,
if you wanna see the dirt truck mash me
and if you wanna see what you don't wanna see.

It is important to hit
harder than you get hit.
Bother not a bit
if your life is not so well lit.

Yo, l'il Marie!
There doth come a fairy,
when your mind is airy
and dreams coax you to marry.

These streets that you fanned,
with curls and frills unmanned,
and a future unplanned,
need your steps be more manned.

Yo l'il Marie!
believe you me
your fears will flee
and you will be less lonely.

Yo, l'il Marie!
Don't you see?
all that you see
is all that you see.

Friday, 5 December 2014

$.when then and then JavaScript...a single-threaded-monolith-of-interpreted-disaster-for-maintenance :) !

The funny thing is that when JavaScript and jQuery are used in conjunction, it can often be a little puzzling as to which event is getting propagated when and whether to use event propagation or event bubbling to ensure that the right sequence of events have been handled or not and when all these aspects did get resolved, as I sat back to contemplate on the immense, combined destructive power of JavaScript and jQuery together not through any power tools but in the way that they resolve each others' problems such that the end result looks more like a compound that could have confounded the best of scientists put together, I realized that that here is an example that could be likened to the splattering of debris from space, to the 'distributed' missile that "Iron Man" goes to demonstrate to the terrorists, to the 'open for interception' messages strewn across the social media that eventually conjoin (if such a word exists) like in the Terminator (the villainous ones who roll back from liquid droplets to human form!) and serves, best, as the prototype to the theory that if art is a reflection of life then software, AI and design patterns (software ones that is) are 'represented' algorithms of human's interactions. 

Tough and tasking, this may be, I can understand, especially if you are reading my blog with a cuppa and thought it would be a breeze to read through my blog ! 

But it was necessary, believe you me, this roundabout, Thomas Hardy-like obscurity-bordering-on-controlled-rant narrative because it is only upon describing the problem statement in detail can you understand or comprehend what the above observation, and the title above it, means !

The problem statement is the usage of two asynchronous mechanisms (not methods) that need to 'listen' (change in location position co-ordinates), 'communicate' (save the change in location to the DB) 'intelligently' (i.e., not as a dumb client that can simply wait for any response and 'redirect' as if passing the blame to the next page!) through an AJAX call to a VB.Net WebScript Service method (which means server-side technology) via JavaScript, as a JSON object, and to finally (the compound), ensure that the GeoLocation call has been successfully completed before calling the Web Service Script method and on return (I had never experienced before (in my mind, that is) how many different places that a call to a function could return to - a JavaScript call can return to any DOM object, it can return to the last line of the calling function, it can return to a callback, 

(Ah, we all know that? Read on for a few minutes more and you will realize why dismissive attitudes are not only demeaning to progressive minds but also needless !))

behave like the dancing hurricane (or typhoon) that deceives to deceive - that is quite a lot of integrity for a scripted, interpreted language,

despite all that junk said about JavaScript being a single-threaded-monolith-of-interpreted-disaster-for-maintenance - ah, so here we are,

So. when a call to a location services and a call to save the consolidated data occur synchronously but also must ensure that the save data will occur only upon successful location seek, the one best way that is known to be used is the 'callback' - which is much like an illusion in JavaScript because, whether you like it or not, the subsequent lines of code after the location seek will be executed.

For instance,

// Lines n to n+25 in "some .js file"
function somefff....{
    if (navigator.geolocation) {
        var positionOptions = {
            enableHighAccuracy: true
        };
Line 1     navigator.geolocation.getCurrentPosition(function success1(position) {
                var brlat = position.coords.latitude;
                var brlongitude = position.coords.longitude;
                sessionStorage.setItem("breakStartlocation", brlat + "," + brlongitude);
             }, function (err) {
                 showError(err);
                 wctr = true;
                 sessionStorage.setItem("breakStartlocation", strlocationErrorMessage);
            },positionOptions);
        } else {
              alert("Location setting is not enabled or supported in your current browser!");
        }

// Lines n+26 

 Line n if (confirm("You have disabled location seek. Press Ok to reset your browser settings or Cancel to deny location information.")) {

}

else if ....{}

// Lines n+200 to 30 (or so!)

        options.success = function (result) {
            alert("Break saved");
        }
        options.error = function (err) { alert("Error");}
Line n+1        setTimeout(function() {
                          $.ajax(options)},3000);
                        }
Line n+1+1 (for the sake of brevity!)

return saveResult;

}

In the above lines of code, Line 1, Line n and Line n+1 and Line n+1+1 fall into a sequence because of JavaScript's execution mechanism, despite the logical requirements, which is to ensure the sequence of the calls. Not a big deal, as the flippantly inexperienced may quickly quip not knowing that the Geolocation provider has made their service an async service, by specs and design!

This means that the calling code or object would have continued on to display the Confirm message, without waiting for the user to acknowledge to the browser (that has already received the location provider's request to seek out the user's location) that their location could be sought.

It also means that the Line n+1 Ajax call to the webservice method is already underway (even the Confirm dialogs can be of no use if the user clicks the Ok buttons real fast!) and while we are at it, we may as well consider the fact that the Ajax call may have already returned back to the calling page ie. Line n+1+1, too, has executed. So, the calling page that has to display (render) a different set of buttons and UI elements (CSS elements), must have a mechanism to determine if the save data call has been a success and here, is where jQuery and Ajax come to the rescue of JavaScript.

The zest for patching up is an age-old technique that has both its 'pros' and 'cons' (probably why it is called the 'jugaad' in India) and this zest is evident with the way many JS developers and designers felt and being more seamlessly tuned to each other's needs than the 'boxed' up Microsoft or Java developers, jQuery is almost the way a poor man or woman cater to their family, a 'patch' here, a patch there - "Oh, does the event bubble up to the document object? ('Daya', in Hindi, means compassion but since CID, a Hindi TV serial of monumental moronity, has become symbolic of a person breaking open doors, unlawfully, it has now become synonymous with 'show some compassion for wooden doors'. What I mean is, desist. Desist from that lust to argue that a Document is part of the DOM.). Let us change the Ajax calls to return to the DOM than to elements or objects..."

This comparison is not meant to be derogatory because it is a "kind of" representation of how nature, too, responds (though in a more perfectly harmonized manner), adjusts and responds to adjustments again (much like the shifting of the tectonic plates to create mountains to change the paths of rivers to cause floods to cause erosion again to level up).

So, to keep the thread of continuity tight as I lead you through this incredible maze of Ajax event handlers, DOM and plain old JavaScript timeouts, let me quickly warm you up to the "Promise" offered by AJAX/jQuery.

Unlike the build-up, this post's ending is pretty abrupt - all you need is a $.when to wrap around the method call  -

// The calling method from another page (can also be interpreted as a DOM, for the sake of understanding this example.) From different page.aspx

$.when('methodTocall').then(func,func1); 


and a .then() with func and func1 representing the 'success' and 'not success' in the function call when it completes! So, what is the promise? All this can be handled with simple callbacks.

The 'Promise' is that you can line up any number of sequence to calls made to asynchronous methods

(ie., methods that make asynchronous calls but which desperately need a mechanism, not provided in JavaScript, that execute async calls, synchronously, but require coherence in sequence to enable manageable logic in execution, not just to tackle complex business models and demands but also for the benefit of testing frameworks and testability)!

but more importantly, as I experienced, I could manage two 'disconnected' events that had 'committed' synchronous activities attached, 'post-' the async call, that relied not on the 'traditional' HTML post or 'form' methods or elements but on CSS elements, which meant callbacks-had-to-'trigger'-an-execution-thread on the client-side upon successful completion (or not), which cannot happen until it happens at the DOM level and which the Ajax's document level event handlers like AjaxStart, AjaxStop, AjaxComplete, AjaxSuccess and many more provide.

But the real joke is in the parameters to the then() method - they, too, execute synchronously !! :D

Wednesday, 3 December 2014

A normal life, after all...

(Dedicated in aid of the victims of the Bhopal tragedy, who need lifelong support and help.)

A terrible, terrible sight
a terrible, terrible plight
it is not a matter of right
nor is it a matter of oversight

if riches are given more weight
over nature's might
then such, that does not become a human sight,
becomes the common's terrible, terrible plight.

Utter not nor hear not nor listen not to no evil
See not nor show not nor teach not to know evil
Make not nor buy not nor sell not no evil
Let not nor allow not nor bear not no evil

for the devil is not in the evil
nor in the 'evil' preached as the devil
the evil is the evil
not preached nor practiced nor known as 'evil'.

Normal work that lead to tragedies
normal play end in disaster
but time flies, faster,
to leave normal life that usually dies

all well said and done and taken in the right spirit,
but this terrible plight, that, that makes such a sight
that does not become common sight, a common, every day plight
still persists to be known as an 'oversight'.

Sunday, 30 November 2014

How to add dynamic rows in Javascript

One of the most curious case has come my way and it pertains to many aspects of software development but most importantly, to testing and the purpose of testers so I think this post becomes necessary as due to online projects and work done more than earlier, many 'unqualified' testers are giving 'opinions' on projects like 'user feedback' on products.

It is also possible that before going 'live' some project owners try to get 'user feedback' to make their system more robust, in which case, it can only be called an 'innovative' approach, but which obviously is more often than not called 'too smart' or 'too stupid' because what is applicable on a 'product development life cycle' is usually not applicable for a 'project development life cycle' and the resulting confusion can only be called 'immaturity' and 'malignant' because it only gives 'support' for 'excuses' made by the project owners to manipulate the 'quality' of delivery to their teams or to vendors or to service providers.

Many testers take it upon themselves to take 'moral' stands, where the issue is either a bug or a feature that may not be working properly. They are 'conveniently' backed by 'time to market' and 'management' theories on how much it costs them if their product is delayed and so undue pressures and compromises and 'jugaads' are initiated.

The whole point is in 'planning' and many get it right and many do not, as happens in the whole software development life cycle of any project.

So, when a solution 'demands' that rows must be added to a table and must be infinite in number upon the click of a user action at the client-side, Javascript and jQuery are the best languages (everybody in the software industry acknowledges this and knows it!) but the problem is how to test a scenario where the events, data and the actions themselves are to be dynamic.

I know, as do many mature Agile developers, that I can use Jasmine to unit test Javascript.

The 'wise' know the pitfalls and prepare a 'plan' to take care of the 'unforeseen' bugs that may occur at runtime for which it becomes important to be 'proactive' enough to identify the 'run time' aspects of the scenario and instead of preparing 'contingency' plans to mitigate the possible delay that may or would be caused by the complexity, they, instead, prepare 'plans' to 'corner' the developers. Seriously !

And many actually 'glare' at others who may know the technique and can do it but they themselves cannot!!

Now, why is such arrogance necessary when you can do your simple work properly by identifying test scenarios and have them tracked in a Google doc or a project management bug tracking system rather than indulging in blame games. The answer could be in the political atmosphere that surrounds a company or some problem totally unrelated to the project or work but which can be identified and best solved by the people themselves.

A question that normal people's culture and etiquette does not allow and some try to take advantage of it all that since the management or the HR are not tech savvy, they can get away with 'bluster' and 'bravado'.

And this is why it is necessary for HRs of organizations to read blogs and consult 'experienced' and 'mature' people before hiring and not rely on Facebook and other 'rigged' references. I remember when working with an organization, I would be called upon plus shared with, the technical and technological plans of projects and the necessary plans for the HR and the teams to make.

Simple thumb of rule for young developers or testers is be humble to ask for help. politely. When you have established yourself then you can go around stomping on everyone's feet but when it is time to learn, do not teach others more capable than yourself ! :)

All that is required is to understand your position and be humble enough to ask for help from other team members, and not 'grand stand' around that such scenarios cannot be tested or even developed !

The greatest disservice anybody could do to their team or even friends and family is to not admit that they were wrong but instead persist with blaming others for their own incapability in either 'testing' or in technique unless of course, hiring 'goons' to enforce that others do it for you without having to pay for the service and without admitting to your own incapability (as happens in Indian movies, where a 'goon' becomes a Doctor by having somebody else taking the medical entrance test to become a MBBS doctor) is an option available for you.

So, it does not even make it lack of knowledge or inexperience or immaturity but sheer 'unprofessional' attitude that does not exist in the IT industry.

I have had this experience and so speak from first hand experience that it is tantamount to a kind of 'cunning' and 'cleverness' that no management would want to associate with, so if you wish to make a career in the IT industry, do not indulge in such practices nor allow others, who may be doing it 'secretively' from 'outside'.

Here is one scenario, where you can add any number of rows to a table, using Javascript (knowledge of Html, JS, jQuery and CSS is required to run the example) and which somebody seems to have professed as 'impossible' and then trying too darned hard to prove themselves right!

// the output as it should be

                          








// Javascript


                        // HTML string to add to table breaks
                        var strBreak = null;
                        var strTxtBreak = null;
                        var rowTxt = null;

                        // used for determining number of rows added to table
                        var xx = 0;

                        // used for calculating distance of textboxes
                        var jk = 5;

                        // used for array index

                        var cell3 = "
";
                        for (var i = 0; i < w; i++) {                      
                            row = table.insertRow(i);
                            strBreak = "
 +
";
                            jk = jk + 5;
                            strTxtBreak = "

";
                            row.innerHTML = strBreak + strTxtBreak;
                            yy = yy + 2;
                            xx = i;
                            jk = jk - 5;
                            jk = jk + 55;
                        }
                        var j = 0;
                     
                        j = xx+1;
                        // Row for Notes
                        var rowN = table.insertRow(j);
                        //var rowN1 = table.insertRow(j+1);

                        // For vertical ruler

                        //var t1cell1 = "
";

                        // Set initial position values of elements
                        notesIconLeftValue = 14;
                        notesIconTopValue = jk;
                        notesAreaLeftValue = 40;

                        // creating style str for Notes
                        styleStrForNotesIcon = "style=" + "'position:absolute;top:" + notesIconTopValue + "px;left:-14px;" + notesIconLeftValue + ";" + "'";
                        styleStrForNotesArea = "style=" + "'position:absolute;top:" + notesIconTopValue + "px;left:" + notesAreaLeftValue + "px;width:310px;height:65px;text-align:left;background-color:lightgray;border-color:lightgray;'"
                        var cell5 = "
";

                        // HTML for Notes box row
                        var strNotesIcon = "
 +

";
                        var strNotesArea = "

"

                        // Inserting Notes row HTML
                        rowN.innerHTML = strNotesIcon + strNotesArea;
                        //rowN1.innerHTML = t1cell1;
                        jk = jk + 50;

                        // HTML for buttons
                                             
                        // Table 'tablebtns' into which to add buttons
                        var table1 = document.getElementById("tablebtns");
                        var k = jk + 55;
                        var l = k + 55;

                        // For continue shift button
                        var m = jk + 30;
                        var nn = m + 25;
                        var t1row1 = table1.insertRow(0);
                        // Table style and position
                        var cell1 = "
 +
Continue Work
";
                        t1row1.innerHTML = cell1;

                        eDiv.appendChild(table);
                        eDiv.appendChild(table1);

                        $('#box1').show();
                        $('#tablebrks').show();
                        $('#tablebtns').show();
                        document.getElementById("continueWork").onclick = clickContinueWork;

// HTML
<html>
     <div id="boxMiddle">
         <table style="position:absolute;top:10px;left:25px;width:305px;display:none" id="tablebrks">
         </table>
     </div>

        <table id="tablebtns" style="display:none"></table>

<style>

#box1 {    position:absolute;
    height:110px;
    top:180px;
    padding: 5px 5px 5px 5px;
    border:none;
    margin:25px;
    background-color:white;
    display:none;
}

#boxMiddle {
    position:relative;
    height:260px;
    /*top:145px;*/
    padding:4px 7px 2px 4px;
    border:none;
    margin:25px;
    background-color:white;
    display:none;
}

div.calloutContinue {
    background-color: #8EC127;
    background-image: -moz-linear-gradient(top, #444, #444);
    position: absolute;
    top:30px;
    left:42px;
    color: #000000;
    padding: 10px;
    border-radius: 3px;
    /*box-shadow: 0px 0px 20px #8EC127;*/
    margin: 25px;
    min-height: 20px;
    /*border: 1px solid #333;*/
    text-shadow: 0 0 1px #000;
    text-align:center;
    height:40px;
    width:145px;
}
.calloutContinue::before {
    content:"";
    width: 0px;
    height: 0px;
    border: 0.4em solid transparent;
    position: absolute;
}

.calloutContinue.right::before {
    left: -16px;
    top: 10%;
    border-right: 10px solid #8EC127;
}
.calloutContinue.right:hover {  
    cursor:pointer;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">

// The javascript code here

<script/>