Question

please visit configurable product

please search for "color" using CTRL + F , than you can see "choose an option"

enter image description here

MRP : 100 , Special price : 50, Discount : 50 % OFF = > Fine

please change choose an option" to "Blue" ,than

MRP : 100 , Special price : 60 , Discount : 50 % OFF = > This is the problem, IT should show **"40% OFF" after change to "Blue".

enter image description here

Configurable.phtml

app/design/frontend/base/default/template/catalog/product/view/type/options/configurable.phtml  

<?php
$_product    = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
    <dl>
    <?php foreach($_attributes as $_attribute): ?>
        <dt><label class="required"><em>*</em><?php echo $_attribute->getLabel() ?></label></dt>
        <dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
            <div class="input-box">
                <select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select">
                    <option><?php echo $this->__('Choose an Option...') ?></option>
                  </select>
              </div>
        </dd>
    <?php endforeach; ?>
    </dl>
    <script type="text/javascript">
        var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
    </script>
<?php endif;?>

Configurable.js

if (typeof Product == 'undefined') {
    var Product = {};
}

/**************************** CONFIGURABLE PRODUCT **************************/
Product.Config = Class.create();
Product.Config.prototype = {
    initialize: function(config){
        this.config     = config;
        this.taxConfig  = this.config.taxConfig;
        if (config.containerId) {
            this.settings   = $$('#' + config.containerId + ' ' + '.super-attribute-select');
        } else {
            this.settings   = $$('.super-attribute-select');
        }
        this.state      = new Hash();
        this.priceTemplate = new Template(this.config.template);
        this.prices     = config.prices;

        // Set default values from config
        if (config.defaultValues) {
            this.values = config.defaultValues;
        }

        // Overwrite defaults by url
        var separatorIndex = window.location.href.indexOf('#');
        if (separatorIndex != -1) {
            var paramsStr = window.location.href.substr(separatorIndex+1);
            var urlValues = paramsStr.toQueryParams();
            if (!this.values) {
                this.values = {};
            }
            for (var i in urlValues) {
                this.values[i] = urlValues[i];
            }
        }

        // Overwrite defaults by inputs values if needed
        if (config.inputsInitialized) {
            this.values = {};
            this.settings.each(function(element) {
                if (element.value) {
                    var attributeId = element.id.replace(/[a-z]*/, '');
                    this.values[attributeId] = element.value;
                }
            }.bind(this));
        }

        // Put events to check select reloads
        this.settings.each(function(element){
            Event.observe(element, 'change', this.configure.bind(this))
        }.bind(this));

        // fill state
        this.settings.each(function(element){
            var attributeId = element.id.replace(/[a-z]*/, '');
            if(attributeId && this.config.attributes[attributeId]) {
                element.config = this.config.attributes[attributeId];
                element.attributeId = attributeId;
                this.state[attributeId] = false;
            }
        }.bind(this))

        // Init settings dropdown
        var childSettings = [];
        for(var i=this.settings.length-1;i>=0;i--){
            var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
            var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
            if (i == 0){
                this.fillSelect(this.settings[i])
            } else {
                this.settings[i].disabled = true;
            }
            $(this.settings[i]).childSettings = childSettings.clone();
            $(this.settings[i]).prevSetting   = prevSetting;
            $(this.settings[i]).nextSetting   = nextSetting;
            childSettings.push(this.settings[i]);
        }

        // Set values to inputs
        this.configureForValues();
        document.observe("dom:loaded", this.configureForValues.bind(this));
    },

    configureForValues: function () {
        if (this.values) {
            this.settings.each(function(element){
                var attributeId = element.attributeId;
                element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId];
                this.configureElement(element);
            }.bind(this));
        }
    },

    configure: function(event){
        var element = Event.element(event);
        this.configureElement(element);
    },

    configureElement : function(element) {
        this.reloadOptionLabels(element);
        if(element.value){
            this.state[element.config.id] = element.value;
            if(element.nextSetting){
                element.nextSetting.disabled = false;
                this.fillSelect(element.nextSetting);
                this.resetChildren(element.nextSetting);
            }
        }
        else {
            this.resetChildren(element);
        }
        this.reloadPrice();
    },

    reloadOptionLabels: function(element){
        var selectedPrice;
        if(element.options[element.selectedIndex].config && !this.config.stablePrices){
            selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
        }
        else{
            selectedPrice = 0;
        }
        for(var i=0;i<element.options.length;i++){
            if(element.options[i].config){
                element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
            }
        }
    },

    resetChildren : function(element){
        if(element.childSettings) {
            for(var i=0;i<element.childSettings.length;i++){
                element.childSettings[i].selectedIndex = 0;
                element.childSettings[i].disabled = true;
                if(element.config){
                    this.state[element.config.id] = false;
                }
            }
        }
    },

    fillSelect: function(element){
        var attributeId = element.id.replace(/[a-z]*/, '');
        var options = this.getAttributeOptions(attributeId);
        this.clearSelect(element);
        element.options[0] = new Option('', '');
        element.options[0].innerHTML = this.config.chooseText;

        var prevConfig = false;
        if(element.prevSetting){
            prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
        }

        if(options) {
            var index = 1;
            for(var i=0;i<options.length;i++){
                var allowedProducts = [];
                if(prevConfig) {
                    for(var j=0;j<options[i].products.length;j++){
                        if(prevConfig.config.allowedProducts
                            && prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){
                            allowedProducts.push(options[i].products[j]);
                        }
                    }
                } else {
                    allowedProducts = options[i].products.clone();
                }

                if(allowedProducts.size()>0){
                    options[i].allowedProducts = allowedProducts;
                    element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
                    if (typeof options[i].price != 'undefined') {
                        element.options[index].setAttribute('price', options[i].price);
                    }
                    element.options[index].config = options[i];
                    index++;
                }
            }
        }
    },

    getOptionLabel: function(option, price){
        var price = parseFloat(price);
        if (this.taxConfig.includeTax) {
            var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
            var excl = price - tax;
            var incl = excl*(1+(this.taxConfig.currentTax/100));
        } else {
            var tax = price * (this.taxConfig.currentTax / 100);
            var excl = price;
            var incl = excl + tax;
        }

        if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
            price = incl;
        } else {
            price = excl;
        }

        var str = option.label;
        if(price){
            if (this.taxConfig.showBothPrices) {
                str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
            } else {
                str+= ' ' + this.formatPrice(price, true);
            }
        }
        return str;
    },

    formatPrice: function(price, showSign){
        var str = '';
        price = parseFloat(price);
        if(showSign){
            if(price<0){
                str+= '-';
                price = -price;
            }
            else{
                str+= '+';
            }
        }

        var roundedPrice = (Math.round(price*100)/100).toString();

        if (this.prices && this.prices[roundedPrice]) {
            str+= this.prices[roundedPrice];
        }
        else {
            str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
        }
        return str;
    },

    clearSelect: function(element){
        for(var i=element.options.length-1;i>=0;i--){
            element.remove(i);
        }
    },

    getAttributeOptions: function(attributeId){
        if(this.config.attributes[attributeId]){
            return this.config.attributes[attributeId].options;
        }
    },

    reloadPrice: function(){
        if (this.config.disablePriceReload) {
            return;
        }
        var price    = 0;
        var oldPrice = 0;
        for(var i=this.settings.length-1;i>=0;i--){
            var selected = this.settings[i].options[this.settings[i].selectedIndex];
            if(selected.config){
                price    += parseFloat(selected.config.price);
                oldPrice += parseFloat(selected.config.oldPrice);
            }
        }

        optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
        optionsPrice.reload();

        return price;

        if($('product-price-'+this.config.productId)){
            $('product-price-'+this.config.productId).innerHTML = price;
        }
        this.reloadOldPrice();
    },

    reloadOldPrice: function(){
        if (this.config.disablePriceReload) {
            return;
        }
        if ($('old-price-'+this.config.productId)) {

            var price = parseFloat(this.config.oldPrice);
            for(var i=this.settings.length-1;i>=0;i--){
                var selected = this.settings[i].options[this.settings[i].selectedIndex];
                if(selected.config){
                    price+= parseFloat(selected.config.price);
                }
            }
            if (price < 0)
                price = 0;
            price = this.formatPrice(price);

            if($('old-price-'+this.config.productId)){
                $('old-price-'+this.config.productId).innerHTML = price;
            }

        }
    }
}

Price .phtml = > http://pastebin.com/cPXyxy6E // only 30000 char allowed

we are using following code for

app/code/community/OrganicInternet/SimpleConfigurableProducts/Catalog/Model/Product/Type/Configurable/Price.php 

<?php

    #The methods in there have become a bit convoluted, so it could benefit from a tidy,
    #...though the logic is not that simple any more.

    class OrganicInternet_SimpleConfigurableProducts_Catalog_Model_Product_Type_Configurable_Price
        extends Mage_Catalog_Model_Product_Type_Configurable_Price
    {
        #We don't want to show a separate 'minimal' price for configurable products.
        public function getMinimalPrice($product)
        {
            return $this->getPrice($product);
        }

        public function getMaxPossibleFinalPrice($product) {
            #Indexer calculates max_price, so if this value's been loaded, use it
            $price = $product->getMaxPrice();
            if ($price !== null) {
                return $price;
            }

            $childProduct = $this->getChildProductWithHighestPrice($product, "finalPrice");
            #If there aren't any salable child products we return the highest price
            #of all child products, including any ones not currently salable.

            if (!$childProduct) {
                $childProduct = $this->getChildProductWithHighestPrice($product, "finalPrice", false);
            }

            if ($childProduct) {
                return $childProduct->getFinalPrice();
            }
            return false;
        }

        #If there aren't any salable child products we return the lowest price
        #of all child products, including any ones not currently salable.
        public function getFinalPrice($qty=null, $product)
    {
        //Start edit
        $selectedAttributes = array();
        if ($product->getCustomOption('attributes')) {
            $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
        }
        //End edit
        if (sizeof($selectedAttributes)) return $this->getSimpleProductPrice($qty, $product);

        if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) {
            return $product->getCalculatedFinalPrice();
        }

        $basePrice = $this->getBasePrice($product, $qty);
        $finalPrice = $basePrice;
        $product->setFinalPrice($finalPrice);
        Mage::dispatchEvent('catalog_product_get_final_price', array('product' => $product, 'qty' => $qty));
        $finalPrice = $product->getData('final_price');

        $finalPrice += $this->getTotalConfigurableItemsPrice($product, $finalPrice);
        $finalPrice += $this->_applyOptionsPrice($product, $qty, $basePrice) - $basePrice;
        $finalPrice = max(0, $finalPrice);

        $product->setFinalPrice($finalPrice);
        return $finalPrice;
    }

    public function getSimpleProductPrice($qty=null, $product)
        {
            $cfgId = $product->getId();
            $product->getTypeInstance(true)
                ->setStoreFilter($product->getStore(), $product);
            $attributes = $product->getTypeInstance(true)
                ->getConfigurableAttributes($product);
            $selectedAttributes = array();
            if ($product->getCustomOption('attributes')) {
                $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue());
            }
            $db = Mage::getSingleton('core/resource')->getConnection('core_read');
            $dbMeta = Mage::getSingleton('core/resource');
            $sql = <<<SQL
    SELECT main_table.entity_id FROM {$dbMeta->getTableName('catalog/product')} `main_table` INNER JOIN
    {$dbMeta->getTableName('catalog/product_super_link')} `sl` ON sl.parent_id = {$cfgId}
    SQL;
            foreach($selectedAttributes as $attributeId => $optionId) {
                $alias = "a{$attributeId}";
                $sql .= ' INNER JOIN ' . $dbMeta->getTableName('catalog/product') . "_int" . " $alias ON $alias.entity_id = main_table.entity_id AND $alias.attribute_id = $attributeId AND $alias.value = $optionId AND $alias.entity_id = sl.product_id";
            }
            $id = $db->fetchOne($sql);
            return Mage::getModel("catalog/product")->load($id)->getFinalPrice($qty);
        }

        public function getPrice($product)
        {
            #Just return indexed_price, if it's been fetched already
            #(which it will have been for collections, but not on product page)
            $price = $product->getIndexedPrice();
            if ($price !== null) {
                return $price;
            }

            $childProduct = $this->getChildProductWithLowestPrice($product, "finalPrice");
            #If there aren't any salable child products we return the lowest price
            #of all child products, including any ones not currently salable.
            if (!$childProduct) {
                $childProduct = $this->getChildProductWithLowestPrice($product, "finalPrice", false);
            }

            if ($childProduct) {
                return $childProduct->getPrice();
            }

            return false;
        }

        public function getChildProducts($product, $checkSalable=true)
        {
            static $childrenCache = array();
            $cacheKey = $product->getId() . ':' . $checkSalable;

            if (isset($childrenCache[$cacheKey])) {
                return $childrenCache[$cacheKey];
            }

            $childProducts = $product->getTypeInstance(true)->getUsedProductCollection($product);
            $childProducts->addAttributeToSelect(array('price', 'special_price', 'status', 'special_from_date', 'special_to_date'));

            if ($checkSalable) {
                $salableChildProducts = array();
                foreach($childProducts as $childProduct) {
                    if($childProduct->isSalable()) {
                        $salableChildProducts[] = $childProduct;
                    }
                }
                $childProducts = $salableChildProducts;
            }

            $childrenCache[$cacheKey] = $childProducts;
            return $childProducts;
        }

    /*
        public function getLowestChildPrice($product, $priceType, $checkSalable=true)
        {
            $childProduct = $this->getChildProductWithLowestPrice($product, $priceType, $checkSalable);
            if ($childProduct) {
                if ($priceType == "finalPrice") {
                    $childPrice = $childProduct->getFinalPrice();
                } else {
                    $childPrice = $childProduct->getPrice();
                }
            } else {
                $childPrice = false;
            }
            return $childPrice;
        }
    */
        #Could no doubt add highest/lowest as param to save 2 near-identical functions
        public function getChildProductWithHighestPrice($product, $priceType, $checkSalable=true)
        {
            $childProducts = $this->getChildProducts($product, $checkSalable);
            if (count($childProducts) == 0) { #If config product has no children
                return false;
            }
            $maxPrice = 0;
            $maxProd = false;
            foreach($childProducts as $childProduct) {
                if ($priceType == "finalPrice") {
                    $thisPrice = $childProduct->getFinalPrice();
                } else {
                    $thisPrice = $childProduct->getPrice();
                }
                if($thisPrice > $maxPrice) {
                    $maxPrice = $thisPrice;
                    $maxProd = $childProduct;
                }
            }
            return $maxProd;
        }

        public function getChildProductWithLowestPrice($product, $priceType, $checkSalable=true)
        {
            $childProducts = $this->getChildProducts($product, $checkSalable);
            if (count($childProducts) == 0) { #If config product has no children
                return false;
            }
            $minPrice = PHP_INT_MAX;
            $minProd = false;
            foreach($childProducts as $childProduct) {
                if ($priceType == "finalPrice") {
                    $thisPrice = $childProduct->getFinalPrice();
                } else {
                    $thisPrice = $childProduct->getPrice();
                }
                if($thisPrice < $minPrice) {
                    $minPrice = $thisPrice;
                    $minProd = $childProduct;
                }
            }
            return $minProd;
        }

        //Force tier pricing to be empty for configurable products:
        public function getTierPrice($qty=null, $product)
        {
            return array();
        }
    }
Was it helpful?

Solution

I see that you are using the Simple Configurable Product extension. You can simply modify the file scp_product_extension.js and add the below two lines of code after line 177 in the javascript file:

var discountAmount = ((price - finalPrice) / price) * 100;
jQuery('.you_save_price').text(discountAmount + '%');

What this is doing is that everytime you select an option the SCP extension javascript file is reloading the price, so adding this code to that js file should do the trick. I tested it on the site provided above. Please give it a shot and let me know if it works!

OTHER TIPS

Lables "50%OFF" only change one time on loading time.

There was no js regarding change in "50%OFF" lable in configurable.js Its calling from price.phtml file.

So need to write javascript for that in your configurable.js file.

Also check in price.phtml file for %OFF coding. I think you are using SCP (https://github.com/organicinternet/magento-configurable-simple)

Place this code in reloadPrice: function() { } before return price in Configurable.js

place your amount/percent in div using jquery.

savePercent = parseFloat( 100 - (Math.round((optionsPrice.productPrice/optionsPrice.productOldPrice) * 100))).toString() ;
saveAmount = parseFloat( optionsPrice.productOldPrice - optionsPrice.productPrice);
console.log( 'Percent: '+savePercent );
console.log( 'Amount: '+saveAmount );

$('save_perc').innerHTML = savePercent;

in your price.phtml file

<div class="You_savee">
    <p class="special-price yousave">
        <span class="label yousave_label">You Save:</span>
        <span class="you_save_price" id="save_perc">50%</span>
    </p>
</div>

add "save_perc" id in you_save_price class. Clear cache folder.

I hope this helps you. Enjoy coding.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top