Tuesday, February 3, 2009

Dynamically create and remove TabPanel on client

TabContainer provides some method to create/remove TabPanel on server-side. However, we want to achieve this on client and needn't to do postback to server.
For example, we can build a button on the page so that it can create a tabpanel on client-side when you click it. The data in this dynamic tabpanel can be static existing in the page, or can be recieved from web service by Ajax. Then we can create a closed-button in each tabpanel header.

The following code can help you to achieve creating TabPanel on client on the fly.

<script type="text/javascript">
    var i = 3;
    function createnew() {

        CreateNewTabPanel('TabContainer1', 'TabPanel' + i, 'TabPanel' + i, 'TabPanel' + i);
        i++;

    
    }

    function CreateNewTabPanel(tabContainerID, tabPanelID, headerText, bodyText) {
        //create header
        var header = document.createElement('span');
        header.id = "__tab_" + tabContainerID + tabPanelID;
        header.innerHTML = headerText;
        $get(tabContainerID + "_header").appendChild(header);

        //create content
        var body = document.createElement('div');
        body.id = tabContainerID + "_" + tabPanelID;
        body.style.display = "none";
        body.style.visibility = "hidden";
        body.innerHTML = bodyText;
        body.cssClass = "ajax__tab_panel";
        $get(tabContainerID + "_body").appendChild(body);


        $create(AjaxControlToolkit.TabPanel, { "headerTab": $get(header.id) }, null, { "owner": tabContainerID }, $get(body.id));


    }


</script>
<body>
    <form id="form1" runat="server">
    <ajaxToolkit:ToolkitScriptManager runat="Server" EnablePartialRendering="true" ID="ScriptManager1" />
<span id="mes"></span><br />
<span id="mes1"></span>
    <ajaxToolkit:TabContainer runat="server" ID="TabContainer1"   >
            <ajaxToolkit:TabPanel runat="server" ID="TabPanel1" HeaderText="TabPanel1">
                <HeaderTemplate>
                    TabPanel1
                </HeaderTemplate>
            <ContentTemplate>  
                TabPanel1     
            </ContentTemplate>
        </ajaxToolkit:TabPanel> 
                    <ajaxToolkit:TabPanel runat="server" ID="TabPanel2" HeaderText="TabPanel2">
            <ContentTemplate>  
                TabPanel2     
            </ContentTemplate>
        </ajaxToolkit:TabPanel>             
    </ajaxToolkit:TabContainer>

    <input type="button" onclick="createnew()" value="create a new pane" />

    </form>
</body>



To remove the related TabPanel on client dynamically, please check the code as below:


<script type="text/javascript">
    function removeAt(tabPanelClientID,index) {

        var activeTabPanel = $find('<%=TabContainer1.ClientID%>').get_tabs()[index];

        var tabContainerID = "<%=TabContainer1.ClientID %>";

        $get(tabContainerID + "_header").removeChild($get(tabPanelClientID+"_tab"));

        $get(tabContainerID + "_body").removeChild($get(tabPanelClientID));

        activeTabPanel.dispose();

        $find('<%=TabContainer1.ClientID%>').set_activeTabIndex(index+1);
    }


</script>

<body>
    <form id="form1" runat="server">
    <input type="image" style="height: 14px; width: 14px" onclick="removeAt(this.alt);return false;"
        alt="0" src="../../../effect/PopupDiv-roundCorner/images/close.gif" />
    <ajaxToolkit:ToolkitScriptManager runat="Server" EnablePartialRendering="true" ID="ScriptManager1" />
    <ajaxToolkit:TabContainer runat="server" ID="TabContainer1">
        <ajaxToolkit:TabPanel runat="server" ID="TabPanel1">
            <HeaderTemplate>
                headertext0
                <input type="image" style="height: 14px; width: 14px" onclick="removeAt('<%=TabPanel1.ClientID %>',0);return false;"
                    alt="0" src="../../../effect/PopupDiv-roundCorner/images/close.gif" />
            </HeaderTemplate>
            <ContentTemplate>
                TabPanel1
            </ContentTemplate>
        </ajaxToolkit:TabPanel>
        <ajaxToolkit:TabPanel runat="server" ID="TabPanel2">
            <HeaderTemplate>
                headertext1
                <input type="image" style="height: 14px; width: 14px" onclick="removeAt('<%=TabPanel2.ClientID %>',1);return false;"
                    alt="1" src="../../../effect/PopupDiv-roundCorner/images/close.gif" />
            </HeaderTemplate>
            <ContentTemplate>
                TabPanel2
            </ContentTemplate>
        </ajaxToolkit:TabPanel>
        <ajaxToolkit:TabPanel runat="server" ID="TabPanel3">
            <HeaderTemplate>
                headertext2
                <input type="image" style="height: 14px; width: 14px" onclick="removeAt('<%=TabPanel3.ClientID %>',2);return false;"
                    alt="2" src="../../../effect/PopupDiv-roundCorner/images/close.gif" />
            </HeaderTemplate>
            <ContentTemplate>
                TabPanel3
            </ContentTemplate>
        </ajaxToolkit:TabPanel>
    </ajaxToolkit:TabContainer>
    </form>
</body>

Thursday, January 22, 2009

Custom AutoComplete 5: Build an additional row on the top of AutoComplete List

Before anything, please check this(http://www.globrix.com/):



We know we can customize AutoComplete. In this image, we can achieve the red background, Font style and seting some shining picture as the background. But one thing we need to notice is that there is an arrowhead on the top of row. So we have to make an additional row for it. And this row is not an item in the list; mouse event should be unavailable here.

Let code speak anything:

In this sample, you can define autocomplete_firstRow css style. In this case, you can define a background image in firstrow.


.autocomplete_firstrow
{
background-color:Red;
height:20px;


}



After you create an AutoComplete on the page, the below JavaScript will be worked of it. It will create an addition row on the top of AutoComplete. Suppose that the behaviorID of AutoComplete is "AutoCompleteEx".

<script type="text/javascript">


        function ClientPopulated() {
            var comletionList = $find("AutoCompleteEx").get_completionList();
           



            var firstrow=document.createElement("div");
            firstrow.id="firstrow";
            firstrow.className = "autocomplete_firstrow";

            comletionList.insertBefore(firstrow, comletionList.firstChild);
  



        }

       

        function pageLoad() {
            var autoc = $find("AutoCompleteEx");
//redefine highlightitem function
            autoc._highlightItem = function(item) {

                var children = autoc._completionListElement.childNodes;
                if (item === children[0])
                    return;

                for (var i = 0; i < children.length; i++) {
                    var child = children[i];
                    if (child._highlighted) {
                        if (autoc._completionListItemCssClass) {
                            Sys.UI.DomElement.removeCssClass(child, autoc._highlightedItemCssClass);
                            Sys.UI.DomElement.addCssClass(child, autoc._completionListItemCssClass);
                        } else {
                            if (Sys.Browser.agent === Sys.Browser.Safari) {
                                child.style.backgroundColor = 'white';
                                child.style.color = 'black';
                            } else {
                                child.style.backgroundColor = autoc._textBackground;
                                child.style.color = autoc._textColor;
                            }
                        }
                        autoc.raiseItemOut(new AjaxControlToolkit.AutoCompleteItemEventArgs(child, child.firstChild.nodeValue, child._value));
                    }
                }

                // Highlight the new item
                if (this._highlightedItemCssClass) {
                    Sys.UI.DomElement.removeCssClass(item, this._completionListItemCssClass);
                    Sys.UI.DomElement.addCssClass(item, this._highlightedItemCssClass);
                } else {
                    if (Sys.Browser.agent === Sys.Browser.Safari) {
                        item.style.backgroundColor = 'lemonchiffon';
                    } else {
                        item.style.backgroundColor = 'highlight';
                        item.style.color = 'highlighttext';
                    }

                }
                item._highlighted = true;

                this.raiseItemOver(new AjaxControlToolkit.AutoCompleteItemEventArgs(item, item.firstChild.nodeValue, item._value));


            };

//redefine settext function
            autoc._setText = function(item) {
            var children = autoc._completionListElement.childNodes;
                if (item === children[0])
                    return;
                var text = (item && item.firstChild) ? item.firstChild.nodeValue : null;

                autoc._timer.set_enabled(false);

                var element = autoc.get_element();
                var control = element.control;
                if (control && control.set_text) {
                    control.set_text(text);
                    $common.tryFireEvent(control, "change");
                }
                else {
                    element.value = text;
                    $common.tryFireEvent(element, "change");
                }
                autoc.raiseItemSelected(new AjaxControlToolkit.AutoCompleteItemEventArgs(item, text, item ? item._value : null));

                autoc._currentPrefix = autoc._currentCompletionWord();
                autoc._hideCompletionList();
            };

      }
       


    </script>

Custom AutoComplete 6: MultiColumn Autocomplete(Mutiple columns message for each Item)

Hello all, I made "Mutiple rows message for each Item" several months ago. Now I'd like to build a MultiColumn Autocomplete. They applies same principle, so it's not a trouble if you checked previous post.

Here is the code in aspx:

<head runat="server">
    <title></title>
    <link href="../Default.css" rel="stylesheet" type="text/css" />
    <style>
    .cloumnspan
    {
        width:35px;
        padding:0px;
        border-color:Black;
        border-style:solid;
        border-width:1px;

    }
   
    </style>
</head>
<body>
    <form id="form1"  runat="server">
        <ajaxToolkit:ToolkitScriptManager runat="server" ID="ScriptManager1" />

           <asp:TextBox runat="server" ID="myTextBox" Width="300" autocomplete="off" />
            <ajaxToolkit:AutoCompleteExtender
                runat="server"  OnClientPopulated="dd" OnClientItemSelected="itemSelected"
                BehaviorID="AutoCompleteEx"
                ID="autoComplete1"
                TargetControlID="myTextBox"
                ServicePath="AutoComplete.asmx"
                ServiceMethod="GetCompletionList5"
                MinimumPrefixLength="2"
                CompletionInterval="1000"
                EnableCaching="true"
                CompletionSetCount="8"
                CompletionListCssClass="autocomplete_completionListElement"
                CompletionListItemCssClass="autocomplete_listItem"
                CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
                DelimiterCharacters=";, :">
            </ajaxToolkit:AutoCompleteExtender>

    </form>
    <script type="text/javascript">
function itemSelected(ev)
{
    var index=$find("AutoCompleteEx")._selectIndex;
    var value=$find("AutoCompleteEx").get_completionList().childNodes[index]._value;
    $find("AutoCompleteEx").get_element().value = value;
}
function dd()
{
    var comletionList=$find("AutoCompleteEx").get_completionList();
    for(i=0;i<comletionList.childNodes.length;i++) {
        var itemobj=new Object();
        var _data = comletionList.childNodes[i]._value;
        itemobj.name= _data.substring(_data.lastIndexOf('|') + 1); // parse name as item value
        comletionList.childNodes[i]._value = itemobj.name;
        _data = _data.substring(0, _data.lastIndexOf('|'));
        itemobj.age = _data.substring(_data.lastIndexOf('|') + 1);
        _data = _data.substring(0, _data.lastIndexOf('|'));
        itemobj.id = _data.substring(_data.lastIndexOf('|') + 1);


        comletionList.childNodes[i].innerHTML = "<div class='cloumnspan' style='width:10%;float:left'>" + itemobj.id + "</div>"
                                              + "<div class='cloumnspan' style='width:70%;float:left'>" + itemobj.name + "</div>"
                                              + "<div class='cloumnspan' style='width:18%;'>" + itemobj.age + "</div>";

    }
   
}



</script>
</body>



Web Method:

[WebMethod]
public string[] GetCompletionList5(string prefixText, int count)
{

    if (count == 0)
    {
        count = 10;
    }

    if (prefixText.Equals("xyz"))
    {
        return new string[0];
    }

    Random random = new Random();
    List<string> items = new List<string>(count);

    for (int i = 0; i < count; i++)
    {

        char c1 = (char)random.Next(65, 90);
        char c2 = (char)random.Next(97, 122);
        char c3 = (char)random.Next(97, 122);
        int id = i;
        int age = random.Next(18, 70);
        items.Add(id.ToString() + "|" + age.ToString() + "|" + prefixText + c1 + c2 + c3);
    }

    return items.ToArray();
}


If you want to add a header for MutiColumn table, you should add an additional row/div at the top of complete list. Please check this: http://vincexu.blogspot.com/2009/01/custom-autocomplete-5-build-additional.html

Wednesday, January 21, 2009

Create a Vertical Tab

In this post, if you are familiar with Css Style and JavaScript, it should not be a difficult thing for you.

This time let's hit to create a Vertical Tab like the tab control in http://www.microsoft.com/. Have you seen the bottom tab content navigation in Microsoft home page http://www.microsoft.com/?

If you used TabContainer before, you must have thought it is really a vertical TabContainer. Now, we get to start from Zero, to create one by css and JavaScript.



See the line in the left section of image, it seems to be faded out and it's like a tail to the end. To achieve this, we have to prepare several images for it. The rest things are simple. (Just create some div in related sections)

Check the below code:

HTML:

<head runat="server">
    <title></title>
    <link href="AutoReport.css" rel="stylesheet" type="text/css" />

    <script src="AutoReport.js" type="text/javascript"></script>

</head>
<body>
    <form id="form1" runat="server">
    <div id="divAdmin">
        <div id="divAdmin_Content">
            <div id="divAdmin_LeftMenu">
                <div id="li-toptail">
                </div>
                <div id="liManager_User" onmouseover="HighLight_Li('liManager_User','liAdd_User','divManager_User','divAdd_User');">
                    Member</div>
                <div id="liAdd_User" onmouseover="HighLight_Li('liAdd_User','liManager_User','divAdd_User','divManager_User');">
                    Add User</div>
                <div class="li">
                </div>
                <div class="li">
                </div>
                <div class="li">
                </div>
                <div class="li">
                </div>
                <div class="li">
                </div>
                <div id="li-bottomtail">
                </div>
            </div>
            <div id="divAdmin_RightView">
                <div id="divManager_User">this is panel1
                </div>
                <div id="divAdd_User">this is panel2
                </div>
            </div>
        </div>
    </div>
    </form>
</body>


AutoReport.css

body
{
    /*font-family: "Trebuchet MS", Verdana, Tahoma, sans-serif;*/
    font-family:Tahoma,Verdana,Segoe,sans-serif;
    font-size: 12px;
    text-align: center;

    color: #666;

}
/*Admin*/
#divAdmin
{
    width: 550px;
}

#divAdmin_Header
{
    padding: 5px;
    background: url(Images/sprite.png) repeat-x 0px 0px;
    height: 22px;
    border: thin solid #D6D6C0;
    text-align: right;
    color: #666666;
}

#divAdmin_Content
{

}

#divAdmin_LeftMenu
{
    float:left;
    height: 350px;
    width: 86px;
    background-image: url('Images/leftmenu.png');
   
    border-left-width: thin;
    border-left-style: solid;
    border-left-color: #CFCFCF;
    border-bottom-style: solid;
    border-bottom-width: thin;
    border-bottom-color: #CFCFCF;
}

#divAdmin_RightView
{
    float: left;
    background-color: #EEEEEE;
    width: 460px;
    height: 350px;
    border-right-width: thin;
    border-right-style: solid;
    border-right-color: #CFCFCF;
    border-bottom-style: solid;
    border-bottom-width: thin;
    border-bottom-color: #CFCFCF;
}
.li
{
    height: 30px;
    width: 86px;
    background-image: url('Images/leftmenu-line.png') ;
}
#li-toptail
{
    background-image: url('Images/leftmenu-toptail.png') ;
    height: 30px;
    list-style-type:none;
    width: 86px;
   
}
#li-bottomtail
{
    background-image: url('Images/leftmenu-bottomtail.png') ;
    height: 30px;
    list-style-type:none;
    width: 86px;
   
}
#divManager_User
{
    padding-left:80px;
    display:block;
    text-align:left;
    padding-top: 5px;
}
#divAdd_User
{
    padding-left:80px;
    display:none;
    text-align:left;
    padding-top: 5px;
           
}
#liManager_User
{
    background-image: url('Images/leftmenu-litail.png') ;
    height: 30px;
    list-style-type:none;
    width: 86px;
}
#liAdd_User
{
    background-image: url(Images/leftmenu-line.png) ;
    height: 30px;
    list-style-type:none;
    width: 86px;
}


AutoReport.js

/*leftmenu onmouseover*/
function HighLight_Li(HighLight_Li,LowLight_Li,Display_div,Hidden_div)
{
    document.getElementById(HighLight_Li).style.backgroundImage='url(Images/leftmenu-litail.png)';
    document.getElementById(LowLight_Li).style.backgroundImage='url(Images/leftmenu-line.png)';
    document.getElementById(Display_div).style.display='block';
    document.getElementById(Hidden_div).style.display='none';
}




Several images need to download, and please put them in Image folder:
leftmenu-toptail.png


leftmenu-litail.png



leftmenu-line.png


leftmenu-bottomtail.png




leftmenu.png



sprite.png

Friday, December 26, 2008

Conditionally display ConfirmButtonExtender

ConfirmButtonExtender is a nice way to build a kindly ModalPopup ConfirmPanel. Sometimes, we hope to show ConfirmButtonExtender only if it satisfies certain conditions, rather than it's popped out once we click the button.
For example, I have a RequiredFieldValidator Validation control on the page. ConfirmButtonExtender should not display even though I click the submit button untill I input something in the TextBox.

See the code:

<body>
    <form id="form1" runat="server">
        <ajaxToolkit:toolkitscriptmanager runat="Server" EnablePartialRendering="true"
            ID="ScriptManager1" />
   
        <asp:TextBox ID="TextBox1" runat="server" ></asp:TextBox>  
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator" ControlToValidate="TextBox1"></asp:RequiredFieldValidator>

        <asp:Button ID="Button" runat="server" Text="Click Me" OnClientClick="disableSubmit();return false;" OnClick="Button_Click" /><br />
        <br />
        Server Time Refresh: <asp:Label ID="Label1" runat="server" Text=""></asp:Label>
        <asp:Button ID="HiddenButton" runat="server" Text="Hiddenbutton" style="display:none;" /><br />    
        <ajaxToolkit:ConfirmButtonExtender ID="ConfirmButtonExtender2" runat="server"
            TargetControlID="HiddenButton"
            OnClientCancel="cancelClick" BehaviorID="ConfirmButtonBehavior"
            DisplayModalPopupID="ModalPopupExtender1"  />
        <br />
        <ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server"
        TargetControlID="HiddenButton"
        PopupControlID="PNL"
        OkControlID="ButtonOk"
        CancelControlID="ButtonCancel" BackgroundCssClass="modalBackground"
        />
        <asp:Panel ID="PNL"  runat="server" style="display:none; width:200px; background-color:White; border-width:2px; border-color:Black; border-style:solid; padding:20px;">
            Are you sure you want to click the Button1?
            <br /><br />
            <div style="text-align:right;">
                <asp:Button ID="ButtonOk" runat="server" Text="OK" OnClientClick="onOkScript()" />
                <asp:Button ID="ButtonCancel" runat="server" Text="Cancel" />
            </div>
        </asp:Panel>
    </form>
</body>
<script type="text/javascript">

function disableSubmit()
{
    if (typeof(Page_ClientValidate)=='function')
    {
        if (Page_ClientValidate() == true)
        {
            return checkSubmit();
        }
        else
        {
            return true;
        }
    }
    else
    {
        return checkSubmit();
    }
}

function checkSubmit() {

    var confirmButton = $find('ConfirmButtonBehavior');
   
    confirmButton._displayConfirmDialog();

}
function onOkScript() {
    var confirmButton = $find('ConfirmButtonBehavior');
    confirmButton._postBackScript = "__doPostBack(\u0027Button\u0027,\u0027\u0027)"; //reset bind onto Button

}
</script>



protected void Button_Click(object sender, EventArgs e)
{
    Label1.Text = "You clicked the " + ((Control)sender).ID + " at " + DateTime.Now.ToLongTimeString() + ".";
}