Index: branches/1.0.x/checkout/cart.tpl =================================================================== diff -u -N -r14792 -r14798 --- branches/1.0.x/checkout/cart.tpl (.../cart.tpl) (revision 14792) +++ branches/1.0.x/checkout/cart.tpl (.../cart.tpl) (revision 14798) @@ -6,6 +6,10 @@ Shopping Cart + + + + @@ -17,165 +21,273 @@
-
-

Shopping Cart

- -
+
+
+ - - - - - - - - - - - - - - - + + + + + + + +
Items in your order (4)Qty.PriceTotal
Nikon D5000 Kit 15-18 Digital Camera -
- -
-
- Quantity Updated -
-
-
-
+ +

Shopping Cart

+ + +
+ + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - -
Items in your order ()Qty.PriceTotal
rowspan="2"> + $75.00$75.00
-
- +
+
+ [ProductId: ; OptionsSalt: ; BackOrderFlag: ]
-
- + + + + +   + + + + + + + + + + +
+ +
+ +
style="display: none;"> + :
+ :
Nikon D5000 Kit 15-18 Digital Camera
- -
-
- Invalid Quantity -
-
-
+ + + + +
$75.00$75.00
Nikon D5000 Kit 15-18 Digital Camera -
- -
+ +
+ $75.00$75.00
Nikon D5000 Kit 15-18 Digital Camera + + -
- -
+ Delete
$75.00$75.00
-
- -

Discounts & Promotional Offers

-

If you have a discount or promotional offer code please enter it and click Apply button.

-
- -
-
- Promotion Code Applied + +
+
+ +
+
+ +
+
+ +
+

Discounts & Promotional Offers

+ +
+
style="display: none;"> + :  + +
+    + <inp2:m_Phrase label='lu_comm_RemoveCoupon' no_editing='1'/> +
-
+ +
style="display: none;"> +

If you have a discount or promotional offer code please enter it and click Apply button.

+
+ + +
+
+ +
+
style="display: none;"> + :  + + +
+ +
style="display: none;"> +

If you have a gift certificate code please enter it and click Apply button.

+
+ + +
+
+
- -
-
-
-
Discount:
-
- $10.00
-
Total
-
$1,959.99
-
-

(before shipping & taxes)

- Checkout +
+
+
style="display: none;"> +
Discount:
+
-
+
+ +
+
Total
+
+
+
+

(before shipping & taxes)

+ Checkout +
+
+ + + + + +

Shopping Cart

+
+ + +
+ +
-
- -
+ -
- + + Index: branches/1.0.x/elements/content_boxes.elm.tpl =================================================================== diff -u -N -r14794 -r14798 --- branches/1.0.x/elements/content_boxes.elm.tpl (.../content_boxes.elm.tpl) (revision 14794) +++ branches/1.0.x/elements/content_boxes.elm.tpl (.../content_boxes.elm.tpl) (revision 14798) @@ -23,7 +23,7 @@ - " title="" alt="" /> + <inp2:m_param name='alt' /> /> Index: branches/1.0.x/inc/cart.css =================================================================== diff -u -N -r14759 -r14798 --- branches/1.0.x/inc/cart.css (.../cart.css) (revision 14759) +++ branches/1.0.x/inc/cart.css (.../cart.css) (revision 14798) @@ -231,6 +231,11 @@ dl.total dd.price3 { font-weight: normal; } dl.total dd.price4 { color: #3f911f; font-size: 1.538em; } +.product-discount .item-price span, .product-discount .item-discount span, +.shop-cart-row .price-cell span, .shop-cart-row .extended-price-cell span { + font-size: 12px; +} + .cart-detail .terms { text-align: right; width: 240px; Index: branches/1.0.x/inc/profile.css =================================================================== diff -u -N -r14770 -r14798 --- branches/1.0.x/inc/profile.css (.../profile.css) (revision 14770) +++ branches/1.0.x/inc/profile.css (.../profile.css) (revision 14798) @@ -81,7 +81,7 @@ .profile-form .alt2 .field { width: 150px; } .field.statusSuccess { background: url(@templates_base@/img/bg-field-success.jpg) repeat-x 0 0; - border: 1px solid #80d04d; + border: 1px solid #80d04d !important; } .field.statusError, .error .field { background: url(@templates_base@/img/bg-field-error.jpg) repeat-x 0 0; Index: branches/1.0.x/inc/js/jquery.scripts.js =================================================================== diff -u -N -r14793 -r14798 --- branches/1.0.x/inc/js/jquery.scripts.js (.../jquery.scripts.js) (revision 14793) +++ branches/1.0.x/inc/js/jquery.scripts.js (.../jquery.scripts.js) (revision 14798) @@ -1,7 +1,51 @@ +/* === General usage functions === */ function jq($selector) { return $selector.replace(/(\[|\]|\.)/g, '\\$1'); } +function in_array(needle, haystack) +{ + return array_search(needle, haystack) != -1; +} + +function array_search(needle, haystack) +{ + for (var i=0; i 0) { + $tmp += '|'; + } + + document.getElementById($hidden_id).value = $tmp.replace(/,$/, ''); +} + +/* === DBlocks class === */ function DBlocks() { var $me = this; this.selectors = ['#lang', '#currency', '#login', '#login-alt', '#profile']; @@ -65,6 +109,7 @@ ); } +/* === RatingManager class === */ function RatingManager ($url) { this.Url = $url; } @@ -121,11 +166,16 @@ $me.attr('href') + '&qty=' + $qty, function ($bubble_content) { $('.basketContent', $bubble).html( $bubble_content.replace(/#QTY#/g, $qty) ); - $bubble.stop(true, true).fadeIn(); + $bubble + .stop(true, true) + .fadeIn( + 'slow', + function () { + var $timer = setTimeout(function(){ $bubble.fadeOut('slow'); }, 2000); + $bubble.data('hide_timer', $timer); + } + ); - var $timer = setTimeout(function(){ $bubble.fadeOut('slow'); }, 2000); - $bubble.data('hide_timer', $timer); - if ( $me.hasClass('addtocart') ) { $me.removeClass('addtocart').addClass('addedtocart').html('Added to Cart'); } Index: branches/1.0.x/elements/ajax/cart_bubble.tpl =================================================================== diff -u -N -r14793 -r14798 --- branches/1.0.x/elements/ajax/cart_bubble.tpl (.../cart_bubble.tpl) (revision 14793) +++ branches/1.0.x/elements/ajax/cart_bubble.tpl (.../cart_bubble.tpl) (revision 14798) @@ -2,7 +2,7 @@

Added to cart:

- +

#QTY# x

Index: branches/1.0.x/inc/js/cart_manager.js =================================================================== diff -u -N --- branches/1.0.x/inc/js/cart_manager.js (revision 0) +++ branches/1.0.x/inc/js/cart_manager.js (revision 14798) @@ -0,0 +1,597 @@ +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('
' + $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) ); + + // 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']) ); +} + +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 + + var $price_parts = $price.toFixed(2).toString().split('.'); + + return this.currencyMask.replace('%s', $price_parts[0] + '.' + $price_parts[1] + ''); +} + +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 = $(''); + + $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 + }; +}