Calculate your DIY e-liquid recipes precisely by weight.
E-Juice Recipe Calculator (by Weight)
Enter your desired final e-liquid volume, target nicotine strength, PG/VG ratio, and flavoring percentages. The calculator will provide the exact weight of each component needed for your mix.
Enter the total volume of e-liquid you want to make (e.g., 100 ml).
The desired nicotine concentration in your final e-liquid (e.g., 3 mg/ml).
The strength of your concentrated nicotine base (e.g., 100 mg/ml).
50% PG / 50% VG
30% PG / 70% VG
70% PG / 30% VG
0% PG / 100% VG
100% PG / 0% VG
Select the desired ratio of Propylene Glycol (PG) to Vegetable Glycerin (VG).
Recipe Breakdown (by Weight)
Total Weight: 0g
Nicotine Base:0g
PG:0g
VG:0g
Flavorings Total:0g
How it's calculated:
The calculator first determines the required amount of nicotine base based on the final volume, target nicotine strength, and the strength of the nicotine base. Then, it calculates the required PG and VG volumes based on the selected ratio. Finally, it sums up the volumes of nicotine, PG, VG, and flavorings to determine the total volume. For weight calculations, we use approximate densities (PG: 1.036 g/ml, VG: 1.261 g/ml, Nicotine: ~1.03 g/ml, Flavors vary but are often close to PG). The calculator assumes these densities to convert volumes to weights for precise mixing.
Results copied to clipboard!
Recipe Component Distribution
Visual representation of the weight percentage of each component in your e-juice recipe.
Component
Weight (g)
Percentage (%)
Nicotine Base
0g
0%
PG
0g
0%
VG
0g
0%
Flavorings Total
0g
0%
Flavor Name
0g
0%
Total
0g
100%
Detailed breakdown of your e-juice recipe components by weight and their contribution to the total mix.
What is E-Juice Calculation by Weight?
{primary_keyword} is a method used by DIY e-liquid enthusiasts to mix their own vaping liquids. Instead of measuring by volume (milliliters), which can be imprecise due to varying densities of liquids, mixing by weight (grams) offers superior accuracy and consistency. This approach is crucial for replicating recipes precisely every time, especially when dealing with different base liquids (PG/VG) and concentrated flavorings.
Who Should Use It?
Anyone who enjoys creating their own e-juices for vaping should consider using a calculator by weight. This includes:
DIY e-liquid mixers seeking consistency and repeatability.
Vapers looking to save money by making their own e-juices.
Users who want precise control over nicotine levels and ingredient ratios.
Individuals mixing larger batches of e-liquid where accuracy is paramount.
Common Misconceptions
A frequent misconception is that volume measurements are sufficient for e-juice mixing. While small batches might tolerate minor inaccuracies, significant deviations can occur because PG, VG, nicotine bases, and flavorings all have different densities. Another myth is that mixing by weight is overly complicated; however, with a simple digital scale and a reliable calculator like this one, it becomes straightforward and significantly improves results. This detailed {primary_keyword} guide will demystify the process.
E-Juice Calculator by Weight Formula and Mathematical Explanation
The core of the {primary_keyword} lies in converting desired volumes and percentages into precise weights, accounting for the densities of each ingredient. Here's a step-by-step breakdown:
Step-by-Step Derivation
Calculate Nicotine Volume: The volume of nicotine required is determined by the final desired volume and the target nicotine concentration, adjusted by the strength of the nicotine base.
Calculate PG and VG Volumes: Based on the chosen PG/VG ratio, the volumes of PG and VG needed to fill the remaining space (after nicotine and flavorings) are calculated.
Calculate Flavoring Volumes: The specified percentage for each flavoring is applied to the final desired volume to find its required volume.
Convert Volumes to Weights: Using the specific gravity (density) of each component (PG, VG, Nicotine, Flavors), the calculated volumes are converted into weights.
Sum Weights: All individual component weights are summed to get the total recipe weight.
Variable Explanations
To understand the calculations, let's define the variables involved:
Percentage by Weight: \( \%W_{component} = \frac{W_{component}}{W_{total}} \times 100 \)
Note: The calculator simplifies by calculating PG and VG volumes directly based on the desired ratio, and then calculating their weights. Flavorings are added as percentages of the final volume and converted to weight. The total weight is the sum of all calculated weights.
Practical Examples (Real-World Use Cases)
Example 1: A Standard 60ml Bottle at 3mg Nicotine
A user wants to create 60ml of e-juice with 3mg/ml nicotine, using a 50/50 PG/VG ratio and 10% total flavoring. They have a 100mg/ml nicotine base.
Now, adjust PG/VG to accommodate nicotine and flavors. The total base liquid volume needed (PG+VG) is \( 60\text{ml} – 1.8\text{ml} – 6\text{ml} = 52.2 \text{ml} \).
Since the desired ratio is 50/50 for the *final* mix, this often implies the base liquid *without* nicotine/flavorings. However, a common approach is to fill to the final volume. Let's recalculate assuming the 50/50 applies to the *entire* final volume *before* accounting for nicotine concentration adjustments. A more precise method: the total *non-nicotine, non-flavor* volume is \(60 \text{ml} – 1.8 \text{ml} = 58.2 \text{ml}\). The flavorings take up 6ml. So, the remaining volume for PG/VG is \( 58.2 \text{ml} – 6 \text{ml} = 52.2 \text{ml} \). This \(52.2 \text{ml}\) needs to be split 50/50 PG/VG. So, \(52.2 \text{ml} / 2 = 26.1 \text{ml}\) PG and \(26.1 \text{ml}\) VG.
Interpretation: The calculator would display these weights, totaling approximately 68 grams. This highlights how the total weight differs from the target volume (60ml) due to the higher density of VG.
Example 2: A Large Batch – 120ml at 6mg Nicotine, Max VG
A user wants a large 120ml batch with a higher nicotine strength of 6mg/ml, prioritizing VG for thicker clouds (Max VG, meaning only enough PG for the nicotine base and flavors). They use a 100mg/ml nicotine base and 15% total flavoring.
Inputs:
Final Volume: 120 ml
Target Nicotine: 6 mg/ml
Nicotine Base Strength: 100 mg/ml
PG/VG Ratio: Set to "Max VG" (effectively, minimal PG)
The "Max VG" scenario means we use the minimum required PG. PG is needed for the nicotine base carrier and potentially the flavorings if they are PG-based. Let's assume the nicotine base is PG-based and flavors are also PG-based unless specified otherwise. For simplicity in "Max VG", we often consider the PG volume needed solely for the nicotine solution and flavorings. Let's allocate 7.2ml (for nicotine) + 18ml (for flavors) = 25.2ml total PG.
Volume of VG: \( 120 \text{ ml} – 7.2 \text{ ml (Nicotine)} – 18 \text{ ml (Flavors)} = 94.8 \text{ ml} \)
Total Volumes: Nicotine: 7.2ml, PG: 25.2ml, VG: 94.8ml. (Total = 7.2 + 25.2 + 94.8 = 127.2ml – Wait, this sum exceeds 120ml. This shows the complexity. A better "Max VG" approach means the *ratio* of PG to VG in the final liquid is very high in VG. Let's retry: The total volume is 120ml. Nicotine is 7.2ml. Flavors are 18ml. That leaves 120 – 7.2 – 18 = 94.8ml for the base PG/VG. If it's Max VG, almost all of this 94.8ml will be VG. We'll use a small amount of PG, say 5ml, to carry the nicotine and flavors if they are concentrated. So, PG = 5ml, VG = 120 – 7.2 – 18 – 5 = 89.8ml. This is more typical for "Max VG" recipes.)
Let's use the calculator's typical logic: It fills PG/VG to the target ratio *after* accommodating nicotine and flavors. If 50/50 ratio is selected, it means 50% of the *remaining* volume after nicotine & flavors is PG, and 50% is VG. For Max VG, it implies 0% PG, 100% VG for the base.
Revised calculation (assuming Max VG means only VG fills the remaining volume):
Interpretation: The resulting e-juice will be very heavy due to the high VG content. The total weight (approx. 145.6g) is significantly more than the target volume (120ml), illustrating the impact of VG's density. This is typical for Max VG recipes designed for maximum vapor production.
How to Use This E-Juice Calculator by Weight
Using the {primary_keyword} calculator is designed to be intuitive. Follow these steps for accurate DIY e-liquid mixing:
Step-by-Step Instructions
Enter Final Volume: Specify the total milliliters (ml) of e-liquid you want to create (e.g., 100ml).
Set Target Nicotine: Input your desired nicotine strength in milligrams per milliliter (mg/ml) for the final e-liquid.
Specify Nicotine Base Strength: Enter the concentration (mg/ml) of the nicotine liquid you are using.
Choose PG/VG Ratio: Select your preferred ratio of Propylene Glycol (PG) to Vegetable Glycerin (VG) from the dropdown. Options like "Max VG" prioritize VG.
Add Flavorings: Use the "Add Another Flavor" button to include all your desired flavorings. For each, enter its name (optional but helpful) and its percentage (%) of the total final volume. Ensure the percentages of all flavorings do not exceed 100% combined.
Calculate: Click the "Calculate Recipe" button.
How to Read Results
The calculator will display:
Primary Result (Total Weight): The most important output, shown in grams (g). This is the total weight you should aim for on your scale.
Intermediate Values: The calculated weight (in grams) for each component: Nicotine Base, PG, VG, and each individual flavoring.
Table Breakdown: A clear table summarizes the weights and calculates the percentage each component contributes to the total weight. This is useful for understanding the final composition.
Chart Visualization: A dynamic chart offers a visual representation of the component distribution by weight.
Decision-Making Guidance
The results from the {primary_keyword} calculator help you make informed decisions:
Accuracy: Ensure you have the correct weights for each ingredient to achieve the precise nicotine strength and flavor profile intended.
Mixing: Use a digital scale accurate to at least 0.01g. Tare (zero out) your scale with the mixing bottle. Add each ingredient by weight according to the calculator's results.
Adjustments: If you find the final mix too harsh (high PG), too wispy (low VG), or not flavorful enough, you can adjust the PG/VG ratio or flavoring percentages in the calculator and re-calculate for your next batch. This iterative process is key to perfecting your recipes. Consider exploring different DIY e-liquid mixing resources.
Key Factors That Affect E-Juice Calculator by Weight Results
While the calculator provides precise outputs based on inputs, several real-world factors can influence the final outcome:
Ingredient Densities: The calculator uses average densities for PG, VG, and nicotine bases. However, these can vary slightly between manufacturers and even batches. Different flavorings also have unique densities. For ultimate precision, you might need to find specific density data for your exact ingredients, though typical values are usually sufficient for DIY mixing. Understanding density variations is key.
Temperature: Like most liquids, PG and VG densities are affected by temperature. Colder liquids are denser. While DIY mixing typically occurs at room temperature, significant temperature fluctuations could introduce minor variances.
Nicotine Base Dilution: If your nicotine base is already diluted (e.g., 100mg/ml nicotine in PG), the calculator correctly uses its effective mg/ml strength. However, ensure you know the carrier liquid (PG or VG) of your nicotine base if you need to fine-tune the final PG/VG ratio manually.
Flavor Concentrates: Flavorings are often highly concentrated and can be PG-based, VG-based, or water-based. Their density varies significantly. The calculator uses an average density; for complex recipes with multiple, very different flavorings, a slight weight deviation might occur.
Mixing Bottle Headspace: The calculator assumes the final volume is achieved perfectly. In practice, small amounts of liquid might cling to mixing tools or the sides of the bottle, potentially leading to a slightly lower final volume than intended. This is usually negligible for typical batch sizes.
Scale Accuracy: The precision of your digital scale is paramount. A scale that measures to only 0.1g increments will introduce more error than one measuring to 0.01g. Always use a high-quality, calibrated scale for accurate results.
Evaporation: While unlikely to be significant during the short mixing process, extremely volatile ingredients or prolonged exposure to air could lead to minor weight loss through evaporation.
Frequently Asked Questions (FAQ)
Q1: Why is mixing e-juice by weight better than by volume?
A: Mixing by weight is more accurate because liquids have different densities. For example, VG is much denser than PG. Measuring by volume can lead to inconsistent nicotine levels and flavor profiles. Weight measurements eliminate density variations, ensuring recipe replication.
Q2: What is the standard density used for PG and VG?
A: Typical densities used are approximately 1.036 g/ml for PG and 1.261 g/ml for VG at room temperature. Nicotine base density is often around 1.03 g/ml, but can vary. Flavoring densities vary widely.
Q3: Do I need a special scale for mixing e-juice?
A: A good quality digital scale that measures in grams (g) and can display increments of 0.01g is highly recommended. It ensures precise measurements of small quantities, especially for nicotine and flavorings.
Q4: How do I handle the "Max VG" option?
A: "Max VG" means you want the highest possible VG percentage in your final e-liquid. The calculator will use only the necessary PG for the nicotine base and flavorings (assuming they are PG-based) and fill the rest with VG to achieve the target volume.
Q5: What if my nicotine base strength is different from the options?
A: Enter the exact mg/ml strength of your nicotine base into the "Nicotine Base Strength" field. Accuracy here is critical for getting the correct nicotine level in your final e-liquid.
Q6: Can I mix base liquids (PG/VG) directly without nicotine or flavors?
A: Yes. Set your Target Nicotine Strength to 0 mg/ml and Total Flavoring Percentage to 0%. The calculator will then determine the PG and VG weights based on your selected ratio and final volume.
Q7: My total calculated weight is much higher than the target volume in ml. Why?
A: This is normal, especially for recipes high in VG, as VG is significantly denser than water or PG. For example, 100ml of pure VG weighs about 126g, while 100ml of pure PG weighs about 104g. The calculator converts volumes to weights accurately based on these densities.
Q8: How accurate do flavor percentages need to be?
A: Flavor percentages are crucial for taste. While slight variations might occur due to flavoring density, aiming for the calculated weight is essential. It's recommended to start with the calculated amounts and adjust in future batches based on your taste preferences. Exploring advanced flavoring techniques can also help.
var flavorCounter = 1;
var currentFlavorCount = 1;
var densityPG = 1.036;
var densityVG = 1.261;
var densityNicotine = 1.03; // Approximate
var avgDensityFlavor = 1.036; // Assumption for average flavor density
function addFlavorInput() {
if (currentFlavorCount >= 10) { // Limit the number of flavors for performance and usability
alert("Maximum of 10 flavors allowed.");
return;
}
flavorCounter++;
currentFlavorCount++;
var newFlavorDiv = document.createElement('div');
newFlavorDiv.className = 'flavor-input-group';
newFlavorDiv.style.marginBottom = '10px';
newFlavorDiv.innerHTML = `
`;
document.getElementById('flavorInputsContainer').appendChild(newFlavorDiv);
}
function removeFlavorInput(buttonElement) {
var flavorDiv = buttonElement.parentNode;
flavorDiv.parentNode.removeChild(flavorDiv);
currentFlavorCount–;
// Update flavor counter display if needed, or just var indices be dynamic
}
function validateInput(id, errorId, minValue, maxValue, isPercentage) {
var input = document.getElementById(id);
var errorDiv = document.getElementById(errorId);
var value = parseFloat(input.value);
var isValid = true;
errorDiv.innerHTML = "; // Clear previous error
if (isNaN(value)) {
errorDiv.innerHTML = 'Please enter a valid number.';
isValid = false;
} else if (value maxValue) {
errorDiv.innerHTML = `Value must not exceed ${maxValue}${isPercentage ? '%' : "}.`;
isValid = false;
}
return isValid;
}
function calculateEjuice() {
var finalVolume = parseFloat(document.getElementById('finalVolume').value);
var targetNicotine = parseFloat(document.getElementById('targetNicotine').value);
var nicotineStrength = parseFloat(document.getElementById('nicotineStrength').value);
var pgvgRatioStr = document.getElementById('pgvgRatio').value;
var flavorNames = [];
var flavorPercents = [];
var totalFlavorPercent = 0;
var flavorErrorElements = [];
var flavorInputGroups = document.querySelectorAll('.flavor-input-group');
for (var i = 0; i < flavorInputGroups.length; i++) {
var nameInput = flavorInputGroups[i].querySelector('.flavorName');
var percentInput = flavorInputGroups[i].querySelector('.flavorPercent');
var errorDiv = flavorInputGroups[i].querySelector('.error-message');
var flavorName = nameInput.value.trim();
var flavorPercent = parseFloat(percentInput.value);
flavorNames.push(flavorName);
flavorPercents.push(flavorPercent);
flavorErrorElements.push(errorDiv);
if (isNaN(flavorPercent) || flavorPercent 100) {
alert("Total flavoring percentage cannot exceed 100%. Please adjust.");
return;
}
if (totalFlavorPercent === 100 && finalVolume > 0) {
alert("100% flavoring leaves no room for PG/VG or Nicotine. Adjust flavor percentages.");
return;
}
var remainingPercent = 100 – totalFlavorPercent;
var calculatedPercentPG = percentPG;
var calculatedPercentVG = percentVG;
// Adjust PG/VG percentages if they exceed remaining percentage (e.g. if user selected 50/50 but only 20% is left for base)
// This is a common approach: the PG/VG ratio applies to the *base* liquid needed.
// Let's assume the ratio applies to the total, and we fill the rest.
// The calculator handles this implicitly by calculating the required volumes and then weights.
var volumeNicotine = (targetNicotine * finalVolume) / nicotineStrength;
if (isNaN(volumeNicotine) || volumeNicotine finalVolume) {
document.getElementById('targetNicotineError').innerHTML = 'Nicotine volume exceeds final volume. Check inputs.';
document.getElementById('nicotineStrengthError').innerHTML = 'Nicotine volume exceeds final volume. Check inputs.';
return;
}
// Calculate volumes for PG and VG based on the ratio for the *entire* final volume
// This is a common simplification. A more complex model might subtract nicotine/flavors first.
var volumePG = finalVolume * (percentPG / 100);
var volumeVG = finalVolume * (percentVG / 100);
// Now, adjust PG/VG volumes to make space for nicotine and flavors.
// This is where "Max VG" gets tricky. Let's follow a standard approach:
// Calculate Nicotine Volume, Flavor Volumes. The remaining volume is split by PG/VG ratio.
var totalFlavorVolume = 0;
var flavorWeights = [];
var flavorPercentsByWeight = []; // To store actual weight percentages for the chart/table
var flavorTotalWeight = 0;
// Reset flavor results display
document.getElementById('otherFlavorResults').innerHTML = ";
var flavorHeaderRow = document.getElementById('tableFlavorHeaderRow');
if (flavorHeaderRow) flavorHeaderRow.style.display = 'none';
var flavorRowTemplate = document.getElementById('flavorRowTemplate');
var existingFlavorRows = document.querySelectorAll('#resultsTableBody tr[id^="flavorRowTemplate"]');
existingFlavorRows.forEach(function(row) {
row.remove();
});
for (var i = 0; i < flavorNames.length; i++) {
var currentFlavorVol = finalVolume * (flavorPercents[i] / 100);
totalFlavorVolume += currentFlavorVol;
var flavorWeight = currentFlavorVol * avgDensityFlavor; // Assuming average density
flavorWeights.push(flavorWeight);
flavorTotalWeight += flavorWeight;
// Add to results display
var resultItem = document.createElement('div');
resultItem.className = 'result-item';
resultItem.innerHTML = `${flavorNames[i] || `Flavor ${i+1}`}:${flavorWeight.toFixed(2)}g`;
document.getElementById('otherFlavorResults').appendChild(resultItem);
// Add to table
var newFlavorRow = flavorRowTemplate.cloneNode(true);
newFlavorRow.id = `flavorRowTemplate_${i}`;
newFlavorRow.style.display = ";
newFlavorRow.querySelector('.flavor-name').textContent = flavorNames[i] || `Flavor ${i+1}`;
newFlavorRow.querySelector('.flavor-weight').textContent = flavorWeight.toFixed(2) + 'g';
document.getElementById('resultsTableBody').appendChild(newFlavorRow);
}
if (flavorTotalWeight > 0) {
if (flavorHeaderRow) flavorHeaderRow.style.display = ";
document.getElementById('tableFlavoringsWeight').textContent = flavorTotalWeight.toFixed(2) + 'g';
}
var remainingVolumeForBase = finalVolume – volumeNicotine – totalFlavorVolume;
if (remainingVolumeForBase finalVolume if nicotine/flavors are added.
// The most robust way is to calculate NIC volume, then FLAVOR volumes, then determine BASE PG/VG volume
// that fits into FINAL VOLUME – NIC_VOL – FLAVOR_VOLS, split by the PG/VG ratio.
// Let's use the latter approach which respects final volume:
finalVolumePG = remainingVolumeForBase * (percentPG / 100);
finalVolumeVG = remainingVolumeForBase * (percentVG / 100);
// Edge case: If user sets 100/0 and total flavor/nicotine already fills most volume,
// this might result in negative remainingVolumeForBase. We capped it at 0.
// If PG/VG are not 0/100 or 100/0, and remainingVolumeForBase is small, PG/VG will be small.
} else {
// Standard ratio calculation for the remaining volume
finalVolumePG = remainingVolumeForBase * (percentPG / 100);
finalVolumeVG = remainingVolumeForBase * (percentVG / 100);
}
// Ensure volumes aren't negative due to rounding or extreme inputs
finalVolumePG = Math.max(0, finalVolumePG);
finalVolumeVG = Math.max(0, finalVolumeVG);
// Calculate weights
var weightNicotine = volumeNicotine * densityNicotine;
var weightPG = finalVolumePG * densityPG;
var weightVG = finalVolumeVG * densityVG;
var totalWeight = weightNicotine + weightPG + weightVG + flavorTotalWeight;
// Update results display
document.getElementById('nicotineWeight').textContent = weightNicotine.toFixed(2) + 'g';
document.getElementById('pgWeight').textContent = weightPG.toFixed(2) + 'g';
document.getElementById('vgWeight').textContent = weightVG.toFixed(2) + 'g';
document.getElementById('primaryResult').innerHTML = `Total Weight: ${totalWeight.toFixed(2)}g`;
// Update table
document.getElementById('tableNicotineWeight').textContent = weightNicotine.toFixed(2) + 'g';
document.getElementById('tablePgWeight').textContent = weightPG.toFixed(2) + 'g';
document.getElementById('tableVgWeight').textContent = weightVG.toFixed(2) + 'g';
document.getElementById('tableTotalWeight').textContent = totalWeight.toFixed(2) + 'g';
// Calculate and display percentages for the table and chart data series
var nicotinePercentWeight = (weightNicotine / totalWeight) * 100;
var pgPercentWeight = (weightPG / totalWeight) * 100;
var vgPercentWeight = (weightVG / totalWeight) * 100;
var flavoringsPercentWeight = (flavorTotalWeight / totalWeight) * 100;
document.getElementById('tableNicotinePercent').textContent = nicotinePercentWeight.toFixed(1) + '%';
document.getElementById('tablePgPercent').textContent = pgPercentWeight.toFixed(1) + '%';
document.getElementById('tableVgPercent').textContent = vgPercentWeight.toFixed(1) + '%';
if (flavorTotalWeight > 0) {
document.getElementById('tableFlavoringsPercent').textContent = flavoringsPercentWeight.toFixed(1) + '%';
}
// Update chart data
updateChart(
totalWeight,
weightNicotine, nicotinePercentWeight,
weightPG, pgPercentWeight,
weightVG, vgPercentWeight,
flavorWeights, flavorPercents, flavorNames
);
document.getElementById('resultsContainer').style.display = 'block';
}
function resetForm() {
document.getElementById('finalVolume').value = 100;
document.getElementById('targetNicotine').value = 3;
document.getElementById('nicotineStrength').value = 100;
document.getElementById('pgvgRatio').value = '50/50′;
// Reset flavors to one default flavor
document.getElementById('flavorInputsContainer').innerHTML = `
`;
flavorCounter = 1;
currentFlavorCount = 1;
document.getElementById('resultsContainer').style.display = 'none';
document.getElementById('copyFeedback').style.display = 'none';
clearCanvas(); // Clear chart
}
function copyResults() {
var resultsText = "E-Juice Recipe (by Weight):\n\n";
resultsText += "— Key Assumptions —\n";
resultsText += "Final Volume: " + document.getElementById('finalVolume').value + " ml\n";
resultsText += "Target Nicotine: " + document.getElementById('targetNicotine').value + " mg/ml\n";
resultsText += "Nicotine Base Strength: " + document.getElementById('nicotineStrength').value + " mg/ml\n";
resultsText += "PG/VG Ratio: " + document.getElementById('pgvgRatio').value + "\n";
var flavorInputs = document.querySelectorAll('.flavor-input-group');
flavorInputs.forEach(function(group, index) {
var name = group.querySelector('.flavorName').value || `Flavor ${index + 1}`;
var percent = group.querySelector('.flavorPercent').value;
resultsText += `Flavor ${index + 1} (${name}): ${percent}%\n`;
});
resultsText += "\n— Recipe Breakdown —\n";
resultsText += "Total Weight: " + document.getElementById('primaryResult').querySelector('span').textContent + "\n";
resultsText += "Nicotine Base: " + document.getElementById('nicotineWeight').textContent + "\n";
resultsText += "PG: " + document.getElementById('pgWeight').textContent + "\n";
resultsText += "VG: " + document.getElementById('vgWeight').textContent + "\n";
var otherFlavorResults = document.getElementById('otherFlavorResults').children;
for (var i = 0; i < otherFlavorResults.length; i++) {
resultsText += otherFlavorResults[i].textContent.replace(":", ": ") + "\n";
}
try {
navigator.clipboard.writeText(resultsText).then(function() {
var feedback = document.getElementById('copyFeedback');
feedback.style.display = 'block';
setTimeout(function() {
feedback.style.display = 'none';
}, 3000);
});
} catch (err) {
console.error('Failed to copy text: ', err);
alert('Could not copy results. Please copy manually.');
}
}
// Charting Logic
var recipeChart;
var chartData = {
labels: [], // Component names
datasets: [{
label: 'Weight (g)',
data: [], // Component weights
backgroundColor: [] // Colors for each slice
}]
};
var chartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'E-Juice Component Distribution by Weight'
}
}
};
function clearCanvas() {
var canvas = document.getElementById('recipeChart');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function updateChart(totalWeight, weightNicotine, percentNicotine, weightPG, percentPG, weightVG, percentVG, flavorWeights, flavorPercentsInput, flavorNames) {
var ctx = document.getElementById('recipeChart').getContext('2d');
// Clear previous chart instance if it exists
if (recipeChart) {
recipeChart.destroy();
}
chartData.labels = [];
chartData.datasets[0].data = [];
chartData.datasets[0].backgroundColor = [];
// Add Nicotine
chartData.labels.push(`Nicotine (${percentNicotine.toFixed(1)}%)`);
chartData.datasets[0].data.push(weightNicotine);
chartData.datasets[0].backgroundColor.push('#004a99'); // Primary Blue
// Add PG
chartData.labels.push(`PG (${percentPG.toFixed(1)}%)`);
chartData.datasets[0].data.push(weightPG);
chartData.datasets[0].backgroundColor.push('#28a745'); // Success Green
// Add VG
chartData.labels.push(`VG (${percentVG.toFixed(1)}%)`);
chartData.datasets[0].data.push(weightVG);
chartData.datasets[0].backgroundColor.push('#ffc107'); // Warning Yellow
// Add Flavors
for (var i = 0; i < flavorWeights.length; i++) {
var flavorName = flavorNames[i] || `Flavor ${i+1}`;
var flavorWeight = flavorWeights[i];
// Calculate percentage by weight for label
var flavorWeightPercent = (flavorWeight / totalWeight) * 100;
chartData.labels.push(`${flavorName} (${flavorWeightPercent.toFixed(1)}%)`);
chartData.datasets[0].data.push(flavorWeight);
// Assign distinct colors to flavors, cycling through a palette
var flavorColors = ['#17a2b8', '#6f42c1', '#d63384', '#fd7e14', '#6610f2', '#0dcaf0'];
chartData.datasets[0].backgroundColor.push(flavorColors[i % flavorColors.length]);
}
// Create new chart instance
recipeChart = new Chart(ctx, {
type: 'pie', // Using pie chart for distribution
data: chartData,
options: chartOptions
});
}
// Initial chart setup (empty or with defaults)
function initializeChart() {
var canvas = document.getElementById('recipeChart');
var ctx = canvas.getContext('2d');
recipeChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["Nicotine", "PG", "VG", "Flavors"],
datasets: [{
label: 'Weight (g)',
data: [0, 0, 0, 0],
backgroundColor: ['#004a99', '#28a745', '#ffc107', '#17a2b8']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'top' },
title: { display: true, text: 'E-Juice Component Distribution by Weight' }
}
}
});
}
// Add event listeners for real-time updates (optional, but good practice)
document.getElementById('finalVolume').addEventListener('input', calculateEjuice);
document.getElementById('targetNicotine').addEventListener('input', calculateEjuice);
document.getElementById('nicotineStrength').addEventListener('input', calculateEjuice);
document.getElementById('pgvgRatio').addEventListener('change', calculateEjuice);
// Event listeners for dynamic flavor inputs need to be managed carefully
// For simplicity, we re-calculate on button click, but could delegate events
document.getElementById('flavorInputsContainer').addEventListener('input', function(event) {
if (event.target.classList.contains('flavorPercent') || event.target.classList.contains('flavorName')) {
// Debounce or throttle this if performance becomes an issue with many flavors
calculateEjuice();
}
});
// Initial calculation on page load
document.addEventListener('DOMContentLoaded', function() {
initializeChart(); // Initialize the chart first
calculateEjuice(); // Perform initial calculation
});