Jump to content

Tawe Luki

Members
  • Content count

    11
  • Joined

  • Last visited

Profile Information

  • Real Name
    Tassilo Kirsch
  1. Tawe Luki

    AJAX Attribute Manager support

    @msinternet: Sorry, wasn't here for some time because my comp went up in smoke. Literally. Well, not too bad - it ran 24/7 for more than 6 years, killing 3 CPU fans in the process. The first two times I was able to notice that something was wrong and replace the fans just in time. The third time, I somehow missed the warning signals... About the variable names: They're a mess, but there is a plan: Names in plural (eg. "options_id") are for fields in database queries. Names in singular (eg. "option_id") are for fields in local arrays. Names in CamelCase (eg. $optionsId) are for variables. Atomic mode does not work for existing products (editing). As you've figured out, it's missing an initialisation where the product's existing attributes are read. Updating the database in attributeManagerUpdateAtomic.inc.php also doesn't work as expected. The following fix is not tested First, the initialisation: Add to attributeManagerAtomic.class.php (add it to the class): function getProductAttributes($get) { $queryString = "select * from ".TABLE_PRODUCTS_ATTRIBUTES." where products_id = '".(int)$get['products_id']."' order by "; $queryString .= !AM_USE_SORT_ORDER ? "options_id" : AM_FIELD_OPTION_VALUE_SORT_ORDER; $query = amDB::query($queryString); while($res = amDB::fetchArray($query)) { $this->arrSessionVar[] = array( 'option_id' => $res['options_id'], 'option_value_id' => $res['options_values_id'], 'price' => $res['options_values_price'], 'prefix' => $res['price_prefix'], 'sortOrder' => $res[AM_FIELD_OPTION_VALUE_SORT_ORDER]); } } In attributeManagerGeneralFunctions.inc.php, replace function &amGetAttributeManagerInstance with: function &amGetAttributeManagerInstance($get) { if (!is_numeric($get['products_id']) || AM_ATOMIC_PRODUCT_UPDATES) { // first time visiting the page - delete the session var and start again if(!tep_not_null($get[AM_ACTION_GET_VARIABLE])) { amSessionUnregister(AM_SESSION_VAR_NAME); } amSessionRegister(AM_SESSION_VAR_NAME, array()); $attributeManager =& new attributeManagerAtomic(amGetSesssionVariable(AM_SESSION_VAR_NAME)); if (is_numeric($get['products_id'])) { $attributeManager->getProductAttributes($get); } } else { $attributeManager =& new attributeManagerInstant($_GET['products_id']); } return $attributeManager; } Finally, the update: In attributeManagerUpdateAtomic.inc.php, replace if(is_array(${AM_SESSION_VAR_NAME}) && is_numeric($products_id)){ with if(is_array(${AM_SESSION_VAR_NAME}) && is_numeric($products_id)){ amDB::query("delete from ". TABLE_PRODUCTS_ATTRIBUTES ." where products_id = '" . $products_id . "'"); The last one is pretty brute force - we just delete all the product's attributes from the database and then insert them again from the session var (as if it was a new product). A better way would be to re-read the original attributes (like in getProductAttributes()) and to check which attributes have actually been changed, added or removed. Btw., there is a general problem with the atomic mode: It only works as long as editing/adding a product is done with a single call of the page which has the attribute manager. It doesn't work as soon as you want to call it again without updating the database in between. As an example, in my catalog products need to have unique model numbers. This means that it's possible to come back to the product page with an error message (model missing or model already exists) and without updating the database. And then you're screwed because the attribute manager forgets all changes made. Another problem comes when the user opens another tab/window for the same product (or another new product). Try this out: open the new product page, enter some attributes, then hit the green arrow next to Firefox's location bar with the middle mouse button (to open another new product page in a new tab) and see what happens...
  2. Tawe Luki

    AJAX Attribute Manager support

    Replace this with $this->arrSessionVar[] = $getArray; and everything should work fine. [] adds a new element to arrSessionVar (that's what we want), while [$id] replaces element arrSessionVar[''] ('' because $id wasn't set to any value before, so it's null, but since null isn't a valid array key, PHP's automatic type conversion comes into play). [$id] was neither in the bugfix nor in the original version, so I guess you somehow messed that up on your own. Well, shit happens all the time. :) Btw. $id in update() isn't an actual id but just an array index. The actual ids are generated later by the database itself when attributeManagerUpdateAtomic.inc.php inserts the attributes.
  3. Tawe Luki

    AJAX Attribute Manager support

    Sounds like a good clue. It should read [0] for the first entry. $res? There shouldn't be a $res in addAttributeToProduct. On that note, can you post your version of function addAttributeToProduct (from Atomic.class)? I think that's the easiest way to fix this. And while we're at it, here's another bugfix, this time for attributeManagerConfig.class.php. Delete line 55 /** * Install templates if not already done so */ $this->installTemplates(); Delete line 69 /** * Install the sort order tables if they dont already exist */ $this->installSortOrder(); Add to the end of function attributeManagerConfig (line 97 before the deletions): /** * Install templates and sort order if they dont already exist */ $this->installTemplates(); $this->installSortOrder(); The reason for this is that both install functions use values which are set after they've been called in the original. As a result, you can see [AM_SESSION_TEMPLATES_INSTALL_CHECKED] and [0] as the names of the session vars, although those name should actually be [am_templates_checked] and [am_sort_order_checked]. The funny thing is that it actually works as expected because on another error: Replace (line 120 before the changes) amSessionRegister('AM_SESSION_TEMPLATES_INSTALL_CHECKED',true); with amSessionRegister($this->getValue('AM_SESSION_TEMPLATES_INSTALL_CHECKED'),true);
  4. Tawe Luki

    AJAX Attribute Manager support

    Are you talking about the bugfixes I've posted? Attribute Manager has two modes, instant and atomic. The difference between them is when the database is updated. Both modes will update the database instantly whenever you add a new option or option value (that is, whenever you're prompted for a name). In instant mode, which is the default when editing an existing product, all changes to the product's attributes (adding, removing, changing the price or sort order) will also update the database instantly. In atomic mode, used for new products, the database isn't updated until you actually create the product (this happens in attributeManagerUpdateAtomic.inc.php). Instead, the data is stored in a session variable. For testing: Add to the end of attributeManager.php <pre> <?php print_r($_SESSION); ?> </pre> Completely breaks the design, but at least you can see what's going on. If you're using Firebug, it's a better idea to add <!-- <?php print_r($_SESSION); ?> --> and to examine the AJAX responses. The critical functions are addAttributeToProduct() (adds a new attribute to the product/session var) and update() (updates the session var for an existing attribute) in attributeManagerAtomic.class.php and the code in attributeManagerUpdateAtomic.inc.php (uses the session var to update the database).
  5. Tawe Luki

    AJAX Attribute Manager support

    Thanks, I can see clearer now (well, at least a little bit). Is it possible that you've changed the error reporting level in admin/aplication_top.php (right at the top of the script) to something different than this? error_reporting(E_ALL & ~E_NOTICE); If so, then change it back for the time you're making changes to your site. We want to see PHP errors (especially warnings). The get data you've posted was very helpful. It shows that the params are correct, but the response isn't. More precisely. there are some things missing in the response: The fields to enter a price (and a sort order) for a new attribute at the bottom of the page, called newPrice, newPrice_gross and newSort. Unfortunately, the newPrice and newPrice_gross fields are needed in the javascript amUpdAllGross() function, which should lead to a javascipt error (something like ... has no properties). The value for the _gross input fields is missing. It is set by tep_round(tep_add_tax($optionValueInfo['price'],$_GET['taxRate'],true),4) And that's really strange. Because of the way tep_draw_input_field and tep_round work, it should be there, no matter what's inside tep_round(). Except something inside generates a PHP warning - that's why I was asking about the error reporting level you're using. But don't waste your time with this bug. Just replace the tep_round(...) code shown above with a simple '' so that you get something like tep_draw_input_field("price_gross_$optionValueId",'','style=... If we get amUpdAllGross to work, we don't need to calculate the tax here any longer. So, let's find out why the newPrice and newPrice_gross fields aren't there!
  6. Tawe Luki

    AJAX Attribute Manager support

    As I said, weird. Because... IF you can see the attribute manager on your page AND Firebug is enabled (the Firebug icon on the right of the browser's status bar is green or red, not gray) AND Show XMLHttpRequests is checked in Firebug's console options (open Firebug, click on the Console tab at the left, then on Options on the right) THEN there has to be a GET entry in Firebug's console. That GET entry shows the XMLHttpRequest needed to create the attribute manager. Without it, you simply couldn't see the attribute manager (it would still be the empty div from attributeManagerPlaceHolder.inc.php). So, please check again. Keep in mind: Knowing how to use Firebug may help you in the future, because there's always another update, another contrib, another bug.
  7. Tawe Luki

    AJAX Attribute Manager support

    That's weird. Anyway, about Firebug: Install from here: https://addons.mozilla.org/en-US/firefox/addon/1843 After that, the first thing you want to do is to disable it (Tools/Firebug/Disable Firebug). Firebug is a great tool for testing and developing, but it's also time and memory consuming and may even crash Firefox when used on really buggy sites. That's why you should enable it only for the sites you're actually developing. After you've disabled Firebug, the Firebug icon on the right of your status bar should be grey. Next, go to your site. Hit F12 to open Firebug and click on "Enable Firebug for this web site". Now the Firebug icon should be green (or red). Then call the page which has the error. In the Firebug window, there's a console tab (should be active on default) which shows javascript errors (in red) and AJAX requests. If there are any javascript errors, you can try to fix them by yourself or post them here. If there aren't, there should be at least one line which starts with GET. That's the AJAX request which created the attributes table. Click on it. Now you'll see three tabs, Params, Headers and Response. Click on Params and copy the tab's content to post it here. Then right-click on Response, choose Copy Response Body and paste it to your post (please use a Insert Special Item - CODEBOX for this). Then we'll see...
  8. Tawe Luki

    AJAX Attribute Manager support

    It shure was, but I still don't know what went wrong. Let's try this: In attributeManager.js change the function amUpdateContent so that it looks like this: function amUpdateContent(id) { getElement(amRequester.getTarget()).innerHTML = amRequester.getText(); amRestoreDisplayState(); amUpdAllGross(); } (in other words: add amUpdAllGross(); to it) If that also doesn't work, then we have to take a closer look at what happens behind the scenes. I recommend using Firefox with the Firebug add-on - a f*cking great tool when testing javascript/AJAX. But hopefully it works. :)
  9. Tawe Luki

    AJAX Attribute Manager support

    What kind of update? And which gross field (the one for the new attribute or the fields in the table)? There's a small problem here: I'm working on an osC fork with heavy changes to the admin section (for instance, my version of the Attribute Manager isn't called from categories.php but from a separate products_edit script) and I'm rewriting the Attribute Manager to fit my needs (like entering gross values, a WYSIWYG approach to the sort order and some bugfixes). This simply means that you have to be a bit more specific about an error so that I can figure out exactly what you did and why the script didn't do what it was supposed to do. :) On that note: Version 2.7 DOES NOT WORK for new products. It will forget all entered prices and may add some bogus attributes. BUGFIX: attributeManagerUpdateAtomic.inc.php Replace "option_value_price" with "price" (without the quotes). attributeManagerAtomic.class.php Replace "option_value_price" with "price" (without the quotes). Now prices will be updated. Replace "options_values_id" with "option_value_id" (without the quotes). Now it's possible to remove an option value. Replace "options_id" with "option_id" (without the quotes). Now it's possible to remove an option. In function update($get) (line 201) replace $this->arrSessionVar[] = $getArray; with foreach($this->arrSessionVar as $id => $res) { if(($res['option_id'] == $getArray['option_id']) && ($res['option_value_id'] == $getArray['option_value_id'])) { $this->arrSessionVar[$id] = $getArray; break; } } (that looks like a copy & paste gone wrong)
  10. Tawe Luki

    AJAX Attribute Manager support

    Sorry, there's a typo. It should read amUpdAllGross instead of amUpdGrossAll. So, Step #5 is: In the tax class selection drop down, replace 'onchange="updateGross()"' with 'onchange="updateGross();amUpdAllGross()"' (basically, just add ;amUpdAllGross() to whatever the onchange event of the tax class selection is right now) This should work now.
  11. Tawe Luki

    AJAX Attribute Manager support

    Entering gross and net prices This allows entering prices with and without tax. It does basically the same as categories.php, instead of one price field there are two, one (to the left) for the gross price and one (to the right) for the net price, both automatically updated via onKeyUp event handlers. Step #1 - Requirements I'm using the latest version of the Attribute Manager (2.7). It should also work with earlier versions, but finding the right places for the replacements could be harder. Check if the following javascript functions exist in your version of categories.php (including linked scripts): function getTaxRate() function doRound(x, places) If not, the contrib(s) you're using have their own ideas about entering gross and net values and I can't help you. :( If they do exist, feel free to continue. :) Step #2 - IMPORTANT! Backup the following files: admin/categories.php admin/attributeManager/attributeManager.php admin/attributeManager/javascript/attributeManager.js Step #3 - Changes to attributeManager.js Replace (in function amSendRequest) function calcGross(net, rate) { if (rate > 0) { return doRound(net * ((rate / 100) + 1), 4); } else { return net; } } function calcNet(gross, rate) { if (rate > 0) { return doRound(gross / ((rate / 100) + 1), 4); } else { return gross; } } function amUpdNet(optionValueId) { var taxRate = getTaxRate(); getElement('price_'+optionValueId).value = calcNet(getDropDownValue('price_gross_'+optionValueId), taxRate); return true; } function amUpdGross(optionValueId) { var taxRate = getTaxRate(); getElement('price_gross_'+optionValueId).value = calcGross(getDropDownValue('price_'+optionValueId), taxRate); return true; } function amUpdNewNet() { var taxRate = getTaxRate(); getElement('newPrice').value = calcNet(getDropDownValue('newPrice_gross'), taxRate); return true; } function amUpdNewGross() { var taxRate = getTaxRate(); getElement('newPrice_gross').value = calcGross(getDropDownValue('newPrice'), taxRate); return true; } function amUpdAllGross() { var inp = getElement('attributeManager').getElementsByTagName("input"); for (var i = 0; i < inp.length; i++) { var n = inp[i].getAttribute('name'); if (n && n.match(/^price_gross_/)) { amUpdGross(n.substr(12)); } } amUpdNewGross(); } Step #4 - Changes to attributeManager.php Add the gross price field and the event handlers to the new attribute values at the bottom: Replace <td valign="top"> <?=AM_AJAX_PRICE?> <?php echo tep_draw_input_field('newPrice','','size="4" id="newPrice"'); ?> </td> with <td valign="top"> <?=AM_AJAX_PRICE?> <?php echo tep_draw_input_field('newPrice_gross','','size="7" id="newPrice_gross" onKeyUp="amUpdNewNet()"'); ?> <?php echo tep_draw_input_field('newPrice','','size="7" id="newPrice" onKeyUp="amUpdNewGross()"'); ?> </td> Add the gross price field and the event handlers to the option value rows in the table: Replace <?php echo tep_draw_input_field("price_$optionValueId",$optionValueInfo['price'],' style="margin:3px 0px 3px 0px;" id="price_'.$optionValueId.'" size="7" onChange="return amUpdate(\''.$optionId.'\',\''.$optionValueId.'\');"'); ?> with <?php echo tep_draw_input_field("price_gross_$optionValueId",tep_round(tep_add_tax($optionValueInfo['price'],$_GET['taxRate'],true),4),' style="margin:3px 0px 3px 0px;" id="price_gross_'.$optionValueId.'" size="7" onKeyUp="amUpdNet(\''.$optionValueId.'\')" onChange="return amUpdate(\''.$optionId.'\',\''.$optionValueId.'\');"'); ?> <?php echo tep_draw_input_field("price_$optionValueId",$optionValueInfo['price'],' style="margin:3px 0px 3px 0px;" id="price_'.$optionValueId.'" size="7" onKeyUp="amUpdGross(\''.$optionValueId.'\')" onChange="return amUpdate(\''.$optionId.'\',\''.$optionValueId.'\');"'); ?> Step #5 - Changes to categories.php Search for the line where the tax class pull down is written, there should be something like tep_draw_pull_down_menu('products_tax_class_id' In this line, replace 'onchange="updateGross()"' with 'onchange="updateGross();amUpdGrossAll()"' (basically, just add ;amUpdGrossAll() to whatever the onchange event of the tax class selection is right now) Step #6 - Happy testing! :D
×