1 2Vue.component('form-utils', { 3 props: { 4 id: String, 5 title: String, 6 fieldtype: String, 7 value: { default: () => "", type: String }, // Quan és un valor únic i no objecte 8 valorinicial: { default: () => [], type: Array }, // Sempre usem aquest si és un valor múltiple 9 valuefile: { default: () => {}, type: Object}, // Sempre usem aquest si és un arxiu que carreguem 10 helptext: { default: '', type: String }, 11 placeholder: { default: '', type: String }, 12 disabled: { default: false, type: Boolean } , 13 options: { default: () => [], type: Array }, 14 groupclass: { default: () => [], type: Array }, 15 errors: { default: () => [] , type: Array }, 16 sterrors: { default: () => [] , type: Array }, //Llistat dels errors més comuns 17 rows: { default: () => 10, type: Number } 18 }, 19 data: function() { 20 return { 21 checklist: this.valorinicial, 22 HiHaError: false, 23 Errors: [], 24 ImageLoading: false, 25 ImageLoaded: false, 26 ImageShow: false, 27 ImageURL: {'url': '', 'hexfile': '', 'name': ''}, 28 ImageName: "", 29 30 /* Variables per al cropping */ 31 cropper: null, 32 objectUrl: null, 33 MostraModal: false, 34 ImageData: {}, 35 debouncedUpdatePreview: _.debounce(this.UpdatePreview, 257) 36 37 } 38 }, 39 computed: { 40 elementclass: function() { 41 let C = ['form-control']; 42 43 this.Errors = []; 44 for(let VP of this.sterrors) { 45 if(VP == 'Telefon' && !ValidaTelefon(this.value)) this.Errors.push("El telèfon no és correcte."); 46 if(VP == 'Email' && !ValidaEmail(this.value)) this.Errors.push("El correu electrònic no és correcte."); 47 if(VP == 'Number' && isNaN(this.value)) this.Errors.push("El valor ha de ser numèric."); 48 49 if(VP == 'Required') { 50 if(this.fieldtype == 'multipleselect') 51 if(!this.checklist) this.Errors.push('El camp és obligatori'); 52 else if(this.checklist.length == 0 ) this.Errors.push("El camp és obligatori."); 53 54 if(this.fieldtype !== 'multipleselect') 55 if(!this.value && this.value !== 0) this.Errors.push("El camp és obligatori."); 56 else if( this.value.length == 0 ) this.Errors.push("El camp és obligatori."); 57 } 58 59 }; 60 61 for(let EN of this.errors) { 62 if(EN[0]) this.Errors.push(EN[1]); 63 }; 64 65 if(this.Errors.length == 0) C.push('is-valid'); 66 else C.push('is-invalid'); 67 68 // Emitim si és o no và lid 69 if(this.fieldtype !== 'button') this.$emit('isvalid', (this.Errors.length == 0) ); 70 71 return C; 72 } 73 }, 74 watch: {}, 75 76 methods: { 77 buttonPress: function() { 78 this.$emit('onButtonPress', this.id); 79 }, 80 inputChange: function($val) { 81 if(this.fieldtype == 'multipleselect'){ 82 this.$emit('onchange', this.checklist); 83 } else { 84 this.$emit('onchange', $val.target.value); 85 } 86 87 }, 88 inputKeyup: function($val) { 89 this.$emit('onkeyup', $val.target.value); 90 }, 91 fileChange: function($val) { 92 93 const files = $val.target.files 94 const fileReader = new FileReader(); 95 96 this.ImageName = files[0].name 97 98 fileReader.addEventListener('load', () => { 99 this.ImageURL = fileReader.result 100 this.ImageLoading = false;
101 this.ImageLoaded = true; 102 this.$emit('onchange', {'url': '', 'hexfile':this.ImageURL, 'name': this.ImageName}) 103 }) 104 this.ImageLoading = true; 105 fileReader.readAsDataURL(files[0]) 106 }, 107 ReiniciaImatge: function(val) { 108 this.ImageURL = ""; 109 this.ImageLoaded = false; 110 }, 111 CarregaImatge: function(selectedFile) { 112 if(this.cropper) this.cropper.destroy(); 113 if(this.objectUrl) { window.URL.revokeObjectURL(this.objectUrl); } 114 if(!selectedFile) { this.cropper = null; this.objectUrl = null; this.ImageURL = null; return; } 115 116 let File = selectedFile.target.files[0]; 117 this.ImageName = File.name; 118 if (File) { 119 var reader = new FileReader(); 120 reader.onload = (e) => { 121 this.objectUrl = e.target.result; 122 this.MostraModal = true; 123 this.$nextTick(this.setupCropperInstance); // Executa després d'un cicle de DOM. Primer carrego la imatge i després hi carrego el canvas 124 } 125 126 reader.readAsDataURL(File); 127 } 128 }, 129 setupCropperInstance() { 130 let AspectRatio = 1; 131 this.cropper = new Cropper(this.$refs.imatge, 132 { 133 aspectRatio: AspectRatio, 134 crop: this.debouncedUpdatePreview 135 } 136 ); 137 }, 138 139 UpdatePreview(event) { 140 this.ImageData = event.detail; 141 const canvas = this.cropper.getCroppedCanvas(); 142 this.ImageURL = canvas.toDataURL('image/png'); 143 }, 144 145 TancaModalImatge: function() { 146 this.MostraModal = false; 147 }, 148 SaveCropImatge: function() { 149 150 const s = {width: 161, height: 90, minWidth: 200, minHeight: 200, maxWidth: 1096, maxHeight: 1096, fillColor: '#fff', imageSmoothingEnabled: false, imageSmoothingQuality: 'high' }; 151 const m = {width: 161, height: 90, minWidth: 400, minHeight: 400, maxWidth: 2096, maxHeight: 2096, fillColor: '#fff', imageSmoothingEnabled: false, imageSmoothingQuality: 'high' }; 152 const l = {width: 161, height: 90, minWidth: 400, minHeight: 400, maxWidth: 4096, maxHeight: 4096, fillColor: '#fff', imageSmoothingEnabled: false, imageSmoothingQuality: 'high' }; 153 let parametresCropper = {}; 154 parametresCropper = 'm'; 155 this.MostraModal = false; 156 this.ImageLoaded = true; 157 this.$emit('onchange', {'url': '', 'hexfile':this.ImageURL, 'name': this.ImageName}) 158 } 159 160 }, 161 162 163 164 165 166 167 168 169 170 171 172 template: ` 173 174 <div :class="[groupclass, 'FormUtils']"> 175 176 <!-- ****************** --> 177 <!-- ***** INPUT ****** --> 178 <!-- ****************** --> 179 180 <div v-if="fieldtype == 'input'" > 181 <label :for="id" class="form-label">{{title}}</label> 182 <input type="text" 183 :class="elementclass" 184 :placeholder="placeholder" 185 :aria-label="title" 186 :aria-describedby="title" 187 :id="id" 188 :value="value" 189 @change="inputChange" 190 @keyup="inputKeyup" 191 > 192 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 193 <small class="form-text text-muted">{{helptext}}</small> 194 </div> 195 196 <!-- ****************** --> 197 <!-- ***** BUTTON ****** --> 198 <!-- ****************** --> 199 200 <div v-if="fieldtype == 'button'"> 201 <label :for="id" class="form-label"></label> 202 <button :disabled="disabled" class="form-control btn btn-success" :aria-label="title" :id="id" @click="buttonPress">{{title}}</button> 203 </div> 204 205 <!-- ****************** --> 206 <!-- ***** SELECT ****** --> 207 <!-- ****************** --> 208 209 <div v-if="fieldtype == 'select'"> 210 <label :for="id" class="form-label">{{title}}</label> 211 <select type="select" 212 :class="elementclass" 213 :placeholder="placeholder" 214 :aria-label="title" 215 :aria-describedby="title" 216 :id="id" 217 :value="value" 218 @change="inputChange" 219 > 220 <option value="">-- Escull una opció --</option> 221 <option v-for="o of options" :value="o.id">{{o.text}}</option> 222 </select> 223 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 224 <small class="form-text text-muted">{{helptext}}</small> 225 </div> 226 227 <!-- *************************** --> 228 <!-- ***** MULTIPLESELECT ****** --> 229 <!-- *************************** --> 230 231 <div v-if="fieldtype == 'multipleselect'"> 232 <label :for="id" :class="[elementclass, 'form-label']">{{title}}</label> 233 <div v-for="o of options" class="form-check"> 234 <input 235 :class="['form-check-input']" 236 type="checkbox" 237 :value="o.id" 238 :id="o.id" 239 :placeholder="placeholder" 240 :aria-label="o.text" 241 :aria-describedby="o.text" 242 @change="inputChange" 243 v-model="checklist" > 244 <label class="form-check-label" for="flexCheckDefault">{{o.text}}</label> 245 </div> 246 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 247 <small class="form-text text-muted">{{helptext}}</small> 248 </div> 249 250 <!-- ****************** -->
251 <!-- ***** DATE ****** --> 252 <!-- ****************** --> 253 254 <div v-if="fieldtype == 'date'"> 255 <label :for="id" class="form-label">{{title}}</label> 256 <input type="date" 257 :class="elementclass" 258 :placeholder="placeholder" 259 :aria-label="title" 260 :aria-describedby="title" 261 :id="id" 262 :value="value" 263 @change="inputChange" 264 @keyup="inputKeyup" 265 @blur="inputKeyup" 266 > 267 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 268 <small class="form-text text-muted">{{helptext}}</small> 269 </div> 270 271 <!-- ****************** --> 272 <!-- ***** TIME ****** --> 273 <!-- ****************** --> 274 275 <div v-if="fieldtype == 'time'"> 276 <label :for="id" class="form-label">{{title}}</label> 277 <input type="time" 278 :class="elementclass" 279 :placeholder="placeholder" 280 :aria-label="title" 281 :aria-describedby="title" 282 :id="id" 283 :value="value" 284 @change="inputChange" 285 @keyup="inputKeyup" 286 @blur="inputKeyup" 287 > 288 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 289 <small class="form-text text-muted">{{helptext}}</small> 290 </div> 291 292 293 <!-- ********************* --> 294 <!-- ***** TEXTAREA ****** --> 295 <!-- ********************* --> 296 297 <div v-if="fieldtype == 'textarea'"> 298 <label :for="id" class="form-label">{{title}}</label> 299 <textarea 300 :class="elementclass" 301 :placeholder="placeholder" 302 :aria-label="title" 303 :aria-describedby="title" 304 :id="id" 305 :value="value" 306 :rows="rows" 307 @change="inputChange" 308 @keyup="inputKeyup" 309 > 310 </textarea> 311 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 312 <small class="form-text text-muted">{{helptext}}</small> 313 </div> 314 315 <!-- ********************* --> 316 <!-- ******** FILE ******* --> 317 <!-- ********************* --> 318 319 <div v-if="fieldtype == 'file' || fieldtype == 'image'"> 320 <label :for="id" v-if="ImageLoaded" class="form-label">{{title}}</label> 321 <label :for="id" v-if="!ImageLoaded" class="custom-file-label">{{title}}</label> 322 323 <div v-if="ImageLoaded" style="display: block; margin-top: 0vw;"> 324 325 <div class="alert alert-success" style="margin-top: 1vw;" role="alert" v-if="ImageLoaded"> 326 Arxiu carregat correctament. 327 </div> 328 <a style="display: block; cursor: pointer" @click="ReiniciaImatge" aria-label="Esborra arxiu"> Esborra </a> 329 </div> 330 331 <div class="form-control" v-if="ImageLoading">Carregant l'arxiu</div> 332 <input v-if="!ImageLoading && !ImageLoaded" 333 type="file" 334 accept="document/pdf, document/word" 335 :class="elementclass" 336 :placeholder="placeholder" 337 :aria-label="title" 338 :aria-describedby="title" 339 :id="id" 340 @change="fileChange" 341 > 342 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 343 <small class="form-text text-muted">{{helptext}}</small> 344 </div> 345 346 347 <!-- ********************* --> 348 <!-- ****** CROPPED ****** --> 349 <!-- ********************* --> 350 351 <div v-if="fieldtype == 'crop'"> 352 <div style="height: 50px" v-if="ImageLoaded"> 353 <img :src="ImageURL" style="height: 50px"> 354 <i @click="ReiniciaImatge()" class="withHand fas fa-tras
354h-alt"></i> 355 </div> 356 <div v-else> 357 <input type="file" accept="image/png, image/jpeg" class="form-control" id="MidaImatge" @change="CarregaImatge($event)" > 358 <label class="custom-file-label" for="MidaImatge" >{{title}}</label> 359 <small v-for="E of Errors" class="form-text-error">{{E}}<br /></small> 360 <small class="form-text text-muted">{{helptext}}</small> 361 </div> 362 363 <div class="modalbox" v-if="MostraModal"> 364 <table> 365 <tr><td><div style="border:1 px solid blue; background-color: black;"> 366 <img style="display: block;" :src="objectUrl" ref="imatge" /> 367 </div> 368 </td><td> 369 <div style="border:1 px solid blue; background-color: black;"> 370 <img style="display: block;" :src="ImageURL" /> 371 </div> 372 </td> 373 </tr><tr> 374 <td> 375 <button v-on:click="TancaModalImatge()" class="btn btn-info">Torna</button> 376 <button v-on:click="SaveCropImatge()" class="btn btn-success">Retalla-la!</button> 377 </td> 378 <td> </td> 379 </tr> 380 </table> 381 </div> 382 </div> 383 384 385 386 387 388 389 </div> 390 391 392` 393});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.