Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Saturday, January 24, 2015

Callback Function After Angular Finished Data Binding

Introduction:
This article mainly focuses on a solution of a common problem that usually being faced doing projects with angular and other JavaScript Frameworks. It's recommended that a basic knowledge of Angular data binding and directive is required for reading this article. A demo application is also created to help understand the solution more in detail.

Problem:
Often we need to bind different JavaScript events or initialize Jquery plugin after ng-bind-html or ng-repeat finished binding. As most of the time the data is retrieved from AJAX call so it's hard to estimate exact time when the DOM will be ready to bind those events or initialize plugins for new loaded element. One very common example would be, when we make a custom dynamic menu where data are bound using ng-repeat and jQuery is used to make all the animation. So the jQuery function, which contains the animation code, must call after data loaded successfully and angular completed binding all the DOM elements.

Solution:
We can solve this problem by creating a custom directive and send a callback function to that directive. For ng-repeat the directive will check whether scope's last object has completed binding and after that it will call the given callback function. Now for ng-html-bind it will watch scope’s htmlElement has any value and when it will see a value, it will call the given callback function. So here is a generic directive that will work for both ng-repeat and ng-html-bind:

app.directive('ngcDone', function ($timeout) {
    return function (scope, element, attrs) {
        scope.$watch(attrs.ngcDone, function (callback) {

            if (scope.$last === undefined) {
                scope.$watch('htmlElement', function () {
                    if (scope.htmlElement !== undefined) {
                        $timeout(eval(callback), 1);
                    }
                });
            }

            if (scope.$last) {
                eval(callback)();
            }
        });
    }
});

Let me give a short description of what is happening here. But before that it is important to know what is directive.

Directives are markers of DOM element which allow you to play with that specific DOM element.

Here we have created a custom directive name ngc-done and sending a callback function as string. The reason for sending it as string is just to make this directive a generic one. Like here if we want call a function which is define under scope then we can give it like ‘scope.YourFunction’.


We’ve used $watch inside the directive’s definition to track changes of our directive. $watch is a great feature of Angular and it takes two parameters. One is the object or property that we like to watch or track changes and another is a listener which will be called if any change is detected. Now we have used two $watch here. One is to track change of our directive and another is to track change of scope’s htmlElement if $last is undefined.

Now the $last is a property of scope which is related to ng-repeat and it’s a Boolean type and it will return true here if ng-repeat has finished binding the last value or object.  $last will return undefined if there is no ng-repeat in the DOM element. If this directive is used in the same element where ng-html-bind is used then $last will be undefined and then it will start watching scope’s htmlElement. If htmlElement is not undefined then directive will invoke the given callback function.

Using the Code:
It is recommended to download the source and there are three examples showing how to use this directive. 2 examples showing how to bind dynamic jQuery menu plugin, one with ng-repeat and another with a ng-html-bind and another example shows how to bind 2 lists and call callback function after it finished binding. The menu plugin that we've used here is available for purchase at CodeCanyon.

Referrences:


Saturday, April 6, 2013

Metro UI Alert Message using Asp.Net User Control & jQuery

Download Source Files (version 1.1)
View Live Demo 


Introduction
In our websites we show different alert messages for different purposes. Some very common alert messages are “Invalid Username or Password”, “Item inserted successfully”, “Thank you for contacting us. We will get back to you soon” or sometimes we show exception messages as well. These messages are usually shown in alert boxes or sometimes in different places on the website. In big projects we have to show numerous numbers of alert messages. Sometimes it is difficult to manage all messages and we use different type of messages for same purpose. In this article I am going to talk about how we can show different alert messages and manage all messages from one place.

Click here to View Demo
















Let's Start 
First let us create a Class to store all the messages. Right click on your project and add a new Class name Message.

Adding Message.cs file

This Class will have an Enum for type of message and another nested Class to store all the text messages. A namespace is given so that we can access the Class from anywhere using this namespace.

namespace Helper
{
    public static class Message
    {
        public enum Type
        {
            success, error, info

        };

        public static class Text
        {
            public const string START_INFO = "Click on the buttons to show different messages. This message will automatically hide after 10 seconds.";

            public const string SUCCESS_SERVER = "This is a Success message from Server Side.";
            public const string ERROR_SERVER = "This is an Error message from Server Side.";
            public const string INFO_SERVER = "This is a general Info message from Server Side.";

            public const string SUCCESS_CLIENT = "This is a Success message from  Client Side.";
            public const string ERROR_CLIENT = "This is an Error message from Client Side.";
            public const string INFO_CLIENT = "This is an Info message from Client Side. This is used for general purpose.";
        }
    }
}


Now let us take a user control to show the messages. Again right click on your project and add a new User Control. Let’s name it Message as well.

Adding Message.ascx file






















Now our target is to create a message box with different color which will animate from right side of the screen. The message box will show our given text and depending on message type it will show in different color. After certain time it will automatically animate outside our screen.
Let’s take a HTML div to create the box and another nested div to show message.

<div id="divMessageBody" class="message-box">
    <a class="close-btn" onclick="HideMessage();">x</a>
    <div id="divMessage" class="message"></div>
</div>

Here is CSS code:

.message-box {
    width: 270px;
    display: inline;
    height: auto;
    padding: 30px 20px;
    position: fixed;
    right: -320px;
    top: 40px;
    font-size: 15px;
    color: #fff;
}

.close-btn {
    position: absolute;
    right: 6px;
    top: 0;
    cursor: pointer;
}

    .close-btn:hover {
        opacity: 0.7;

        -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
        filter: alpha(opacity=70);
    }

.message {
    width: 100%;
}

.success {
    background-color: #72A101;
    border: 2px solid #4d6d01;
}

.error {
    background-color: #d04a01;
    border: 2px solid #983600;
}

.info {
    background-color: #0285c2;
    border: 2px solid #00577f;
}


Here we will give success, error or info class to divMessageBody depending on which type of message we want to show. This classes will show different color for different messages. To add this class we've created an Enum named Type in our Message.cs class. We will send this Enum value as string to this div as css class. Another thing is we give the message-box class’s position fixed so that it will not break our website’s UI structure. Also this message box supports all the modern browser including ie7 and above.

Now let us create two JavaScript function, ShowMessage and  HideMessage. ShowMessage will take two parameter which are message and type. This function will insert message into divMessage and add type to divMessageBody as CSS class. Here is the code for both ShowMessage and HideMessage.

<script type="text/javascript">
    var msgBoxTimeout;
    var timeToShow = 10000;
    var msgBoxRight = -320;

    function ShowMessage(msg, type) {
        clearInterval(msgBoxTimeout);
        $("#divMessageBody").css("right", msgBoxRight);

        var classAttr = "message-box " + type;
        $("#divMessage").html(msg);
        $("#divMessageBody").attr("class", classAttr);

        $("#divMessageBody").stop().animate({
            right: "0px"
        }, 700, "easeInOutCirc");

        msgBoxTimeout = setTimeout(function () {
            HideMessage();
        }, timeToShow);
    }

    function HideMessage() {
        $("#divMessageBody").stop().animate({
            right: msgBoxRight
        }, 900, "easeInOutCirc");

        clearInterval(msgBoxTimeout);
    }
</script>


Here we've used jQuery animate function to animate our message box. We also used easing effect for beautiful and smooth animation . If you want to use easing effect make sure you've added jquery.easing.js or jqery.custom.ui.js in your webpage. Also if you don’t want to use easing effect then remove easeInOutCirc from jquery animate function.

Now let’s create a ShowMessage function for server side code. This function will call the javascript ShowMessage function with a message and type. 

public void ShowMessage(string msg, string type)
{
        Page.ClientScript.RegisterStartupScript(GetType(), "Script", "<script type=\"text/javascript\">ShowMessage(\"" + msg + "\",\"" + type + "\");</script>");
}

Now call this function from both server side and client side.

Server Side: 

protected void btnSuccess_Click(object sender, EventArgs e)
{
        ucMessage.ShowMessage(Message.Text.SUCCESS_SERVER, Message.Type.success.ToString());

}

Client Side:

<input type="button" value="Success" class="btn btn-success" onclick="ShowMessage('<%= Helper.Message.Text.SUCCESS_CLIENT %>    ','<%= Helper.Message.Type.success %>');" />

How to Integrate Quickly ? 
You can directly use this user control in your project. Just download the file and add the user control Message.ascx in your project. Also add required CSS from layout.css and add Message.cs file from App_Code folder. If you want to add more messages then add them in Message.cs file’s Text Class. Also if you want to add new type add it in the Type Enum and create css class of that same name in your CSS file. For example if you want to add a new type exception then first add a new value on the Type Enum.

public enum Type
{
      success, error, info, exception
};


Then add an exception class in you CSS file.

.exception {
    background-color: #a8a8a9;
    border: 2px solid #696969;
}


Now you can call the exception type from anywhere with your exception message.

ucMessage.ShowMessage(ex.Message, Message.Type.exception.ToString());

Conclusion
Now a days it is very important to make user friendly environment. Most users are attracted to the websites with beautiful user experience. So it is important to show different alert messages in such a way so that users don’t get confused or disturbed.  I hope this article will help you to let user know what you want to inform them. Good luck :)

Thursday, December 13, 2012

Binding Metro UI Tiles with Knockout.js

Download Source Files
View Live Demo


Introduction
Knockout is a JavaScript library which dynamically binds data between different html contents and follow Model-View-View-Model (MVVM) design pattern.  It’s one of the core feature is Observable, which can detect changes in the view model and updates the model according to that change. It’s a special JavaScript object that can detect dependencies among controls automatically. In this article we will mostly use observable to bind controls and update data dynamically.

Problem
Consider a metro tile where each tile has a title and description. It has a background color as well. There can be multiple tiles of same type. Our target is to create tiles dynamically and with every tile there would be an edit panel where user can edit its title, description and background color. If you are confused about this scenario then I recommend you to view demo first.

Solution
One of the main features of Knockout is, it can track each element of UI and can update automatically. We will use this feature to bind our metro tiles with its edit panel and when user will change in edit panel, tiles of that panel will change automatically. Knockout will track edit panel with its correspondent tile. For this, first we have to take a javascript object where all the property of a metro tile is defined. Here we have title, description and color as an observable. This observable will detect depedencies between each tile and its edit panel and it will keep each tile object updated automatically. Here is a how Tile object looks: 

var Tile = function (title, description, color) {
     var self = this;
     self.title = ko.observable(title);
     self.description = ko.observable(description);
     self.tileColor = ko.observable(color);
     self.editPanel = ko.observable(false);
     self.expandEdit = function () {
          self.editPanel(true);
     };
     self.collapseEdit = function () {
          self.editPanel(false);
     };

}; 

Another additional observable is taken named editPanel which will detect visibility of its tile’s edit panel. expandEdit and collapsEdit will make editPanel true or false on click event. Here ObservableArray is taken to store all tiles. addTile and removeTile functions will add new tile on the view and remove tile will delete its corresponding tile from the view and from the observableArray as well. 

var TileModel = function () {
     var self = this;
     self.lines = ko.observableArray([
           new Tile("Batman", "The Dark Night Rises", "#525252"), 
           new Tile("Transformer", "Revenge of the Fallen", "#DA532C")
     ]);
     self.addTile = function () {
          self.lines.push(new Tile("Title", "Description", RandomColor()))
     };
     self.removeTile = function (line) { 
          self.lines.remove(line) };
     };
ko.applyBindings(new TileModel()); 

Also two tiles are pushed into the array on load and observable will bind them with the HTML control automatically. Then finally we’ve bind the full model with Knockout with ko.applyBindings().
Now let’s take a look at HTML controls which are bind with observable object:

<a id="aCreate" class="btn-add-tile" data-bind='click: addTile'>Add Tile</a>
<div class="tile-container" data-bind='foreach: lines'>
     <div class="tile-area">
          <div class="tile-elem" data-bind="style: { background: tileColor }">
               <p class="tile-description" data-bind="text: description"></p>
          </div>
          <span class="tile-title" data-bind="text: title" style=""></span>
          <div class="bottom-bar">
               <span class="arrow" data-bind='click: expandEdit, ifnot:editPanel'>
                    <img src="Styles/images/MetroDown.png" alt="Open edit panel" /></span>
               <span class="arrow" data-bind='click: collapseEdit, if:editPanel'>
                    <img src="Styles/images/MetroUp.png" alt="Close edit panel" /></span>
               <span class="close-btn" data-bind='click: $parent.removeTile'>
                    <img src="Styles/images/MetroClose.png" alt="Remove tile" /></span>
          </div>
          <div data-bind="if: editPanel">
               <div class="edit-panel">
                    <label>Title:</label>
                    <input class="text-title" data-bind="value: title, valueUpdate: 'afterkeydown'" maxlength="12" />
                    <label>Description:</label>
                    <textarea class="txtdesc" rows="2" data-bind="value: description, valueUpdate: 'afterkeydown'"></textarea>
               </div>
          </div>
     </div>
</div>

Here Knockout will search for data-bind attribute to bind data with its model. Now on clicking Add Tile button we are calling addTile function from TileModel which adds a new object to lines. With foreach, Knockout is generating all the tile object stored in lines with a loop. Every time a tile is added or removed, it tracks the changes in the model and bind tiles dynamically. Now edit panel’s <textarea> is bind with <p> of tile element with description object. <p> is updated when <textarea> has an input character. We are updating the description object after key down. Title will update same way like description. So the main thing is all the observables track dependencies among the HTML controls and it updates automatically.

Why Knockout? 
Situation like this, where we have to bind data dynamically and need to track all the dependencies among controls, then Knockout is best choice. We will bind observable with UI controls and observable will notify about changes and it will update automatically. Another good feature is, it can update data very frequently, like when we bind afterkeydown method, observable detects change and update correspondent element at that moment. 

Run Source Code 
Download the zip file, extract it, open KnockoutTiles.sln file and hit F5. It’s a Asp.Net web project written in Visual Studio 2012 and used knockout.js version 2.2.0.

Conclusion 
Knockout follows MVVM pattern where observable track dependencies between model and view model and update view automatically. This article gives a very basic idea on observable. I recommend to download the source file and see for yourself how it actually works.