1/* 2 * Il codice contenuto in questo file js viene eseguito 3 * su ogni pagina di portal 4 * 5 */ 6 7$(document).ready(function() { 8 9 if(typeof(openweb_csrf)!="undefined") { 10 $("form").append('<input type="hidden" name="CSRF" value="'+openweb_csrf+'">'); 11 $("a").each(function(){ 12 if(!$(this).hasClass("noCSRF") && $(this).prop("href")!="" && $(this).prop("href").indexOf(".php")>=0 && $(this).prop("href").indexOf(".php?")<0) { 13 $(this).prop("href", $(this).prop("href")+"?"); 14 } 15 if(!$(this).hasClass("noCSRF") && $(this).prop("href")!="" && $(this).prop("href").indexOf("javascript:")<0 && $(this).prop("href").indexOf(".aspx")<0 && $(this).prop("href").indexOf("?")>=0 && $(this).prop("href").indexOf("CSRF")<0) { 16 $(this).prop("href", $(this).prop("href")+"&CSRF="+openweb_csrf); 17 } 18 }); 19 $allResponsiveTables = $("table.table-responsive"); 20 $allResponsiveTables.each(function() { 21 22 if (!$(this).hasClass("no-responsive")) { 23 24 tableToUl($(this)) 25 26 } 27 }); 28 } 29 30 /* ============================================================= 31 * bootstrap-typeahead.js v2.0.1 32 * http://twitter.github.com/bootstrap/javascript.html#typeahead 33 * ============================================================= 34 * Copyright 2012 Twitter, Inc. 35 * 36 * Licensed under the Apache License, Version 2.0 (the "License"); 37 * you may not use this file except in compliance with the License. 38 * You may obtain a copy of the License at 39 * 40 * http://www.apache.org/licenses/LICENSE-2.0 41 * 42 * Unless required by applicable law or agreed to in writing, software 43 * distributed under the License is distributed on an "AS IS" BASIS, 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 * See the License for the specific language governing permissions and 46 * limitations under the License. 47 * ============================================================ */ 48 49!function( $ ){ 50 51 "use strict" 52 53 var Typeahead = function ( element, options ) { 54 this.$element = $(element) 55 this.$keyField = this.$element.data( "key-field" )!=""?this.$element.nextAll("#"+this.$element.data( "key-field" )):{}; 56 this.options = $.extend({}, $.fn.typeahead.defaults, options) 57 this.matcher = this.options.matcher || this.matcher 58 this.sorter = this.options.sorter || this.sorter 59 this.highlighter = this.options.highlighter || this.highlighter 60 this.$menu = $(this.options.menu).appendTo('body') 61 this.source = this.options.source 62 this.keys = this.options.keys 63 this.shown = false 64 this.listen() 65 } 66 67 Typeahead.prototype = { 68 69 constructor: Typeahead 70 71 , select: function () { 72 var val = this.$menu.find('.active').attr('data-value') 73 var index = $.inArray(val, this.source); 74 if (index < 0) { 75 this.$element.val(""); 76 if(this.$keyField.length) { this.$keyField.val(""); this.$keyField.trigger("change"); } 77 } 78 else { 79 this.$element.val(val); 80 if(this.$keyField.length) { this.$keyField.val(this.keys[index]); this.$keyField.trigger("change"); } 81 } 82 83 return this.hide() 84 } 85 86 , show: function () { 87 var pos = $.extend({}, this.$element.offset(), { 88 height: this.$element[0].offsetHeight 89 }) 90 91 this.$menu.css({ 92 top: pos.top + pos.height 93 , left: pos.left 94 }) 95 96 this.$menu.show() 97 this.shown = true 98 return this 99 } 100 101 , hide: function () { 102 this.$menu.hide() 103 this.shown = false 104 return this 105 } 106 107 , lookup: function (event) { 108 var that = this 109 , items 110 , q 111 112 this.query = this.$element.val() 113 114 if (!this.query) { 115 return this.shown ? this.hide() : this 116 } 117 118 items = $.grep(this.source, function (item) { 119 if (that.matcher(item)) return item 120 }) 121 122 items = this.sorter(items) 123 124 if (!items.length) { 125 return this.shown ? this.hide() : this 126 } 127 128 return this.render(items.slice(0, this.options.items)).show() 129 } 130 131 , matcher: function (item) { 132 return item?~item.toLowerCase().indexOf(this.query.toLowerCase()):false 133 } 134 135 , sorter: function (items) { 136 var beginswith = [] 137 , caseSensitive = [] 138 , caseInsensitive = [] 139 , item 140 141 while (item = items.shift()) { 142 if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item) 143 else if (~item.indexOf(this.query)) caseSensitive.push(item) 144 else caseInsensitive.push(item) 145 } 146 147 return beginswith.concat(caseSensitive, caseInsensitive) 148 } 149 150 , highlighter: function (item) { 151 return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) { 152 return '<strong>' + match + '</strong>' 153 }) 154 } 155 156 , render: function (items) { 157 var that = this 158 159 items = $(items).map(function (i, item) { 160 i = $(that.options.item).attr('data-value', item) 161 i.find('a').html(that.highlighter(item)) 162 return i[0] 163 }) 164 165 items.first().addClass('active') 166 this.$menu.html(items) 167 return this 168 } 169 170 , next: function (event) { 171 var active = this.$menu.find('.active').removeClass('active') 172 , next = active.next() 173 174 if (!next.length) { 175 next = $(this.$menu.find('li')[0]) 176 } 177 178 next.addClass('active') 179 } 180 181 , prev: function (event) { 182 var active = this.$menu.find('.active').removeClass('active') 183 , prev = active.prev() 184 185 if (!prev.length) { 186 prev = this.$menu.find('li').last() 187 } 188 189 prev.addClass('active') 190 } 191 192 , listen: function () { 193 this.$element 194 .on('blur', $.proxy(this.blur, this)) 195 .on('keypress', $.proxy(this.keypress, this)) 196 .on('keyup', $.proxy(this.keyup, this)) 197 198 // CONTROLO DEPRECATO RIMOSSO PER COMPATIBILITA' CON JQUERY 3.5.1 199 // if ($.browser.webkit || $.browser.msie) { 200 // this.$element.on('keydown', $.proxy(this.keypress, this)) 201 // } 202 203 204 this.$menu 205 .on('click', $.proxy(this.click, this)) 206 .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) 207 } 208 209 , keyup: function (e) { 210 211 switch(e.keyCode) { 212 case 40: // down arrow 213 case 38: // up arrow 214 e.stopPropagation() 215 e.preventDefault() 216 break 217 218 case 9: // tab 219 if (!this.shown) return 220 this.select() 221 break; 222 case 13: // enter 223 e.stopPropagation() 224 e.preventDefault() 225 if (!this.shown) return 226 this.select() 227 break 228 229 case 27: // escape 230 e.stopPropagation() 231 e.preventDefault() 232 this.hide() 233 break 234 235 default: 236 e.stopPropagation() 237 e.preventDefault() 238 this.lookup() 239 } 240 241 } 242 243 , keypress: function (e) { 244 e.stopPropagation() 245 if (!this.shown) return 246 247 switch(e.keyCode) { 248 case 9: // tab 249 case 13: // enter 250 case 27: // escape 251 e.preventDefault() 252 break 253 254 case 38: // up arrow 255 e.preventDefault() 256 this.prev() 257 break 258 259 case 40: // down arrow 260 e.preventDefault() 261 this.next() 262 break 263 } 264 } 265 266 , blur: function (e) { 267 var val = this.$element.val(); 268 var index = $.inArray(val, this.source); 269 if (index < 0) { 270 this.$element.val(""); 271 if(this.$keyField.length) { this.$keyField.val(""); } 272 } 273 var that = this 274 e.stopPropagation() 275 e.preventDefault() 276 setTimeout(function () { that.hide() }, 150) 277 } 278 279 , click: function (e) { 280 e.stopPropagation() 281 e.preventDefault() 282 this.select() 283 } 284 285 , mouseenter: function (e) { 286 this.$menu.find('.active').removeClass('active') 287 $(e.currentTarget).addClass('active') 288 } 289 290 } 291 292 293 /* TYPEAHEAD PLUGIN DEFINITION 294 * =========================== */ 295 296 $.fn.typeahead = function ( option ) { 297 return this.each(function () { 298 var $this = $(this) 299 , data = $this.data('typeahead') 300 , options = typeof option == 'object' && option 301 if (!data) $this.data('typeahead', (data = new Typeahead(this, options))) 302 if (typeof option == 'string') data[option]() 303 }) 304 } 305 306 $.fn.typeahead.defaults = { 307 source: [] 308 , items: 8 309 , menu: '<ul class="typeahead dropdown-menu"></ul>' 310 , item: '<li><a href="#"></a></li>' 311 } 312 313 $.fn.typeahead.Constructor = Typeahead 314 315 316 /* TYPEAHEAD DATA-API 317 * ================== */ 318 319 $(function () {
320 $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { 321 var $this = $(this) 322 if ($this.data('typeahead')) return 323 e.preventDefault() 324 $this.typeahead($this.data()) 325 }) 326 }) 327 328}( window.jQuery ); 329 /* 330 * Ogni elemento con classe form-hidable verràdotato di un pulsante per mostrare il form (sopra lo stesso) 331 * ed un pulsante per nascondere il form (all'interno dello stesso, nel div con classe .buttons-row) 332 * 333 * La classe form-hidable viene aggiunta automaticamente nel template dei widget quando $W->config['hidable'] == true 334 */ 335 $(".form-hidable").each(function() { 336 $form = $(this); 337 $form.find(".buttons-row").append('<input type="button" class="btn btn-default btn-hide mt10" value="Nascondi ricerca">'); 338 $form.before('<div class="col-xs-12 mb15"><input type="button" class="btn btn-default btn-show btn-outline-primary" value="Ricerca"></div>'); 339 340 $hideButton = $form.find(".btn-hide"); 341 $showButton = $form.prev().find(".btn-show"); 342 343 $hideButton.click(function() {$form.hide(); $showButton.show();}); 344 $showButton.click(function() {$form.show(); $showButton.hide();}); 345 346 var searchActive = false; 347 $form.find("input,select,textarea").not(':button').not(':hidden').not(':submit').each(function(){ 348 if($(this).val()!="") { 349 searchActive = true; 350 } 351 }); 352 353 if(!searchActive){$form.hide();} 354 else {$showButton.hide();} 355 }); 356 $(".nav-pills a").click(function(e) { 357 console.log($(this).text()); 358 $("html").scrollTop( $($(this).attr("href")).offset().top-116 ); 359 }); 360 361 if($('input.datepicker').length > 0) { 362 $('input.datepicker').each(function(){ 363 var value = $(this).val(); 364 $(this).datepicker({ 365 "dateFormat": "dd/mm/yy", 366 constrainInput: true, 367 dayNames: [ "Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato" ], 368 dayNamesShort: [ "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab" ], 369 dayNamesMin: [ "Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa" ], 370 monthNames: [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ], 371 monthNamesShort: [ "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic" ], 372 firstDay: 1, 373 setDate: value, 374 }); 375 }); 376 } 377 378 if($('#current_page').length > 0) { 379 var current_page = $('#current_page').val(); 380 if(!page && current_page) {page=current_page;} 381 var show_per_page = parseInt($('body').find("#items_per_page").val()); 382 var number_of_items = parseInt($('body').find('.pagination_content .paginated_element').length); 383 var last_page_number = Math.ceil(number_of_items/show_per_page); 384 385 386 function paginatorListeners($element) { 387 var ulContent = $element.find('ul').html(); 388 if(ulContent) { 389 $element.html(ulContent); 390 } 391 $element.find('li').each(function() { 392 $(this).find('a').click(function() { 393 var href = $(this).attr('href'); 394 var targetPage = 1; 395 if(href.indexOf("go_to_page") > -1) { 396 targetPage = href.replace("javascript:go_to_page(","").replace(", 'body')","").replace(",'body')",""); 397 } 398 else if(href.indexOf("first_page") > -1) { 399 targetPage = 1; 400 } 401 else if(href.indexOf("previous") > -1) { 402 targetPage = parseInt($('body').find('#current_page').val())-1; 403 } 404 else if(href.indexOf("next") > -1) { 405 targetPage = parseInt($('body').find('#current_page').val())+1; 406 } 407 else if(href.indexOf("last_page") > -1) { 408 targetPage = last_page_number; 409 } 410 if(targetPage<1) {targetPage=1;} 411 console.log("setting target to "+targetPage); 412 $.post( paginatorPOSTurl, { paginatorPOSTparam: targetPage } ); 413 }); 414 }); 415 } 416 417 if(number_of_items>show_per_page) { 418 419 init_paginatore(); 420 421 paginatorListeners($('#paginator_div')); 422 paginatorListeners($('.lista_pagine')); 423 $('#paginator_div').bind("DOMSubtreeModified",function(event){ 424 paginatorListeners($(this)); 425 paginatorListeners($('.lista_pagine')); 426 current_page = $('#current_page').val(); 427 }); 428 429 if (page && page>1) 430 { 431 go_to_page(page, 'body'); 432 } 433 } else { 434 $('#paginator_div').remove(); 435 } 436 437 } 438 439 $('.row_linked').on('click', 'tr', function(){ 440 if(typeof($(this).find('a').attr('href'))!="undefined") { 441 console.log("Going to "+$(this).find('a').attr('href')); 442 window.location = $(this).find('a').attr('href'); 443 } 444 }); 445 /*$('.row_linked tbody tr').each(function() { 446 $(this).css( "cursor", "pointer" ); 447 $(this).click( function() { 448 window.location = $(this).find('a').attr('href'); 449 }).hover( function() { 450 $(this).toggleClass('hover'); 451 }); 452 });*/ 453 454 455 var $labels = $("label:contains('*')" ); 456 if($labels.length) { 457 var forms = []; 458 $labels.each(function(){ 459 $(this).next("div").find("input, select, textarea").attr("required", true); 460 var noval = $(this).closest("form").attr("novalidate"); 461 if(typeof noval === typeof undefined || noval === false || noval == "force") { 462 $(this).closest("form").attr("novalidate", true); 463 forms.push($(this).closest("form")); 464 } 465 }); 466 for (var i in forms) { 467 initValidation(forms[i]); 468 } 469 } 470 471 $("#menu_responsive_laterale").removeAttr("style"); 472}); 473 474var typeaheads = {}; 475function enableTypeahead($element, keys, values) 476{ 477 typeaheads[$element.prop("id")] = $element; 478 $elementTypeahead = $element.clone(true,true); 479 $elementTypeahead.insertAfter($element); 480 $element.remove(); 481 $elementTypeahead.val(""); 482 $elementTypeahead.attr( 'autocomplete', 'off' ); 483 484 $elementTypeahead.typeahead({source: values, keys: keys},{fitToElement: true}); 485 $elementTypeahead.data("has-typeahead", true); 486 console.log("typeahead enabled on "+$element.attr("id")); 487} 488 489function disableTypeahead($element) { 490 if(typeof(typeaheads[$element.prop("id")])!="undefined") { 491 typeaheads[$element.prop("id")].insertAfter($element); 492 $element.remove(); 493 delete typeaheads[$element.prop("id")]; 494 $elementTypeahead.removeData("has-typeahead"); 495 console.log("typeahead disabled on "+$element.attr("id")); 496 } 497} 498 499function stradario($input, comune) { 500 console.log("stradario on "+$input.attr("id")+" for comune "+comune); 501 disableTypeahead($input); 502 var $wait = $('#'+$input.attr("id")+'_wait'); 503 var $container = $input.parent(); 504 if(!$wait.length) { 505 $wait = $("<input>"); 506 $wait.attr("type", "text").attr("id", "referente_comuneResidenza_via_wait").val("caricamento stradario...").attr("disabled","true").addClass("form-control"); 507 $container.append($wait); 508 } 509 $wait.hide(); 510 if(comune!="") { 511 $input.hide(); 512 $wait.show(); 513 $.get( "get_indirizzi.php?comune="+comune, function( data ) { 514 $wait.hide(); 515 $input.show(); 516 var res = jQuery.parseJSON(data.replace(/'/g,'"')); 517 if(res.length>0) { 518 var ids = []; 519 var descrizioni = []; 520 for (var i in res) { 521 ids.push(res[i].codice); 522 descrizioni.push(decodeEntities(res[i].descrizione)); 523 } 524 enableTypeahead($input, ids, descrizioni); 525 if($input.val()){$('#'+$input.attr("id")).val($input.val());} 526 } 527 else { 528 disableTypeahead($input); 529 } 530 }); 531 } 532 else { 533 $wait.hide(); 534 $input.show(); 535 } 536} 537 538var decodeEntities = (function() { 539 // this prevents any overhead from creating the object each time 540 var element = document.createElement('div'); 541 542 function decodeHTMLEntities (str) { 543 if(str && typeof str === 'string') { 544 // strip script/html tags 545 str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, ''); 546 str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ''); 547 element.innerHTML = str; 548 str = element.textContent; 549 element.textContent = ''; 550 } 551 552 return str; 553 } 554 555 return decodeHTMLEntities; 556})(); 557 558function initValidation($form, callback) { 559 if($form && $form.length) { 560 console.log("initValidation on "+$form.attr("id")); 561 console.log("received callback ["+callback+"]"); 562 savedCallback = callback; 563 // $form.find('input, select, textarea').blur(function(){ 564 $form.on('blur', 'input,select,textarea', function(e){ 565 // valida al blur solo se non è datepicker 566 if(Object.keys($(this).data()).indexOf("datepicker")===-1){validate($(this));} 567 }); 568 $form.find('input[type=radio]').change(function(){validate($(this));}); 569 $form.find('input, select').keypress(function (e) { 570 if (e.which == 13) { 571 return false;
572 } 573 }); 574 575 $form.submit(function( event, triggered ) { 576 event.stopImmediatePropagation(); // avoid double submission 577 console.log("-----------------"); 578 console.log("form submitted"); 579 var invalidFields = $.map($form.find("input,textarea,select"), function(element) { if(typeof $(element).data("is-valid") !== 'undefined' && $(element).data("is-valid")===false) return $(element).attr("id"); }); 580 if(triggered) { 581 console.log("form is triggered, return true without checking"); 582 $form.find("input[name='submit']").removeAttr("name"); // remove input with name="submit" in form, which overrides the native form.submit (programmatically submits the form) method that is being called internally in jQuery causing the form not to submit 583 return true; 584 } 585 else if(validateForm($(this), savedCallback) && invalidFields.length == 0) { 586 console.log("callback is "+savedCallback); 587 console.log("form is valid, return true"); 588 $form.find("input[name='submit']").removeAttr("name"); // remove input with name="submit" in form, which overrides the native form.submit (programmatically submits the form) method that is being called internally in jQuery causing the form not to submit 589 return true; 590 } 591 else { 592 console.log("form is not valid, return false"); 593 console.log("prevent default"); 594 event.preventDefault(); 595 if(!$(".bootbox").is(":visible") && invalidFields.length>0) { 596 bootbox.alert("I dati inseriti contengono degli errori.", function(){ 597 var addOffset = 0; 598 if($('#header_border_fixed').length) { 599 addOffset = $('#header_border_fixed').height()+20; 600 } 601 var offset = $form.find(".text-danger").first().length?$form.find(".text-danger").first().offset().top-addOffset:0; 602 $('html, body').animate({scrollTop: offset}, 200); 603 }) 604 } 605 return false; 606 } 607 }); 608 } 609} 610 611function validate($field) { 612 if($field.next('.help-block').length>0) {$field.next('.help-block').remove();} 613 if($field.parent().parent().find(".help-block").length>0) {$field.parent().parent().find(".help-block").remove();} 614 var valid = false; 615 if($field.data("validate") && $field.is(":visible")) { 616 console.log("calling validatePhpType for field "+$field.attr("name")); 617 valid = validatePhpType($field,$field.data("validate")); 618 } 619 else if($field.attr("required") && $field.is(":visible")) { 620 if($field.attr("type")=="radio") { 621 //if($field.parent().prev("td").find('.help-block').length>0) {$field.parent().prev("td").find('.help-block').remove();} 622 /*var radios = $("[name="+$field.attr("name").replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" )+"]"); 623 for(var r in radios) { 624 if($field.is(':checked')) { valid = true; } 625 }*/ 626 var checkedVal = $("input[name="+$field.attr("name").replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" )+"]:checked").val(); 627 valid = checkedVal == "1" || checkedVal == "0"; 628 if($field.parent().prop("tagName")=="TD") { 629 if($field.parent().prev("td").find('.help-block').length<1) {$('<span class="help-block"></span>').appendTo($field.parent().prev("td"));} 630 $field.parent().parent().toggleClass("text-danger",!valid); 631 $field.parent().parent().toggleClass("has-success",valid); 632 if(!valid) { 633 //$('<span class="help-block">È obbligatorio specificare una risposta.</span>').appendTo($field.parent().prev("td")); 634 $field.parent().prev("td").find(".help-block").html("È obbligatorio specificare una risposta."); 635 } else { 636 $field.parent().prev("td").find(".help-block").html("Risposta impostata correttamente."); 637 } 638 } else { 639 if($field.parent().prev("td").find('.help-block').length>0) {$field.parent().prev("td").find('.help-block').remove();} 640 $field.parent().toggleClass("text-danger",!valid); 641 $field.parent().toggleClass("has-success",valid); 642 if(!valid) { 643 $('<span class="help-block">È obbligatorio scegliere un\'opzione.</span>').insertAfter($field); 644 } 645 } 646 } else { 647 valid = $field.val()!="" && $field.val()!=null; 648 if($field.next('.help-block').length>0) {$field.next('.help-block').remove();} 649 if($field.parent().parent().find(".help-block").length>0) {$field.parent().parent().find(".help-block").remove();} 650 if($field.parent().hasClass("input-group")) { 651 $field.parent().parent().toggleClass("text-danger",!valid); 652 $field.parent().parent().toggleClass("has-success",valid); 653 if(!valid) { 654 $('<span class="help-block">Questo campo è obbligatorio.</span>').insertAfter($field.parent()); 655 } 656 } else { 657 $field.parent().toggleClass("text-danger",!valid); 658 $field.parent().toggleClass("has-success",valid); 659 if(!valid) { 660 $('<span class="help-block">Questo campo è obbligatorio.</span>').insertAfter($field); 661 } 662 } 663 } 664 } 665 else { 666 valid = true; 667 if($field.parent().hasClass("input-group")) { 668 $field.parent().parent().toggleClass("text-danger",!valid); 669 $field.parent().parent().toggleClass("has-success",valid); 670 } else { 671 $field.parent().toggleClass("text-danger",!valid); 672 $field.parent().toggleClass("has-success",valid); 673 } 674 } 675 676 $field.data( "is-valid", valid ); 677 678 if(valid && $field.data("field-callback")) { 679 if($field.parent().hasClass("input-group")) { 680 $field.parent().parent().removeClass("text-danger"); 681 $field.parent().parent().removeClass("has-success"); 682 } else { 683 $field.parent().removeClass("text-danger"); 684 $field.parent().removeClass("has-success"); 685 } 686 $field.trigger($field.data("field-callback")); 687 } 688 689 return valid; 690} 691 692function validatePhpType($field, type) { 693 var value = $field.val().replace("C:\\fakepath\\","");
694 var valid = false; 695 var required = $field.attr("required"); 696 var minLength = $field.data("min-length"); 697 var maxLength = $field.data("max-length"); 698 var maxSize = $field.data("max-size"); 699 var fixedLength = $field.data("fixed-length"); 700 var notFuture = $field.data("not-future"); 701 var warning = $field.data("error-type")&&$field.data("error-type")=="warning"; 702 var message = ""; 703 704 if(required && value == "") { 705 valid = false; 706 warning = false; 707 message = "è obbligatorio"; 708 } 709 else if(required && value != "" && type=="money" && isNumber(value) && ( ( $field.data("allow-zero") && value.replace(".","").replace(",",".") < 0 ) || ( !$field.data("allow-zero") && value.replace(".","").replace(",",".")<=0) )) { 710 valid = false; 711 warning = false; 712 message = $field.data("allow-zero")?"non può essere negativo":"dev'essere maggiore di 0"; 713 } 714 else if(!required && value == "") { 715 valid = true; 716 } 717 else if(value != "" && minLength && value.length<minLength) { 718 valid = false; 719 message = "deve contenere almeno "+minLength+" caratteri"; 720 } 721 else if(value != "" && maxLength && value.length>maxLength) { 722 valid = false; 723 message = "non può contenere più di "+maxLength+" caratteri"; 724 if(warning) { message += ".<br>Proseguendo i caratteri eccessivi verranno troncati"; } 725 } 726 else if(value != "" && fixedLength && value.length!=fixedLength) { 727 valid = false; 728 message = "deve contenere "+fixedLength+" caratteri"; 729 } 730 else { 731 switch(type) { 732 case "piva": 733 valid = /^\d{11}$/.test(value); 734 message = "non contiene una Partita IVA valida"; 735 break; 736 case "cf": 737 var sesso = $('#'+$field.data('sesso-field')).val(); 738 var validCF = isCodiceFiscale(value, $('#'+$field.data('nascita-field')).val(), sesso); 739 var validCFformat = /^[A-Z]{6}[\dLMNP-V]{2}[A-EHLMPRST][\dLMNP-V]{2}[A-Z][\dLMNP-V]{3}[A-Z]$/.test(value); 740 valid = validCF; 741 if(warning && !valid && !validCFformat) { 742 warning = false; 743 } 744 message = "non contiene un codice fiscale valido"; 745 break; 746 case "cforpiva": 747 if($('#'+$field.data('sesso-field')).length==0) { 748 // non avendo specificato il sesso, non possiamo sapere se è persona fisica o giuridica o ditta individuale (ad es. partecipante benefici)
749 var validCF = isCodiceFiscale(value,false, false); 750 var validPiva = /^\d{11}$/.test(value); 751 var validCFformat = /^[A-Z]{6}[\dLMNP-V]{2}[A-EHLMPRST][\dLMNP-V]{2}[A-Z][\dLMNP-V]{3}[A-Z]$/.test(value); 752 valid = validPiva || validCF; 753 // warning è sempre a true perchè non posso determinare il tipo (cf o piva) 754 } else { 755 var sesso = $('#'+$field.data('sesso-field')).val(); 756 var validPFCF = isCodiceFiscale(value, $('#'+$field.data('nascita-field')).val(), sesso); 757 var validPiva = /^\d{11}$/.test(value); 758 var validCFformat = /^[A-Z]{6}[\dLMNP-V]{2}[A-EHLMPRST][\dLMNP-V]{2}[A-Z][\dLMNP-V]{3}[A-Z]$/.test(value); 759 var personaFisica = !sesso || (["M", "F"].indexOf(sesso)>-1); 760 var personaGiuridica = sesso == "G"; 761 valid = (!personaFisica && validPiva) || (personaGiuridica && validPiva) || ((personaFisica||!personaGiuridica) && validPFCF); 762 if(warning && !valid && (personaFisica && !validCFformat) && (personaGiuridica && !validPiva) && (!personaGiuridica && !personaFisica && !validPiva && !validCFformat)) { 763 warning = false; 764 } 765 } 766 message = "non contiene un codice fiscale o una p.iva valida"; 767 break; 768 case "cforpiva_length": 769 valid = value.length==11 || value.length==16; 770 message = "deve contenere 11 o 16 caratteri"; 771 break; 772 case "number": 773 valid = /^\d+$/.test(value); 774 message = "deve contenere un numero valido"; 775 break; 776 case "alphanumeric": 777 valid = /^[a-zA-Z0-9]+$/.test(value); 778 message = "puo' contenere solo lettere e numeri"; 779 break; 780 case "string": 781 valid = /^[a-zA-Z0-9 \.\-&"\u00C0-\u017F]+$/.test(value); 782 message = "puo' contenere solo lettere, lettere accentate, numeri, spazi, . - \" e &"; 783 break; 784 case "email": 785 valid = emailIsValid(value); 786 message = "deve contenere un indirizzo email valido"; 787 break; 788 case "money": 789 valid = isNumber(value); 790 message = "deve contenere un importo valido"; 791 break; 792 case "filesize": 793 var notZeroSize = isNotZeroSize($field); 794 if(!notZeroSize) { 795 valid = false; 796 message = "deve contenere un file di dimensioni maggiori di 0 byte"; 797 } else { 798 if(maxSize) { 799 valid = isBelowMaxSize($field, maxSize); 800 if(!valid) { 801 message = "contiene un file troppo grande. Le dimensioni massime consentite sono di "+((maxSize / 1048576).toFixed(0))+ "MB ("+maxSize+" byte)"; 802 } 803 } else { 804 valid = true; 805 } 806 } 807 break; 808 case "filename": 809 var filenameOk = isFilename(value); 810 var sizeOk = isNotZeroSize($field); 811 valid = filenameOk && sizeOk; 812 message = !sizeOk?"deve contenere un file di dimensioni maggiori di 0 byte":"può contenere solo un nome file composto da lettere non accentate, numeri, punti singoli, trattini ed underscore (trattino basso). Non vengono accettati caratteri accentati, simboli, doppi punti, spazi e caratteri speciali"; 813 if(warning && sizeOk) { message += ".<br>I caratteri non validi verranno eliminati automaticamente"; } 814 break; 815 case "extension": 816 var sizeOk = isNotZeroSize($field); 817 valid = sizeOk; 818 // non faccio il warning sul filename che tanto viene rinominato automaticamente 819 // var filenameOk = isFilename(value); 820 // valid = filenameOk && sizeOk; 821 // message = !sizeOk?"deve contenere un file di dimensioni maggiori di 0 byte":"può contenere solo un nome file composto da lettere non accentate, numeri, punti singoli, trattini ed underscore (trattino basso). Non vengono accettati caratteri accentati, simboli, doppi punti, spazi e caratteri speciali"; 822 // if(sizeOk && !filenameOk) { warning = true; message += ".<br>I caratteri non validi verranno eliminati automaticamente"; } 823 if(valid) { 824 var hasExtension = RegExp(/^(.*?)((?:\.[a-zA-Z0-9]{2,4})|(?:\.p7m|\.m7m)|(?:\.[a-zA-Z0-9]{2,4})(?:\.p7m|\.m7m))$/i); 825 if(hasExtension.test(value)) { 826 valid = hasValidExtension(value); 827 message = "deve contenere un file con una doppia estensione se il file è firmato digitalmente (ad esempio filefirmato.pdf.p7m)"; 828 } else { 829 valid = false;
830 message = "non può contenere file senza estensione"; 831 } 832 } else { 833 message = "deve contenere un file di dimensioni maggiori di 0 byte"; 834 } 835 break; 836 case "date": 837 valid = isDate(value, notFuture); 838 message = "deve contenere una data valida"; 839 break; 840 default: 841 valid = true; 842 break; 843 } 844 } 845 846 if($field.parent().hasClass("input-group")) { 847 $field.parent().parent().toggleClass("has-success",valid); 848 $field.parent().parent().toggleClass("has-warning",!valid&&warning); 849 $field.parent().parent().toggleClass("text-danger",!valid&&!warning); 850 if(!valid) { 851 $('<span class="help-block">Questo campo '+message+'.</span>').insertAfter($field.parent()); 852 } 853 } else { 854 $field.parent().toggleClass("has-success",valid); 855 $field.parent().toggleClass("has-warning",!valid&&warning); 856 $field.parent().toggleClass("text-danger",!valid&&!warning); 857 if(!valid) { 858 $('<span class="help-block">Questo campo '+message+'.</span>').insertAfter($field); 859 } 860 } 861 if(warning&&!valid){valid = warning;} 862 return valid; 863} 864 865// mi salvo qui callback, altrimenti diventa undefined tempo che facciamo il submit del form 866var savedCallback; 867function validateForm($form, callback) { 868 if(typeof callback === typeof undefined) { callback = false; } 869 $form.find(".has-success").removeClass("has-success"); 870 $form.find(".has-warning").removeClass("has-warning"); 871 $form.find(".text-danger").removeClass("text-danger"); 872 var formIsValid = true; 873 $form.find('input, select, textarea').each(function() { 874 if(typeof($(this).attr("id")) != "undefined" && $(this).is(":visible")) { 875 if(!validate($(this))){formIsValid=false;} 876 } 877 }); 878 var warnings = $form.find(".has-warning").length; 879 console.log("Form is valid: "+formIsValid); 880 console.log("Warnings: "+warnings); 881 882 if(!formIsValid) { 883 // se ci sono errori nel form interrompo l'esecuzione del submit ancora prima di verificare callback 884 bootbox.alert("I dati inseriti contengono degli errori.", function(){ 885 var addOffset = 0; 886 if($('#header_border_fixed').length) { 887 addOffset = $('#header_border_fixed').height()+20; 888 } 889 var offset = $form.find(".text-danger").first().length?$form.find(".text-danger").first().offset().top-addOffset:0; 890 $('html, body').animate({scrollTop: offset}, 200); 891 }) 892 return false; 893 } else { 894 // nessun errore sul form, verifichiamo callback 895 var callbackResult = {result: true, message: ""}; 896 console.log("check callback function "+callback); 897 if(callback) { 898 console.log("callback function "+callback+" exists"); 899 callbackResult = callback(); 900 } else { 901 console.log("callback function "+callback+" is not a valid callback"); 902 } 903 formIsValid = formIsValid && callbackResult.result; 904 var message = callbackResult.message && callbackResult.message!=""?callbackResult.message:"Si è verificato un errore."; 905 console.log("Callback result: "+callbackResult.result); 906 if(!formIsValid && callbackResult.result===false) { 907 console.log("Showing error message for !formIsValid (after callback)"); 908 bootbox.alert(message, function(){ }); 909 return false; 910 } 911 912 /*if(!formIsValid) { 913 bootbox.alert("I dati inseriti contengono degli errori.", function(){ 914 var addOffset = 0; 915 if($('#header_border_fixed').length) { 916 addOffset = $('#header_border_fixed').height()+20; 917 } 918 var offset = $form.find(".text-danger").first().length?$form.find(".text-danger").first().offset().top-addOffset:0; 919 $('html, body').animate({scrollTop: offset}, 200); 920 }); 921 return false; 922 }*/ 923 else { 924 // nessun errore anche su callback, verifichiamo i warning 925 console.log("Warnings: "+warnings); 926 if(warnings) { 927 console.log("Showing force dialog"); 928 bootbox.dialog({ 929 message: "Attenzione: i dati inseriti non risultano corretti. Proseguire comunque?", 930 buttons: { 931 "force": { 932 label: "Forza inserimento", 933 className: "btn-default", 934 callback: function() { console.log("Force dialog closing and forcing"); $form.trigger('submit', true); } 935 }, 936 "fix": { 937 label: "Modifica dati", 938 className: "btn-primary", 939 callback: function() { 940 console.log("Force dialog closing and staying"); 941 var addOffset = 0; 942 if($('#header_border_fixed').length) { 943 addOffset = $('#header_border_fixed').height()+20; 944 } 945 $('html, body').animate({scrollTop: $form.find(".has-warning").first().offset().top-addOffset}, 200); 946 } 947 } 948 } 949 }); 950 return false; // restituisco sempre false perchè bootbox non interrompe il processo in attesa di user input 951 // eventualmente faccio il submit se l'utente decide di forzare 952 } 953 else { return true; } 954 } 955 } 956} 957 958function hasValidExtension(fileName) { 959 var fileNameSplit = fileName.split("\\"); 960 if(fileNameSplit.length<2) { 961 fileNameSplit = fileName.split("/"); 962 }
963 fileName = fileNameSplit[fileNameSplit.length-1]; 964 965 var signed = RegExp(/(?:\.p7m|\.m7m)$/i); 966 var valid = true; 967 if(signed.test(fileName)) { 968 /*var validSignedExt = RegExp(/^(.*?)((?:\.[a-zA-Z0-9]{2,3})(?:\.p7m|\.m7m))$/i); 969 valid = validSignedExt.test(fileName);*/ 970 var validSignedExt = /^(?:.*?)(?:\.([a-zA-Z0-9]{2,4})){1}(?:\.(p7m|m7m)){1}$/i; 971 var matches = fileName.match(validSignedExt); 972 if(matches && matches.length>1) { 973 valid = matches[1] != "p7m" && matches[1] != "m7m"; 974 } else { 975 valid = false; 976 } 977 } 978 979 return valid; 980} 981 982 983function isFilename(fileName) { 984 var fileNameSplit = fileName.split("\\"); 985 if(fileNameSplit.length<2) 986 { 987 fileNameSplit = fileName.split("/"); 988 } 989 fileName = fileNameSplit[fileNameSplit.length-1]; 990 991 var regex = RegExp(/^[a-zA-Z_\.\-0-9]*$/); 992 var regex2 = RegExp(/\.{2,}/); 993 994 return regex.test(fileName)&&!regex2.test(fileName); 995} 996 997function isBelowMaxSize($field, maxSize) { 998 var belowMaxSize = false; 999 if(!window.FileReader) { 1000 // impossibile leggere il file 1001 } 1002 var input = $field[0]; 1003 if (!input) { 1004 // impossibile leggere il file 1005 } 1006 else if (!input.files) { 1007 // impossibile leggere il file 1008 } 1009 else if (!input.files[0]) { 1010 // impossibile leggere il file 1011 } 1012 else { 1013 file = input.files[0]; 1014 belowMaxSize = file.size<=maxSize; 1015 } 1016 return belowMaxSize; 1017} 1018 1019function isNotZeroSize($field) { 1020 var notZeroSize = false; 1021 if(!window.FileReader) { 1022 notZeroSize = true; 1023 } 1024 var input = $field[0]; 1025 if (!input) { 1026 notZeroSize = true; 1027 } 1028 else if (!input.files) { 1029 notZeroSize = true; 1030 } 1031 else if (!input.files[0]) { 1032 notZeroSize = true; 1033 } 1034 else { 1035 file = input.files[0]; 1036 notZeroSize = file.size>0; 1037 } 1038 return notZeroSize; 1039} 1040 1041function isCodiceFiscale(cf, dataNascita, sesso) { 1042 var str = cf.replace(/\s/g,'').toUpperCase(); // converte in maiuscolo e rimuove spazi bianchi 1043 1044 if(cf.length!=16) { 1045 return false; 1046 } 1047 1048 // verifica formato 1049 if(!/^[A-Z]{6}[\dLMNP-V]{2}[A-EHLMPRST][\dLMNP-V]{2}[A-Z][\dLMNP-V]{3}[A-Z]$/.test(str)) { 1050 return false; 1051 } 1052 1053 // verifica vocali/consonanti in nome/cognome 1054 var re = /^[^AEIOU]*[AEIOU]*X*$/; 1055 if(!re.test(str.substr(0,3)) || !re.test(str.substr(3,3))) { 1056 return false; 1057 } 1058 1059 // verifica data 1060 var day = str.substr(9,2); 1061 // TODO: gestire anni di nascita > 1999? 1062 var year = '19'+str.substr(6,2); 1063 1064 var female = false; 1065 if(day > 31){day = day -40; female = true;} 1066 1067 var months = 'ABCDEHLMPRST'; 1068 var month = months.indexOf(str.charAt(8)); 1069 if(dataNascita) { 1070 var dateString = day+'/'+(month+1)+'/'+year; 1071 1072 if(!isDate(dateString)) { 1073 return false; 1074 } 1075 } 1076 1077 // verifica corrispondenza date nascita 1078 var cfDate = new Date(year, month, day, 0,0,0,0); 1079 if(dataNascita) { 1080 var data = dataNascita.split('/'); 1081 var birthDate = new Date(data[2], data[1]-1, data[0], 0, 0, 0, 0); 1082 1083 if(cfDate.getTime() != birthDate.getTime()) { 1084 return false; 1085 } 1086 } 1087 1088 // verifica corrispondenza sesso 1089 if(!sesso || (["M", "F"].indexOf(sesso)<0) || sesso == 'F' && female || sesso == 'M' && !female) { 1090 // ok 1091 } else { 1092 return false; 1093 } 1094
1095 // verifica codice controllo (converte numeri in lettere e calcola checksum) 1096 str = str.replace(/\d/g, function(c) { return 'ABCDEFGHIJ'[c]; }); 1097 1098 for(var s=str.charCodeAt(15),i=1;i<15;i+=2) { 1099 s -= str.charCodeAt(i); 1100 } 1101 for(i=0;i<15;i+=2) { 1102 s -= 'BAFHJNPRTVCESULDGIMOQKWZYX'.charCodeAt(str.charCodeAt(i)-65); 1103 } 1104 1105 return Math.abs(s%26) == 0; 1106} 1107 1108function isNumber(n) { 1109 var nIT = n.replace(".","").replace(",","."); 1110 var numeroIT = !isNaN(parseFloat(nIT)) && isFinite(nIT); 1111 var numeroEN = !isNaN(parseFloat(n)) && isFinite(n); 1112 return (numeroIT && isFinite(numeroIT)) || (numeroEN && isFinite(numeroEN)); 1113} 1114 1115function emailIsValid(email) { 1116 var isValid = false; 1117 var user, domain; 1118 var emailsplit = email.split('@'); 1119 if(emailsplit.length == 2) { 1120 user = emailsplit[0]; 1121 domain = emailsplit[1]; 1122 if(domain.indexOf('.')>-1) { 1123 isValid = true; 1124 } 1125 } 1126 return isValid; 1127} 1128 1129function isDate(dateString, notFuture) { 1130 var data = dateString.split('/'); 1131 var dataDate = new Date(data[2], data[1]-1, data[0], 0, 0, 0, 0); 1132 var nowDate = new Date(); 1133 var dataMonth = data[1] - 1; 1134 var dataDateMonth = dataDate.getMonth(); 1135 var validDay = data[0] == dataDate.getDate(); 1136 var validMonth = data[1] - 1 == dataDate.getMonth(); 1137 var validYear = data[2] == dataDate.getFullYear() && dataDate.getFullYear() >= 1900; 1138 return validDay && validMonth && validYear && (!notFuture || (notFuture && dataDate.getTime() < nowDate.getTime())); 1139} 1140 1141function tableToUl($table){ 1142 if($table.is("table")){ 1143 var $ul=$("<ul>"); 1144 var empty=$table.find("td").length<1; 1145 var balanceColumns=false; 1146 $ul.addClass($table.attr("class")); 1147 if($table.find("[class^=cell-wide]").length==0){ 1148 $table.find("td").addClass("cell-wide"); 1149 balanceColumns=true 1150 }else{$ul.addClass("no-filler")} 1151 $ul.attr("id",$table.attr("id")); 1152 if($ul.attr("id")==""||typeof($ul.attr("id"))=="undefined"){ 1153 $ul.attr("id",$table.find("tbody").attr("id")) 1154 } 1155 if($ul.attr("id")==""||typeof($ul.attr("id"))=="undefined"){ 1156 var index=-1; 1157 for(var i=0;i<$allResponsiveTables.length;i++){ 1158 if($table.is($allResponsiveTables[i])){index=i} 1159 }if(index>-1){$ul.attr("id","table_"+index)} 1160 } 1161 var columns=[]; 1162 var htmlColumns=[]; 1163 var $allTableHeaders=$table.find("tr:has(th)"); 1164 1165 $allTableHeaders.each(function(){ 1166 var $li=$("<li>"); 1167 if($(this).find("th").length==1){ 1168 $li.addClass("table-caption"); 1169 $li.html($(this).find("th").html()) 1170 }else{ 1171 $li.addClass("table-header"); 1172 $li.addClass($(this).attr("class")); 1173 $(this).find("th").each(function(){ 1174 var $div=$("<div>"+$(this).html()+"</div>"); 1175 columns.push($(this).text()); 1176 var $link=$(this).find("a"); 1177 if($link.length>0){ 1178 htmlColumns.push($(this).html()); 1179 $link.addClass("btn btn-default"); 1180 $table.parent().find(".mobile-sorting").append($link) 1181 } 1182 $li.append($div) 1183 }); 1184 if(empty){ 1185 $li.find("div").css("width",((100/columns.length)*1.1)+"%") 1186 } 1187 } 1188 $li.appendTo($ul) 1189 }); 1190 $ul.insertBefore($table); 1191 var $tbody=$table.find("tbody"); 1192 $table.find("tfoot tr").each(function(){ 1193 $(this).appendTo($tbody)}); 1194 if(!empty){ 1195 var largestCol=rowsToLi($tbody,$ul,columns,balanceColumns); 1196 setCellWidths(largestCol,columns,$ul) 1197 } 1198 if($ul.find("li:not(.table-header)").find("a").length<1){ 1199 $ul.removeClass("row_linked") 1200 }if($(".page_navigation.pagination.pagination-desktop").length<1){ 1201 $(".page_navigation.pagination").addClass("pagination-desktop"); 1202 $(".sel_pagine").addClass("sel_pagine-desktop"); 1203 var $loadMore=$('<a class="btn btn-default btn-block">Carica altri</a>'); 1204 $loadMore.click(function(){ 1205 $(this).hide(); 1206 $(this).parent().append('<i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw muted"></i><span class="sr-only">Caricamento...</span>'); 1207 find(".fa-spin").remove(); 1208 $hiddenRows.slice(0,show_per_page).show(); 1209 var $hiddenRows=$container.find(".pagination_content .paginated_element:hidden"); 1210 if($hiddenRows.length>0){ 1211 $(this).show() 1212 } 1213 }); 1214 if($ul.find(".paginated_element:hidden").length>0){ 1215 if($(".pagination-mobile-loadmore").length<1){ 1216 $('<div class="pagination-mobile pagination-mobile-loadmore"></div>').insertAfter($ul) 1217 } 1218 $(".pagination-mobile-loadmore").append($loadMore) 1219 } 1220 } 1221 if($table.is("table")){ 1222 $table.remove() 1223 } 1224 } 1225 } 1226 1227/** 1228* 1229* @param {any} campoParam 1230* @param {string} alertMsg 1231*/ 1232function disableCampo(campoParam, alertMsg) { 1233 const campoToDisable = getCampo(campoParam); 1234 1235 if (!campoToDisable) { 1236 return; 1237 } 1238 1239 campoToDisable.attr('disabled', 'disabled'); 1240 if (alertMsg) { 1241 addAlertInfo(alertMsg, campoToDisable.parent()); 1242 } 1243 campoToDisable.val(null); 1244} 1245 1246/** 1247 * 1248 * @param {any} campoParam 1249 */ 1250function enableCampo(campoParam) { 1251 1252 const campoToEnable = getCampo(campoParam); 1253 1254 if (!campoToEnable) { 1255 return; 1256 } 1257 1258 campoToEnable.removeAttr('disabled'); 1259 campoToEnable.parent().find('.alert').remove(); 1260} 1261 1262function getCampo(campoParam) { 1263 1264 if (typeof campoParam === 'string') { 1265 1266 if (!campoParam || campoParam.length === 0) { 1267 return; 1268 } 1269 1270 if (campoParam.includes('#')) { 1271 return $(campoParam); 1272 1273 } else { 1274 return $('#' + campoParam); 1275 } 1276 } else if (campoParam instanceof jQuery) { 1277 return campoParam; 1278 } 1279 1280}
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.