1

This is long-winded but should be easy for one of you knowledgable chaps to workout.

I have a DotNetNuke webpage with a dynamic login link. If you are not logged in the link will be 'login' and have the appropriate URL to a login popup. If you are logged in the link will be 'logout' and likewise have an the appropriate URL to the webpage that handles logout.

When the page determines if you are logged in or not the HTML link gets built with an attribute of : onclick="return dnnModal.show('http://blahblah.com....').

The code that does this:

 loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550));

Regardless of what the link is, the ID and Class always remain the same. My problem is that I would like to replace the login text with an image, infact a different image for login and logout. The issue here is that because the ID and Class stay the same I can't just do it via CSS as I normally would, but I have been able to style classes based on their attributes. I have tested this by finding out the output of the creation of the HTML link and styling the class based on the 'href' attribute for example:

a #dnn_dnnLogin_loginLink .LoginLink [href="http://some very very long dynamically created URL.aspx"]{ styles here }

The problem with this is the login/logout links change based on what page you are currently on.

I do know that each of the two rendered options has a uniqe attribue that I could style and that's their "Text" attribute. So quite simply how do I add this attribute to be rendered in HTML so that I can style it with CSS?

I have tried several variations such as:

loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550) " Text", + loginLink.Text);

In the hope that what would be rendered would be something like:

onclick="return dnnModal.show('http://localhost/CPD/tabid/87/ctl/Login/Default.aspx?returnurl=%2fCPD.aspx&popUp=true',/*showReturn*/true,200,550,true,'')" Text="Login"

So I could style:

a #dnn_dnnLogin_loginLink .LoginLink [Text="Login"]{styles here}
a #dnn_dnnLogin_loginLink .LoginLink [Text="Logout"]{styles here}

But instead I get a generic error. I have tried various ways of writing the line without success, I just don't know the syntax.

Could someone point me in the right direction? I so hope I'm not barking up the wrong tree as this would be a really simple solution to my initial problem.

Thanks,

Edit - Code for the whole page if that helps?

    using System;
using System.Web;
using System.Web.UI;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using DotNetNuke.UI.Modules;

namespace DotNetNuke.UI.Skins.Controls
{
public partial class Login : SkinObjectBase
{

    private const string MyFileName = "Login.ascx";

    public string Text { get; set; }

    public string CssClass { get; set; }

    public string LogoffText { get; set; }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        try
        {
            if (!String.IsNullOrEmpty(CssClass))
            {
                loginLink.CssClass = CssClass;
            }

            if (Request.IsAuthenticated)
            {
                if (!String.IsNullOrEmpty(LogoffText))
                {
                    if (LogoffText.IndexOf("src=") != -1)
                    {
                        LogoffText = LogoffText.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath);
                    }
                    loginLink.Text = LogoffText;
                }
                else
                {
                    loginLink.Text = Localization.GetString("Logout", Localization.GetResourceFile(this, MyFileName));
                }
                loginLink.NavigateUrl = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Logoff");
            }
            else
            {
                if (!String.IsNullOrEmpty(Text))
                {
                    if (Text.IndexOf("src=") != -1)
                    {
                        Text = Text.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath);
                    }
                    loginLink.Text = Text;
                }
                else
                {
                    loginLink.Text = Localization.GetString("Login", Localization.GetResourceFile(this, MyFileName));
                }

                string returnUrl = HttpContext.Current.Request.RawUrl;
                if (returnUrl.IndexOf("?returnurl=") != -1)
                {
                    returnUrl = returnUrl.Substring(0, returnUrl.IndexOf("?returnurl="));
                }
                returnUrl = HttpUtility.UrlEncode(returnUrl);

                loginLink.NavigateUrl = Globals.LoginURL(returnUrl, (Request.QueryString["override"] != null));

                if (PortalSettings.EnablePopUps && PortalSettings.LoginTabId == Null.NullInteger)
                {
                    loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550));
                }
            }
        }
        catch (Exception exc)
        {
            Exceptions.ProcessModuleLoadException(this, exc);
        }
    }

}
}
devio
  • 36,858
  • 7
  • 80
  • 143
Agamemnon
  • 587
  • 2
  • 15
  • 44
  • I dont really see why you cant add a second class. That would solve your problem, right? – Philip Daubmeier May 24 '12 at 08:39
  • I mean instead of replacing your "LoginLink" class, you can add another one, like: `` – Philip Daubmeier May 24 '12 at 08:41
  • I gotta be honest, I have no idea how I could change the class of each link as they are generated dynamically. I can post the code for the whole page if that makes it easier to grasp? – Agamemnon May 24 '12 at 09:03
  • I never worked with DotNetNuke, so I dont really know exactly if and how this could be done, but if you can add attributes, you should be able to add/modify classes, since ``class`` is an ordinary attribute as well. – Philip Daubmeier May 24 '12 at 09:06
  • Oh sorry, I see what you're saying. The thing is that line generates code for both links so if I add a class="Login" to that line it will render the page with the same class="Login" for both link possibilites. I reason I was heading towards attributes is that I know each link gets an attribute added to it dynamically that is different for each link. So everything is axactly the same for each link apart from two attributes: [href] and [text]. In the above code only one of these attributes is being rendered, I need to know how to add the other one as well - what the syntax for doing that is. – Agamemnon May 24 '12 at 09:15
  • Yes I see why you thought to do it this way around, but if it comes to styling you should use the things that are desinged for styling: classes. I added an answer below. – Philip Daubmeier May 24 '12 at 09:23

2 Answers2

1

CSS classes are just designed for this purpose, and they are supported by all browsers that use CSS styling (even very old ones). You don't have to fight around with obscure selectors that are referencing some link that could change and break your styling again.

Since you said you already have a class assigned to these tags, you just want to specify an additional one. You can have more than one class assinged to a tag. See the W3C css class page for more info, in section 'Attribute Values':

Specifies one or more class names for an element. To specify multiple classes, separate the class names with a space, e.g. . This allows you to combine several CSS classes for one HTML element.

You can set the second class simply by appending it to the WebControl.CssClass string, separated by a space:

loginLink.CssClass = loginLink.CssClass + " login";

or

loginLink.CssClass = loginLink.CssClass + " logout";

this way you can access it via a single class selector or even the multiple class selector (only selects those tags that have both classes assigned) in your CSS style sheet:

.LoginLink.login { /* styles here */ }
.LoginLink.logout { /* styles here */ }
Philip Daubmeier
  • 14,584
  • 5
  • 41
  • 77
  • If I knew the code better this is the path I would take but I don't know how to add the class conditionally. Would it simply be a case of adding another 'if'? like: if (Request.IsAuthenticated) { loginLink.CssClass = loginLink.CssClass + " login"; } Else { loginLink.CssClass = loginLink.CssClass + " logout";} – Agamemnon May 24 '12 at 10:00
  • Just set it where the text is set, too: after this line ``loginLink.Text = Localization.GetString("Logout", Localization.GetResourceFile(this, MyFileName));`` and the same for the 'login' text. – Philip Daubmeier May 24 '12 at 10:06
  • Well, after tinkering with what you had provided I have found what I need to do to get the classes changed conditionally. Thanks for the help. – Agamemnon May 24 '12 at 10:49
0

The text on the login/logout button is not stored in the Text="" attribute, but in the InnerHTML node. So your CSS selector would not apply. (I also think that the spacings in the selector are wrong, and that this solution would not support multilingual buttons, etc.)

Usually this type of styling would be implemented by in the Skin Editor (Admin/Skins/scroll down to section Skin Designer), where you select Skin or Container, File, Token=LOGIN, Setting=Text and LogoffText, and add a value src=path/to/a.gif. However, the skin designer seems to be broken in 6.1.x (bug report)

You might still try and have a look at the login.ascx and login.ascx.cs files in the admin\Skins directory of your DNN installation. Edit the code to assign loginLink.ImageUrl depending on Request.IsAuthenticated.

devio
  • 36,858
  • 7
  • 80
  • 143
  • Thanks for your input here. My proposed solution came about from me seeing that the link was created dynamically and me not knowing how to affect what went into the link (e.g. adding classes based on 'logged in'). The only thing I noticed was that Text/LogOffText could be rendered and so I assumed these could be attribues that I could use as selectors, I assume this is not the case? The code I posted was indeed from login.ascx.cs, how would I be able to add the class, say cssclass="login" to link? or is there a better method still? – Agamemnon May 24 '12 at 09:57
  • Yes, just as stated by Philip and your comment there – devio May 24 '12 at 10:20