Page MenuHomeIn-Portal Phabricator

modern-store
No OneTemporary

File Metadata

Created
Thu, Apr 17, 11:59 PM

modern-store

Index: branches/1.0.x/inc/js/cart_manager.js
===================================================================
--- branches/1.0.x/inc/js/cart_manager.js (revision 14831)
+++ branches/1.0.x/inc/js/cart_manager.js (revision 14832)
@@ -1,597 +1,603 @@
function ShopCartManager( $settings ) {
this.updateUrl = '';
this.orderInfo = {};
this.constants = {};
this.currencyMask = '%s';
this.debugMode = false;
$.extend(this, $settings);
this.rowTimers = {};
var $me = this;
$(document).ready(
function () {
$me.init();
}
);
}
ShopCartManager.prototype.init = function () {
var $me = this;
this.process(this.orderInfo);
$('.delete-cart-link').click(
function ($e) {
var $order_item_id = $(this).parents('tr:first').attr('order_item_id');
$me.apply( [{name: 'delete_id', value: $order_item_id}] );
return false;
}
);
$('.product-qty:input', '#shopping-cart-form')
.blur(
function ($e) {
var $row_index = $(this).parents('tr[row_index]:first').attr('row_index');
if ( $me.debugMode ) {
console.log('blur on ', $row_index, ' row');
}
$me.clearRowTimers($row_index);
if ( $me.debugMode ) {
console.log('doing apply (from blur) on ', $row_index, ' row');
}
$me.apply();
return false;
}
)
.keyup(
function ($e) {
var $row_index = $(this).parents('tr[row_index]:first').attr('row_index');
if ( $me.debugMode ) {
console.log('keyup on ', $row_index, ' row');
}
$me.clearRowTimers($row_index);
$me.rowTimers[$row_index] = setTimeout(
function() {
if ( $me.debugMode ) {
console.log('doing apply (from keyup) on ', $row_index, ' row');
}
$me.apply();
}
, 2000
);
}
);
$('#remove-coupon').click(
function ($e) {
$me.apply( [{name: 'remove', value: 'coupon'}] );
return false;
}
);
$('#remove-gift-certificate').click(
function ($e) {
$me.apply( [{name: 'remove', value: 'gift_certificate'}] );
return false;
}
);
$('#update-cart, #apply-coupon, #apply-gift-certificate').click(
function ($e) {
$me.apply();
return false;
}
);
}
ShopCartManager.prototype.clearRowTimers = function ($row_index) {
if ( this.rowTimers[$row_index] !== undefined ) {
if ( this.debugMode ) {
console.log('cleartimers on ', $row_index, ' row -> found = delete');
}
clearTimeout(this.rowTimers[$row_index]);
delete this.rowTimers[$row_index];
}
else if ( this.debugMode ) {
console.log('cleartimers on ', $row_index, ' row -> not found = skip');
}
}
ShopCartManager.prototype.apply = function ($params) {
var $me = this;
$.post(
this.updateUrl,
this.getFormData($params),
function ($data) {
$data = eval('(' + $data + ')');
$me.process($data);
}
)
}
ShopCartManager.prototype.getFormData = function ($params) {
var $ret = $('#shopping-cart-form').serializeArray();
if ( $params !== undefined ) {
while( $params.length > 0 ) {
$ret.push( $params.shift() );
}
}
return $ret;
}
ShopCartManager.prototype.process = function ($data) {
// 1. row missing ajax response -> was deleted in db
// 2. row missing in HTML -> was added in db
var $me = this,
$old_rows = this.getOldRows(),
$new_rows = this.getNewRows($data),
$add_rows = $new_rows.diff($old_rows),
$delete_rows = $old_rows.diff($new_rows);
if ( this.debugMode ) {
console.log('proessing data: ', $data);
}
// add rows
$($add_rows).each(
function () {
$me.addRow( this, $data.items[this] );
}
);
// delete rows
$($delete_rows).each(
function () {
var $row = $me.getRowByIndex(this);
// $row.next('tr.separator').remove();
$row.remove();
}
);
this.updateExistingRows($data);
this.showErrors($data);
this.showFooter($data);
if ( this.debugMode ) {
console.log('old: ', $old_rows, '; new: ', $new_rows, '; add: ', $add_rows, '; delete: ', $delete_rows);
}
}
ShopCartManager.prototype.addRow = function ($row_index, $row_data) {
if ( this.debugMode ) {
console.log('adding row: ', $row_data);
}
var $html = $('#product-row-mask').val(),
$value = '';
/*f: OrderItemId ; v: 101
f: ProductName ; v: Product With Stock Limit = 5; with backorder
f: BackOrderFlag ; v: 1
f: FlatPrice ; v: 2
f: Price ; v: 1.2308
f: Quantity ; v: 2
f: Virtual ; v: 0
f: cust_Availability ; v:*/
for (var $field in $row_data.fields) {
$value = $row_data.fields[$field];
if ( $field == 'Price' || $field == 'FlatPrice' ) {
$value = this.formatPrice($value);
}
$html = $html.replace(new RegExp('{field:' + $field + '}', 'g'), $value);
if ( this.debugMode ) {
console.log('f: ', $field, '; v: ', $value);
}
}
$html = $html.replace(/{ROW_INDEX}/g, $row_index);
// $html = $html.replace(/{DISCOUNT}/g, $row_index);
// $html = $html.replace(/{EXTENDED_PRICE}/g, $row_index);
// var $separator = $( $('#product-row-separator-mask').val() );
$('.shop-cart-row:last').after($html);
/*$('.shop-cart-row:last').after($separator);
$separator.after($html);*/
}
ShopCartManager.prototype.updateExistingRows = function ($data) {
if ( $.isArray($data.items) ) {
// todo: hide empty shopping cart & show special message
$('#item-count').html(0);
return;
}
var $row_count = 0;
for (var $row_index in $data.items) {
var $fields = $data.items[$row_index].fields,
$discount = $fields['FlatPrice'] - $fields['Price'],
$product_row = this.getRowByIndex($row_index),
$discount_container = $('.product-discount', $product_row);
// update product title
var $product_with_link = $('.product-with-link', $product_row);
$('a:first', $product_with_link)
.attr('href', $data.items[$row_index].product_url)
.html($fields['ProductName']);
$product_with_link.toggle( $fields['Virtual'] == 0 );
$('.product-without-link', $product_row)
.toggle( $fields['Virtual'] == 1 )
.html($fields['ProductName']);
$('.free-shipping', $product_row).toggle( $data.items[$row_index].free_promo_shipping );
$('.back-order-mark', $product_row).toggle( $fields['BackOrderFlag'] > 0 );
$('.product-availability', $product_row)
.toggle( $fields['cust_Availability'] != '' )
.html('<br/>' + $fields['cust_Availability']);
$('.product-qty.read-only', $product_row).toggle( $fields['Type'] != this.constants['PRODUCT_TYPE_TANGIBLE'] );
$('.product-qty:not(.read-only)', $product_row).toggle( $fields['Type'] == this.constants['PRODUCT_TYPE_TANGIBLE'] );
// update product specific discount
$('.item-price', $discount_container).html( this.formatPrice($fields['FlatPrice']) );
$('.item-discount', $discount_container).html( '- ' + this.formatPrice($discount) );
$discount_container.toggle( $discount > 0 );
// update product prices
$('.price-cell', $product_row).html( this.formatPrice($fields['Price']) );
$('.extended-price-cell', $product_row).html( this.formatPrice($fields['Quantity'] * $fields['Price']) );
$row_count++;
}
$('#item-count').html($row_count);
}
ShopCartManager.prototype.showErrors = function ($data) {
var $error_code = 0, $error_info = [],
$row_index = '', $field = '',
$tooltip_options = '',
$coupon_error_code = this.getErrorByType('OrderCheckoutErrorType::COUPON', $data),
$gift_certificate_error_code = this.getErrorByType('OrderCheckoutErrorType::GIFT_CERTIFICATE', $data),
$discount_error_code = this.getErrorByType('OrderCheckoutErrorType::DISCOUNT', $data);
if ( $.isArray($data.errors) ) {
// when no error, then it's array
return ;
}
if ( $coupon_error_code ) {
if ( $coupon_error_code == this.constants['OrderCheckoutError::COUPON_APPLIED'] ) {
var $input = $('.coupon-name', '#coupon-row');
}
else {
var $input = $('.coupon-code:input', '#coupon-row');
}
$tooltip_options = this.getCouponErrorOptions($coupon_error_code);
if ( $tooltip_options ) {
this.createTooltip($input, $tooltip_options);
}
}
if ( $gift_certificate_error_code ) {
if ( $gift_certificate_error_code == this.constants['OrderCheckoutError::GC_APPLIED'] ) {
var $input = $('.gift-certificate-discount', '#gift-certificate-row');
}
else {
var $input = $('.gift-certificate-code:input', '#gift-certificate-row');
}
$tooltip_options = this.getGiftCertificateErrorOptions($gift_certificate_error_code);
if ( $tooltip_options ) {
this.createTooltip($input, $tooltip_options);
}
}
if ( $discount_error_code ) {
$input = $('#sub-total');
$tooltip_options = this.getDiscountErrorOptions($discount_error_code);
if ( $tooltip_options ) {
this.createTooltip($input, $tooltip_options);
}
}
for (var $error_type in $data.errors) {
$tooltip_options = '';
$error_info = $error_type.split(':');
$error_code = parseInt( $data.errors[$error_type] );
if ( $error_info[0] == this.constants['OrderCheckoutErrorType::PRODUCT'] ) {
this.processProductError($error_info, $error_code, $data);
}
if ( this.debugMode ) {
console.log('error_type: ', $error_type, '; error_code: ', $error_code, '; row_index: ', $row_index, '; field: ', $field);
}
}
}
ShopCartManager.prototype.showFooter = function ($data) {
var $discount_total = $data.order['DiscountTotal'];
// update "Total Savings"
$('#discount-row').toggle( $discount_total > 0 );
- $('.price1', '#discount-row').html( this.formatPrice($discount_total) );
+ $('.price2', '#discount-row').html( this.formatPrice($discount_total) );
// update Coupon Info
if ( $data.order['CouponId'] == 0 ) {
$('.coupon-code', '#coupon-row').val('');
}
$('.used', '#coupon-row').toggle( $data.order['CouponId'] > 0 );
$('.not-used', '#coupon-row').toggle( $data.order['CouponId'] == 0 );
$('.coupon-name', '#coupon-row').html( $data.order['CouponName'] );
// update Gift Certificate Info
if ( $data.order['GiftCertificateId'] == 0 ) {
$('.gift-certificate-code', '#gift-certificate-row').val('');
}
$('.used', '#gift-certificate-row').toggle( $data.order['GiftCertificateId'] > 0 );
$('.not-used', '#gift-certificate-row').toggle( $data.order['GiftCertificateId'] == 0 );
$('.gift-certificate-discount', '#gift-certificate-row').html( this.formatPrice($data.order['GiftCertificateDiscount']) );
// update "subtotal"
$('#sub-total').html( this.formatPrice($data.order['SubTotal']) );
+
+ // update page header
+ $('#header-items-in-cart').html( $data.order['ItemsInCart'] );
+ $('#header-cart-subtotal').html( this.formatPrice($data.order['SubTotal'], 'i') );
}
ShopCartManager.prototype.processProductError = function ($error_info, $error_code, $data) {
var $error_type = $error_info.shift(),
$field = $error_info.pop(),
$row_index = $error_info.join(':');
if ( this.getRowByIndex($row_index).length == 0 ) {
// row was deleted
return ;
}
if ( $field == 'Quantity' ) {
var $input = $('.product-qty:input', this.getRowByIndex($row_index)),
$allow_qty_replace = [
this.constants['OrderCheckoutError::FIELD_UPDATE_SUCCESS'],
this.constants['OrderCheckoutError::QTY_CHANGED_TO_MINIMAL']
];
if ( in_array($error_code, $allow_qty_replace) && $input.val() != $data.items[$row_index]['fields']['Quantity'] ) {
// qty changed during ord:OnRecalculateItems
$input.val( $data.items[$row_index]['fields']['Quantity'] );
}
$tooltip_options = this.getQtyErrorOptions($error_code);
if ( $tooltip_options ) {
this.createTooltip($input, $tooltip_options);
}
}
}
ShopCartManager.prototype.getErrorByType = function ($contant_name, $data) {
var $error_type = this.constants[$contant_name];
return $data.errors[$error_type] !== undefined ? $data.errors[$error_type] : false;
}
ShopCartManager.prototype.getRowByIndex = function ($row_index) {
return $("tr.shop-cart-row[row_index='" + $row_index + "']", '#shop-cart-table');
}
ShopCartManager.prototype.getOldRows = function () {
var $ret = [];
$('tr.shop-cart-row', '#shop-cart-table').each(
function () {
$ret.push( $(this).attr('row_index') );
}
);
return $ret;
}
ShopCartManager.prototype.getNewRows = function ($data) {
var $ret = [];
if ( $.isArray($data.items) ) {
return $data.items;
}
for (var $row_index in $data.items) {
$ret.push( $row_index );
}
return $ret;
}
-ShopCartManager.prototype.formatPrice = function ($price) {
- // TODO: format currency
+ShopCartManager.prototype.formatPrice = function ($price, $decimal_tag) {
+ if ( $decimal_tag === undefined ) {
+ $decimal_tag = 'span';
+ }
var $price_parts = $price.toFixed(2).toString().split('.');
- return this.currencyMask.replace('%s', $price_parts[0] + '.<span>' + $price_parts[1] + '</span>');
+ return this.currencyMask.replace('%s', $price_parts[0] + '.<' + $decimal_tag + '>' + $price_parts[1] + '</' + $decimal_tag + '>');
}
ShopCartManager.prototype.getQtyErrorOptions = function ($error_code) {
var $ret = false;
switch ($error_code) {
case this.constants['OrderCheckoutError::FIELD_UPDATE_SUCCESS']:
$ret = this.getTooltipOptions('FIELD_UPDATE_SUCCESS', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::FIELD_UPDATE_ERROR']:
$ret = this.getTooltipOptions('FIELD_UPDATE_ERROR', 'ui-tooltip-red');
break;
case this.constants['OrderCheckoutError::QTY_UNAVAILABLE']:
$ret = this.getTooltipOptions('QTY_UNAVAILABLE', 'ui-tooltip-red');
break;
case this.constants['OrderCheckoutError::QTY_OUT_OF_STOCK']:
$ret = this.getTooltipOptions('QTY_OUT_OF_STOCK', 'ui-tooltip-red');
break;
case this.constants['OrderCheckoutError::QTY_CHANGED_TO_MINIMAL']:
$ret = this.getTooltipOptions('QTY_CHANGED_TO_MINIMAL', 'ui-tooltip-green');
break;
}
return $ret;
}
ShopCartManager.prototype.getCouponErrorOptions = function ($error_code) {
var $ret = false;
switch ($error_code) {
case this.constants['OrderCheckoutError::COUPON_APPLIED']: // for label
$ret = this.getTooltipOptions('COUPON_APPLIED', 'ui-tooltip-green');
break;
// all next error for input
case this.constants['OrderCheckoutError::COUPON_REMOVED']:
$ret = this.getTooltipOptions('COUPON_REMOVED', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::COUPON_REMOVED_AUTOMATICALLY']:
$ret = this.getTooltipOptions('COUPON_REMOVED_AUTOMATICALLY', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::COUPON_CODE_INVALID']:
$ret = this.getTooltipOptions('COUPON_CODE_INVALID', 'ui-tooltip-red');
break;
case this.constants['OrderCheckoutError::COUPON_CODE_EXPIRED']:
$ret = this.getTooltipOptions('COUPON_CODE_EXPIRED', 'ui-tooltip-red');
break;
}
return $ret;
}
ShopCartManager.prototype.getGiftCertificateErrorOptions = function ($error_code) {
var $ret = false;
switch ($error_code) {
case this.constants['OrderCheckoutError::GC_APPLIED']: // for label
$ret = this.getTooltipOptions('GC_APPLIED', 'ui-tooltip-green');
break;
// all next error for input
case this.constants['OrderCheckoutError::GC_REMOVED']:
$ret = this.getTooltipOptions('GC_REMOVED', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::GC_REMOVED_AUTOMATICALLY']:
$ret = this.getTooltipOptions('GC_REMOVED_AUTOMATICALLY', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::GC_CODE_INVALID']:
$ret = this.getTooltipOptions('GC_CODE_INVALID', 'ui-tooltip-red');
break;
case this.constants['OrderCheckoutError::GC_CODE_EXPIRED']:
$ret = this.getTooltipOptions('GC_CODE_EXPIRED', 'ui-tooltip-red');
break;
}
return $ret;
}
ShopCartManager.prototype.getDiscountErrorOptions = function ($error_code) {
var $ret = false;
switch ($error_code) {
case this.constants['OrderCheckoutError::DISCOUNT_APPLIED']:
$ret = this.getTooltipOptions('DISCOUNT_APPLIED', 'ui-tooltip-green');
break;
case this.constants['OrderCheckoutError::DISCOUNT_REMOVED']:
$ret = this.getTooltipOptions('DISCOUNT_REMOVED', 'ui-tooltip-green');
break;
}
return $ret;
}
ShopCartManager.prototype.createTooltip = function ($input, $tooltip_options) {
var $me = this,
$tooltip = $input.next('.formStatus'),
$is_error = $tooltip_options.classes == 'ui-tooltip-red',
$timer = $input.data('timer');
clearTimeout($timer);
if ( $tooltip.length == 1 ) {
$tooltip.hide().remove();
}
$tooltip = $('<div class="formStatus ' + ($is_error ? 'formError' : 'formSuccess') + '" style="display: none;">\
<div class="formContent">' + $tooltip_options.text + '</div>\
<div class="formArrow"></div>\
</div>');
$input
.after($tooltip)
.removeClass('statusSuccess statusError')
.addClass($is_error ? 'statusError' : 'statusSuccess');
$tooltip.fadeIn(
'slow',
function () {
$timer = setTimeout( function() { $me.removeTooltip($input); }, 2000);
$input.data('timer', $timer);
}
);
$input.focus( function() { $me.removeTooltip($input); } );
}
ShopCartManager.prototype.removeTooltip = function ($input) {
var $tooltip = $input.next('.formStatus');
$input.removeClass('statusError').removeClass('statusSuccess');
$tooltip.fadeOut('slow', function() { $tooltip.remove(); });
}
ShopCartManager.prototype.getTooltipOptions = function ($text, $css_classes) {
return {
text: $text,
classes: $css_classes
};
}
Index: branches/1.0.x/elements/ajax/cart_bubble.tpl
===================================================================
--- branches/1.0.x/elements/ajax/cart_bubble.tpl (revision 14831)
+++ branches/1.0.x/elements/ajax/cart_bubble.tpl (revision 14832)
@@ -1,19 +1,20 @@
<inp2:m_NoDebug/>
<p class="subtitle">Added to cart:</p>
<div class="img">
<!--width="58" height="58"-->
<img src="<inp2:p_ImageSrc primary='1' MaxWidth='58' DefaultWidth='58' DefaultImage='img/no_picture.gif'/>" alt="" />
</div>
<div class="info good-item">
<p>#QTY# x <inp2:p_Field name="Name"/></p>
<p class="price"><inp2:p_Field name="Price" currency="selected" decimal_tag="span"/></p>
</div>
<div class="clear"></div>
<script type="text/javascript">
$(document).ready(
function () {
- $('.cart .items').html('<inp2:ord_ItemsInCart/> Items: <inp2:ord_Field name="TotalAmount" currency="selected" decimal_tag="i"/>');
+ $('#header-items-in-cart').html('<inp2:ord_ItemsInCart/>');
+ $('#header-cart-subtotal').html('<inp2:ord_Field name="SubTotal" currency="selected" decimal_tag="i"/>');
}
)
</script>
\ No newline at end of file
Index: branches/1.0.x/elements/header.elm.tpl
===================================================================
--- branches/1.0.x/elements/header.elm.tpl (revision 14831)
+++ branches/1.0.x/elements/header.elm.tpl (revision 14832)
@@ -1,86 +1,86 @@
<inp2:m_if check="m_Get" name="ajax" equals_to="yes">
<inp2:m_NoDebug/>
<inp2:m_Set skip_last_template="1"/>
<inp2:m_else/>
<div id="header">
</inp2:m_if>
<div class="logo">
<a href="<inp2:m_Link template='index' m_cat_id='0' />"><img src="<inp2:m_TemplatesBase/>img/logo.jpg" width="238" height="79" alt="<inp2:m_GetConfig name='Site_Name'/>" /></a>
<inp2:st_ContentBlock num="100" page="index"/>
</div>
<div class="infoblock">
<div class="welcome">
<div class="lang">
<div <inp2:m_if check="lang.current_Field" name="IconURL">class="with-icon" style="background-image: url(<inp2:m_TemplatesBase/>img/lang/<inp2:lang.current_Field name='IconURL'/>);"<inp2:m_else/>class="without-icon"</inp2:m_if>>
<a href="<inp2:lang.current_LanguageLink/>"" id="lang"><inp2:lang.current_Field name='LocalName'/></a>
</div>
<div id="lang-sel" class="plashka">
<ul>
<inp2:m_DefineElement name="lang_elem" no_editing="1">
<li>
<inp2:m_if check="Field" name="IconURL">
<a href="<inp2:LanguageLink/>" style="background-image: url(<inp2:m_TemplatesBase/>img/lang/<inp2:Field name='IconURL'/>);" class="with-icon<inp2:m_if check='SelectedLanguage'> active</inp2:m_if>">
<inp2:Field name="LocalName"/>
</a>
<inp2:m_else/>
<a href="<inp2:LanguageLink/>" class="without-icon<inp2:m_if check='SelectedLanguage'> active</inp2:m_if>">
<inp2:Field name="LocalName"/>
</a>
</inp2:m_if>
</li>
</inp2:m_DefineElement>
<inp2:lang_ListLanguages render_as="lang_elem" no_table="1"/>
</ul>
</div>
</div>
<div class="currency">
<div class="cur">
<a href="<inp2:curr.current_CurrencyLink/>" id="currency"><inp2:curr.current_Field name="ISO"/></a>
</div>
<div id="currency-sel" class="plashka">
<ul>
<inp2:m_DefineElement name="currency_elem">
<li>
<a href="<inp2:CurrencyLink/>"<inp2:m_if check='SelectedCurrency'> class="active"</inp2:m_if>>
<inp2:Field name="ISO"/>
</a>
</li>
</inp2:m_DefineElement>
<inp2:curr_ListCurrencies render_as="currency_elem" no_table="1"/>
</ul>
</div>
</div>
<inp2:m_include template="elements/login.elm"/>
</div>
<div class="cart">
<span class="phone">1-855-WWW-PROS</span>
- <span class="items"><inp2:ord_ItemsInCart/> Items: <inp2:ord_Field name="SubtotalWithDiscount" currency="selected" decimal_tag="i"/></span>
+ <span class="items"><em id="header-items-in-cart"><inp2:ord_ItemsInCart/></em> Items: <em id="header-cart-subtotal"><inp2:ord_Field name="SubTotal" currency="selected" decimal_tag="i"/></em></span>
<span class="delim">|</span>
<a href="<inp2:m_Link template='cart' m_cat_id='0' m_cat_page='1'/>">Checkout</a>
</div>
<!-- Show recently added Product by loading content with Ajax -->
<div class="basketStatus" style="display: none;">
<div class="basketArrow"></div>
<div class="basketContent"></div>
</div>
<!-- end -->
</div>
<div class="clear"></div>
<inp2:m_ifnot check="m_Get" name="ajax" equals_to="yes">
</div>
</inp2:m_ifnot>
<script type="text/javascript">
new DBlocks();
</script>
\ No newline at end of file

Event Timeline