Этикетки на детали
Перетащите сюда файл модели .b3d или нажмите, чтобы выбрать. На этикетке: позиция (номер детали), деталь, размер, материал, модуль, заказ и дата, схема кромки, QR-код или штрихкод для станка. Рулон (58×40, 100×50…) или лист A4 (24, 21, 12, 8 шт). Одна этикетка на деталь или на позицию с количеством.
'); return h.join('\n'); } // ---------- Нумерация: группы одинаковых деталей (те же правила, что в проверке «Нумерация деталей») ---------- // Вставляется внутрь ядра MC (копия из «ПРОВЕРКИ ОБЩЕЙ»), пользуется его функциями (vec, V, dot, num, r1, words, hasToken, notFurniture). function partGroups(S, C, perModule) { var nskip = words(C.numSkip); var sheet = S.panels.filter(function (p) { return !p.hidden && p.ath >= 2 && p.ath <= 50 && !notFurniture(p) && !hasToken(p.mat + ' ' + p.name, nskip); }); var sigCache = new Map(), TOL = Math.max(0.0001, Number(C.numTol) || 0.01); var sigOf = function (p) { if (sigCache.has(p)) return sigCache.get(p); var W = p.w, H = p.h, feats = []; p.elems.forEach(function (e) { if (e.butt) feats.push(['e' + num(e.butt, 1), (e.p1[0] + e.p2[0]) / 2 - p.lmin[0], (e.p1[1] + e.p2[1]) / 2 - p.lmin[1]]); }); var zm = (p.z0 + p.z1) / 2; p.hi.forEach(function (i) { var h = S.holes[i], l = vec(p.ref.GlobalToObject(V(h.p[0], h.p[1], h.p[2]))); var face = Math.abs(dot(h.d, p.az)) > 0.8 ? (h.depth >= p.ath - 0.5 ? 'S' : l[2] < zm ? 'A' : 'B') : 'T'; feats.push(['h' + num(h.dia, 1) + face, l[0] - p.lmin[0], l[1] - p.lmin[1]]); }); if (H > W + 0.5) { feats = feats.map(function (f) { return [f[0], f[2], W - f[1]]; }); var t = W; W = H; H = t; } var s = { W: W, H: H, feats: feats }; sigCache.set(p, s); return s; }; var swapFace = function (c) { return c.replace(/A$/, '#').replace(/B$/, 'A').replace(/#$/, 'B'); }; var same = function (a, b) { var x = sigOf(a), y = sigOf(b); if (Math.abs(x.W - y.W) > TOL || Math.abs(x.H - y.H) > TOL || Math.abs(a.ath - b.ath) > TOL || a.mat.toLowerCase() !== b.mat.toLowerCase()) return false; if (x.feats.length !== y.feats.length) return false; var W = y.W, H = y.H, f = y.feats; var variants = [f, f.map(function (q) { return [q[0], W - q[1], H - q[2]]; }), f.map(function (q) { return [swapFace(q[0]), W - q[1], q[2]]; }), f.map(function (q) { return [swapFace(q[0]), q[1], H - q[2]]; })]; return variants.some(function (v) { var used = []; return x.feats.every(function (q) { for (var i = 0; i < v.length; i++) if (!used[i] && v[i][0] === q[0] && Math.abs(v[i][1] - q[1]) <= TOL && Math.abs(v[i][2] - q[2]) <= TOL) { used[i] = true; return true; } return false; }); }); }; // группы в порядке первой встречи (порядок деталей - как в структуре модели); одинаковые - ещё и с одинаковым названием var groups = []; sheet.forEach(function (p) { var nk = p.name.trim().toLowerCase().replace(/\s+/g, ' '); for (var i = 0; i < groups.length; i++) { var g = groups[i]; if (g.name === nk && (!perModule || g.mod === p.mod) && same(g.parts[0], p)) { g.parts.push(p); return; } } groups.push({ name: nk, mod: p.mod, parts: [p] }); }); return { groups: groups, skipped: S.panels.length - sheet.length }; } return { partGroups: partGroups, snapshot: snapshot, run: run, report: report, cncRenames: cncRenames, CHECKS: CHECKS, DEFAULTS: DEFAULTS, LOADS: LOADS, LEVELS: LEVELS, MACHINES: MACHINES }; })(); // QR-код (байтовый режим, коррекция M, версии 1-25) - для страницы этикеток. Только ES5 и ASCII (вставляется через toString). // text -> { size: N, m: [[0/1 x N] x N] } (m[y][x], 1 - тёмный модуль) или null, если текст слишком длинный. function werdanQR(text) { var ECC = [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28]; var BLK = [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21]; var s = unescape(encodeURIComponent(String(text))), data = [], i, j; for (i = 0; i < s.length; i++) data.push(s.charCodeAt(i) & 255); function rawModules(v) { var r = (16 * v + 128) * v + 64; if (v >= 2) { var na = Math.floor(v / 7) + 2; r -= (25 * na - 10) * na - 55; if (v >= 7) r -= 36; } return r; } function dataCw(v) { return Math.floor(rawModules(v) / 8) - ECC[v] * BLK[v]; } var ver = 0; for (var v = 1; v < ECC.length; v++) if (4 + (v < 10 ? 8 : 16) + data.length * 8 <= dataCw(v) * 8) { ver = v; break; } if (!ver) return null; // биты: режим 0100, длина, данные, конец, добивка var bits = []; function put(val, n) { for (var k = n - 1; k >= 0; k--) bits.push((val >>> k) & 1); } put(4, 4); put(data.length, ver < 10 ? 8 : 16); for (i = 0; i < data.length; i++) put(data[i], 8); var cap = dataCw(ver) * 8; put(0, Math.min(4, cap - bits.length)); put(0, (8 - bits.length % 8) % 8); for (var pad = 0xEC; bits.length < cap; pad ^= 0xEC ^ 0x11) put(pad, 8); var cw = []; for (i = 0; i < bits.length; i += 8) { var b = 0; for (j = 0; j < 8; j++) b = (b << 1) | bits[i + j]; cw.push(b); } // Рида-Соломона function mul(x, y) { var z = 0; for (var k = 7; k >= 0; k--) { z = (z << 1) ^ ((z >>> 7) * 0x11D); z ^= ((y >>> k) & 1) * x; } return z; } var deg = ECC[ver], div = [], root = 1; for (i = 0; i < deg - 1; i++) div.push(0); div.push(1); for (i = 0; i < deg; i++) { for (j = 0; j < deg; j++) { div[j] = mul(div[j], root); if (j + 1 < deg) div[j] ^= div[j + 1]; } root = mul(root, 2); } function rem(d) { var r = []; for (var k = 0; k < deg; k++) r.push(0); for (var q = 0; q < d.length; q++) { var f = d[q] ^ r.shift(); r.push(0); for (var t = 0; t < deg; t++) r[t] ^= mul(div[t], f); } return r; } var nb = BLK[ver], raw = Math.floor(rawModules(ver) / 8), nShort = nb - raw % nb, shortLen = Math.floor(raw / nb), blocks = [], pos = 0; for (i = 0; i < nb; i++) { var dat = cw.slice(pos, pos + shortLen - deg + (i < nShort ? 0 : 1)); pos += dat.length; var ec = rem(dat); if (i < nShort) dat.push(0); blocks.push(dat.concat(ec)); } var all = []; for (i = 0; i < blocks[0].length; i++) for (j = 0; j < nb; j++) if (i !== shortLen - deg || j >= nShort) all.push(blocks[j][i]); // матрица var N = ver * 4 + 17, m = [], fn = []; for (i = 0; i < N; i++) { m.push([]); fn.push([]); for (j = 0; j < N; j++) { m[i].push(0); fn[i].push(false); } } function setF(x, y, d) { m[y][x] = d ? 1 : 0; fn[y][x] = true; } for (i = 0; i < N; i++) { setF(6, i, i % 2 === 0); setF(i, 6, i % 2 === 0); } function finder(x, y) { for (var dy = -4; dy <= 4; dy++) for (var dx = -4; dx <= 4; dx++) { var d = Math.max(Math.abs(dx), Math.abs(dy)), xx = x + dx, yy = y + dy; if (xx >= 0 && xx < N && yy >= 0 && yy < N) setF(xx, yy, d !== 2 && d !== 4); } } finder(3, 3); finder(N - 4, 3); finder(3, N - 4); var al = []; if (ver > 1) { var na = Math.floor(ver / 7) + 2, step = Math.ceil((ver * 4 + 4) / (na * 2 - 2)) * 2; al = [6]; for (var p = N - 7; al.length < na; p -= step) al.splice(1, 0, p); } for (i = 0; i < al.length; i++) for (j = 0; j < al.length; j++) { if (i === 0 && j === 0 || i === 0 && j === al.length - 1 || i === al.length - 1 && j === 0) continue; for (var ay = -2; ay <= 2; ay++) for (var ax = -2; ax <= 2; ax++) setF(al[i] + ax, al[j] + ay, Math.max(Math.abs(ax), Math.abs(ay)) !== 1); } function format(mask) { var d = (0 << 3) | mask, r = d; // уровень M = 00 for (var k = 0; k < 10; k++) r = (r << 1) ^ ((r >>> 9) * 0x537); var fb = ((d << 10) | r) ^ 0x5412, bit = function (n) { return (fb >>> n) & 1; }; for (k = 0; k <= 5; k++) setF(8, k, bit(k)); setF(8, 7, bit(6)); setF(8, 8, bit(7)); setF(7, 8, bit(8)); for (k = 9; k < 15; k++) setF(14 - k, 8, bit(k)); for (k = 0; k < 8; k++) setF(N - 1 - k, 8, bit(k)); for (k = 8; k < 15; k++) setF(8, N - 15 + k, bit(k)); setF(8, N - 8, 1); } format(0); if (ver >= 7) { var r2 = ver; for (i = 0; i < 12; i++) r2 = (r2 << 1) ^ ((r2 >>> 11) * 0x1F25); var vb = (ver << 12) | r2; for (i = 0; i < 18; i++) { var bt = (vb >>> i) & 1, a = N - 11 + i % 3, c = Math.floor(i / 3); setF(a, c, bt); setF(c, a, bt); } } var bi = 0; for (var right = N - 1; right >= 1; right -= 2) { if (right === 6) right = 5; for (var vert = 0; vert < N; vert++) for (j = 0; j < 2; j++) { var x = right - j, up = ((right + 1) & 2) === 0, y = up ? N - 1 - vert : vert; if (!fn[y][x] && bi < all.length * 8) { m[y][x] = (all[bi >>> 3] >>> (7 - (bi & 7))) & 1; bi++; } } } function maskOn(k, x, y) { switch (k) { case 0: return (x + y) % 2 === 0; case 1: return y % 2 === 0; case 2: return x % 3 === 0; case 3: return (x + y) % 3 === 0; case 4: return (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0; case 5: return x * y % 2 + x * y % 3 === 0; case 6: return (x * y % 2 + x * y % 3) % 2 === 0; default: return ((x + y) % 2 + x * y % 3) % 2 === 0; } } function applyMask(k) { for (var yy = 0; yy < N; yy++) for (var xx = 0; xx < N; xx++) if (!fn[yy][xx] && maskOn(k, xx, yy)) m[yy][xx] ^= 1; } function penalty() { var sc = 0, x, y, run, dark = 0; var line = function (get) { for (var a = 0; a < N; a++) { run = 1; for (var b = 1; b <= N; b++) { if (b < N && get(a, b) === get(a, b - 1)) run++; else { if (run >= 5) sc += run - 2; run = 1; } } for (b = 0; b + 11 <= N; b++) { var s1 = '', k2; for (k2 = 0; k2 < 11; k2++) s1 += get(a, b + k2); if (s1 === '10111010000' || s1 === '00001011101') sc += 40; } } }; line(function (a, b) { return m[a][b]; }); line(function (a, b) { return m[b][a]; }); for (y = 0; y < N - 1; y++) for (x = 0; x < N - 1; x++) { var c0 = m[y][x]; if (c0 === m[y][x + 1] && c0 === m[y + 1][x] && c0 === m[y + 1][x + 1]) sc += 3; } for (y = 0; y < N; y++) for (x = 0; x < N; x++) dark += m[y][x]; sc += (Math.ceil(Math.abs(dark * 20 - N * N * 10) / (N * N)) - 1) * 10; return sc; } var best = 0, bestSc = Infinity; for (var k = 0; k < 8; k++) { applyMask(k); format(k); var sc = penalty(); if (sc < bestSc) { bestSc = sc; best = k; } applyMask(k); } applyMask(best); format(best); return { size: N, m: m, ver: ver }; } // Штрихкод Code 128 (наборы B и C) - для станков. Только ES5 и ASCII (вставляется через toString). // text -> { w: [ширины полос по очереди: штрих, пробел, штрих, …], n: всего модулей, text: что закодировано (латиница) } function werdanC128(text) { var P = ('212222 222122 222221 121223 121322 131222 122213 122312 132212 221213 221312 231212 112232 122132 122231 113222 123122 123221 223211 221132 ' + '221231 213212 223112 312131 311222 321122 321221 312212 322112 322211 212123 212321 232121 111323 131123 131321 112313 132113 132311 211313 ' + '231113 231311 112133 112331 132131 113123 113321 133121 313121 211331 231131 213113 213311 213131 311123 311321 331121 312113 312311 332111 ' + '314111 221411 431111 111224 111422 121124 121421 141122 141221 112214 112412 122114 122411 142112 142211 241211 221114 413111 241112 134111 ' + '111242 121142 121241 114212 124112 124211 411212 421112 421211 212141 214121 412121 111143 111341 131141 114113 114311 411113 411311 113141 ' + '114131 311141 411131 211412 211214 211232').split(' '); var s = werdanTranslit(text).replace(/[^\x20-\x7E]/g, '?'); var codes = [], i = 0, set = ''; function digitsAt(k) { var n = 0; while (k + n < s.length && s.charCodeAt(k + n) >= 48 && s.charCodeAt(k + n) <= 57) n++; return n; } while (i < s.length) { var dn = digitsAt(i); // набор C (пары цифр) - для длинных цифровых участков: в начале/конце от 4 цифр, в середине от 6 var useC = dn >= (i === 0 || i + dn === s.length ? 4 : 6); if (useC) { if (dn % 2) { if (set !== 'B') { codes.push(set ? 100 : 104); set = 'B'; } codes.push(s.charCodeAt(i) - 32); i++; dn--; } if (set !== 'C') { codes.push(set ? 99 : 105); set = 'C'; } for (var e = i + dn; i < e; i += 2) codes.push(Number(s.substr(i, 2))); } else { if (set !== 'B') { codes.push(set ? 100 : 104); set = 'B'; } codes.push(s.charCodeAt(i) - 32); i++; } } if (!codes.length) { codes.push(104); } var sum = codes[0]; for (i = 1; i < codes.length; i++) sum += codes[i] * i; codes.push(sum % 103); var w = [], n = 0; codes.forEach(function (c) { for (var k = 0; k < 6; k++) { var v = Number(P[c].charAt(k)); w.push(v); n += v; } }); [2, 3, 3, 1, 1, 1, 2].forEach(function (v) { w.push(v); n += v; }); // стоп return { w: w, n: n, text: s }; } // русские буквы - латиницей (штрихкод и программы станков понимают только латиницу) function werdanTranslit(t) { var a = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя', b = ['a', 'b', 'v', 'g', 'd', 'e', 'e', 'zh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'ts', 'ch', 'sh', 'sch', '', 'y', '', 'e', 'yu', 'ya']; return String(t).replace(/[Ѐ-ӿ]/g, function (ch) { var lo = ch.toLowerCase(), k = a.indexOf(lo); if (k < 0) return '?'; var r = b[k]; return ch !== lo && r ? r.charAt(0).toUpperCase() + r.substring(1) : r; }).replace(/[×]/g, 'x').replace(/[–—]/g, '-'); } // Страница этикеток (выполняется в браузере). Только ES5; русские строки допустимы - вся страница потом переводится в \uXXXX. // D = { title, date, labels: [{pos, name, mod, w, h, t, mat, e:[верх, право, низ, лево], fig, qty, n}] } function werdanLabels(D) { var FORMATS = [ { id: 'r58x40', name: 'Рулон 58 × 40', w: 58, h: 40 }, { id: 'r58x30', name: 'Рулон 58 × 30', w: 58, h: 30 }, { id: 'r75x50', name: 'Рулон 75 × 50', w: 75, h: 50 }, { id: 'r100x50', name: 'Рулон 100 × 50', w: 100, h: 50 }, { id: 'r100x70', name: 'Рулон 100 × 70', w: 100, h: 70 }, { id: 'own', name: 'Рулон - свой размер', w: 0, h: 0 }, { id: 'a24', name: 'A4, 24 шт (70 × 37)', w: 70, h: 37, cols: 3, rows: 8 }, { id: 'a21', name: 'A4, 21 шт (70 × 42,3)', w: 70, h: 42.3, cols: 3, rows: 7 }, { id: 'a12', name: 'A4, 12 шт (105 × 48)', w: 105, h: 48, cols: 2, rows: 6 }, { id: 'a8', name: 'A4, 8 шт (105 × 74)', w: 105, h: 74, cols: 2, rows: 4 } ]; // code - вид кода (qr, bar - штрихкод Code 128, both, none); data - что в коде; tpl - свой шаблон var DATA = [ { id: 'short', name: 'Для людей: заказ, позиция, деталь, размер' }, { id: 'full', name: 'Для людей: всё с этикетки' }, { id: 'giblab', name: 'GibLab / .project: код детали (позиция или обозначение)' }, { id: 'prog', name: 'Имя программы: заказ_позиция' }, { id: 'own', name: 'Свой шаблон…' } ]; var FIELDS = '{заказ} {поз} {код} {деталь} {модуль} {материал} {ш} {в} {т} {кол} {n}'; var S = { fmt: 'r58x40', ow: 58, oh: 40, each: 1, code: 'qr', data: 'short', tpl: '{заказ}_{поз}' }; try { var sv = JSON.parse(localStorage.getItem('werdanLabels') || '{}'); for (var k in sv) if (S.hasOwnProperty(k)) S[k] = sv[k]; } catch (e) { } function save() { try { localStorage.setItem('werdanLabels', JSON.stringify(S)); } catch (e) { } } function esc(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } function n1(v) { var r = Math.round(v * 10) / 10; return String(r).replace('.', ','); } function fmtOf() { for (var i = 0; i < FORMATS.length; i++) if (FORMATS[i].id === S.fmt) { var f = FORMATS[i]; if (f.id === 'own') return { id: 'own', w: Math.max(20, Number(S.ow) || 58), h: Math.max(15, Number(S.oh) || 40) }; return f; } return FORMATS[0]; } function qrSvg(text, size) { var q = werdanQR(text); if (!q) return ''; var Q = 2, N = q.size + Q * 2, d = ''; for (var y = 0; y < q.size; y++) for (var x = 0; x < q.size; x++) if (q.m[y][x]) d += 'M' + (x + Q) + ' ' + (y + Q) + 'h1v1h-1z'; return '' + ''; } // схема кромки: прямоугольник детали в пропорции, кромленые стороны - толстой линией, рядом толщина function edgeSvg(L, bw, bh) { var pad = 3.2, aw = bw - pad * 2, ah = bh - pad * 2; if (aw <= 2 || ah <= 2) return ''; var k = Math.min(aw / Math.max(L.w, 1), ah / Math.max(L.h, 1)), rw = Math.max(L.w * k, 3), rh = Math.max(L.h * k, 3); var x0 = (bw - rw) / 2, y0 = (bh - rh) / 2, x1 = x0 + rw, y1 = y0 + rh, s = ''; s += ''; var side = [[x0, y0, x1, y0], [x1, y0, x1, y1], [x0, y1, x1, y1], [x0, y0, x0, y1]]; var lab = [[(x0 + x1) / 2, y0 - 0.7, 'middle'], [x1 + 0.6, (y0 + y1) / 2 + 0.8, 'start'], [(x0 + x1) / 2, y1 + 2.4, 'middle'], [x0 - 0.6, (y0 + y1) / 2 + 0.8, 'end']]; var any = false; for (var i = 0; i < 4; i++) if (L.e[i]) { any = true; var c = side[i]; s += ''; s += '' + n1(L.e[i]) + ''; } if (!any) s += '' + (L.fig ? 'кромка фигурная' : 'без кромки') + ''; else if (L.fig) s += '+ фигурная'; return '' + s + ''; } function codeText(L, idx) { var dims = n1(L.w) + 'x' + n1(L.h) + 'x' + n1(L.t); if (S.data === 'short') return D.title + ' | поз. ' + (L.pos || '-') + ' | ' + L.name + ' | ' + dims; if (S.data === 'full') { var e = ['верх', 'право', 'низ', 'лево'], ed = []; for (var i = 0; i < 4; i++) if (L.e[i]) ed.push(e[i] + ' ' + n1(L.e[i])); return 'Заказ: ' + D.title + '\nМодуль: ' + L.mod + '\nПоз. ' + (L.pos || '-') + ': ' + L.name + '\n' + dims + '\n' + L.mat + '\nКромка: ' + (ed.length ? ed.join(', ') : 'нет') + (L.fig ? ', фигурная' : ''); } var tpl = S.data === 'giblab' ? '{код}' : S.data === 'prog' ? '{заказ}_{поз}' : String(S.tpl || '{поз}'); var v = { 'заказ': D.title, 'поз': L.pos, 'код': L.code || L.pos, 'деталь': L.name, 'модуль': L.mod, 'материал': L.mat, 'ш': String(L.w), 'в': String(L.h), 'т': String(L.t), 'кол': String(L.qty), 'n': String(idx) }; return tpl.replace(/\{([^}]+)\}/g, function (m0, k) { k = k.toLowerCase(); return v.hasOwnProperty(k) ? v[k] : m0; }); } function barSvg(text, bw, bh) { var b = werdanC128(text), Q = 10, mw = bw / (b.n + Q * 2), cap = bh >= 7 ? 2 : 0; if (mw < 0.17) return '
штрихкод не помещается - выберите код короче
'; var x = Q, s = ''; for (var i = 0; i < b.w.length; i++) { if (i % 2 === 0) s += ''; x += b.w[i]; } if (cap) s += '' + esc(b.text) + ''; return '' + s + ''; } function label(L, F, copy, copies, idx) { var W = F.w, H0 = F.h, P = 1.5, gap = 1; // шапка: название модели (объект, телефон) крупно во всю ширину, шрифт уменьшается под длину var hf = Math.max(2.4, Math.min(H0 * 0.11, (W - P * 2) / (Math.max(String(D.title).length, 1) * 0.64))); var hdr = hf * 1.2 + 0.8, top = P + hdr; var hasQr = S.code === 'qr' || S.code === 'both', hasBar = S.code === 'bar' || S.code === 'both'; var barH = hasBar ? Math.max(5, H0 * 0.17) : 0, H = H0 - hdr - (barH ? barH + gap : 0), txt = S.code === 'none' ? '' : codeText(L, idx); var c = Math.min(W * 0.36, H * 0.5); // правая колонка: QR сверху, схема кромки под ним var qrH = hasQr ? c : 0, restH = H - P * 2 - qrH - (qrH ? gap : 0); var schemeRight = restH >= c * 0.45 || !qrH, tw = W - P * 2 - (qrH || schemeRight ? c + gap : 0); var schemeH = schemeRight ? (qrH ? restH : H - P * 2) : Math.max(H * 0.32, 8); var u = Math.min(H0 / 40, W / 58); var h = '
'; h += '
' + esc(D.title) + '
'; h += '
'; h += '
' + esc(L.pos || '—') + (L.qty > 1 && !S.each ? ' × ' + L.qty + '' : '') + (S.each && copies > 1 ? ' ' + copy + '/' + copies + '' : '') + '
'; h += '
' + esc(L.name) + '
'; h += '
' + n1(L.w) + ' × ' + n1(L.h) + ' × ' + n1(L.t) + '
'; h += '
' + esc(L.mat) + '
'; h += '
' + esc(L.mod) + '
'; h += '
' + esc(D.date) + '
'; h += '
'; if (qrH) h += '
' + qrSvg(txt, c) + '
'; var bot = P + (barH ? barH + gap : 0); if (schemeRight) h += '
' + edgeSvg(L, c, schemeH) + '
'; else h += '
' + edgeSvg(L, tw, schemeH) + '
'; if (barH) h += '
' + barSvg(txt, W - P * 2, barH) + '
'; return h + '
'; } function render() { var F = fmtOf(), list = [], idx = 0; D.labels.forEach(function (L) { if (S.each) for (var i = 1; i <= L.qty; i++) list.push(label(L, F, i, L.qty, ++idx)); else list.push(label(L, F, 1, 1, ++idx)); }); var css = F.cols ? '@page{size:210mm 297mm;margin:0}' : '@page{size:' + F.w + 'mm ' + F.h + 'mm;margin:0}'; document.getElementById('pg').textContent = css; var out = ''; if (F.cols) { var per = F.cols * F.rows, mx = (210 - F.cols * F.w) / 2, my = (297 - F.rows * F.h) / 2; for (var s = 0; s < list.length; s += per) { out += '
' + list.slice(s, s + per).join('') + '
'; } } else out = list.map(function (x) { return '
' + x + '
'; }).join(''); document.getElementById('out').innerHTML = out; document.getElementById('cnt').textContent = 'Этикеток: ' + list.length + (F.cols ? ', листов: ' + Math.ceil(list.length / (F.cols * F.rows)) : ''); document.getElementById('own').style.display = F.id === 'own' ? '' : 'none'; document.getElementById('tplw').style.display = S.data === 'own' && S.code !== 'none' ? '' : 'none'; document.getElementById('data').style.display = S.code === 'none' ? 'none' : ''; } var bar = '' + esc(D.title) + ' ' + ' ширина × высота мм' + ' ' + ' ' + ' ' + ' шаблон ' + esc(FIELDS) + '' + ' '; document.getElementById('bar').innerHTML = bar; var $ = function (id) { return document.getElementById(id); }; $('fmt').value = S.fmt; $('ow').value = S.ow; $('oh').value = S.oh; $('each').value = S.each ? '1' : '0'; $('code').value = S.code; $('data').value = S.data; $('tpl').value = S.tpl; $('fmt').onchange = function () { S.fmt = this.value; save(); render(); }; $('ow').onchange = function () { S.ow = Number(this.value) || 58; save(); render(); }; $('oh').onchange = function () { S.oh = Number(this.value) || 40; save(); render(); }; $('each').onchange = function () { S.each = this.value === '1' ? 1 : 0; save(); render(); }; $('code').onchange = function () { S.code = this.value; save(); render(); }; $('data').onchange = function () { S.data = this.value; save(); render(); }; $('tpl').onchange = function () { S.tpl = this.value; save(); render(); }; $('pr').onclick = function () { window.print(); }; render(); } '; // заголовок окна - через &#; (страница целиком ASCII, кодировка файла неважна) page = page.replace(/([^<]*)<\/title>/, function (m0, t) { return '<title>' + t.replace(/[^\x00-\x7E]/g, function (ch) { return '&#' + ch.charCodeAt(0) + ';'; }) + ''; }); page = asciiJs(page); return { page: page, labels: labels.length, parts: total }; }