Only zero is empty, and the last day is worth reading
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div class="code-generator">
|
||||
<div class="no-print">
|
||||
<div class="page-header">
|
||||
<h1>Barcode / QR Generator</h1>
|
||||
<router-link to="/tools" class="btn btn-secondary">Back to Tech Tools</router-link>
|
||||
</div>
|
||||
<div class="page-header no-print">
|
||||
<h1>Barcode / QR Generator</h1>
|
||||
<router-link to="/tools" class="btn btn-secondary">Back to Tech Tools</router-link>
|
||||
</div>
|
||||
|
||||
<div class="controls card">
|
||||
<div class="workspace">
|
||||
<div class="options no-print">
|
||||
<div class="controls card">
|
||||
<!-- What to encode -->
|
||||
<div class="control-row">
|
||||
<label>
|
||||
@@ -285,33 +286,52 @@
|
||||
{{ overlong.length }} row(s) could not be encoded as CODE128 or were empty:
|
||||
{{ overlong.slice(0, 3).join(', ') }}{{ overlong.length > 3 ? ' ...' : '' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview doubles as the print surface: what is on screen is what prints. -->
|
||||
<div class="sheet">
|
||||
<div
|
||||
v-for="item in visible"
|
||||
:key="item.index"
|
||||
class="label"
|
||||
:class="labelClasses(item.page)"
|
||||
>
|
||||
<img v-if="showPicture(item.page) && pictureposition === 'behind'"
|
||||
:src="pictureUrl" class="picture-behind" alt="" />
|
||||
<div class="content">
|
||||
<div v-if="showPicture(item.page) && pictureposition !== 'behind'" class="picturebox">
|
||||
<img :src="pictureUrl" class="picture-img" alt="" />
|
||||
</div>
|
||||
<div class="codegroup">
|
||||
<div v-if="layoutFor(item.page) !== 'textonly'" class="codebox">
|
||||
<img v-if="images[item.index]" :src="images[item.index]" class="code-img" alt="" />
|
||||
</div>
|
||||
<div v-if="layoutFor(item.page) !== 'codeonly' && item.page.label" class="label-text">
|
||||
{{ item.page.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="backenabled" class="side-flag">{{ item.page.side }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Preview doubles as the print surface: what is on screen is what
|
||||
prints, so everything around it is chrome that print must strip. -->
|
||||
<div class="preview">
|
||||
<div class="preview-head no-print">
|
||||
<h4 class="section-heading">Preview</h4>
|
||||
<span class="preview-count">
|
||||
{{ cardCount }} label{{ cardCount === 1 ? '' : 's' }}<span
|
||||
v-if="backenabled">, {{ pages.length }} pages</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sheet">
|
||||
<div
|
||||
v-for="item in visible"
|
||||
:key="item.index"
|
||||
class="label"
|
||||
:class="labelClasses(item.page)"
|
||||
>
|
||||
<img v-if="showPicture(item.page) && pictureposition === 'behind'"
|
||||
:src="pictureUrl" class="picture-behind" alt="" />
|
||||
<div class="content">
|
||||
<div v-if="showPicture(item.page) && pictureposition !== 'behind'" class="picturebox">
|
||||
<img :src="pictureUrl" class="picture-img" alt="" />
|
||||
</div>
|
||||
<div class="codegroup">
|
||||
<div v-if="layoutFor(item.page) !== 'textonly'" class="codebox">
|
||||
<img v-if="images[item.index]" :src="images[item.index]" class="code-img" alt="" />
|
||||
<!-- An empty code box is indistinguishable from a label that
|
||||
simply has no code on it, which is how a failed render
|
||||
reads as "the barcode does not appear". Say so, on screen
|
||||
only - the printed label must never carry this. -->
|
||||
<span v-else class="code-missing">no code</span>
|
||||
</div>
|
||||
<div v-if="layoutFor(item.page) !== 'codeonly' && item.page.label" class="label-text">
|
||||
{{ item.page.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="backenabled" class="side-flag">{{ item.page.side }}</span>
|
||||
</div>
|
||||
<p v-if="!pages.length" class="preview-empty no-print">
|
||||
Nothing to print yet - enter content above.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -732,6 +752,47 @@ watch([pages, codetype, backcodetype, errorcorrection], renderAll)
|
||||
|
||||
.code-generator { width: 100%; }
|
||||
|
||||
/* Settings on the left, the labels themselves on the right, where they stay in
|
||||
view while the settings that change them are being worked. The preview
|
||||
column scrolls on its own so a 500-label run cannot push the controls off
|
||||
the screen. */
|
||||
.workspace {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 3fr) minmax(300px, 2fr);
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.preview {
|
||||
position: sticky;
|
||||
top: 12px;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px 16px;
|
||||
max-height: calc(100vh - var(--main-pad-top) - 24px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.preview-head {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.preview-head .section-heading { margin-top: 0.25rem; }
|
||||
|
||||
.preview-count { font-size: 0.8125rem; color: var(--text-light); }
|
||||
|
||||
.preview-empty { color: var(--text-light); font-size: 0.8125rem; margin: 0; }
|
||||
|
||||
/* One column once the two would be too narrow to work in. */
|
||||
@media (max-width: 1200px) {
|
||||
.workspace { grid-template-columns: minmax(0, 1fr); }
|
||||
.preview { position: static; max-height: none; }
|
||||
}
|
||||
|
||||
.controls {
|
||||
background: var(--bg-card);
|
||||
color: var(--text);
|
||||
@@ -905,18 +966,35 @@ watch([pages, codetype, backcodetype, errorcorrection], renderAll)
|
||||
.label.type-barcode .codebox {
|
||||
flex: 1 1 auto;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
/* Never below 40% of the label: past that a CODE128 is too few narrow bars
|
||||
to scan, so it is better for the caption to wrap or clip. */
|
||||
min-width: 40%;
|
||||
height: var(--tool-barh);
|
||||
}
|
||||
|
||||
.label.layout-stack.type-barcode .codebox { min-width: 100%; }
|
||||
|
||||
/* Screen-only, and deliberately loud: an empty box means the render failed. */
|
||||
.code-missing {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 6px;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.code-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* The caption takes what it needs and no more. Both boxes used to grow, so a
|
||||
caption of any length halved the barcode and then kept going - at 1x0.5in
|
||||
with a couple of words it left a 36px stub that reads as "the code did not
|
||||
render". A code that cannot be scanned is not a label. */
|
||||
.label-text {
|
||||
flex: 1 1 auto;
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
font-family: "Arial Narrow", Arial, Helvetica, sans-serif;
|
||||
@@ -943,7 +1021,20 @@ watch([pages, codetype, backcodetype, errorcorrection], renderAll)
|
||||
|
||||
@media print {
|
||||
.side-flag { display: none !important; }
|
||||
.code-missing { display: none !important; }
|
||||
.sheet { padding: 0; display: block; gap: 0; }
|
||||
/* The preview column is chrome. Its overflow matters most: a scrolling
|
||||
ancestor clips a multi-page print to whatever was on screen. */
|
||||
.workspace { display: block; }
|
||||
.preview {
|
||||
position: static;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
background: none;
|
||||
}
|
||||
/* The back's dotted variant outspecifies a bare .label reset, so it printed
|
||||
a dashed rule down the edge of every second card. */
|
||||
.label,
|
||||
|
||||
Reference in New Issue
Block a user