acttrader-charts 1.4.0-beta.12 → 1.4.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{MACD-B8LTAGUU.d.cts → MACD-ico-au5d.d.cts} +0 -4
- package/dist/{MACD-B8LTAGUU.d.ts → MACD-ico-au5d.d.ts} +0 -4
- package/dist/index.cjs +130 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +130 -120
- package/dist/index.js.map +1 -1
- package/dist/indicators/index.d.cts +2 -2
- package/dist/indicators/index.d.ts +2 -2
- package/dist/webview/chart.html +6 -6
- package/package.json +1 -1
|
@@ -323,10 +323,6 @@ interface ChartSettingsTemplate {
|
|
|
323
323
|
}
|
|
324
324
|
/** Mints a stable, collision-free id for a settings-template name. */
|
|
325
325
|
declare function makeSettingsTemplateId(name: string, existingIds?: readonly string[]): string;
|
|
326
|
-
/**
|
|
327
|
-
* Deep-copies a settings snapshot one level past `canvasColors`, so a saved
|
|
328
|
-
* template can never be mutated by later edits to the live chart (or vice versa).
|
|
329
|
-
*/
|
|
330
326
|
declare function cloneSettings(s: ChartSettingsSnapshot): ChartSettingsSnapshot;
|
|
331
327
|
/** Builds a template from a settings snapshot. */
|
|
332
328
|
declare function captureSettingsTemplate(name: string, settings: ChartSettingsSnapshot, opts?: {
|
|
@@ -323,10 +323,6 @@ interface ChartSettingsTemplate {
|
|
|
323
323
|
}
|
|
324
324
|
/** Mints a stable, collision-free id for a settings-template name. */
|
|
325
325
|
declare function makeSettingsTemplateId(name: string, existingIds?: readonly string[]): string;
|
|
326
|
-
/**
|
|
327
|
-
* Deep-copies a settings snapshot one level past `canvasColors`, so a saved
|
|
328
|
-
* template can never be mutated by later edits to the live chart (or vice versa).
|
|
329
|
-
*/
|
|
330
326
|
declare function cloneSettings(s: ChartSettingsSnapshot): ChartSettingsSnapshot;
|
|
331
327
|
/** Builds a template from a settings snapshot. */
|
|
332
328
|
declare function captureSettingsTemplate(name: string, settings: ChartSettingsSnapshot, opts?: {
|
package/dist/index.cjs
CHANGED
|
@@ -27089,6 +27089,123 @@ var IndicatorSettingsDialog = class {
|
|
|
27089
27089
|
}
|
|
27090
27090
|
};
|
|
27091
27091
|
|
|
27092
|
+
// src/core/templateStore.ts
|
|
27093
|
+
function slugify(name) {
|
|
27094
|
+
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
27095
|
+
}
|
|
27096
|
+
function mintId(name, existingIds = [], fallback = "template") {
|
|
27097
|
+
const base = slugify(name) || fallback;
|
|
27098
|
+
if (!existingIds.includes(base)) return base;
|
|
27099
|
+
let n = 2;
|
|
27100
|
+
while (existingIds.includes(`${base}-${n}`)) n++;
|
|
27101
|
+
return `${base}-${n}`;
|
|
27102
|
+
}
|
|
27103
|
+
function upsertById(list, entry) {
|
|
27104
|
+
const idx = list.findIndex((e) => e.id === entry.id);
|
|
27105
|
+
if (idx === -1) return [...list, entry];
|
|
27106
|
+
const next = [...list];
|
|
27107
|
+
next[idx] = entry;
|
|
27108
|
+
return next;
|
|
27109
|
+
}
|
|
27110
|
+
function removeById(list, id) {
|
|
27111
|
+
return list.filter((e) => e.id !== id);
|
|
27112
|
+
}
|
|
27113
|
+
function findByIdOrName(list, idOrName) {
|
|
27114
|
+
const byId = list.find((e) => e.id === idOrName);
|
|
27115
|
+
if (byId) return byId;
|
|
27116
|
+
const slug = slugify(idOrName);
|
|
27117
|
+
return list.find((e) => slugify(e.name) === slug);
|
|
27118
|
+
}
|
|
27119
|
+
|
|
27120
|
+
// src/core/settingsTemplates.ts
|
|
27121
|
+
function makeSettingsTemplateId(name, existingIds = []) {
|
|
27122
|
+
return mintId(name, existingIds, "settings");
|
|
27123
|
+
}
|
|
27124
|
+
function cloneCanvasColors(c) {
|
|
27125
|
+
if (!c) return c;
|
|
27126
|
+
return {
|
|
27127
|
+
...c,
|
|
27128
|
+
...c.dark ? { dark: { ...c.dark } } : {},
|
|
27129
|
+
...c.light ? { light: { ...c.light } } : {}
|
|
27130
|
+
};
|
|
27131
|
+
}
|
|
27132
|
+
function cloneSettings(s) {
|
|
27133
|
+
return {
|
|
27134
|
+
tradeDisplayFilter: s.tradeDisplayFilter,
|
|
27135
|
+
positionRenderStyle: s.positionRenderStyle,
|
|
27136
|
+
theme: s.theme,
|
|
27137
|
+
showTradeLevelsAlways: s.showTradeLevelsAlways,
|
|
27138
|
+
showPriceAxisCountdown: s.showPriceAxisCountdown,
|
|
27139
|
+
...s.canvasColors ? {
|
|
27140
|
+
canvasColors: {
|
|
27141
|
+
...s.canvasColors.dark ? { dark: { ...s.canvasColors.dark } } : {},
|
|
27142
|
+
...s.canvasColors.light ? { light: { ...s.canvasColors.light } } : {}
|
|
27143
|
+
}
|
|
27144
|
+
} : {},
|
|
27145
|
+
// Each group is one level deep, so a spread copy is a full copy.
|
|
27146
|
+
...s.statusLine ? { statusLine: { ...s.statusLine } } : {},
|
|
27147
|
+
...s.scales ? { scales: { ...s.scales } } : {},
|
|
27148
|
+
...s.canvas ? { canvas: { ...s.canvas } } : {},
|
|
27149
|
+
...s.barColorSource ? { barColorSource: s.barColorSource } : {}
|
|
27150
|
+
};
|
|
27151
|
+
}
|
|
27152
|
+
function captureSettingsTemplate(name, settings, opts = {}) {
|
|
27153
|
+
return {
|
|
27154
|
+
id: opts.id ?? makeSettingsTemplateId(name, opts.existingIds ?? []),
|
|
27155
|
+
name: name.trim(),
|
|
27156
|
+
settings: cloneSettings(settings),
|
|
27157
|
+
...opts.savedAt !== void 0 ? { savedAt: opts.savedAt } : {}
|
|
27158
|
+
};
|
|
27159
|
+
}
|
|
27160
|
+
function upsertSettingsTemplate(list, template) {
|
|
27161
|
+
return upsertById(list, template);
|
|
27162
|
+
}
|
|
27163
|
+
function removeSettingsTemplate(list, id) {
|
|
27164
|
+
return removeById(list, id);
|
|
27165
|
+
}
|
|
27166
|
+
function findSettingsTemplate(list, idOrName) {
|
|
27167
|
+
return findByIdOrName(list, idOrName);
|
|
27168
|
+
}
|
|
27169
|
+
function isGroup(v) {
|
|
27170
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
27171
|
+
}
|
|
27172
|
+
function sanitizeSettingsTemplates(input) {
|
|
27173
|
+
if (!Array.isArray(input)) return [];
|
|
27174
|
+
const out = [];
|
|
27175
|
+
for (const raw of input) {
|
|
27176
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
27177
|
+
const t = raw;
|
|
27178
|
+
if (typeof t.name !== "string" || t.name.trim() === "") continue;
|
|
27179
|
+
if (typeof t.settings !== "object" || t.settings === null) continue;
|
|
27180
|
+
const s = t.settings;
|
|
27181
|
+
out.push({
|
|
27182
|
+
id: typeof t.id === "string" && t.id !== "" ? t.id : makeSettingsTemplateId(
|
|
27183
|
+
t.name,
|
|
27184
|
+
out.map((x) => x.id)
|
|
27185
|
+
),
|
|
27186
|
+
name: t.name.trim(),
|
|
27187
|
+
settings: {
|
|
27188
|
+
tradeDisplayFilter: s.tradeDisplayFilter ?? "all",
|
|
27189
|
+
positionRenderStyle: s.positionRenderStyle ?? "line",
|
|
27190
|
+
theme: s.theme === "light" ? "light" : "dark",
|
|
27191
|
+
showTradeLevelsAlways: s.showTradeLevelsAlways === true,
|
|
27192
|
+
showPriceAxisCountdown: s.showPriceAxisCountdown === true,
|
|
27193
|
+
...typeof s.canvasColors === "object" && s.canvasColors !== null ? { canvasColors: s.canvasColors } : {},
|
|
27194
|
+
// Groups are carried through when present and dropped when not.
|
|
27195
|
+
// Absent is meaningful: it means "leave the chart as it is",
|
|
27196
|
+
// which is what an old template saved before these existed has
|
|
27197
|
+
// to mean if applying it is not to rearrange the chart.
|
|
27198
|
+
...isGroup(s.statusLine) ? { statusLine: s.statusLine } : {},
|
|
27199
|
+
...isGroup(s.scales) ? { scales: s.scales } : {},
|
|
27200
|
+
...isGroup(s.canvas) ? { canvas: s.canvas } : {},
|
|
27201
|
+
...s.barColorSource === "previousClose" || s.barColorSource === "open" ? { barColorSource: s.barColorSource } : {}
|
|
27202
|
+
},
|
|
27203
|
+
...typeof t.savedAt === "number" ? { savedAt: t.savedAt } : {}
|
|
27204
|
+
});
|
|
27205
|
+
}
|
|
27206
|
+
return out;
|
|
27207
|
+
}
|
|
27208
|
+
|
|
27092
27209
|
// src/ui/ChartSettingsDialog.ts
|
|
27093
27210
|
var TAB_LABELS = {
|
|
27094
27211
|
appearance: "Appearance",
|
|
@@ -27198,7 +27315,7 @@ var ChartSettingsDialog = class {
|
|
|
27198
27315
|
}
|
|
27199
27316
|
show(current, onChange, onReset) {
|
|
27200
27317
|
const wasVisible = this.isVisible;
|
|
27201
|
-
this.current = { ...current };
|
|
27318
|
+
this.current = { ...current, canvasColors: cloneCanvasColors(current.canvasColors) };
|
|
27202
27319
|
this.onChange = onChange;
|
|
27203
27320
|
this.onReset = onReset ?? null;
|
|
27204
27321
|
this.renderContent();
|
|
@@ -27258,7 +27375,7 @@ var ChartSettingsDialog = class {
|
|
|
27258
27375
|
}
|
|
27259
27376
|
// ── Private – emit ────────────────────────────────────────────────────────
|
|
27260
27377
|
emit() {
|
|
27261
|
-
this.onChange?.({ ...this.current });
|
|
27378
|
+
this.onChange?.({ ...this.current, canvasColors: cloneCanvasColors(this.current.canvasColors) });
|
|
27262
27379
|
}
|
|
27263
27380
|
// ── Private – panel theme ─────────────────────────────────────────────────
|
|
27264
27381
|
applyPanelTheme() {
|
|
@@ -28038,9 +28155,11 @@ var ChartSettingsDialog = class {
|
|
|
28038
28155
|
}
|
|
28039
28156
|
];
|
|
28040
28157
|
const makeSwatch = (def) => this.makeColorSwatch(current[def.field] ?? def.fallback, (hex) => {
|
|
28041
|
-
|
|
28042
|
-
|
|
28043
|
-
|
|
28158
|
+
const cc = this.current.canvasColors ?? {};
|
|
28159
|
+
this.current.canvasColors = {
|
|
28160
|
+
...cc,
|
|
28161
|
+
[themeKey]: { ...cc[themeKey] ?? {}, [def.field]: hex }
|
|
28162
|
+
};
|
|
28044
28163
|
this.emit();
|
|
28045
28164
|
});
|
|
28046
28165
|
for (const { label, s1, s2 } of rows) {
|
|
@@ -32039,34 +32158,6 @@ function formatMeasureDate(time, timeframe, timezone) {
|
|
|
32039
32158
|
return `${date} ${pick(cp, "hour")}:${pick(cp, "minute")}`;
|
|
32040
32159
|
}
|
|
32041
32160
|
|
|
32042
|
-
// src/core/templateStore.ts
|
|
32043
|
-
function slugify(name) {
|
|
32044
|
-
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
32045
|
-
}
|
|
32046
|
-
function mintId(name, existingIds = [], fallback = "template") {
|
|
32047
|
-
const base = slugify(name) || fallback;
|
|
32048
|
-
if (!existingIds.includes(base)) return base;
|
|
32049
|
-
let n = 2;
|
|
32050
|
-
while (existingIds.includes(`${base}-${n}`)) n++;
|
|
32051
|
-
return `${base}-${n}`;
|
|
32052
|
-
}
|
|
32053
|
-
function upsertById(list, entry) {
|
|
32054
|
-
const idx = list.findIndex((e) => e.id === entry.id);
|
|
32055
|
-
if (idx === -1) return [...list, entry];
|
|
32056
|
-
const next = [...list];
|
|
32057
|
-
next[idx] = entry;
|
|
32058
|
-
return next;
|
|
32059
|
-
}
|
|
32060
|
-
function removeById(list, id) {
|
|
32061
|
-
return list.filter((e) => e.id !== id);
|
|
32062
|
-
}
|
|
32063
|
-
function findByIdOrName(list, idOrName) {
|
|
32064
|
-
const byId = list.find((e) => e.id === idOrName);
|
|
32065
|
-
if (byId) return byId;
|
|
32066
|
-
const slug = slugify(idOrName);
|
|
32067
|
-
return list.find((e) => slugify(e.name) === slug);
|
|
32068
|
-
}
|
|
32069
|
-
|
|
32070
32161
|
// src/core/savedLayouts.ts
|
|
32071
32162
|
function makeLayoutId(name, existingIds = []) {
|
|
32072
32163
|
return mintId(name, existingIds, "layout");
|
|
@@ -32121,87 +32212,6 @@ function sanitizeLayouts(input) {
|
|
|
32121
32212
|
return out;
|
|
32122
32213
|
}
|
|
32123
32214
|
|
|
32124
|
-
// src/core/settingsTemplates.ts
|
|
32125
|
-
function makeSettingsTemplateId(name, existingIds = []) {
|
|
32126
|
-
return mintId(name, existingIds, "settings");
|
|
32127
|
-
}
|
|
32128
|
-
function cloneSettings(s) {
|
|
32129
|
-
return {
|
|
32130
|
-
tradeDisplayFilter: s.tradeDisplayFilter,
|
|
32131
|
-
positionRenderStyle: s.positionRenderStyle,
|
|
32132
|
-
theme: s.theme,
|
|
32133
|
-
showTradeLevelsAlways: s.showTradeLevelsAlways,
|
|
32134
|
-
showPriceAxisCountdown: s.showPriceAxisCountdown,
|
|
32135
|
-
...s.canvasColors ? {
|
|
32136
|
-
canvasColors: {
|
|
32137
|
-
...s.canvasColors.dark ? { dark: { ...s.canvasColors.dark } } : {},
|
|
32138
|
-
...s.canvasColors.light ? { light: { ...s.canvasColors.light } } : {}
|
|
32139
|
-
}
|
|
32140
|
-
} : {},
|
|
32141
|
-
// Each group is one level deep, so a spread copy is a full copy.
|
|
32142
|
-
...s.statusLine ? { statusLine: { ...s.statusLine } } : {},
|
|
32143
|
-
...s.scales ? { scales: { ...s.scales } } : {},
|
|
32144
|
-
...s.canvas ? { canvas: { ...s.canvas } } : {},
|
|
32145
|
-
...s.barColorSource ? { barColorSource: s.barColorSource } : {}
|
|
32146
|
-
};
|
|
32147
|
-
}
|
|
32148
|
-
function captureSettingsTemplate(name, settings, opts = {}) {
|
|
32149
|
-
return {
|
|
32150
|
-
id: opts.id ?? makeSettingsTemplateId(name, opts.existingIds ?? []),
|
|
32151
|
-
name: name.trim(),
|
|
32152
|
-
settings: cloneSettings(settings),
|
|
32153
|
-
...opts.savedAt !== void 0 ? { savedAt: opts.savedAt } : {}
|
|
32154
|
-
};
|
|
32155
|
-
}
|
|
32156
|
-
function upsertSettingsTemplate(list, template) {
|
|
32157
|
-
return upsertById(list, template);
|
|
32158
|
-
}
|
|
32159
|
-
function removeSettingsTemplate(list, id) {
|
|
32160
|
-
return removeById(list, id);
|
|
32161
|
-
}
|
|
32162
|
-
function findSettingsTemplate(list, idOrName) {
|
|
32163
|
-
return findByIdOrName(list, idOrName);
|
|
32164
|
-
}
|
|
32165
|
-
function isGroup(v) {
|
|
32166
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
32167
|
-
}
|
|
32168
|
-
function sanitizeSettingsTemplates(input) {
|
|
32169
|
-
if (!Array.isArray(input)) return [];
|
|
32170
|
-
const out = [];
|
|
32171
|
-
for (const raw of input) {
|
|
32172
|
-
if (typeof raw !== "object" || raw === null) continue;
|
|
32173
|
-
const t = raw;
|
|
32174
|
-
if (typeof t.name !== "string" || t.name.trim() === "") continue;
|
|
32175
|
-
if (typeof t.settings !== "object" || t.settings === null) continue;
|
|
32176
|
-
const s = t.settings;
|
|
32177
|
-
out.push({
|
|
32178
|
-
id: typeof t.id === "string" && t.id !== "" ? t.id : makeSettingsTemplateId(
|
|
32179
|
-
t.name,
|
|
32180
|
-
out.map((x) => x.id)
|
|
32181
|
-
),
|
|
32182
|
-
name: t.name.trim(),
|
|
32183
|
-
settings: {
|
|
32184
|
-
tradeDisplayFilter: s.tradeDisplayFilter ?? "all",
|
|
32185
|
-
positionRenderStyle: s.positionRenderStyle ?? "line",
|
|
32186
|
-
theme: s.theme === "light" ? "light" : "dark",
|
|
32187
|
-
showTradeLevelsAlways: s.showTradeLevelsAlways === true,
|
|
32188
|
-
showPriceAxisCountdown: s.showPriceAxisCountdown === true,
|
|
32189
|
-
...typeof s.canvasColors === "object" && s.canvasColors !== null ? { canvasColors: s.canvasColors } : {},
|
|
32190
|
-
// Groups are carried through when present and dropped when not.
|
|
32191
|
-
// Absent is meaningful: it means "leave the chart as it is",
|
|
32192
|
-
// which is what an old template saved before these existed has
|
|
32193
|
-
// to mean if applying it is not to rearrange the chart.
|
|
32194
|
-
...isGroup(s.statusLine) ? { statusLine: s.statusLine } : {},
|
|
32195
|
-
...isGroup(s.scales) ? { scales: s.scales } : {},
|
|
32196
|
-
...isGroup(s.canvas) ? { canvas: s.canvas } : {},
|
|
32197
|
-
...s.barColorSource === "previousClose" || s.barColorSource === "open" ? { barColorSource: s.barColorSource } : {}
|
|
32198
|
-
},
|
|
32199
|
-
...typeof t.savedAt === "number" ? { savedAt: t.savedAt } : {}
|
|
32200
|
-
});
|
|
32201
|
-
}
|
|
32202
|
-
return out;
|
|
32203
|
-
}
|
|
32204
|
-
|
|
32205
32215
|
// src/core/indicatorTemplates.ts
|
|
32206
32216
|
function makeTemplateId(name, existingIds = []) {
|
|
32207
32217
|
return mintId(name, existingIds);
|
|
@@ -39352,7 +39362,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
39352
39362
|
this.tradeDisplayFilter = config.tradeDisplayFilter;
|
|
39353
39363
|
}
|
|
39354
39364
|
if (config.canvasColors) {
|
|
39355
|
-
this.settingsCanvasColors = config.canvasColors;
|
|
39365
|
+
this.settingsCanvasColors = cloneCanvasColors(config.canvasColors);
|
|
39356
39366
|
}
|
|
39357
39367
|
this.recomputeRenderStyle();
|
|
39358
39368
|
this.showBidAskLines = config.showBidAskLines ?? false;
|
|
@@ -41877,7 +41887,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
41877
41887
|
* like the dialog's own picks, and `stateChange` fires.
|
|
41878
41888
|
*/
|
|
41879
41889
|
setCanvasColors(colors) {
|
|
41880
|
-
this.settingsCanvasColors = colors ?? {};
|
|
41890
|
+
this.settingsCanvasColors = cloneCanvasColors(colors ?? {});
|
|
41881
41891
|
this.setTheme(this.themeName);
|
|
41882
41892
|
return this;
|
|
41883
41893
|
}
|
|
@@ -42292,7 +42302,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
42292
42302
|
})),
|
|
42293
42303
|
positionRenderStyle: this.baseRenderStyle(),
|
|
42294
42304
|
tradeDisplayFilter: this.tradeDisplayFilter,
|
|
42295
|
-
canvasColors: Object.keys(this.settingsCanvasColors).length > 0 ?
|
|
42305
|
+
canvasColors: Object.keys(this.settingsCanvasColors).length > 0 ? cloneCanvasColors(this.settingsCanvasColors) : void 0,
|
|
42296
42306
|
tfcEnabled: this.tfcActive,
|
|
42297
42307
|
viewport: this.getViewportTimestamps(),
|
|
42298
42308
|
priceScale: this.priceScaleFactor !== 1 || this.pricePanOffset !== 0 ? { factor: this.priceScaleFactor, panOffset: this.pricePanOffset } : void 0,
|
|
@@ -42395,7 +42405,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
42395
42405
|
this.tradeDisplayFilter = state.tradeDisplayFilter;
|
|
42396
42406
|
}
|
|
42397
42407
|
if (state.canvasColors) {
|
|
42398
|
-
this.settingsCanvasColors = state.canvasColors;
|
|
42408
|
+
this.settingsCanvasColors = cloneCanvasColors(state.canvasColors);
|
|
42399
42409
|
}
|
|
42400
42410
|
if (state.tfcEnabled !== void 0 && this.tfcEnabled) {
|
|
42401
42411
|
this.tfcActive = state.tfcEnabled;
|
|
@@ -44559,7 +44569,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
44559
44569
|
theme: this.themeName,
|
|
44560
44570
|
showTradeLevelsAlways: this.showTradeLevelsAlways,
|
|
44561
44571
|
showPriceAxisCountdown: this.showPriceAxisCountdown,
|
|
44562
|
-
canvasColors:
|
|
44572
|
+
canvasColors: cloneCanvasColors(this.settingsCanvasColors),
|
|
44563
44573
|
// The resolved sets, not the sparse ones. A template is a thing
|
|
44564
44574
|
// the user means to reproduce exactly; saving the gaps would make
|
|
44565
44575
|
// it reproduce whatever the *next* chart's defaults happen to be.
|
|
@@ -44583,7 +44593,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
44583
44593
|
}
|
|
44584
44594
|
this.positionRenderStyle = settings.positionRenderStyle;
|
|
44585
44595
|
if (settings.canvasColors) {
|
|
44586
|
-
this.settingsCanvasColors = settings.canvasColors;
|
|
44596
|
+
this.settingsCanvasColors = cloneCanvasColors(settings.canvasColors);
|
|
44587
44597
|
}
|
|
44588
44598
|
if (this.showTradeLevelsAlways !== settings.showTradeLevelsAlways) {
|
|
44589
44599
|
this.showTradeLevelsAlways = settings.showTradeLevelsAlways;
|