Deals

Sunday, May 3, 2015

Laravel App Change TimeZone dynamically

Hello,

Recently I was working on mobile app where we have APIs return in Laravel. We were handling some date and times on server side. This dates and time from server side was displayed to mobile users. Now mobile users can be in different timezones and so APIs should set timezones and show dates and time according to timezone. Here is how I implemented it. I saved user's timezone in db and for each API request from that user set timezone from database.

First extend a laravel controller with base controller so we don't need to repeat this code everywhere.

class ApiController extends BaseController {
    public function __construct() {
         parent::__construct();
    }
}

Now go to BaseController and add constructor.

class BaseController {
        $employeeId = null;
        if(Input::has('employee_id')){
              $employeeId = Input::get('employee_id');
        }

        if($employeeId!=null){
            $employeeDetails = EmployeeDetails::find($employeeId);
            if($employeeDetails->timezone != null){
                Config::set('app.timezone', $employeeDetails->timezone);
                date_default_timezone_set($employeeDetails->timezone);
            }
        }
}

That's it and now you will have dynamic timezone as per user.

Sencha Touch Add Loading Mask on Each Ajax Request

Hello,

This is short and quick blog about how to add global logic to show and hide load mask for each Aajx request in Sencha Touch Application.

In Sencha Touch application Ajax request is used in two ways. Either one can call Ajax request with

Ext.Ajax.request({
})

Or in stores you may have Ajax proxy which will generate Ajax request when store is auto loaded or you call load method. Since this is background process you may want to show loading mask to users. For that you can call setMasked method before Ajax request and you remove that mask in success and failure function. This you have to write everywhere in your code. So it's better to add it to single place.

This how you can do it. Add following code to your launch function in your app.js file.

                Ext.Ajax.on("beforerequest", function(){
Ext.Viewport.setMasked(true);
});

Ext.Ajax.on("requestcomplete", function(){
Ext.Viewport.setMasked(false);
});

Ext.Ajax.on("requestexception(", function(){
Ext.Viewport.setMasked(false);
});

Since Ext.Ajax is singleton class we have added event handler for beforerequest, requestcomplete and requestexception.

In beforerequest event handler we are setting mask to viewport and in requestcomplete and requestexception handler we are removing it. That's it and the mask will be displayed every time there is a ajax request.  Hope this helps you. 

Add iOS in App Purchase to Your Cordova Application

Hello,

Recently I was working on cordova application where we have to add in app purchase in iOS. In this blog I am going to explain how to add in app purchase to cordova based application.

First of all open your MainViewController.m file and un comment following function.


- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType

As we are going to use above function to pass product id to native code from JavaScript with use of this function. Here is how to do this. From your JavaScript file add following code.

window.location.href = 'http://buyproduct.com?productId='+sku.toLowerCase();

This will invoke shouldStartLoadWithRequest delegate. Now in that delegate add following code.

NSURL *url = [request URL];
if([[url hostisEqual: @"buyproduct.com"]){
        NSString *queryString = url.query;
        NSArray* queryStringValues = [queryString componentsSeparatedByString: @"&"];
        NSString* productId = [[[queryStringValues objectAtIndex:0] componentsSeparatedByString: @"="] objectAtIndex:1];
       return NO;
}

This way we get product id in native code and since we returned NO in that delegate, webview will not invoke this url.

Now let's add required library to support in App Purchase. First select project from project explorer and select build phases tab. At bottom where we have linked libraries click on + sign and search for storekit. It will show following framework. Add this to project.


Now open MainViewController.h file and add necessary import statements and delegates. Copy following code.

#import
#import
#import
#import

@interface MainViewController : CDVViewController <SKProductsRequestDelegate, UIAlertViewDelegate, SKPaymentTransactionObserver>
@property (retain, nonatomic) SKProduct* fetchedProduct;
@end
@interface MainCommandDelegate : CDVCommandDelegateImpl
@end

@interface MainCommandQueue : CDVCommandQueue
@end

Now open MainViewController.m file and add necessary callbacks.

#pragma mark -
#pragma mark SKProductsRequestDelegate methods

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    SKPayment * payment = [SKPayment paymentWithProduct:fetchedProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction * transaction in transactions) {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
            default:
                break;
        }
    };
}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {
    
}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
    NSLog(@"restoreTransaction...");
    //call javascript function to consume product only
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {
    
    NSLog(@"failedTransaction...");
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }
    
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

This are necessary functions to support transactions and product request. Now lets first request a product information. Go back to shouldStartLoadWithRequest and add following code at the end.

BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productId];
        if (productPurchased) {
            //call javascript function to consume product
            [self.webView stringByEvaluatingJavaScriptFromString:@"consumePurchasedProduct();"];
        }else{
            SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
            productsRequest.delegate = self;
            [productsRequest start];
        }

Here we are checking if product already purchased. If already purchased simply call JavaScript function to consume it else start product request. After we get product information we have to show it to user.  Add following code to productRequest delegate.

NSArray *products = response.products;
    fetchedProduct = [products count] == 1 ? [products firstObject] : nil;
    if (fetchedProduct)
    {
        NSLog(@"Product title: %@" , fetchedProduct.localizedTitle);
        NSLog(@"Product description: %@" , fetchedProduct.localizedDescription);
        NSLog(@"Product price: %@" , fetchedProduct.price);
        NSLog(@"Product id: %@" , fetchedProduct.productIdentifier);
        
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [formatter setLocale:[NSLocale currentLocale]];
        NSString *localizedMoneyString = [formatter stringFromNumber:fetchedProduct.price];

        NSString *productPrice = @"Price : ";
        productPrice = [productPrice stringByAppendingString:localizedMoneyString];
        NSString* alertViewContent = fetchedProduct.localizedDescription;
        alertViewContent = [alertViewContent stringByAppendingString:@"\n \n"];
        alertViewContent = [alertViewContent stringByAppendingString:productPrice];
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:fetchedProduct.localizedTitle message:alertViewContent delegate:self cancelButtonTitle:@"Buy" otherButtonTitles:nil];
        [alert show];
    }

Above function will show alert like this with product information.


As you can see we have a buy button there. When user clicks on Buy it will call clickedButtonAtIndex function added in above code and it will start payment process. One payment is done it will call completeTransaction delegate. Add following code to it.

NSLog(@"completeTransaction...");
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:fetchedProduct.productIdentifier];
    //call javascript function to consume product
    [self.webView stringByEvaluatingJavaScriptFromString:@"consumePurchasedProduct();"];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

Here we are adding product to user defaults in case network got disconnected before user can consume product. In case of transaction failure other functions will be called.

Wednesday, April 22, 2015

JavaScript identify Android WebView

Hello,

Recently I was working on the cordova project where we have mobile web application hosted on server. With the same URL loaded in Android webview we created native app. Now we have some functionalities in app that should only be available if URL is loaded in Android WebView like camera capture. For that we have to identify webview with JavaScript. In this blog I will explain how to do this.

I added very simple logic. I set custom user agent for WebView from Native android app and just checked that in JavaScript and set global variable. Here is how you can do that.

First of all open res/values/string.xml and add following line.


<string name="user_agent_suffix">AppName/1.0</string>

Then we this Custom Agent from onCreate function of Android Activity.

this.appView.getSettings().setUserAgentString(
            this.appView.getSettings().getUserAgentString() 
            + " "
            + getString(R.string.user_agent_suffix)
         );

So we are setting custom user agent in Android WebView. Now in our app we just have to check this with UserAgent.

Var isNativeApp  = /AppName\/[0-9\.]+$/.test(navigator.userAgent) ? true : false//For checking native app.

That's it now you can check isNativeApp variable anywhere in app to set functions on if the app is running in Android WebView.


Mageto Cart API - Add Simple Product with Custom Options and Configurable Products

Hello,

Recently I was working with Magento SOAP API and I was using cart_product.add API of Magento. I had to support three types of products.

1) Simple Products
2) Simple Product with Custom Options
3) Configurable Products

If you try to add simple products with custom options without specifying options it will give you error. Same thing for configurable products. You have to specify product options. If you check their documentation, there is no information about adding options and attributes.  So here in this blog I am going to explain how to do that. check following code.


$client = new SoapClient($baseurl.'/api/soap/?wsdl');
        $session = $client->login(USER,PASS);
        $quote_id = $_POST['quote_id'];
        $arrProducts = null;
        if($_POST['has_options'] == "false"){
        $arrProducts = array(
array(
"product_id" => $_POST['product_id'],
"qty" => $_POST['qty']
)
);
        }else{
        $jsondata = $_POST['product_options'];
        $allOptions = json_decode($jsondata,true);
        $productType = $_POST['product_type'];
       
        if($productType == 'simple'){
        $arrProducts = array(
array(
"product_id" => $_POST['product_id'],
"qty" => $_POST['qty'],
'options' => $allOptions
                                               //array("option1"=>"value1","option2"=>"value2")
)
);
        }else if($productType == 'configurable'){
        $arrProducts = array(
array(
"product_id" => $_POST['product_id'],
"qty" => $_POST['qty'],
'super_attribute' => $allOptions
                                               //array("option1"=>"value1","option2"=>"value2")
)
);
        }
        }

As you can see above first we creating SOAP client and then creating $arrProducts. As you can see in above code we are passing product options as JSON encoded data and passing type of product. If product is simple product we set key as "options" and if product type is configurable product we need key as "super_attribute". I hope this helps you.

Friday, April 10, 2015

Cocoa OSX NSTextField Select All Text On Focus

Hello,

Recently I was working on MAC application where there was a requirement to select text inside NSTextField as soon as user focus it. In this blog I am going to explain how to do this.

First add a class to your project and name is CustomTextField. It will create two files CustomTextField.h and CustomTextField.m

Open CustomTextField.h file and add following code to it.

#import

@interface CustomTextField : NSTextField


@end

Now open CustomTextField.m file and add following code to it.

#import "CustomTextField.h"

@implementation CustomTextField

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Drawing code here.
}

- (BOOL)becomeFirstResponder
{
    BOOL result = [super becomeFirstResponder];
    if(result){
        [self performSelector:@selector(selectText:) withObject:self afterDelay:0];
    }
    return result;
}
@end

As you can see we have added event handler for becomeFirstResponder event. This event is fired as soon as user focus the text field. In that function we are selecting text by calling selector selectText with zero second delay. This will immediately select the text as soon as user focus on it. Now go to your Storyboard or xib file and select the TextField in which you want this behavior. 

Go to identity inspector and select the class CustomTextField for your textfield.

That's it.You can also do additional stuff like changing background color on focus.

[self setBackgroundColor:[NSColor clearColor]];
[self setBackgroundColor:[NSColor redColor]];

Hope this helps you. 

Sencha Touch MessageBox Can Not Be Closed.

Recently in one of my Sencha Touch project, I had an issue with MessageBox, specifically in Android. The issue was when user taps on Ok button message box does not go away. Ideally it should hide, but instead of that it's body is still visible and due to that app was not usable. Issue was hide animation of message box. ActiveAnimation is blocking messagebox from closing properly, so the workaround is to force "end" function of that animation. it was not ended correctly, probably because of events.

Add following code to your application.

 Ext.override(Ext.MessageBox, {    
            hide:  function() {
                if (this.activeAnimation && this.activeAnimation._onEnd) {
                    this.activeAnimation._onEnd();
                }
                return this.callParent(arguments);
            }
});

This will solve your problem. Now message box will be hidden as soon as you tap on Ok button. Hope this helps you.