
/*
Formats the number according to the ‘format’ string;
adherses to the american number standard where a comma
is inserted after every 3 digits.
 note: there should be only 1 contiguous number in the format,
where a number consists of digits, period, and commas
       any other characters can be wrapped around this number, including ‘$’, ‘%’, or text
       examples (123456.789):
         ‘0′ - (123456) show only digits, no precision
         ‘0.00′ - (123456.78) show only digits, 2 precision
         ‘0.0000′ - (123456.7890) show only digits, 4 precision
         ‘0,000′ - (123,456) show comma and digits, no precision
         ‘0,000.00′ - (123,456.78) show comma and digits, 2 precision
         ‘0,0.00′ - (123,456.78) shortcut method, show comma and digits, 2 precision

@method format
@param format {string} the way you would like to format this text
@return {string} the formatted number
@public
*/

(function() {
  
Number.prototype.format = function(format) {
  if (! typeof format == 'string') {return '';} // sanity check

  var hasComma = -1 < format.indexOf(','),
    psplit = stripNonNumeric(format).split('.'),
    that = this;

  // compute precision
  if (1 < psplit.length) {
    // fix number precision
    that = that.toFixed(psplit[1].length);
  }
  // error: too many periods
  else if (2 < psplit.length) {
    throw('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
  }
  // remove precision
  else {
    that = that.toFixed(0);
  }

  // get the string now that precision is correct
  var fnum = that.toString();

  // format has comma, then compute commas
  if (hasComma) {
    // remove precision for computation
    psplit = fnum.split('.');

    var cnum = psplit[0],
      parr = [],
      j = cnum.length,
      m = Math.floor(j / 3),
      n = cnum.length % 3 || 3; // n cannot be ZERO or causes infinite loop

    // break the number into chunks of 3 digits; first chunk may be less than 3
    for (var i = 0; i < j; i += n) {
      if (i != 0) {n = 3;}
      parr[parr.length] = cnum.substr(i, n);
      m -= 1;
    }

    // put chunks back together, separated by comma
    fnum = parr.join(',');

    // add the precision back in
    if (psplit[1]) {fnum += '.' + psplit[1];}
  }

  // replace the number portion of the format with fnum
  return format.replace(/[\d,?\.?]+/, fnum);
};

// This function removes non-numeric characters
function stripNonNumeric( str )
{
  str += '';
  var rgx = /^\d|\.|-$/;
  var out = '';
  for( var i = 0; i < str.length; i++ )
  {
    if( rgx.test( str.charAt(i) ) ){
      if( !( ( str.charAt(i) == '.' && out.indexOf( '.' ) != -1 ) ||
             ( str.charAt(i) == '-' && out.length != 0 ) ) ){
        out += str.charAt(i);
      }
    }
  }
  return out;
}

;
  var toExec;

  Array.prototype.sum = function() {
    var that, total;
    that = this;
    total = 0;
    $.each(that, function(index, value) {
      return total += value;
    });
    return total;
  };

  toExec = function($) {
    var FormHelper, Product, Testimonial;
    FormHelper = (function() {

      function FormHelper(selector) {
        this.selector = selector;
        this.form = $(this.selector);
      }

      FormHelper.prototype.addHiddenFields = function(namesAndValues) {
        var name, value;
        for (name in namesAndValues) {
          value = namesAndValues[name];
          $('<input type="hidden">').attr({
            name: name,
            value: value,
            "class": 'dynamically-added'
          }).appendTo(this.form);
        }
        return this.form;
      };

      return FormHelper;

    })();
    Testimonial = (function() {

      function Testimonial(curIndex) {
        this.curIndex = curIndex;
        if (this.curIndex >= Testimonial.testimonials.length) this.curIndex = 0;
        this.obj = Testimonial.testimonials[this.curIndex];
        this.duration = this.obj.duration;
        this.signature = this.obj.signature;
        this.text = this.obj.text;
      }

      Testimonial.prototype.display = function() {
        var testimonial;
        testimonial = this;
        $(".testimonials #success_story").fadeOut(400, (function() {
          $(".testimonials .signature").fadeIn(400).html("&mdash;" + testimonial.signature);
          return $(".testimonials #success_story").fadeIn(400, function() {
            return testimonial.setupNext();
          }).html("\"" + testimonial.text + "\"");
        }));
        return $(".testimonials .signature").fadeOut(400);
      };

      Testimonial.prototype.setupNext = function() {
        var next;
        next = new Testimonial(this.curIndex + 1);
        return setTimeout((function() {
          return next.display();
        }), this.duration * 1000);
      };

      Testimonial.begin = function() {
        return (new Testimonial(Math.floor(Math.random() * (this.testimonials.length - 1)))).display();
      };

      return Testimonial;

    })();
    Product = (function() {

      function Product(values) {
        this.values = values;
        this.id = this.values.id;
        this.displayName = this.values.displayName;
        this.price = this.values.price || 0;
        this.fields = $("#prod-" + this.id + "-quantity");
        this.quantity = Number(this.fields.find('.in-cart').text());
      }

      Product.prototype.fillTotalField = function() {
        this.totalDiv || (this.totalDiv = this.fields.find('.total'));
        return this.totalDiv.text('$' + this.total().format('0,000.00'));
      };

      Product.prototype.total = function(quantity) {
        if (quantity == null) quantity = this.quantity;
        return this.quantity * this.price;
      };

      Product.prototype.updateTotal = function() {
        var numField;
        numField = this.fields.find('.num-field');
        this.quantity = Number(numField.val()) || 0;
        this.fields.find('.in-cart').text(this.quantity);
        numField.val('');
        return this.fillTotalField();
      };

      Product.prototype.prepareForSubmit = function() {
        var fields;
        if (this.quantity > 0) {
          fields = {};
          fields["item_name_" + Product.itemIndex] = this.displayName;
          fields["amount_" + Product.itemIndex] = this.price;
          fields["quantity_" + Product.itemIndex] = this.quantity;
          (new FormHelper('#purchase-form')).addHiddenFields(fields);
          return Product.itemIndex++;
        }
      };

      Product.find = function(prod_id) {
        var val;
        return new Product(((function() {
          var _i, _len, _ref, _results;
          _ref = this.products;
          _results = [];
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            val = _ref[_i];
            if (val.id === prod_id) _results.push(val);
          }
          return _results;
        }).call(this))[0] || {
          id: prod_id
        });
      };

      Product.curProducts = function() {
        var prod_id, _i, _len, _ref, _results;
        _ref = $('.prod-quantity-col').map(function(index, obj) {
          return $(obj).data('product');
        });
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          prod_id = _ref[_i];
          _results.push(this.find(prod_id));
        }
        return _results;
      };

      Product.updateTotal = function() {
        var checkoutBtn, discount, prod, products, subtotal, total, val;
        products = this.curProducts();
        subtotal = products.map(function(obj) {
          return obj.total();
        }).reduce(function(t, s) {
          return t + s;
        });
        $('#subtotal').text('$' + subtotal.format('0,000.00'));
        discount = subtotal * (this.discountValue * 0.01);
        $('#discount').text(discount > 0 ? "-$" + (discount.format('0,000.00')) + " (" + this.discountValue + "%)" : "$0.00");
        total = subtotal - discount;
        $('#final-total').text("$" + (total.format('0,000.00')));
        $('#cart-quantity').text(val = ((function() {
          var _i, _len, _results;
          _results = [];
          for (_i = 0, _len = products.length; _i < _len; _i++) {
            prod = products[_i];
            _results.push(prod.quantity);
          }
          return _results;
        })()).sum());
        checkoutBtn = $('#proceed-to-checkout');
        if (total > 0) {
          if (!Product.checkingOut) return checkoutBtn.removeClass('disabled');
        } else {
          if (!checkoutBtn.hasClass('disabled')) {
            return checkoutBtn.addClass('disabled');
          }
        }
      };

      Product.discountValue = 0;

      Product.checkingDiscountCode = false;

      Product.checkingOut = false;

      Product.prepareForSubmit = function() {
        var fields;
        $('.dynamically-added').remove();
        fields = {
          business: Product.businessEmail,
          /*
                  Prompt for a shipping address, and require one
          
                   Other values are:
                    0 - prompt for an address, but do not require one
                    1 - do not prompt for an address
                    2 - prompt for an address, and require one
          */
          no_shipping: Product.paypalRequireShipping
        };
        if (Product.discountValue > 0) {
          fields["discount_rate_cart"] = Product.discountValue;
          fields["custom"] = $('#discount-code').val();
        }
        (new FormHelper('#purchase-form')).addHiddenFields(fields);
        Product.itemIndex = 1;
        return $.each(Product.curProducts(), function() {
          return this.prepareForSubmit();
        });
      };

      Product.waitForDiscount = function(runAfter, tryFor) {
        if (tryFor == null) tryFor = 10;
        if (Product.checkingDiscountCode || tryFor === 0) {
          return setTimeout(function() {
            Product.waitForDiscount(runAfter, tryFor);
            return tryFor--;
          }, 500);
        } else {
          return runAfter();
        }
      };

      return Product;

    })();
    window.Product = Product;
    window.Testimonial = Testimonial;
    return $(function() {
      var embedYouTubeURL, generatePhone, val;
      generatePhone = function() {
        /*
              I know this won't stop the smarter phone mining bots,
              but I suspect this minor obfuscation of not including
              the values in the initial html load should stop many of them.
        */
        var number, numberA, numberB, numberC, numberD;
        numberA = ['1'];
        numberB = ['7'];
        numberB.push('7');
        numberB.push('8');
        numberC = ['1'];
        numberC.push('7');
        numberC.push('5');
        numberD = ['8'];
        numberD.push('1');
        numberD.push('7');
        numberD.push('7');
        return number = [numberA, numberB, numberC, numberD];
      };
      $('.shimmy-phone-number').text(((function() {
        var _i, _len, _ref, _results;
        _ref = generatePhone();
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          val = _ref[_i];
          _results.push(val.reverse().join(''));
        }
        return _results;
      })()).join('-'));
      $('.map').maphilight({
        fill: false,
        stroke: false,
        shadow: true,
        shadowPosition: 'outside',
        shadowFrom: 'fill',
        shadowRadius: 25,
        shadowColor: '2077c8',
        shadowOpacity: 0.9
      });
      $('[data-hilight]').mouseover(function() {
        return $("#" + ($(this).data('hilight'))).mouseover();
      }).mouseout(function() {
        return $("#" + ($(this).data('hilight'))).mouseout();
      });
      Testimonial.begin();
      $('.add-to-cart').click(function(e) {
        var product;
        e.preventDefault();
        if (!Product.checkingOut) {
          $(this).find('.btn-text').text($(this).data('update_cart_text'));
          product = Product.find($(this).parents('.prod-quantity-col').data('product'));
          product.fields.find('.checkout-hint').show();
          product.updateTotal();
          return Product.updateTotal();
        }
      });
      $('#discount-code').change(function() {
        var field;
        $(this).removeClass('discount-success', 'discount-failure');
        field = $(this);
        Product.checkingDiscountCode = true;
        return $.ajax(Product.discountCheckPath, {
          data: {
            discountCode: $(this).val()
          },
          success: function(data, textStatus, xhr) {
            Product.checkingDiscountCode = false;
            Product.discountValue = Number(data) || 0;
            Product.updateTotal();
            if (Product.discountValue > 0) {
              return field.addClass('discount-success');
            } else {
              return field.addClass('discount-failure');
            }
          }
        });
      });
      $('#proceed-to-checkout').click(function(e) {
        e.preventDefault();
        if (!$(this).hasClass('disabled') && !Product.checkingOut) {
          Product.checkingOut = true;
          $('.add-to-cart').addClass('disabled');
          $(this).addClass('disabled');
          return Product.waitForDiscount(function() {
            Product.prepareForSubmit();
            return $('#purchase-form').submit();
          });
        }
      });
      $('#purchase-form').keypress(function(e) {
        var c;
        c = e.which ? e.which : e.keyCode;
        if (c === 13) return e.preventDefault();
      });
      embedYouTubeURL = function(url) {
        /* Get the v= code
        */
        var v;
        v = url.match(/\?.*v=([^&]+)/)[1];
        return "http://www.youtube.com/embed/" + v + "?rel=0";
      };
      $('.youtube-link').click(function(e) {
        e.preventDefault();
        if (!$(this).hasClass('active-video')) {
          $('.active-video').removeClass('active-video');
          $(this).addClass('active-video');
          return $('#embedded-youtube').attr('src', embedYouTubeURL($(this).attr('href')));
        }
      });
      $('.play-audio').click(function(e) {
        /*
              Feature detection...can we play this in the browser?
              If not, it should just use normal functionality and either
              download the mp3 file or play it in a new window in the browser
        */
        var audio;
        if (!!document.createElement('audio').canPlayType) {
          e.preventDefault();
          audio = $(this).next('audio').get('0');
          if ($(this).hasClass('playing')) {
            $(this).removeClass('playing');
            return audio.pause();
          } else {
            $(this).addClass('playing');
            return audio.play();
          }
        }
      });
      $('audio').bind('ended', function() {
        $(this).prev('.play-audio').removeClass('playing');
        return $(this).currentTime = 0;
      });
      if ($('#discount-code').val() !== '') $('#discount-code').trigger('change');
      /*
          Fixes a box-shadow drawing error in MacOS webkit
          when the rotated elements are hovered:
          http://stackoverflow.com/questions/8932697/webkit-box-shadow-gitches-on-top-of-the-other-elements
      */
      return $('.top-nav a').hover(function() {
        return $($('.top-nav a').toArray().reverse()).each(function() {
          $(this).hide();
          this.offsetHeight;
          return $(this).show();
        });
      });
    });
  };

  toExec(jQuery);

}).call(this);

