Hi Dan,
thank you for your answers and time you have to spend.
Take care
Flo
Printable View
Hi Dan,
thank you for your answers and time you have to spend.
Take care
Flo
I like this add on, but I have a small issue I can't seem to work out. I sell printing and want to set up my products with attribute pricing so my customers can calculate a price for any quantity instantly.
The way I have to price my products I need to us an attribute with a price per copy (ex. $0.01 for #20 white bond) and also use a one time charge (ex. $20.00) for setup costs of the print run. I put a test product on my site but it only shows the price per copy for Your Price: and doesn't add in the one time charge. It shows the total correctly in the shopping cart just not on the Your Price amount on the product page.
http://discountprintingservice.com/i...ducts_id=19812
Can your add on be configured so it will show the total price???
Thanks,
GoldBuckle
Thanks for the reply jstnice, but my question still isn't answered. In your attribute setting you have boxes to enter pricing per attribute:
Prices & Weights
Price---------Weight--------Order----------One Time
+.02-------------0-------------1---------------$25.00
When I test it it is only calculating the Price (+.02) and is not adding in the one time charge of $25.00. It does however add up in the shopping cart, it just doesn't show up on the product page for Your Price
For example, (base on the above example) if someone orders 1000 flyers it should multiply 1000 by the Price of +.02 (which would be $20.00) then add the one time charge of $25.00 for a total of $45.00.
On my test product it is only multiplying the price +0.02 by 1000 and displaying that number without adding in the one time charge of $25.00.
Can anyone tell me how to fix this???
:frusty:
Anyone got any ideas on this one???
Hi
Can anyone shed any light on this query!!
I have the Dynamic Price Updater installed on my website and:
I have been adding extra prices to certain attributes of my products recently and have now noticed the sum of the attributes (at product level) are different to the data that is inputted into Zen.
However, when you add the product to cart, the price reverts back to the correct price! You can also briefly see the correct price if you refresh the page at product level, but it will then change, and settle incorrectly.
I have gone through numerous settings on zen to track down where the error is coming from and it seems that the problem occurs when I change the individual products' 'Tax Class' from 'none' to 'Taxable Goods'. (which I have set at 17.5%)
If you have the time to take a quick look at the site:
http://www.prestigeringcompany.com/i...roducts_id=377
and suggest any solutions to this I would be most grateful.
I hope that makes sense.
cheers
Darrel
Sorry, to add:
I am currently using version 1.3.8
The price on the product page is always higher (1%) than it should be. If you refresh the page, you can see the CORRECT price very briefly and then it settles INCORRECTLY.
However, when you add the product to cart, the price reverts back to the CORRECT price that has been set for that particular product!!
I have viewed the 'pricing round up' thread issues, and it doesn't seem to be this as it is only the Dynamic Price Updater that gets the incorrect total.
Any suggestions would be very appreciated.
Thanks
Darrel
In my store I have a large amount of products that have no attributes, and when I use the DPUv2 the products that I have specials and no attributes get updated with the Special Price and when the product is Sold Out it shows as "Your Price: 0.00". The product that I'm testing has 3 attributes. The first one is "Add Canopy" and it is a check that adds $91.00. The second one is the finish options with radio buttons. They don't add any amount to the price, and the last attribute is purely a test called Other Option with a "Just Add Me" value and adds the amount of $35.00 to the price. Well, in that order, the canopy Updates the price with the $91.00, but the Just Add Me does not Update the price with its $35.00. If I shuffle the order of the attributes to Add Canopy (first), Just Add Me (second), and the Finish at the end, then it works and both Attributes get to Update the Price.
Using the original DPU, there are no problems with the rest of the products that don't have attributes. The test product with the attributes works exactly the same way that it does with DPUv2 but in IE it shows the Done (with errors) symbol on the lower left corner of the browser and when double clicking the error we get:
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Timestamp: Fri, 14 May 2010 13:13:58 UTC
Message: Object required
Line: 158
Char: 4
Code: 0
URI: http://f i s h p e t l o v e.com/index.php?main_page=product_info&cPath=11&products_id=14580
Message: Object required
Line: 158
Char: 4
Code: 0
URI: http://f i s h p e t l o v e.com/index.php?main_page=product_info&cPath=11&products_id=14580
The error only shows in some IE in some computers, I have seen the IE in two different setups in different locations. I talk with my hosting and they had the same version of IE I have (version: 8.0.6001.18702 running Windows XP) and they didn't see the error. Firefox does not show the error. I setted up IE to not show errors, and it is still showing.:cry::frusty::Flush:
My jscript_updater.php looks like:
Help Please.Code:<?php
// Small module to dynamically update main price when the product has price altering attributes
// (c) D Parry (Chrome) 2007 ([email protected])
// This module is free to distribute and use as long as the above copyright message is left in tact
// Alterations are permitted but please let me know of any changes you make, specifically where incompatibility is concerned
// some contstant declarations
define('UPDATER_PREFIX_TEXT', 'Price: ');
define('UPDATER_SB_TITLE', 'Price Breakdown'); // the heading that shows in the Updater sidebox
?>
<script language="javascript" type="text/javascript">
// <![CDATA[
var objPrice, origPrice;
var defaultCurrencyLeft, defaultCurrencyRight;
defaultCurrencyLeft = defaultCurrencyRight = '';
var quantity = false; // do not alter this
var showQuantity = false; // show the quantity the customer has requested in the main price header
var showQuantitySB = false; // show the quantity the customer has requested in the sidebox
var prArr = nameArr = new Array(); // holds an array of prices to be adjusted (for multiple price adjustments)
var _oflag = false; // do not alter this
var seeker = new RegExp(/\(\s*([+-]?)([^0-9]*)([0-9,]+\.[0-9]+)([^0-9)]*)\s*\)/);
// Updater sidebox settings
var _sidebox = false; // set this to: false - don't use or the ID of the sidebox you want the display to insert above (must be exact)
var objSB = false; // this holds the sidebox object
// Second price setting
// the following settings allow a second price to be displayed... if a page is very long this allows you to add another price display
// thanks to Ryk on the Zen Cart forums for the idea and pointing out the issue
var _secondPrice = 'false'; // set this to either false for disabled or supply the ID of an element for the price to appear BEFORE... for example, cartAdd
var _SPDisplay = 'update'; // governs the behaviour of the second... 'always' permanently displays and 'update' shows the second price only when an attribute is selected
var objSP = false; // please don't adjust this
// debug settings
var _debug = false; // set to false to disable debug output
var _db = '';
var _dbdiv = false;
function init() { // discover the selects that are required to adjust the main price
var centre = document.getElementById('productGeneral');
var objSel = centre.getElementsByTagName('SELECT');
var objInp = centre.getElementsByTagName('INPUT');
var db = '';
var _flag = false; // flag to decide if a load of attribute information is needed
if (!_oflag) { // get the base price and the quantity box (if it exists)
// firstly find out if debug messages should be shown
if (_debug === true) { // build the div that will hold debug messages
createdb();
}
if (_secondPrice !== false && _SPDisplay == 'always') {
regdb('SP Onload', 'Type: ' + _SPDisplay);
updSP();
}
// quantity box
var qtemp = document.getElementById('cartAdd');
if (qtemp) { // got the containing div... go for the quantity!
var itemp = qtemp.getElementsByTagName('INPUT');
if (itemp) { // make sure some inputs are available to scan
for (var i=0; itemp[i]; i++) {
if (itemp[i].name == 'cart_quantity') { // we have the input we need
quantity = itemp[i].value;
regdb('Onload quantity', 'Cart add INPUT discovered (' + quantity + ')');
itemp[i].onkeyup = function () { adjQuan(this); }
}
}
}
}
// if quantity is still false we'll assign it a value of 1
if (quantity === false) quantity = 1;
if (!(objPrice = document.getElementById('productPrices').getElementsByTagName('SPAN')[1])) {
objPrice = document.getElementById('productPrices');
} else {
regdb('Onload sale', 'Looks like an item on sale');
}
origPrice = Number(objPrice.innerHTML.match(/([0-9,.]+)/g)[0].replace(/,/g, ''));
var origHTML = objPrice.innerHTML;
var db = '';
if (!origPrice) {
db = 'Initial phase failure';
if (objPrice) {
db += ' - H2 found';
var temp = objPrice.getElementsByTagName('SPAN');
for (var i=0; temp[i]; i++) {
if (temp[i].className = 'productSpecialPrice') {
origPrice = temp[i].innerHTML.match(/([0-9,.]+)/g)[0].replace(/,/g, '');
db += ' - price in SPAN';
origHTML = temp[i].innerHTML;
if (!origPrice) return;
}
}
} else {
db += ' - price not found!';
return;
}
} else {
db = 'Price found: ' + origPrice;
}
regdb('Onload base price', db);
// try and find the default currency symbols
var temp = origHTML.match(/s*([^0-9 ]*)([0-9.,]+)(.*)/);
defaultCurrencyLeft = temp[1];
db = 'Left: ' + defaultCurrencyLeft;
defaultCurrencyRight = temp[3];
db += ' - Right: ' + defaultCurrencyRight;
regdb('Onload default currency locator', db);
}
for (var i=0; objSel[i]; i++) {
var _this = objSel[i];
objSel[i].onchange = function () { updatePrice(this); }
db = 'Name - ' + objSel[i].name + ' : ID - ' + objSel[i].id;
// scan the attributes to find out if any adjustments are needed
var matches = objSel[i][objSel[i].selectedIndex].text.match(seeker);
if (matches) { // yep
db += ' - Adjusted!';
prArr[objSel[i].id] = new Array();
prArr[objSel[i].id]['p'] = Number(matches[3].replace(/,/, '')); // push the value onto the stack
prArr[objSel[i].id]['n'] = objSel[i][objSel[i].selectedIndex].text.replace(seeker, '');
prArr[objSel[i].id]['m'] = matches[1]; // mode indicator
prArr[objSel[i].id]['l'] = matches[2]; // left side currency indeicator
prArr[objSel[i].id]['r'] = matches[4]; // the right side currency indicator
_flag = true;
}
regdb ('Onload SELECT', db);
}
for (var i=0; objInp[i]; i++) {
if (objInp[i].type == 'radio' || objInp[i].type == 'checkbox') { // make sure we're dealing with radio boxes
db = 'Name - ' + objInp[i].name + ' : ID - ' + objInp[i].id;
matches = objInp[i].nextSibling.innerHTML.match(seeker);
if (matches) {
db += ' : Adjusted!';
objInp[i].onclick = function () { updateR(this); }
if (objInp[i].checked) updateR(objInp[i]);
}
}
regdb('Onload RAD/CH', db);
}
if (_flag && !_oflag) {
updatePriceNow();
}
if (_oflag === true) regdb('Onload', '--- End of loading procedures ---');
_oflag = true;
}
function updSP() {
// adjust the second price display; create the div if necessary
var flag = false; // error tracking flag
if (_secondPrice !== false) { // second price is active
var centre = document.getElementById('productGeneral');
var temp = document.getElementById('productPrices');
var itemp = document.getElementById(_secondPrice);
if (objSP === false) { // create the second price object
if (!temp || !itemp) flag = true;
if (!flag) {
objSP = temp.cloneNode(true);
objSP.id = temp.id + 'Second';
regdb('updSP', 'Price node cloned!');
if (!itemp.parentNode.insertBefore(objSP, itemp.nextSibling)) {
regdb('updSP', 'Unable to insert node at point ' + _secondPrice);
} else {
regdb('updSP', 'Node inserted successfully');
}
} else {
regdb('updSP', 'Unable to clone price node!');
}
}
regdb('updSP', 'Duplicating price, by jove!');
objSP.innerHTML = temp.innerHTML;
} else { // second price inactive
regdb('updSP', 'Cancelled');
}
}
function adjQuan(objInp) {
// adjust the global cart quantity for multiplication
var newVal = Number(objInp.value.match(/[0-9]+/g));
quantity = newVal;
regdb('Quantity change', newVal);
updatePriceNow();
if (_sidebox !== false && objSB === false) createSB();
if (objSB !== false) updateSB(); // update the sidebox
}
function updateR(objInp) {
var matches = objInp.nextSibling.innerHTML.match(seeker);
var priceAdj, totalAdj = 0;
var flag = false;
var db = '';
if (matches) { // make sure this attribute is price-adjust-worthy
db += '*Adj* - ';
priceAdj = Number(matches[3].replace(/,/g, '')); // Number(matches[0].match(/[0-9.]+/)[0]);
} else {
db += '*No adj* - ';
priceAdj = 0;
}
if (objInp.type == 'radio') {
// the radio type input can be inserted into the array using its name as a reference as radio boxes are mutually
// exclusive in their group
db += 'Radio - Name: ' + objInp.name + ' - ';
prArr[objInp.name] = new Array();
prArr[objInp.name]['p'] = priceAdj; // push the price adjustment into the array referenced by the ID of the calling select
prArr[objInp.name]['n'] = objInp.nextSibling.innerHTML.replace(seeker, '');
prArr[objInp.name]['m'] = matches[1];
prArr[objInp.name]['l'] = matches[2]; // left side currency indeicator
prArr[objInp.name]['r'] = matches[4]; // the right side currency indicator
db += 'Price adjust: ' + priceAdj + ' - Mode: ' + matches[1];
} else {
// checkboxes are always autonomous so can have multiple selections from a group so use the ID as before
if (objInp.checked) {
db += 'Checkbox - ID: ' + objInp.id + ' - ';
prArr[objInp.id] = new Array();
prArr[objInp.id]['p'] = priceAdj; // push the price adjustment into the array referenced by the ID of the calling select
prArr[objInp.id]['n'] = objInp.nextSibling.innerHTML.replace(seeker, ''); // attribute name, price removed
prArr[objInp.id]['m'] = matches[1]; // the mode (+, - or base) of the attribute
prArr[objInp.id]['l'] = matches[2]; // left side currency indeicator
prArr[objInp.id]['r'] = matches[4]; // the right side currency indicator
db += 'Price adjust: ' + priceAdj + ' - Mode: ' + matches[1];
} else {
prArr[objInp.id] = null;
db = 'Checkbox ID ' + objInp.id + ' is now NULL';
}
}
regdb('updateR', db);
updatePriceNow();
}
function updatePrice(objSel) { // update the main price from the value extracted by the regex
var matches = objSel[objSel.selectedIndex].text.match(seeker);
var priceAdj, totalAdj = 0;
var db = '';
if (matches) { // make sure this attribute is price-adjust-worthy
db = '*Adj* - ';
priceAdj = Number(matches[3].replace(/,/g, ''));
} else {
db = '*No adj* - ';
priceAdj = 0;
}
if (matches) {
prArr[objSel.id] = new Array();
prArr[objSel.id]['p'] = priceAdj; // push the price adjustment into the array referenced by the ID of the calling select
prArr[objSel.id]['n'] = objSel[objSel.selectedIndex].text.replace(seeker, '');
prArr[objSel.id]['m'] = matches[1];
prArr[objSel.id]['l'] = matches[2]; // left side currency indeicator
prArr[objSel.id]['r'] = matches[4]; // the right side currency indicator
db += 'ID: ' + objSel.id + ' - Price adjust: ' + priceAdj + ' - Mode: ' + matches[1];
} else {
prArr[objSel.id] = null;
db = 'SELECT ID ' + objSel.id + ' is now NULL';
}
regdb('updatePrice', db);
updatePriceNow();
}
function updatePriceNow() { // update the price display
var totalAdj = 0;
var db = '';
var l = defaultCurrencyLeft;
var r = defaultCurrencyRight;
for (var i in prArr) {
if (prArr[i] == '') {
l = (prArr[i]['l'] == '' || typeof(prArr[i]['l']) == 'undefined' ? defaultCurrencyLeft : prArr[i]['l']);
r = (prArr[i]['r'] == '' ? defaultCurrencyRight : prArr[i]['r']);
db = 'Item: ' + prArr[i]['n'] + ' - ';
switch (true) { // adjust the price according to its given mode
case prArr[i]['m'] == '+': // add the attribute price to the base price
db += 'Mode: Add';
db += ' - totalAdj: ' + totalAdj + ' - Adding ' + prArr[i]['p'];
totalAdj += prArr[i]['p'];
break;
case prArr[i]['m'] == '-': // subtract the attribute price from the base
db += 'Mode: Subtract';
db += ' - totalAdj: ' + totalAdj + ' - Subtracting ' + prArr[i]['p'];
totalAdj -= prArr[i]['p'];
break;
case prArr[i]['m'] == '': // this means the attribute actually replaces the base price
db += 'Mode: Base';
db += ' - Altering base to ' + prArr[i]['p'];
origPrice = prArr[i]['p'];
break;
}
regdb('updatePriceNow', db);
}
}
var newPrice = ((origPrice + totalAdj) * quantity).toFixed(2);
document.getElementById('productPrices').innerHTML = '<?php echo UPDATER_PREFIX_TEXT; ?>' + l + addCommas(newPrice) + r + (showQuantity ? ' (' + quantity + ')' : '');
if (_sidebox !== false && objSB === false) createSB();
if (objSB !== false) updateSB(); // update the sidebox
updSP();
}
function createSB() { // create the sidebox for the attributes info display
if (_sidebox !== false) {
var temp = document.getElementById(_sidebox); // get a handle to the sidebox to insertBefore
if (temp) {
objSB = document.createElement('DIV'); // create the sidebox wrapper
objSB.id = 'updaterSB';
objSB.className = 'leftBoxContainer'; // set the CSS reference
// create the heading bit
var tempH = document.createElement('H3');
tempH.id = 'updateSBHeading';
tempH.className = 'leftBoxHeading';
tempH.innerHTML = '<?php echo UPDATER_SB_TITLE; ?>';
objSB.appendChild(tempH);
// create the content div
var tempC = document.createElement('DIV');
tempC.id = 'updaterSBContent';
tempC.className = 'sideBoxContent';
tempC.innerHTML = 'If you can read this Chrome has broken something';
objSB.appendChild(tempC);
temp.parentNode.insertBefore(objSB, temp);
regdb('createSB', 'Sidebox created!');
} else {
regdb('createSB', 'Sidebox could not be created!');
}
}
}
function updateSB() { // update the contents of the sidebox with the updated info from the attributes selector
var newText = hText = '';
var l = defaultCurrencyLeft;
var r = defaultCurrencyRight;
var totalAdj = origPrice;
for (var i in prArr) {
if (prArr[i] == '') {
l = (prArr[i]['l'] == '' || typeof(prArr[i]['l']) == 'undefined' ? defaultCurrencyLeft : prArr[i]['l']);
r = (prArr[i]['r'] == '' ? defaultCurrencyRight : prArr[i]['r']);
if (prArr[i]['m'] !== null && prArr[i]['m'] != '') {
if (prArr[i]['m'] == '-') newText += '<span style="color: red;">';
newText += prArr[i]['n'] + (prArr[i]['p'] != 0 ? ' - ' + (showQuantitySB ? quantity + 'x ' : '') + prArr[i]['l'] + prArr[i]['p'].toFixed(2) + prArr[i]['r']: '') + '<br/>';
if (prArr[i]['m'] == '-') newText += '<\/span>';
switch (true) { // adjust the price according to its given mode
case prArr[i]['m'] == '+': // add the attribute price to the base price
totalAdj += prArr[i]['p'];
break;
case prArr[i]['m'] == '-': // subtract the attribute price from the base
totalAdj -= prArr[i]['p'];
break;
case prArr[i]['m'] == '': // this means the attribute actually replaces the base price
origPrice = prArr[i]['p'];
break;
}
}
}
}
hText += 'Product price - ' + (showQuantitySB ? quantity + 'x ' : '') + l + addCommas(origPrice.toFixed(2)) + r + '<br/>';
newText += '<hr />Total: ' + l + addCommas((totalAdj * quantity).toFixed(2)) + r;
// I know innerHTML is cheating but I careth not :)
objSB.getElementsByTagName('DIV')[0].innerHTML = hText + newText;
}
function addCommas(nStr)
{ // this function can be found at http://www.mredkj.com/javascript/numberFormat.html#addcommas
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
function createdb () {
var centre = document.getElementById('productGeneral');
if (_dbdiv === false) {
_dbdiv = document.createElement('DIV');
_dbdiv.style.border = '2px dashed #666';
_dbdiv.style.padding = '0.1em';
centre.appendChild(_dbdiv)
}
_dbdiv.innerHTML = '<div style="cursor: pointer; width: 100%; text-align: center; margin-bottom: 5px; background-color: #aaa; padding: 1px; font-size: 110%; font-weight: bold;" onclick="createdb();">Debug messages<\/div>';
}
function regdb(strTitle, strText) { // simple routine to format and output the debug messages
if (_debug === true) { // make sure debug messages should be displayed
_dbdiv.innerHTML += '<div style="margin: 2px 0; background-color: #ddd; border-top: 1px solid #aaa; border-bottom: 1px solid #aaa;"><span style="font-weight: bold;">' + strTitle + ':<\/span> ' + strText + '<\/div>';
}
}
// the following statements should allow multiple onload handlers to be applied
// I know this type of event registration is technically deprecated but I decided to use it because I haven't before
// There shouldn't be any fallout from the downsides of this method as only a single function is registered (and in the bubbling phase of each model)
// For backwards compatibility I've included the traditional DOM registration method
try { // the IE event registration model
window.attachEvent('onload', init);
} catch (e) { // W3C event registration model
window.addEventListener('load', init, false);
} finally {
window.onload = init;
}
// ]]></script>
Fred
Hi all
Sorry for taking ages to reply... I've been away from my machine for some time and I'm just now getting caught up with everything
The tax problem I think I have an idea about now so I'm going to be looking into it as soon as I can
Fred, have you tried V2 of the Updater to see what that makes of your attributes? I know V2 has some issues currently but these seem to largely revolve around the tax class
Let me know and I will also check out your site
Cheers
Dan
Hi Dan, Check out the test product I set up with some attributes:
http://f i s h p e t l o v e . c o m /test
Just put the letters together and you will be there
I tried V2 also, but V2 had more problems. v1 gives the following error in the little triangle (Done but with errors) only shows in Internet explorer:
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Timestamp: Wed, 19 May 2010 02:59:25 UTC
Message: Object required
Line: 158
Char: 4
Code: 0
URI: http://f i s h p e t l o v e . c o m /test
Message: Object required
Line: 158
Char: 4
Code: 0
URI: http://f i s h p e t l o v e . c o m /test
Thanks
Fred.