Sunday, March 20, 2016

Fox News Navigation is Broken

Fox News Navigation is Broken
Site Navigation in Fox News is not so smart for the user to navigate back from where it came. In the example in Figure 1 below, end user visited Home > U.S. > Environment. Just in three steps, he is lost. There is no site navigation or breadcrumb here. It seems to be, this website is optimized only for search engines, not for the end user to be a regular visitor.

Figure 1. Navigating three level down in Fox News website
As per Spencer (2008), breadcrumb links refer to a trail of category and subcategory links on a website just beneath the master head (main navigation). Keyword-rich breadcrumb links reinforce website's internal hierarchical linking structure to the search engines, as well as enhance its usability. Leave aside breadcrumb, main navigation is altogether missing on just third level in Fox News website.
References
Kumar, H. (2016, March 20). Fox News Navigation [Video file]. Retrieved March 20, 2016, from https://youtu.be/JiIUZCBm4jA
Spencer, S. (2008). The search is on. Multichannel Merchant, 25(4), 29-n/a. Retrieved from http://search.proquest.com/docview/195854706?accountid=27424


Unnecessary Hype up Apple iphone Features

Unnecessary Hype up Apple iphone Features
On Apple official website, there are lots of features of all versions of iphone mentioned, which if studied in detail, don’t even make sense to perspective buyer. Possible reason behind, they hide proper help at right place, is to let the buyer be in confusion and seller take the advantage of this situation. For example, on the Apple website, where end user compare iPhone features with older models, some terms e.g. local tone mapping make no sense to an average end user, as mentioned in Figure 1. Even if end user search for this term in search box, nothing much helpful is available.


Figure 1. Apple must help end user to understand what a feature means, they claim to be present in a product.
As per Kantner, Shroyer, and Rosenbaum (2002), the way end user is trying to seek help for products is changing drastically. Help and documentation about the product should be done in a way which faces least resistance by the end user to understand. Apple must provide end user with running help for the features in a product. This could either take the negotiations in positive direction for seller or may be, in negative direction if user choose not spend money for a feature claimed. But in any case, some kind of running help as suggested in Figure 1 will definitely lead to better satisfaction as a whole.

References

Kantner, L., Shroyer, R., & Rosenbaum, R. (2002). Structured Heuristic Evaluation of Online Documentation. Retrieved March 19, 2016, from http://teced.com/wp-content/uploads/2011/06/kantner_HE_of_online_doc.pdf 

Saturday, March 19, 2016

People Search Filters Missing in Bing Search

People Search Filters Missing in Bing Search
Biggest problem with Bing search Engine is that, they are busy copying Google features without a thought in head. People search is an example that supports this fact. Search results layout for a person name in Google and Bing is almost the same. Good thing is that by keyword, both search engines know that, end user is searching for a person, at least. But, the most important thing, effectiveness of search results is diminished by missing person filters.  

Figure 1. Bing Search results for a person name.

Figure 2. Google Search results for a person name.

Figure 3. Suggested dynamic filter features for search results page – action: search person name.

As per Thurow and Musica (2009), while studying a search engine, its effectiveness, efficiency, learnability, memorability, error prevention & recovery and satisfaction is taken into account. By copying Google as described in Figure 1 and Figure 2 above, Bing Search Engine is trying to cater learnability only. There should be something more Bing must plan to cater to go above and beyond Google. With dynamic filtering suggestion described in Figure 3 above, Bing could achieve better effectiveness and satisfaction.

References

Thurow, S., & Musica, N. (2009). When Search Meets Web Usability. Retrieved March 19, 2016, from http://deca.cuc.edu.cn/Community/cfs-filesystemfile.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.11.64/When.Search.Meets.Web.Usability.pdf

Google Calendar Won’t Let You Print All Search Results

This is a very common use case, where you want to print large number of events in Google Calendar. But print view of this tool is not optimized for printing. Suppose, a user has many (33 in current example in Figure 1 below) events upcoming for a search keyword, if he tries to print the results, he may only get few of the events (13 in the Figure 1 example below) in the paper print he takes.
Figure 1. Google Calendar is not optimized for printing.
As per Leavitt and Shneiderman (2013), dimensions of content should be adjusted to fit most common page size while printing. But Google Calendar print style sheet is not smart enough to remove scroll bars while printing.

References
Leavitt, M., & Shneiderman, B. (2013). Research-Based Web Design & Usability Guidelines. Retrieved March 19, 2016, from http://www.usability.gov/sites/default/files/documents/guidelines_book.pdf

Author Commentary Options Missing in Blogger

According to research by Salas-Rueda (2016), audio-visual content facilitates the teaching-learning process. Blogger gives the facility to insert a YouTube video, as mentioned in Figure 1. But, the steps involved in attaching a video may be, publishing a video (lengthy process in itself) and then refer it here.  
Figure 1. Option to attach video in Blogger.com with possible improvement.
As per Nielsen (1995), a system should cater both inexperienced and experienced users. Had there been a webcam option in Blogger for videos, it would have been more flexible and efficient to use.

References
Nielson, J. (1995, January 1). 10 Usability Heuristics for User Interface Design. Retrieved March 02, 2016, from https://www.nngroup.com/articles/ten-usability-heuristics/
Salas-Rueda, R. (2016). The impact of usable system for regression analysis in higher education. International Journal of Educational Technology in Higher Education, 13(1), 1-10.

Sunday, March 13, 2016

Strictly JavaScript Income Tax Calculator


This example explains how to use the right conditions at right place.

"use strict"; //  undeclared variables prohibited.
var $ = function (id) {
    return document.getElementById(id);
};



window.onload = function () {
    $("calculate").onclick = calculateTax;
    $("reset").onclick = resetInputValues;

};
// this method is called on click of reset button
function resetInputValues() {
    $("tax").value = "";
    $("income").value = "";
    $("mymessage").innerHTML = "";
    return;
}

// this method is called on click of calculate button
function calculateTax() {
    //input validation
    var mySalary = $("income").value.trim();
    if (isNaN(mySalary)) {
        window.alert("Invalid input.");
        return;
    }
    mySalary = parseFloat(mySalary);

    var taxPaid = 0;

    if (mySalary > 413200) {
        taxPaid = (mySalary - 413200) * 0.396 + 119996.25;
    }
    else if (mySalary > 411500) {
        taxPaid = (mySalary - 411500) * 0.35 + 119401.25;
    }
    else if (mySalary > 189300) {
        taxPaid = (mySalary - 189300) * 0.33 + 46075.25;
    }
    else if (mySalary > 90750) {
        taxPaid = (mySalary - 90750) * 0.28 + 18481.25;
    }
    else if (mySalary > 37450) {
        taxPaid = (mySalary - 37450) * 0.25 + 5156.25;
    }
    else if (mySalary > 9225) {
        taxPaid = (mySalary - 9225) * 0.15 + 922.50;
    }
    else {
        taxPaid = mySalary * 0.10;
    }

    $("tax").value = taxPaid.toFixed(2);
    $("mymessage").innerHTML = taxPaid + " is rounded to " + $("tax").value;

}



Sample strictly JavaScript Monthly Balance Calculator


Save this folder somewhere you can edit and play around with these files.

Some  of the learning :

1. how to set undeclared variables prohibited
2. handle arrays
3. playing around with dates in jacascript. new Date, setYear, setMonth, setDate, getDateParts, getFullYear, getMonth, getDate
Especially the formatting.
4. classes and objects in JavaScript
5. parseInt, parseFloat

and so on

balance.js:

"use strict"; //  undeclared variables prohibited.

// get element by id
var $ = function (id) { return document.getElementById(id); };

//creates the grid to display based on transList array available in memory ctrl F5 to start over.
var updateDisplay = function () {
    var html = "<tr><th>Date</th><th>Amount</th><th>Balance</th></tr>";
    var html = html.concat("<tr><td></td><td></td><td>0</td></tr>"); // initially balance is zero.

    var count = getTransaction();//get number of elements in transList array.
    var total = 0;

    //itrate transList to create actual transaction grid
    for (var i = 0; i < count; i++) {
        var trans = getTransaction(i);//get i+1 element in transList array.
        total = calculateBalance(trans["type"], trans["amount"], total);//get cumulative balance after current transaction.
        //system allows blank value in date, if blank is passed as input, itmeans current date. If type is withdrawal amount is displayed like, (amount).
        // date format id  MMM DD YYYY ( e.g. Feb 29 2016). future and past dates are allowed.
        html = html.concat("<tr><td>", trans["dateDisplay"], "</td><td>", trans["amountDisplay"], "</td><td>", formatTotal(total), "</td></tr>");
    }
    // set the html calculated to UI.
    $("transactions").innerHTML = html;

};

//if date input field is blank(noTrim) , it means user wants to enter current date
var getValidDateString = function () {
    var dtParts; //undefined
    //if user wants current date
    if ($("date").value === "") {
        dtParts = getDateParts();
    } else {
        dtParts = getDateParts($("date").value);
    }
    //if user wants current date, almost no chance that dtParts remains undefined
    //but if user enters some value it must be a valid date in format MM/DD/YYYY or else dtParts is undefined
    if (typeof dtParts !== "undefined") {
        //return valid date entered/ assumed in format MMM DD YYYY
        return months[dtParts[0] - 1] + " " + ((dtParts[1] < 10 ? "0" : "") + dtParts[1]) + " " + dtParts[2];
    }
    alert("Please enter date in format MM/DD/YYYY e.g. 02/28/2017. You may leave blank if transaction happened today.");// Instrictions
    $("date").focus(); // take user to date input field to re-enter.


};


// there is almost no chance of error here, since dropdown has only two options
var getValidType = function (type) {

    if ($("type").value === "deposit" || $("type").value === "withdrawal")
        return $("type").value;

    alert("Invalid Type.");
    $("type").focus();

}
//if user enters some random text or he tries to give negative values, this will throw alert.
var getValidateAmount = function () {

    //check if not a number.
    if (isNaN($("amount").value)) {
        alert("Invalid amount.");
        $("amount").focus();
        return;
    }
    //round to two decimals
    var returnValue = parseFloat($("amount").value, 10).toFixed(2);//string here to return
    //negative value not allowed, since it means withdrawal, denoted by transaction type
    if (parseFloat($("amount").value, 10) < 0) {
        alert("If it is a withdrawal, select withdrawal in Type dropdown and enter a positive amount here.");
        $("amount").focus();
        return;
    }
    return returnValue;
}

var add = function () {
    var cType = getValidType();
    var cAmount = getValidateAmount();
    var cDateString = getValidDateString();
    if (typeof cType === "undefined" || typeof cAmount === "undefined" || typeof cDateString === "undefined")
        return;
    //till this point we are ready with valid inputs(assumed/actual).
    addTransaction(cType, cAmount, cDateString);
    //now update display to include just added transaction.
    updateDisplay();
};

//bind add function to click of add button on load of window
window.onload = function () {
    $("add").onclick = add;
    updateDisplay();

};

library_balance.js

"use strict"; //  undeclared variables prohibited.

//no form input fields reffered here to make it look like a library.

var transList = []; // array to store transactions

// short form of months to be displayed. This is needed because old browsers don't support toLocaleDateString
//can't use substring on date string, because it contains "," which is not presented in date in screenshot
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

//transaction is the class will be used to insert objects in transList
function transaction(type, amount, date) {
    this.type = type; // deposit or withdrawal  - string
    this.amount = amount; //string
    this.amountDisplay = (type === "deposit") ? amount : "(" + amount + ")"; // display (amount) for withdrawal
    this.dateDisplay = date;//date is already validated and converted to format to be displayed

};


//if input is undefined, it will consider current date as input
//input is string/nothing
//outout is  01/01/2001 >  [ 1, 1, 2001] ie. [ month, day, year]
var getDateParts = function (dateValue) {

    if (typeof dateValue === "undefined") {
        var currentdate = new Date();
        //month is done + 1 because it returns one less number than actual month e.g. 2 for march
        return [currentdate.getMonth() + 1, currentdate.getDate(), currentdate.getFullYear()];
    }
    var datereg = /^\d{1,2}\/\d{1,2}\/\d{4}$/; //e.g.  99/99/1111
    if (dateValue.match(datereg)) {
        var splitDateInput = dateValue.split("/");
        var monthPart = parseInt(splitDateInput[0], 10);// e.g. 99
        var dayPart = parseInt(splitDateInput[1], 10);// e.g. 99
        var yrPart = parseInt(splitDateInput[2], 10);// e.g. 1111
        var date = new Date();// gives current date
        date.setYear(yrPart);
        date.setMonth(monthPart - 1);
        date.setDate(dayPart);
        // now test data ( 99/99/1111) gives date as Sat Jun 07 1119 00:00:00 GMT-0400 (Eastern Daylight Time)
        //so now compare with inputs again.
        //good thing is leap check is also done in below if condition, like 02/29/2015 will fail here.
        if (date.getFullYear() === yrPart && date.getMonth() + 1 === monthPart && date.getDate() === dayPart) {
            return [monthPart, dayPart, yrPart];
        }
        //if input was valid ,an array containing month, day , year numbers is returned
        //or else nothing - undefined

    }

}

//input integer/nothing
//output is a transaction object
var getTransaction = function (index) {
    if (typeof index === "undefined") {
        return transList.length;
    }
    else if (index < transList.length) {
        return transList[index];
    }



};

//now add transaction is simple, inputs must be valid, simply add an object of type transaction to transList
//input string, string , string
var addTransaction = function (type, amount, date) {

    transList.push(new transaction(type, amount, date));
};

//this adds amount to total for deposit
// and subtract amount from deposit for withdrawal
//input string, string, string
//output string
var calculateBalance = function (type, amount, total) {
    //amount = parseFloat(parseFloat(amount, 10).toFixed(2), 10);
    // total = parseFloat(parseFloat(total, 10).toFixed(2), 10);
    amount = parseFloat(amount, 10);
    total = parseFloat(total, 10);
    if (type === "deposit")
        return (total + amount).toFixed(2);
    else
        return (total - amount).toFixed(2);
};

//used to format any string like  -23.2222 to (23.22)
//or 23.2222 to 23.22
var formatTotal = function (am) {

    am = parseFloat(am, 10);

    return (am < 0) ? "(" + Math.abs(am).toFixed(2) + ")" : am.toFixed(2);


};