Commit f2de59354a21fe42ee89921d5de4960d8800bdcf

Authored by Rodrigo Souto
1 parent 77496dba

JS, CSS and HTML.

Don't panic!  =D
plugins/shopping_cart/public/cart.js 0 → 100644
... ... @@ -0,0 +1,246 @@
  1 +function Cart(config) {
  2 + var $ = jQuery;
  3 + Cart.instance = this; // this may be a list on the future;
  4 + this.cartElem = $("#cart1")[0];
  5 + this.cartElem.cartObj = this;
  6 + this.contentBox = $("#cart1 .cart-content");
  7 + this.itemsBox = $("#cart1 .cart-items");
  8 + this.items = {};
  9 + this.visible = false;
  10 + if (config.hasProducts) {
  11 + $(this.cartElem).show();
  12 + this.enterprise = config.enterprise;
  13 + this.listProducts();
  14 + }
  15 + $(".cart-buy", this.cartElem).button({ icons: { primary: 'ui-icon-cart'} });
  16 +}
  17 +
  18 +(function($){
  19 +
  20 + Cart.prototype.listProducts = function() {
  21 + var me = this;
  22 + $.ajax({
  23 + url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/list',
  24 + dataType: 'json',
  25 + success: function(data, ststus, ajax){
  26 + if ( !data.ok ) alert(data.error.message);
  27 + else me.addToList(data, true);
  28 + },
  29 + cache: false,
  30 + error: function(ajax, status, errorThrown) {
  31 + alert('List cart items - HTTP '+status+': '+errorThrown);
  32 + }
  33 + });
  34 + }
  35 +
  36 + Cart.prototype.addToList = function(data, clear) {
  37 + if( clear ) this.itemsBox.empty();
  38 + var me = this;
  39 + for( var item,i=0; item=data.products[i]; i++ ) {
  40 + this.items[item.id] = { price:item.price, quantity:item.quantity };
  41 + this.updateTotal();
  42 + var liId = "cart-item-"+item.id;
  43 + var li = $("#"+liId);
  44 + if( !li[0] ) li = $('<li id="'+liId+'"></li>\n').appendTo(this.itemsBox);
  45 + li.empty();
  46 + $('<div class="picture" style="background-image:url('+item.picture+')"></div>' +
  47 + '<span class="item-name">'+ item.name +'</span>' +
  48 + '<div class="item-price">' +
  49 + '<input size="1" value="'+item.quantity+'" />'+ (item.price ? '&times; '+ item.price : '') +'</div>' +
  50 + ' <a href="remove:'+item.name+'" onclick="Cart.removeItem(\''+this.enterprise+'\', '+item.id+'); return false"' +
  51 + ' class="button icon-delete"><span>remove</span></a>'
  52 + ).appendTo(li);
  53 + var input = $("input", li)[0];
  54 + input.lastValue = input.value;
  55 + input.itemId = item.id;
  56 + input.ajustSize = function() {
  57 + var len = this.value.toString().length;
  58 + if(len > 2) len--;
  59 + this.style.width = len+"em";
  60 + };
  61 + input.ajustSize();
  62 + input.onchange = function() {
  63 + me.updateQuantity(this, this.itemId, this.value);
  64 + };
  65 + document.location.href = "#"+liId;
  66 + document.location.href = "#"+this.cartElem.id;
  67 + history.go(-2);
  68 + var liBg = li.css("background-color");
  69 + li[0].style.backgroundColor = "#FF0";
  70 + li.animate({ backgroundColor: liBg }, 1000);
  71 + }
  72 + if( !this.visible ) {
  73 + this.contentBox.hide();
  74 + this.show();
  75 + }
  76 + }
  77 +
  78 + Cart.prototype.updateQuantity = function(input, itemId, quantity) {
  79 + quantity = parseInt(quantity);
  80 + input.disabled = true;
  81 + var originalBg = input.style.backgroundImage;
  82 + input.style.backgroundImage = "url(/images/loading-small.gif)";
  83 + var me = this;
  84 + if( quantity == NaN ) return input.value = input.lastValue;
  85 + $.ajax({
  86 + url: '/profile/'+ this.enterprise +'/plugins/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity,
  87 + dataType: 'json',
  88 + success: function(data, status, ajax){
  89 + if ( !data.ok ) {
  90 + alert(data.error.message);
  91 + input.value = input.lastValue;
  92 + }
  93 + else {
  94 + input.lastValue = quantity;
  95 + me.items[itemId].quantity = quantity;
  96 + me.updateTotal();
  97 + }
  98 + },
  99 + cache: false,
  100 + error: function(ajax, status, errorThrown) {
  101 + alert('Add item - HTTP '+status+': '+errorThrown);
  102 + input.value = input.lastValue;
  103 + },
  104 + complete: function(){
  105 + input.disabled = false;
  106 + input.style.backgroundImage = originalBg;
  107 + input.ajustSize();
  108 + }
  109 + });
  110 + }
  111 +
  112 + Cart.prototype.removeFromList = function(itemId) {
  113 + $("#cart-item-"+itemId).slideUp(500, function() {$(this).remove()});
  114 + delete this.items[itemId];
  115 + this.updateTotal();
  116 + }
  117 +
  118 + Cart.addItem = function(enterprise, itemId, link) {
  119 + // on the future, the instance may be found by the enterprise identifier.
  120 + link.intervalId = setInterval(function() {
  121 + steps = ['w', 'n', 'e', 's'];
  122 + if( !link.step || link.step==3 ) link.step = 0;
  123 + link.step++;
  124 + $(link).button({ icons: { primary: 'ui-icon-arrowrefresh-1-'+steps[link.step]}, disable: true })
  125 + }, 100);
  126 + var stopBtLoading = function() {
  127 + clearInterval(link.intervalId);
  128 + $(link).button({ icons: { primary: 'ui-icon-cart'}, disable: false });
  129 + };
  130 + this.instance.addItem(enterprise, itemId, stopBtLoading);
  131 + }
  132 +
  133 + Cart.prototype.addItem = function(enterprise, itemId, callback) {
  134 + if(!this.enterprise) {
  135 + this.enterprise = enterprise;
  136 + if( !this.visible ) $(this.cartElem).show();
  137 + }
  138 + var me = this;
  139 + $.ajax({
  140 + url: '/profile/'+ enterprise +'/plugins/shopping_cart/add/'+ itemId,
  141 + dataType: 'json',
  142 + success: function(data, status, ajax){
  143 + if ( !data.ok ) alert(data.error.message);
  144 + else me.addToList(data);
  145 + },
  146 + cache: false,
  147 + error: function(ajax, status, errorThrown) {
  148 + alert('Add item - HTTP '+status+': '+errorThrown);
  149 + },
  150 + complete: callback
  151 + });
  152 + }
  153 +
  154 + Cart.removeItem = function(enterprise, itemId) {
  155 + var message = this.instance.cartElem.getAttribute('data-l10nRemoveItem');
  156 + if( confirm(message) ) this.instance.removeItem(enterprise, itemId);
  157 + }
  158 +
  159 + Cart.prototype.removeItem = function(enterprise, itemId) {
  160 + if ($("li", this.itemsBox).size() < 2) return this.clean();
  161 + var me = this;
  162 + $.ajax({
  163 + url: '/profile/'+ enterprise +'/plugins/shopping_cart/remove/'+ itemId,
  164 + dataType: 'json',
  165 + success: function(data, status, ajax){
  166 + if ( !data.ok ) alert(data.error.message);
  167 + else me.removeFromList(data.product_id);
  168 + },
  169 + cache: false,
  170 + error: function(ajax, status, errorThrown) {
  171 + alert('Remove item - HTTP '+status+': '+errorThrown);
  172 + }
  173 + });
  174 + }
  175 +
  176 + Cart.toggle = function(link) {
  177 + link.parentNode.parentNode.cartObj.toggle();
  178 + }
  179 + Cart.prototype.toggle = function() {
  180 + this.visible ? this.hide() : this.show();
  181 + }
  182 +
  183 + Cart.prototype.show = function() {
  184 + this.visible = true;
  185 + this.contentBox.slideDown(500);
  186 + $(".cart-toggle .str-show", this.cartElem).hide();
  187 + $(".cart-toggle .str-hide", this.cartElem).show();
  188 +
  189 + }
  190 + Cart.prototype.hide = function() {
  191 + this.visible = false;
  192 + this.contentBox.slideUp(500);
  193 + $(".cart-toggle .str-show", this.cartElem).show();
  194 + $(".cart-toggle .str-hide", this.cartElem).hide();
  195 + }
  196 +
  197 + Cart.prototype.updateTotal = function() {
  198 + var total = 0;
  199 + var currency, sep = "";
  200 + for( var itemId in this.items ) {
  201 + var item = this.items[itemId];
  202 + if( item.price ) {
  203 + currency = item.price.replace(/^([^0-9]+).*$/, "$1");
  204 + sep = item.price.charAt(item.price.length-3);
  205 + var price = item.price.replace(/[^0-9]/g,"");
  206 + total += item.quantity * parseFloat(price);
  207 + }
  208 + }
  209 + total = Math.round(total).toString().replace(/(..)$/, sep+"$1")
  210 + $(".cart-total b", this.cartElem).text( ( (total!=0) ? currency+" "+total : "---" ) );
  211 + }
  212 +
  213 + Cart.clean = function(link) {
  214 + var message = this.instance.cartElem.getAttribute('data-l10nCleanCart');
  215 + if( confirm(message) ) link.parentNode.parentNode.parentNode.cartObj.clean();
  216 + }
  217 +
  218 + Cart.prototype.clean = function() {
  219 + var me = this;
  220 + $.ajax({
  221 + url: '/profile/'+ me.enterprise +'/plugins/shopping_cart/clean',
  222 + dataType: 'json',
  223 + success: function(data, status, ajax){
  224 + if ( !data.ok ) alert(data.error.message);
  225 + else{
  226 + me.items = {};
  227 + $(me.cartElem).slideUp(500, function() {
  228 + $(me.itemsBox).empty();
  229 + me.hide();
  230 + me.enterprise = null;
  231 + me.updateTotal();
  232 + });
  233 + }
  234 + },
  235 + cache: false,
  236 + error: function(ajax, status, errorThrown) {
  237 + alert('Remove item - HTTP '+status+': '+errorThrown);
  238 + }
  239 + });
  240 + }
  241 +
  242 + $(function(){
  243 + $('.cart-add-item').button({ icons: { primary: 'ui-icon-cart'} })
  244 + });
  245 +
  246 +})(jQuery);
... ...
plugins/shopping_cart/public/style.css 0 → 100644
... ... @@ -0,0 +1,106 @@
  1 +.cart-add-item {
  2 + position: absolute;
  3 + right: 5px;
  4 + top: 5px;
  5 +}
  6 +
  7 +.cart {
  8 + position: absolute;
  9 + right: 20px;
  10 + top: 0px;
  11 + width: 200px;
  12 + z-index: 1000;
  13 + border: 1px solid #777;
  14 + border-top: none;
  15 + background: rgba(200,200,200,0.6);
  16 +}
  17 +
  18 +.cart h3 {
  19 + color: #888;
  20 + margin: 0px 0px 0px 5px;
  21 +}
  22 +
  23 +.cart-clean {
  24 + color: #AAA;
  25 + position: absolute;
  26 + top: 1px;
  27 + right: 5px;
  28 + text-decoration: none;
  29 +}
  30 +.cart-clean:hover {
  31 + color: #888;
  32 +}
  33 +
  34 +.cart-content {
  35 + display: none;
  36 +}
  37 +
  38 +.cart-items {
  39 + margin: 0px;
  40 + padding: 0px;
  41 + max-height: 328px;
  42 + overflow: auto;
  43 +}
  44 +
  45 +.cart-items li {
  46 + height: 50px;
  47 + padding: 5px;
  48 + margin: 3px;
  49 + border: 1px solid #999;
  50 + list-style: none;
  51 + background: #FFF;
  52 + position: relative;
  53 +}
  54 +
  55 +.cart-items .picture {
  56 + float: left;
  57 + width: 50px;
  58 + height: 50px;
  59 + margin-right: 10px;
  60 + background-repeat: no-repeat;
  61 + background-position: 50% 50%;
  62 +}
  63 +
  64 +.cart .item-name {
  65 + margin-right: 20px;
  66 +}
  67 +
  68 +.cart .button {
  69 + position: absolute;
  70 + top: 2px;
  71 + right: 2px;
  72 +}
  73 +
  74 +.cart input {
  75 + border: 1px solid transparent;
  76 + background: transparent 50% 50% no-repeat;
  77 + text-align: center;
  78 + padding: 0px;
  79 + font-family: monospace;
  80 + width: 2em;
  81 +}
  82 +.cart:hover input, .cart input:focus {
  83 + border: 1px solid #CCC;
  84 +}
  85 +
  86 +.cart-buy {
  87 + display: block;
  88 + margin: 2px 4px;
  89 +}
  90 +
  91 +.cart-total {
  92 + position: absolute;
  93 + left: 5px;
  94 + bottom: 0px;
  95 +}
  96 +
  97 +.cart-toggle {
  98 + display: block;
  99 + color: #AAA;
  100 + text-decoration: none;
  101 + float: right;
  102 + padding: 0px 5px;
  103 +}
  104 +.cart-toggle:hover {
  105 + color: #555;
  106 +}
... ...
plugins/shopping_cart/views/cart.html.erb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<div id="cart1" class="cart" style="display:none"
  2 + data-l10nRemoveItem="<%=_('Are you sure you want to remove this item?')%>"
  3 + data-l10nCleanCart="<%=_('Are you sure you want to clean your cart?')%>">
  4 + <div class="cart-inner">
  5 + <div class="cart-content">
  6 + <h3><%= _("Cart") %></h3>
  7 + <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean cart')%></a>
  8 + <ul class="cart-items"></ul>
  9 + <div class="cart-total"><%=_('Total:')%> <b></b></div>
  10 + <a href="cart:buy" class="cart-buy" onclick="alert('foi mô pai!'); return false"><%=_('Shopping checkout')%></a>
  11 + </div>
  12 + <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle">
  13 + <span class="str-show"><%=_('Show cart')%></span>
  14 + <span class="str-hide" style="display:none"><%=_('Hide cart')%></span>
  15 + </a>
  16 + </div>
  17 +</div>
  18 +
  19 +<script type="text/javascript">
  20 + new Cart({hasProducts:<%= !locals[:cart].nil? ? "true, enterprise:'#{Enterprise.find(locals[:cart][:enterprise_id]).identifier}'" : "false" %>});
  21 +</script>
... ...