Product attributes layour question

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
13 years ago
On my product page I use product variant attrributes, they work great but the layout is not very tidy, I added a few <div> around the attributes but if the user did not enter a required value the page blew up,  all I want is to have the atribute values left justyfied to make it look a little tydier, I added a line between each but that just makes the page longer.

Help

Steve
13 years ago
What version are you using? And you're talking attributes like size and color right? I have 1.70 and 1.80 running and mine ARE left justified.

Do you have a link to look at what you're talking about?
13 years ago
Barry,

Sorry I thought I had put in a link

http://www.abreena.co.uk/products/103-bride-groom-engraved-champagne-bottle-with-photograph.aspx

Do you have a link to yours?

I am running 1.80 and as I said below added a few line breaks, the text is left justifyed but the controls are all butted up to the end of the text and it looks a bit messy.

Thanks

Steve
13 years ago
I have tried to add a table with limited success, the label appears in the first column but the control is outside, any help appreciated as I would like to have the label and the control left justified, and both in the table

I have added a few lines of code for a table but if you look at the link you will see the problem

http://www.abreena.co.uk/products/103-bride-groom-engraved-champagne-bottle-with-photograph.aspx

Steve



//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  https://www.nopcommerce.com/License.aspx.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
//
// Contributor(s): _______.
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using NopSolutions.NopCommerce.BusinessLogic;
using NopSolutions.NopCommerce.BusinessLogic.Configuration.Settings;
using NopSolutions.NopCommerce.BusinessLogic.Directory;
using NopSolutions.NopCommerce.BusinessLogic.Localization;
using NopSolutions.NopCommerce.BusinessLogic.Products;
using NopSolutions.NopCommerce.BusinessLogic.Products.Attributes;
using NopSolutions.NopCommerce.BusinessLogic.Tax;
using NopSolutions.NopCommerce.Common.Utils;
using System.Globalization;
using NopSolutions.NopCommerce.Controls;

namespace NopSolutions.NopCommerce.Web.Modules
{
    public partial class ProductAttributesControl : BaseNopUserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            CreateAttributeControls();
        }

        public void CreateAttributeControls()
        {
            var productVariant = ProductManager.GetProductVariantById(this.ProductVariantId);
            if (productVariant != null)
            {
                this.phAttributes.Controls.Clear();
                var productVariantAttributes = productVariant.ProductVariantAttributes;
                if (productVariantAttributes.Count > 0)
                {
                    StringBuilder adjustmentTableScripts = new StringBuilder();
                    StringBuilder attributeScripts = new StringBuilder();

                    this.Visible = true;
                    foreach (var attribute in productVariantAttributes)
                    {
                        var divAttribute = new Panel();
                        var attributeTitle = new Label();

                        // CODE-CHANGE BY SM ADDED DIV ADDED SO EACH ATTRIBUTE ALIGNS ON LEFT
                        // *********************************************************
                        attributeTitle.Text = "<table width='100%' border='1'>";
                        attributeTitle.Text += "<tr >";
                        attributeTitle.Text += "<td width='33%'>";
                        // *********************************************************

                        if (attribute.IsRequired)
                            // attributeTitle.Text = "<span>*</span> ";
                            attributeTitle.Text += "<span style='color:red'><br/>*</span> "; // CODE-CHANGE BY SM * IS NOW COLOURED RED & <br /> ADDED
                        else
                            attributeTitle.Text += "<span><br/>&nbsp;&nbsp;</span>"; // CODE-CHANGE BY SM * IS NOW COLOURED RED & <br /> ADDED
                    

                        //text prompt / title
                        string textPrompt = string.Empty;
                        if (!string.IsNullOrEmpty(attribute.TextPrompt))
                            textPrompt = attribute.TextPrompt;
                        else
                            textPrompt = attribute.ProductAttribute.LocalizedName;

                        attributeTitle.Text += Server.HtmlEncode(textPrompt);
                        attributeTitle.Style.Add("font-weight", "bold");

                        //description
                        if (!string.IsNullOrEmpty(attribute.ProductAttribute.LocalizedDescription))
                            attributeTitle.Text += string.Format("<span>{0}</span>", Server.HtmlEncode(attribute.ProductAttribute.LocalizedDescription));

                        bool addBreak = true;
                        switch (attribute.AttributeControlType)
                        {
                            case AttributeControlTypeEnum.TextBox:
                            case AttributeControlTypeEnum.DropdownList: // CODE-CHANGE BY SM ~ NOT NEEDED
                            case AttributeControlTypeEnum.Datepicker: // CODE-CHANGE BY SM ~ NOT NEEDED
                                {
                                    //addBreak = false;  // CODE-CHANGE BY SM ~ ADDS NEW LINE FOR ALL CONTROLS
                                }
                                break;
                            default:
                                break;
                        }
                        if (addBreak)
                        {
                            attributeTitle.Text += "<br />";
                        }
                        else
                        {
                            attributeTitle.Text += "&nbsp;&nbsp;&nbsp;";
                        }

                      
                        divAttribute.Controls.Add(attributeTitle);
                        phAttributes.Controls.Add(divAttribute);

                        attributeTitle.Text += "</td>";  // CODE-CHANGE BY SM ADDED DIV ADDED SO EACH ATTRIBUTE ALIGNS ON LEFT
                        attributeTitle.Text += "<td>";  // CODE-CHANGE BY SM ADDED DIV ADDED SO EACH ATTRIBUTE ALIGNS ON LEFT



                      
                        string controlId = string.Format("{0}_{1}", attribute.ProductAttribute.ProductAttributeId, attribute.ProductVariantAttributeId);
                        switch (attribute.AttributeControlType)
                        {
                            case AttributeControlTypeEnum.DropdownList:
                                {
                                    var ddlAttributes = new DropDownList();
                                    ddlAttributes.ID = controlId;
                                    divAttribute.Controls.Add(ddlAttributes);
                                    ddlAttributes.Items.Clear();

                                    if (!attribute.IsRequired)
                                    {
                                        ddlAttributes.Items.Add(new ListItem("---", "0"));
                                    }
                                    var pvaValues = attribute.ProductVariantAttributeValues;

                                    adjustmentTableScripts.AppendFormat("{0}['{1}'] = new Array(", AdjustmentTableName, ddlAttributes.ClientID);
                                    attributeScripts.AppendFormat("$('#{0}').change(function(){{{1}();}});\n", ddlAttributes.ClientID, AdjustmentFuncName);

                                    bool preSelectedSet = false;
                                    foreach (var pvaValue in pvaValues)
                                    {
                                        string pvaValueName = pvaValue.LocalizedName;
                                        if (!this.HidePrices &&
                                            (!SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest)))
                                        {
                                            decimal taxRate = decimal.Zero;
                                            decimal priceAdjustmentBase = TaxManager.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                            decimal priceAdjustment = CurrencyManager.ConvertCurrency(priceAdjustmentBase, CurrencyManager.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);
                                            if (priceAdjustmentBase > decimal.Zero)
                                            {
                                                pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceAdjustment, false, false));
                                            }
                                            adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", (float)priceAdjustment);
                                        }
                                        var pvaValueItem = new ListItem(pvaValueName, pvaValue.ProductVariantAttributeValueId.ToString());
                                        if (!preSelectedSet && pvaValue.IsPreSelected)
                                        {
                                            pvaValueItem.Selected = pvaValue.IsPreSelected;
                                            preSelectedSet = true;
                                        }
                                        ddlAttributes.Items.Add(pvaValueItem);
                                    }
                                    adjustmentTableScripts.Length -= 1;
                                    adjustmentTableScripts.Append(");\n");
                                }
                                break;
                            case AttributeControlTypeEnum.RadioList:
                                {
                                    var rblAttributes = new RadioButtonList();
                                    rblAttributes.ID = controlId;
                                    divAttribute.Controls.Add(rblAttributes);
                                    rblAttributes.Items.Clear();

                                    var pvaValues = attribute.ProductVariantAttributeValues;
                                    bool preSelectedSet = false;
                                    foreach (var pvaValue in pvaValues)
                                    {
                                        string pvaValueName = pvaValue.LocalizedName;
                                        if (!this.HidePrices &&
                                            (!SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest)))
                                        {
                                            decimal taxRate = decimal.Zero;
                                            decimal priceAdjustmentBase = TaxManager.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                            decimal priceAdjustment = CurrencyManager.ConvertCurrency(priceAdjustmentBase, CurrencyManager.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);
                                            if (priceAdjustmentBase > decimal.Zero)
                                            {
                                                pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceAdjustment, false, false));
                                            }
                                            adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = {3};\n", AdjustmentTableName, rblAttributes.ClientID, rblAttributes.Items.Count, (float)priceAdjustment);
                                            attributeScripts.AppendFormat("$('#{0}_{1}').click(function(){{{2}();}});\n", rblAttributes.ClientID, rblAttributes.Items.Count, AdjustmentFuncName);
                                        }
                                        var pvaValueItem = new ListItem(Server.HtmlEncode(pvaValueName), pvaValue.ProductVariantAttributeValueId.ToString());
                                        if (!preSelectedSet && pvaValue.IsPreSelected)
                                        {
                                            pvaValueItem.Selected = pvaValue.IsPreSelected;
                                            preSelectedSet = true;
                                        }
                                        rblAttributes.Items.Add(pvaValueItem);
                                    }
                                }
                                break;
                            case AttributeControlTypeEnum.Checkboxes:
                                {
                                    var cblAttributes = new CheckBoxList();
                                    cblAttributes.ID = controlId;
                                    divAttribute.Controls.Add(cblAttributes);
                                    cblAttributes.Items.Clear();

                                    var pvaValues = attribute.ProductVariantAttributeValues;
                                    foreach (var pvaValue in pvaValues)
                                    {
                                        string pvaValueName = pvaValue.LocalizedName;
                                        if (!this.HidePrices &&
                                            (!SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest)))
                                        {
                                            decimal taxRate = decimal.Zero;
                                            decimal priceAdjustmentBase = TaxManager.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                            decimal priceAdjustment = CurrencyManager.ConvertCurrency(priceAdjustmentBase, CurrencyManager.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);
                                            if (priceAdjustmentBase > decimal.Zero)
                                                pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceA
13 years ago
Hi Mr. Shrek,

I feel for you brother!

I get the general direction you are trying to go.  Based on what it appears you are trying to do you will have a little bit of work ahead of you.  What I would suggest is to add a class to this area of your code:

// CODE-CHANGE BY SM ADDED DIV ADDED SO EACH ATTRIBUTE ALIGNS ON LEFT
                        // *********************************************************
                        attributeTitle.Text = "<table width='100%' border='1'>";
                        attributeTitle.Text += "<tr >";
                        attributeTitle.Text += "<td width='33%'>";
                        // *********************************************************


Something like this:

attribute.Text = "<table class='mycustomtableclass'>";


This is a good idea for several reasons:
1. It keeps inline styling out of your markup
2. It gives you way more control in your styling. e.g. table.mycustomclass td{height:20px;text-align:center;width:100px}
3. Because you are no longer in code-behind you don't have to recompile your application everytime you make a inline-styling change.  Just change your styling markup in styles.css and hit refresh.  Ahhhh, instance feedback.

Hope this helps and good luck.
13 years ago
Trevor,

Good pointer, will impliment that if I get the control (textbox, dropdown etc) to appear in the table, I am not sure were/how it is created I know it is in a panel but the rest is magic, and to top it all C is foriegn to me as I know VB.

Thanks

Steve
13 years ago
Steve,

If I understand your need, you want the attribute drop down to appear inside of the table you mentioned in your previous post.

This is possible but there are a lot of moving parts you will need to account for.  If you plan on using the drop down in a table for all of your products then there is less you have to do.  If this is the case, I would probably hard code a table 'around' the placeholder where the drop down is to be used. eg.

<table>
<tbody>
<tr>
<td><asp:placeholder/></td>
</tr>
</tbody>
</table>


If you plan on having a mix of products with a table and some without or if you need multiple attribute drop downs in your table then I would suggest a custom attribute control.  You will notice that in productattributes.cs there is a 'switch' and 'case'.  What you can do is add your own 'case'.  You will need to add it to the productattributeenum in the products/attribute folder of the BLL.

public enum AttributeControlTypeEnum : int
    {
        /// <summary>
        /// Dropdown list
        /// </summary>
        DropdownList = 1,
        /// <summary>
        /// Radio list
        /// </summary>
        RadioList = 2,
        /// <summary>
        /// Checkboxes
        /// </summary>
        Checkboxes = 3,
        /// <summary>
        /// TextBox
        /// </summary>
        TextBox = 4,
        /// <summary>
        /// Multiline textbox
        /// </summary>
        MultilineTextbox = 10,
        /// <summary>
        /// Datepicker
        /// </summary>
        Datepicker = 20,
///<summary>
///DropDownTable
///</summary>
DropDownTable = 5,

    }


Now in the productattributes.cs you would add your DropDownTable 'case' in the the same way you see the other controls.  Basically you will need to wrap your table around a dropdown or dropdowns.  You will also need to wire up the selected attributes.  This solution will give you a custom control that you can select from the attributes section in the admin.  It is a little more involved but it will be very robust and allow you to use it whenever you need it.

Another method and this may be the easiest for you to do, would be to add some custom classes to the dropdowns or any other controls that would allow you to move them around in the markup. e.g.

ddlAttributes.Attributes.Add("class", "customdropdownclass");


Then in your page you could move this dropdown where you need it using jQuery.  e.g.
$('.customdropdownclass').appendTo('.customtableclass td.customtablecell');


This is a little hacky but it's fast and reliable.  Hope this gives you some ideas to go on.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.