Magento + jQuery + Аякс - Как мне перезагрузить только части моего пользовательского модуля вместо всего блока?
Совсем недавно мне было поручено за 5 дней создать простой конфигуратор продукта для нашего шаблона Magento, в котором вы можете выбрать некоторые атрибуты, и он рассчитает для вас цену, изменит новое изображение и изменит кнопку "Добавить в корзину" на новый продукт.
До этого у меня не было опыта работы с PHP или jQuery, а только некоторые основы в Magento (никогда раньше не делал пользовательский модуль). Мой единственный опыт программирования - это ООП-игры в сценарии действий 3.
Пока мой код как-то работает. У меня есть некоторые переменные, которые я могу изменить нажатием некоторых переключателей, и переменные обновляются с помощью метода ajax. В качестве URL-адреса вызывается мой метод индекса блока, который просто загружает и отображает мой макет. После того, как я добавлю возвращенный HTML (который является всем моим блоком) в родительский элемент моего самого внешнего div в моем блоке. Это работает, но я, похоже, не могу найти способ анимировать изменения, и это кажется довольно медленным, если ajax перестраивает весь блок каждый раз, когда пользователь просто меняет один вариант.
Есть ли более элегантный способ просто перезагрузить измененные части, плавно анимировать изменения и заставить мой блок запоминать изменения в моих входных данных?
Вот все файлы для загрузки: http://www.roflxd.de/doorconfig.zip
Если вам нужен доступ к самому сайту, чтобы посмотреть, как он выглядит в настоящее время, пожалуйста, напишите мне:)
Заранее спасибо!
Мой блок phtml:
<?php
$type = 'Simple';
$color = 'FFFFFF';
$size = '2500x1800';
if (isset($_POST['color'])) {
$color = "#" . $_POST['color'];
}
if (isset($_POST['type'])) {
$type = $_POST['type'];
}
if (isset($_POST['size'])) {
$size = $_POST['size'];
}
$currentStoreUrl = Mage::getBaseUrl();
$currentProduct = $this->getProduct($type,$color,$size);
$currentId = $currentProduct->getId();
$currentUrl = $currentProduct->getProductUrl();
$currentPrice = $this->getPrice($currentId);
$currentImgUrl = $this->getDoorBaseImgUrl($type, $size);
?>
<div id="door_wrapper" class="">
<div id="door_left_wrapper" class="mj-grid48">
<form id="testform">
<div id="door_colors">
<label id="FFFFFF">White<input type="radio" name="toggle" value="FFFFFF"></label>
<label id="000000">Black<input type="radio" name="toggle" value="000000"></label>
<label id="736D6C">Grey<input type="radio" name="toggle" value="736D6C"></label>
</div>
<div id="door_model" >
<?php print_r($_POST); ?>
<?php echo $type;?>
<?php echo $color;?>
<?php echo $size;?>
<br>
<?php echo $currentImgUrl;?>
</div>
<div id="door_size">
<select name="doorsizes">
</select>
</div>
<?php if ($currentProduct->isSaleable()): ?>
<button type="button">
<a href="<?php echo $currentStoreUrl . "checkout/cart/add?product=" . $currentId . "&qty=1";?>">
Test
</a>
</button>
<?php else: ?>
<button disabled>Out of Stock</button>
<?php endif;?>
</form>
</div>
<div id="door_right_wrapper" class="mj-grid48">
<div id="door_img">
<img src="<?php echo $currentImgUrl;?>">
</div>
<div id="result"></div>
</div>
</div>
<script type="text/javascript">
var $col = "000000";
var $type = "Advanced";
var $size = "3050x2150";
function ajaxUpdate()
{
$j.ajax({
url: "/doorconfig/ajax/index",
type: "POST",
data: {color : $col, type : $type, size : $size },
context: $j('#door_wrapper').parent(),
success: function(data)
{
$j(this).html(data).$(this).fadeIn(slow);
}
});
};
$j(document).ready(function()
{
$j("input[name=toggle]:radio").change(function ()
{
ajaxUpdate();
})
});
</script>
Мой блок php:
<?php
class Geeklab_DoorConfig_Block_Doorconfig extends Mage_Core_Block_Template
{
public function getProduct($type,$color,$size)
{
//Get Product Collection
$collection = Mage::getModel('catalog/product')->getCollection();
//Select needed Attributes
$collection->addAttributeToSelect('doorconfig_enable');
$collection->addAttributeToSelect('doorconfig_color');
$collection->addAttributeToSelect('doorconfig_size');
$collection->addAttributeToSelect('doorconfig_type');
//Filter for Selected Product
$collection->addFieldToFilter('doorconfig_enable',
array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute('doorconfig_enable')
->getSource()
->getOptionId('Yes')
)
);
$collection->addFieldToFilter('doorconfig_color',
array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute('doorconfig_color')
->getSource()
->getOptionId($color)
)
);
$collection->addFieldToFilter('doorconfig_size',
array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute('doorconfig_size')
->getSource()
->getOptionId($size)
)
);
$collection->addFieldToFilter('doorconfig_type',
array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute('doorconfig_type')
->getSource()
->getOptionId($type)
)
);
$product = $collection->getFirstItem();
return $product;
}
public function getPrice($id)
{
$product = Mage::getModel('catalog/product')->load($id);
$_taxHelper = new Mage_Tax_Helper_Data;
$finalprice = $_taxHelper->getPrice($product, $product->getFinalPrice(), true);
$finalprice .= $this->getCurrency();
return $finalprice;
}
public function getCurrency()
{
return Mage::app()->getLocale()->currency(Mage::app()->getStore()->getCurrentCurrencyCode())->getSymbol();
}
public function getDoorImageDir()
{
return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'wysiwyg/geeklab/doorconfig/';
}
public function getDoorBaseImgUrl($type, $size)
{
return $this->getDoorImageDir() . strtolower($size) . '_' . str_replace("\040", "\137", strtolower($type)) . '.png';
}
public function getDoorColorImgUrl($color, $size)
{
return $this->getDoorImageDir() . strtolower($size) . '_' . strtolower($color) . '.png';
}
}
?>
И мой AjaxController.php
<?php
class Geeklab_DoorConfig_AjaxController extends Mage_Core_Controller_Front_Action
{
public function indexAction ()
{
$this->loadLayout();
$this->renderLayout();
}
}
?>
1 answers
Поэтому я придумал решение, которое работает просто потрясающе. Я добавил еще одно действие контроллера и модель для взаимодействия с Magento во время моих вызовов ajax. Так что позвольте мне показать вам, как это делается, я надеюсь, что рано или поздно кто-нибудь сможет извлечь из этого выгоду:)
Мое новое действие:
public function updateAction ()
{
//Instantiate Product Model
$productModel = Mage::getModel('doorconfig/product');
//Get Updated Values from the Model
$currentProduct = $productModel->getProduct($_POST);
$currentProductId = $currentProduct->getId();
$currentProductUrl = $currentProduct->getProductUrl();
$currentPrice = $productModel->getPrice($currentProductId);
$currentType = $this->getRequest()->getPost('doorconfig_type');
$currentSize = $this->getRequest()->getPost('doorconfig_size');
$currentProductBaseImgUrl = $productModel->getDoorBaseImgUrl($currentType,$currentSize);
//Populate Resultarray
$result = array("currentProductId"=>$currentProductId,"currentPrice"=>$currentPrice,"currentProductUrl"=>$currentProductUrl,"currentProductBaseImgUrl"=>$currentProductBaseImgUrl);
//Encode Result in JSON
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
return $result;
}
Моя модель только что получила большую часть бизнес-логики из моего блока, так что ничего особенного в этом нет.
И, наконец, обновленный раздел Ajax, который теперь запускает мое новое действие контроллера, получает результат в виде кодирования JSON и изменяет значения в DOM:
<script type="text/javascript">
var $price = "";
var $baseImgUrl = "";
var $productUrl = "";
var $productId = "";
var $f = $j("#attributeform");
var $formData;
var $currentStoreUrl = "<?php echo $currentStoreUrl ?>";
function ajaxUpdate()
{
$j.ajax({
url: "/doorconfig/index/update",
type: "POST",
data: $formData,
dataType: "json",
success: function(data)
{
$productId = data.currentProductId;
$price = data.currentPrice;
$baseImgUrl = data.currentProductBaseImgUrl;
$productUrl = data.currentProductUrl;
$j("#result").text($price);
$j("#addtocart").attr('href', $currentStoreUrl + "checkout/cart/add?product=" + $productId + "&qty=1");
$j("#productimg").attr('src', $baseImgUrl);
console.log(data);
},
error: function(error)
{
console.log("Error:");
console.log(error);
alert("ERROR");
}
});
};
$j(document).ready(function()
{
$j("#result").text('<?php echo $defaultProductPrice; ?>');
$j("#addtocart").attr('href', '<?php echo $currentStoreUrl . "checkout/cart/add?product=" . $defaultProductId . "&qty=1" ?>');
$j("#moreinfo").attr('href', '<?php echo $defaultProductUrl; ?>');
$j("#productimg").attr('src', '<?php echo $defaultProductImgUrl; ?>');
$j("#attributeform")[0].reset();
$j("form[name=attributeform]").change(function ()
{
$formData = $f.serialize();
ajaxUpdate();
})
});
</script>
Если вам нужны какие-либо дополнительные объяснения или вы хотите что-то улучшить, пожалуйста, прокомментируйте:)