-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInputfieldObjectDimensions.module
286 lines (244 loc) · 10.5 KB
/
InputfieldObjectDimensions.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
<?php
declare(strict_types=1);
namespace ProcessWire;
/*
* Inputfield ObjectDimensions to enter length, width and height of an object
*
* Created by Jürgen K.
* https://github.com/juergenweb
* File name: FieldtypeObjectDimensions.module
* Created: 02.02.2022
*/
class InputfieldObjectDimensions extends Inputfield {
/**
* Set the input field parameters
* @return array
*/
public static function getModuleInfo():array {
return [
'title' => 'Inputfield Object Dimensions',
'summary' => 'Inputfield for entering 2 (length, width) or 3 (length, width and height) dimensions of an object as integer or float number.',
'version' => '1.2.2',
'href' => 'https://github.com/juergenweb/FieldtypeObjectDimensions',
'icon' => 'cube',
'permanent' => false,
'requires' => [
'FieldtypeObjectDimensions',
'PHP>=8.0',
'ProcessWire>=3'
],
'author' => 'Jürgen Kern'
];
}
public function __construct() {
parent::__construct();
// set default values for field configuration
$this->set('input_type', '3d');
$this->set('input_sizeunit', 'cm');
$this->set('input_digits', 10);
$this->set('input_decimals', 2);
$this->set('input_required', []);
$this->set('input_showhint', false);
}
/**
* init() is called when the system is ready for API usage
* @return void
*/
public function init():void {
$version = $this->getModuleInfo()['version'] . '-' . time();
//Add CSS and JS files
$this->config->styles->add(config()->urls->{$this->className} . 'assets/objectdimensions.css?v=' . $version);
$this->config->scripts->add(config()->urls->{$this->className} . 'assets/objectdimensions.js?v=' . $version);
}
/**
* Output an array of the labels of the dimensions
* @return array
*/
public static function getLabels():array {
return [
'length' => __('Length'),
'width' => __('Width'),
'height' => __('Height'),
'volume' => __('Volume'),
'area' => __('Area'),
'dimensions' => __('Dimensions')
];
}
/**
* Render the input fields for the dimension values
* @return string
*/
public function ___render():string {
$out = '';
//check decimals setting
$decimals = intval($this->input_decimals);
if ($decimals === 1) {
$hint = sprintf($this->_('Please enter %s decimals.'), $this->input_decimals);
$steps = '0.1';
} elseif ($decimals >= 1) {
$hint = sprintf($this->_('Please enter %s decimals.'), $this->input_decimals);
$steps = '0.'.str_repeat('0', $decimals - 1).'1';
} else {
$hint = $this->_('Please enter no decimals.');
$steps = '1';
}
//create placeholder depending on number of decimals
$placeholderStr = '0.' . str_repeat('0', $this->input_decimals);
// remove volume, area and dimensions from getLabels
$dimensionItems = self::getLabels();
unset($dimensionItems['volume']);
unset($dimensionItems['area']);
unset($dimensionItems['dimensions']);
foreach ($dimensionItems as $key => $v) {
if ((($this->input_type == '2d') && ($key != 'height')) || ($this->input_type == '3d')) {
$out .= '<div id="' . $key . '_dimension" class="dimension-field">';
// create the label tag
$label = InputfieldWrapper::getMarkup()['item_label'];
$unit = $this->input_sizeunit ? ' (' . $this->input_sizeunit . ')' : '';
$label = str_replace('{out}', $v . $unit, $label);
$out .= str_replace('{for}', $this->name . '_' . $key, $label);
// create the input tag
$inputfield = new InputfieldText();
$inputfield->attr('id|name', $this->name . '_' . $key);
$inputfield->attr('class', 'two-decimals');
$inputfield->attr('type', 'number');
$inputfield->value = $this->value->$key;
$inputfield->attr('step', $steps);
$inputfield->attr('min', '0');
//$inputfield->attr('style', 'width:' . $this->input_width . 'px');
$inputfield->attr('oninput', 'restrict(this,' . $decimals . ')');
$inputfield->placeholder = $placeholderStr;
$out .= $inputfield->render();
$out .= '</div>';
}
}
// inform the user about how much decimals can be entered
if ($this->input_showhint) {
$notes = InputfieldWrapper::getMarkup()['item_notes'];
$notes = str_replace('{out}', $hint, $notes);
$out .= $notes;
}
return $out;
}
/**
* Sanitize and validate the values of the dimensions field
*
* @param WireInputData $input
* @return $this
*
*/
public function ___processInput(WireInputData $input):self {
$name = $this->attr('name');
$value = $this->attr('value');
$nameAttributes = [ // name in db => name input element
'length' => $name . "_length",
'width' => $name . "_width"
];
// if 3 dimension add height to the array
if ($this->input_type == '3d') {
$height = ['height' => $name . "_height"];
$nameAttributes = array_merge($nameAttributes, $height);
}
// loop through all inputs and set them if changed
foreach ($nameAttributes as $key => $name) {
// sanitize all values to be a float with the number of decimals set in the configuration
$input->$name = (float)number_format((float)$input->$name, (int)$this->input_decimals, '.', '');
$errors = [];
// if field is required, check if field has a value
if ($this->required) {
if ((empty($input->$name)) || ($input->$name == 0.0)) {
$this->error(sprintf($this->_('Field "%s" is required and must contain a positive value higher than 0.'),
self::getLabels()[$key]));
$errors[] = 'required';
}
}
if (!empty($input->$name)) {
// check if value is not negative
if ($input->$name < 0) {
$errors[] = 'negative';
$this->error(sprintf($this->_('Field "%s" does not accept negative values.'),
self::getLabels()[$key]));
}
}
if (!count($errors)) {
// if no errors occur at all, sanitize and set the value back to the inputfield and track potential
// changes in the value
if ($this->input_decimals > 0) {
$sanitizedValue = (float)$input->$name;
} else {
$sanitizedValue = (int)$input->$name;
}
$value->set($key, $sanitizedValue);
$this->trackChange('value');
}
}
return $this;
}
/**
* Add additional configuration fields to the input field
*
* @return InputfieldWrapper
*
* @throws WirePermissionException
*/
// Add additional configuration fields
public function ___getConfigInputfields():InputfieldWrapper {
//get all parent input fields
$inputfields = parent::___getConfigInputfields();
$f = modules()->get("InputfieldSelect");
$f->set("label", $this->_('Type'));
$f->attr("name+id", "input_type");
$f->attr("value", $this->input_type);
$f->addOptions([
'3d' => $this->_('3 dimensions'),
'2d' => $this->_('2 dimensions')
]);
$f->required(true);
$f->description = $this->_('3 dimensions: length, width and height; 2 dimensions: length and width.');
$inputfields->append($f);
// field to enter a specific size unit for the dimensions (fe cm, inch, m,....)
$f = $this->modules->get('InputfieldText');
$f->attr('name+id', 'input_sizeunit');
$f->label = $this->_('Size unit');
$f->attr('value', $this->input_sizeunit);
$f->attr('size', 10);
$f->required(true);
$f->description = $this->_('The size unit for the 3 dimensions.');
$inputfields->append($f);
// field to enter the number of decimals (fe 2) -> will be appended after the inputfield
$f = $this->modules->get('InputfieldInteger');
$f->attr('name+id', 'input_decimals');
$f->attr('type', 'number');
$f->label = $this->_('Number of decimals');
$f->attr('value', $this->input_decimals);
$f->attr('size', 10);
$f->attr('min', 0);
$f->attr('max', 30);
$f->required(true);
$f->description = $this->_('The number of decimals that can be entered in the dimension fields.');
$f->notes = $this->_('A value of 0 means that the dimension value is a type of integer and not decimals. Max value is 30.');
$inputfields->append($f);
// checkbox field to enable/disable the hint text for the max numbers of decimals on the form
$f = $this->modules->get('InputfieldCheckbox');
$f->attr('name+id', 'input_showhint');
$f->attr('checked', $this->input_showhint == '1' ? 'checked' : '');
$f->checkboxLabel = $this->_('Show hint');
$f->label = $this->_('Show hint for max number of decimals below input fields.');
$f->description = $this->_('If checked, a hint text will be displayed under the input fields to inform the user how many decimals are allowed.');
$inputfields->append($f);
// output all input fields (parent and custom)
return $inputfields;
}
/**
* Allow these fields to get overwritten by user on per template base
* @param Field $field
* @return array
*
*/
public function getConfigAllowContext(Field $field):array {
return [
'input_type',
'input_showhint'
];
}
}