Author Topic: Custom Attributes Extended 2.1 [Hack]  (Read 536680 times)

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Custom Attributes Extended 2.1 [Hack]
« on: May 11, 2007, 04:01:16 AM »
UPDATE: I no longer support this hack.  It was created for an older version of Virtuemart and for Joomla 1.0.x.  Someone has carried it further in it's development here: http://forum.virtuemart.net/index.php?topic=39666.0

Custom Attribues Extended 2.1 [Hack]
For Virtuemart 1.0.12
Allows you to turn your shopping cart into an in-depth shopping experience.  This hack enables you to allow different types of form elements to be included in each product.

Features of this Hack:
- user defined set, add, or subtract price field.  Great for a donation systems. No brackets needed.
- text box and text area field.
- File upload field.  Great for customers to include artwork or needed documents w/ order.
- Javascript Date Pop-up Calendar.
- Single or Multiple Checkboxes or Radio buttons.
- Drop-down select or Multiple Selectbox.
- Prices can be included in almost all fields using brackets ex. [+3.25]
- Make certain attribute fields required using -r ex: (textarea-r)
- [ ] brakets are stripped off in frontend and replaced with curreny sign
- NEW include image thumbnails with checkboxes,radio buttons, and select box.
- NEW charge extra for text on an per word, per character (w/ or w/out spaces), or all
- NEW charge for a file upload
- NEW add help tips to each field as a hovering tool tip, below title, above field, or below field
- Tested on Joomla 1.0.13 on JSAS w/ VirtueMart 1.0.10

Here is how to implement the Hack: (files included at end)

Backup files first.

Step 1:
download files: ps_product_custom_attribute.php & ps_product_custom_type.php
(found below in .zip file)
Add them to folder: <site_root>/administrator/components/com_virtuemart/classes/

Step 2:
open the file: ps_product_attribute.php
location: <site_root>/administrator/components/com_virtuemart/classes/

find the function around line 354 called: list_custom_attribute()

replace the whole function with the following code:
Code: [Select]
/**
* Creates form fields for customizable products from the custom attribute format
* @author Ted Barnett (ted@contemplatedesign.com)
* @param unknown_type $product_id
* @return string HTML code containing form fields with Labels
*/
function list_custom_attribute($product_id) {
global $mosConfig_secret, $mosConfig_live_site, $mainframe;

require_once(CLASSPATH.'ps_product_custom_attribute.php');
$product_custom_attributes = new ps_product_custom_attribute;

$db = new ps_DB;

$q = "SELECT product_id, custom_attribute from #__{vm}_product WHERE product_id='$product_id'";
$db->query($q);
$db->next_record();

$custom_attr_list=$db->f("custom_attribute");
if ($custom_attr_list) {
$has_custom_attributes=1;
$fields=explode(";",$custom_attr_list);
$html = "";
foreach($fields as $field)
{
$fieldVars = array();
$fieldVars = $product_custom_attributes->customAttributeVars($field);
$html .= $product_custom_attributes->customAttributeHTML($fieldVars['attr_type'], $fieldVars);
}

}

if ($custom_attr_list) {
return $html;
}
}

Step 3:

in the same file find the function around line 391 called getAdvancedAttributes()

replace the whole function with the following code:
Code: [Select]
/**
* This function returns an array with all "advanced" attributes of the product specified by
* $product_id
*
* @param int $product_id
*/
function getAdvancedAttributes( $product_id ) {
global $ps_product;
if( is_null( $ps_product )) {
$ps_product = new ps_product();
}
$attributes_array = array();
$attributes = $ps_product->get_field( $product_id, 'attribute' );

require_once(CLASSPATH.'ps_product_custom_attribute.php');
$product_custom_attributes = new ps_product_custom_attribute;

if($attributes){ $attributes .= ';'; }
$attributes .= $ps_product->get_field( $product_id, 'custom_attribute' );

// Get each of the attributes into an array
$product_attribute_keys = explode( ";", $attributes );
foreach( $product_attribute_keys as $attribute ) {
if(strpos($attribute, "(")){
  
   $fieldVars = array();
$fieldVars = $product_custom_attributes->customAttributeVars($attribute);
$attribute_name = trim($fieldVars['attr_title']);

require_once(CLASSPATH.'ps_product_custom_type.php');
$attr_type_class = 'ps_product_custom_type_'.$fieldVars['attr_type'];
$product_custom_type = new $attr_type_class;
$attribute_values = $product_custom_type->customTypeSecureValue($fieldVars);
} else {
$attribute_name = substr( $attribute, 0, strpos($attribute, ",") );
$attribute_values = substr( $attribute, strpos($attribute, ",")+1 );
}

$attributes_array[$attribute_name]['name'] = trim($attribute_name);
// Read the different attribute values into an array
$attribute_values = explode(',', $attribute_values );
$operand = '';
$my_mod = 0;
foreach( $attribute_values as $value ) {
$operand = '';
$my_mod = 0;
// Get the price modification for this attribute value
$start = strpos($value, "[");
$finish = strpos($value,"]", $start);

$o = substr_count ($value, "[");
$c = substr_count ($value, "]");
// check to see if we have a bracket (means: a price modifier)
       for ($x=0;$x<$c;$x++) {
       if (True != is_int($finish) ) { continue; }
$length = $finish-$start;

// We found a pair of brackets (price modifier?)
if ($length > 1) {
$my_mod=substr($value, $start+1, $length-1);

if ($o != $c) { // skip the tests if we don't have to process the string
if ($o < $c ) {
$char = "]";
$offset = $start;
}
else {
$char = "[";
$offset = $finish;
}
$s = substr_count($my_mod, $char);
for ($r=1;$r<$s;$r++) {
$pos = strrpos($my_mod, $char);
$my_mod = substr($my_mod, $pos+1);
}
}
$operand=substr($my_mod,0,1);

$my_mod=substr($my_mod,1);


}
}
if( $start > 0 ) {
$value = substr($value, 0, $start);
}
$value = trim( $value );

$attributes_array[$attribute_name]['values'][$value]['name'] = $value;
$attributes_array[$attribute_name]['values'][$value]['operand'] = $operand;
$attributes_array[$attribute_name]['values'][$value]['adjustment'] = $my_mod;
$operand = '';
$my_mod = 0;
}

}

return $attributes_array;

}

Step 4:

in the same file find the following function called: cartGetAttributes()

within that function, replace this code on line 503: (which should now be line 528)
Code: [Select]
// added for custom fields by denie van kleef
$custom_attribute_list=$db->f("custom_attribute");
$custom_attribute_given = false;
if ($custom_attribute_list) {
$fields=explode(";",$custom_attribute_list);

$description=$d["description"];
foreach($fields as $field)
{
$pagevar=str_replace(" ","_",$field);
if (!empty($d[$pagevar])) {
$custom_attribute_given = true;
}
if ($description!='') {
$description.="; ";
}
$description.=$field.":";
$description .= empty($d[$pagevar]) ? '' : $d[$pagevar];
}
rtrim($description);
$d["description"] = $description;
// END add for custom fields by denie van kleef

}

with this code:
Code: [Select]
// added for custom fields by ted barnett
global $charge;
$charge = array();
$custom_attributes = array();
$custom_attribute_list=$db->f("custom_attribute");
$description=$d["description"];
$custom_attribute_given = false;
if ($custom_attribute_list) {

require_once(CLASSPATH.'ps_product_custom_attribute.php');
$product_custom_attributes = new ps_product_custom_attribute;

$fields=explode(";",$custom_attribute_list);
foreach($fields as $field) {

$fieldVars = array();
$fieldVars = $product_custom_attributes->customAttributeVars($field);

$pagevar = trim($fieldVars['attr_pagevar']);
if ($fieldVars['attr_type'] == 'line') {
continue;
}
                if ($fieldVars['attr_req'] && empty($d[$pagevar])) {
                       $custom_attribute_given = false;
                       break;                                  
                }
if (!empty($d[$pagevar])) {
$custom_attribute_given = true;
}
if ($description!='') {
$description.="; ";
}
$description.=trim($fieldVars['attr_title']).":";

// strip accidental currency symbols
// add aditional as needed
$d[$pagevar]=str_replace("$","",$d[$pagevar]); // Dollar
$d[$pagevar]=str_replace("£","",$d[$pagevar]); // Pounds
$d[$pagevar]=str_replace("¥","",$d[$pagevar]); // Yen
$d[$pagevar]=str_replace("€","",$d[$pagevar]); // Euro

require_once(CLASSPATH.'ps_product_custom_type.php');
$attr_type_class = 'ps_product_custom_type_'.$fieldVars['attr_type'];
$product_custom_type = new $attr_type_class;
$d[$pagevar] = $product_custom_type->customTypeProcess($d[$pagevar],$fieldVars);
$description .= empty($d[$pagevar]) ? '' : $d[$pagevar];
}
}
rtrim($description);
$d["description"] = $description;
// END add for custom fields by ted barnett

SAVE THE FILE!

Step 5:
open the file: ps_product.php
location: <site_root>/administrator/components/com_virtuemart/classes/

find the function get_adjusted_attribute_price() and go down to about line #1648.

replace the following line of code:
Code: [Select]
// if we've been given a description to deal with, get the adjusted price
if ($description != '') { // description is safe to use at this point cause it's set to ''
require_once(CLASSPATH.'ps_product_attribute.php');
$product_attributes = ps_product_attribute::getAdvancedAttributes($product_id);

$attribute_keys = explode( ";", $description );

for($i=0; $i < sizeof($attribute_keys); $i++ ) {
$temp_desc = $attribute_keys[$i];

$temp_desc = trim( $temp_desc );
// Get the key name (e.g. "Color" )
$this_key = substr( $temp_desc, 0, strpos($temp_desc, ":") );
$this_value = substr( $temp_desc, strpos($temp_desc, ":")+1 );

if( in_array( $this_key, $custom_attribute_fields )) {
if( @$custom_attribute_fields_check[$this_key] == md5( $mosConfig_secret.$this_key )) {
// the passed value is valid, don't use it for calculating prices
continue;
}
}
                
$this_value=str_replace("_"," ",$this_value);
if( isset( $product_attributes[$this_key]['values'][$this_value] )) {
$modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment'];
$operand = $product_attributes[$this_key]['values'][$this_value]['operand'];

// if we have a number, allow the adjustment
if (true == is_numeric($modifier) ) {
                    
// Now add or sub the modifier on
if ($operand=="+") {
$adjustment += $modifier;
}
else if ($operand=="-") {
$adjustment -= $modifier;
}
else if ($operand=='=') {
// NOTE: the +=, so if we have 2 sets they get added
// this could be moded to say, if we have a set_price, then
// calc the diff from the base price and start from there if we encounter
// another set price... just a thought.

$setprice += $modifier;
$set_price = true;
}
}
} else {
continue;
}
}
}

with this:
Code: [Select]
// if we've been given a description to deal with, get the adjusted price
if ($description != '') { // description is safe to use at this point cause it's set to ''
require_once(CLASSPATH.'ps_product_attribute.php');
$product_attributes = ps_product_attribute::getAdvancedAttributes($product_id);

$attribute_keys = explode( ";", $description );

for($i=0; $i < sizeof($attribute_keys); $i++ ) {
$temp_desc = $attribute_keys[$i];

$temp_desc_keys = explode( ",", $temp_desc );
foreach ($temp_desc_keys as $temp_desc){

$temp_desc = trim( $temp_desc );
// Get the key name (e.g. "Color" )
if(strpos($temp_desc, ":")){
$this_key = substr( $temp_desc, 0, strpos($temp_desc, ":") );
$this_value = substr( $temp_desc, strpos($temp_desc, ":")+1 );
} else {
   $this_key = $this_key;
$this_value = $temp_desc;
}

if( in_array( $this_key, $custom_attribute_fields )) {
if( @$custom_attribute_fields_check[$this_key] == md5( $mosConfig_secret.$this_key )) {
// the passed value is valid, don't use it for calculating prices
continue;
}
}

$this_value=str_replace("_"," ",$this_value);
if( !isset( $product_attributes[$this_key]['values'][$this_value] )) {
$this_true_value = $this_value;
$this_value = 'vm_charge';
}
if( isset( $product_attributes[$this_key]['values'][$this_value] )) {
$modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment'];
$operand = $product_attributes[$this_key]['values'][$this_value]['operand'];
if($this_value == 'vm_charge'){
$this_value = this_true_value;
}
// if we have a number, allow the adjustment
if (true == is_numeric($modifier) ) {
                    
// Now add or sub the modifier on
if ($operand=="+") {
$adjustment += $modifier;
}
else if ($operand=="-") {
$adjustment -= $modifier;
}
else if ($operand=='=') {
// NOTE: the +=, so if we have 2 sets they get added
// this could be moded to say, if we have a set_price, then
// calc the diff from the base price and start from there if we encounter
// another set price... just a thought.

$setprice += $modifier;
$set_price = true;
}
}
} else {
continue;
}
}
}
}



Step 6:

in the same file find the following function called: getDescriptionWithTax()

within that function, replace this code on line 1789: (which should now be line 1811)
Code: [Select]

foreach( $attribute_keys as $temp_desc ) {
$finish = strpos($temp_desc,"]");
$temp_desc = trim( $temp_desc );
// Get the key name (e.g. "Color" )
$this_key = substr( $temp_desc, 0, strpos($temp_desc, ":") );
$this_value = substr( $temp_desc, strpos($temp_desc, ":")+1 );

if( in_array( $this_key, $custom_attribute_fields )) {
if( @$custom_attribute_fields_check[$this_key] == md5( $mosConfig_secret.$this_key )) {
// the passed value is valid, don't use it for calculating prices
continue;
}
}
            $this_value = str_replace("_"," ",$this_value);
if( isset( $product_attributes[$this_key]['values'][$this_value] )) {
$modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment'];
$operand = $product_attributes[$this_key]['values'][$this_value]['operand'];

$value_notax = $modifier;
if( abs($value_notax) >0 ) {
$value_taxed = $value_notax * ($my_taxrate+1);
$temp_desc_new  = str_replace( $operand.$modifier, $operand.' '.$CURRENCY_DISPLAY->getFullValue( $value_taxed ), $temp_desc );
                        
$description = str_replace( $this_key.':'.$this_value,
$this_key.':'.$this_value.' ('.$operand.' '.$CURRENCY_DISPLAY->getFullValue( $value_taxed ).')',
$description);

}
$temp_desc = substr($temp_desc, $finish+1);
}

}

with this:
Code: [Select]
foreach( $attribute_keys as $temp_desc ) {
$temp_desc_keys = explode( ",", $temp_desc );
foreach ($temp_desc_keys as $temp_desc){
$finish = strpos($temp_desc,"]");
$temp_desc = trim( $temp_desc );
// Get the key name (e.g. "Color" )
if(strpos($temp_desc, ":")){
$this_key = substr( $temp_desc, 0, strpos($temp_desc, ":") );
$this_value = substr( $temp_desc, strpos($temp_desc, ":")+1 );
} else {
   //$temp_desc .= $this_key.':'.$temp_desc;
   $this_key = $this_key;
$this_value = $temp_desc;
}
if( in_array( $this_key, $custom_attribute_fields )) {
if( @$custom_attribute_fields_check[$this_key] == md5( $mosConfig_secret.$this_key )) {
// the passed value is valid, don't use it for calculating prices
continue;
}
}

           $this_value = str_replace("_"," ",$this_value);
if( !isset( $product_attributes[$this_key]['values'][$this_value] )) {
$this_true_value = $this_value;
$this_value = 'vm_charge';
}
if( isset( $product_attributes[$this_key]['values'][$this_value] )) {
$modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment'];
$operand = $product_attributes[$this_key]['values'][$this_value]['operand'];
  if($this_value == 'vm_charge'){
$this_value = $this_true_value;
}
$value_notax = $modifier;
if( abs($value_notax) >0 ) {
$value_taxed = $value_notax * ($my_taxrate+1);
$temp_desc_new  = str_replace( $operand.$modifier, $operand.' '.$CURRENCY_DISPLAY->getFullValue( $value_taxed ), $temp_desc );
                     
$description = str_replace( $this_value,
$this_value.' ('.$operand.' '.$CURRENCY_DISPLAY->getFullValue( $value_taxed ).')',
$description);

}
$temp_desc = substr($temp_desc, $finish+1);
}
}
}

SAVE THE FILE!


ALL DONE!  Enjoy.  All new and edited files are found in the .zip file below.
The next post will explain the syntax.
-barnett

--UPDATED -- 9-18-07
-- rehashed how to handle added charges to apply tax
-- Updated to Joomla 1.0.13 & VM 1.0.12

-- UPDATED -- 5-17-07
- fixed files in step 1
- fixed lines in step 5
- fixed multiple select box image thumbnail problem
- fixed blank results for non-charge radio, checkbox, select, & multiple items
- added NEW attribute type (number)... see syntax

-- UPDATED -- 5-19-07
- added Max file Size & Min File Size options to file upload... see syntax

-- UPDATED -- 5-23-07
- fixed "File Type Error" for file upload
- fixed File Upload always defaulting to required
- fixed Default Checked Radio & Check boxes for Safari (haven't tested)

-- UPDATED -- 5-23-07
- fixed multiple attributes of same type not being calculated in IE bug

-- UPDATED -- 5-23-07
- fixed file upload to play nice w/ multiple file uploads
- print file name to screen when there is an error

-- UPDATED -- 5-24-07
- fixed IE7 bug: image path was appearing in drop-down select
- added "-d" option to text and textarea charge types to show cost break down in cart... see syntax

[attachment cleanup by admin]

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #1 on: May 11, 2007, 04:08:45 AM »
Syntax:
Name(attribute type)(tip text|tip location)(attribute data);

add "-r" to attribute type to make it required.
if no tip needed you must still add: Name(text)(|)(data);

Attribute Types: price, text, textarea, line, date, file, checkbox, radio, select, multiple, number

Tip Locations: title-hover, title-below, field-above, field-below

Attribute Data:

Price:
Name(price)(tip here|location)(default price|price type);

examples:
Donation(price)(please enter donation|title-below)(10.00|+);
Reduce By(price)(How much to subtract|field-below)(|-);

Text & Textarea:
Name(text)(tip here|location)(default text|price|charge type);

charge types: char,char_nospace,word,all
Note: add "-d" to end of charge type to show cost break down in cart

examples:
name(text)(1.00 per character|field-below)(|1.00|char);
message(textarea)(5.00 per word|title-hover)(message here|5.00|word);
Test(text)(1.50 per character|title-hover)(|1.50|char_nospace-d); 

Number:
Name(number)(tip here|location)(default number|price);

example:
Number of chocolates(number)(enter # of chocolates|title-hover)(10|0.25);

Date:
Name(date)(tip here|location)(|);


Checkbox & Radio & Select & Multiple:
Name(checkbox)(tip here|location)(option1|image1,option2*|image2,option3 [+5.00]|image3);
* = selected

images work for checkboxes, radio buttons, and select boxes.

examples:
Donate(checkbox)(tip here|title-hover)(Widows [+5.00],Orphans [+10.00]);
Colors(radio)(tip here|title-hover)(Blue [+5.00]|images/img_blue.jpg,Red [+10.00]|images/img_red.jpg);

File:
Name(file)(tip here|title-below)(directory|file types|charge|max file size|min file size);

Max file size & Min file size measures in bytes.

examples:
File Upload(file)(upload file of type .jpg or .doc|title-below)(images/|.jpg,.doc);
Art Work(file)(upload artwork, $20.00 charge|title-below)(images/|.jpg,.doc|20.00);
Picture(file)(upload picture, $20.00 charge, max file of .5MB|title-below)(images/|.jpg|20.00|500000|300);

Line:
Name(line)(tip-here|field-below)(custom line code);

examples:
Further Options(line)(here are more options|field-below)();
(line)(|)(<b>--------------------------------</b>);

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #2 on: May 11, 2007, 04:26:22 AM »
Here is a sample.  I entered the following data into the custom attributes field:

Date(date)(tip here|field-above)(|);
Color Options(checkbox)(another tip|title-hover)(test1 [+10.00]|images/img_1.jpg,test2 [-20.00]|images/img_2.jpg,test3 [-10.00]|images/img_3.jpg,test4 [+30.00]*|images/img_4.jpg,test5 [-5.00]|images/img_5.jpg);
Divide(line)(tip-here|field-below)(<b>---------------------------</b>);
Engrave(text)(3.00 per character|field-below)(name here|3.00|char);
Donation(price-r)(help us out|field-below)(25.00|+);
File Upload(file)(20.00 for file upload|field-below)(images/|.jpg,.doc|20.00);


and it produced the following screen shots for me.
-barnett

[attachment cleanup by admin]

Christian Bach

  • Beginner
  • *
  • Posts: 29
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #3 on: May 11, 2007, 10:23:39 AM »
Hi Barnett,

I have implemented the new code and it works great. Thanks!  :)

I have inserted 3 engraving lines, and they are not required, however the shop promts me that I need to select a variant?  ??? The engraving is just an option.

Am i missing something?

Would you rather that I post this in the original thread?

/cbach

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #4 on: May 11, 2007, 14:50:13 PM »
I have inserted 3 engraving lines, and they are not required, however the shop promts me that I need to select a variant?  ??? The engraving is just an option.

Am i missing something?
/cbach
@cbach

Are there any other options you can add (like a radio button) that won't charge, just so the user can fill something out.  I'll look into this option...  could you post your custom attribute code you have?
Thanks
-barnett

standby

  • Beginner
  • *
  • Posts: 13
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #5 on: May 11, 2007, 18:21:06 PM »
My English isn´t very good, but I´ll try explain my question.

The problem:
I want to sell packaged products with the choice of what the customer wants to put in this package. For example, if you have a chocolates factory and wanted to sell boxes of chololates but let the choice for the customer of how much he wants in the box and how much boxes he wants.

I need some way of adding to cart the Total= (items per box) x (nº of  boxes)


The solution?:

I have a possible solution, buy I don´t know to code it:


Using attibutes:

- attribute 1: quantity per box
- attribute 2: box needed (default 0 , customer must select a quantity)

Then when customer change attribute 2 the program change the "add to cart quantity" (= attibute 1 x attribute 2).But I don´t know how code this step.

I found in an other thread a function which  "Searches for an attribute of a given name" (http://virtuemart.net/index.php?option=com_smf&Itemid=71&topic=20632.msg50385#msg50385)

Then using that function, if exist an attibute "box needed", that attributes input form in prodcut details need the param "onchange"  which change the variable $quantity in shop.product_details.php ( in ADD-TO-CART) $quantity= "quantity per box" x "box needed".


In general, I think is interesting to found a way to change "add to cart quantity" using attributes.

I post this here because I think this will be a good addition in this great hack.

Any help?

(Again, sorry for my English)

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #6 on: May 11, 2007, 18:40:46 PM »
In general, I think is interesting to found a way to change "add to cart quantity" using attributes.

I post this here because I think this will be a good addition in this great hack.

Any help?

this would be a good addition to the hack.  I'll look into it further, but I'm not sure how to appraoch it with the current hack.

I'm not sure why you would not just have the customer select the options they want and then fill in the quantity they want as normal, unless you're wanting to restrict the quantity to sets like 10,50,100, etc...?  Maybe i'm not understanding the scenario well.

What I'm understanding you say is the customer would enter in that they want 100 individual chocolates and then enters a quantity of 50 (which represents boxes).  That would be doable with this hack.

But I do see what you're saying about a multiplier function.  Maybe I could adjust the hack to add something like this.

# of chocolate(number)(tip here|field-below)(0.50);

something so that the user could enter the number of chocolates and then those each be charged .50 cents and then will be multiplied by the number of boxes!

Is this what you mean?
-barnett

dubey

  • Beginner
  • *
  • Posts: 21
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #7 on: May 11, 2007, 20:36:37 PM »
this is a really great hack. I was wondering, is it a simple job to replace the javascript calender with a javascript colour swatch such as this:

http://www.free-color-picker.com/color-pop-combo.php

standby

  • Beginner
  • *
  • Posts: 13
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #8 on: May 11, 2007, 20:40:49 PM »
Thanks for responding.

You can see the same problem (better explained) here:

http://virtuemart.net/index.php?option=com_smf&Itemid=71&topic=25614.0

Quote
Using VM and Joomla, the website for my printing & copying business allows customers to place printing orders online. My situation is that my pricing breakdown is per page... but what if a customer wants several copies of a multiple page document? Well, until I figure that one out, I simply have two custom attribute fields: Number of Pages in Document, and Amount of Sets Needed. I instruct the customer that those two fields must be multiplied to achieve the right quantity, and that they must enter the solution to that equation manually.

I'd like to modify the code so that; a.)  the Quantity box updates automatically when these two fields are filled, b.) the Product is not added to the cart if either field is left blank, and c.) ....

This method has worked thus far, but there is always some confusion because no matter how easily you explain it, there's still always 3-4 persons who just can't grasp the concept for every 1-2 persons who do. Thusly, I must alleviate this confusion somehow, and that is the only way I can see as being the solution.

dubey

  • Beginner
  • *
  • Posts: 21
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #9 on: May 11, 2007, 21:26:17 PM »
I suck at php, but if someone can point to the files in question perhaps I can experiment.

Which file do I need to examine in order to modify the "charge extra for text per word" attributes?

I need the customer to enter a numerical figure for the amount of words (to be supplied as a .doc upload)

- say the customer wants 500 words at 3 dollars a word, I need the customer to enter the figure "500", and the price to be modified by 3*500.


Christian Bach

  • Beginner
  • *
  • Posts: 29
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #10 on: May 11, 2007, 22:05:51 PM »
@cbach

Are there any other options you can add (like a radio button) that won't charge, just so the user can fill something out.  I'll look into this option...  could you post your custom attribute code you have?
Thanks
-barnett

Hi,

Do you ever sleep? :)

You can see th eproduct here:
https://shop.bachdan.dk/index.php?page=shop.product_details&category_id=10&flypage=shop.flypage&product_id=1&option=com_virtuemart&Itemid=26

If I don't want any engraving then I would just klik add to basket. And if I wanted engraving then I would select the font and type the text. But it tells me that I have to select a variant. I have made the custom attribute as simple as possible for testing purposes. But I can't seem to figure it out.
The backend and frontend php files are the ones from your zip package.

This is my variant section:
Code: [Select]
Model,1011 45 mm.[=52.80],1012 50 mm.[=59.20],1013 60 mm.[=63.20],1014 80 mm.[=92.80],1015 100 mm.[=111.20],1016 125 mm.[=113.60],1017 150 mm.[=188.80]
This is my code in the custom attribute section:
Code: [Select]
Skrifttyper(radio)(|)(Enkeltblok|/images/stories/gravering/eb.gif,Dobbeltblok|/images/stories/gravering/db.gif,Enkeltskriveskrift|/images/stories/gravering/es.gif,Dobbeltskriveskrift|/images/stories/gravering/ds.gif);
Gravering Linie 1(text)(|)(|field-below)(|1.00|char_nospace);
Gravering Linie 2(text)(|)(|field-below)(|1.00|char_nospace);
Gravering Linie 3(text)(|)(|field-below)(|1.00|char_nospace)

Sorry for the Danish language, can't seem to shake it. ;)

Have a nice "weekend".

/cbach


barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #11 on: May 12, 2007, 15:57:22 PM »
- say the customer wants 500 words at 3 dollars a word, I need the customer to enter the figure "500", and the price to be modified by 3*500.

I'm going to add a new attribute type soon which will allow for this.  It will look something like this:
Enter # of words(number)(3.00 a word|field-below)(3.00|*);

-barnett

barnett

  • Jr. Member
  • **
  • Posts: 92
    • Contemplate Design
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #12 on: May 12, 2007, 16:00:59 PM »
This is my variant section:
Code: [Select]
Model,1011 45 mm.[=52.80],1012 50 mm.[=59.20],1013 60 mm.[=63.20],1014 80 mm.[=92.80],1015 100 mm.[=111.20],1016 125 mm.[=113.60],1017 150 mm.[=188.80]
This is my code in the custom attribute section:
Code: [Select]
Skrifttyper(radio)(|)(Enkeltblok|/images/stories/gravering/eb.gif,Dobbeltblok|/images/stories/gravering/db.gif,Enkeltskriveskrift|/images/stories/gravering/es.gif,Dobbeltskriveskrift|/images/stories/gravering/ds.gif);
Gravering Linie 1(text)(|)(|field-below)(|1.00|char_nospace);
Gravering Linie 2(text)(|)(|field-below)(|1.00|char_nospace);
Gravering Linie 3(text)(|)(|field-below)(|1.00|char_nospace)

/cbach


your code should be this:

Code: [Select]
Skrifttyper(radio)(|)(Enkeltblok|/images/stories/gravering/eb.gif,Dobbeltblok|/images/stories/gravering/db.gif,Enkeltskriveskrift|/images/stories/gravering/es.gif,Dobbeltskriveskrift|/images/stories/gravering/ds.gif);
Gravering Linie 1(text)(|)(|1.00|char_nospace);
Gravering Linie 2(text)(|)(|1.00|char_nospace);
Gravering Linie 3(text)(|)(|1.00|char_nospace);

you had an extra () making four in all instead of three.  Hope that helps.
-barnett

dubey

  • Beginner
  • *
  • Posts: 21
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #13 on: May 12, 2007, 16:03:03 PM »
- say the customer wants 500 words at 3 dollars a word, I need the customer to enter the figure "500", and the price to be modified by 3*500.

I'm going to add a new attribute type soon which will allow for this.  It will look something like this:
Enter # of words(number)(3.00 a word|field-below)(3.00|*);

-barnett

Great news. I think it would be a powerful and flexible addition to the hack.

dubey

  • Beginner
  • *
  • Posts: 21
Re: Custom Attributes Extended 2.0 [Hack]
« Reply #14 on: May 14, 2007, 02:39:23 AM »
I am trying a cheap hack, not really knowing what I'm doing. I am trying to replace the calender with a swatch.

In ps_product_custom_type I have simply changed the name of the javascript file. I'm guessing thsi is not enough?

$mainframe->addCustomHeadTag( '<script type="text/javascript" src="'. $mosConfig_live_site . '/includes/js/joomla.javascript.js"></script>' );
      mosCommonHTML::loadOverlib();
      mosCommonHTML::loadCalendar();


      $mainframe->addCustomHeadTag( '<script type="text/javascript" src="'. $mosConfig_live_site . '/includes/js/swatch/301a.js"></script>' );
      mosCommonHTML::loadOverlib();
      mosCommonHTML::loadCalendar();

here is the javascript

//*******************************************************************************
//Title:      FCP Combo-Chromatic Color Picker
//URL:        http://www.free-color-picker.com
//Product No. FCP201a
//Version:    1.2
//Date:       10/01/2006
//NOTE:       Permission given to use this script in ANY kind of applications IF
//            script code remains UNCHANGED and the anchor tag "powered by FCP"
//            remains valid and visible to the user.
//
//  Call:     showColorGrid3("input_field_id","span_id")
//  Add:      <DIV ID="COLORPICKER301" CLASS="COLORPICKER301"></DIV> anywhere in body
//*******************************************************************************
function getScrollY(){var scrOfX = 0,scrOfY=0;if(typeof(window.pageYOffset)=='number'){scrOfY=window.pageYOffset;scrOfX=window.pageXOffset;}else if(document.body&&(document.body.scrollLeft||document.body.scrollTop)){scrOfY=document.body.scrollTop;scrOfX=document.body.scrollLeft;}else if(document.documentElement&&(document.documentElement.scrollLeft||document.documentElement.scrollTop)){scrOfY=document.documentElement.scrollTop;scrOfX=document.documentElement.scrollLeft;}return scrOfY;}document.write("<style>.colorpicker301{text-align:center;visibility:hidden;display:none;position:absolute;background-color:#FFF;border:solid 1px #CCC;padding:4px;z-index:999;filter:progid:DXImageTransform.Microsoft.Shadow(color=#D0D0D0,direction=135);}.o5582brd{border-bott6om:solid 1px #DFDFDF;border-right:solid 1px #DFDFDF;padding:0;width:12px;height:14px;}a.o5582n66,.o5582n66,.o5582n66a{font-family:arial,tahoma,sans-serif;text-decoration:underline;font-size:9px;color:#666;border:none;}.o5582n66,.o5582n66a{text-align:center;text-decoration:none;}a:hover.o5582n66{text-decoration:none;color:#FFA500;cursor:pointer;}.a01p3{padding:1px 4px 1px 2px;background:whitesmoke;border:solid 1px #DFDFDF;}</style>");function gett6op6(){csBrHt=0;if(typeof(window.innerWidth)=='number'){csBrHt=window.innerHeight;}else if(document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)){csBrHt=document.documentElement.clientHeight;}else if(document.body&&(document.body.clientWidth||document.body.clientHeight)){csBrHt=document.body.clientHeight;}ctop=((csBrHt/2)-132)+getScrollY();return ctop;}function getLeft6(){var csBrWt=0;if(typeof(window.innerWidth)=='number'){csBrWt=window.innerWidth;}else if(document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)){csBrWt=document.documentElement.clientWidth;}else if(document.body&&(document.body.clientWidth||document.body.clientHeight)){csBrWt=document.body.clientWidth;}cleft=(csBrWt/2)-125;return cleft;}var nocol1="&#78;&#79;&#32;&#67;&#79;&#76;&#79;&#82;",clos1="&#67;&#76;&#79;&#83;&#69;",tt6="&#70;&#82;&#69;&#69;&#45;&#67;&#79;&#76;&#79;&#82;&#45;&#80;&#73;&#67;&#75;&#69;&#82;&#46;&#67;&#79;&#77;",hm6="&#104;&#116;&#116;&#112;&#58;&#47;&#47;&#119;&#119;&#119;&#46;";hm6+=tt6;tt6="&#80;&#79;&#87;&#69;&#82;&#69;&#68;&#32;&#98;&#121;&#32;&#70;&#67;&#80;";function setCCbldID6(objID,val){document.getElementById(objID).value=val;}function setCCbldSty6(objID,prop,val){switch(prop){case "bc":if(objID!='none'){document.getElementById(objID).style.backgroundColor=val;}break;case "vs":document.getElementById(objID).style.visibility=val;break;case "ds":document.getElementById(objID).style.display=val;break;case "tp":document.getElementById(objID).style.top=val;break;case "lf":document.getElementById(objID).style.left=val;break;}}function putOBJxColor6(OBjElem,Samp,pigMent){if(pigMent!='x'){setCCbldID6(OBjElem,pigMent);setCCbldSty6(Samp,'bc',pigMent);}setCCbldSty6('colorpicker301','vs','hidden');setCCbldSty6('colorpicker301','ds','none');}function showColorGrid3(OBjElem,Sam){var objX=new Array('00','33','66','99','CC','FF');var c=0;var z='"'+OBjElem+'","'+Sam+'",""';var xl='"'+OBjElem+'","'+Sam+'","x"';var mid='';mid+='<center><table bgcolor="#b9298b" border="0" cellpadding="0" cellspacing="0" style="border:solid 1px #d31b1b;padding:2px;"><tr>';mid+="<td colspan='18' align='left' style='font-size:10px;background:#6666CC;color:#FFF;font-family:arial;'>&nbsp;Combo-Chromatic Selection Palette</td></tr><tr><td colspan='18' align='center' style='margin:0;padding:2px;height:14px;' ><input class='o5582n66' type='text' size='10' id='o5582n66' value='#b9298b'><input class='o5582n66a' type='text' size='2' style='width:14px;' id='o5582n66a' onclick='javascript:alert(\"click on selected swatch below...\");' value='' style='border:solid 1px #666;'>&nbsp;|&nbsp;<a class='o5582n66' href='javascript:onclick=putOBJxColor6("+z+")'><span class='a01p3'>"+nocol1+"</span></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='o5582n66' href='javascript:onclick=putOBJxColor6("+xl+")'><span class='a01p3'>"+clos1+"</span></a></td></tr><tr>";var br=1;for(o=0;o<6;o++){mid+='</tr><tr>';for(y=0;y<6;y++){if(y==3){mid+='</tr><tr>';}for(x=0;x<6;x++){var grid='';grid=objX
  • +objX[y]+objX
  • ;var b="'"+OBjElem+"', '"+Sam+"','#"+grid+"'";mid+='<td class="o5582brd" style="background-color:#'+grid+'"><a class="o5582n66"  href="javascript:onclick=putOBJxColor6('+b+');" onmouseover=javascript:document.getElementById("o5582n66").value="#'+grid+'";javascript:document.getElementById("o5582n66a").style.backgroundColor="#'+grid+'";  title="#'+grid+'"><div style="width:12px;height:14px;"></div></a></td>';c++;}}}mid+='</tr></table>';var objX=new Array('0','3','6','9','C','F');var c=0;var z='"'+OBjElem+'","'+Sam+'",""';var xl='"'+OBjElem+'","'+Sam+'","x"';mid+='<table bgcolor="#b9298b" border="0" cellpadding="0" cellspacing="0" style="border:solid 1px #d31b1b;padding:1px;"><tr>';var br=0;for(y=0;y<6;y++){for(x=0;x<6;x++){if(br==18){br=0;mid+='</tr><tr>';}br++;var grid='';grid=objX[y]+objX
  • +objX[y]+objX
  • +objX[y]+objX
  • ;var b="'"+OBjElem+"', '"+Sam+"','#"+grid+"'";mid+='<td class="o5582brd" style="background-color:#'+grid+'"><a class="o5582n66"  href="javascript:onclick=putOBJxColor6('+b+');" onmouseover=javascript:document.getElementById("o5582n66").value="#'+grid+'";javascript:document.getElementById("o5582n66a").style.backgroundColor="#'+grid+'";  title="#'+grid+'"><div style="width:12px;height:14px;"></div></a></td>';c++;}}mid+="</tr><tr><td colspan='18' align='right' style='padding:2px;border:solid 1px #FFF;background:#FFF;'><a href='"+hm6+"' style='color:#666;font-size:8px;font-family:arial;text-decoration:none;lett6er-spacing:1px;'>"+tt6+"</a></td>";mid+='</tr></table></center>';setCCbldSty6('colorpicker301','tp','100px');document.getElementById('colorpicker301').style.top=gett6op6();document.getElementById('colorpicker301').style.left=getLeft6();setCCbldSty6('colorpicker301','vs','visible');setCCbldSty6('colorpicker301','ds','block');document.getElementById('colorpicker301').innerHTML=mid;}