Skip to content

Commit c97f7dc

Browse files
authored
Merge branch 'master' into OLMIS-8179-compact-inputs
2 parents 21b1f5c + 749e767 commit c97f7dc

6 files changed

Lines changed: 123 additions & 82 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
7.2.17-SNAPSHOT (WIP)
22
==================
33
* [OLMIS-8179](https://openlmis.atlassian.net/browse/OLMIS-8179): Compact packs/doses quantity inputs.
4+
* [OLMIS-8191](https://openlmis.atlassian.net/browse/OLMIS-8191) / [OLMIS-8192](https://openlmis.atlassian.net/browse/OLMIS-8192): Add openlmis-long-text class and directive so long free-text in table cells grows with content then wraps — for both the editable textarea and its read-only display.
45

56
7.2.16 / 2026-06-09
67
==================

src/common/_variables.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ $padding-small: 0.5em;
6565
$padding: (2 * $padding-small);
6666
$padding-large: (2 * $padding);
6767

68+
// openlmis-long-text widen-then-wrap: cap = where wrapping starts, floor = editable typing room.
69+
$openlmis-long-text-max-width: 35em !default;
70+
$openlmis-long-text-min-width: 14em !default;
71+
6872
$margin: 1em;
6973

7074
$padding2px:2px;

src/openlmis-table-form/_table-forms.scss

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,24 @@ td > label.checkbox {
142142
width: 100%;
143143
}
144144

145-
.openlmis-table td > div.input-control > textarea {
146-
min-width: 14em;
147-
max-width: 20em;
145+
// Long free-text in a table column: widens with content, then wraps. Opt-in class on the
146+
// editable textarea (sized by the openlmisLongText directive) and the read-only span.
147+
.openlmis-long-text {
148+
display: inline-block;
149+
max-width: $openlmis-long-text-max-width;
148150
white-space: pre-wrap;
151+
overflow-wrap: break-word;
149152
overflow: hidden;
150153
resize: none;
151154
vertical-align: middle;
152155
}
156+
157+
// Editable: minimum typing width (the directive sets the actual width).
158+
textarea.openlmis-long-text {
159+
min-width: $openlmis-long-text-min-width;
160+
}
161+
162+
// Read-only: size to content up to the cap, so short cells stay narrow and long text wraps.
163+
span.openlmis-long-text {
164+
width: max-content;
165+
}

src/openlmis-table-form/textarea-auto-resize.directive.js renamed to src/openlmis-table-form/openlmis-long-text.directive.js

3.57 KB
Binary file not shown.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* This program is part of the OpenLMIS logistics management information system platform software.
3+
* Copyright © 2017 VillageReach
4+
*
5+
* This program is free software: you can redistribute it and/or modify it under the terms
6+
* of the GNU Affero General Public License as published by the Free Software Foundation, either
7+
* version 3 of the License, or (at your option) any later version.
8+
*  
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
11+
* See the GNU Affero General Public License for more details. You should have received a copy of
12+
* the GNU Affero General Public License along with this program. If not, see
13+
* http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org. 
14+
*/
15+
16+
describe('openlmisLongText directive', function() {
17+
18+
beforeEach(function() {
19+
module('openlmis-table-form');
20+
21+
inject(function($injector) {
22+
this.$compile = $injector.get('$compile');
23+
this.$rootScope = $injector.get('$rootScope');
24+
});
25+
26+
this.$scope = this.$rootScope.$new();
27+
28+
this.compileMarkup = function(markup) {
29+
const element = this.$compile(markup)(this.$scope);
30+
angular.element('body').append(element);
31+
this.$scope.$apply();
32+
return element;
33+
};
34+
});
35+
36+
it('should set an explicit width and height on a textarea with the class', function() {
37+
const textarea = this.compileMarkup('<textarea class="openlmis-long-text">short</textarea>');
38+
39+
expect(Number.parseInt(textarea[0].style.width, 10)).toBeGreaterThan(0);
40+
expect(Number.parseInt(textarea[0].style.height, 10)).toBeGreaterThan(0);
41+
});
42+
43+
it('should grow width when the value becomes longer', function() {
44+
const textarea = this.compileMarkup('<textarea class="openlmis-long-text">short</textarea>');
45+
const previousWidth = Number.parseInt(textarea[0].style.width, 10);
46+
47+
textarea[0].value = 'a value that is clearly longer than the initial one';
48+
this.$scope.$apply();
49+
50+
expect(Number.parseInt(textarea[0].style.width, 10)).toBeGreaterThan(previousWidth);
51+
});
52+
53+
it('should grow height when the value spans multiple lines', function() {
54+
const textarea = this.compileMarkup('<textarea class="openlmis-long-text">short</textarea>');
55+
const previousHeight = Number.parseInt(textarea[0].style.height, 10);
56+
57+
textarea[0].value = 'first line\nsecond line\nthird line\nfourth line';
58+
this.$scope.$apply();
59+
60+
expect(Number.parseInt(textarea[0].style.height, 10)).toBeGreaterThan(previousHeight);
61+
});
62+
63+
it('should not resize a textarea that does not have the class', function() {
64+
const textarea = this.compileMarkup('<textarea>plain</textarea>');
65+
66+
expect(textarea[0].style.width).toEqual('');
67+
expect(textarea[0].style.height).toEqual('');
68+
});
69+
70+
it('should not set an inline size on a read-only span with the class', function() {
71+
const span = this.compileMarkup('<span class="openlmis-long-text">read only</span>');
72+
73+
expect(span[0].style.width).toEqual('');
74+
expect(span[0].style.height).toEqual('');
75+
});
76+
77+
it('should not collapse a textarea that is hidden when linked', function() {
78+
const textarea = this.compileMarkup(
79+
'<textarea class="openlmis-long-text" style="display: none;">hidden</textarea>'
80+
);
81+
82+
// A hidden textarea reports scrollHeight 0; sizing it then would bake height:0 and
83+
// leave it collapsed once shown (e.g. an ng-show free-text comment). It must be skipped.
84+
expect(textarea[0].style.height).not.toEqual('0px');
85+
});
86+
87+
it('should size a pre-filled textarea once it becomes visible after being hidden', function() {
88+
const textarea = this.compileMarkup(
89+
'<textarea class="openlmis-long-text" style="display: none;">a pre-filled value</textarea>'
90+
);
91+
92+
// Hidden at link time -> skipped, no inline height yet.
93+
expect(textarea[0].style.height).toEqual('');
94+
95+
// Shown later without a value change -> the visibility watch must size it.
96+
textarea[0].style.display = '';
97+
this.$scope.$apply();
98+
99+
expect(Number.parseInt(textarea[0].style.height, 10)).toBeGreaterThan(0);
100+
expect(Number.parseInt(textarea[0].style.width, 10)).toBeGreaterThan(0);
101+
});
102+
});

src/openlmis-table-form/textarea-auto-resize.directive.spec.js

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)