Deals

Saturday, April 19, 2014

How to solve MySql errorno : 150 "Can't Create Table"

Recently I faced one issues while creating tables in database. I was adding primary and foreign key in tables and I get errorno : 150 "Can't Create Table" I took almost couple of hours to resolve that error so in this blog I am going to explain what could be possible cause for this error. If you get this error check following possible cause.

1) The two tables must have same storage ENGINE

As we know we can configure storage engines like MyISAM, InnoDB. When you add foreign key to the table both parent and reference table should have same storage engine.

2) The two tables must have the same charset.

MySql supports more than 30 character sets. Both parent and reference table should have the same charset.

3) Primary key and Foreign key column must have same datatype.

When you add a foreign key, the primary key in parent table must have the same datatype as foreign key. For example if you have following definition of primary key

id INT UNSIGNED NOT NULL AUTO_INCREMENT

then you must define foreign key as

pk_id INT UNSIGNED NOT NULL

Else it will give you an error and will not work.

4) Primary key and Foreign key column must have same collation type

MySql supports more than 70 collation type. To define primary key and foreign key both columns should have same collation type

5) If there is already data is must match 

If there are already data in both the tables it should match otherwise MySql will not allow to add foreign key. If there is data inconsistency, first delete the inconsistent data and then add primary key.

6) If the reference column is part of composite primary key, it may not work.

If the referenced column is part of composite primary key it may not work so if it's not required to have composite primary key, just define single column as primary key.

Hope this helps you.

Add Tap Hold Event in Sencha Touch panel

Recently in one of my project, requirement was to display context menu when user tap and hold on sencha touch panel. We all know we can add itemtphold event on sencha touch list. But in my case I have to use panel. In this blog I will explain how to add tap hold event to sencha touch list.

The logic is simple , first of all we have to bind touchstart and touchend event on panel. When touch starts we will check after some interval if touchend event is fired or not. If there is no touch event fired that means user is still holding tap. See the code below.

{
      xtype: 'panel',
      html: 'tap and hold',
     listeners: {
                            painted: function(element){
                            var isTouch = false;
                            element.on({
                            touchstart: function(){
                            isTouch = true;
                            setTimeout(function(){
                            if(isTouch == true){
                                 //There is a tap hold
                            }
                            }, 2000);
                            },
                            touchend: function(){
                            isTouch = false;
                            }
                            });
                            }
                            }
}

As you can see in above code after touch start event we are setting timeout to check isTouch variable after two seconds. You can change the interval according to your need. If touch ends before two seconds we set isTouch to false. So after timeout when this variable is checked you will get false and tap hold event is not fired.  This way you can add tap hold event to any of the sencha touch component.



Monday, March 10, 2014

Sencha Touch List Find Top Visible Item Index

Recently in one of my project we have a Sencha Touch list and top banner. Each list item have certain banner text to show. When user scrolls up or down we have to show the banner text of list item which is on top position in the top banner panel. It should change as user moves up or down.  For that we have to find top visible item index or record of list. So here is my logic for that. 

As we know that all the list item have certain fix height that we can specify with itemHeight config. Each list is scrollable with scroll view. We can simply calculate top visible item by dividing y offset of scrollview with item height of the list. This will give us top visible item index. Here is the logic to do that. Add reference of your list to controller and bind initialize event of the list.

myList:{
                initialize: 'onMyListInit'
 },

No we will bind scroll event to this list scroller.

onMyListInit: function(list){
          var listItemHeight = 53;
          var scroller = list.getScrollable().getScroller();
          scroller.on({
            scroll: function(scroller, x, y, e){
                          var currentVisibleItemOnTopIndex = parseInt(y/listItemHeight);
                }
          });
}

This logic will give us top visible item index. You can find record from index using getAt method of list store. In my case I get the record and use it's banner text to display on top banner above the list. It keeps changing as you scroll up or down the list. Please note that this trick will only work if you have simple list with fixed height of the item. If you have variable heights or group list.  This trick will not work. As in group list we have items arranged in groups so their indexes changed. We might have to find some other solution for that. If you have any idea post a comment.

Friday, March 7, 2014

Sencha Touch List Expand and Collapse All Items

Recently in one of our Sencha Touch project we have a requirement to have expand and collapse all button on top of like to expand and collapse all the items of the list. Here is how we implemented it.

First add events of the buttons to your controller.

btnExpandAll: {
        tap: 'expandAll'
      },
btnCollapseAll: {
         tap: 'collapseAll'
        }

Now add above two functions in controller.

expandAll: function(){
    var list = this.getItemsList();
    var items = list.getViewItems();
        var itemsLn = items.length;
        for (i = 0; i < itemsLn; i++) {
            item = items[i];
            Ext.Animator.run({
element: item.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: 60
},
to: {
height: 190
}
});
        }
    }

collapseAll: function(){
    var list = this.getItemsList();
    var items = list.getViewItems();
        var itemsLn = items.length;
        for (i = 0; i < itemsLn; i++) {
            item = items[i];
            Ext.Animator.run({
element: item.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: 190
},
to: {
height: 60
}
});
        }
    }

You can set your own from and to height according to your requirement.


Wednesday, March 5, 2014

Sencha Touch List, Different background colors for Group Header

Recently in one of my project we have a Sencha Touch list with grouped headers. We know that we can control group header styles by CSS or we can change it by overriding base css class. In this case we will have one same color for each group header, while in my case the requirement was to have different background colors for each group header. This blog is about how how I implement it, you may have better idea. Feel free to comment.

Here I added background color in each items of the list and then grouped it based in certain field. For example.

Ext.define('MyApp.model.MyModel', {
    extend: 'Ext.data.Model',
    config:{
        fields: [
            { name:'id', type:'int'},
            { name:'group_background_color', type:'string'},
            { name:'item_name', type:'auto'},
            { name: 'group', type: 'string'}
        ]
    }
})

Then we have following Store definition.

Ext.define('MyApp.store.MyStore', {
    extend: 'Ext.data.Store',
    config: {
        model: 'MyApp.model.MyModel',
        autoLoad: true,
        grouper: {
        groupFn: function (item) {
            return item.get('group');
            }
        },
        proxy: {
            type:'ajax',
            actionMethods:{
                read: 'POST'
            },
            url:'items.json',
            reader:{
                type:'json',
                rootProperty:'items'
            }
        }
    }
});

Now we have our list where we will show this data.

{
        xtype: 'list',
        id:'myList',
itemId:'myList',
scrollable: true,
grouped: true,
itemTpl:'<div>{item_name}</div>' ,
        store: 'MyStore'
}

This will create list with groups and group header. If you use default Sencha Theme the group header will have blue as background color. We have to change it to our colors dynamically. For that we will update on list refresh. List refresh event is fired when list is visible first time and there is some change in data in store or list store is loaded. Add refresh event in controller.

control:{
            '#myList':{
                refresh: 'refreshListHeaders'
            }
}

And here is the function.

refreshListHeaders: function(list){
    if(list.groups){
    var groupElements  = document.getElementsByClassName('x-list-header');
    for(var i=0;i < groupElements.length i++){     
       var firstChild = list.groups[i].children[0];
    var backGroundColor = firstChild.data.banner_background_color;
    groupElements[i+1].style.setProperty('background-color', backGroundColor, '!important');
    }
    }
    }

So our logic is very simple. We get all the elements with class name "x-list-header" . That gives us all the header elements.  Now for each group we are getting background color from the first item of the group and set it as background color to group header.

Friday, February 28, 2014

JavaScript Simulate Touch Events on Phone to Mouse Events

Have you ever faced an issue that some of the JavaScript code for handling touch events  does not work on phone?

For example take an example of jQuery draggable. when you test it it does not work in mobile browser. The reason is, it binds and tracks mouse events while phone we don't have mouse events but we have touch events and that's why jQuery draggable will not work. Same way if you have some other old JavaScript framework which may not work on phone because of this issue. What if you have to use that framework or code and you can not change it because it's minified files? Here in this blog we will explain the solution for it. Basically we will simulate touch events to mouse events so this types of code works.

We will convert

touchstart => mousedown
touchmove => mousemove
touchend => mouseup

Check the following code.

function touchToMouseHandler(event) {
var touch = event.changedTouches[0];

var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent({
touchstart: "mousedown",
touchmove: "mousemove",
touchend: "mouseup"
}[event.type], true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);

touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}

function initHandlers() {
document.addEventListener("touchstart", touchToMouseHandler, true);
document.addEventListener("touchmove", touchToMouseHandler, true);
document.addEventListener("touchend", touchToMouseHandler, true);
document.addEventListener("touchcancel", touchToMouseHandler, true);
}


So here initHandlers function will add listers to touch events and function touchToMouseHandler will convert touch events to mouse events and simulate the action. Above code you can out in JS file on script tag in your html file and call the initHandlers function. With this above code you can use code with mouse events on phone browsers. Hope this helps you.

Sencha Touch List Accordion Layout (Expand and Collapse Sencha Touch List Item)

Hello,

Recently I was working on a project where we have a requirement to have accordion layout in Sencha Touch List items. Basically there are few items in list and user should be able to expand and collapse it by taping in respective list item. In this blog, we will see how to implement it.  First set fix item height for the list. For example,

{
       xtype: 'list',
       itemId: 'itemsList',
       id: 'itemsList',
       store: 'Items',
       itemHeight: 30,
       itemTpl:'<div style="overflow:hidden">Touch me to Expand Item {itemName}'+
                           '<div>'+
                                  '{itemDescription}'
                           '</div>'+
                    '</div>'
}

As you see in above code we have set height of item to 30 and set overflow to hidden so now you can have big texts as item description that will not be visible completely in collapsed mode. Now we have to add tap event for list in controller.

control: {
        '#itemsList': {
        itemtap: 'expandCollapseItemView'
        }
        }
And the function expandCollapseItemView in your controller.

expandCollapseItemView: function(list, index, target, record, event){
        var fromHeight = 0;
    var toHeight = 0;
    if(target.element.dom.clientHeight <= 30){
    fromHeight = 30;
    toHeight = 100;
     }else{
    fromHeight = 100;
    toHeight = 30;
     }
    Ext.Animator.run({
element: target.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: fromHeight
},
to: {
height: toHeight
}
});
}

So if you check the above code we are identifying if we have expand or collapse based on client height of the item with the property target.element.dom.clientHeight. If height is less then or equal to 30 which is our item height for the list, we will expand the list item. After expanding list item the height will be 100 next time we will get clientHeight as 100 so we will collapse it to 30.

And we are running the animation with Ext.Animator.run and setting height from small to big or big to small.

With this you have expandable and collapsible list items.