Robert
Robert

Reputation: 812

element null in Magento

I upgrade magento from 1.8.1 to 1.9.0, and I have a problem with one js file:

TypeError: $(...) is null
$('product_addtocart_form').getElements().each(function(el) {


simple_product_pricing.js (line 1131, col 5)

I think this file is related to the Ayasoftware_SimpleProductPricing, maybe someone can help me to solve this. Before upgrade in 1.8.1 version everything was fine, in 1.9.0 version I have this error.

I will add here the entire js:

/*

    Some of these override earlier varien/product.js methods, therefore

    varien/product.js must have been included prior to this file.

    some of these functions were initially written by Matt Dean ( http://organicinternet.co.uk/ )

*/ 



Product.Config.prototype.getMatchingSimpleProduct = function(){

    var inScopeProductIds = this.getInScopeProductIds();

    if ((typeof inScopeProductIds != 'undefined') && (inScopeProductIds.length == 1)) {

        return inScopeProductIds[0];

    }

    return false;

};



/*

    Find products which are within consideration based on user's selection of

    config options so far

    Returns a normal array containing product ids

    allowedProducts is a normal numeric array containing product ids.

    childProducts is a hash keyed on product id

    optionalAllowedProducts lets you pass a set of products to restrict by,

    in addition to just using the ones already selected by the user

*/

Product.Config.prototype.getInScopeProductIds = function(optionalAllowedProducts) {



    var childProducts = this.config.childProducts;

    var allowedProducts = [];



    if ((typeof optionalAllowedProducts != 'undefined') && (optionalAllowedProducts.length > 0)) {

        allowedProducts = optionalAllowedProducts;

    }



    for(var s=0, len=this.settings.length-1; s<=len; s++) {

        if (this.settings[s].selectedIndex <= 0){

            break;

        }

        var selected = this.settings[s].options[this.settings[s].selectedIndex];

        if (s==0 && allowedProducts.length == 0){

            allowedProducts = selected.config.allowedProducts;

        } else {

            allowedProducts = allowedProducts.intersect(selected.config.allowedProducts).uniq();

        }

    }



    //If we can't find any products (because nothing's been selected most likely)

    //then just use all product ids.

    if ((typeof allowedProducts == 'undefined') || (allowedProducts.length == 0)) {

        productIds = Object.keys(childProducts);

    } else {

        productIds = allowedProducts;

    }

    return productIds;

};





Product.Config.prototype.getProductIdOfCheapestProductInScope = function(priceType, optionalAllowedProducts) {



    var childProducts = this.config.childProducts;

    var productIds = this.getInScopeProductIds(optionalAllowedProducts);



    var minPrice = Infinity;

    var lowestPricedProdId = false;



    //Get lowest price from product ids.

    for (var x=0, len=productIds.length; x<len; ++x) {

        var thisPrice = Number(childProducts[productIds[x]][priceType]);

        if (thisPrice < minPrice) {

            minPrice = thisPrice;

            lowestPricedProdId = productIds[x];

        }

    }

    return lowestPricedProdId;

};





Product.Config.prototype.getProductIdOfMostExpensiveProductInScope = function(priceType, optionalAllowedProducts) {



    var childProducts = this.config.childProducts;

    var productIds = this.getInScopeProductIds(optionalAllowedProducts);



    var maxPrice = 0;

    var highestPricedProdId = false;



    //Get highest price from product ids.

    for (var x=0, len=productIds.length; x<len; ++x) {

        var thisPrice = Number(childProducts[productIds[x]][priceType]);

        if (thisPrice >= maxPrice) {

            maxPrice = thisPrice;

            highestPricedProdId = productIds[x];

        }

    }

    return highestPricedProdId;

};



Product.OptionsPrice.prototype.updateSpecialPriceDisplay = function(price, finalPrice) {



    var prodForm = $('product_addtocart_form');



    jQuery('p.msg').hide();

    jQuery('div.price-box').show();



    var specialPriceBox = prodForm.select('p.special-price');

    var oldPricePriceBox = prodForm.select('p.old-price, p.was-old-price');

    var magentopriceLabel = prodForm.select('span.price-label');



    if (price == finalPrice) {

        //specialPriceBox.each(function(x) {x.hide();});

        magentopriceLabel.each(function(x) {x.hide();});

        oldPricePriceBox.each(function(x) { x.hide();

//            x.removeClassName('old-price');

  //          x.addClassName('was-old-price');

        });

        jQuery('.product-shop').removeClass('sale-product') ;

    }else{

        specialPriceBox.each(function(x) {x.show();});

        magentopriceLabel.each(function(x) {x.show();});

        oldPricePriceBox.each(function(x) { x.show();

            x.removeClassName('was-old-price');

            x.addClassName('old-price');

        });

        jQuery('.product-shop').addClass('sale-product') ;

    }



};



//This triggers reload of price and other elements that can change

//once all options are selected

Product.Config.prototype.reloadPrice = function() {

    var childProductId = this.getMatchingSimpleProduct();

    var childProducts = this.config.childProducts;

    var usingZoomer = false;

    if(this.config.imageZoomer){

        usingZoomer = true;

    }



    if(childProductId){

        var price = childProducts[childProductId]["price"];

        var finalPrice = childProducts[childProductId]["finalPrice"];

        optionsPrice.productPrice = finalPrice;

        optionsPrice.productOldPrice = price;

        optionsPrice.reload();

        optionsPrice.reloadPriceLabels(true);

        optionsPrice.updateSpecialPriceDisplay(price, finalPrice);

        if(this.config.updateShortDescription) {

          this.updateProductShortDescription(childProductId);

        } 

        if(this.config.updateDescription) {

          this.updateProductDescription(childProductId);

        }

        if(this.config.updateProductName) {

          this.updateProductName(childProductId);

        } 

        if(this.config.customStockDisplay) {

            this.updateProductAvailability(childProductId);

        }       

        this.showTierPricingBlock(childProductId, this.config.productId);

        if (usingZoomer) {

            this.showFullImageDiv(childProductId, this.config.productId);

        } else {

           if(this.config.updateproductimage) {

               this.updateProductImage(childProductId);

           } 

        }



    } else {

        var cheapestPid = this.getProductIdOfCheapestProductInScope("finalPrice");

        var price = childProducts[cheapestPid]["price"];

        var finalPrice = childProducts[cheapestPid]["finalPrice"];

        optionsPrice.productPrice = finalPrice;

        optionsPrice.productOldPrice = price;

        optionsPrice.reload();

        optionsPrice.reloadPriceLabels(false);

        if(this.config.updateProductName) {

          this.updateProductName(false);

        }

        if(this.config.updateShortDescription) {

           this.updateProductShortDescription(false);

        }

        if(this.config.updateDescription) {

           this.updateProductDescription(false);

        }

        if(this.config.customStockDisplay) {

           this.updateProductAvailability(false);

        } 

        optionsPrice.updateSpecialPriceDisplay(price, finalPrice);

        this.showTierPricingBlock(false);

        this.showCustomOptionsBlock(false, false);

        if (usingZoomer) {

            this.showFullImageDiv(false, false);

        } else {

           if(this.config.updateproductimage) {

                   this.updateProductImage(false);

           }

        }

    }

};





Product.Config.prototype.updateProductImage = function(productId) {

    var imageUrl = this.config.imageUrl;

    if(productId && this.config.childProducts[productId].imageUrl) {

        imageUrl = this.config.childProducts[productId].imageUrl;

    }

    if (!imageUrl) {

        return;

    }

    if($('image')) {

        $('image').src = imageUrl;

    } else {

        $$('#product_addtocart_form p.product-image img').each(function(el) {

            var dims = el.getDimensions();

            el.src = imageUrl;

            el.width = dims.width;

            el.height = dims.height;

        });

    }

};



Product.Config.prototype.updateProductName = function(productId) {

    var productName = this.config.productName;   

    if (productId && this.config.ProductNames[productId].ProductName) {

        productName = this.config.ProductNames[productId].ProductName;

    }

    $$('#product_addtocart_form div.product-name h1').each(function(el) {

        el.innerHTML = productName;

    });



    var productSku = this.config.sku ;

    if (productId && this.config.childProducts[productId].sku) {

        productSku = this.config.childProducts[productId].sku ;

    }

    jQuery('.sku span').text(productSku) ;



    var productDelivery = this.config.delivery;

    if (productId && this.config.childProducts[productId].delivery) {

        productDelivery = this.config.childProducts[productId].delivery ;

    }

    jQuery('.delivery-info').html(productDelivery) ;



    var productReturns = this.config.returns;

    if (productId && this.config.childProducts[productId].returns) {

        productReturns = this.config.childProducts[productId].returns ;

    }

    jQuery('.returns-info').html(productReturns) ;



    var productDownloads = this.config.downloads;

    if (productId && this.config.childProducts[productId].downloads) {

        productDownloads = this.config.childProducts[productId].downloads;

    }

    if (productDownloads) jQuery('.downloads-info').html(productDownloads) ;

    else jQuery('.downloads-info').html('There are no downloads for this product') ;



    var productAttribs = this.config.attributesTable;

    if (productId && this.config.childProducts[productId].attributesTable) {

        productAttribs = this.config.childProducts[productId].attributesTable ;

    }

    jQuery('.attribs-info').html(productAttribs) ;

    decorateTable('product-attribute-specs-table') ;



    if (productId && this.config.childProducts[productId].isNew) {

        jQuery('.product-image .new-label').show() ;

    } else {

        jQuery('.product-image .new-label').hide() ;

    }



    if (productId && this.config.childProducts[productId].isOnSale) {

        jQuery('.product-image .sale-label').show() ;

    } else {

        jQuery('.product-image .sale-label').hide() ;

    }





    if (productId) jQuery('input[name="pid"]').val(productId) ;

};



Product.Config.prototype.updateProductAvailability = function(productId) {

    var stockInfo = this.config.stockInfo;

    var is_in_stock = false;

    var stockLabel = '';

    if (productId && stockInfo[productId]["stockLabel"]) {

        stockLabel = stockInfo[productId]["stockLabel"];

        stockQty = stockInfo[productId]["stockQty"];

        is_in_stock =  stockInfo[productId]["is_in_stock"];

    }

    $$('#product_addtocart_form p.availability span').each(function(el) {

        if(is_in_stock) {

            $$('#product_addtocart_form p.availability').each(function(es) {

                 es.removeClassName('availability out-of-stock');

                 es.addClassName('availability in-stock');

            });

             el.innerHTML = /*stockQty + '  ' + */stockLabel;

        } else {

             $$('#product_addtocart_form p.availability').each(function(ef) {

                 ef.removeClassName('availability in-stock');

                 ef.addClassName('availability out-of-stock');

             });

                el.innerHTML = stockLabel;

        }



    });

};



Product.Config.prototype.updateProductShortDescription = function(productId) {

   var shortDescription = this.config.shortDescription;

    if (productId && this.config.shortDescriptions[productId].shortDescription) {

        shortDescription = this.config.shortDescriptions[productId].shortDescription;

    }

    $$('#product_addtocart_form div.short-description div.std').each(function(el) {

        el.innerHTML = shortDescription;

    });

};



Product.Config.prototype.updateProductDescription = function(productId) {

   var description = this.config.description;

    if (productId && this.config.Descriptions[productId].Description) {

        description = this.config.Descriptions[productId].Description;

    }

    $$('#product_tabs_description_tabbed_contents div.std').each(function(el) {

        el.innerHTML = description;

    });

};



Product.Config.prototype.updateProductAttributes = function(productId) {

    var productAttributes = this.config.productAttributes;

    if (productId && this.config.childProducts[productId].productAttributes) {

        productAttributes = this.config.childProducts[productId].productAttributes;

    }

    //If config product doesn't already have an additional information section,

    //it won't be shown for associated product either. It's too hard to work out

    //where to place it given that different themes use very different html here

    console.log(productAttributes) ;

    $$('div.product-collateral div.attribs-info').each(function(el) {



        el.innerHTML = productAttributes;

        decorateTable('product-attribute-specs-table');

    });

};



Product.Config.prototype.showCustomOptionsBlock = function(productId, parentId) {

    var coUrl = this.config.ajaxBaseUrl + "co/?id=" + productId + '&pid=' + parentId;

    var prodForm = $('product_addtocart_form');



   if ($('SCPcustomOptionsDiv')==null) {

      return;

   }



    Effect.Fade('SCPcustomOptionsDiv', { duration: 0.5, from: 1, to: 0.5 });

    if(productId) {

        //Uncomment the line below if you want an ajax loader to appear while any custom

        //options are being loaded.

        //$$('span.scp-please-wait').each(function(el) {el.show()});



        //prodForm.getElements().each(function(el) {el.disable()});

        new Ajax.Updater('SCPcustomOptionsDiv', coUrl, {

          method: 'get',

          evalScripts: true,

          onComplete: function() {

              $$('span.scp-please-wait').each(function(el) {el.hide()});

              Effect.Fade('SCPcustomOptionsDiv', { duration: 0.5, from: 0.5, to: 1 });

              //prodForm.getElements().each(function(el) {el.enable()});

          }

        });

    } else {

        $('SCPcustomOptionsDiv').innerHTML = '';

        try{window.opConfig = new Product.Options([]);} catch(e){}

    }

};





Product.OptionsPrice.prototype.reloadPriceLabels = function(productPriceIsKnown) {

    var priceFromLabel = '';

    var prodForm = $('product_addtocart_form');



    if (!productPriceIsKnown && typeof spConfig != "undefined") {

        priceFromLabel = spConfig.config.priceFromLabel;

    }



    var priceSpanId = 'configurable-price-from-' + this.productId;

    var duplicatePriceSpanId = priceSpanId + this.duplicateIdSuffix;



    if($(priceSpanId) && $(priceSpanId).select('span.configurable-price-from-label'))

        $(priceSpanId).select('span.configurable-price-from-label').each(function(label) {

        label.innerHTML = priceFromLabel;

    });



    if ($(duplicatePriceSpanId) && $(duplicatePriceSpanId).select('span.configurable-price-from-label')) {

        $(duplicatePriceSpanId).select('span.configurable-price-from-label').each(function(label) {

            label.innerHTML = priceFromLabel;

        });

    }

};







//SCP: Forces the 'next' element to have it's optionLabels reloaded too

Product.Config.prototype.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.reloadOptionLabels(element.nextSetting);

            this.resetChildren(element.nextSetting);

        }

    }

    else {

        this.resetChildren(element);

    }

    this.reloadPrice();

};





//SCP: Changed logic to use absolute price ranges rather than price differentials

Product.Config.prototype.reloadOptionLabels = function(element){

    var selectedPrice;

    var childProducts = this.config.childProducts;

    var stockInfo = this.config.stockInfo;



    //Don't update elements that have a selected option

    if(element.options[element.selectedIndex].config){

        return;

    }



    for(var i=0;i<element.options.length;i++){

        if(element.options[i].config){

            var cheapestPid = this.getProductIdOfCheapestProductInScope("finalPrice", element.options[i].config.allowedProducts);

            var mostExpensivePid = this.getProductIdOfMostExpensiveProductInScope("finalPrice", element.options[i].config.allowedProducts);

            var cheapestFinalPrice = childProducts[cheapestPid]["finalPrice"];

            var mostExpensiveFinalPrice = childProducts[mostExpensivePid]["finalPrice"];

            var stock = '';



            if(cheapestPid == mostExpensivePid ){

                if(stockInfo[cheapestPid]["stockLabel"] != '') {

                  stock = '( ' +stockInfo[cheapestPid]["stockLabel"] + ' )';

                } 

            }

            if (this.config.showOutOfStock){

                if(this.config.disable_out_of_stock_option ) {

                    if(!stockInfo[cheapestPid]["is_in_stock"] ) {

                        if(cheapestPid == mostExpensivePid ){

                           element.options[i].disabled=true;

                            var stock = '( ' +stockInfo[cheapestPid]["stockLabel"] + ' )';

                        }

                    }

                }

            }

            var tierpricing = childProducts[mostExpensivePid]["tierpricing"];

            element.options[i].text = this.getOptionLabel(element.options[i].config, cheapestFinalPrice, mostExpensiveFinalPrice, stock , tierpricing);

        }

    }

};



Product.Config.prototype.showTierPricingBlock = function(productId, parentId) {    



    var coUrl = this.config.ajaxBaseUrl + "co/?id=" + productId + '&pid=' + parentId;

    var prodForm = $('product_addtocart_form');

       if(productId) {

            new Ajax.Updater('sppTierPricingDiv', coUrl, {



              method: 'get',

              evalScripts: true,

              onComplete: function() {

                  $$('span.scp-please-wait').each(function(el) {el.hide()});

              }

            });

        } else {

            $('sppTierPricingDiv').innerHTML = '';

        }

    };



//SCP: Changed label formatting to show absolute price ranges rather than price differentials

Product.Config.prototype.getOptionLabel = function(option, lowPrice, highPrice, stock, tierpricing){

    var str = option.label;

    if(tierpricing > 0  && tierpricing < lowPrice) {

    var tierpricinglowestprice = ': As low as (' + this.formatPrice(tierpricing,false) + ')';

    } else {

        var tierpricinglowestprice = '';

    }

    if (!this.config.showPriceRangesInOptions) {

        return str;

    }



    if (!this.config.showOutOfStock){

        stock = '';

    }



    lowPrices = this.getTaxPrices(lowPrice);

    highPrices = this.getTaxPrices(highPrice);



    if (this.config.hideprices) {

        if (this.config.showOutOfStock){

               return str + '  ' + stock + '  ';

        } else {

            return str;

        }

    }



    var to = ' ' + this.config.rangeToLabel + ' ';

    var separator = ': ( ';



    if(lowPrice && highPrice){

        if (this.config.showfromprice) {

          this.config.priceFromLabel = this.config.priceFromLabel; //'From: ';

        } 

        if (lowPrice != highPrice) {

            if (this.taxConfig.showBothPrices) {

                str+= separator + this.formatPrice(lowPrices[2], false) + ' (' + this.formatPrice(lowPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';

                str+= to + this.formatPrice(highPrices[2], false) + ' (' + this.formatPrice(highPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';

                str += " ) ";

            } else {

                str+= separator + this.formatPrice(lowPrices[0], false);

                str+= to + this.formatPrice(highPrices[0], false);

                str += " ) ";

            }

        } else {



            if (this.taxConfig.showBothPrices) {

                str+= separator + this.formatPrice(lowPrices[2], false) + ' (' + this.formatPrice(lowPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';

                str += " ) ";

                str += stock;

                str += tierpricinglowestprice;

            } else {

                if(tierpricing == 0 ) {

                    str+= separator + this.formatPrice(lowPrices[0], false);

                    str += " ) ";

                }

                str += tierpricinglowestprice;

                str += '  ' + stock;

            }

        }

    }

    return str;

};





//SCP: Refactored price calculations into separate function

Product.Config.prototype.getTaxPrices = function(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;

    }



    return [price, incl, excl];

};

//SCP: Forces price labels to be updated on load

//so that first select shows ranges from the start

document.observe("dom:loaded", function() {

    //Really only needs to be the first element that has configureElement set on it,

    //rather than all.

    if (typeof opConfig  != "undefined") {

        spConfig.reloadPrice();

    }

    $('product_addtocart_form').getElements().each(function(el) {

        if(el.type == 'select-one') {

            if(el.options && (el.options.length > 1)) {

                el.options[0].selected = true;

                spConfig.reloadOptionLabels(el);

            }

        }

    }); 

});

Thank you

Upvotes: 0

Views: 387

Answers (1)

codedge
codedge

Reputation: 5174

The version 1.5.11 is not compatible w/ Magento 1.9 according to the extension version on Magento connect. Please obtain the newest version of the extension and/or ask the creator to give you support. As far as I can see 1.9 support is support with 1.11.6, released 11th March 2015. The infos on their homepage and Magento connect are different - not good. On the homepage it says Works with Magento 1.9.0.X . tested 15 May 2014.

Upvotes: 1

Related Questions