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() + ".";
}

Thursday, December 25, 2008

Custom AutoComplete 4: Build an UpdateProgress for AutoComplete

I have introduced some kinds of Custom AutoComplete. Again, there is an another one -- Build an UpdateProgress for AutoComplete.

Check the code directly:

<head runat="server">
    <title>Untitled Page</title>
    <style>
        .autocomplete_completionListElement
        {
            visibility: hidden;
            margin: 0px !important;
            background-color: inherit;
            color: windowtext;
            border: buttonshadow;
            border-width: 1px;
            border-style: solid;
            cursor: 'default';
            overflow: auto;
            height: 200px;
            text-align: left;
            list-style-type: none;
            font-family: courier new;
            font-size: 8pt;
        }
        /* AutoComplete highlighted item */.autocomplete_highlightedListItem
        {
            background-color: #e3ec6e;
            color: black;
            padding: 1px;
        }
        /* AutoComplete item */.autocomplete_listItem
        {
            background-color: window;
            color: windowtext;
            padding: 1px;
        }
        body, div, p, h1, h2, h3, h4, ul, li, table
        {
            margin: 0;
            padding: 0;
            border: none;
        }
    </style>
</head>

<script type="text/javascript">
    function pageLoad() {
        $find('autocomplteextender1').add_populated(shownev); //if no result, this event will not be triggered and "loading" can't be hidden. But if result is exist, hiding event will be triggered when the user selects value to hide popuplist.So we need populated event to hide "loading" when the result is not empty.

        $find('autocomplteextender1').add_populating(populatingev);
        $find('autocomplteextender1').add_hiding(onhiding); // no matter the result is empty or not, hiding event will be triggered. If the result is empty, it will trigger hiding event after response returned. If the result is exist, hiding event will be triggered after user selected value to hide popuplist.
    }
    function onhiding() {

        var updateProgress = $get('<%= UpdateProgress2.ClientID %>');
        var dynamicLayout = '<%= UpdateProgress2.DynamicLayout.ToString().ToLower() %>';

        if (dynamicLayout) {
            updateProgress.style.display = "none";
        }
        else {
            updateProgress.style.visibility = "hidden";
        }
    }
    function shownev() {
        var updateProgress = $get('<%= UpdateProgress2.ClientID %>');
        var dynamicLayout = '<%= UpdateProgress2.DynamicLayout.ToString().ToLower() %>';

        if (dynamicLayout) {
            updateProgress.style.display = "none";
        }
        else {
            updateProgress.style.visibility = "hidden";
        }

    }
    function populatingev() {
        var updateProgress = $get('<%= UpdateProgress2.ClientID %>');
        var dynamicLayout = '<%= UpdateProgress2.DynamicLayout.ToString().ToLower() %>';

        if (dynamicLayout) {
            updateProgress.style.display = "block";
        }
        else {
            updateProgress.style.visibility = "visible";
        }


    }

</script>

<body>
    <form id="form2" runat="server">
    <asp:ScriptManager ID="ScriptManager2" runat="server" />
    <asp:UpdateProgress ID="UpdateProgress2" runat="server">
        <ProgressTemplate>
            loading...
        </ProgressTemplate>
    </asp:UpdateProgress>   
    <asp:TextBox ID="TextBox1" runat="server" Width="437px"></asp:TextBox>
    <cc1:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" BehaviorID="autocomplteextender1"
        MinimumPrefixLength="1" ServicePath="AutoComplete.asmx" ServiceMethod="GetCompletionList1"
        TargetControlID="TextBox1" CompletionListCssClass="autocomplete_completionListElement"
        CompletionListItemCssClass="autocomplete_listItem" CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
        CompletionInterval="1000" DelimiterCharacters=";" CompletionSetCount="10" FirstRowSelected="true"
        EnableCaching="true" Enabled="true">
    </cc1:AutoCompleteExtender>

    </form>
</body>

Thursday, December 18, 2008

Custom AutoComplete 3: Check if AutoComplete List has result items

This kide of requirement I encountered many times.
When the prefixText the user inputed didn't cause any result items from AutoComplete, we need generate an alert for it. For example, the background of TextBox should become red if empty result occurs. See the below thumbnail.



When I'm during the process of typing "mary", the result of web method will be returned. After I type additional "x", the result is empty as "maryx" is not exist. Then the background becomes red.

We need rebuild the onMethodComplete function to attach a callback function after results are updated so that we can generate the alert meassage. Now we can see the code:

<head runat="server">
    <title></title>
    <style>
        .autocomplete_completionListElement
        {
            visibility: hidden;
            margin: 0px !important;
            background-color: inherit;
            color: windowtext;
            border: buttonshadow;
            border-width: 1px;
            border-style: solid;
            cursor: 'default';
            overflow: auto;
            height: 200px;
            text-align: left;
            list-style-type: none;
            font-family: courier new;
            font-size: 8pt;
        }
        /* AutoComplete highlighted item */.autocomplete_highlightedListItem
        {
            background-color: #e3ec6e;
            color: black;
            padding: 1px;
        }
        /* AutoComplete item */.autocomplete_listItem
        {
            background-color: window;
            color: windowtext;
            padding: 1px;
        }

    </style>
</head>

<script type="text/javascript">
    function pageLoad() {

        $find('autocomplteextender1')._onMethodComplete = function(result, context) {

            $find('autocomplteextender1')._update(context, result, /* cacheResults */false);
            webservice_callback(result, context);
        };

    }
    function webservice_callback(result, context) {

        if (result == "")
            $find("autocomplteextender1").get_element().style.backgroundColor = "red";
        else
            $find("autocomplteextender1").get_element().style.backgroundColor = "white";
    }

</script>

<body>
    <form id="form2" runat="server">
    <asp:ScriptManager ID="ScriptManager2" runat="server" />
    <asp:UpdatePanel ID="uppanle1abcxyz" runat="server">
        <ContentTemplate>
            <asp:TextBox ID="TextBox1" runat="server" Width="150px"></asp:TextBox>
            <cc1:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" BehaviorID="autocomplteextender1"
                MinimumPrefixLength="1" ServicePath="AutoComplete.asmx" ServiceMethod="GetCompletionList1"
                TargetControlID="TextBox1" CompletionListCssClass="autocomplete_completionListElement"
                CompletionListItemCssClass="autocomplete_listItem" CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
                CompletionInterval="500" DelimiterCharacters=";" CompletionSetCount="10" Enabled="true">
            </cc1:AutoCompleteExtender>
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>

Wednesday, December 3, 2008

How to do somthing(call JavaScript code) after AnimationExtender completed

Many engineers use AjaxControlToolkit AnimationExtender to achieve the animation process. It encapsulates JavaScript library to achieve.
Now there is a scenario: When the AnimationExtender is completed, how can we do some JavaScript? For example:

<asp:ImageButton ID="ib1" ImageUrl="~/images/AJAX.gif" OnClientClick="return false;"  Height="100px" Width="100px" runat="server" />
<ajaxToolkit:AnimationExtender id="OpenAnimation" runat="server" BehaviorID="AnimationBehavior"  TargetControlID="ib1" >
   <Animations>
        <OnClick>
           <Sequence>
           <EnableAction Enabled="false" />              
           <Pulse Duration=".1" />
           <Parallel AnimationTarget="ib1" Duration=".3" Fps="30">
             <FadeOut />
               <Scale ScaleFactor="5" Unit="px" Center="true"  ScaleFont="true" FontUnit="pt" />
           </Parallel>              
           <StyleAction Attribute="postbackurl" Value="~/Default.aspx"/>
         </Sequence>
        </OnClick>
     </Animations>
</ajaxToolkit:AnimationExtender>



With the above sample, it will do Animation after you click the imagebutton. But now, we want to make it redirect to a new page after clicking the imagebutton and completing the Animation. If you define imagebutton OnClick event, it will not be triggered because OnClientClick returns false. If you remove out OnClientClick="return false;", it will do postback directly when you click the button, rather than waiting the completion of animation. Maybe we can call some client event, which will be triggered after AnimationExtender is completed. But the problem is AnimationBehavior hasn't any client event about onCompleted.

Actually, I'd like to make a way to achieve it: we can build an Animation object to contact with the AnimationBehavior, receive the Animation instance from it and declare OnEnd client event of Animation object.


<script type="text/javascript">

     function pageLoad() {
         var animation =$find('AnimationBehavior')._onClick.get_animation();
         animation.add_ended(onend);
     }
     function onend() {
         window.location.href = "../../../Default.aspx";
    
     }

</script>


Now, after you click the imagebutton, it will do the Animation. After anything is completed, it will go to the new page.