4

I'm working on a shopping site and want to give my users the ability to dynamically create multiple products based on variants they specify. I allow these users to create any number of 'Types', which define things like Size, Colour, or Capacity. But the user can specify the name of this and the number of types they want.

Within each Type, I also allow the user to configure multiple Choices. For example, the type Size might have choices Small, Medium, Large. Again the user can define the names of these fields and there shouldn't be any limit to how many fields they can create.

After the user has finished defining their product, I have an array for types and inside each type, an array for choices.

As a sample, a mobile phone product might have the following type and choice structure:

[
  {
  'id': 1,
  'type': 'Colour',
  'options': ['Black', 'White', 'Gold']
  },
  { 
  'id': 2,
  'type': 'Size',
  'options': ['Standard', 'Large"']
  },
  { 
  'id': 3,
  'type': 'Capacity',
  'options': ['32GB', '64GB', '128GB']
  }
]

From this data, I want to create 18 (3*2*3) possible product variants for which the user can specify specific price, weight, or SKU options. To end up with the following variants:

Black - Standard - 32GB
Black - Standard - 64GB
Black - Standard - 128GB
Black - Large - 32GB
Black - Large - 64GB
Black - Large - 128GB
White - Standard - 32GB
White - Standard - 64GB
White - Standard - 128GB
White - Large - 32GB
White - Large - 64GB
White - Large - 128GB
Gold - Standard - 32GB
Gold - Standard - 64GB
Gold - Standard - 128GB
Gold - Large - 32GB
Gold - Large - 64GB
Gold - Large - 128GB

Which I can imagine being in an array like this:

[
  {
    'variant_id': 1,
    'options':
      [{ 'type': 'Colour', 'choice': 'Black' },
      { 'type': 'Size', 'choice' 'Standard' },
      { 'type': 'Capacity', 'choice' '32G' }]
  },
  {
    'variant_id': 2,
    'options':
      [{ 'type': 'Colour', 'choice': 'Black' },
      { 'type': 'Size', 'choice' 'Standard' },
      { 'type': 'Capacity', 'choice' '64GB' }]
  },
  {
    'variant_id': 3,
    'options':
      [{ 'type': 'Colour', 'choice': 'Black' },
      { 'type': 'Size', 'choice' 'Standard' },
      { 'type': 'Capacity', 'choice' '128GB' }]
  }
<snip>

My question is how I can create a loop that will allow me to iterate over the various types and choices to create my final variant list? I'm having a hard time visualising just how I could go about delivering this function.

1
  • @SherinMathew it is my understanding that this can be unlimited. otakumike, in all honestly, if you are on a online store viewing a product, most of the time users don't select one option out of a long drop down selection but instead there would be a different select box for each type. For a t-shirt, first select size. Next select which color you want granted it is still in stock for that size. Next select custom graphics/etc. Commented Oct 21, 2014 at 12:29

2 Answers 2

1

Try the below code. It does exactly what you want in pure javascript. The generateOutput function is called in a loop for the options of first element, and then generateOutput function is called recursively generating the required result. Its hard to explain the logic in writing. Just add debuggers and to understand the flow. Best of luck.

var data = [{
  'id': 1,
  'type': 'Colour',
  'options': ['Black', 'White', 'Gold']
}, {
  'id': 2,
  'type': 'Size',
  'options': ['Standard', 'Large"']
}, {
  'id': 3,
  'type': 'Capacity',
  'options': ['32GB', '64GB', '128GB']
}];



function generateOutput(dataIndex, optionIndex) {
  var option, result, i, subResult;
  option = {
    type: data[dataIndex].type,
    choice: data[dataIndex].options[optionIndex]
  };

  if (dataIndex == data.length - 1) {
    result = {
      isLast: true,
      options: [option]
    }
    return result;
  }

  result = [];
  for (i = 0; i < data[dataIndex + 1].options.length; i++) {
    subResult = generateOutput(dataIndex + 1, i);
    if (subResult.isLast) {
      subResult.options.unshift(option);
      result.push(subResult.options);
    } else {
      result = result.concat(subResult);
    }
  }

  if (!subResult.isLast) {
    for (var j = 0; j < result.length; j++) {
      result[j].unshift(option);
    }
  }

  return result;
}

function getOutput() {
  var result = [],
    option, i;
  for (i = 0; i < data[0].options.length; i++) {
    option = {
      type: data[0].type,
      choice: data[0].options[i]
    };
    var subResult = generateOutput(0, i);
    if (subResult.isLast) {
      result.push(subResult.options);
    } else {
      result = result.concat(subResult);
    }
  }
  
  var output = [];
  for (i = 0; i < result.length; i++) {
    output.push({
      variant_id: (i+1),
      options: result[i]
    })
  }
  return output;
}

console.log(getOutput());

Sign up to request clarification or add additional context in comments.

Comments

0

here is some jquery code using various jquery array methods

var list = [{
    'id': 1,
        'type': 'Colour',
        'options': ['Black', 'White', 'Gold']
}, {
    'id': 2,
        'type': 'Size',
        'options': ['Standard', 'Large']
}, {
    'id': 3,
        'type': 'Capacity',
        'options': ['32GB', '64GB', '128GB']
}];

var return_list = [];
var prev_options = list[0].options;

$.each(list, function (index, value) {
    if (index == 0) return;
    $.each(value.options, function (index, value) {
        var temp_list = [];

        temp_list = $.map(prev_options, function (v, i) {
            return v + ' ' + value;
        });
        return_list = $.merge(return_list, temp_list);
    });

    return_list = $.grep(return_list, function (i) {
        return $.inArray(i, prev_options) == -1;
    });

    prev_options = return_list.slice(0);
});

you can test here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.