Clicks im "empty space"

7 posts, 0 answers
  1. ManniAT
    ManniAT avatar
    877 posts
    Member since:
    Nov 2003

    Posted 10 Mar 2009 Link to this post

    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
  2. ManniAT
    ManniAT avatar
    877 posts
    Member since:
    Nov 2003

    Posted 11 Mar 2009 Link to this post

    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
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Fiko
    Admin
    Fiko avatar
    1406 posts

    Posted 12 Mar 2009 Link to this post

    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.
  5. ManniAT
    ManniAT avatar
    877 posts
    Member since:
    Nov 2003

    Posted 12 Mar 2009 Link to this post

    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
  6. ManniAT
    ManniAT avatar
    877 posts
    Member since:
    Nov 2003

    Posted 23 Apr 2009 Link to this post

    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
  7. Fiko
    Admin
    Fiko avatar
    1406 posts

    Posted 23 Apr 2009 Link to this post

    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.
  8. ManniAT
    ManniAT avatar
    877 posts
    Member since:
    Nov 2003

    Posted 23 Apr 2009 Link to this post

    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
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017