2018-12-10 12:52:24 +01:00
|
|
|
import { macroName, round, sampleStyle } from "./utils";
|
2018-08-05 18:19:48 +02:00
|
|
|
import Part from "./part";
|
|
|
|
import Point from "./point";
|
|
|
|
import Path from "./path";
|
|
|
|
import Snippet from "./snippet";
|
|
|
|
import Svg from "./svg";
|
2018-08-01 18:18:29 +02:00
|
|
|
import pack from "bin-pack";
|
2018-08-05 18:19:48 +02:00
|
|
|
import Store from "./store";
|
2018-12-09 14:17:46 +01:00
|
|
|
import hooks from "./hooks";
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
export default function Pattern(config = false) {
|
2018-12-11 18:49:00 +01:00
|
|
|
this.config = config; // Pattern configuration
|
|
|
|
this.width = false; // Will be set after render
|
|
|
|
this.height = false; // Will be set after render
|
|
|
|
this.is = ""; // Will be set when drafting/sampling
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-11 18:49:00 +01:00
|
|
|
this.store = new Store(); // Store for sharing data across parts
|
|
|
|
this.parts = {}; // Parts container
|
|
|
|
this.hooks = hooks; // Hooks container
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-11 18:49:00 +01:00
|
|
|
this.Part = Part; // Part constructor
|
|
|
|
this.Point = Point; // Point constructor
|
|
|
|
this.Path = Path; // Path constructor
|
|
|
|
this.Snippet = Snippet; // Snippet constructor
|
|
|
|
|
|
|
|
// Default settings
|
2018-08-09 15:10:15 +02:00
|
|
|
this.settings = {
|
2018-09-12 17:34:53 +02:00
|
|
|
complete: true,
|
2018-08-27 16:45:03 +02:00
|
|
|
idPrefix: "fs-",
|
|
|
|
locale: "en",
|
2018-09-11 11:39:50 +02:00
|
|
|
units: "metric",
|
2018-12-11 18:49:00 +01:00
|
|
|
margin: 2,
|
2018-08-27 16:45:03 +02:00
|
|
|
options: {}
|
2018-08-05 14:04:15 +02:00
|
|
|
};
|
2018-12-09 14:17:46 +01:00
|
|
|
|
|
|
|
// Convert options
|
2018-08-09 14:21:10 +02:00
|
|
|
for (let i in config.options) {
|
|
|
|
let option = config.options[i];
|
2018-08-11 15:05:40 +02:00
|
|
|
if (typeof option === "object") {
|
2018-12-11 18:49:00 +01:00
|
|
|
if (typeof option.pct !== "undefined")
|
|
|
|
this.settings.options[i] = option.pct / 100;
|
|
|
|
else if (typeof option.mm !== "undefined")
|
|
|
|
this.settings.options[i] = option.mm;
|
|
|
|
else if (typeof option.deg !== "undefined")
|
|
|
|
this.settings.options[i] = option.deg;
|
2018-09-22 10:41:51 +02:00
|
|
|
else if (typeof option.count !== "undefined")
|
2018-12-11 18:49:00 +01:00
|
|
|
this.settings.options[i] = option.count;
|
2018-09-03 12:20:51 +02:00
|
|
|
else if (typeof option.dflt !== "undefined")
|
2018-12-11 18:49:00 +01:00
|
|
|
this.settings.options[i] = option.dflt;
|
2018-08-31 09:44:12 +02:00
|
|
|
else throw "Unknown option type";
|
2018-09-03 12:20:51 +02:00
|
|
|
} else {
|
2018-12-11 18:49:00 +01:00
|
|
|
this.settings.options[i] = option;
|
2018-08-11 15:05:40 +02:00
|
|
|
}
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-08-05 14:04:15 +02:00
|
|
|
|
2018-12-11 18:49:00 +01:00
|
|
|
// Context object (will be added to parts by createPart() )
|
2018-07-23 11:12:06 +00:00
|
|
|
this.context = {
|
|
|
|
parts: this.parts,
|
2018-07-24 08:34:26 +02:00
|
|
|
config: this.config,
|
2018-07-25 14:53:10 +00:00
|
|
|
settings: this.settings,
|
2018-08-05 16:32:38 +02:00
|
|
|
store: this.store
|
2018-07-23 11:44:34 +00:00
|
|
|
};
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-11 18:49:00 +01:00
|
|
|
// Creates a new part with the pattern context
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.createPart = function() {
|
|
|
|
let part = new Part();
|
|
|
|
part.context = this.context;
|
2018-09-30 16:25:03 +02:00
|
|
|
|
2018-12-09 14:17:46 +01:00
|
|
|
return part;
|
|
|
|
};
|
2018-09-30 16:25:03 +02:00
|
|
|
|
2018-12-11 18:49:00 +01:00
|
|
|
// Merges settings object with this.settings
|
|
|
|
Pattern.prototype.mergeSettings = function(settings) {
|
|
|
|
for (let key of Object.keys(settings)) {
|
|
|
|
if (typeof settings[key] === "object") {
|
|
|
|
this.settings[key] = {
|
|
|
|
...this.settings[key],
|
|
|
|
...settings[key]
|
|
|
|
};
|
|
|
|
} else this.settings[key] = settings[key];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.runHooks = function(hookName, data = false) {
|
|
|
|
if (data === false) data = this;
|
|
|
|
let hooks = this.hooks[hookName];
|
|
|
|
if (hooks.length > 0) {
|
|
|
|
for (let hook of hooks) {
|
|
|
|
hook.method(data, hook.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2018-09-30 16:25:03 +02:00
|
|
|
|
2018-07-23 20:14:32 +02:00
|
|
|
/**
|
2018-09-30 16:25:03 +02:00
|
|
|
* Calls _draft in the method, and pre- and postDraft
|
2018-07-23 20:14:32 +02:00
|
|
|
*/
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.draft = function() {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.is = "draft";
|
|
|
|
this.runHooks("preDraft");
|
2018-09-30 16:25:03 +02:00
|
|
|
this._draft();
|
2018-12-09 14:17:46 +01:00
|
|
|
this.runHooks("postDraft");
|
2018-09-30 16:25:03 +02:00
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @throws Will throw an error when called
|
|
|
|
*/
|
|
|
|
Pattern.prototype._draft = function() {
|
2018-07-23 20:14:32 +02:00
|
|
|
throw Error(
|
2018-09-30 16:25:03 +02:00
|
|
|
"You have to implement the _draft() method in your Pattern instance."
|
2018-07-23 20:14:32 +02:00
|
|
|
);
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-09 15:10:15 +02:00
|
|
|
/**
|
|
|
|
* Handles pattern sampling
|
|
|
|
*/
|
|
|
|
Pattern.prototype.sample = function() {
|
|
|
|
if (this.settings.sample.type === "option") {
|
|
|
|
return this.sampleOption(this.settings.sample.option);
|
2018-08-09 16:45:46 +02:00
|
|
|
} else if (this.settings.sample.type === "measurement") {
|
|
|
|
return this.sampleMeasurement(this.settings.sample.measurement);
|
2018-08-10 14:25:26 +02:00
|
|
|
} else if (this.settings.sample.type === "models") {
|
2018-08-24 20:16:01 +02:00
|
|
|
return this.sampleModels(
|
|
|
|
this.settings.sample.models,
|
|
|
|
this.settings.sample.focus || false
|
|
|
|
);
|
2018-08-09 15:10:15 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-08-10 14:25:26 +02:00
|
|
|
Pattern.prototype.sampleParts = function() {
|
|
|
|
let parts = {};
|
2018-09-22 10:41:51 +02:00
|
|
|
this.settings.complete = false;
|
2018-08-10 14:25:26 +02:00
|
|
|
this.settings.paperless = false;
|
|
|
|
this.draft();
|
|
|
|
for (let i in this.parts) {
|
|
|
|
parts[i] = new Part();
|
|
|
|
parts[i].render = this.parts[i].render;
|
|
|
|
}
|
|
|
|
return parts;
|
|
|
|
};
|
|
|
|
|
2018-09-22 10:41:51 +02:00
|
|
|
Pattern.prototype.sampleRun = function(
|
|
|
|
parts,
|
|
|
|
anchors,
|
|
|
|
run,
|
|
|
|
runs,
|
|
|
|
extraClass = false
|
|
|
|
) {
|
2018-09-07 16:09:14 +02:00
|
|
|
this.draft();
|
|
|
|
for (let i in this.parts) {
|
|
|
|
let anchor = false;
|
|
|
|
let dx = 0;
|
|
|
|
let dy = 0;
|
|
|
|
if (this.parts[i].points.anchor) {
|
|
|
|
if (typeof anchors[i] === "undefined")
|
|
|
|
anchors[i] = this.parts[i].points.anchor;
|
|
|
|
else {
|
|
|
|
if (!anchors[i].sitsOn(this.parts[i].points.anchor)) {
|
|
|
|
dx = this.parts[i].points.anchor.dx(anchors[i]);
|
|
|
|
dy = this.parts[i].points.anchor.dy(anchors[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let j in this.parts[i].paths) {
|
2018-09-22 10:41:51 +02:00
|
|
|
parts[i].paths[j + "_" + run] = this.parts[i].paths[j]
|
2018-09-07 16:09:14 +02:00
|
|
|
.clone()
|
2018-09-22 10:41:51 +02:00
|
|
|
.attr("style", sampleStyle(run, runs));
|
2018-09-07 16:09:14 +02:00
|
|
|
if (this.parts[i].points.anchor)
|
2018-09-22 10:41:51 +02:00
|
|
|
parts[i].paths[j + "_" + run] = parts[i].paths[j + "_" + run].translate(
|
2018-09-07 16:09:14 +02:00
|
|
|
dx,
|
|
|
|
dy
|
|
|
|
);
|
|
|
|
if (extraClass !== false)
|
2018-09-22 10:41:51 +02:00
|
|
|
parts[i].paths[j + "_" + run].attributes.add("class", extraClass);
|
2018-09-07 16:09:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-08-09 15:10:15 +02:00
|
|
|
/**
|
|
|
|
* Handles option sampling
|
|
|
|
*/
|
2018-09-06 12:03:18 +02:00
|
|
|
Pattern.prototype.sampleOption = function(optionName) {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.is = "sample";
|
|
|
|
this.runHooks("preSample");
|
2018-08-12 18:50:48 +02:00
|
|
|
let step, val;
|
2018-09-06 16:48:36 +02:00
|
|
|
let factor = 1;
|
2018-09-06 15:32:43 +02:00
|
|
|
let anchors = {};
|
2018-08-10 14:25:26 +02:00
|
|
|
let parts = this.sampleParts();
|
2018-09-06 12:03:18 +02:00
|
|
|
let option = this.config.options[optionName];
|
2018-09-11 16:22:08 +02:00
|
|
|
if (typeof option.list === "object") {
|
|
|
|
return this.sampleListOption(optionName);
|
|
|
|
}
|
2018-09-06 12:03:18 +02:00
|
|
|
if (typeof option.min === "undefined" || typeof option.max === "undefined") {
|
2018-09-07 16:25:17 +02:00
|
|
|
let min = option * 0.9;
|
|
|
|
let max = option * 1.1;
|
|
|
|
option = { min, max };
|
2018-08-12 18:50:48 +02:00
|
|
|
}
|
2018-09-06 16:48:36 +02:00
|
|
|
if (typeof option.pct !== "undefined") factor = 100;
|
|
|
|
val = option.min / factor;
|
|
|
|
step = (option.max / factor - val) / 9;
|
2018-09-22 10:41:51 +02:00
|
|
|
for (let run = 1; run < 11; run++) {
|
2018-12-11 18:49:00 +01:00
|
|
|
this.settings.options[optionName] = val;
|
2018-09-06 12:03:18 +02:00
|
|
|
this.debug(
|
2018-09-25 10:09:53 +00:00
|
|
|
"info",
|
2018-09-25 13:49:10 +02:00
|
|
|
"🏃🏿♀️ Sample run",
|
2018-09-06 12:03:18 +02:00
|
|
|
`Sampling option ${optionName} with value ${round(val)}`
|
|
|
|
);
|
2018-09-22 10:41:51 +02:00
|
|
|
this.sampleRun(parts, anchors, run, 10);
|
2018-08-10 14:25:26 +02:00
|
|
|
val += step;
|
2018-08-09 16:45:46 +02:00
|
|
|
}
|
|
|
|
this.parts = parts;
|
2018-12-09 14:17:46 +01:00
|
|
|
this.runHooks("postSample");
|
2018-08-09 16:45:46 +02:00
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
2018-09-11 16:22:08 +02:00
|
|
|
Pattern.prototype.sampleListOption = function(optionName) {
|
|
|
|
let parts = this.sampleParts();
|
|
|
|
let option = this.config.options[optionName];
|
|
|
|
let anchors = {};
|
2018-09-22 10:41:51 +02:00
|
|
|
let run = 1;
|
2018-12-07 15:59:57 +01:00
|
|
|
let runs = option.list.length;
|
2018-09-11 16:22:08 +02:00
|
|
|
for (let val of option.list) {
|
2018-12-11 18:49:00 +01:00
|
|
|
this.settings.options[optionName] = val;
|
2018-09-11 16:22:08 +02:00
|
|
|
this.debug(
|
2018-09-25 10:09:53 +00:00
|
|
|
"info",
|
2018-09-25 13:49:10 +02:00
|
|
|
"🏃🏿♀️ Sample run",
|
2018-09-11 16:22:08 +02:00
|
|
|
`Sampling option ${optionName} with value ${round(val)}`
|
|
|
|
);
|
2018-09-22 10:41:51 +02:00
|
|
|
this.sampleRun(parts, anchors, run, runs);
|
|
|
|
run++;
|
2018-09-11 16:22:08 +02:00
|
|
|
}
|
|
|
|
this.parts = parts;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
2018-08-09 16:45:46 +02:00
|
|
|
/**
|
|
|
|
* Handles measurement sampling
|
|
|
|
*/
|
2018-09-06 12:03:18 +02:00
|
|
|
Pattern.prototype.sampleMeasurement = function(measurementName) {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.is = "sample";
|
|
|
|
this.runHooks("preSample");
|
2018-09-07 16:09:14 +02:00
|
|
|
let anchors = {};
|
2018-08-10 14:25:26 +02:00
|
|
|
let parts = this.sampleParts();
|
2018-09-06 12:03:18 +02:00
|
|
|
let val = this.settings.measurements[measurementName];
|
2018-08-12 18:50:48 +02:00
|
|
|
if (val === undefined) throw "Cannot sample a measurement that is undefined";
|
2018-08-10 14:25:26 +02:00
|
|
|
let step = val / 50;
|
2018-08-09 16:45:46 +02:00
|
|
|
val = val * 0.9;
|
2018-09-22 10:41:51 +02:00
|
|
|
for (let run = 1; run < 11; run++) {
|
2018-09-06 12:03:18 +02:00
|
|
|
this.settings.measurements[measurementName] = val;
|
|
|
|
this.debug(
|
2018-09-25 10:09:53 +00:00
|
|
|
"info",
|
2018-09-25 13:49:10 +02:00
|
|
|
"🏃🏿♀️ Sample run",
|
2018-09-06 12:03:18 +02:00
|
|
|
`Sampling measurement ${measurementName} with value ${round(val)}`
|
|
|
|
);
|
2018-09-22 10:41:51 +02:00
|
|
|
this.sampleRun(parts, anchors, run, 10);
|
2018-08-10 14:25:26 +02:00
|
|
|
val += step;
|
|
|
|
}
|
|
|
|
this.parts = parts;
|
2018-12-09 14:17:46 +01:00
|
|
|
this.runHooks("postSample");
|
2018-08-10 14:25:26 +02:00
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles models sampling
|
|
|
|
*/
|
2018-08-24 20:16:01 +02:00
|
|
|
Pattern.prototype.sampleModels = function(models, focus = false) {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.is = "sample";
|
|
|
|
this.runHooks("preSample");
|
2018-09-07 16:09:14 +02:00
|
|
|
let anchors = {};
|
2018-08-10 14:25:26 +02:00
|
|
|
let parts = this.sampleParts();
|
2018-09-22 10:41:51 +02:00
|
|
|
let run = 0;
|
2018-09-22 11:14:10 +02:00
|
|
|
let runs = Object.keys(models).length;
|
2018-08-10 14:25:26 +02:00
|
|
|
for (let l in models) {
|
2018-09-22 10:41:51 +02:00
|
|
|
run++;
|
2018-08-10 14:25:26 +02:00
|
|
|
this.settings.measurements = models[l];
|
2018-09-25 13:49:10 +02:00
|
|
|
this.debug("info", "🏃🏿♀️ Sample run", `Sampling model ${l}`);
|
2018-09-07 16:09:14 +02:00
|
|
|
let className = l === focus ? "sample-focus" : "";
|
2018-09-22 10:41:51 +02:00
|
|
|
this.sampleRun(parts, anchors, run, runs, className);
|
2018-08-09 15:10:15 +02:00
|
|
|
}
|
|
|
|
this.parts = parts;
|
2018-12-09 14:17:46 +01:00
|
|
|
this.runHooks("postSample");
|
2018-08-09 15:57:30 +02:00
|
|
|
|
|
|
|
return this;
|
2018-08-09 15:10:15 +02:00
|
|
|
};
|
|
|
|
|
2018-08-07 15:23:37 +02:00
|
|
|
/** Debug method, exposes debug hook */
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.debug = function(...data) {
|
|
|
|
this.runHooks("debug", data);
|
|
|
|
};
|
2018-08-01 18:18:29 +02:00
|
|
|
|
2018-08-07 15:23:37 +02:00
|
|
|
Pattern.prototype.render = function() {
|
|
|
|
this.svg = new Svg(this);
|
2018-12-09 14:17:46 +01:00
|
|
|
this.svg.hooks = this.hooks;
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-03 14:20:28 +02:00
|
|
|
return this.pack().svg.render(this);
|
2018-07-23 20:14:32 +02:00
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.on = function(hook, method, data) {
|
|
|
|
this.hooks[hook].push({ method, data });
|
2018-07-23 20:14:32 +02:00
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.with = function(plugin, data = false) {
|
2018-09-30 16:25:03 +02:00
|
|
|
this.debug(
|
|
|
|
"success",
|
|
|
|
"🔌 Plugin loaded",
|
|
|
|
`${plugin.name} v${plugin.version}`
|
|
|
|
);
|
2018-12-09 14:17:46 +01:00
|
|
|
if (plugin.hooks) this.loadPluginHooks(plugin, data);
|
2018-07-23 20:14:32 +02:00
|
|
|
if (plugin.macros) this.loadPluginMacros(plugin);
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-07-23 20:14:32 +02:00
|
|
|
return this;
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-12-09 14:17:46 +01:00
|
|
|
Pattern.prototype.loadPluginHooks = function(plugin, data) {
|
|
|
|
for (let hook of Object.keys(this.hooks)) {
|
2018-07-23 20:14:32 +02:00
|
|
|
if (typeof plugin.hooks[hook] === "function") {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.on(hook, plugin.hooks[hook], data);
|
2018-08-14 09:20:47 +02:00
|
|
|
} else if (typeof plugin.hooks[hook] === "object") {
|
2018-08-11 14:03:06 +02:00
|
|
|
for (let method of plugin.hooks[hook]) {
|
2018-12-09 14:17:46 +01:00
|
|
|
this.on(hook, method, data);
|
2018-08-11 14:03:06 +02:00
|
|
|
}
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.loadPluginMacros = function(plugin) {
|
2018-07-23 20:14:32 +02:00
|
|
|
for (let macro in plugin.macros) {
|
|
|
|
if (typeof plugin.macros[macro] === "function") {
|
|
|
|
this.macro(macro, plugin.macros[macro]);
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
|
|
|
};
|
2018-07-24 14:38:03 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.macro = function(key, method) {
|
|
|
|
this.Part.prototype[macroName(key)] = method;
|
2018-07-24 14:38:03 +00:00
|
|
|
};
|
2018-08-01 18:18:29 +02:00
|
|
|
|
|
|
|
/** Packs parts in a 2D space and sets pattern size */
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.pack = function() {
|
2018-08-01 18:18:29 +02:00
|
|
|
let bins = [];
|
|
|
|
for (let key in this.parts) {
|
|
|
|
let part = this.parts[key];
|
2018-08-12 16:19:04 +02:00
|
|
|
// Avoid multiple render calls to cause stacking of transforms
|
|
|
|
part.attributes.set("transform", "");
|
2018-08-16 12:09:57 +02:00
|
|
|
if (part.render && this.needs(key)) {
|
2018-08-01 18:18:29 +02:00
|
|
|
part.stack();
|
|
|
|
bins.push({
|
2018-08-05 15:52:37 +02:00
|
|
|
id: key,
|
2018-08-01 18:18:29 +02:00
|
|
|
width: part.bottomRight.x - part.topLeft.x,
|
|
|
|
height: part.bottomRight.y - part.topLeft.y
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let size = pack(bins, { inPlace: true });
|
|
|
|
for (let bin of bins) {
|
|
|
|
let part = this.parts[bin.id];
|
|
|
|
if (bin.x !== 0 || bin.y !== 0)
|
|
|
|
part.attr("transform", `translate (${bin.x}, ${bin.y})`);
|
|
|
|
}
|
|
|
|
this.width = size.width;
|
|
|
|
this.height = size.height;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|
2018-08-15 18:54:47 +02:00
|
|
|
|
2018-08-16 12:09:57 +02:00
|
|
|
/** Determines whether a part is needed
|
|
|
|
* This depends on the 'only' setting. People can pass
|
|
|
|
* the name of a part, or an array of parts
|
|
|
|
* The absence of only means all parts are needed.
|
2018-08-15 18:54:47 +02:00
|
|
|
*
|
2018-08-16 12:09:57 +02:00
|
|
|
* If partName is an array of names, any name needed
|
|
|
|
* will cause this to return true
|
2018-08-15 18:54:47 +02:00
|
|
|
*/
|
2018-08-20 12:16:13 +02:00
|
|
|
Pattern.prototype.needs = function(partName, strict = false) {
|
2018-08-15 18:54:47 +02:00
|
|
|
if (typeof partName !== "string") {
|
|
|
|
for (let part of partName) {
|
2018-08-20 12:16:13 +02:00
|
|
|
if (this.needs(part, strict)) return true;
|
2018-08-15 18:54:47 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-08-20 12:16:13 +02:00
|
|
|
if (typeof this.settings.only === "undefined") {
|
|
|
|
if (strict) return false;
|
|
|
|
else return true;
|
|
|
|
} else if (this.settings.only === partName) return true;
|
2018-08-16 16:09:47 +02:00
|
|
|
else if (
|
|
|
|
typeof this.settings.only === "object" &&
|
|
|
|
this.settings.only.indexOf(partName) !== -1
|
2018-08-20 12:16:13 +02:00
|
|
|
) {
|
2018-08-16 16:09:47 +02:00
|
|
|
return true;
|
2018-08-20 12:16:13 +02:00
|
|
|
} else return false;
|
2018-08-15 18:54:47 +02:00
|
|
|
};
|