Forums

Two separate questions..

arrick 11 Nov, 2016
You can view my form at http://tinyurl.com/hwtgh48 to see what I am talking about... I am trying to get the item number in the multiplier to start at 1, but it starts with __N__ for the first item, and has 1 for the second item... it also doesn't behave like the demo, even though I set it up exactly as the demo... meaning that the first item is there, but the demo has the item not shown until the plus sign is clicked.


The other question is... calculations... I cant remember how to do them...
so... psuedocode is located below
I have the fields QTY, prPriceEach, prLineSub, and prSalesTax on each line, and at the end of the form, I have prSubTotal, prSalesTaxTotal and prTotal for fields.

Step 1: populate the prLineSub field for each line automatically using QTY*prPriceEach

Next Item
IF prSalesTax = checked, then prLineSub*.06
Store each line result in a variable somehow for addition at the end, to populate the prSalesTaxTotal field

Next Item
calculate subtotal of all "prLineSub" fields from the multiplier

Last, but not least
Calculate prSalesTaxTotal+prSubTotal and fill the prTotal field.
GreyHead 12 Nov, 2016
Hi Arrick,

There are options in the Multiplier Container settings to hide and/or disable the first multiplier content element.

Please see this FAQ for the basics in using JavaScript with your multiplier. It gets more complicated if you want to do calculations but it is possible.

What I did for a client was to add a hidden input to each multiplier line with an 'id' for that line, then when the + or x buttons are clicked re-check and update a JavaScript array of current ids. That is needed to cope with the ability add or remove lines.

Then you can use that array to scan the form elements when something changes to re-calculate the totals.

I do have an example but it is about 250 lines of JS and may not be useful??

Bob
arrick 14 Nov, 2016
I could probably use that example Bob, thank you.
GreyHead 15 Nov, 2016
Hi Arrick,

Here you go
jQuery(document).ready(function(jQ) {
  var g_id, g_id_list, garments;
  g_id = [];
  garments = [];
/*  jQ('#quantity').change(calculate);
  jQ('#style').change(calculate);
  jQ('#material_colour').change(calculate);
  jQ('#calc_btn').click(calculate);*/
  jQ('#garment_multiplier .multiplier-add-button').click(delayUpdate);
  jQ('#garment_multiplier').on('click', '.multiplier-remove-button', delayUpdate );
  jQ('#garment_multiplier').on('change', '.update', calculateGarmentPrice );
  updateGarments();

  /**
  This function delays the execution of the calculate function
  to allow time for the multiplier code to add the new item.
  */
  function delayUpdate(){
    setTimeout(updateGarments, 500);
  }

  function updateGarments(){
    var i, quantity, max_quantity, g_id, diff, new_g_id_list;

    max_quantity = 100;

    /** There is a hidden input with the class g_id
    that has the item number set as its value.
    We find all the current values here */
    g_id = jQ('#garment_multiplier :input').filter('.g_id');
    new_g_id_list = g_id.map(
      function(){
        return this.value;
      }
    ).get();
    // remove the hidden copy with the '##' index
    i = new_g_id_list.indexOf('##');
    if ( i != -1 ) {
      new_g_id_list.splice(i, 1);
    }
    // set the Item Count
    jQ('#item_count').text(new_g_id_list.length);

    // see what has changed from the saved list
    // if there is a value it is for the new row added.
    diff = jQ(new_g_id_list).not(g_id_list).get()[0];

    g_id_list = new_g_id_list;

    // remove any deleted garments
    garments = garments.filter(function( obj ) {
      id = obj.id.toString();
      var test = jQ.inArray(id, g_id_list);
      if ( jQ.inArray(id, g_id_list) > -1 ) {
        return true;
      } else {
        return false;
      }
    });

    // Hide the Add button if we've got to Max Quantity
    quantity = g_id_list.length;
    if ( quantity >= ( parseInt(max_quantity) ) ) {
      jQ('#garment_multiplier .multiplier-add-button').hide();
    } else {
      jQ('#garment_multiplier .multiplier-add-button').show();
    }

    if ( !diff ) {
      // there are no new garments
      calculateTotals();
      return false;
    }

    // add change changeColourOptions to the new Style drop-down
    jQ('#garment_'+diff+'_style').change({g_id: diff}, function(event) {
      style = event.currentTarget.value;
      target = jQ('#garment_'+diff+'_colour');
      colours = changeColourOptions(style);
      replaceOptions(target, colours);
    });

    // copy the new list into the saved list
    garment = {
      id: diff,
      style: '',
      price: 0,
      name: '',
      number: ''
    };
    garments.push(garment);

    calculateTotals();
  }

  function calculateGarmentPrice() {
    var price;
    el = jQ(this);
    var value = el.val();
    var id = el.prop('id').split('_');
    var style = jQ('#'+id[0]+'_'+id[1]+'_style').val();
    var back_name = jQ('#'+id[0]+'_'+id[1]+'_back_name').val();
    var back_number = jQ('#'+id[0]+'_'+id[1]+'_back_number').val();

    switch ( style ) {
      case '':
      price = '??.??';
      default:
      case '1':
      case '2':
      case '4':
        price = 18.99;
        break;
      case '3':
        price = 20.99;
        break;
    }
    is_name = '';
    if ( back_name ) {
      price += 2.50;
      is_name = 1;
    }
    is_number = '';
    if ( back_number ) {
      price += 2.50;
      is_number = 1;
    }
    // display the price for the item
    var price_tag = jQ('#price_'+id[1]);
    price_tag.text(price.toFixed(2));

    changePrice(id[1], style, price, is_name, is_number );

    calculateTotals();
  }

  // update the price and style in the garment array
  function changePrice( id, style, price, name, number  ) {
    var i;
     for ( i in garments ) {
       if ( garments[i].id == id) {
          garments[i].price = price;
          garments[i].style = style;
          garments[i].name = name;
          garments[i].number = number;
          break;
       }
     }
  }

  /** Calculate the total order price and discounts */
  function calculateTotals() {
    var total_price, shirts, polos, non_polos, discount;
    total_price = 0;
    shirts = 0;
    polos = 0;
    jQ.each(garments, function(garment, data) {
      total_price += data.price;
    if ( data.style != '' ) {
        shirts += 1;
      }
    });

    discount = 0;
    if ( shirts > 5 ) {
      discount += shirts * 4;
    } else if ( shirts > 2 ) {
      discount  += shirts * 2;
    }

    price_text = '£'+total_price.toFixed(2);
    if ( discount > 0 ) {
      price_text += ' less quantity discount of £'+discount.toFixed(2)+' : £'+(total_price - discount).toFixed(2);
    }

    jQ('#total_price').text(price_text);
  }

  /* This function updates the shirt color picker */
  function changeColourOptions(style) {
    switch ( style ) {
      default:
        colours = no_options;
        break;
      case '1': // Standard T-Shirt
        colours = standard_colour;
        break;
      case '2': // Fitted T-Shirt
        colours = fitted_colour;
        break;
      case '3': // Polo
        colours = polo_colour;
        break;
      case '4': // Vest
        colours = vest_colour;
        break;
    }
    return colours;
  }

  // These are the arrays of available colour options for each style
  var no_options = [];
  var fitted_colour = [
    {text: 'Please select', value: ''},
    {text: 'Black', value: 'Black'},
    {text: 'White', value: 'White'}
  ];
  var vest_colour = [
    {text: 'Please select', value: ''},
    {text: 'Black', value: 'Black'},
    {text: 'White', value: 'White'},
    {text: 'Dark Grey', value: 'Dark Grey'}
  ];
  var polo_colour = [
    {text: 'Please select', value: ''},
    {text: 'Black', value: 'Black'},
    {text: 'White', value: 'White'},
    {text: 'Dark Grey', value: 'Dark Grey'},
    {text: 'Hot Pink', value: 'Hot Pink'}
  ];
  var standard_colour = [
    {text: 'Please select', value: ''},
    {text: 'Black', value: 'Black'},
    {text: 'White', value: 'White'},
    {text: 'Dark Grey', value: 'Dark Grey'},
    {text: 'Hot Pink', value: 'Hot Pink'},
    {text: 'Light Pink', value: 'Light Pink'},
    {text: 'Red', value: 'Red'},
    {text: 'Purple', value: 'Purple'},
    {text: 'Royal Blue', value: 'Royal Blue'},
    {text: 'Navy Blue', value: 'Navy Blue'},
    {text: 'Sky Blue', value: 'Sky Blue'},
    {text: 'Green', value: 'Green'},
    {text: 'Yellow', value: 'Yellow'}
  ];

  function replaceOptions(colour, options) {
    var self, option, colour;
    colour.empty();
    jQ.each(options, function(index, option) {
      option = jQ("<option></option>")
        .attr("value", option.value)
        .text(option.text);
      colour.append(option);
    });
  };

});

This was written for a multiplier a bit more complicated than yours. Each row allows you to select a different kind of garment with different pricing and colour options so a chunk of the code is used to handle those.

Rows 9 & 10 are triggered when the Add and Delete buttons are clicked - they both fire a delayUpdate(function) that just waits half a second (to allow the add or remove to complete) then calls the updateGarments() function

updateGarments() scans the current set of multiplier rows and updates an array g_id_list with the current ids. If there is a new row if sets the options for that row.

calculateGarmentPrice() does just that for a single garment row - using the selected options for that row and calls changePrice() to update the form.

calculateTotals() scans the current garment rows and updates the total including some discounts for quantities of garments of the same type.

Bob
This topic is locked and no more replies can be posted.