Deals

Monday, June 20, 2016

Sencha Touch Data Store Tips and Tricks

Recently one my friend asked me for some help on Sencha Touch Data store and form our conversation I got an idea for this blog.

Tip 1

If you want to pass extra params to store there are two ways to do that.

1) Pass it in load method.

store.load({
            params: {
                param1 : value1
            }
        });

2) Set it as extra param.

store.getProxy().setExtraParams({
            'param1' : value1,
            'param2': value2
        });

So what's the difference between this two and when to use which.

When you have requirement to add and use params only once. Also every time store load, you want to pass different params you have to use below method.

store.load({
            params: {
                param1 : value1
            }
        });

Params added here are only added once. Next time when you call load method of store, these params are not passed. You can use it for dynamic parameters.

When you have fixed params that you have to pass every time,  a store is loaded. You have to use following method.

store.getProxy().setExtraParams({
            'param1' : value1,
            'param2': value2
        });


This will permanently add those params to the store and it will be passed every time store.load() method is called.


Tip 2

How can you add callback function for store load dynamically. Again there are two ways to do that. If you want to add and use it only once, use following method. 

store.load({
       callback: function(){
              console.log('store is loaded'); 
       }
});

But if you want to wait for store load every time you should use following logic.

store.on({
       load: function(){
              console.log('store is loaded'); 
       },
       scope: this
});

Tricks

1) To reset all the extra params in store use do the following.

store.getProxy().setExtraParams({
});

Just pass the empty object in function and it will clear all previous params.

2) Reset page param in store when using list paging.

You can use currentPage config. store.currentPage = 1

3) Get raw response from of store load.

store.getProxy().getReader().rawData

This will return you all the raw data your API has returned.

Saturday, June 18, 2016

Sencha Touch Create Dropdown Like Standard HTML Control

Recently in one of my project, we have a requirement to create dropdown like standard HTML dropdown with Sencha Touch. See the below screenshot.


As we know in Sencha Touch Selectfield (dropdown)  uses either floating panels and bottom picker to show and choose value from one. So in this blog I am going to mention how to do this. 

First of all following should be our views.

{
    xtype : 'panel',
    height: 40,
    itemId: 'monthSelector',
    id: 'monthSelector',
    style: 'background-color:#ffffff;color: #019297;border-bottom:1px solid #019297;font-size: 12px',
    html: '<div style="height:100%;width:100%;display: table;">$lt;div style="display: table-cell;vertical-align: middle;">Select Month</div><img style="position:relative;float:right;top:10px" height="20" width="20" src="resources/css/images/black-down-arrow.png"/></div>',
    listeners: {
         initialize: function( element ) {
               this.element.on({
                    tap: function( ele ){
                             MyApp.app.getController('MyController').toggleDropDown();
                    }
               });
         }
     }
},

{
xtype: 'dataview',
itemId: 'expenseMonthSelector',
id: 'expenseMonthSelector',
scrollable: false,
style: 'font-size: 12px',
height: 80,
store: {
fields: ['id', 'name','color'],
data: [
{id : 1, name: 'Current Month', color: '#9decf0'},
{id : 2, name: 'Previous Month', color: '#6cd2d6'}
]
},
itemTpl: '<div style="background-color: {color}; color:#000000;height:40px;width:100%;display: table;"><div style="display: table-cell;vertical-align: middle;padding-left: 20px">{name}</div></div>'
}

As you can see above we have one panel with layout look like a dropdown and one dataview which will act like options for the dropdown.

After this we will add our toggleDropDown function to toggle dropdown.

toggleDropDown: function(){
        if(this.getExpenseMonthSelector().isHidden() == true){
            this.getExpenseMonthSelector().show();
        }else{
            this.getExpenseMonthSelector().hide();
        }
},

Above code will simply show hide data view. Hope this helps you.

JavaScript Create Date With TimeZone

Hello,

Recently in one of my project we faced lots of issues regarding in correct dates displayed to users. The problem was TimeZone. A user is in India but he don't know that he has set timezone to USA timezone and hence we get user's device date it was showing wrong date and time.

We asked our users to fix it but as we know end users are always unpredictable they still set the timzone to USA or others and keep complaining us about dates and times.

So here is what we did to fix this issue.

Step 1 : Get User's Current Location

You can use HTML 5 GeoLocation.

if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(gotUserPosition);
}

Step 2 : From the Latitude and Longitude, get user's current timezone using Google API.

function gotUserPosition(position){

     Ext.Ajax.request({
            url: 'https://maps.googleapis.com/maps/api/timezone/json?       location='+ position.coords.latitude +','+position.coords.longitude+'&timestamp='+parseInt(Date.now()/10)+'&key=YOUR_KEY',
            method: 'GET',
            disableCaching: false,
            success: function(response) {
                var result = Ext.decode(response.responseText);
                if(result.status == 'OK'){
                    localStorage.setItem('time_offset',result.rawOffset);
                    localStorage.setItem('timeZoneId',result.timeZoneId);
                }
            },
            failure: function(response) {
             
            },
            scope: this
     });

}

For this you have to create a Google API project and enable timezone API and add your key in stead of YOUR_KEY

As you can see above we are sending user's latitude and longitude to google maps api and getting the result. If result is OK. then we are saving time offset to local storage.

Now this time offset is the offset in number of seconds from UTC time. For example Indian Standard Time is ahead of UTC for 5 hours and 30 minutes. So here my offset will be 19800 seconds which is 5 hours and 30 minutes.

Now use the following logic to create date object.


var utcDate = (new Date()).toISOString();
var offsetHours = parseInt(Number(localStorage.getItem('time_offset'))/60/60);
var offsetMinutes = parseInt(Number(localStorage.getItem('time_offset'))/60%60);

var currentDate = new Date(Date.UTC(Number(utcDate.split('T')[0].split('-')[0]), Number(utcDate.split('T')[0].split('-')[1]) - 1, Number(utcDate.split('T')[0].split('-')[2]), (Number(utcDate.split('T')[1].split(':')[0]) + Number(offsetHours)), (Number(utcDate.split('T')[1].split(':')[1]) + Number(offsetMinutes)),0));

function z(n){return (n < 10? '0' : '') + n;};

var currentDateString = currentDate.getUTCFullYear() + '-' + z(currentDate.getUTCMonth() + 1) + '-' + z(currentDate.getUTCDate());

So above logic about creating UTC date and then adding number of hours and minutes to it to get desired date and time in UTC timezone. So virtually it's UTC date and time but since we added offset it will show you local date and time.

Hope this helps you.



Wednesday, June 15, 2016

Android Identify Notification Tap and Go To Particular Fragment In App

Hello,

Recently in one of my project there was a requirement to go to certain section of app as soon as user taps on particular notification in Android top bar. In this blog I am going to mention how to do this.

First of all you have to properly create notification object.

private static void generateNotification(Context context, String message, String type, String date) {

int icon = R.drawable.icon;

long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
notification.defaults = Notification.DEFAULT_SOUND;
String title = context.getString(R.string.app_name);

Intent notificationIntent = new Intent(context.getApplicationContext(),
MyActivity.class);
notificationIntent.putExtra("msg", message);
notificationIntent.putExtra("type", type);
notificationIntent.putExtra("date", date);

notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context.getApplicationContext(), 0, notificationIntent, 0);
notification.contentIntent = contentIntent;

// set intent so it does not start a new activity

PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}

As you can see in above code we have created notificationIntent where I have specified My fragment activity and put all the params we get in notification as extra in intent. No go to your FragmentActivity class and add following code in onCreate method.


onNewIntent(getIntent()); 

And added following code in in your activity

@Override
public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    if(extras != null){
        if(extras.containsKey("msg"))
        {
            // extract the extra-data in the Notification
            String msg = extras.getString("msg");
            if(isConsiderNewIntent == true){
            Log.v("GCM","GCM message is on new intent"+msg);
            String type = intent.getStringExtra("type");
            String date = intent.getStringExtra("date");
            //check type of message here and go to certain fragment.
            }
        }
    }
}

Hope this helps you.

Magento 2.0 Products API Get all the Details Of Products.

Hello,

It's been long since I have worked on Magento and published a blog on it. But recently my team was stuck in Magento REST Products API so I have to look into it. Basically the problem was

V1/categories/:categoryId/products API.

This API gives following result in an array.

{
     "sku": "Cotton"
     "position": 10001
     "category_id": "2"
}

Now that's little bit weird as there are no other info of products like product name, description etc. So to get this info we have to use other API which is.


V1/products/:sku

But practically that is not a solution. As we may have n number of products so we can call details API n number of times. So what to do in this case. I have spent almost couple of hours on this but could not get any solution so finally this is what I did.


I used SOAP V1/categories/:categoryId/products API in other PHP file go get array of SKUs and loop through an array and formed following strings of SKUs.

sku1,sku2,sku3,sku4,sku5

Now I used SOAP V1/products API will following search criteria.

V1/products?searchCriteria[filter_groups][0][filters][0][field]=sku&searchCriteria[filter_groups][0][filters][0][value]=sku1,sku2, sku3,sku4,sku5&searchCriteria[filter_groups][0][filters][0][condition_type]=in

As you can see above I used filed SKU in search criteria , passed all the SKU I need in comma separated format and used condition IN.

But wait there was another problem,  After calling above API, I did not get any result. I used few different tricks like

[sku1,sku2,sku3,sku4,sku5]

['sku1','sku2','sku3','sku4','sku5']

'sku1','sku2','sku3','sku4','sku5'

But nothing worked. Again I tried to find solution for sometime ad found solution in Magento 2 GitHub repo.

Please check this link.

https://github.com/magento/magento2/commit/65819d2f61a63e4fa9fc978220f8662ee5472791

This problem is going to be fixed in next release but we could not wait so here I updated Magento code myself.

Open the following file.

lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php

Go to line no 2792

and add following code.

if (($key == 'in' || $key == 'nin') && is_string($value)) {
$value = explode(',', $value);
}

That's it and now run following API.

V1/products?searchCriteria[filter_groups][0][filters][0][field]=sku&searchCriteria[filter_groups][0][filters][0][value]=sku1,sku2, sku3,sku4,sku5&searchCriteria[filter_groups][0][filters][0][condition_type]=in


It should give all the details of mentioned SKU. Hope this helps you.

Thursday, May 5, 2016

Create Dynamic Half Circular Progress Bar With HTML 5 CSS 3 - Create Gauge Chart In HTML 5

Recently in one of my project there was a requirement to create half circle gauge chart to show progress of some actions. Something like below image


So first of all I decided to use some charts library to create UI like this but since this was mobile application I do not find any suitable chart library. So I decided to build UI from scratch. So here is the step by step guide. 

First our basic HTML and CSS

<div style="visibility: hidden" class="container" id="container">
                       <div id="border" class="active-border">
                            <div id="circle" class="circle">
                               <div id="needle" class="needle"></div> 
                            </div>
                        </div>
                      </div>

Now the basic CSS.

.container{
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
    top: -25%;
}

.circle{
    position: relative;
    top: 5px;
    left: 5px;
    text-align: center;
    width: 200px;
    height: 200px;
    border-radius: 100%;
    background-color: rgba(0,0,0,1);
}

.border{
    position: relative;
    text-align: center;
    width: 210px;
    height: 210px;
    border-radius: 100%;
    top : 50%;
    background-color:#00a651;
}

.needle {
    position: absolute;
    background-color: #f0566f;
    height: 100%;
    width: 0.5%;
    left: 50%;
}

.needle:before {
    content: "";
    position: absolute;
    top: 0px;
    left: -10px;
    width: 0px;
    height: 0px;
    border-top: 10px solid transparent;
    border-right: 20px solid #f0566f;
    border-bottom: 10px solid transparent;
    -webkit-transform: rotate(90deg);
}

Now here comes the dynamic things. first of we have to set height and width of all the elements inside container to screen width and height.

var containerWidth = 0;

if(document.getElementById('container').clientHeight > document.getElementById('container').clientWidth){
containerWidth = document.getElementById('container').clientWidth;
}
else{
containerWidth = document.getElementById('container').clientHeight;
}

var circleWidth =  containerWidth - 10;
var activeBorderWidth =  containerWidth;
var padding = (document.getElementById('container').clientWidth - document.getElementById('container').clientHeight) / 2;

document.getElementById('circle').style.width = circleWidth + 'px';
document.getElementById('circle').style.height = circleWidth + 'px';
document.getElementById('container').style.paddingLeft = padding + 'px';

document.getElementById('border').style.width = activeBorderWidth + 'px';
document.getElementById('border').style.height = activeBorderWidth + 'px';

So as you can see we are setting border with to container width and make it fit inside container and setting inner circle width to bit less than border width to create circular progress bar. Now we calculate transform degrees to set up liner gradient to show progress. 

var degree = (180 * Number(count)) / (Number(total));

document.getElementById('border').style.background = '-webkit-linear-gradient('+degree+'deg, #9a9a9a 50%, #00a651 50%)';

As you can see since we have half circle we are calculating degrees by 180. If you want full circle progress bar then calculate it with 360 degree.                 

Now set needle transformation.

var needleTransformDegree = 180 - degree;

document.getElementById('needle').style.webkitTransform = 'rotate('+needleTransformDegree+'deg)';
               
document.getElementById('container').style.visibility = 'visible'

That's it and end result look something like below.


Hope this helps you.

CSS Border Radius Not Working in Android WebView or Chrome

Recently while working on mobile app project which was cross platform application we were creating pie shaped menu where we faced a very strange issue.

Actually I was trying to create following menu and I created that successfully while I was working in Xcode and iPhone simulator.



And it worked fine but as soon as I checked it in Android phone it came up like following.


Now that was so embarrassing. Off course, after spending couple of days to make such menu and it came up like this, that is so disappointing. How ever after spending some time over it I found out a solution, in this blog I am going to explain this. There more than one solutions so I posting each one. 

1) Some older version does not support percentage value. 

Some older version of chrome does not support percentage values for border radius. So instead of percentage give pixel values.

Use border-radius : 50px in stead of border-radius : 10%

2) Specify top, left right and bottom property separately. 

some Chrome does understand single value like border-radius : 50px. So here you have to specify each border radius saperately.


Use 
border-top-left-radius: 50px;border-top-right-radius: 50px;border-bottom-right-radius: 50px;border-bottom-left-radius: 50px;


In stead of 

border-radius : 50px

3) Now here comes the issue which I have faced,  background-color "leaking" outside of a border when border-radius is present. In my case there were few div tags which was having background color and was going out side of main container because of transformation.  So here are the two solutions you can do.

Apply overflow: hidden property to main container

If that does not work apply following CSS property to main container.

-webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box;

This should solve your all border radius related problem in all the versions of Chrome. Hope this helps you.