Showing posts with label clicks. Show all posts
Showing posts with label clicks. Show all posts

Wednesday, March 28, 2012

Tracking Link Clicks

Hi,

I posted this before in the "Web Forms" section, but I was just thinking what I might need is an AJAXian solution.

I'm trying to figure out the best way to track user clicks on links. I could easily do this by making all the links LinkButton's and just use the PostBackUrl property or response.redirect or something like that to send the user on to the page they clicked to.

However, this is not a very good solution because spiders would be unable to crawl these links and I need to have the option of opening the pages from the links in a new browser window at times.

So basically if the HyperLink control had an "OnClick" property that fired before doing the default thing (ie following the link), that would be ideal, but it does not.

So I was just wondering if anyone had any good ideas on how to create a "link" control that would allow search engines to crawl the links, allow me to at times open the linked page into a new browser window (ie target=_blank), and also to record the user clicks into a database?

Would there be a way to use the javascript onclick event to fire some function that calls a service or something on the server to update my database with the click information? If so how would I do that?

Hi,

I just replied in your other thread. Though now I've seen you mention AJAX this would allow you to accomplish a lot more.

Cheers,

Al

Tree view nested in Accordion taking two clicks to fire selectedNodeChanged event

I have a treeview in one of my accordion panes. When I click on a node for the first time, instead of firing the selectedNodeChanged event, it just goes through a normal postback. However the second time I click it, the event is fired correctly. Is there another event being fired that I'm not seeing?

Here's a trimed down version of the code. Thanks for any ideas. -d

<atlasToolKit:Accordion ID="navAccordion" runat="server" Height="410"
FadeTransitions="true" FramesPerSecond="40"
TransitionDuration="250"
AutoSize="None"
>

<atlasToolKit:AccordionPane ID="AccordionPane2" runat="server">
<Header><a href="http://links.10026.com/?link=" onclick="return false;" class="accordionLink">Tank Groups</a></Header>
<Content>
<asp:Panel ID="navPanel" runat="server" ScrollBars="auto" CssClass="extraPadding" BackColor="white" Width="180" Height="200">
<asp:TreeView ID="navTankGroups" OnUnload="nav_Unload" OnSelectedNodeChanged="nav_SelectedNodeChanged" runat="server" SkinID="nav" >
<Nodes>
<asp:TreeNode Text="Page 1" Value="~/page1.aspx" />
<asp:TreeNode Text="Page 2" Value="~/page2.aspx" />
</Nodes>
</asp:TreeView>
</asp:Panel>
</Content>
</atlasToolKit:AccordionPane>
</atlasToolKit:Accordion>

Here's the selectedNodeChanged routine.

Protected Sub nav_selecedNodeChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim navTankGroups As TreeView = CType(AccordionPane2.ContentContainer.FindControl("navTankGroups"), TreeView)
If Not navSchedule.SelectedNode.ValuePath = String.Empty Then
Response.Redirect(navTankGroups.SelectedNode.Value)
End If
End Sub


This appears to only be an issue on master pages. I placed the accordion in a new page and it worked fine. Anyone have an idea on why it is taking two clicks in the masterpages? -d

Hi dtamber,

I'm not sure what's going on with this... could you perhaps post the simplest possible version you have that still causes the problem?

Thanks,
Ted


Look at the source code before and after the button click, there is one of 2 possibilities.

1. someting being created dynamicly doesn't have an ID property set, in this case you'll see the treeview control in the source with different names

Like ctl03 and ctl05 in the treeview's name

2. I have fixed my postback issues by adding a hidden field to each accordion pane at page_init. I don't know why this fixes the erradic behavior, but it does.

Let me know if either of these works.

Chris


I think this needs a bump.

I just tried using an accordion in a usercontrol and added 3 panes, each containing an updatepanel containing a button.

The button click event is not fired. Adding a hidden field as Chris suggested allows the click event to fire.

Nathan


I also ran into the exact same problem. I was using a gridview inside an accordion and the events weren't firing the first attempt. If you add a control to it during OnInit then it appears to work. My assumption is that there's a problem with the RenderControls or something.

Astynax777:

I also ran into the exact same problem. I was using a gridview inside an accordion and the events weren't firing the first attempt. If you add a control to it during OnInit then it appears to work. My assumption is that there's a problem with the RenderControls or something.

Astynaxx777 - This clicking twice problem has been a real issue for me. Can you please elaborate with a small example if possible? You mean to add a control to the AccordionPane when the page loads (through the code behind)?

Your help would be greatly appreciated.


I ran into the same problem where I couldn't get a Button click event to fire off until I did whatCConchelos tried:

"2. I have fixed my postback issues by adding a hidden field to each accordion pane at page_init. I don't know why this fixes the erradic behavior, but it does."

Here's a basic example:

 
<body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> </div> <cc1:Accordion ID="Accordion1" runat="server"> <Panes> <cc1:AccordionPane ID="AccordionPane1" runat="server"> <Header>Test1</Header> <Content> <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton> </Content> </cc1:AccordionPane> <cc1:AccordionPane ID="AccordionPane2" runat="server"> <Header>Test2</Header> <Content> <asp:Button ID="Button1" runat="server" Text="Button" /> </Content> </cc1:AccordionPane> </Panes> </cc1:Accordion> </form></body>

The Button1 click event would not get called until I added a hidden field to the AccordionPane that contained Button1 on the Page_Init:

Private Sub Page_Init(ByVal senderAs System.Object,ByVal eAs System.EventArgs)Handles MyBase.InitDim myAccordionPaneAs AccordionPaneDim myTextBoxAs New TextBox myTextBox.Visible =False myAccordionPane =MyBase.FindControl("AccordionPane2") myAccordionPane.Controls.Add(myTextBox)End Sub

I thinkAstynax777 is right - there must be something wrong with the controls inside an AccordionPane when being rendered.


Thank you very much. It should be noted that after Astynax777's suggestion I tried it with a button and I forgot to hide it, and it didn't work as expected.

Excellent example, thanks again.


Hi,

has anyone found out more about this issue? As indicated in a previous post, the issue appears to be that controls are not rendered properly the first time the accordion is loaded. When the postback occurs, the controls have a different id, and no event is fired since it cannot be hooked up to the appropriate control (since the ID has changed).

I have a slightly different problem than those posted above as the accordion I'm working with is loaded via a datasource. I cannot add controls on the init event as a temporary fix. Any idea for a workaround would be greatly appreciated until this is resolved.

Thanks


btw, this "click twice" error disappears when I have only 1 accordion control on a page. If there are two accordion controls (one is data bound, the other is not), then I have to click twice. When I only have the databound accordion, it works as intended.

The good thing is that adding the "invisible" control to each pane in the Accordion which is not databound has fixed the "click twice" error in the databound Accordion.


Ok, I think I have this problem fixed. You can see the changes I made athttp://www.codeplex.com/AtlasControlToolkit/WorkItem/View.aspx?WorkItemId=5796 . There's 2 files I uploaded for that issue. I might help you... or it might not, I have not tested it for your problem but it certainly fixed mine! Good luck.


Has anybody else tried it with the new 10660 release? For me, the event handling never worked. My accordion is completely databound and does not contain any unbound panes. Consequently, the workaround will not work for me. I've just tried it with 10660, but no change.

Dennis Doomen
Aviva Solutions


I was having all of those 'click twice' problems but in randomly places. I used Accordions on many different pages and I couldnt figure out why it worked on some pages and didnt on others. I realized that on the page that it didnt work I was doing my control loading during OnInit and on my other pages that did work it was during PageLoad. Im guessing you have to make sure that everything must be done in one or the other. If you have User Controls make sure that your logic and things are also in it's page load as well. Dont mix and match :)

Monday, March 26, 2012

Trigger does not work

I have a trigger, which is set to lblProgress.Text property. Once the user clicks the button, the code changes the property, but nothing is displayed untill the onclick event finish. Should not be the Atlas asynchronous?

Default.aspx:

<%

@dotnet.itags.org.PageLanguage="C#"AutoEventWireup="true"CodeFile="Default.aspx.cs"Inherits="_Default" %>

<!

DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<

htmlxmlns="http://www.w3.org/1999/xhtml">

<

headrunat="server"><title>Untitled Page</title>

</

head>

<

body><formid="form1"runat="server"><atlas:ScriptManagerID="scriptManager"EnablePartialRendering="true"runat="server"/>

<atlas:UpdatePanelID="UpdatePanel1"Mode="Conditional"runat="server"><ContentTemplate><asp:ButtonID="btnImport"runat="server"Text="Import"OnClick="btnImport_Click"/><divstyle="background-color:Lime"><h1><asp:LabelID="lblProgress"runat="server"Text=""></asp:Label></h1></div></ContentTemplate><Triggers><atlas:ControlValueTriggerControlID="lblProgress"PropertyName="Text"/></Triggers></atlas:UpdatePanel></form>

</

body>

</

html>

Deafault.aspx.cs

using

System;

using

System.Data;

using

System.Configuration;

using

System.Web;

using

System.Web.Security;

using

System.Web.UI;

using

System.Web.UI.WebControls;

using

System.Web.UI.WebControls.WebParts;

using

System.Web.UI.HtmlControls;

public

partialclass_Default : System.Web.UI.Page

{

protectedvoid Page_Load(object sender,EventArgs e)

{

}

protectedvoid btnImport_Click(object sender,EventArgs e)

{

lblProgress.Text =

"Starting Import...";

System.Threading.

Thread.Sleep(5000);

lblProgress.Text =

"That took awhile...";

}

}

I suspect any of two:

1) Call to button_Onclick is not asynchronous, so the page is waiting for the sub to finish

or

2) Setting lblProgress.Text from code does not trigger the trigger.. That would mean a bug in Atlas I guess

Wonder what you think...


Hi,

Atlas being asynchronous means that when you trigger an update for an UpdatePanel, a HTTP request is sent asynchronously to the web server, i.e. you can do other processing on client-side while the request you sent is being processed and the corresponding response is generated.

But the above response is generated when the partial postback ends, i.e. when the page has completed its whole lifecycle and rendered the HTML for the controls inside the UpdatePanel. This means that when btnImport_Click returns, the Label's text is set to "That took awhile..." and it's this text that will be displayed, since it is this text that it is rendered by the Label control and sent in the response from the server.

OK, sounds logical.How do I make the label to refresh in my long running process, which is executed after click?

I have also noticed that UpdatePanel has update property, but not sure how to use it...


Hi,

there are many approaches to monitor a long running task. The one I would take is to spawn a separate thread to run the task (btw checkthis article) and then poll the server at a specified interval to check the task's status and update a progress bar or other kind of progress indicator.

Without Atlas, this could be done using pure Javascript or a meta refresh. Adding Atlas would probably mean using a Timer control to just send the polling requests asynchronously, and update some controls (the progress indicators) inside an UpdatePanel.

Thanks, I was hoping that this could be done simpler using Atlas, if I could only somehow force the UpdatePanel to refresh itself once the lblProgress.text property is updated, my initial thought was that the trigger would do it, but than reading your post I realized that it is waiting for the btnImport_OnClick sub to finish...

Maybe if I need to have btnImport_OnClick running in seperate thread?


You said:

"...But the above response is generated when the partial postback ends, i.e. when the page has completed its whole lifecycle and rendered the HTML for the controls inside the UpdatePanel. This means that when btnImport_Click returns, the Label's text is set to "That took awhile..." and it's this text that will be displayed, since it is this text that it is rendered by the Label control and sent in the response from the server..."

Can I render page early in my onlick sub? before onclick sub will finish?How would I execute UpdatePanel partial postback once my onlick sub sets the lplProgress.text property?


Hi,

rfurdzik:


Can I render page early in my onlick sub? before onclick sub will finish?


no, because the rendering of a page is a stage in its lifecycle and you cannot modify the Page's lifecycle.

rfurdzik:


How would I execute UpdatePanel partial postback once my onlick sub sets the lplProgress.text property?


A partial postback is just a postback performed asynchronously (i.e. using XMLHTTP). From the Page's lifecycle point of view, a classic postback and a partial postback are pretty much the same thing: the Page goes through all its whole lifecycle, like in a "regular" postback. The difference is that only the HTML of the controls inside the UpdatePanels that are updating is injected into the response.

Also what is the porpouse of UpdatePanel1.Update(); ?

Does it force UpdatePanel to do partial postback?


I have also found this interesting article:http://forums.asp.net/thread/1338483.aspx

Seems that he found a way around to execute partial postback... Wonder how would it be possible to execute partial postback in my code:

protectedvoid btnImport_Click(object sender,EventArgs e)

{

lblProgress.Text =

"Starting Import...";

//Here I would like to execute partial postback of Updatepanel1. I have tried UpdatePanel.Update(), but it did not work

System.Threading.

Thread.Sleep(5000);

//THIS LAST MESSAGE IS ONLY SHOWN

lblProgress.Text =

"That took awhile...";

}


<<A partial postback is just a postback performed asynchronously (i.e. using XMLHTTP). From <<the Page's lifecycle point of view, a classic postback and a partial postback are pretty much <<the same thing: the Page goes through all its whole lifecycle, like in a "regular" postback. The <<difference is that only the HTML of the controls inside the UpdatePanels that are updating is <<injected into the response.

I think I understand now, so the page lifecycle will be finished when the last line of the OnClick sub is executed. Is this correct? In this case I guess I need:

1) to have Onclick to instantiate a seperate thread for long running task and leave the task running.. (what happens if the user closes the browser?)

2) My import class calls delegate method (part of my page, setup in import class constructor),how could I make that delegate method to update the lblProgress.text and execute partial postback?

Do you think that using webservice would make more sense?


After doing some research I realized that you were right,btnClick_ONClick sub is part of Postback, that is why postback request can not be generated within.

So now the question would be which aproach to use?

1) The one suggested by you btnClick_ONClick sub would create a seperate thread. Seems like it should be OK to execute Postback from a seperate thread process...

2) Create control in Atlas and have the control to call webservice. Seems like only the control can update progress label settings, server side code can not...

What would be the cons and prons of eighter aproach?


Instead of worrying about creating a new thread, you could separate the single request into 3 separate requests. The initial button click would cause the UpdatePanel to postback where you can change the text to 'loading', and use RegisterClientScriptBlock to inject javascript which would then initiate a second postback. The second postback would then perform your long operation, and would use RegisterClientScriptBlock to inject javascript to fire the final request which would be responsible for changing your text to 'finished' or whatever you decide.

Hope this helps,
-Tony


That is a great idea! I did not think about it. Would this technique allow the text to change several times during the Long Running Process? For example (1,2,3% etc..)

What is the exact injected java script/atlas code to fire the LRP sub? I do not know java script too much... Do you think that that javascript could call asynchronous web method, which would perform LRP and update the label's text? Will the web method have access to the Page object? Thanks,

Rafal


<< and then poll the server at a specified interval to check the task's status

Is not that waste of resources? I was thinking to have the LRP (Long Running Process) to call page's method (via delegate) and force the page to postback itself (partial postback).

What do you think?

Saturday, March 24, 2012

Trigger UpdatePanel with javascript

I have a GridView inside an UpdatePanel. Also on the page is a button, that when the user clicks opens up a modal dialog box. After the user selects an item from the dialog box, the dialog closes which triggers a javascript function. The purpose of this javascript function is to re-bind the GridView, thereby displaying the item just selected from the dialog box.

The javascript function simply triggers a hidden linkbutton that also resides inside the UpdatePanel.

The javascript code:

document.getElementById('ctl00_Main_LinkButton1').click();

The LinkButton code:

ProtectedSub LinkButton1_Click(ByVal senderAsObject,ByVal eAs System.EventArgs)Handles LinkButton1.Click

GridView1.DataBind()

EndSub

This all works fine under IE6. The problem just started when I upgraded to IE7. The LinkButton is no longer getting triggered, so the GridView doesn't update. I've tried this with both the Atlas release, and the Ajax Beta 2 release. Neither seems to do what I want with IE7.

One other thing, if I remove the UpdatePanel from the page entirely, and force a full page refresh, it works fine with IE7.

Has anyone else noticed this? Any ideas on a work around?

hello.

try using fiddler to see the error you're getting.


I downloaded and ran Fiddler, but can see no errors.

I have many apps that use the similar method, and it works in IE6, IE7 and Firefox v2.0 and Apple Browser (don't remember the name - Safari?) hmmm who cares.

Try put your LinkButton outside the update panel.

WS

p.s: my apps use button instead link button. AND I don't use modal window, because it's not supported by many browsers. Instead, I use floating div. Good Luck.


I think the key difference with your solution is that all the logic resides in one page (with the use of floating div). I have tried adding a linkbutton outside the updatepanel, but this makes no difference in my solution.

With the modal dialog, I can trigger the javascript function when the dialog is closed. I tested this my triggering an Alert from my javascript function, so I know the function is being called when I close the dialog.

I next tried adding an HTML Input button outside the updatepanel:

<inputid="Button1"type="button"value="button"onclick="javascript:document.getElementById('LinkButton1').click();"/>

When I clicked this button, itdid trigger a refresh. I'm just not sure why it won't do it automatically once the dialog box is closed. Again, I've proven that the function is being called when the dialog is closed. I'm wondering if this isn't some IE 7 security issue. I've played around with the permissions a bit, but still have no joy.


For what it's worth,

I finally found a solution to my problem. I did a little digging into the JS file for the AJAX ModalPopup control, and modified my javascript accordingly:

window.setTimeout(

"document.getElementById('ctl00_Main_LinkButton1').click();", 0);

Now works with both IE6 and IE7.

Thanks to all for your responses.