Friday, January 22, 2016

A Unique Group for Writers, Story Makers, Fiction Lovers and Creative Writers

This is total different blog. Usually I write Tech blogs. This blog is about a group on Facebook.

To Be Continued is a group where we all are here to learn. Learning is the ultimate thing which is limitless.

JOIN THIS GROUP


Let me first tell you the theme of the group. Here admin would start a story of few lines and leave it there. And the members would continue the story in the comment section.

As an amateur writer, I am always looking for other types of writing and storytelling. And of course, different people have different styles. It can be the simplest yet interesting learning process for me and you. Here we all can provide our own taste of write ups, stories (fiction and non-fiction), use of language, use of grammar, and vocabulary.

Here, write ups would be one's own creation. There is no point of copy-pasting the material. But yes, if you find a good piece of writing somewhere, you can post here with proper credit and a clear reason of your posting. But try to be original as much as possible.

Please free to give your suggestions and feedbacks on posts also. After all we look forward to improvement at the end.

Let's take a look at some RULES:

1. This group is for writers and people who are interested in writing. So please DO NOT post any other content which is not related to writing. (Admins have rights to decide whether the post is related to the subject) if found any, Admins will delete the post/s without notifying the respected one.

2. Try to post your own write ups. Try to be original. That's the strongest way that we can learn. And if you are using someone else's content, then you will HAVE TO GIVE A REQUIRED CREDIT AND A CLEAR REASON OF YOUR POSTING.

3. In posting or commenting, you CAN NOT USE languages like ROFL, LOL, BTW kind of abbreviations which are not in dictionaries. If found any, Admins will delete the post/s and comments without notifying the respected one.

4. While posting a write up or commenting, YOU CAN NOT USE OFFENSIVE LANGUAGE. (Admins have the right to decide whether the language or the content is offensive) And if found any, Admins will delete it without notifying the respected one.

5. When you are giving suggestions or feedback, you would need to be more clear with your thought with proper explanation so that other members can also understand your point and learn new things.

NO FOUL OR OFFENSIVE LANGUAGE WOULD BE ALLOWED.

=======================================

I hope you would enjoy your time here.

Happy writing

jQuery JSTree Tips and Tricks Like Expand All Nodes, Get Selected Node, Get Extra Information

Hello,

Recently in one my project I used jQuery JSTree for display data in tree format and while working with I faced certain issues so here I am sharing some tips and tricks you can use with JSTree.

1) Expand All Nodes on Page Load


If you have dynamic dataset in JSTree and you want to expand it when tree is created here is what you can do. First call AJAX service to get data.

$.ajax({
            url: "cat-tree",
            cache: false
        }).done(function( json ) {
            //init js tree here
         
        });

For example in above service I am calling url cat-tree and get my JSON data. Now add following code to initialize JSTree.

$('#categoryTree').jstree({
                'plugins': ["wholerow", "types"],
                'core': {
                    "themes" : {
                        "responsive": false
                    },
                    'data': json
                },
                "types" : {
                    "default" : {
                        "icon" : "fa fa-folder icon-state-warning icon-lg"
                    },
                    "file" : {
                        "icon" : "fa fa-file icon-state-warning icon-lg"
                    }
                }
            });

That's it now wait for sometime to get it rendered in DOM and then expand it.

setTimeout(function(){
                $('#categoryTree').jstree("open_all");
            },500);

2) Add select event and get Selected Node in JSTree

Add following code to add select event.

$('#categoryTree').on('select_node.jstree', function(e,data) {
                    //Your code here
                });

Use following code to get single selected node of JSTree.

var selectedNode = $('#categoryTree').jstree().get_selected(true)[0];

Use following code to get single multiple selected nodes of JSTree.

var selectedNode = $('#categoryTree').jstree().get_selected(true);

3) Deselect all the Nodes in JSTree

Use following code to deselect all the nodes in JSTree.

$('#categoryTree').jstree("deselect_all");

4) Access Additional Data of Selected Node

We know that there is a standard format of data used with JSTree. For example.

[
       'Simple root node',
       {
         'text' : 'Root node 2',
         'state' : {
           'opened' : true,
           'selected' : true
         },
         'children' : [
           { 'text' : 'Child 1' },
           'Child 2'
         ]
      }
    ]

What if you want to have extra data like this.

[
       'Simple root node',
       {
         'text' : 'Root node 2',
         'key1': 'value1',
         'key2': 'value2'
         'state' : {
           'opened' : true,
           'selected' : true
         },
         'children' : [
           { 'text' : 'Child 1' , 'key1': 'value1', 'key2': 'value2'},
           'Child 2'
         ]
      }
    ]

You can pass any number of extra data buy how will you access it. Check the following code.

First get selected node.

var selectedNode = $('#categoryTree').jstree().get_selected(true)[0];

Extra data is available in key  called original.

var value1 = selectedNode.original.key1;
var value2 = selectedNode.original.key2;

Hope this helps you.

Sunday, January 17, 2016

Passing and Retrieving Data from Booststrap Modal

Recently in one my project I was using a theme which is using boostrap modal. Basically I was using modal for confirmation of delete and once user click on confirm process the delete action. I was using laravel REST API so we have to pass the id of object to be destroyed. So I have to pass id of object to modal and confirmation call API to delete. In this blog I will explain how to do this.

First of all add following modal code to your HTML.

<div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
                <h4 class="modal-title">Confirmation</h4>
            </div>
            <div class="modal-body">
                <p> Are you sure you want to delete? </p>
                <input type="hidden" id="objectId"/>
            </div>
            <div class="modal-footer">
                <button type="button" data-dismiss="modal" class="btn dark btn-outline">Cancel</button>
                <button id="confirmDelete" type="button" data-dismiss="modal" class="btn green">Continue</button>
            </div>
        </div>
    </div>

As you can in above code I have added one hidden field in modal where we will store object id.

Now following will your code of delete button.

<a id="deleteButton" data-id="{{$object->id}}" data-toggle="modal" href="#deleteConfirmation" class="btn btn-danger btn-sm">

As soon as you click on delete button modal will be displayed.

Now add following code to your JavaScript.

    $(document).on("click", "#deleteButton", function () {
        var id = $(this).data('id');
        jQuery('#deleteConfirmation .modal-body #objectId').val( id );
    });

    $('#deleteConfirmation .modal-footer button').on('click', function (e) {
        var $target = $(e.target); // Clicked button element
        $(this).closest('.modal').on('hidden.bs.modal', function () {
            if($target[0].id == 'confirmDelete'){
                $id = $('#deleteConfirmation .modal-body #objectId').val();
            }
        });
    });

As you can in above code we have added click event on delete button and setting id in modal hidden field.

Then we are adding event for confirm button in modal window and getting value stored in hidden field and then you can call the APIs or submit form whatever you want.

Hope this helps you.

Laravel 5.1 Restrict Routes Based on User's Access

Recently I was working on a Laravel project where we have three different types of users and based on their access levels, they are not allowed to view certain URLs. So if by chances user know the urls and try to view in browser, they should be redirected to not authorized page. So here in this blog I am going to explain how to do this in Laravel 5.1

For this you have to use Laravel 5.1 HTTP middle ware. HTTP middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application. So first of all create middleware. Go to your laravel application directory in terminal.

php artisan make:middleware AdminMiddleWare

What I did is I created additional column in my users table called access_level and defined three access level

1 = Admin
2 = User

Add following code to middleware we created.


namespace App\Http\Middleware;

use Closure;

class AdminMiddleWare
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->user() == null){
            return redirect('login');
        }

        if ($request->user()->access_level != 1)
        {
            return redirect('not-authorized');
        }

        return $next($request);
    }
}

in the function handle we have added code to check access level. First of all if check if user is logged in by checking following condition.

$request->user() == null

So if there is no authenticated user we redirect to login and if user is logged in we check access level. If access level is not one we redirect them to not authorized page.

Now how will this middle ware works with routes. Go to your routes.php page.

Route::group(['middleware' => 'App\Http\Middleware\ AdminMiddleWare'], function()
{
    Route::get('admin/login',array('middleware' => 'auth', 'uses' => 'AdminController@index'));
    Route::resource('admin-url1', 'AdminController');
    Route::resource('admin-url1', 'AdminController');
    Route::resource('admin-url1', 'AdminController');
});

As you can see in above code we have create route group and assigned AdminMiddleWare to group and specified all admin urls inside the group. 

Hope this helps you.

Wednesday, January 6, 2016

HTML Fit Content to Available Space - Dynamic Font Size

Hello,

Recently in one of my project we have to fit content to available screen height. Basically it was cross platform mobile application built in HTML 5 and JavaScript. On screen there was a card with content. Card height and width as set to screen height and width. Now the problem was content can big or small and there should not be scrollbar. So what I did is I reduced the size of font till the content fits available width and height. This I did in JavaScript. So here in blog I am going to explain how to do this.

First of all add onload method to your body tag.

<body onload="resizeFontSizeInit()">

   <div id="contentContainer" style="width:100%;height:100%;overflow:hidden;">
       <div id="content">
        Dynamic Content Here
       </div>
   </div>

</body>

Now add following function to JavaScript

function resizeFontSizeInit(){
   resizeFont(0.1);
}

function resizeFont(emSize){
      //first get the screen height
      var screenHeight = document.documentElement.clientHeight;
   
      //Now set the font size to content div
      var contentDiv = document.getElementById('content');
      contentDiv.style.fontSize = String(emSize)+"em";

      //Now check the height of screen to height of content div
      var contentHeight = contentDiv.clientHeight;

      //Check if content height is less than screen height.
      if(contentHeight < screenHeight){
           //Increase font size and call the same function recursively.
           emSize = emSize + 0.1;
           resizeFont(emSize);
      }else{
           //content height is greater than screen size so time to stop recursion.
          //set fontsize to previous size.
          revertFontSizeToPreviousSize(emSize);
      }
}

function revertFontSizeToPreviousSize(emSize){
      emSize = emSize - 0.1;
      var contentDiv = document.getElementById('content');
      contentDiv.style.fontSize = String(emSize)+"em";
}

So basically we start with 0.1 em font size and keep increasing it till the content height is greater than screen height. As soon as it's bigger we have to stop and reset it to previous size. This way no matter what your content is, it will fit to screen without scroll bar.

Saturday, January 2, 2016

Push Google Cloud Message (GCM) from PHP Web Application

In this blog I am going to explain how to push a Google Cloud Message (GCM) from PHP web application.

First of all you will need API key from your Google API account. Go to Google API console and add GCM t your API project and generate a key for Android.  This key you have to add in your PHP script.

Now add following function to your PHP script.

public function send_notification($registatoin_ids, $message) {
     
        // Set POST variables
        $url = 'https://android.googleapis.com/gcm/send';
        $apiKey = 'your_api_key';
     
        $fields = array(
            'registration_ids' => $registatoin_ids,
            'data' => $message,
        );

        $headers = array(
            'Authorization: key=' . $apiKey,
            'Content-Type: application/json'
        );
        // Open connection
        $ch = curl_init();

        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);

        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        // Disabling SSL Certificate support temporarly
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));

        // Execute post
        $result = curl_exec($ch);
        if ($result === FALSE) {
            die('Curl failed: ' . curl_error($ch));
        }
     
        // Close connection
        curl_close($ch);
        return $result;
    }

As you can see above function takes registration id and message as param and use curl to send push message to particular device. Registration is is unique per device for all the android phones.

Android Application - Load Images from App Data Directory and Display in Gallery

Hello,

Recently in one of my project, we have list of images in one of the application directory. The requirement was to read those images and display like a gallery. In this blog I am going to explain how to do this.

First of all add following file in your layout xmls and name it activity_image_list.xml. Following is the code.

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/imageGridview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="auto_fit"
    android:columnWidth="120dp"
    android:horizontalSpacing="10dp"
    android:verticalSpacing="10dp"
    android:gravity="center"
    android:stretchMode="columnWidth"  >

</GridView>

This is the Grid View which will show the images like a gallery. Now add an activity and set this xml as contentView in onCreate method.

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_list);


Now for grid we need to have adapter so I created following class and add it to activity.

public class ImageAdapter extends BaseAdapter{
        private Context mContext;
        public int getCount() {
             return mThumbIds.length;
        }                               
        public Object getItem(int position) {
             return mThumbIds[position];
        }                               
        public long getItemId(int position) {
             return 0;
        }                               
        public ImageAdapter(Context c) {
             mContext = c;
        }    
        
        public void setFiles(File[] savedSnapshots){
        this.mThumbIds = savedSnapshots;
        }
                              
        public View getView(int position, View convertView, ViewGroup parent) {
             ImageView imageView;
             if (convertView == null){  
                imageView = new ImageView(mContext);
                imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                imageView.setPadding(8, 8, 8, 8);
             } 
             else{
                 imageView = (ImageView) convertView;
             }
             try{
             Bitmap thumbnail = BitmapFactory.decodeFile(mThumbIds[position].getAbsolutePath());
                 imageView.setImageBitmap(thumbnail);
             }catch(Exception e){
             
             }
             return imageView;
        }
                             
        private File[] mThumbIds = {};        
    }

Now we will load list of images from specific directory and display it in grid,

GridView gridview = (GridView) findViewById(R.id.imageGridview);
ImageAdapter adapter = new ImageAdapter(this);
ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getDir("snapshots", Context.MODE_PRIVATE);
snapshots = directory.listFiles();
adapter.setFiles(snapshots);
gridview.setAdapter(adapter);

As you can see above we are reading images from snapshots directory and create an adapter and set list of files in it. 

And inside getView method of adapter we are creating bitmap and assigned it to image view. This way images will be displayed in grids..

Hope this helps you.

Resolve App Transport Security Exceptions in iOS 9 and OSX 10.11

Hello,

Recently I was working on an old iOS application for my client. This app was developed on iOS 7 and we were adding few updates, I was using iOS 9 SDK on my Xcode. While development I found that none of the web services were working on app. In short app was not able to get data from remote URLs. I show the logs and there was App Transport Security Exception.

Let's first understand what is App Transport Security (ATS).

At WWDC 2015, Apple announced “App Transport Security” for iOS 9 and OSX 10.11 El Capitan. The “What’s New in iOS” guide for iOS 9 explains:

App Transport Security (ATS) lets an app add a declaration to its Info.plist file that specifies the domains with which it needs secure communication. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one.

If you’re developing a new app, you should use HTTPS exclusively. If you have an existing app, you should use HTTPS as much as you can right now, and create a plan for migrating the rest of your app as soon as possible.

In simple terms, this means that if your application attempts to connect to any HTTP server (in this example, yourserver.com) that doesn’t support the latest SSL technology (TLSv1.2), your connections will fail with an error like this:

CFNetwork SSLHandshake failed (-9801)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fb080442170 {NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9802, NSUnderlyingError=0x7fb08055bc00 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1200.)", NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://yourserver.com, NSErrorFailingURLStringKey=https://yourserver.com, _kCFStreamErrorDomainKey=3}

In short app should have all the remote calls with Https protocol. How ever in my case it was not possible as my client refused to install SSL certificate. So I have to bypass App Transport Security.

So here how to do this. Open your project in Xcode and open info.plist file and add following key.

App Transport Security Settings



Now add one more key under that key which you added above. Following is the name of key.

Allow Arbitrary Loads and set it's value to YES. After adding both keys your info.plist should look as below.



That's it and now all your services should work with http protocols.



Send Apple Push Notifications (APN) from PHP Web Application

Hello,

In this blog I am going to explain how to configure your PHP server to send Apple Push Notifications (APN). Please note you will need a valid apple developer account for this.

First of all you will need a PEM file on your server. Following are the steps to create PEM file. Log into apple member center with your developer account credentials.

https://developer.apple.com/membercenter/index.action

Go to Certificates, Identifies & Profiles

Select iOS Apps - > Certificates

We will see how to create both development and production PEM file. Click on + sign on top right corner to add new certificate. It will show you list of certificate types.



Choose from development if you want development certificate or choose from production if you want production certificate. Click on Next and it will ask you to select your application in next step.



Select your desired application and click on next. Now you have to upload certificate signing request. Following are steps to generate certificate signing request


  • Open Keychain Access on your Mac (located in Applications/Utilities).
  • Open Preferences and click Certificates. Make sure both Online Certificate Status Protocol and Certificate Revocation List are set to Off.
  • Choose Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority.
  • Note: If you have a private key selected when you do this, the CSR won’t be accepted. Make sure no private key is selected. Enter your user email address and common name. Use the same address and name as you used to register in the iOS Developer Program. No CA Email Address is required.
  • Select the options “Saved to disk” and “Let me specify key pair information” and click Continue.
  • Specify a filename and click Save.

Upload CSR in the following screen and click on continue.



In the next step click on generate and it will generate your certificate. Download certificate to your local machine and double click on it and it will be added to key chain access and it will open and should show you following screen.



As you can see above development certificates are added as Apple Development iOS Push Services and Production certificate are added as Apple Push Services. Now click on left arrow and expand it. You will see name of certificate signing authority there. Select both name and certificate and double tap on it it will show you following menu.



Click on export two items and save .p12 file.



Now we will convert .p12 file to .pem file using OpenSSL. Open your terminal and run following command.

openssl pkcs12 -in Certificates.p12 -out Certificates.pem -nodes -clcerts

That's it your pem file is ready. Upload it your server and add following functions to send APNs for production and development respectively in your PHP.

public function sendAPNProduction($deviceToken, $msg, $message){

        $payload['aps'] = array('alert' => $msg, 'badge' => 1, 'sound' => 'default');
        $payload['messages'] = $message;
        $payload = json_encode($payload);

        $apnsCert = 'Certicates.pem';

        $streamContext = stream_context_create();
        stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);

        $apns = stream_socket_client('ssl://gateway.push.apple.com:2195', $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);

        $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
        fwrite($apns, $apnsMessage);

        //socket_close($apns); seems to be wrong here ...
        fclose($apns);

}

public function sendAPNDevelopment($deviceToken, $msg, $message){

        $payload['aps'] = array('alert' => $msg, 'badge' => 1, 'sound' => 'default');
        $payload['messages'] = $message;
        $payload = json_encode($payload);

        $apnsCert = 'Certicates.pem';

        $streamContext = stream_context_create();
        stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);

        $apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);

        $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
        fwrite($apns, $apnsMessage);

        //socket_close($apns); seems to be wrong here ...
        fclose($apns);

}

That's it and now your PHP web app is ready to send Apple Push Notifications (APNs). I hope this helps you.