1

Introduction:

I have a repeater with linkbuttons, and when I click on some button, I want it and only it to become transparent, and that the rest of the buttons wouldn't change.

D-Tails:

I have a Repeater of LinkButtons:

<div style="position: relative">
<asp:Repeater runat="server" ID="repStatuses" 
        onitemdatabound="repStatuses_ItemDataBound"
        onitemcommand="repStatuses_ItemCommand">
  <ItemTemplate>
        <div id="divLinkBtn" style="display:inline"><asp:LinkButton ID="linkBtnStatuses" runat="server" CommandName="ShowText" 
            CommandArgument='<%# Eval("Priority") + ";" + Eval("LevelID") + ";" + Eval("ID") %>'
            OnClientClick='<%# "MyFunc(" + Eval("Priority") + ");" %>'>
            <div runat="server" id="divSts" class="fontAriel" ></div>
        </asp:LinkButton></div>
  </ItemTemplate>
    </asp:Repeater>
</div>

The LinkButtons fade in on Page_Load using the following Jquery function. Here's the Page_Load and the jquery code:

Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    SetPageTitle();

    if (!Page.IsPostBack)
    {
        LoadStatusesAndButtons();

        ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>LoadBarWithFadeIN();</script>", false);
    }

    else
        ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>LoadBar();</script>", false);

}

Jquery

function LoadBarWithFadeIN() {
$(document).ready(function () {

    $('a[id*="repStatuses"]').each(function () {
        $(this).show(2500);
        $(this).delay(1000);
    });
});

}

function LoadBar() {
$(document).ready(function () {

    $('a[id*="repStatuses"]').each(function () {
        $(this).show(0);

    });
});

}

When I click on some LinkButton, it becomes Transparent. I found that this code makes only the first linkButtons transparent:

  $(document).ready(function () {
  $('#divLinkBtn').click(function () {
      alert('divlinkbutton presed');
      $(this).css({ 'opacity': 0.4 });
  });
});

THE PROBLEM IS that the button becomes transparent for a second and then the page loads the LoadBar() function and the transparency dissapears. Another thing is that this function does not handle the rest of the buttons.

Now what I need is that this LinkButton should stay transparent until I click on some other linkbutton.

I was thinking of a way to load all the unclicked buttons as is and somehow load the specific clicked button with the trancparency but I can't find a way of doing this due to lack of coding experience.

Sorry for the "short" post :)

Any help'd be much appreciated!!!!!

Yanker
  • 292
  • 5
  • 10
  • 25

2 Answers2

1

The probable reason the button reappears after second page load is that Your changes done in jQuery are not saved in ViewState and so are not preserved across postbacks. If You get a postback on a LinkButton click, You can save the information that it was clicked server-side (i.e. in add a class clicked in Your c# code handling the click event). Then, You can change the client-side script to set transprency for all the LinkButton controls with this class (and some special handling for the button clicked recently). You can also just define a class giving elements appropriate transparency settings. Let me know if You need any help with the code for this.

As to the second issue, please note that You get element by ID and it should be unique in the scope of a html page. That's probably why it works only for the first one. To make it work for all the elements, use a class instead. You can assign a class in your aspx like this:

<div id="divLinkBtn" class="divLnkBtnClass" style="display:inline">... </div>

and assign click handler like this:

$(document).ready(function () {
$('.divLnkBtnClass').click(function () {
  alert('divlinkbutton presed');
  $(this).css({ 'opacity': 0.4 });
});
});

This should make the script work for all the divs.

I haven't tested this code yet, so please let me know if You have any issues with it, so I can fix it and help You to make it work correctly.

UPDATE

There are few methods to preserve transparency across postbacks. You get postback on each item click, so I suppose saving it and restoring it server-side would be one of the easiest ways to achieve the desired effect.

  • First, add a private field to Your page in code-behind:

    private List<String> itemsClicked = null;
    

    and a HiddenField control in your aspx (outside of the Repeater control):

    <asp:HiddenField runat="server" ID="hfButtonsClicked" Value="" />
    

    We will use this HiddenField to save ClientIDs of LinkButton controls, which were already clicked.

  • Then, in Page_Load method, initialize the field with value from the hidden field:

    protected void Page_Load(object sender, EventArgs e)
    {
        SetPageTitle();
    
        //initialize itemsClicked before binding data to the repeater
        itemsClicked = hfButtonsClicked.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
    
        if (!Page.IsPostBack)
        {
            LoadStatusesAndButtons();
    
            ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>LoadBarWithFadeIN();</script>", false);
        }
        else
        {
            ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "tmp", "<script type='text/javascript'>LoadBar();</script>", false);
        }
    }
    
  • Next, add a new method to the page, which will be used in the next step:

    private void SetOpacity(LinkButton linkButton, string opacityValue)
    {
        linkButton.Style.Remove("opacity");
        linkButton.Style.Add("opacity", opacityValue);
    }
    
  • The last thing is adding code saving the id when the item is clicked, You can use click event or just utilize the existing OnItemCommand event handler:

    protected void repStatuses_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
        //get LinkButton that was clicked
        LinkButton lnkBtnClicked = (e.CommandSource as LinkButton);
        if (lnkBtnClicked != null)
        {
            //if item was not clicked before, so the opacity is not set
            if (lnkBtnClicked.Style["opacity"] == null)
            {
                //save control ClientID in the HiddenField
                hfButtonsClicked.Value += String.Format(";{0}", lnkBtnClicked.ClientID);
    
                SetOpacity(lnkBtnClicked, "0.4");
            }
        }
    
        //the rest of the original code should be here
        //...
    }
    

and method restoring the opacity after the postback when item is data bound:

    protected void repStatuses_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        LinkButton lnkBtn = (e.Item.FindControl("linkBtnStatuses") as LinkButton);

        if (lnkBtn != null)
        {
            //if item was clicked before, so the opacity should be restored
            if (itemsClicked.Contains(lnkBtn.ClientID))
            {
                SetOpacity(lnkBtn, "0.4");
            }
        }

        //the rest of the original code should be here
        //...
    }

I implemented this in a sample application and it seems to work as expected. Let me know if You encounter any difficulties with this code.

Additional notes

You can also use a ViewState object instead the additional HiddenField control, but if You would like to change the solution to save/restore opacity in jQuery eventually, working with a HiddenField should be much easier.

There are also some improvements that should be made to the code (i.e. moving string separator to a read-only variable or not hardcoding the value of opacity attribute), but I wrote it this way to make the answer shorter and a little bit easier to read.

Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • The second part works great. Thanks :) As for the first part, I can't see it through, maybe I didn't queit understand you. Help with the code might be a great idea. – Yanker Jan 01 '13 at 13:49
  • Ok I'll try to find the solution in the meanwhile – Yanker Jan 02 '13 at 10:59
  • I've just updated my answer, please take a look at it and let me know if it works for You. – Lukasz M Jan 02 '13 at 11:41
  • 1
    That works great. Too good actually :) I need only the clicked button become transparent, the rest of the buttons should get back to normal. Thank you – Yanker Jan 02 '13 at 14:19
  • Oh, I see. Should I edit the answer to make it work this way? If the answer in this form is ok for You, please accept it :). – Lukasz M Jan 02 '13 at 14:57
  • No, I prefer completing it by myself :) Once again, thank you Lukasz – Yanker Jan 02 '13 at 15:11
  • Just wanted to ask: Why do I need the following line: `linkButton.Style.Remove("opacity");` in the `SetOpacity` method?? – Yanker Jan 02 '13 at 15:14
  • I wasn't sure whether it'll work correctly without this line when there already is an `opacity` key defined for the item. In fact, there is also an additional check for this in `repStatuses_ItemDataBound`, so the line You mentioned is not necessary. – Lukasz M Jan 02 '13 at 15:30
  • To be honest, I've deleted most of the code and somehow it still works and saves all the buttons as transparent. God knows how. The amazing thing is that I got stuck with the original mission - making only the clicked button transparent... ohh well – Yanker Jan 02 '13 at 23:42
  • That's probably because most of the code is respponsible with savin opacty of multiple buttons ;). – Lukasz M Jan 03 '13 at 16:25
1

After a good night sleep, here's a simple (not the most elegant though) solution:

 protected void repStatuses_ItemCommand(object source, RepeaterCommandEventArgs e)
{
   SetAsOriginal();

    //Get the linkbutton that was clicked
    LinkButton lnkBtnClicked = e.CommandSource as LinkButton;       //e- is the object of the repeater. CommandSource- is the clicked
    if (lnkBtnClicked != null)
    {
        SetOpacity(lnkBtnClicked, "0.4");
    }

private void SetAsOriginal()
{
    foreach (RepeaterItem item in repStatuses.Items)
    {
        LinkButton btn = item.FindControl("linkBtnStatuses") as LinkButton;
        SetOpacity(btn, "1.0");
    }
}

private void SetOpacity(LinkButton linkButton, string opacityValue)         //SET THE OPACITY TO THE SPECIFIC linkbutton 
{
    linkButton.Style.Add("opacity", opacityValue);
}

The thing is, that the answer above was very good and working, but did not answer my demand.. I needed to set only the clicked button as transparent and the rest of the buttons are to be set back to original.

So I've decided to specify the solution for those who might encounter with similar issue.

thank you everyone.

P.s: special thanks to @Lukasz M

Yanker
  • 292
  • 5
  • 10
  • 25
  • You can even remove `SetAsOriginal` method and it should still work correctly:). – Lukasz M Jan 03 '13 at 16:30
  • Here I disagree! At first, I didnt have that method and god knows from soe reason it kept remembering the previous clicked buttons and they stood transparent. Tha'd be great if you find the reason for it. But I SetAsOriginal exactly from that reason... – Yanker Jan 04 '13 at 11:14
  • 1
    You are right, I haven't noticed this difference before, but in a sample application I wrote `DataSource` of the `Repeater` was rebound on each postback, which caused the opacity changes to be automatically cleared. In Your code, however, it seems that You only set the `DataSource` on the first page load, so the style changes are handled by the ViewState and automatically restored after postback. That's probably why You needed to manually set the original opacity. – Lukasz M Jan 04 '13 at 21:50