Prices output in templates are restrictive to front-end developers/designers

Started by bigbangireland, August 22, 2011, 22:30:14 PM

Previous topic - Next topic

bigbangireland

I've just been looking over the template files for VM2 and have noticed that they use functions for prices like the following to wrap the number and add a currency symbol;

echo $this->currency->createPriceDiv('variantModification', 'COM_VIRTUEMART_PRODUCT_VARIANT_MOD', $this->product->prices);

I can see a number of problems with this;

  • createPriceDiv() does not allow for additional attributes.
  • Unnecessary inline styles are used
  • Poor semantics

It would be much better if the semantics and styling were left to template devs to control (and an option to use or not to use vm js).

There are good reasons for this;

  • New specs can be used for SEO - such as http://www.schema.org/Offer.
  • More design options.
  • Semantic layouts using the increasingly supported HTML5 spec.
  • Ability to use custom JS using a chosen AJAX library

Is there another a way of outputting raw values (whilst still supporting currency conversion)? If not, can you please change the helper functions to only output the raw values?


Milbo

you can just take a look into this function and write your own in the template.

Why does it has a poor semantics? How you would write it? the other thing is that there are a lot reasons that actually for templaters, why we use a special function to write them.

The function is checking if a price should be shown (show different price system depending by shoppergroup( B2B or B2C) ), is converting to the currency chosen by the shopper and it is also heavily used by ajax to update the prices.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

bigbangireland

Thanks for your reply Milbo,

The data should be in a list (ul, dl or even a table) when presented together the way it is in the default template to be classed as semantic.

But that is not really my point, the raw data is needed so front-end devs can use all info semantically (page wide) in new and unique ways; and to implement SEO enhancements (It may mean that the actual price is big and bold (with Microdata or RDFa) at the top of the page and the taxes, etc (in a list) at the bottom of the page).

There's no need for the wrapping divs/spans to be called in the function - letting the template do what a template does would provide more flexibility, preventing vm core hacks and endless forum questions.

If AJAX is used to update the prices it will still work if the divs/spans (or whatever tag is used with the appropriate id/class) are outputed in the template.

schema.org is about to become very important for SEO especially for eCommerce. All three major search engines are pushing for it's use (http://googlewebmastercentral.blogspot.com/2011/06/introducing-schemaorg-search-engines.html).
I'm sure that no VM user would pass up the opportunity for enhanced search results for their store.

I would also suggest you consider outputting the availability, itemCondition, priceCurrency data described here: http://www.schema.org/Offer.

These are simple changes that could have great impact for SEO and VM's future viability.

pamwo

<a href="http://www.intextual.com">In Text Ads</a>

Milbo

Why do you want your prices in a table?

The question is what do you want to be changed on that line?

<div style="display : '.$vis.';" >'.$descr.'<span class="Price'.$name.'" >'.$product_price[$name].'</span></div>

You can style every price as you wish, you can place it everywhere as you wish. You style it with "Price".$name. The div is just for hiding it. We could add a kind of manual override in the span.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

bigbangireland

I didn't say I wanted prices in a table; you asked me what would be semantic and a table was just one of the answers.

What I did say was that all semantics and styling should be left in the template for a front-end dev or designer to decide its use and relevance (calls to js included).

Here is an example of a simple product page marked up with HTML5 and schema.org Microdata -

<article itemscope itemtype="http://schema.org/Product">

  <header> 
      <h1 itemprop="name">Kenmore White 17" Microwave</h1>
   </header>

  <figure> 
    <img src="kenmore-microwave-17in.jpg" alt='Kenmore 17" Microwave' />
    <figcaption>Kenmore 17" Microwave</figcaption>
  </figure>

  <section itemprop="offers" itemscope itemtype="http://schema.org/Offer">
      <strong itemprop="price">$55.00</strong>
      <link itemprop="availability" href="http://schema.org/InStock" />In stock
   </section>

   <p itemprop="description">0.7 cubic feet countertop microwave. Has six preset cooking categories and convenience features like Add-A-Minute and Child Lock.</p>

</article>



As you can see above, some tags and attributes are very different to XHTML. This is the direction the web is moving in!

Also, with the rapid demise of IE6, CSS can now (most of the time) be used to style tags using other attributes -


span[itemprop="price"] { color: green }
span[itemprop="price"]:before { content: "$" }


Being able to use selectors such as the ones above will un-clutter the DOM and give a better content/markup ratio - but this is all for frontend speshitpillt to decide.

There is no valid reason why wrapping tags need to be in a function instead of the template, a kind of manual override in the span is making this needlessly complicated when there is a very simple fix.

Milbo

Then say how you would like to do the line. I am sorry, I do not completly understand.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

bigbangireland

NOTE: Below is only an example of how a list could display the prices in the template, it's not necessarily the way I would display prices in a template. The point I'm trying to emphasize is that the raw data would be available for use in any possible situation. I've tried to do this in a way that it would make sense to most Joomla template devs.

createPriceDiv() would need the $description variable removed, output only the raw number (and symbol) and the function possibly renamed.

Another advantage would be that prices would be completely removed if null instead of being set to display:none - preventing potential SEO problems.


<?php if($this->show_prices) { ?>
<ul class="product-prices">
<?php if($this->showBasePrice) { ?>
<li>
<?php if($this->product->product_unit && VmConfig::get ('vm_price_show_packaging_pricelabel')) { ?>
<strong><?php echo JText::('COM_VIRTUEMART_CART_PRICE_PER_UNIT'); ?> (<?php echo $this->product->product_unit?>):</strong>;
<?php } else { ?>
<strong><?php echo JText::('COM_VIRTUEMART_CART_PRICE'); ?></strong>
<?php ?>
<span class="PricebasePrice"><?php echo $this->currency->createPriceDiv('basePrice'$this->product->prices ); ?></span>
<!--
<span itemprop="price" class="PricebasePrice"><?php echo $this->currency->createPriceDiv('basePrice'$this->product->prices ); ?></span>
A template that is optomised for schema.org could then include itemprop="price" here.
-->
</li>
<?php ?>
<?php if(!empty($this->product->prices['variantModification'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_VARIANT_MOD'); ?>:</strong> 
<span class="PricevariantModification"><?php echo $this->currency->createPriceDiv('variantModification'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['basePriceWithTax'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_BASEPRICE_WITHTAX'); ?>:</strong> 
<span class="PricebasePriceWithTax"><?php echo $this->currency->createPriceDiv('basePriceWithTax'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['discountedPriceWithoutTax'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_DISCOUNTED_PRICE'); ?>:</strong> 
<span class="PricediscountedPriceWithoutTax"><?php echo $this->currency->createPriceDiv('discountedPriceWithoutTax'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['salesPriceWithDiscount'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_SALESPRICE_WITH_DISCOUNT'); ?>:</strong>
<span class="PricesalesPriceWithDiscount"><?php echo $this->currency->createPriceDiv('salesPriceWithDiscount'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['salesPrice'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_SALESPRICE'); ?>:</strong>
<span class="PricesalePrice"><?php echo $this->currency->createPriceDiv('salesPrice'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['priceWithoutTax'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_SALESPRICE_WITHOUT_TAX'); ?>:</strong>
<span class="PricepriceWithoutTax"><?php echo  $this->currency->createPriceDiv('priceWithoutTax'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['discountAmount'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_DISCOUNT_AMOUNT'); ?>:</strong>
<span class="PricediscountAmount"><?php echo $this->currency->createPriceDiv('discountAmount'$this->product->prices); ?></span>
</li>
<?php ?>
<?php if(!empty($this->product->prices['taxAmount'])) { ?>
<li>
<strong><?php echo JText::_('COM_VIRTUEMART_PRODUCT_TAX_AMOUNT'); ?>:</strong>
<span class="PricetaxAmount"><?php echo $this->currency->createPriceDiv('taxAmount'$this->product->prices); ?></span>
</li>
<?php ?>
</ul>
<?php ?>

Art_Koenig

Where is the function createPriceDiv defined? I haven't found it and really like to customize it. Thanks for your help.

Art_Koenig

This was from BigBangIreland in his first post:

QuoteNew specs can be used for SEO - such as http://www.schema.org/Offer.

Where can I get the URL of the image used in the product page?

The idea would be to add in the productsdetails/default.php the folllowing code:

<span itemprop="image">URL of the image</span>

This helps A LOT for SEO as Google can fetch now microdata for products in a shopping site.

Right now the image is generated by the function displayMediaFull but I can't seem to find where this function is initiated so that I can see where is the URL of the image!

Thanks for your help.


Stonedfury

How can I insert text into your span for the price. See html output.
<div class="PricesalesPrice" style="display : block;" >Sales price: <span class="PricesalesPrice" >$29.85</span>
Is there a way to separate the 2 classes without breaking the style so that I can include in the itemprop="price" into the <span class="PricesalesPrice" >$29.85</span> to look like <span class="PricesalesPrice" itemprop="price" >$29.85</span>
I believe I am in the right area. as I have gotten the title, and such to produce output.
templates/mytemplate/html/virtuemart/default_products.php
And in this area I believe is the price.
<a href="<?php echo JRoute::'index.php?option=com_virtuemart&view=productdetails&virtuemart_product_id=' $product->virtuemart_product_id '&virtuemart_category_id=' $product->virtuemart_category_id )?>" >
<div class="product-price price">
<div class="price-class">
<?php echo $this->currency->createPriceDiv('salesPrice''COM_VIRTUEMART_PRODUCT_SALESPRICE'$product->prices); ?>
<?php 
$SalesPrice number_format((float)$product->prices['salesPrice'], 2'.''');
$BasePrice number_format((float)$product->prices['basePriceWithTax'], 2'.''');
if ($SalesPrice !== $BasePrice and $product->prices['discountAmount'] > 0) { ?>

<span class="price-before-dicount">
<?php echo $this->currency->createPriceDiv'basePriceWithTax'''$product->prices ); ?>
</span>
<?php ?>
<div class="product-discount">
<?php
$SalesPrice number_format((float)$product->prices['salesPrice'], 2'.''');
$BasePrice number_format((float)$product->prices['basePriceWithTax'], 2'.''');
if ($SalesPrice !== $BasePrice and $product->prices['discountAmount'] > 0) {
if($templateparams->get('discount')==1) {
$DiscountAmount $product->prices['discountAmount'];
$ActualPrice $product->prices['priceWithoutTax'] + $product->prices['discountAmount'];
$Discount $DiscountAmount $ActualPrice 100;
$Discount number_format((float)$Discount2'.''').'%';
echo '('.JText::_('COM_VIRTUEMART_CART_SUBTOTAL_DISCOUNT_AMOUNT').': '; echo $Discount.')';
} if($templateparams->get('discount')==2) {
$DiscountAmount $product->prices['discountAmount'];
$ActualPrice $product->prices['salesPrice'] + $product->prices['discountAmount'];
$Discount $DiscountAmount $ActualPrice 100;
$Discount number_format((float)$Discount2'.''').'%';
echo '('.JText::_('COM_VIRTUEMART_CART_SUBTOTAL_DISCOUNT_AMOUNT').': '; echo $Discount.')';
}    
?>

</div>
</div>
</div>
</a>

No such thing as a stupid question, only a stupid answer. I won't ask if I know the answer or found it using the search as you suggested.

Stonedfury

No such thing as a stupid question, only a stupid answer. I won't ask if I know the answer or found it using the search as you suggested.