This is a migrated thread and some comments may be shown as answers.

Clicks im "empty space"

6 Answers 107 Views
Rotator
This is a migrated thread and some comments may be shown as answers.
ManniAT
Top achievements
Rank 2
ManniAT asked on 10 Mar 2009, 01:15 PM
Hi,

I use (want to) RadRotator to scroll items on to of a page (Header im Masterpage).
One issue is keeping the item index up do date - still no solution :(

But I got a nem thing.

My Header contains some information (image) and on top of it I have the rotator.
Finally it should do nothing more than srcoll in ONE item from the right - stop on the left,
display the item some time - and scroll in the next.
Since I have info in that section I only want to display one item a time.

Now the problem - as also reproduceable in your sample RadRotator is "full clickable".
http://demos.telerik.com/aspnet-ajax/rotator/examples/gallery/defaultcs.aspx

Thats my Problem - my Header looks like this:
BBBBxxxxIIIIIIIIIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBBBB
Where BBBB are some border Elements, IIIII is the place where the image is shown and xxxxxx is the scrolling range (width of rotator).
The problem -- IIIIII should be clickable -- BUT -- xxxxx not (except when an item is running by -- but that's not needed).

So how can I avoid that the user can click everywhere in Rotator?

Regards

Manfred

6 Answers, 1 is accepted

Sort by
0
ManniAT
Top achievements
Rank 2
answered on 11 Mar 2009, 09:16 AM
Hi,

the problem is not solved - but I did a workaround which works.
Maybe someone else has this problem - so I'll share the solutins here.

Inspecting the rendered layout of the rotator I found (guessed) it would not be so easy to "reduce" the clickable area.
I'm mor the "desktop C# guy" - so messing around with jscript, css and all this funny things is not what I like :)

So I decided to ignore the rotators click - and make the thing rotating clickable.
This is not to hard to achive - and it gives great flexibility on "where you can click".

My app works with a DB but for easier understanding I some (nasty I know :)) "string machting" here.
Anyhow - the approach should fit any (normal) scenario.
I have my rotating content - and this thing displays something.
The rotator binds some kind of a "ID" (path to image, string to display, whatever) to it.

In my case I show up a thumpnail, a title below it and some description next to it.
To make the thing "clickable" (in an easy manner) simply create a usercontrol out of it.

Here is my Control (ObjectID is a string - in this sample it matches the image filename - part of it).

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ObjectViewTop.ascx.cs" Inherits="House1.Controls.ObjectViewTop" %> 
 
<table border="0" style="width: 240px; border: solid 1px red; background-color: #F5F5F5;" cellpadding="0" cellspacing="0">  
        <tr> 
            <td rowspan="1" style="width: 100px; margin:0px 0px 0px 0px;vertical-align:middle">  
                    <img id="imgOne" runat="server" alt="NoData" src="/Images/Dummy.jpg" style="width: 100px; height: 75px; margin: 0px 0px -3px 0px;border:none;" /> 
            </td> 
            <td rowspan="2" style="height: 20px; text-align: left; vertical-align: top;border-left:solid 1px black;line-height:8px;padding: 3px 0px 0px 2px">  
                <asp:Label ID="lblObjectInfo" Style="font-size: 10px" runat="server" /> 
            </td> 
        </tr> 
        <tr style="height: 20px;">  
            <td rowspan="1" style="vertical-align: middle; text-align: center; font-weight: bold; color: Navy; border-top: solid 1px black;">  
                <asp:Label ID="lblObjectID" runat="server" /> 
            </td> 
        </tr> 
    </table> 
 
CODE BEHIND  
 
public partial class ObjectViewTop : System.Web.UI.UserControl{  
 
        #region ObjectID  
        private string m_strObjectID;  
        public string ObjectID {  
            get { return m_strObjectID; }  
            set { m_strObjectID = value;  
//important for databinding -- this may occure AFTER Page_Load!!!  
            SetValues();  
            }  
        }  
        #endregion  
 
        protected void Page_Load(object sender, EventArgs e) {  
            SetValues();  
        }  
 
        private void SetValues() {  
            lblObjectID.Text = ObjectID;  
            lblObjectInfo.Text = "Info about: " + ObjectID + "<br/> will be here";  
            imgOne.Src = "/Images/Gallery/TXA" + ObjectID + ".jpg";  
            imgOne.Alt = "Image of " + ObjectID;  
        }  
So what does it do - it builds a simple layout with a table.
In Code behind it binds the values - that's it.
And it has a public property "ObjectID" where I can bind a string.

RadRotator looks like this

<style type="text/css">  
        .rotItemTemplate  
        {  
            text-align: left;  
            padding: 0px 360px 0px 10px;  
            border: none;  
        }  
    </style> 
 
<telerik:RadRotator ID="rrRot" runat="server" PauseOnMouseOver="false" Width="618px" FrameDuration="4000" ScrollDuration="900">  
                    <ItemTemplate> 
                        <div class="rotItemTemplate">  
                            <uc:ObjectViewTop ID="myPrev" runat="server" ObjectID='<%# Eval("ObjectID") %>' /> 
                        </div> 
                    </ItemTemplate> 
                </telerik:RadRotator> 
 
CODE BEHIND  
 
string[] straS = { "Sau1", "Sau2", "Sau3", "Sau4", "Sau5", "Sau6", "Sau7", "Sau8", "Sau9" };   
//called from Page_Load  
        private void RebindRotator() {  
            DataTable rotatorData = new DataTable();  
            rotatorData.Columns.Add("ObjectID");  
            foreach (string strX in straS) {  
                rotatorData.Rows.Add(strX);  
            }  
            rrRot.DataSource = rotatorData;  
            rrRot.DataBind();  
        } 
Also very simple for this sample.
So now - how to handle the clicks?

First of all - make the UserControl clickable.
I simply place a div around the table I showes formerly.
Of course I could do this with my image, some table row or whatever..
<div onclick="<%# String.Format("javascript:{0}",Page.GetPostBackEventReference(this)) %>"> 
<table....> 
</table> 
</div> 
IMPORTANT: notice that I use double quotation marks on all the places.
Normaly I do xxx='<%.....%>' at least when I have quotation marks inside the "code".
But in the case this would result in a jscript error!!
The reason Page.GetPostBackEventReference results in something like __doPostBack('ctk.....','')
The final result would be onclick='javascript:__doPostBack('ctl...','')'
So it would give you an error.

What we have got so far - we injected a postback for the onclick of the div.
Now (of course) we have to handle this in code behind.
There is an interface for this - IPostBackEventHandler.
public partial class ObjectViewTop : System.Web.UI.UserControl, IPostBackEventHandler {  
 
        #region Click  
        public event EventHandler Click;  
        #endregion  
......NO CHANGES TO EXISTING CODE  
        #region IPostBackEventHandler Member  
 
        public void RaisePostBackEvent(string eventArgument) {  
            OnClick(new EventArgs());  
        }  
        protected virtual void OnClick(EventArgs e) {  
            if (Click != null) {  
                Click(this, e);  
            }  
        }  
 
        #endregion  
    } 
I guess this code is very straight - no need to comment it :)
Last no least the changes to my rotator.
First of all attach the onclick event.
Don't expect designer support (or intellisense) - at least for me there is nothing there - but it is not hard to do it.
<telerik:RadRotator.....> 
    <ItemTemplate> 
        <div class="rotItemTemplate">  
            <uc:ObjectViewTop OnClick="ucTV_OnClick" ID=....  
 
Just write OnClick - and assign a method name.
In code behind have the handler.
In my case it will open a "view details page" - and for SEO (user friendly locking URLs) it does URLRewriting.
So /..../IDofMyObject_Details. is in reality /.../ObjectDetail.aspx?ObjectID=IDofMyObject
protected void ucTV_OnClick(object sender, EventArgs e) {  
    ObjectViewTop ovT = sender as ObjectViewTop;  
    if (ovT != null) {  
        Response.Redirect("/Objects/" + ovT.ObjectID + "_Detail.aspx");  
    }  
}  
 

Thats it.

I'm afraid that some telerik guy will answer this thread with something like
Simply use this CSS so the blank areas will no longer be clickable...
:))

Anyhow I think an approach like this could be usefull - especially if you would like to achive "special things" like that only a part of your rotated thing should be clickable.
Or for an example if you want some areas to do differnt things.
Page.GetPostBackEventReference has an overload where you can specify a string which will be passed to the RaisePostBackEvent Method.
So you place more of this Page.GetPostBackEventReference on your control - and in the handler you evaluate the string and do different things depending on the values.

Maybe this post is helpfull for someone.

For me the RadRotator problem is solved (I'll stay on this approach) BUT I'm still interested in an answer from telerik if there is some "correct" solution to avoid "empty space clicks".

Regards

Manfred
0
Fiko
Telerik team
answered on 12 Mar 2009, 02:01 PM
Hi Manfred,

Thank you for sharing this solution. I would also suggest to try another solution of  the problem:
  • attach a function to the onclick event of the image, that is inside in the ItemTempalte of the RadRotator :

    <telerik:RadRotator ID="RadRotator1" runat="server" Height="132px" OnClientItemShown="onClientItemShown" 
        ItemHeight="92px" Width="400px" ItemWidth="400px" DataSourceID="XmlDataSource1"
        <ItemTemplate> 
            <asp:Label ID="Label1" runat="server">Not clickable Not clickable </asp:Label> 
            <asp:Image ID="Image1" onclick="onImageClick(this);" runat="server" ImageUrl='<%# XPath("ImageURL") %>' 
                AlternateText="IMAGE" class="clickableImage" /> 
        </ItemTemplate> 
    </telerik:RadRotator> 

  • implement the onImageClick() function as follow :

    function onImageClick(image) 
        alert(image.src); // Print the path to the clicked image

After implementing this functionality you will be able to click on the image and process the result.
As you see in the RadRotator's declaration I attach a handler to the OnClientItemShown event. I do this in reference to the first RadRotator's issue :  "One issue is keeping the item index up do date - still no solution :(". Bellow I pasted the code that you can use to get the index of the currently showed rotator's item :

function onClientItemShown(sender, args) 
    var rotItem = args.get_item(); 
    var showIndex = $get("LabelIndex"); 
    showIndex.innerHTML = "Current Item Index :" + rotItem.get_index(); // show the index in an asp:Label 

For your convenience I attached a simple demo to this thread.
I hope this helps.

All the best,
Fiko
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
ManniAT
Top achievements
Rank 2
answered on 12 Mar 2009, 02:13 PM
Hi,

what I see is that you handle the click on client -- my problem was to handle this on the server.
Of course I guess your solution would also work if I use an asp:image - and finally this is what I do.
The difference - I use a usercontrol - which has unfortunately no "out of the box click server event" - but if you break down the thing you end on a <asp:SomeClickableControl ....OnClick=... in the content of RadRotator.

But you are (very) right with your comment - since what I do means a useless overhead when the Rotator's content is something basic like an image or so.
My proposal to wrap an image in an usercontrol was not the best idea :))

About the issue with the index maintanning I already opened a support ticked - the result - this apporach does not work when changing pages (that was my problem).

BUT - I also got a solution for this - since page changes are (more thant 90%) done by the navigation pane (a RadMenu) I handle the OnClick there - store the index in a session variable an reload it later in the masterpage.
The combination of both approaches (your script for handling "on page postbacks") and my extension for the menu finally solved the problem.


Regards

Manfred
0
ManniAT
Top achievements
Rank 2
answered on 23 Apr 2009, 01:10 PM
Final Solution,

I want to inform you that I changed my solution - and finally got an approach which works very well in my MasterPage scenario.
The solution with a hidden control and a "onclick handler" for the (navigation) RadMenu made to much problems - so I had to change it.
And I guess my final solution could be helpful for someone else too.

My problems with the Menu approach:
To get a click event on the menu you have to keep NavigateUrl empty.
This is bad for SEO approaches.
Next my customer uses a lot of "normal links" (in the content) so that the guessed 90% navigation through menu ends in about 30%.

My final approach looks like this:
1.) I have a masterpage with the rotator
2.) the masterpage holds the radscriptmanager
3.) all my content pages are derived from a common base class

About point 3 - I generally do this in my projects since there is normally always something to do for all the pages.
Point 2 looks like this
<telerik:RadScriptManager ID="rsmMain" runat="server" EnablePageMethods="True">  
 
The only noticeable thing here is that I set EnablePageMethods to true.
In my base class for all the pages (does not work for me in the masterpage!!) I do:
[WebMethod]  
public static void SetIDX(string strIDX) {  
    try {   //don't care if it fails  
        int nIDX = int.Parse(strIDX);  
        HttpContext.Current.Session["rotIDX"] = nIDX;  
    }  
    catch { }  
}     
 
The rest of the infrastructure is like it was before - a bit changed.
First of all - (thanks again) the client handler for the index change (OnItemShow) sitting in the head of the master page:
<telerik:RadCodeBlock runat="server">  
    <script type="text/javascript">  
        function OnItemShown(sender, arg) {  
            SendIDX(sender.get_currentItem()._index);  
        }  
        function SendIDX(nIDX) {  
            try {  
                PageMethods.SetIDX(nIDX);  
            }  
            catch (x) {  
            }  
        }  
    </script>  
</telerik:RadCodeBlock>  
 
And in code behind of the masterpage I do:
protected void Page_Load(object sender, EventArgs e) {  
...  
    RebindRotator(); //bind data to the rotator  
    if (!IsPostBack) {  
        if (Session["rotIDX"] != null) {  
            rrRot.InitialItemIndex = (int)Session["rotIDX"];  
        }  
...  
    }  
}  
 
That's all I had to do and now my rotator keeps it's current index across all the pages.
You may have noticed that I do 2 times a "try - catch" - once in the base page and ones in the javascript.
This is to remove dependance from the webmethod and the correct call of the webmethod.
So if I use a page in my masterpage which does not derived from my base class "PageMethods.SetIDX" is not there - no matter it is ignored.
And if I some call to SetIDX is made with wrong (missing) parameters - it also makes no problems.
So these two things make the solution transparent - no WebMethod there - no problem; wrong call to the method - no problem either.

Regards

Manfred
0
Fiko
Telerik team
answered on 23 Apr 2009, 03:42 PM
Hi Manfred,

I already answered you support ticket. It is good to know that you found a workaround for the index maintaining in your scenario.

Please do not hesitate to contact us if you have any problems.


Sincerely yours,
Fiko
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
ManniAT
Top achievements
Rank 2
answered on 23 Apr 2009, 04:18 PM
Hi Fiko,

I know you did answer my ticket (a long time ago - or in other words very fast).
And it was this answer what did not solve my problem - but brought me in the right direction!

Thanks again for you excellent support

Manfred
Tags
Rotator
Asked by
ManniAT
Top achievements
Rank 2
Answers by
ManniAT
Top achievements
Rank 2
Fiko
Telerik team
Share this question
or