MediaWiki:Common.js

Από Εθνικό Μητρώο Διοικητικών Διαδικασιών
Μετάβαση σε:πλοήγηση, αναζήτηση

Σημείωση: μετά την αποθήκευση, ίσως χρειαστεί να παρακάμψετε την προσωρινή μνήμη του προγράμματος περιήγησής σας για να δείτε τις αλλαγές.

  • Firefox / Safari: Κρατήστε πατημένο το Shift κάνοντας ταυτόχρονα κλικ στο κουμπί Ανανέωση ή πιέστε Ctrl-F5 ή Ctrl-R (⌘-R σε Mac)
  • Google Chrome: Πιέστε Ctrl-Shift-R (⌘-Shift-R σε Mac)
  • Internet Explorer: Κρατήστε πατημένο το Ctrl κάνοντας ταυτόχρονα κλικ στο κουμπί Ανανέωση, ή πιέστε Ctrl-F5
  • Opera: Εκκαθαρίστε την προσωρινή μνήμη από το μενού Εργαλεία → Προτιμήσεις
// ΠΑΡΑΤΗΡΗΣΕΙΣ
// 1) Πρέπει να τοποθετηθεί το 'var' μπροστά από τα ονόματα μεταβλητών κατά τη δήλωση
//    καθώς αν το παραλείψει κανείς, αυτές δηλώνονται ως properties του global object 'window',
//    εκτός αν υπάρχει σκοπιμότητα
//
// 2) Δηλώνονται πολλές μέθοδοι οι οποίες απλώς καλούνται στην επόμενη γραμμή. 
//    Μήπως να τις αντικαταστήσουμε με IIFEEs? Αυτό ταυτόχρονα θα βοηθήσει στο να διατηρούνται 
//    οι μεταβλητές σε ένα local scope.
//
// 3) Ενδεχομένως να πρέπει να προσθέσουμε error handling οταν καλούμε scripts από CDN
//
// 4) Καλό είναι περιορίσουμε στο μέγιστο την χρήση strings μέσα στον κώδικα και να τις τοποθετήσουμε
//    σε μεταβλητές ομαδοποιημένα, πχ σε σταθερές, λεκτικά, χρώματα κτλ
//
// 5) Χρειάζεται καθάρισμα του κώδικα, διότι υπάρχουν σημεία όπως το παρακάτω
//    else if( $(element).val() === "Απόφαση Διοικητικού Συμβουλίου" || 
//				$(element).val() === "Απόφαση Δημοτικού Συμβουλίου" || 
//				$(element).val() === "Απόφαση Περιφερειακού Συμβουλίου" || 
//				$(element).val() === "Εγκύκλιος" ||
//				$(element).val() === "Απόφαση Δημοτικού Συμβουλίου" 
//
// 6) Πρέπει να βγουν τα magic numbers και να μπουνε και αυτά σε μεταβλήτές/σταθερές 
//    ωστέ το όνομα να είναι ενδεικτικό της χρησιμότητας του

// Το script θα μπορούσε να χωριστεί σε μικρότερα. Ενδεικτικά:
// 1) Main
// 2) Constants / Variables
// 3) Utils (εναλλακτικά, μπορεί να συμπεριλαμβάνεται στο #1)
// 4) MainPage - Αρχική Σελίδα
// 5) Κατάλογος Διαδικασιών
// 6) Public Process
// 7) Form-related
// 7) Form validation rules
// 8) Λεκτικά (εναλλακτικά, μπορεί να συμπεριλαμβάνεται στο #2)

// Outer IIFEe to keep the scope local for variables declared with 'var'
(function(){
// **********************************************************
// ********** SECTION X - CONSTANTS **************
// **********************************************************
var API_ENDPOINT = '//reg-diavlos.gov.gr/api';
var JQUERY_UI_JS_URL = 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js';
var JQUERY_UI_CSS_URL = 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css';
var LITY_JS_URL = "https://reg-diavlos.gov.gr/skins/chameleon/resources/lity/lity.min.js";
var LITY_CSS_URL = "https://reg-diavlos.gov.gr/skins/chameleon/resources/lity/lity.min.css";
var SWIPER_JS_URL = "https://unpkg.com/swiper/swiper-bundle.js";
var SWIPER_CSS_URL = "https://unpkg.com/swiper/swiper-bundle.css";
var BASE_BPMN_URL = "//api.reg-diavlos.gov.gr/bpmn";
var BASE_DIAUGEIA_URL = "https://reg-diavlos.gov.gr/api/diavgeia/code/";

var SERVICE_NAMESPACES = ['ΥΕ', 'ΠΕ', 'ΠΔ', 'ΔΔ'];
var SERVICE_TAB_NAME = 'Διαδικασία';


// **********************************************************
// ******************* SECTION X - UTILS *********************
// **********************************************************
// Henceforth, add console warnings to console.warningLogs
// and handle any warning errors at runtime
console.stdwarning = console.warn.bind(console);
console.warningLogs = [];
console.warn = function() {
    console.warningLogs.push(Array.from(arguments));
    console.stdwarning.apply(console, arguments);
};
handleRuntimeWarningErrors = setInterval(function () {
	$.each(console.warningLogs, function (i, obj) {
		if ((obj[0] instanceof Error)) {
			if (!alert('Συνέβη σφάλμα κατά τη φόρτωση σελίδας. Πατήστε ΟΚ για ανανέωση.')) {
	    		location.reload(true);
	    		clearInterval(handleRuntimeWarningErrors);
	    	}
		}
	});
}, 1000);


// **********************************************************
// **************** SECTION X - SCRIPT LOADING **************
// **********************************************************
// jQuery-ui load
$.getScript( JQUERY_UI_JS_URL, function( data, textStatus, jqxhr ) {
	// Load the CSS as well
	$("head").append("<link>");
	var css = $("head").children(":last");
	css.attr({
		  rel:  "stylesheet",
		  type: "text/css",
		  href: JQUERY_UI_CSS_URL 
	});
    // TODO - Handle load error?
});

// load swiper script
jQuery.cachedScript = function( url, options ) {
	// Allow user to set any option except for dataType, cache, and url
	options = $.extend( options || {}, {
    	dataType: "script",
    	cache: true,
    	url: SWIPER_JS_URL 
	});

  // Use $.ajax() since it is more flexible than $.getScript
  // Return the jqXHR object so we can chain callbacks
	return jQuery.ajax( options );
};

// SCRIPT LOAD + OPERATION -> Comment for block classification purposes
// Show the popup for feedback everywhere.
$.getScript( LITY_JS_URL, function( data, textStatus, jqxhr ) {
	// Load the CSS as well
	$("head").append("<link>");
	var css = $("head").children(":last");
	css.attr({
		  rel:  "stylesheet",
		  type: "text/css",
		  href: LITY_CSS_URL 
	});
	
	// Set the link of the support page with the current url.
	if(  $('.support-link').length > 0 ) {
		var href = $('.support-link').attr( 'href' );
		href = href + '?from=' + $(location).attr('href');
		$('.support-link').attr( 'href', href );
	}
});


// **********************************************************
// *********** SECTION X - ELEMENT MANIPULATION *************
// **********************************************************
$(".action-formedit").append( "<div id='dialog' title='dialog' style='display: none'>Παρακαλώ πατήστε αποθήκευση</div>" );

setInterval( function () {
	$("#dialog").dialog({
                modal: true,
                title: "",
            	width: 300,
                height: 150,
                open: function (event, ui) {
                    setTimeout(function () {
                        $("#dialog").dialog("close");
                    }, 10000);
                }
            });
}, 900000); // 15minutes interval time


// Rename ΥΕ, ΠΕ, ΠΔ, ΔΔ tab text
tabLink = $('#p-namespaces .tab-group .selected a');
tabLinkText = tabLink.text();
$.each(SERVICE_NAMESPACES, function (i, ns) {
	if (tabLinkText == ns) {
		tabLink.text(SERVICE_TAB_NAME);
	}
});

// Remove "Προβολή φόρμας" tab button
$('div#ca-formedit:contains(Προβολή φόρμας)').remove();	

// Remove tab buttons for non-sysop users
if (mw.config.get('wgUserGroups').indexOf('sysop') == -1) {
	$('div#ca-move:contains(Ιστορικό)').remove();
}

if ((mw.config.get('wgUserGroups').indexOf('sysop') == -1) && (mw.config.get('wgUserGroups').indexOf('supervisor') == -1)) {
	$('div#ca-move:contains(Μετακίνηση)').remove();
}

// Fix menu selector.
if( $('.emd-menu-selector').length > 0 ) {
	$('.emd-menu-selector').on( 'click', function( e){
		e.preventDefault();
		$( '.p-personal-tools' ).toggleClass('opened');
	});
}

// Perform these on all pages.
// Remove all br tags
$('br').remove();

// Remove all empty paragraphs (trash).
$('p').filter(function () { return $.trim(this.innerHTML) === "" }).remove();
	
// This is foreas.
if( $('.ns-9000').length > 0 ) {
	/* TODO: Remove following. This functionality was replaced with External Data (inside template Φορέας). */
	// if( $('#org-secretariats').length > 0 ) {
	// 	var list_container = $('#org-secretariats');
	// 	var name = list_container.attr( 'data-name' );
	// 	if( name ) {
	// 		$.ajax({
	// 			url: API_ENDPOINT + '/units/name/'+name+'/unit_types/4,3,41/',
	// 			dataType: 'json',
	// 			crossDomain: true
	// 		}).done(function(data) {
	// 			if( data.success === true || data.success == 'true' ) {
	// 				$.each(data.result, function(i, obj) {
	// 				  //use obj.id and obj.name here, for example:
	// 				  list_container.append('<li>'+obj.preferredLabel+'</li>');
	// 				});
	// 			} else {
	// 				// It did not find anything.
	// 			}
	// 		}).fail(function() {
	// 			mw.log.error('Contacting service API failed for name: ' + name );
	// 		});
	// 	}
	// }
}
// **********************************************************
// ************ SECTION X - ΦΟΡΕΑΣ*********
// **********************************************************
if($('.ns-9000').length > 0 ) {
	setTimeout(function (){
		// console.log($('.headerSort').text());
		if($('.headerSort').length > 0 ){
			var thHeaderSort = $('th.headerSort');
			$(thHeaderSort).click();
		}
	}, 1000);
}
// **********************************************************
// ************ SECTION X - PAGES GENERATION     ************
// **********************************************************
// add styling to pages generation
if( $('.action-generatepages').length > 0){
	var form = $('form');
	var as = $(form).find('a');
	$.each(as, function(idx, a){
		$(a).after("<br/>");
	});
}

// **********************************************************
// ************ SECTION X - ΑΝΑΖΗΤΗΣΗ*********
// **********************************************************
if( $('.rootpage-Ειδικό_Αναζήτηση').length > 0 ){
	$('.mw-search-profile-tabs').hide();
	$('#mw-searchoptions').hide();
}

// **********************************************************
// ********* SECTION X - MAIN PAGE - ΑΡΧΙΚΗ ΣΕΛΙΔΑ **********
// **********************************************************
if( $('.rootpage-Αρχική_σελίδα').length > 0 || $('.page-Αρχική_σελίδα').length > 0) {
	
	var initalizeBootstrapTooltips = function(){
      $('[data-toggle="tooltip"]').tooltip({
		 delay: {show: 100, hide: 200},
		 position: { my: "bottom", at: "top" }
	  });
	};
	
	// swiperJS load
	$.cachedScript( "ajax/swiper-bundle.js" ).done( function( script, textStatus ) {
	  // Load the CSS as well
		$("head").append("<link>");
		var css = $("head").children(":last");
		css.attr({
			  rel:  "stylesheet",
			  type: "text/css",
			  href: SWIPER_CSS_URL
		});
		
		var swiper = new Swiper('.swiper-container', {
			// Optional parameters
			direction: 'horizontal',
			loop: true,
			// Navigation arrows
			navigation: {
				nextEl: '.swiper-button-next',
			    prevEl: '.swiper-button-prev',
			},
			on: {
    			init: initalizeBootstrapTooltips
		    }
	        // autoplay: {
	        //   delay: 2500,
	        //   disableOnInteraction: false,
	        // },
		});
	});
}

// **********************************************************
// ************ SECTION X - ΚΑΤΑΛΟΓΟΣ ΔΙΑΔΙΚΑΣΙΩΝ ***********
// **********************************************************
var categoryCatalogEl = $('.mw-category-generated');
var foreasCatalogEl = $('.mw-spcontent');
/* T6179
* Τα επιμέρους φίλτρα περιορισμού των αποτελεσμάτων (σε φορείς, μητρώα) να τοπο-
* θετηθούν μετά τον κατάλογο των φορέων χωρίς τίτλους ( Λειτουργία, τύπος) (υπό έλεγχο).
*/
if (foreasCatalogEl.length > 0){
	var drilldownResultsEl = $('.drilldown-results');
	
	function findDrilldownResultsAndMoveIt(){
		if (!drilldownResultsEl) return;
		var drilldownFiltersEl =  drilldownResultsEl.find('.drilldown-filters');
		if (!drilldownFiltersEl) return;
	    moveDrilldownResultsAtBottomOfPage(drilldownFiltersEl);
	}
	
	function moveDrilldownResultsAtBottomOfPage(drilldownFiltersEl){
		var drilldownText = drilldownFiltersEl.prev();
        drilldownText.addClass("drilldown-text");
        drilldownText.detach();
        drilldownFiltersEl.detach();
        drilldownResultsEl.append(drilldownText);
        drilldownResultsEl.append(drilldownFiltersEl);
        drilldownResultsEl.addClass("moved");
	}
	
	findDrilldownResultsAndMoveIt();
}


if( categoryCatalogEl.length > 0 || foreasCatalogEl.length > 0 ) {
	
	function setGrayNonPublished(elements, message ) {
		$.each($(elements), function (idx, element) {
			$(element).removeAttr("href");
			
			// add class Tooltip
			$(element).addClass("tooltip tooltip-list");
			$(element).append("<span class='tooltiptext'>"+message+"</span>");
		})
	}
	
	YE = $('a[title*="ΥΕ:"]');
	PE = $('a[title*="ΠΕ:"]');
	PD = $('a[title*="ΠΔ:"]');
	
	setGrayNonPublished(YE, 'Η διαδικασία είναι υπό επεξεργασία');
	setGrayNonPublished(PE, 'Η διαδικασία είναι υπό επεξεργασία');
	setGrayNonPublished(PD, 'Η διαδικασία είναι υπό επεξεργασία');
	
    // Non-authenticated user
	if( $('.emd-menu-login').length > 0 ) {
		DD = $('a[title*="ΔΔ:"]');
		setGrayNonPublished(DD, 'Η διαδικασία είναι υπό επεξεργασία');
	} else {
		if (categoryCatalogEl){
			$('.pageSchema.mw-collapsible ' ).show();
			$('.drilldownInfo.mw-collapsible ' ).show();
		}
	}
	
	/* T6254
	* Τα Bullets στους τίτλους των διαδικασιών εξακολουθούν να εμφανίζονται στη δεύτερη γραμμή του
	* τίτλου και όχι στην πρώτη.
	*/
	if( categoryCatalogEl ) {
		var uls = $(categoryCatalogEl).find('ul');
		$.each(uls, function (idx, ul) {
			$(ul).css('list-style', 'none');
		})
	}
}

// **********************************************************
// *************** SECTION X - PUBLIC PROCESS ***************
// **********************************************************
if( $('.emd-single-content-wrapper').length > 0 ) {
	
	// Remove all empty divs
	$( '.emd-row-area > div' ).filter(function () { return $.trim(this.innerHTML) === "" }).remove();
	
    // TODO - Transform to IIFEEs
	/** T6009 SDG
	* 
	**/	 
	function setSdgStuff() {
	 	sdgs = $(".process_sdg");
	 	if(sdgs.length >= 1){
	 		sdg_containerParent = $('.sdg-feedback').parent();
	 		
	 		opinion = "<a id='your-opinion' href='https://foq.youreurope.europa.eu/info-service-noft?lang=el' target='_blank'><h5>Η άποψη σου</h5></a>";
	 		sdg_containerParent.append(opinion);
	 	}
	}
	setSdgStuff();
	
	// Remove elements needed 
	$( '.remove-me' ).remove();
	
	// Process elements withing page.
	$('#firstHeading').prepend( '<span>' + $( '#code-process_id' ).text() + '</span>' );

	// Add the page scroller here.
	$( '#emd-single-sidebar > li > a').on( 'click', function( e ) {
		e.preventDefault();
		
		$('.emd-active-menu').removeClass( 'emd-active-menu' );
		$( this ).parent().addClass( 'emd-active-menu' );
		
		var scrollTo  =  $( $(this).attr( 'href' ) ).offset().top - 30;
		
		$('html, body').animate({
			scrollTop: scrollTo
		}, 500, 'swing');
	} );
	
	// Automatically move listed elements below content.
	var movableElements = [
		'process_conditions',
		'process_evidences_cost',
		'process_evidences',
		'process_rules',
		'process_steps',
		'process_steps_digital',
		'process_provision_digital_locations',
		'process_useful_links',
		'process_nace',
		'process_sdg'
	];
	
	$.each( movableElements, function ( key, element_class ) {
		$('.' + element_class).each( function() {
			if( $( '#container_' + element_class + '_glance' ).length > 0 ) {
				$(this).clone().appendTo( '#container_' + element_class + '_glance' );
			}
			$(this).appendTo( '#container_' + element_class );
		} );
	});
	
	// See if we should add a BPMN Popup here.
	if( $('.process_steps').length > 0 || $('.process_steps_digital').length > 0  ) {
				
		if( $('.process_steps').length > 0 ) {
			$('a[href="#bpmn_manual_click"]').addClass( 'manual_click' );
		} else {
			$('a[href="#bpmn_manual_click"]').remove();
		}
		if( $('.process_steps_digital').length > 0 ) {
			$('a[href="#bpmn_digital_click"]').addClass( 'digital_click' );
		} else {
			$('a[href="#bpmn_digital_click"]').remove();
		}
		
		public_bpmn_on_click();
	} else {
		$( '#bpmn_links').remove();
	}
	
	// Remove sections without steps
	$('.section-content-template-container').each( function(){
		var children = $(this).find( 'li' );	
		//This is empty. Remove it.
		if( children.length < 1 ) {
			if( ! $(this).hasClass( 'emd-has-content' ) ) {
				$(this).closest( '.emd-row-area' ).remove();
			}
		} else {
			$(this).closest( '.emd-row-area' ).addClass( 'emd-has-content' );
		}
	});
	
	// Remove subsection withouth steps
	$('.section-content-template-container-inline').each( function(){
		var children = $(this).find( 'li' );	
		//This is empty. Remove it.
		if( children.length < 1 ) {
			$(this).closest( '.section-content-template-container-inline-parent' ).remove();
		} else {
			$(this).closest( '.emd-row-area' ).addClass( 'emd-has-content' );
		}
	});
	
	// Remove empty sections
	$( '.emd-row-area' ).each( function(){
		if( ! $(this).hasClass( 'emd-has-content' ) ) {
		
			var children = $(this).find( '.section-content' );
			if( children.length < 1 ) {
				$(this).remove();
			}
		}
	});
	
	// Remove not needed nav links
	$('#emd-single-sidebar > li > a').each(function(){
		if( $( $(this).attr('href') ).length < 1 ) {
			$(this).parent().remove();
		}
	});
	
	// Shorten texts
	$( '.process_evidences > .list-description').each( function(){
		var content = $(this).text();
		content = content.substring(0,100);
		content = content +  ' ...';
		 $(this).text( content );
	});
	
	$( '.is-child').each( function(){
		var is_child = $(this).text();
		if( 'Ναι' == is_child ) {
			$(this).closest( '.process_list_item' ).addClass( 'child-process' );
		} 
		$(this).remove();
	});
	
	$( '.is-exit').each( function(){
		var is_exit = $(this).text();
		if( 'Ναι' == is_exit ) {
			$(this).closest( '.process_list_item' ).addClass( 'exit-process' );
		} 
		$(this).remove();
	});
	
	$('.list-more-container' ).each( function(){
		
		if( !$.trim(  $(this).html() ).length ) {
			$(this).parent().find( '.list-more' ).remove();
			$(this).remove();
		}	
	});
	
	// Add Sticky Sidebar
	var sticky_url = "https://cdnjs.cloudflare.com/ajax/libs/sticky-sidebar/3.3.1/jquery.sticky-sidebar.js";
	
	$.getScript( sticky_url, function( data, textStatus, jqxhr ) {
		var sidebar = new StickySidebar('#emd-single-main-container', {
			topSpacing: 20,
			bottomSpacing: 20,
			containerSelector: '#emd-single-main-container',
			innerWrapperSelector: '#emd-single-sidebar'
		});
	});
	
	$('.list-more').on( 'click', function(e){
		e.preventDefault();
		
		$(this).toggleClass('opened');
		$(this).closest( 'li' ).find( '.list-more-container' ).toggleClass( 'emd-visible' );
		
		if( $(this).hasClass('opened') ) {
			$(this).removeClass('fa-caret-down').addClass('fa-caret-up');
		} else {
			$(this).addClass('fa-caret-down').removeClass('fa-caret-up');
		}
	});
	
	// round process_cost_min
	$('#process_cost_min').text(parseFloat($('#process_cost_min').text()).toFixed(2));
	$('#process_cost_max').text(parseFloat($('#process_cost_max').text()).toFixed(2));
	
    // TODO - Transform to IIFEEs
	/** T5914 
	* ο εμφανιζόμενο κόστος στο «Με μια ματιά» να εμφανίζει το σύμβολο "~" δίπλα στο νούμερο, 
	* εφόσον υπάρχει έστω και ένα εναλλακτικό παράβολο/τέλος 
    **/
	function setApproximateSymbolToCost () {
		sumOfAllCosts = 0; // sum of all costs (alternative or not)
		$.each($('.process_evidences_cost'), function (idx, cost){
			sumOfAllCosts = sumOfAllCosts + parseFloat($(cost).find('.list-min').text().split(" ")[0]);
		});
		
		process_cost_minINT = parseFloat($('#process_cost_min').text());
		sumOfAllCosts = parseFloat(sumOfAllCosts.toFixed(2));
		
		if(process_cost_minINT != sumOfAllCosts){
			$('#process_cost_min').text('~ '+ $('#process_cost_min').text());
		}
	}
	setApproximateSymbolToCost();
	
	/** T5915
	*	Στην ενότητα «Με μια ματιά» να εμφανίζεται «Εκτιμώμενος χρόνος υλοποίησης» 
	*	μόνο αν έχει συμπληρωθεί ο εκτιμώμενος χρόνος υλοποίησης, αλλιώς «προθεσμία υλοποίησης» 
	*	αν έχει συμπληρωθεί η προθεσμία. 
	*	Εάν δεν έχιε συμπληρωθεί τίποτα να εμφανίζει «Εκτιμώμενος χρόνος»
	**/
	function setApproximateTime() {
		item = $('#process_estimated_implementation_time');
		titleText = 'Εκτιμώμενος Χρόνος';
		if(item){
			item = $('#process_deadline_type');
			titleText = 'Προθεσμία υλοποίησης';
		}
		
		title = $(item).closest('.section-content-item').find('.mw-headline');
		$(title).text(titleText);
	}
	setApproximateTime();
	
	/** T5922
	* process_provision_digital_locations_glance
	**/
	function setNoProvisionDigital () {
	 	provisions = $('#container_process_provision_digital_locations_glance');
	 	provisionsChildren = $(provisions).children();
	 	provisionsLen = provisionsChildren.length;

	 	if(provisionsLen === 0){
	 		$(provisions).append('<div>Δεν παρέχεται ψηφιακά</div>');
	 	}
	}
	setNoProvisionDigital();
	 
	 /**
	  * 
	  T5961 
	  * 
	  **/
	 function removeTotalDigitalSteps() {
	 	process_total_duration_steps_digital_min = $('#process_total_duration_steps_digital_min');
	 	topElem = $("div.section-content-item.border-top");
	 	
	 	process_evidence_step_digital_total_number = $('.process_evidence_step_digital_total_number');

	 	valueMin = $(process_total_duration_steps_digital_min).text().split(" ")[1];
	 	valueMax = $(process_total_duration_steps_digital_min).text().split(" ")[3];

	 	if(valueMin === "0" && valueMax === "0"){
	 		$(topElem).hide();
	 	}
	 	
	 	if(valueMin === valueMax) {
	 		$(process_total_duration_steps_digital_min).text(valueMin);
	 	}
	 }
	 removeTotalDigitalSteps();
	 
	/** T6057 FIX Εμφάνισης URLs
	**/
	function fixUrlShown(){
		var listValues = $('.list-value');
		
		$.each(listValues, function (i, listValue){
			var listLabel = $(listValue).prev();
			var a = $(listValue).find('a');
			if(a.length > 0) {
				if(listLabel.text().includes('Σχετιζόμενη διαδικασία')){
					var newText = $(a).attr('title').split(":")[1];
					a.text(newText);
				}else{
					// a.text('Σύνδεσμος');
					var len = a.text().length;
					var truncated = a.text().substring(0, len/3) + '...' + a.text().substring(2*len/3+1, len);
					a.text(truncated);
				}
			}
		});
	 }
	 fixUrlShown();
	 
	/** T5734
	* Η εμφάνιση της νομοθεσίας δεν είναι κατατοπιστική στον χρήστη
	**/
	function reOrderLaw() {
	 	ruleContainers = $('.rule-container');

	 	$.each(ruleContainers, function (idx, ruleContainer) {
	 		listtype = $(ruleContainer).find('.list-type').text();
	 		listnumber = $(ruleContainer).find('.list-number').text();
	 		listyear = $(ruleContainer).find('.list-year').text();
	 		
	 		listgazettenumber = $(ruleContainer).find('.list-gazette-number').text();
	 		listgazetteissue = $(ruleContainer).find('.list-gazette-issue').text();
	 		listarticle = $(ruleContainer).find('.list-article').text();
	 		
	 		$(ruleContainer).children().remove();
	 		
	 		$(ruleContainer).append("<span>"+ listtype + "</span>");
	 		
	 		if(listnumber) {
	 			$(ruleContainer).append("<span> " + listnumber + "/" + listyear + "</span>");
	 		}
	 		
	 		if(listgazettenumber) {
	 			$(ruleContainer).append("<span> (ΦΕΚ "+listgazettenumber + "/" + listgazetteissue + ")</span>");
	 		}
	 		
	 		if(listarticle) {
	 			$(ruleContainer).append( "<span>" + " Άρθρα " + listarticle + "</span>");
	 		}
	 		
	 		listValue = $(ruleContainer).next().next().find("a");
	 		if(listValue){
	 			listValue.text("Σύνδεσμος");
	 		}
	 	});
	}
	reOrderLaw();
	
	/**
	 * T5927, Τ6090
	 * Καταστήματα παροχής
	 **/
	 function setProvisionOrgGroup() {
	 	var process_provision_org_group_Parent = $('#Σημεία_εξυπηρέτησης').parent().parent();
	 	var process_provision_org_group_Values = $(process_provision_org_group_Parent).find('.section-content-value');
	 	var process_provision_org_group_Values_LENGTH = $(process_provision_org_group_Values).length;
	 	
	 	var foreis = $('#Φορέας_που_την_παρέχει').closest('.section-content-item').find('.section-content-value');
	 	
	 	function appendToElement(foreis) {
	 		if(foreis.length != 0){
		 		$.each(foreis, function(idx, foreas){
		 			$(foreas).clone().appendTo(process_provision_org_group_Parent);
		 		});
		 	}
	 	}
	 	
	 	// Αν δεν υπάρχουν καταστήματα παροχής βάλε τον Φορέα που την παρέχει
	 	if(process_provision_org_group_Values_LENGTH < 1) {
	 		appendToElement(foreis);
	 	}else{
	 		// Αν υπάρχουν καταστήματα παροχής και υπάρχει ο αναφερόμενος φορέας
	 		// βάλε το Οργανική μονάδα θεσμικού φορέα αν υπάρχει
	 		// αλλιώς βάλε τον Αναφερόμενο φορέα
	 		$.each(process_provision_org_group_Values, function(idx, value){
	 			var p = $(value).find('p');
	 			var text = $(p).text().trim();
	 			
	 			if(text.includes("Αναφερόμενος φορέας")){
	 				process_provision_org_owner_directory = $("#Οργανική_μονάδα_θεσμικού_φορέα").closest('.section-content-title').next().find('.section-content-value');
	 				if(process_provision_org_owner_directory.length > 0) {
	 					var newText = text.replace("Αναφερόμενος φορέας",process_provision_org_owner_directory.text());
	 					$(p).text(newText);
	 				}else if(foreis.length != 0) {
	 					appendToElement(foreis);
	 					text = text.replace("Αναφερόμενος φορέας,","");
	 					text = text.replace("Αναφερόμενος φορέας","");
	 					text = text.replace(", Αναφερόμενος φορέας","");
	 					$(p).text(text);
	 				}
	 			}
	 		});
	 	}
	 }
	 setProvisionOrgGroup();
	
	/**
	  * T6203 
	  * Όταν η διαδικασία έχει μόνο ψηφιακά βήματα (δεν έχει κανονικά),
	  * δηλαδή έχει μόνο ψηφιακή υλοποίηση να εμφανίζεται μόνο ο Εκτιμώμενος χρόνος και όχι το άθροισμα των ψηφιακών βημάτων-εκτιμώμενος χρόνος ψηφιακά).
	 **/
	(function checkAndHideDigitalStepsSum(){
		var hasPhysicalSteps= function(){
			return $('.process_steps').length > 0;
		}
		var hasDigitalSteps = function(){
			return $('.process_steps_digital').length > 0;
		}
		if (hasDigitalSteps() && !hasPhysicalSteps()){
			(function hideDigitalStepsSum(){
				var el = document.getElementById("Εκτιμώμενος_χρόνος_(ψηφιακά)");
				var parentEl = el.parentElement;
				if (!parentEl) return;
				var grandParentEl = parentEl.parentElement;
				if (!grandParentEl) return;
				grandParentEl.style.display = "none";
			})();
		}
	})();
	
	/* T6234
     * Η πληροφορία «Φορέας που την παρέχει» πρέπει να φύγει από τις Βασικές Πληροφορίες,
     * επειδή το περιεχόμενό της όταν υπάρχει εμφανίζεται στα σημεία εξυπηρέτησης.(Περίπτωση Αναφερόμενου Φορέα)
    */
	(function swapAnaferomenosForeas() {
	    var $pointsOfServiceEl = $('#points-of-service');
	    
	    if (!$pointsOfServiceEl.length) return;
	
	        function hasValueAnaferomenosForeas() {
	            if ($($pointsOfServiceEl).text().split(",").indexOf("Αναφερόμενος φορέας") > -1) return true;
	            return false;
	        }
	        
	        if (!hasValueAnaferomenosForeas()) return;
	
	        var $foreas = $('#Φορέας_που_την_παρέχει').closest('.section-content-item').find('.section-content-value > a');
	        
	        if ($foreas.length) {
	            var newText = ($pointsOfServiceEl).text().split(',').filter(function(val, index, a) {
	                return (val !== "Αναφερόμενος φορέας");
	             }).join(",");
	            $($pointsOfServiceEl).text(newText);
	            
	            var foreasOuterHtml = $foreas[0].outerHTML;
	            var oldInnerHTML = $($pointsOfServiceEl).html();
	            $($pointsOfServiceEl).html(oldInnerHTML + ", " + foreasOuterHtml);
	            $($foreas).closest('.section-content-item').remove();
	        }
	})();
}

function public_bpmn_on_click() {

	var url = BASE_BPMN_URL + '/?uuid=' + $( '#code-process_uuid' ).text() ;
	
	$('#bpmn_links_container a').each( function( ){
		var type = 'manual';
		
		if( $(this).hasClass( 'digital_click') ) {
			type = 'digital';
		}
		
		url = url + '&type=' + type + '&popup=true';
		$(this).attr( 'href', url );
		$(this).attr( 'data-lity', true );
		console.log($(this));
	});	
}


// **********************************************************
// ******************** SECTION X - FORM ********************
// **********************************************************
uuid = {
	is: function (string) {
		uuidRegExp = new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/);
		return uuidRegExp.test(string);
	},
	v4: function () {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
			var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
			return v.toString(16);
		});
	}
};

// TODO - Why not declare this function inside the above object literal?
uuid.n_digit_number = function (n) {
	return uuid.v4().match(/\d/g).join('').substr(0, n);
};

// TODO - Put 'var' in front of variable declarations since omitting 'var' declares the variables in the global scope (window object)
// TODO - Differentiate constants from other varables like those with boolean values
mw.loader.using( [ 'mediawiki.util' ] ).done( function () {
	/* Begin of mw.loader.using callback */
    var servicesFormPageName = 'Φόρμα:Διαδικασίες';
    var servicesEMDProcessManagementPageName = 'Ειδικό:EMDProcessManagement';
    var servicesFormEditSpecialPagePrefix = 'Ειδικό:ΕπεξεργασίαΦόρμας/Διαδικασίες/';
    var serviceCanonicalNamespace = 'Διαδικασία';
    var serviceTitleMaxLength = 125;
    var formEditAction = 'formedit';
    var pageIsServicesFormCreationPage = mw.config.get( 'wgPageName' ) == servicesFormPageName;
    var pageIsServicesEMDProcessManagementPage = mw.config.get( 'wgPageName' ) == servicesEMDProcessManagementPageName;
    var pageIsServicesFormEditPage = (mw.config.get( 'wgPageName' ).startsWith(servicesFormEditSpecialPagePrefix)) || 
		(mw.config.get('wgCanonicalNamespace') == serviceCanonicalNamespace && mw.config.get('wgAction') == formEditAction) ||
		$('#firstHeading').text().includes(serviceCanonicalNamespace);
    var serviceUuidInputNameSuffix = '[process_uuid]';
    var serviceIdInputNameSuffix = '[process_id]';
    var codeBaseErrorMessage = 'Ασύμβατος κωδικός ';
    var evidenceErrorId = 'evidence-error';
    var evidenceErrorMessage = codeBaseErrorMessage + '(μορφή: 2-4 αριθμοί, π.χ. 12 ή 7206).';
    var evidenceErrorHTML = '<span id="' + evidenceErrorId + '" class="error" style="color: #dc3545;">' + evidenceErrorMessage + '</span>';
    var evidenceCostCode = 'process_evidence_cost_code';
    var evidenceCostCodeNameSuffix = '[' + evidenceCostCode + ']';
    var evidenceCostDescriptionSuffix = '[process_evidence_cost_description]';
    var evidenceCostMinSuffix = '[process_evidence_cost_min]';
    var evidenceCostMaxSuffix = '[process_evidence_cost_max]';
    var evidenceCostCodeButtonClass = evidenceCostCode + '-button';
    var evidenceCostCodeInputsSelector = '[name$="' + evidenceCostCodeNameSuffix + '"]';
    var evidenceCostDescriptionInputsSelector = '[name$="' + evidenceCostDescriptionSuffix + '"]';
    var evidenceCostMinInputsSelector = '[name$="' + evidenceCostMinSuffix + '"]';
    var evidenceCostMaxInputsSelector = '[name$="' + evidenceCostMaxSuffix + '"]';
    var evidenceCostCodeApiEndpoint = API_ENDPOINT + '/paravola/code/';
    var evidenceCodeRegex = new RegExp(/^(?:\d{2,4})?$/);
    var naceCode = 'process_nace_code';
    var naceCodeNameSuffix = '[' + naceCode + ']';
    var naceCodeInputSelector = '[name$="' + naceCodeNameSuffix + '"]';
    var naceCodeDescriptionSuffix = '[process_nace_description]'
    var naceCodeDescriptionSelector = '[name$="' + naceCodeDescriptionSuffix + '"]';
    var naceCodeButtonId = naceCode + '-button';
    var naceCodeApiEndpoint = API_ENDPOINT + '/nace/code/';
    var naceCodeRegex = new RegExp(/^(?:\d{1,2}\.\d{1,2})?$/);
    var naceErrorId = 'nace-error';
    var naceErrorMessage = codeBaseErrorMessage + '(μορφή: ΧΧ.ΧΧ, όπου Χ αριθμός).';
    var naceErrorHTML = '<label id="' + naceErrorId + '" class="error" style="color: #dc3545;">' + naceErrorMessage + '</span>';
    var sdgCode = 'process_sdg_code';
    var sdgCodeNameSuffix = '[' + sdgCode + ']';
    var sdgTitleSuffix = '[process_sdg_title]';
    var sdgDescriptionSuffix = '[process_sdg_description]';
    var sdgCodeΙnputsSelector = '[name$="' + sdgCodeNameSuffix + '"]';
    var sdgTitleInputsSelector = '[name$="' + sdgTitleSuffix + '"]';
    var sdgDescriptionInputsSelector = '[name$="' + sdgDescriptionSuffix + '"]';
    var sdgCodeButtonClass = sdgCode + '-button';
    var sdgCodeApiEndpoint = API_ENDPOINT + '/sdg/code/';
    var sdgCodeRegex = new RegExp(/^(?:[A-Z]\d)?$/);
    var sdgErrorId = 'sdg-error';
    var sdgErrorMessage = codeBaseErrorMessage + '(μορφή: ΛΧ, όπου Λ λατινικός χαρακτήρας και Χ αριθμός, π.χ. F1)';
    var sdgErrorHTML = '<span id="' + sdgErrorId + '" class="error" style="color: #dc3545;">' + sdgErrorMessage + '</span>';
    var tabsSelector = '.oo-ui-labelElement-label';
    var uniqueIdLength = 6;

	/**
	 * Assign IDs to Service
	 * 
	 * @author [[User:Ckarageorgkaneen]]
	 * 
	 */
	
	function assignUuid(inputElement) {
		$(inputElement).val(uuid.v4());
	}
	
	function assignId(inputElement) {
		function assignUniqueId() {
			id = uuid.n_digit_number(uniqueIdLength);
			$.ajax({
				url: API_ENDPOINT + '/service/id/' + id,
				dataType: 'json',
			}).done(function(data) {
				if( data.success === true || data.success == 'true' ) {
					// Id already exists
					assignUniqueId();
				} else {
					// Id is unique
					$(inputElement).val(id);
				}
			}).fail(function() {
				mw.log.error('Contacting service API failed for id: ' + id);
			});
		}
		assignUniqueId();
	}
	
	if (pageIsServicesFormEditPage) {
		// Set uuid
		uuidInputElement = $('[name$="' + serviceUuidInputNameSuffix + '"]');
		uuidInputElementValue = $(uuidInputElement).val();
		// Set as readonly
		$(uuidInputElement).prop("readonly", true);
		if (!uuidInputElementValue) {
			// Assign uuid
			assignUuid(uuidInputElement);
		}
		// Set id
		idInputElement = $('[name$="' + serviceIdInputNameSuffix + '"]');
		idInputElementValue = $(idInputElement).val();
		// Set as readonly
		$(idInputElement).prop("readonly", true);
		if (!idInputElementValue || idInputElementValue.length != uniqueIdLength) {
			assignId(idInputElement);
		}
	}
	
	/**
	* Add the Link to produce BPMN
	*/ /*
	if (pageIsServicesFormEditPage) {
		
		uuidInputElement = $('[name$="' + serviceUuidInputNameSuffix + '"]');
		uuidInputElementValue = $(uuidInputElement).val();
		
		hasManualSteps = false;
		hasDigitalSteps = false;
			
		if ( uuidInputElementValue ) {
			// TODO: Calculate this correctly
			hasManualSteps = true;
			hasDigitalSteps = true;
		}
		
		if( hasManualSteps ) {
			var bpmnFileInputManual = $('input[name="process[process_bpmn_file]"]');
					
			if( '' === bpmnFileInputManual.val() ) {
				bpmnFileInputManual.after( '<a id="bpmn-fetch-manual" href="#" class="" style="">Παραγωγή BPMN αρχείου</a>' );
			} else {
				bpmnFileInputManual.after( '<a id="bpmn-fetch-manual" href="#" class="" style="">Παραγωγή Νέου BPMN αρχείου</a>' );
			}
			
			$('#bpmn-fetch-manual').on( 'click', function( e ) { 
				e.preventDefault();
				$('select[name="process[process_bpmn_source]"]').val( 'Αυτόματη Εξαγωγή' );
				produceAndFetchBPMNFile( bpmnFileInputManual, uuidInputElementValue, 'manual' );
			});
		} else {
			// Hide BPMN Manual Fields
		}
		
		if( hasDigitalSteps ) {		
			var bpmnFileInputDigital = $('input[name="process[process_bpmn_digital_file]"]');
					
			if( '' === bpmnFileInputDigital.val() ) {
				bpmnFileInputDigital.after( '<a id="bpmn-fetch-digital" href="#" class="" style="">Παραγωγή BPMN αρχείου</a>' );
			} else {
				bpmnFileInputDigital.after( '<a id="bpmn-fetch-digital" href="#" class="" style="">Παραγωγή Νέου BPMN αρχείου</a>' );
			}
			
			$('#bpmn-fetch-digital').on( 'click', function( e ) {
				e.preventDefault();
				$('select[name="process[process_bpmn_digital_source]"]').val( 'Αυτόματη Εξαγωγή' );
				produceAndFetchBPMNFile( bpmnFileInputDigital, uuidInputElementValue, 'digital' );
			});
		} else {
			// Hide BPMN Digital Fields
		}
	} */

    /**
	 * Fetches the actual BPNM file
	 */
    var produceAndFetchBPMNFile = function( bpmnFileInput, processUuid, bpmnType ) {
		
		$.ajax({
				url: '/bpmn/uuid/' + processUuid + '/type/' + bpmnType,
				dataType: 'json',
				beforeSend: function() {
					// do something before running the request
					$('#bpmn-error').remove();
				}
			}).done(function(data) {
				
				// process data and autofill based on reponse
				if( data.success ) {
					
					bpmnFileInput.val( data.result );
					
				} else {
					bpmnFileInput.after( '<span id="bpmn-error" class="error" style="color: rgb(255, 0, 0);">' + data.result + '</span>' );
				}
			}).fail(function() {
				// code
			}).always(function() {
				// code that runs regardless of request succeeding or failing
			});
	};
	
	
	/**
	 * Services Page Form Validation
	 * 
	 * @author [[User:Ckarageorgkaneen]]
	 */
	if (pageIsServicesEMDProcessManagementPage || pageIsServicesFormEditPage) {
		successClass = 'success';
		errorClass = 'error';
		
		builtInValidationMethods = [
			'required',
			'remote',
			'minlength',
			'maxlength',
			'rangelength',
			'min',
			'max',
			'range',
			'step',
			'email',
			'url',
			'date',
			'dateISO',
			'number',
			'digits',
			'equalTo'
		];
		
		
		loadJQueryValidationPlugin = function (onLoadFunction) {
			var validationScript = document.createElement('script');
		    validationScript.onload = onLoadFunction;
		    validationScript.src = 'https://cdn.jsdelivr.net/npm/jquery-validation@1.19.2/dist/jquery.validate.min.js';
			document.head.appendChild(validationScript);
		};
		
		checkValidParentheses = function (expr) {
		    holder = [];
		    openBrackets = ['«'];
		    closedBrackets = ['»'];
		    for(var i = 0; i < expr.length; i++){
		    	letter = expr.charAt(i);
		        if(openBrackets.includes(letter)){
		            holder.push(letter);
		        }else if(closedBrackets.includes(letter)){
		            openPair = openBrackets[closedBrackets.indexOf(letter)];
		            if(holder[holder.length - 1] === openPair){
		                holder.splice(-1,1);
		            }else{
		                holder.push(letter);
		                break;
		            }
		        }
		    }
		    return (holder.length === 0);
		};
		
		minMaxComparisonCheckObject = function (isMin) {
			minString = 'min';
			maxString = 'max';
			method = function (value, element) {
				if (value === '') {
					return true;
				}
				if (isMin) {
					comparisonString = minString;
					comparisonComplementString = maxString;
					comparisonFunction = function (num1, num2) {
						return num1 <= num2;
					};
				} else {
					comparisonString = maxString;
					comparisonComplementString = minString;
					comparisonFunction = function (num1, num2) {
						return num1 >= num2;
					};
				}
				elementName = $(element).attr('name');
				if (!elementName.includes(comparisonString)) {
					mw.log.error('Element name: ' + elementName + ' does not include "' + comparisonString + '".');
					return true;
				}
				complementElementName = elementName.replace(comparisonString, comparisonComplementString);
				complementElement = $('input[name="' + complementElementName + '"]');
				if ((complementElement === null) || (complementElement === undefined)) {
					mw.log.error('Cannot find complementElement.');
					return true;
				}
				// For greek comma decimal format
				// value = Number(value.replace(',', '.'));
				// complementElementValue = Number($(complementElement).val().replace(',', '.'));
				value = Number(value);
				complementElementValue = Number($(complementElement).val());
				compareResult = comparisonFunction(value, complementElementValue);
				if (compareResult) {
					$(complementElement).removeClass(errorClass);
					$('#' + $(complementElement).attr('id') + '-' + errorClass).remove();
					$(complementElement).addClass(successClass);
				}
				return compareResult;
			};
			
			if (isMin) {
				message = 'Μεγαλύτερο από το ' + maxString + '.';
			} else {
				message = 'Μικρότερο από το ' + minString + '.';	
			}			
			return {
				method: method,
				message: message
			};
		};
		
		autofillMinMaxFromComplementObject = function (isMin, isFieldRequired) {
			minString = 'min';
			maxString = 'max';
			method = function (value, element) {
				// Make sure autofill happens when cursor is out of focus (use stops writing)
				if ((!$(element).is(':focus'))) {
					if (isMin) {
						comparisonString = minString;
						comparisonComplementString = maxString;
					} else {
						comparisonString = maxString;
						comparisonComplementString = minString;
					}
					elementName = $(element).attr('name');
					if (!elementName.includes(comparisonString)) {
						mw.log.error('Element name: ' + elementName + ' does not include "' + comparisonString + '".');
						return true;
					}
					complementElementName = elementName.replace(comparisonString, comparisonComplementString);
					complementElement = $('input[name="' + complementElementName + '"]');
					if(elementName.includes('digital')){
						complementElementDurationType = $('select[name$="process_step_digital_duration_type]"]');
					}else{
						complementElementDurationType = $('select[name$="process_step_duration_type]"]');
					}
					
					if ((complementElement === null) || (complementElement === undefined) || (complementElementDurationType === undefined)) {
						mw.log.error('Cannot find complementElement.');
						return true;
					}
					valueNumber = Number(value);
					complementElementValue = $(complementElement).val();
					// Fill complement element value (only if it is empty, 
					// e.g. if min value is 5 and max value is empty, make max value == 5)
					if (complementElementValue == '' && !isNaN(valueNumber)) {
						$(complementElement).val(valueNumber);
						// $(complementElementDurationType).val('Δευτερόλεπτα'); // set also Μονάδα μέτρησης χρόνου
					}
					// Fill this element only if it is empty, based on complement
					complementElementValueNumber = Number(complementElementValue);
					if (value == '' && !isNaN(complementElementValueNumber)) {
						// console.log(complementElementValueNumber)
						$(element).val(complementElementValueNumber);
					}
				}
				if (isFieldRequired) {
					return $(element).val() !== '';
				}
				return true;
			};
			return {
				method: method,
				message: isFieldRequired ? 'Υποχρεωτικό πεδίο.' : null,
			};
		};
		
		naturalNumberMaxDigitsObject = function (maxDigits) {
			return {
				method: function (value, element) {
					naturalNumberMaxDigitsCheckRegex = new RegExp('^(?:[1-9](?:\\d{1,' + (maxDigits - 1) + '})?)?$');
					return naturalNumberMaxDigitsCheckRegex.test(value);
				},
				message: 'Μόνο φυσικοί αριθμοί εως ' + maxDigits + ' ψηφία.'
			};
		};
		
		decisionYearCheckObject = function () {
			firstDecisionYear = 1830;
			currentYear = new Date().getFullYear();
			return {
				method : function (value, element) {
					if (value === '') {
						return true;
					}
					valueNumber = Number(value);
					return (valueNumber >= firstDecisionYear) && (valueNumber <= currentYear);
				},
				message: 'Αποδεκτά έτη: '+ firstDecisionYear + '-' + currentYear + '.',
			};
		};
		
		processRuleType = function(element) {
			process_rule_ada = $(element).closest('tbody').find('[name$="process_rule_ada]"]');
			process_rule_gazette_doc_number = $(element).closest('tbody').find('[name$="process_rule_gazette_doc_number]"]');
			process_rule_gazette_doc_issue = $(element).closest('tbody').find('[name$="process_rule_gazette_doc_issue]"]');
			

			if($(element).val() === "Νόμος" ||
				$(element).val() === "Ευρωπαϊκός Κανονισμός" ||
				$(element).val() === "Ευρωπαϊκή Οδηγία" ||
				$(element).val() === "Προεδρικό Διάταγμα" ||
				$(element).val() === "Βασιλικό Διάταγμα" ||
				$(element).val() === "Διεθνής Σύμβαση" ||
				$(element).val() === "Νομοθετικό Διάταγμα" ||
				$(element).val() === "Απόφαση ευρωπαϊκών οργάνων"
			){
				// disable process_rule_ada
				$(process_rule_ada).prop('disabled', 'disabled');
				//enable Fek
				process_rule_gazette_doc_number.prop('disabled', false);
				process_rule_gazette_doc_issue.prop('disabled', false);
			}else if( $(element).val() === "Απόφαση Διοικητικού Συμβουλίου" || 
				$(element).val() === "Απόφαση Δημοτικού Συμβουλίου" || 
				$(element).val() === "Απόφαση Περιφερειακού Συμβουλίου" || 
				$(element).val() === "Εγκύκλιος" ||
				$(element).val() === "Απόφαση Δημοτικού Συμβουλίου" 
			){
				// enable process_rule_ada
				process_rule_ada.prop('disabled', false);
				// disable FEK
				process_rule_gazette_doc_number.prop('disabled', 'disabled');
				process_rule_gazette_doc_issue.prop('disabled', 'disabled');
			}else{
				//enable ALL
				process_rule_ada.prop('disabled', false);
				process_rule_gazette_doc_number.prop('disabled', false);
				process_rule_gazette_doc_issue.prop('disabled', false);
			}
		}
		
		validationObjects = {
			adaValidation: {
				method: function (value, element) {
					var code = $(element).val();
					var success = false;
					var url = BASE_DIAUGEIA_URL + encodeURI(code) ;
					if(code === "" || code === " "){
						return true;
					}
					$.ajax({
						url: url,
						async: false,
						dataType: 'json',
						crossDomain: true,
					}).done( function (data){
						if(data.success === true || data.success === 'true') {
							success = true;
						}
					}).fail(function (data) {
						console.log('fail');
					});
					return success;

				},
				message: "Λάθος Αριθμός Διαδικτυακής ανάρτησης",
			},
			servicesLastStepChildDisable: {
				method: function (value, element){
					
					
					var alert_message = "Δεν μπορεί να είναι το τελευταίο βήμα, βήμα διακλάδωσης, παρακαλώ εισαγάγετε ένα τελικό βημα ολοκλήρωσης της διαδικασίας";

					$(value).change( function () {
						var process_step_childs = $('[name$="process_step_child][value]"]');
						var num_id = $(value).closest('tbody').find('[name$="process_step_num_id]"]');
						var num_idINT = parseInt($(num_id).val());
						var process_step_childsLEN = process_step_childs.length - 1;
						if(num_idINT === process_step_childsLEN && $(value).is(':checked') && num_idINT >= 6) {
							alert(alert_message);
							$(value).prop('checked', false);
							return false;
						}else{
							return true;
						}
					})
				},
				message: "Δεν γίνεται"
			},
			servicesEvidenceType: {
				method: function(value, element){
					// console.log(value, element);
					
					elem = $('#'+$(value).attr('id'));
				
					process_evidence_identification_type = $(elem).closest('tbody').find('[name$="process_evidence_identification_type][]"]');
					// console.log(process_evidence_identification_type);
					
					if($(elem).attr('name').includes('process_evidence_type')){
						name = $(elem).attr('name');
						templateInstancePrefix = name.substr(0, name.indexOf(']') + 1);
						process_evidence_identification_type_otherInputName = templateInstancePrefix + '[process_evidence_identification_type_other]';
						process_evidence_identification_type_other = $('[name="' + process_evidence_identification_type_otherInputName + '"]');
						
						if($(elem).val() === 'Αίτηση' || $(elem).val() === 'Ένσταση/Προσφυγή' || $(elem).val() === 'Αναφορά/Καταγγελία' || $(elem).val() === 'Γνωστοποίηση/Αναγγελία/Ανακοίνωση'){
							process_evidence_identification_type.prop('disabled', false);
							if($(process_evidence_identification_type).val().includes('Άλλο')){
								process_evidence_identification_type_other.prop('disabled', false);
							}else {
								process_evidence_identification_type_other.prop('disabled', 'disabled');
							}
						}else {
							process_evidence_identification_type_other.val('');
							process_evidence_identification_type_other.prop('disabled', 'disabled');
							process_evidence_identification_type.prop('disabled', 'disabled');
						}
						
						

						$(elem).change(function () {
							if($(elem).val() === 'Αίτηση' || $(elem).val() === 'Ένσταση/Προσφυγή' || $(elem).val() === 'Αναφορά/Καταγγελία' || $(elem).val() === 'Γνωστοποίηση/Ανακοίνωση'){
								process_evidence_identification_type.prop('disabled', false);
								$(process_evidence_identification_type).change( function () {
									// console.log($(process_evidence_identification_type).val())
									if($(process_evidence_identification_type).val().includes('Άλλο')){
										process_evidence_identification_type_other.prop('disabled', false);
									}else {
										process_evidence_identification_type_other.prop('disabled', 'disabled');
									}
								});
							}else {
								process_evidence_identification_type.prop('disabled', 'disabled');
								process_evidence_identification_type_other.prop('disabled', 'disabled');
								process_evidence_identification_type_other.val('');
							}
						});
					}
					
					return true;
					
				}	
			},
			disableFirst: {
				method: function (value, element){
					// console.log(element);
					return true;
				},
				message: ""
			},
			servicesProcessRuleType: {
				method: function (value, element) {
					if(value === "" || value === " ")
						return false;
					
					processRuleType(element); // first click
					
					// select change handler for Είδος
					$(element).change( function () {
						processRuleType(element);
					});
					
					return true;
				},
				message: "Υποχρεωτικό πεδίο"
			},
			servicesFirstCharCheck: {
				method: function (value, element) {
							servicesFirstCharCheckRegex = new RegExp(/^(?:[Α-ΩΆ-Ώ1-9][^]*)?$/);
							return servicesFirstCharCheckRegex.test(value);
						},
				message: 'Δε μπορεί να αρχίζει με: μικρά, λατινικά ή σύμβολα.'
			},
			servicesFirstWordCheck: {
				method: function (value, element) {
					firstWord = value.split(' ')[0];
					onlyGreekAlphanumsCheckRegex = new RegExp(/^(?:[\dΑ-ΩΆ-Ώα-ωίϊΐόάέύϋΰήώ]+)?$/);
					return onlyGreekAlphanumsCheckRegex.test(firstWord);
				},
				message: 'Αποδεκτοί χαρακτήρες πρώτης λέξης: ελληνικά ή αριθμοί.'
			},
			servicesTitleLengthCheck: {
				method: function (value, element) {
					return value.length <= serviceTitleMaxLength;
				},
				message: 'Ακατάλληλο μήκος τίτλου.'
			},
			servicesTitleOtherCharsCheck: {
				method: function (value, element) {
					servicesTitleOtherCharsCheckRegex = new RegExp(/^(?:[Α-ΩΆ-Ώ1-9](?:[\dα-ωά-ώa-z\.\'"\-–,\:()«»&\r\n\/]+)?(?: [\dΑ-ΩΆ-ΏA-Zα-ωά-ώa-z\.\'"\-–,\:()«»&\r\n\/]+)*)?$/);
					return servicesTitleOtherCharsCheckRegex.test(value);
				},
				message: 'Αποδεκτοί χαρακτήρες: γράμματα, αριθμοί, \., \', ", -, –, <b>,</b>, :, (, ),«, », &, /'
			},
			servicesUrlTitleOtherCharsCheck: {
				method: function (value, element) {
					servicesUrlTitleOtherCharsCheckRegex = new RegExp(/^(?:(?:[Α-ΩΆ-ΏA-Za-z1-9](?:[\dα-ωά-ώa-z\.\'"\-–()«»\/]+)?)+(?: [\dΑ-ΩΆ-ΏA-Zα-ωά-ώa-z\.\'"\-–()«»\/]+)*)?$/);
					return servicesUrlTitleOtherCharsCheckRegex.test(value);
				},
				message: 'Αποδεκτοί χαρακτήρες: γράμματα, αριθμοί, \., \', ", -, –, (, ),«, », /'
			},
			greekNumberCheck: {
				method: function (value, element) {
					greekNumberCheckRegex = new RegExp(/^\d*\,?\d*$/);
					return greekNumberCheckRegex.test(value);
				},
				message: "Πρέπει να είναι αριθμός (αποδεκτό σύμβολο υποδιαστολής: ',')."
			},
			minZeroCheck: {
				method: function (value, element) {
					number = Number(value.replace(',', '.'));
					if (!isNaN(number)) {
						return number >= 0;	
					}
				},
				message: "Ελάχιστη τιμή: 0."
			},
			notAllLatinAlphanumCheck: {
				method: function (value, element) {
					allLatinAlphanumCheckRegex = new RegExp(/^[\da-zA-Z\s]+$/);
					return !allLatinAlphanumCheckRegex.test(value);
				},
				message: 'Πρέπει να περιέχει ελληνικούς χαρακτήρες.'
			},
			illegalEndingCharsCheck: {
				method: function (value, element) {
					illegalEndingCharsCheckRegex = new RegExp(/^(?:([^](?![\.&:,\/\-–]$))+)?$/);
					return illegalEndingCharsCheckRegex.test(value);
				},
				message: 'Δε μπορεί να τελειώνει με <b>.</b>, &, :, <b>,</b>, /, -, –'
			},
			validParenthesesCheck: {
				method: function (value, element) {
					return checkValidParentheses(value);
				},
				message: 'Λανθασμένος αριθμός ή τοποθέτηση εισαγωγικών.'
			},
			validQuotesCheck: {
				method: function (value, element) {
					double_quote_count = (value.match(/"/g) || []).length;
					return (double_quote_count % 2 === 0);
				},
				message: 'Λανθασμένος αριθμός <b>"</b> εισαγωγικών.'
			},
			validAmbersunCheck: {
				method: function (value, element) {
					ambersun_count = (value.match(/&/g) || []).length;
					if (ambersun_count > 1) {
						return false;	
					}
					else if (ambersun_count == 1) {
						return /^.*\s+&\s+.*$/.test(value);
					}
					return true;
				},
				message: 'Το σύμβολο \'&\' πρέπει να εμφανίζεται μόνο μία φορά, ανάμεσα σε δύο λέξεις.'
			},
			notOneWordCheck: {
				method: function (value, element) {
					if (value !== '') {
						return value.split(' ').length != 1;	
					}
					return true;
				},
				message: 'Πρέπει να είναι περισσότερες από μία λέξη.'
			},
			evidenceCostType: {
				method: function (value, element){
					// console.log(value, element);
					name = $(element).attr('name');
					templateInstancePrefix = name.substr(0, name.indexOf(']') + 1);
					process_evidence_cost_codeInputName = templateInstancePrefix + '[process_evidence_cost_code]';
					process_evidence_cost_codeInput = $('[name="' + process_evidence_cost_codeInputName + '"]');
					process_evidence_cost_payment_typeInputName = templateInstancePrefix + '[process_evidence_cost_payment_type][]';
					process_evidence_cost_payment_type = $('[name="' + process_evidence_cost_payment_typeInputName + '"]');
					
					process_evidence_cost_code_button = $(process_evidence_cost_codeInput).closest('tbody').find('.process_evidence_cost_code-button');
					// console.log(process_evidence_cost_codeInput, process_evidence_cost_code_button);

					var disableEvidenceCode = function () {
						if($(element).val() === "Παράβολο"){
							$(process_evidence_cost_codeInput).prop('disabled', false);
							$(process_evidence_cost_code_button).prop('disabled', false);
							$(process_evidence_cost_payment_type).val(['Ψηφιακά (web banking)','Ψηφιακά (χρεωστική/πιστωτική κάρτα)','ΕΛΤΑ', 'Ταμείο τραπέζης']);
							$(process_evidence_cost_payment_type).trigger('change');
						}else {
							$(process_evidence_cost_codeInput).prop('disabled', 'disabled');
							$(process_evidence_cost_code_button).prop('disabled', 'disabled');
						}
					}
					
					$(disableEvidenceCode);
					
					if(!(jQuery._data( element, "events" ).change)){
				    	$(element).change(disableEvidenceCode);
				    }
					
					return true;
				},
				message: ""
			},
			evidenceCodeCheck: {
				method: function (value, element) {
					return evidenceCodeRegex.test(value);
				},
				message: evidenceErrorMessage,
			},
			naceCodeCheck: {
				method: function (value, element) {
					return naceCodeRegex.test(value);
				},
				message: naceErrorMessage
			},
			sdgCodeCheck: {
				method: function (value, element) {
					return sdgCodeRegex.test(value);
				},
				message: sdgErrorMessage
			},
			durationTypeCheck: {
				method: function (element, value) {
					// e.g. "process steps[0a][process_step_duration_type]"
					var name = $(element).attr('name');
					// e.g. "process steps[0a]"
					var templateInstancePrefix = name.substr(0, name.indexOf(']') + 1);
					var stepDurationMinInputName = templateInstancePrefix + '[process_step_duration_min]';
					var stepDurationMaxInputName = templateInstancePrefix + '[process_step_duration_max]';
					var stepDurationStepDurationTypeName = templateInstancePrefix + '[process_step_duration_type]';
					var stepDurationMinInput = $('[name="' + stepDurationMinInputName + '"]');
					var stepDurationMaxInput = $('[name="' + stepDurationMaxInputName + '"]');
					var stepDurationStepDurationTypeInput = $('[name$="' + stepDurationStepDurationTypeName + '"]');

					if($(stepDurationMinInput).val() == "" || $(stepDurationMaxInput).val() == "") {
						$(stepDurationStepDurationTypeInput).prop('disabled', 'disabled');
					}else{
						$(stepDurationStepDurationTypeInput).prop('disabled', false);
					}
					
					if($(stepDurationMinInput).val() == 0 && ($(stepDurationMaxInput).val() == 0 || $(stepDurationMaxInput).val() === "" || $(stepDurationMaxInput).val() === " ")){
						$(stepDurationStepDurationTypeInput).val("Δευτερόλεπτα")
					}
					if($(stepDurationMinInput).val() == 0 && ($(stepDurationMaxInput).val() == 0 || $(stepDurationMaxInput).val() === "" || $(stepDurationMaxInput).val() === " ")){
						$(stepDurationStepDurationTypeInput).val("Δευτερόλεπτα")
					}
					
					
					$(stepDurationMinInput).change( function() {
						if($(stepDurationMinInput).val() == 0 && ($(stepDurationMaxInput).val() == 0 || $(stepDurationMaxInput).val() === "" || $(stepDurationMaxInput).val() === " ")){
							$(stepDurationStepDurationTypeInput).val("Δευτερόλεπτα")
						}
						
						if($(stepDurationMinInput).val() != "") {
							$(stepDurationStepDurationTypeInput).prop('disabled', false);
						}else {
							$(stepDurationStepDurationTypeInput).prop('disabled', 'disabled');
						}
					});
					
					$(stepDurationMaxInput).change( function() {
						if($(stepDurationMinInput).val() == 0 && ($(stepDurationMaxInput).val() == 0 || $(stepDurationMaxInput).val() === "" || $(stepDurationMaxInput).val() === " ")){
							$(stepDurationStepDurationTypeInput).val("Δευτερόλεπτα")
						}
						
						if($(stepDurationMaxInput).val() != "") {
							$(stepDurationStepDurationTypeInput).prop('disabled', false);
						}else {
							$(stepDurationStepDurationTypeInput).prop('disabled', 'disabled');
						}
					});
				
					
					return Number($(stepDurationMinInput).val()) || Number($(stepDurationMaxInput).val());
				}
			},
			orgOwnerCheck: {
				method: function (element) {
					// e.g. "process[process_org_owner]"
					name = $(element).attr('name');
					// e.g. "process"
					templateInstancePrefix = name.substr(0, name.indexOf('['));
					privOrgOwnerInputName = templateInstancePrefix + '[process_org_owner_private]';
					privOrgOwnerInput = $('[name="' + privOrgOwnerInputName + '"]');
					return !privOrgOwnerInput.val();
				}
			},
			deadlineTypeCheck: {
				method: function (element) {
					// e.g. "process[process_deadline_type]"
					name = $(element).attr('name');
					// e.g. "process"
					templateInstancePrefix = name.substr(0, name.indexOf('['));
					deadlineInputName = templateInstancePrefix + '[process_deadline]';
					deadlineTypeInputName = templateInstancePrefix + '[process_deadline_type]';
					deadlineInput = $('[name="' + deadlineInputName + '"]');
					deadlineTypeInput = $('[name="' + deadlineTypeInputName + '"]');
					deadlineInputValue = $(deadlineInput).val();
					process_estimated_implementation_time = $('input[name$="process_estimated_implementation_time]"]');
					process_estimated_implementation_time_type = $('[name$="process_estimated_implementation_time_type]"]');
					
					console.log($(deadlineInput).val(), $(element).val());
					
					// if($(deadlineTypeInput).val() === ""){
					// 	$(deadlineTypeInput).val('Δευτερόλεπτα');
					// }
					
					//first run
					if($(deadlineInput).val() != ""){
						$(process_estimated_implementation_time).prop('disabled', 'disabled');
						$(process_estimated_implementation_time_type).prop('disabled', 'disabled');
					}else{
						$(process_estimated_implementation_time).prop('disabled', false);
						$(process_estimated_implementation_time_type).prop('disabled', false);
						return true;
					}
					
					$(process_estimated_implementation_time).change( function() {
						if($(process_estimated_implementation_time).val() != "") {
							$(deadlineTypeInput).prop('disabled', 'disabled');
							$(deadlineInput).prop('disabled', 'disabled');
						}else {
							$(deadlineTypeInput).prop('disabled', false);
							$(deadlineInput).prop('disabled', false);
						}	
					});
					
					$(deadlineInput).change( function() {
						if($(deadlineInput).val() != ""){
							$(process_estimated_implementation_time).prop('disabled', 'disabled');
							$(process_estimated_implementation_time_type).prop('disabled', 'disabled');
						}else{
							$(process_estimated_implementation_time).prop('disabled', false);
							$(process_estimated_implementation_time_type).prop('disabled', false);
							return true;
						}
					});
					
					return deadlineInputValue != "";
				},
			},
			estImplTimeTypeCheck: {
				method: function (element) {
					// e.g. "process[process_estimated_implementation_time]"
					name = $(element).attr('name');
					// e.g. "process"
					templateInstancePrefix = name.substr(0, name.indexOf('['));
					estImplTimeInputName = templateInstancePrefix + '[process_estimated_implementation_time]';
					estImplTimeTypeInputName = templateInstancePrefix + '[process_estimated_implementation_time_type]';
					estImplTimeInput = $('[name="' + estImplTimeInputName + '"]');
					estImplTimeTypeInput = $('[name="' + estImplTimeTypeInputName + '"]');
					estImplTimeInputValue = $(estImplTimeInput).val();
					process_deadline = $('input[name$="process_deadline]"]');
					process_deadline_type = $('[name$="process_deadline_type]"]');
					
					// console.log($(estImplTimeInput))
					
					// if($(estImplTimeTypeInput).val() === '') {
					// 	$(estImplTimeTypeInput).val('Δευτερόλεπτα');
					// }
					
					// first run
					if($(estImplTimeInput).val() != ""){
						$(process_deadline).prop('disabled', 'disabled');
						$(process_deadline_type).prop('disabled', 'disabled');
					}else{
						$(process_deadline).prop('disabled', false);
						$(process_deadline_type).prop('disabled', false);
						return true;
					}
					
					$(estImplTimeInput).change(function() {
						if($(estImplTimeInput).val() != ""){
							$(process_deadline).prop('disabled', 'disabled');
							$(process_deadline_type).prop('disabled', 'disabled');
						}else{
							$(process_deadline).prop('disabled', false);
							$(process_deadline_type).prop('disabled', false);
							return true;
						}
					});
					
					
					return estImplTimeInputValue != "";
				}
			},
			lessThanMaxCheck: minMaxComparisonCheckObject(true),
			moreThanMinCheck: minMaxComparisonCheckObject(false),
			autofillMin: autofillMinMaxFromComplementObject(true, false),
			autofillMax: autofillMinMaxFromComplementObject(false, false),
			autofillMinRequired: autofillMinMaxFromComplementObject(true, true),
			autofillMaxRequired: autofillMinMaxFromComplementObject(false, true),
			naturalNumberThreeDigitsMaxCheck: naturalNumberMaxDigitsObject(3),
			naturalNumberFourDigitsMaxCheck: naturalNumberMaxDigitsObject(4),
			naturalNumberSixDigitsMaxCheck: naturalNumberMaxDigitsObject(6),
			decisionYearCheck: decisionYearCheckObject(),
		};
		
		builtinValidationΟbjects = function (builtinValidationMethod, args) {
			if (builtinValidationMethod == 'required') {
				message = 'Υποχρεωτικό πεδίο.';	
			} else if (builtinValidationMethod == 'url') {
				message = 'Ακατάλληλη μορφή συνδέσμου.';
			} else if (builtinValidationMethod == 'number') {
				message = 'Μόνο αριθμοί.';
			} else if (builtinValidationMethod == 'digits') {
				message = 'Μόνο ακέραιοι αριθμοί.';
			} else if (builtinValidationMethod == 'min') {
				message = 'Ελάχιστο: ' + args;
			} else if (builtinValidationMethod == 'max') {
				message = 'Μεγιστο: ' + args;
			} else {
				message = 'Ακατάλληλη μορφή.';
			}
			return {
				message: message,
				args: args,
			};
		};
		
		servicesAdaValidation = function () {
			return {
				adaValidation: validationObjects.adaValidation,
			}
		}
		
		servicesLastStepChildDisable = function () {
			return {
				required: builtinValidationΟbjects('required', validationObjects.servicesLastStepChildDisable.method),
			}
		}
		
		servicesDisableFirst = function () {
			return {
				disableFirst: validationObjects.disableFirst
			}
		}
		
		servicesRequiredValidation = function () {
			return {
				required: builtinValidationΟbjects('required', validationObjects.servicesEvidenceType.method),
			};
		};
		
		servicesUrlValidation = function () {
			return {
				url: builtinValidationΟbjects('url', null),
			};
		};
		
		servicesUrlValidationRequired = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				url: builtinValidationΟbjects('url', null),
			};
		};
		
		servicesEvidenceCostTypeValidation = function (){
			return {
				evidenceCostType: validationObjects.evidenceCostType
			}
		}
		
		servicesEvidenceCodeValidation = function() {
			return {
				evidenceCodeCheck: validationObjects.evidenceCodeCheck,
			};
		};
		
		servicesNaceCodeValidation = function () {
			return {
				naceCodeCheck: validationObjects.naceCodeCheck,
			};
		}
		
		servicesSdgCodeValidation = function () {
			return {
				sdgCodeCheck: validationObjects.sdgCodeCheck,
			};
		}
		
		servicesProcessEvidenceCostMinValidation = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				autofillMin: validationObjects.autofillMin,
				number: builtinValidationΟbjects('number', null),
				min: builtinValidationΟbjects('min', 0),
				lessThanMaxCheck: validationObjects.lessThanMaxCheck,
			};
		};
		
		servicesProcessEvidenceCostMaxValidation = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				autofillMax: validationObjects.autofillMax,
				number: builtinValidationΟbjects('number', null),
				min: builtinValidationΟbjects('min', 0),
				moreThanMinCheck: validationObjects.moreThanMinCheck,
			};
		};
		
		servicesProcessStepDurationMinValidation = function () {
			return {
				autofillMin: validationObjects.autofillMin,
				number: builtinValidationΟbjects('number', null),
				min: builtinValidationΟbjects('min', 0),
				max: builtinValidationΟbjects('max', 200),
				lessThanMaxCheck: validationObjects.lessThanMaxCheck,
			};
		};
		
		servicesProcessStepDurationMaxValidation = function () {
			return {
				autofillMax: validationObjects.autofillMax,
				number: builtinValidationΟbjects('number', null),
				min: builtinValidationΟbjects('min', 0),
				max: builtinValidationΟbjects('max',200),
				moreThanMinCheck: validationObjects.moreThanMinCheck,
			};
		};
		
		servicesProcessStepDurationTypeValidation = function () {
			// return {
			// 	durationTypeCheck: validationObjects.durationTypeCheck
			// }
			return {
				required: builtinValidationΟbjects('required', validationObjects.durationTypeCheck.method)
			};
		};
		
		servicesProcessOrgOwnerValidation = function () {
			return {
				required: builtinValidationΟbjects('required', validationObjects.orgOwnerCheck.method)
			};
		}
		
		servicesDeadlineValidation = function () {
			return {
				number: builtinValidationΟbjects('number', validationObjects.deadlineTypeCheck.method),
				min: builtinValidationΟbjects('min', 0),
				max: builtinValidationΟbjects('max', 200)
			};
		};
		
		servicesDeadlineTypeValidation = function () {
			return {
				required: builtinValidationΟbjects('required', validationObjects.deadlineTypeCheck.method)
			};
		};
		
		servicesEstImplTimeValidation = function () {
			return {
				number: builtinValidationΟbjects('number', null),
				min: builtinValidationΟbjects('min', 0),
				max: builtinValidationΟbjects('max', 200),
			};
		};
		
		servicesEstImplTimeTypeValidation = function () {
			return {
				required: builtinValidationΟbjects('required', validationObjects.estImplTimeTypeCheck.method)
			};
		};
		
		servicesProcessRuleDecisionNumberValidation = function () {
			return {
				digits: builtinValidationΟbjects('digits', null),
				naturalNumberSixDigitsMaxCheck: validationObjects.naturalNumberSixDigitsMaxCheck,
			};
		};
		
		servicesProcessRuleTypeValidation = function () {
			return {
				servicesProcessRuleType: validationObjects.servicesProcessRuleType
			};
		}
		
		servicesProcessRuleDecisionYearValidation = function () {
			return {
				digits: builtinValidationΟbjects('digits', null),
				decisionYearCheck: validationObjects.decisionYearCheck,
			};
		};
		
		servicesProcessRuleArticleValidation = function () {
			return {
				digits: builtinValidationΟbjects('digits', null),
				naturalNumberThreeDigitsMaxCheck : validationObjects.naturalNumberThreeDigitsMaxCheck,
			};
		};
		
		servicesProcessRuleGazetteDocNumberValidation = function () {
			return {
				digits: builtinValidationΟbjects('digits', null),
				naturalNumberFourDigitsMaxCheck : validationObjects.naturalNumberFourDigitsMaxCheck,
			};
		};
		
		servicesProcessRuleGazetteDocYearValidation = function () {
			return {
				digits: builtinValidationΟbjects('digits', null),
				decisionYearCheck: validationObjects.decisionYearCheck,
			};
		};
		
		servicesUrlTitleValidation = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				servicesUrlTitleOtherCharsCheck: validationObjects.servicesUrlTitleOtherCharsCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
			};
		};
		
		servicesTitleValidation = function () {
			return {
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				servicesTitleOtherCharsCheck: validationObjects.servicesTitleOtherCharsCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				illegalEndingCharsCheck: validationObjects.illegalEndingCharsCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
				validAmbersunCheck: validationObjects.validAmbersunCheck,
				notOneWordCheck: validationObjects.notOneWordCheck,
			};
		};
		
		servicesTitleValidationRequired = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				servicesTitleOtherCharsCheck: validationObjects.servicesTitleOtherCharsCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				illegalEndingCharsCheck: validationObjects.illegalEndingCharsCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
				validAmbersunCheck: validationObjects.validAmbersunCheck,
				notOneWordCheck: validationObjects.notOneWordCheck,
			};
		};
		
		servicesPageTitleValidationRequired = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				servicesTitleLengthCheck: validationObjects.servicesTitleLengthCheck,
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				servicesTitleOtherCharsCheck: validationObjects.servicesTitleOtherCharsCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				illegalEndingCharsCheck: validationObjects.illegalEndingCharsCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
				validAmbersunCheck: validationObjects.validAmbersunCheck,
				notOneWordCheck: validationObjects.notOneWordCheck,
			};
		};
		
		servicesDescriptionValidation = function () {
			return {
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
				notOneWordCheck: validationObjects.notOneWordCheck,
			};
		};
		servicesDescriptionValidationRequired = function () {
			return {
				required: builtinValidationΟbjects('required', null),
				servicesFirstCharCheck: validationObjects.servicesFirstCharCheck,
				servicesFirstWordCheck: validationObjects.servicesFirstWordCheck,
				notAllLatinAlphanumCheck: validationObjects.notAllLatinAlphanumCheck,
				validQuotesCheck: validationObjects.validQuotesCheck,
				validParenthesesCheck: validationObjects.validParenthesesCheck,
				notOneWordCheck: validationObjects.notOneWordCheck,
			};
		};
		
		addMethodsToValidator = function (methodObjects) {
			$.each(methodObjects, function (methodName, methodObject) {
				$.validator.addMethod(
					methodName,
					methodObject.method,
					methodObject.message);
			});
		};
		
		validationRules = function (validationFunc) {
			validationMethods = validationFunc();
			rules = {
		    	normalizer: function (value) {
		        	// Normalize before validation
		        	return $.trim(value.replace(/ +(?= )/g,''));
		        },
		        messages: {},
		    };
		    validationMethodsValue = {};
		    $.each(validationMethods, function (methodName, methodObject) {
		    	validationMethodsValue[methodName] = true;
		    });
		    // Add custom messages for built-in validation methods
		    $.each(builtInValidationMethods, function (index, builtInMethodName) {
		    	if (builtInMethodName in validationMethods) {
			    	tempMessages = {};
			    	tempMessages[builtInMethodName] = validationMethods[builtInMethodName].message;
			    	// Overwrite true value if argument was provided
			    	builtInMethodArgs = validationMethods[builtInMethodName].args;
			    	if (builtInMethodArgs != null) {
			    		validationMethodsValue[builtInMethodName] = builtInMethodArgs;	
			    	}
			    	$.extend(rules.messages, tempMessages);
			    	// No need to re-add built-in method to validator
			    	delete validationMethods[builtInMethodName];
		    	}
		    });
		    addMethodsToValidator(validationMethods);
		    return $.extend(rules, validationMethodsValue);
		};
		
		defaultValidationOptions = {
	  		debug: false,
	  		ignore: [],
	  		onsubmit: false,
			errorPlacement: function (error, element) {
				element_parent = element.parent();
				if (element.attr('name').substring(0, 5) == 'wpemd') {
					element_parent.find('br').remove();
					element.after('<br/>');
					element.after(error);
				}
				else if (element.is('select') || (element_parent.attr('class') != 'inputSpan')) {
					error.appendTo(element_parent.parent().after());
				} else {
					error.appendTo(element_parent.after());
				}
				// Remove error labels in hidden multipleTemplateStarter class
				$('.multipleTemplateStarter').find('[id$="error"]').remove();
		    },
		    validClass: successClass,
		    success: function (label, element) {
		    	// Remove evidence error (set on ajax done)
				$('#' + evidenceErrorId).remove();
		    	// Remove valid class from buttons
			    $('[type="button"]').removeClass(successClass);
	    		label.parent().removeClass(errorClass);
		    	label.remove();
		    },
		    invalidHandler: function(form, validator) {
		    	// set submit button red & add text
		    	button = $('input[name="wpSave"]');
				oldColor = button.css( "background-color" );
				button.animate( { "background-color": "red" } ).delay( 10000 ).animate( { "background-color": oldColor } );
				if($('#errorP').length === 0){
					button.after("<p id='errorP' style='color:red; margin:auto;'>Υπάρχει σφάλμα στην φόρμα. Πατήστε εκ νέου αποθήκευση για να δείτε το σημείο στο οποίο υπάρχει πρόβλημα</p>");
				}
		    	
				// Scroll to error input element on submit button click
				errorInputElements = $(':input.createboxInput.error').not('.disabledByPF');
				if (errorInputElements.length) {
					firstErrorInputElement = errorInputElements[0];
					containingTabPanel = $(firstErrorInputElement).closest('[role="tabpanel"]')[0];
					tabs = $('[role="tablist"]').children();
					tabPanels = $('[role="tabpanel"]');
					tab = null;
					$.each(tabPanels, function (key, tabPanel) {
					    if (tabPanel == containingTabPanel) {
					      tab = tabs[key];
				    	}
					});
					toggleTab(tab);
					if ($(firstErrorInputElement).is(":hidden")) {
						$(firstErrorInputElement).click();
					}
					$([document.documentElement, document.body]).animate({
				      scrollTop: $(firstErrorInputElement).offset().top
				    }, 2000);
				};
		    },
		};

		validateStaticInputElements = function (form, staticInputElementValidationFuncs) {
			validateForm = function () {
				defaultValidationOptions.onsubmit = true;
				form.validate(defaultValidationOptions);
				// Add static input element rules
				$.each(staticInputElementValidationFuncs, function (inputName, inputValidationFunc) {
					inputSelector = '[name$="'+inputName+'"]';
					inputElement = $(inputSelector);
					
					/* add * to required table elements */
					// find parent <tr></tr>
					inputElement.closest('tr').find('th').toggleClass('requiredValue');
					
					inputRules = validationRules(inputValidationFunc);
					inputElement.rules('add', inputRules);
				});
			};
			loadJQueryValidationPlugin(validateForm);
		};

		whenTabPanelsLoad = function (callback, nTabs) {
			var checkExists = setInterval(function () {
				tabPanels = $('[role="tabpanel"]');
				all_tabs_loaded = (tabPanels.length == nTabs);
				// If all tabs load
				if (all_tabs_loaded) {
					callback();
					clearInterval(checkExists);
				}
			}, 100);	
		};
		
		function getTabPanel (tabName) {
			tabs = $('[role="tablist"]').children();
			tabPanels = $('[role="tabpanel"]');
			tabPanel = null;
			$.each(tabs, function (key, tab) {
				selectedTab = $(tab).filter(function() {
				    return $(this).text() === tabName;
				});
				if ($(selectedTab).length) {
					tabPanel = tabPanels[key];
				}
			});
			return tabPanel;
		}
		
		function validateDynamicInputElements (inputValidationFuncs, nTabs) {
			function addRulesToDynamicTabInputs () {
				addRuleToNewlyCreatedInput = function (inputSelector, inputRule) {
					// console.log($(inputSelector));
					// Wait for new template to be added
					setTimeout(function () {
						// Remove all add-above small buttons
						$('td.instanceAddAbove').remove();
						// Add rule to newly-added input element
						$(inputSelector).last().rules('add', inputRule);
					}, 100);
				};
				createAddButtonCallback = function (inputSelector, inputRule) {
					return function () {
						addRuleToNewlyCreatedInput(inputSelector, inputRule);
					};
				};
				// Add rules to dynamically-created tab inputs
				$.each(inputValidationFuncs, function (tabName, tabInputValidationFuncs) {
					$.each(tabInputValidationFuncs, function (inputName, inputValidationFunc) {
						inputSelector = '[name$="'+inputName+'"]';
						inputElements = $(inputSelector);
						// console.log(inputElements);
						
						/* add * to required table elements */
						// find parent <tr></tr>
						inputElements.closest('tr').find('th').toggleClass('requiredValue');
						
						inputRules = validationRules(inputValidationFunc);
						// Add rules to pre-existing input elements
						$(inputElements).each(function () {
							$(this).rules('add', inputRules);
		    			});
		    			tabPanel = getTabPanel(tabName);
		    			tabAddButton = $(tabPanel).find('.multipleTemplateAdder');
		    			// Add rules to input elements created after button-click
						$(tabAddButton).on('click', createAddButtonCallback(inputSelector, inputRules));
					});
				});
				// Remove all add-above small buttons
				$('td.instanceAddAbove').remove();
			};
			whenTabPanelsLoad(addRulesToDynamicTabInputs, nTabs);
		};
	
		/**
		 * Services Form Creation Page Logic
		 */
		if (pageIsServicesEMDProcessManagementPage) {
		    form = $('form#emdprocessaddform');
			// Validation
			staticInputElementValidationFuncs = {
				'wpemd-process-title': servicesPageTitleValidationRequired,
			};
			validateStaticInputElements(form, staticInputElementValidationFuncs);
		}

		/**
		 * Services Form Edit Page Logic
		 */
		if (pageIsServicesFormEditPage) {
		 	form = $('form.createbox');
		 	dynamicInputElementValidationFuncs = {
		 		'Γενικές Πληροφορίες': {
		 			'[process_official_title]': servicesTitleValidationRequired,
			  		'[process_alternative_titles]': servicesTitleValidation,
			  		'[process_description]': servicesDescriptionValidation,
			  		'[process_org_owner]': servicesProcessOrgOwnerValidation,
			  		'[process_remarks]': servicesDescriptionValidation,
			  		'[process_deadline]': servicesDeadlineValidation,
			  		'[process_deadline_type]': servicesDeadlineTypeValidation,
			  		'[process_estimated_implementation_time]': servicesEstImplTimeValidation,
			  		'[process_estimated_implementation_time_type]': servicesEstImplTimeTypeValidation,
		 		},
				'Κατηγορίες': {
				},
				'Έννομα μέσα': {
				},
				'Ειδικά πεδία': {
					'[process_nace_code]': servicesNaceCodeValidation,
				},
				'NACE': {
				},
				'SDG': {
					'[process_sdg_code]': servicesSdgCodeValidation,
				},
				'Προϋποθέσεις': {
					'[process_conditions_name]': servicesRequiredValidation,
					'[process_conditions_url]': servicesUrlValidation,
				},
				'Παράβολα-Τέλη': {
					'[process_evidence_cost_type]': servicesEvidenceCostTypeValidation,
					'[process_evidence_cost_code]' : servicesEvidenceCodeValidation,
					'[process_evidence_cost_min]': servicesProcessEvidenceCostMinValidation,
					'[process_evidence_cost_max]': servicesProcessEvidenceCostMaxValidation,
					'[process_evidence_cost_url]': servicesUrlValidation,
				},
				'Δικαιολογητικά': {
					'[process_evidence_alternative]' : servicesDisableFirst,
					'[process_evidence_type]': servicesRequiredValidation,
					'[process_evidence_description]': servicesDescriptionValidationRequired,
					'[process_evidence_submission_type]': servicesRequiredValidation,
					'[process_evidence_related_url]': servicesUrlValidation,
				},
				'Νομοθεσία': {
					'[process_rule_type]': servicesProcessRuleTypeValidation,
					'[process_rule_decision_year]': servicesProcessRuleDecisionYearValidation,
					'[process_rule_description]': servicesDescriptionValidation,
					'[process_rule_gazette_doc_number]': servicesProcessRuleGazetteDocNumberValidation,
					'[process_rule_gazette_doc_year]': servicesProcessRuleGazetteDocYearValidation,
					'[process_rule_url]': servicesUrlValidation,
					'[process_rule_ada]': servicesAdaValidation,
				},
				'Βήματα': {
					'[process_step_title]': servicesDescriptionValidationRequired,
					'[process_step_duration_min]': servicesProcessStepDurationMinValidation,
					'[process_step_duration_max]': servicesProcessStepDurationMaxValidation,
					'[process_step_duration_type]': servicesProcessStepDurationTypeValidation,
					// '[process_step_child][value]' : servicesLastStepChildDisable,
				},
				'Ψηφιακά Βήματα': {
					'[process_step_digital_title]': servicesDescriptionValidationRequired,
					'[process_step_digital_duration_min]': servicesProcessStepDurationMinValidation,
					'[process_step_digital_duration_max]': servicesProcessStepDurationMaxValidation,
					'[process_step_digital_duration_type]': servicesProcessStepDurationTypeValidation,
				},
				'Ψηφιακά Σημεία Παροχής': {
					'[process_provision_digital_location_title]': servicesUrlTitleValidation,
					'[process_provision_digital_location_url]': servicesUrlValidationRequired,
					'[process_provision_digital_location_description]': servicesDescriptionValidation,
				},
				'Χρήσιμοι Σύνδεσμοι': {
					'[process_useful_link_title]': servicesUrlTitleValidation,
					'[process_useful_link_url]': servicesUrlValidationRequired,
				},
			};

			nTabs = Object.keys(dynamicInputElementValidationFuncs).length;

			validateForm = function () {
				form.validate(defaultValidationOptions);
				validateDynamicInputElements(dynamicInputElementValidationFuncs, nTabs);
				function bindCustomFormSubmitHandler () {
					var interval = setInterval(function () {
						// Wait until jquery validate plugin binds its submit handler
						eventsObj = $._data($(form)[0], 'events');
						eventsObjHasSubmitProperty = eventsObj.hasOwnProperty('submit');
						if (Boolean(eventsObj) && eventsObjHasSubmitProperty) {
							allSubmitHandlersBound = eventsObj.submit.length == 2
							if (allSubmitHandlersBound) {
								// Bind custom form submit handler
								$(form).submit(function (event) {
									//mw.log.warn('In custom form submit handler.');
									return $(this).valid();
								});
								//mw.log.warn('Just bound custom form submit handler.');
								clearInterval(interval);
							}
						}
					}, 100);
				}
				bindCustomFormSubmitHandler();
			};
			loadJQueryValidationPlugin(validateForm);
			
			function toggleTab (tab) {
				if (tab != null) {
				  	tabOouiObject = OO.ui.infuse(tab);
			    	tabSelectWidget = tabOouiObject.getClosestScrollableElementContainer();
			    	tabSelectWidgetOouiObject = OO.ui.infuse(tabSelectWidget);
			    	tabSelectWidgetOouiObject.selectItemByLabel(tabOouiObject.label);
				}
			}
			
			// Automatically set 'total number' inputs
			tabNameByInputNameSuffix = {
				'[process_conditions_total_number]': 'Προϋποθέσεις',
				'[process_evidence_cost_total_number]': 'Παράβολα-Τέλη',
				'[process_evidence_total_number]': 'Δικαιολογητικά',
				'[process_evidence_step_total_number]': 'Βήματα',
				'[process_evidence_step_digital_total_number]': 'Ψηφιακά Βήματα',
			};
			alternativeCheckBoxNamesByInputNameSuffix = {
				'[process_conditions_total_number]': 'process_conditions_alternative', // Προυποθέσεις
				'[process_evidence_cost_total_number]': 'process_evidence_cost_alternative', // Παράβολα-Τέλη
				'[process_evidence_total_number]': 'process_evidence_alternative', // Δικαιολογητικά
				'[process_evidence_step_total_number]': null,
				'[process_evidence_step_digital_total_number]': null,
			};
			setTotalNumberInputValueFunc = function (inputNameSuffix, tabName) {
				return function () {
				    tabPanel = getTabPanel(tabName);
					tabPanelTemplateInstances = $(tabPanel).find('.multipleTemplateInstance');
				    totalNumberTabInstances = tabPanelTemplateInstances.length;
				    // Subtract alternatives count from total count
				    altCheckboxName = alternativeCheckBoxNamesByInputNameSuffix[inputNameSuffix]

				    if (altCheckboxName != null) {
				    	altEvidenceCheckboxes = $('[name$="['+ altCheckboxName + '][value]"]');
				    	//console.log($(altEvidenceCheckboxes));
				    	
				    	$.each(altEvidenceCheckboxes, function (key, altEvidenceCheckbox) {
				    		if (altEvidenceCheckbox.checked) {
				    			totalNumberTabInstances--;
				    		}
				    	});
				    }
				    totalNumberInput = $('[name$="' + inputNameSuffix + '"]');
				    if (totalNumberTabInstances != $(totalNumberInput).val()) {
				      $(totalNumberInput).val(totalNumberTabInstances);
				    }
				   
			  };
			};
			updateTotalNumberInputs = function () {
				$.each(tabNameByInputNameSuffix, function (inputNameSuffix, tabName) {
					totalNumberInput = $('[name$="' + inputNameSuffix + '"]');
					$(totalNumberInput).val(0);
					setInterval(setTotalNumberInputValueFunc(inputNameSuffix, tabName), 1000);
				});
			};
			whenTabPanelsLoad(updateTotalNumberInputs, nTabs);
			
			function disableOptions (elements) {
				$.each(elements, function (idx, element){
					$(element).prop('disabled', 'disabled');	
				});
			}
			
			function setEventListener(element, elemsToChange){
				if($(element).is(":checked")){
					$.each(elemsToChange, function(idx, elem) {
						$(elem).prop('disabled', false);
					});
				}else {
					$.each(elemsToChange, function(idx, elem) {
						$(elem).val(" ");
						$(elem).prop('disabled', 'disabled');
					});
				}
				
				if(!(jQuery._data( element, "events" ))){
					$(element).change(function (){
						
						if($(element).is(":checked")){
							$.each(elemsToChange, function(idx, elem) {
								$(elem).prop('disabled', false);
							});
						}else {
							$.each(elemsToChange, function(idx, elem) {
								$(elem).val(" ");
								$(elem).prop('disabled', 'disabled');
							});
						}
					})
				}	
			}
			
			// Automatically update number id inputs
			numIdInputNames = [
				'process_conditions_num_id', // Προϋποθέσεις
				'process_evidence_cost_num_id', // Παράβολα-Τέλη
				'process_evidence_num_id', // Δικαιολογητικά
				'process_step_num_id', // Βήματα
				'process_step_digital_num_id', // Ψηφιακά Βήματα
			]
			function setNumIdInputsFunc (numIdInputName) {
				return function () {
					numIdInputs = $('[name$="[' + numIdInputName + ']"][data-origid]');
					num = 1; // Default offset
					$.each(numIdInputs, function (key, numIdInput) {
						$(numIdInput).val(num);
						var name = $(numIdInput).attr('name');
						disabled = [];
						
						// Προυποθέσεις
						if(name.includes('process_conditions_num_id')){
							disabled = [
								$(numIdInput).closest('tbody').find('[name$="process_conditions_alternative][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_conditions_alternative_of_selector]"]')
							]
						}
						
						// Παράβολα-Τέλη
						if(name.includes('process_evidence_cost_num_id')){
							disabled = [
								$(numIdInput).closest('tbody').find('[name$="process_evidence_cost_alternative][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_evidence_cost_alternative_of_selector]"]')
							]
						}
						
						// Δικαιολογητικά
						if(name.includes('process_evidence_num_id')){
							disabled = [
								$(numIdInput).closest('tbody').find('[name$="process_evidence_alternative][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_evidence_alternative_of_selector]"]')
							]
						}
						
						// Βήματα
						if(name.includes('process_step_num_id')){
							disabled = [
								$(numIdInput).closest('tbody').find('[name$="process_step_child][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_step_exit][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_step_previous_child_selector]"]')
							];
						}
							
						// Ψηφιακά Βήματα
						if(name.includes('process_step_digital_num_id')){
							disabled = [
								$(numIdInput).closest('tbody').find('[name$="process_step_digital_child][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_step_digital_exit][value]"]'),
								$(numIdInput).closest('tbody').find('[name$="process_step_digital_previous_child_selector]"]')
							];
						}
						
						if( num === 1 ) {
							disableOptions(disabled);
						}
						else {
							if(name.includes('process_step_digital_num_id') || name.includes('process_step_num_id')){
								setEventListener(disabled[0], disabled.slice(2, disabled.length));
							}else {
								setEventListener(disabled[0], disabled.slice(1, disabled.length));
							}
						}
						
						fieldValuesDisplay = $(numIdInput).closest('.instanceMain').prev('.fieldValuesDisplay');
						if (fieldValuesDisplay.length == 1) {
							text = $(fieldValuesDisplay).text();
							if (text == 'No data') {
								text = '';
							}
							spaceIdx = text.indexOf(' ');
							if (spaceIdx == -1) {
								text_slice = '';
							} else {
								text_slice = text.slice(spaceIdx);
							}
							new_text = num + text_slice;
							$(fieldValuesDisplay).text(new_text);
						}
						num++;
					});
				}
			}
			updateEvidenceNumIdInputs = function () {
				$.each(numIdInputNames, function (key, numIdInputName) {
					setInterval(setNumIdInputsFunc(numIdInputName), 1000);	
				});
			};
			whenTabPanelsLoad(updateEvidenceNumIdInputs, nTabs);
			
			function getDropdownInputs (inputName) {
				return $('[name$="[' + inputName + ']"][data-origid]');
			}
			
			function getDropdownHiddenValueHolder(dropdown, dropdownInputName) {
				dropdownHiddenValueHolderName = $(dropdown).attr('name').replace('_selector', '');
				dropdownValueHolder = $('[name="' + dropdownHiddenValueHolderName + '"]');
				return dropdownValueHolder;
			}
			
			// Automatically update dropdown input options
			dropdownInputNameByNumIdInputName = {
				'process_conditions_num_id': 'process_conditions_alternative_of_selector', // Προϋποθέσεις
				'process_evidence_cost_num_id': 'process_evidence_cost_alternative_of_selector', // Παράβολα-Τέλη
				'process_evidence_num_id': 'process_evidence_alternative_of_selector', // Δικαιολογητικά
				'process_step_num_id': 'process_step_previous_child_selector', // Βήματα
				'process_step_digital_num_id': 'process_step_digital_previous_child_selector', // Ψηφιακά Βήματα
			}
			function setDropdownOptionsFunc (numIdInputName, dropdownInputName) {
				return function () {
					numIds = $('[name$="[' + numIdInputName +']"]').map(function(){
						exit = $(this).closest('tbody').find('[name$="process_step_digital_exit][value]"]');
						value = $(this).val();
						if (value != '' && !($(exit).is(":checked"))) {
							return value;
						}
					}).get();
					if (numIds.length) {
						dropdowns = getDropdownInputs(dropdownInputName);
						$.each(dropdowns, function (key, dropdown) {
							selectedValue = $(dropdown).val();
							dropdownOptions = $(dropdown).find('option');
							dropdownOptionValues = $(dropdownOptions).map(function() {
								return $(this).val();
							}).get();
							templateNamePrefix = $(dropdown).attr('name').replace('[' + dropdownInputName + ']', '')
							fullNumIdInputName = templateNamePrefix + '[' + numIdInputName +']';
							templateInstanceNumId = $('[name="'+ fullNumIdInputName +'"]').val();
					    	// Remove redundant options
					    	$.each(dropdownOptions, function (key, dropdownOption) {
								if (((dropdownOption.value != '' && !numIds.includes(dropdownOption.value)) || 
			 						(templateInstanceNumId != '' && dropdownOption.value == templateInstanceNumId))) {
									dropdownOption.remove();
					    		}
					    	})
					    	// Add options
					    	$.each(numIds, function (idx, numId) {
								if (numId != templateInstanceNumId && !dropdownOptionValues.includes(numId)) {
									$(dropdown).append( new Option(numId, numId) );
					    		}
					    	})
						})
					}		
				}
			}
			updateDropdownInputs = function () {
				$.each(dropdownInputNameByNumIdInputName, function (numIdInputName, dropdownInputName) {
					setInterval(setDropdownOptionsFunc(numIdInputName, dropdownInputName), 1500);
				});
			};
			whenTabPanelsLoad(updateDropdownInputs, nTabs);
			
			dropdownInputNames = [
				'process_conditions_alternative_of_selector', // Προϋποθέσεις
				'process_evidence_alternative_of_selector', // Δικαιολογητικά
				'process_evidence_cost_alternative_of_selector', // Παράβολα-Τέλη
				'process_step_previous_child_selector', // Βήματα
				'process_step_digital_previous_child_selector', // Ψηφιακά Βήματα
			];
			
			// Load selected dropdown input values from hidden fields
			function loadDropdownInputsFromHiddenFields () {
				setTimeout(function () {
					$.each(dropdownInputNames, function (idx, dropdownInputName) {
						dropdowns = getDropdownInputs(dropdownInputName);
						$.each(dropdowns, function (key, dropdown) {
							dropdownValueHolder = getDropdownHiddenValueHolder(dropdown, dropdownInputName);
							dropdownValueHolderValue = $(dropdownValueHolder).val();
							if (dropdownValueHolderValue) {
								// Set dropdown selected value
								$(dropdown).val(dropdownValueHolderValue);
							}
						});
					});
				}, 2000); // Wait for the automatic dropdown input options update
			}
			whenTabPanelsLoad(loadDropdownInputsFromHiddenFields, nTabs);
			
			function setHiddenDropdownFields () {
				$.each(dropdownInputNames, function (idx, dropdownInputName) {
					dropdowns = getDropdownInputs(dropdownInputName);
					$.each(dropdowns, function (key, dropdown) {
						dropdownValueHolder = getDropdownHiddenValueHolder(dropdown, dropdownInputName);
						dropdownValue = $(dropdown).val();
						if (dropdownValue != $(dropdownValueHolder).val()) {
							// Set dropdown selected value
							//mw.log.error('Setting hidden dropdown with: ', dropdownValue);
							$(dropdownValueHolder).val(dropdownValue);
						}
					});
				});
			}
			// Automatically update hidden dropdown fields
			function updateHiddenDropdownFields () {
				setTimeout(function () {
					setInterval(setHiddenDropdownFields, 2000);	
				}, 3000);
			}
			whenTabPanelsLoad(updateHiddenDropdownFields, nTabs);
			
			// Automatically update step total duration fields (min, max and type)
			// Suffixes
			totalDurationMinSuffix = "process_total_duration_steps_min]";
			totalDurationMaxSuffix = "process_total_duration_steps_max]";
			totalDurationTypeSuffix = "process_total_duration_steps_type]";
			stepDurationMinFieldSuffix = "step_duration_min]";
			stepDurationMaxFieldSuffix = "step_duration_max]";
			stepDurationTypeFieldSuffix = "step_duration_type]";
			stepChildCheckboxSuffix = '[process_step_child][value]';
			stepPrevChildSuffix = '[process_step_previous_child_selector]';
			totalDurationDigitalMinSuffix = 'process_total_duration_steps_digital_min]';
			totalDurationDigitalMaxSuffix = 'process_total_duration_steps_digital_max]';
			totalDurationDigitalTypeSuffix = 'process_total_duration_steps_digital_type]';
			stepDigitalDurationMinFieldSuffix = 'step_digital_duration_min]';
			stepDigitalDurationMaxFieldSuffix = 'step_digital_duration_max]';
			stepDigitalDurationTypeFieldSuffix = 'step_digital_duration_type]';
			stepDigitalChildCheckboxSuffix = '[process_step_digital_child][value]';
			stepDigitalPrevChildSuffix = '[process_step_digital_previous_child_selector]';
			// Selectors
			totalDurationMinSelector = '[name$="' + totalDurationMinSuffix + '"]';
			totalDurationMaxSelector = '[name$="' + totalDurationMaxSuffix + '"]';
			totalDurationTypeSelector = '[name$="' + totalDurationTypeSuffix + '"]';
			stepDurationMinsSelector = '[name$="' + stepDurationMinFieldSuffix + '"]';
			stepDurationMaxsSelector = '[name$="' + stepDurationMaxFieldSuffix + '"]';
			stepDurationTypesSelector = '[name$="' + stepDurationTypeFieldSuffix + '"]';
			totalDurationDigitalMinSelector = '[name$="' + totalDurationDigitalMinSuffix + '"]';
			totalDurationDigitalMaxSelector = '[name$="' + totalDurationDigitalMaxSuffix + '"]';
			totalDurationDigitalTypeSelector = '[name$="' + totalDurationDigitalTypeSuffix + '"]';
			stepDigitalDurationMinsSelector = '[name$="' + stepDigitalDurationMinFieldSuffix + '"]';
			stepDigitalDurationMaxsSelector = '[name$="' + stepDigitalDurationMaxFieldSuffix + '"]';
			stepDigitalDurationTypesSelector = '[name$="' + stepDigitalDurationTypeFieldSuffix + '"]';
			// Duration types
			SECONDS = "Δευτερόλεπτα";
			MINUTES = "Λεπτά";
			HOURS = "Ώρες";
			DAYS = "Ημέρες";
			WEEKS = "Εβδομάδες";
			MONTHS = "Μήνες";
			// Time constants
			SECONDS_PER_MIN = 60;
			MINS_PER_HOUR = 60;
			HOURS_PER_DAY = 24;
			DAYS_PER_WEEK = 7;
			DAYS_PER_MONTH = 30;
			// Seconds-by functions
			function secondsByMinutes(minutes) {
				return minutes * SECONDS_PER_MIN;
			}
			function secondsByHours (hours) {
				return secondsByMinutes(hours * MINS_PER_HOUR);
			}
			function secondsByDays (days) {
				return secondsByHours(days * HOURS_PER_DAY);
			}
			function secondsByWeeks (weeks) {
				return secondsByDays(weeks * DAYS_PER_WEEK);
			}
			function secondsByMonths (months) {
				return secondsByDays(months * DAYS_PER_MONTH);
			}
			toSecondsFuncByDurationType = {}
			toSecondsFuncByDurationType[SECONDS] = function (seconds) { return seconds; };
			toSecondsFuncByDurationType[MINUTES] = secondsByMinutes;
			toSecondsFuncByDurationType[HOURS] = secondsByHours;
			toSecondsFuncByDurationType[DAYS] = secondsByDays;
			toSecondsFuncByDurationType[WEEKS] = secondsByWeeks;
			toSecondsFuncByDurationType[MONTHS] = secondsByMonths;
			// By-seconds functions
			function minutesBySeconds (seconds) {
				return seconds / SECONDS_PER_MIN;
			}
			function hoursBySeconds (seconds) {
				return seconds / secondsByHours(1);
			}
			function daysBySeconds (seconds) {
				return seconds / secondsByDays(1);
			}
			function weeksBySeconds (seconds) {
				return seconds / secondsByWeeks(1);
			}
			function monthsBySeconds (seconds) {
				return seconds / secondsByMonths(1);
			}
			function roundToNearestDecimal (number) {
				return (Math.round(Number(number) * 2) / 2).toFixed(1); 
			}
			durationTypesAndBySecondsFuncs = [
				[MONTHS, monthsBySeconds],
				[WEEKS, weeksBySeconds],
				[DAYS, daysBySeconds],
				[HOURS, hoursBySeconds],
				[MINUTES, minutesBySeconds],
			]
			
			function createSetTotalDurationFieldsFunc(
				stepDurationMinsSelector,
				stepDurationMaxsSelector,
				stepDurationTypesSelector,
				totalDurationMinSelector,
				totalDurationMaxSelector,
				totalDurationTypeSelector,
				stepChildCheckboxSuffix,
				stepPrevChildSuffix) {
				
				return function () {
					stepDurationMins = $(stepDurationMinsSelector);
					stepDurationMaxs = $(stepDurationMaxsSelector);
					stepDurationTypes = $(stepDurationTypesSelector);
					// It holds true that: stepDurationMins.length == stepDurationMaxs.length == stepDurationTypes.length
					totalSecondsDurationMin = 0;
					totalSecondsDurationMax = 0;
					// Gather alternative steps
					// prevStep key -> step duration field index
					prevStepChildren = {}
					$.each(stepDurationMins, function(field_idx, stepDurationMin) {
						name = $(stepDurationMin).attr('name');
						if (name.includes('[num]')) {
							return;
						}
					    nameSplitArray = name.split('][');
					    namePrefix = nameSplitArray[0] + ']';
					    altStepCheckBoxName = namePrefix + stepChildCheckboxSuffix;
					    altStepCheckBox = $('[name="' + altStepCheckBoxName + '"]');
					    prevStepSelectorName = namePrefix + stepPrevChildSuffix;
					    prevStepSelector = $('[name="' + prevStepSelectorName + '"]');
					    prevStepValue = $(prevStepSelector).val();
					    altStepCheckBoxIsChecked = altStepCheckBox[0].checked;
					    if (altStepCheckBoxIsChecked && prevStepValue) {
					    	if (prevStepChildren.hasOwnProperty(prevStepValue)) {
					    		prevStepChildren[prevStepValue].push(field_idx);
					    	} else {
					    		prevStepChildren[prevStepValue] = [field_idx];
					    	}
						}
					});
					// Calculate average durations in minutes (for alternative steps)
					totalAltAverageSecondsDurationMin = 0;
					totalAltAverageSecondsDurationMax = 0;
					alreadyConsideredIndeces = new Set();
					$.each(prevStepChildren, function(prevStepKey, childIndices) {
						totalAltSecondsDurationMin = 0;
						totalAltSecondsDurationMax = 0;
						childrenIncluded = 0;
						$.each(childIndices, function(i, childIndex) {
							durationMin = Number($(stepDurationMins[childIndex]).val());
					    	durationMax = Number($(stepDurationMaxs[childIndex]).val());
					    	durationType = $(stepDurationTypes[childIndex]).val();
					    	if (durationType && !(isNaN(durationMin) || isNaN(durationMax))) {
					    		toSeconds = toSecondsFuncByDurationType[durationType];
					    		totalAltSecondsDurationMin += toSeconds(durationMin);
					    		totalAltSecondsDurationMax += toSeconds(durationMax);
					    		alreadyConsideredIndeces.add(childIndex);
					    		childrenIncluded++;
					    	}
						});
						if (childrenIncluded) {
					    	totalAltAverageSecondsDurationMin = totalAltSecondsDurationMin / childrenIncluded;
					  		totalAltAverageSecondsDurationMax = totalAltSecondsDurationMax / childrenIncluded;
						}
					});
					// Add total average durations to total
					totalSecondsDurationMin += totalAltAverageSecondsDurationMin;
					totalSecondsDurationMax += totalAltAverageSecondsDurationMax;
					// Calculate total durations in minutes (for regular non-alternative steps)
					for (var i = 0; i < stepDurationMins.length; i++) {
						if (!alreadyConsideredIndeces.has(i)) {
							durationMin = Number($(stepDurationMins[i]).val());
							durationMax = Number($(stepDurationMaxs[i]).val());
							durationType = $(stepDurationTypes[i]).val();
							if (durationType && !(isNaN(durationMin) || isNaN(durationMax))) {
								toSeconds = toSecondsFuncByDurationType[durationType];
								totalSecondsDurationMin += toSeconds(durationMin);
								totalSecondsDurationMax += toSeconds(durationMax);
							}	
						}
					};
					// Calculate process duration (min, max and type) intelligently
					processDurationMin = totalSecondsDurationMin;
					processDurationMax = totalSecondsDurationMax;
					processDurationType = SECONDS;
					for (i = 0; i < durationTypesAndBySecondsFuncs.length; i++) {
						durationType = durationTypesAndBySecondsFuncs[i][0];
						bySecondsFunc = durationTypesAndBySecondsFuncs[i][1];
						newProcessDurationMin = bySecondsFunc(totalSecondsDurationMin);
						if (newProcessDurationMin >= 1) {
							processDurationMin = newProcessDurationMin;
							processDurationMax = bySecondsFunc(totalSecondsDurationMax);
							processDurationType = durationType;
							break;
						}
					};
					roundedProcessDurationMin = parseFloat(roundToNearestDecimal(processDurationMin));
					roundedProcessDurationMax = parseFloat(roundToNearestDecimal(processDurationMax));
					
					// Set process duration fields
					if ($(totalDurationMinSelector).val() != roundedProcessDurationMin) {
						$(totalDurationMinSelector).val(roundedProcessDurationMin);
					}
					if ($(totalDurationMaxSelector).val() != roundedProcessDurationMax) {
						$(totalDurationMaxSelector).val(roundedProcessDurationMax);
					}
					if ($(totalDurationMinSelector).val() && $(totalDurationMaxSelector).val() && ($(totalDurationTypeSelector).val() != processDurationType)) {
						$(totalDurationTypeSelector).val(processDurationType);
					}
					if (!($(totalDurationMinSelector).val() && $(totalDurationMaxSelector).val()) && ($(totalDurationTypeSelector).val() != '')) {
						$(totalDurationTypeSelector).val('');
					}
					
					// set totalDurationMin -> 1 if totalDurationMin is 0 && totalDurationDigitalSteps
					process_steps_digital_number = $('[name$="process_step_digital_num_id]"]').length;
					if((roundedProcessDurationMin == 0 || $(totalDurationMinSelector).val() == '0') && (process_steps_digital_number > 1)){
						$(totalDurationMinSelector).val('1');
					}
					// console.log('$(totalDurationMinSelector).val()', $(totalDurationMinSelector).val());
				}
						
			}
			
			function updateTotalDurationFields () {
				setTimeout(function () {
					setInterval(createSetTotalDurationFieldsFunc(
									stepDurationMinsSelector,
									stepDurationMaxsSelector,
									stepDurationTypesSelector,
									totalDurationMinSelector,
									totalDurationMaxSelector,
									totalDurationTypeSelector,
									stepChildCheckboxSuffix,
									stepPrevChildSuffix), 2000);
					setInterval(createSetTotalDurationFieldsFunc(
									stepDigitalDurationMinsSelector,
									stepDigitalDurationMaxsSelector,
									stepDigitalDurationTypesSelector,
									totalDurationDigitalMinSelector,
									totalDurationDigitalMaxSelector,
									totalDurationDigitalTypeSelector,
									stepDigitalChildCheckboxSuffix,
									stepDigitalPrevChildSuffix), 2000);
				}, 1500);
			}
			whenTabPanelsLoad(updateTotalDurationFields, nTabs);
			
			// Automatically update total cost fields (min and max)
			// Suffixes
			processCostMinSuffix = "process_cost_min]";
			processCostMaxSuffix = "process_cost_max]";
			processEvidenceCostAltCheckboxSuffix = 'process_evidence_cost_alternative][value]';
			processEvidenceCostMinSuffix = "process_evidence_cost_min]";
			processEvidenceCostMaxSuffix = "process_evidence_cost_max]";
			// Selectors
			processCostMinSelector = '[name$="' + processCostMinSuffix + '"]';
			processCostMaxSelector = '[name$="' + processCostMaxSuffix + '"]';
			processEvidenceCostAltCheckboxSelector = '[name$="' + processEvidenceCostAltCheckboxSuffix + '"]';
			processEvidenceCostMinSelector = '[name$="' + processEvidenceCostMinSuffix + '"]';
			processEvidenceCostMaxSelector = '[name$="' + processEvidenceCostMaxSuffix + '"]';
			function setTotalCostFields () {
				evidenceCostAltCheckboxes = $(processEvidenceCostAltCheckboxSelector);
				evidenceCostMins = $(processEvidenceCostMinSelector);
				evidenceCostMaxs = $(processEvidenceCostMaxSelector);
				totalCostMin = 0;
				totalCostMax = 0;
				// Calculate total costs
				for (var i = 0; i < evidenceCostMins.length; i++) {
					evidenceCostAltCheckbox = evidenceCostAltCheckboxes[i];
					evidenceCostMin = Number($(evidenceCostMins[i]).val());
					evidenceCostMax = Number($(evidenceCostMaxs[i]).val());
					if (!evidenceCostAltCheckbox.checked && !(isNaN(durationMin) || isNaN(durationMax))) {
						totalCostMin += evidenceCostMin;
						totalCostMax += evidenceCostMax;
					}
				};
				costMinField = $(processCostMinSelector);
				costMaxField = $(processCostMaxSelector);
				costMinFieldValue = $(costMinField).val();
				costMaxFieldValue = $(costMaxField).val();
				// Set process duration fields
				if ((costMinFieldValue == '') || (costMinFieldValue != totalCostMin)) {
					$(costMinField).val(totalCostMin);
				}
				if ((costMaxFieldValue == '') || (costMaxFieldValue != totalCostMax)) {
					$(costMaxField).val(totalCostMax);
				}
			}
			function updateTotalCostFields () {
				setTimeout(function () {
					setInterval(setTotalCostFields, 2000);	
				}, 1500);
			}
			whenTabPanelsLoad(updateTotalCostFields, nTabs);
			
			// Add NACE, SDG and evidence by-code information fetchers
			function setFieldsByCode (apiEndpoint, codeInput, fieldInputsObject) {
				function checkIfExists(codeInput, codeVal){
					// var codeVal = parseFloat($(codeInput).val());
					var codeName = $(codeInput).attr('name').split('[')[2];
					var elements = $('[name$="['+codeName+'"]');
					var exists = false;
					$.each(elements, function (idx, element) {
						if( element == codeInput ) { return }
						if(idx === $(elements).length - 1) { return }
						var elemVal = parseFloat($(element).val());
						if(!isNaN(elemVal) && elemVal === parseFloat(codeVal)){
							exists = true;
						}
					})
					return exists;
				}
				function setFieldInputs (value) {
			    	$.each(fieldInputsObject, function (fieldType, fieldInputObj) {
			    		console.log(fieldType, fieldInputObj)
			        	newValue = value ? value[fieldType] : '';
			      		if (fieldInputObj.constructor === Array) {
							$.each(fieldInputObj, function (idx, fieldInput) {
			          			$(fieldInput).val(newValue);
			        		});
			        	} else {
							$(fieldInputObj).val(newValue);
			        	}
			    	});
				}
				var code = $(codeInput).val();
				var error_alert_message = 'Έχετε εισαγάγει ήδη αυτόν τον κωδικό. Παρακαλώ επιλέξτε έναν άλλο κωδικό.';
				if(checkIfExists(codeInput, code)){
					alert(error_alert_message);
					return false;
				}
				var url = apiEndpoint + code;
				$.ajax({
		    		url: url,
		    		dataType: 'json',
				}).done(function(data) {
		    		if($(codeInput).valid() && (data.success === true || data.success == 'true') && (!$.isEmptyObject(data.result))) {
    					dataResult = (data.result.constructor == Array) ? data.result[0] : data.result;
		    			setFieldInputs(dataResult);
		    		} else {
		    			setFieldInputs('');
		    		}
				}).fail(function() {
		    		setFieldInputs('');
				}).always(function() {});
			}
			function createFetchFieldsByCodeCallback (apiEndpoint, codeInput, fieldInputsObject) {
				return function() {
					setFieldsByCode(apiEndpoint, codeInput, fieldInputsObject)
				}
			}
			// // NACE
			// function bindSetNaceDescription () {
			// 	setTimeout(function () {
			// 		naceCodeButton = $('#' + naceCodeButtonId);
			// 		naceCodeInput = $(naceCodeInputSelector);
			// 		naceCodeDescriptionInput = $(naceCodeDescriptionSelector);
			// 		fieldInputsObject = {
			// 			description: naceCodeDescriptionInput
			// 		}
			// 		naceCodeButton.on('click', createFetchFieldsByCodeCallback (
			// 			naceCodeApiEndpoint, naceCodeInput, fieldInputsObject));
			// 	}, 1500);
			// }
			// whenTabPanelsLoad(bindSetNaceDescription, nTabs);
			
			// SDG
			function bindSetSdgFields () {
				setTimeout(function () {
					// Bind pre-existing SDG template instances
					var sdgCodeΙnputs = $(sdgCodeΙnputsSelector);
					var sdgTitleInputs = $(sdgTitleInputsSelector);
					var sdgDescriptionInputs = $(sdgDescriptionInputsSelector);
					var sdgCodeButtons = $('.' + sdgCodeButtonClass);
					// it holds true that sdgCodeΙnputs.length == sdgTitleInputs.length == sdgDescriptionInputs.length
					$.each(sdgCodeΙnputs, function (key, sdgCodeInput) {
					  var sdgTitleInput = sdgTitleInputs[key];
					  var sdgDescriptionInput = sdgDescriptionInputs[key];
					  var fieldInputsObject = {
					    title: sdgTitleInput,
					    description: sdgDescriptionInput
					  }
					  var sdgCodeButton = sdgCodeButtons[key];
					  $(sdgCodeButton).on('click', function(){
					  	createFetchFieldsByCodeCallback(sdgCodeApiEndpoint, sdgCodeInput, fieldInputsObject);
					  });
					});
					// Bind new SDG template instances
				    var sdgAddButton = $(getTabPanel('SDG')).find('.multipleTemplateAdder');
					sdgAddButton.on('click', function () {
					  setTimeout(function () {
					    var sdgCodeButtons = $('.' + sdgCodeButtonClass);
					    var lastSdgCodeButton = sdgCodeButtons[sdgCodeButtons.length - 1];
					    var sdgCodeΙnputs = $(sdgCodeΙnputsSelector);
					    var sdgTitleInputs = $(sdgTitleInputsSelector);
					    var sdgDescriptionInputs = $(sdgDescriptionInputsSelector);
					    var lastSdgCodeΙnput = sdgCodeΙnputs[sdgCodeΙnputs.length - 1];
					    var lastSdgTitleInput = sdgTitleInputs[sdgTitleInputs.length - 1];
					    var lastSdgDescriptionInput = sdgDescriptionInputs[sdgDescriptionInputs.length - 1];
					    var fieldInputsObject = {
					      title: lastSdgTitleInput,
					      description: lastSdgDescriptionInput
					    };
					    $(lastSdgCodeButton).on('click', createFetchFieldsByCodeCallback(sdgCodeApiEndpoint, lastSdgCodeΙnput, fieldInputsObject));
					  }, 300);
					});
				}, 1500);
			}
			whenTabPanelsLoad(bindSetSdgFields, nTabs);
			
			// Evidence
			function bindSetEvidenceFields () {
				setTimeout(function () {
					// Bind pre-existing SDG template instances
					var evidenceCostCodeΙnputs = $(evidenceCostCodeInputsSelector);
					var evidenceCostDescriptionInputs = $(evidenceCostDescriptionInputsSelector);
					var evidenceCostMinInputs = $(evidenceCostMinInputsSelector);
					var evidenceCostMaxInputs = $(evidenceCostMaxInputsSelector);
					var evidenceCostCodeButtons = $('.' + evidenceCostCodeButtonClass);
					// it holds true that evidenceCostCodeΙnputs.length == evidenceCostDescriptionInputs.length == evidenceCostMinInputs.length == evidenceCostMaxInputs.length
					$.each(evidenceCostCodeΙnputs, function (key, evidenceCostCodeΙnput) {
					  var evidenceCostDescriptionInput = evidenceCostDescriptionInputs[key];
					  var evidenceCostMinInput = evidenceCostMinInputs[key];
					  var evidenceCostMaxInput = evidenceCostMaxInputs[key];
					  var fieldInputsObject = {
					    description: evidenceCostDescriptionInput,
					    price: [evidenceCostMinInput, evidenceCostMaxInput],
					  }
					  var evidenceCostCodeButton = evidenceCostCodeButtons[key];
					  $(evidenceCostCodeButton).on('click', createFetchFieldsByCodeCallback(evidenceCostCodeApiEndpoint, evidenceCostCodeΙnput, fieldInputsObject));
					});
					
					// Bind new Evidence template instances
					var evidenceCostAddButton = $(getTabPanel('Παράβολα-Τέλη')).find('.multipleTemplateAdder');
					evidenceCostAddButton.on('click', function () {
					  setTimeout(function () {
					    var evidenceCostCodeButtons = $('.' + evidenceCostCodeButtonClass);
					    var lastEvidenceCostCodeButton = evidenceCostCodeButtons[evidenceCostCodeButtons.length - 1];
					    var evidenceCostCodeΙnputs = $(evidenceCostCodeInputsSelector);
					    var evidenceCostDescriptionInputs = $(evidenceCostDescriptionInputsSelector);
					    var evidenceCostMinInputs = $(evidenceCostMinInputsSelector);
					    var evidenceCostMaxInputs = $(evidenceCostMaxInputsSelector);
					    var lastEvidenceCostCodeΙnput = evidenceCostCodeΙnputs[evidenceCostCodeΙnputs.length - 1];
					    var lastEvidenceCostDescriptionInput = evidenceCostDescriptionInputs[evidenceCostDescriptionInputs.length - 1];
					    var lastEvidenceCostMinInput = evidenceCostMinInputs[evidenceCostMinInputs.length - 1];
					    var lastEvidenceCostMaxInput = evidenceCostMaxInputs[evidenceCostMaxInputs.length - 1];
					    var fieldInputsObject = {
					      description: lastEvidenceCostDescriptionInput,
					      price: [lastEvidenceCostMinInput, lastEvidenceCostMaxInput],
					    };
					    $(lastEvidenceCostCodeButton).on('click', createFetchFieldsByCodeCallback(evidenceCostCodeApiEndpoint, lastEvidenceCostCodeΙnput, fieldInputsObject));
					  }, 300);
					});
				}, 1500);
			}
			whenTabPanelsLoad(bindSetEvidenceFields, nTabs);
			
			// NACE NEW
			function bindSetNaceFields(){
				setTimeout(function () {
					// Bind pre-existing NACE template instances
					var naceCodeΙnputs = $(naceCodeInputSelector);
					var naceCodeDescriptionInputs = $(naceCodeDescriptionSelector);
					// var naceCodeButtons = $('#' + naceCodeButtonId);
					var naceCodeButtons = $('*[data-origid="process_nace_code-button"]');

					// it holds true that naceCodeΙnputs.length == naceDescriptionInputs.length
					$.each(naceCodeΙnputs, function (key, naceCodeInput) {
					  var naceCodeDescriptionInput = naceCodeDescriptionInputs[key];
					  var fieldInputsObject = {
					    description: naceCodeDescriptionInput
					  }
					  var naceCodeButton = naceCodeButtons[key];
					  $(naceCodeButton).on('click', createFetchFieldsByCodeCallback(naceCodeApiEndpoint, naceCodeInput, fieldInputsObject));
					});
					
					// Bind new NACE template instances
					var naceAddButton = $(getTabPanel('NACE')).find('.multipleTemplateAdder');
					naceAddButton.on('click', function () {
					  setTimeout(function () {
					    var naceCodeButtons = $('#' + naceCodeButtonId);
					    var lastNaceCodeButton = naceCodeButtons[naceCodeButtons.length - 1];
					    var naceCodeΙnputs = $(naceCodeInputSelector);
					    var naceCodeDescriptionInputs = $(naceCodeDescriptionSelector);
					    var lastNaceCodeΙnput = naceCodeΙnputs[naceCodeΙnputs.length - 1];
					    var lastNaceCodeButton = $(lastNaceCodeΙnput).parent().next();
					    var lastNaceCodeDescriptionInput = naceCodeDescriptionInputs[naceCodeDescriptionInputs.length - 1];
					    var fieldInputsObject = {
					      description: lastNaceCodeDescriptionInput
					    }
					    $(lastNaceCodeButton).on('click', createFetchFieldsByCodeCallback(naceCodeApiEndpoint, lastNaceCodeΙnput, fieldInputsObject));
					  }, 300);
					});
				});
			}
			whenTabPanelsLoad(bindSetNaceFields, nTabs);
			
			// Autocomplete fields using AJAX call parameterized by other field value
			processProvisionOrgNameSuffix = '[process_provision_org][]';
			urlPlaceholder = '@@@@';
			otherField = '[process_org_owner]';
			autocompleteFieldByOtherFieldCandidates = {
				// Field
				'[process_provision_org_owner_directory][]': [
					// URL (urlPlaceholder will be replaced by other field value)
					'https://reg-diavlos.gov.gr/api/units/name/' + urlPlaceholder + '/unit_types/4,3,41',
					// Other field
					otherField
				],
				'[process_output_registries][]': [	
					'https://reg-diavlos.gov.gr/api.php?action=ask&query=[[Registry org main::Φορέας:' + urlPlaceholder + ']]|limit=1000&format=json',
					otherField
				]
			};
			autocompleteFieldByOtherFieldCandidates[processProvisionOrgNameSuffix] = [
				'https://reg-diavlos.gov.gr/api.php?action=ask&query=[[Gov org subOrganizationOf::Φορέας:' + urlPlaceholder + ']]|limit=1000&format=json',
				otherField
			];
			
			function filterSelectDataByString (selectData, str) {
			  function normalizeGreekString (greekStr) {
			    return greekStr.normalize('NFD').replace(/[\u0300-\u036f]/g, "").toLowerCase();
			  }
			  if (!str) {
			    // Nothing to filter with
			    return selectData;
			  }
			  filteredData = {results: []};
			  normalizedString = normalizeGreekString(str);
			  $.each(selectData.results, function (i, result) {
			    normalizedResultText = normalizeGreekString(result.text);
			    if (normalizedResultText.includes(normalizedString)) {
			      filteredData.results.push(result);
			    }
			  });
			  return filteredData;
			}
			function bindAutocompleteFieldByOtherFieldFunc (fieldNameSuffix, urlWithPlaceholder, otherFieldNameSuffix) {
				return function () {
					savedUrl = null;
					field = $('[name$="' + fieldNameSuffix + '"]');
					otherFieldValue = $('[name$="' + otherFieldNameSuffix + '"]').val();
					console.log('field', field);
					console.log('otherFieldValue', otherFieldValue);
					field.select2({
					  minimumInputLength: 1,
					  data: [],
					  language: {
					    searching: function() {
					      return "Γίνεται αναζήτηση...";
					    },
					    noResults: function () {
					      return "Δε βρέθηκαν αποτελέσματα."
					    }
					  },
					  multiple: true,
					  query: function (query) {
					    function callQueryCallbackWithData (emptyData) {
					      if (emptyData) { self.data = []; }
					      query.callback(filterSelectDataByString(self.data, query.term));
					    }
					    otherFieldValue = $('[name$="' + otherFieldNameSuffix + '"]').val();
					    if (otherFieldValue) {
					      url = urlWithPlaceholder.replace(urlPlaceholder, otherFieldValue);
					      if ((self.data == []) || (url != savedUrl)) {
					        savedUrl = url;
					        callQueryCallbackWithData(true);
					        $.get(url, function (data) {
					          if (typeof data === 'string') {
					          	data = JSON.parse(data);
					          }
					          dataResults = '';
					          if ('query' in data) {
					          	dataResults = Object.values(data.query.results);
					        	dataResultTextKey = 'displaytitle';
					          } else if ('result' in data) {
					        	dataResults = data.result;
					        	dataResultTextKey = 'preferredLabel';
					          }
					          if (dataResults) {
					          	self.data = {
					          		results: dataResults.map(function (registry, index) {
					          			return {
					          				id: registry[dataResultTextKey],
					          				text: registry[dataResultTextKey]
					          			};
					          		})
					            };
					            if (fieldNameSuffix == processProvisionOrgNameSuffix) {
					            	self.data.results.push({
					            		id: otherFieldValue,
					            		text: otherFieldValue
					            	});
					            }
					          }
					          callQueryCallbackWithData(false);
					        });
					      } else {
					        callQueryCallbackWithData(false);
					      }
					    } else {
					      callQueryCallbackWithData(true);
					    }
					  },
					  escapeMarkup: function (m) { return m; },
					});
					// Have otherFieldValue option selected by default
					// if ((fieldNameSuffix == processProvisionOrgNameSuffix) && otherFieldValue) {
					// 	var newOption = new Option(otherFieldValue, otherFieldValue, false, true);
					// 	$(field).append(newOption).trigger('change');
					// }
				};
			}
			function bindAutocompleteFieldByOtherFieldCandidates () {
				$.each(autocompleteFieldByOtherFieldCandidates, function (fieldNameSuffix, obj) {
					urlWithPlaceholder = obj[0];
					otherFieldNameSuffix = obj[1];
					setTimeout(bindAutocompleteFieldByOtherFieldFunc(
						fieldNameSuffix,
						urlWithPlaceholder,
						otherFieldNameSuffix),
					1500);	
				});
			}
			whenTabPanelsLoad(bindAutocompleteFieldByOtherFieldCandidates, nTabs);
			
			// Set specific fields as readonly
			readonlyCandidateNames = [
				// 'process[process_org_owner]',
				'process[process_total_duration_steps_min]',
				'process[process_total_duration_steps_max]',
				'process[process_total_duration_steps_type]',
				'process[process_total_duration_steps_digital_min]',
				'process[process_total_duration_steps_digital_max]',
				'process[process_total_duration_steps_digital_type]',
				'process[process_cost_min]',
				'process[process_cost_max]',
				'process[process_evidence_cost_total_number]',
				'process[process_evidence_total_number]',
				'process[process_evidence_step_total_number]',
				'process[process_evidence_step_digital_total_number]',
			]
			function setFieldsAsReadonly() {
				$.each(readonlyCandidateNames, function (i, readonlyCandidateName) {
					readonlyCandidate = $('[name="' + readonlyCandidateName + '"');
					$(readonlyCandidate).prop('readOnly', true);
				});
			}
			whenTabPanelsLoad(setFieldsAsReadonly, nTabs);
			
			// Fix all form elements (change,texts and hide elements)
			styleFormElements = function () {
				
				// Remove all empty paragraphs (trash).
				$('p').filter(function () { return $.trim(this.innerHTML) == "" }).remove();
				
				// Change form heading.
				var heading_title = $('#firstHeading').text();
				var process_id    = $('.field_process_id' ).val();
				// console.log( process_id );
				if( process_id != '' ) {
					heading_title = heading_title.replace( "Επεξεργασία Διαδικασίας: Διαδικασία:", process_id + ' | ' ); 
				} else {
					// This is addition. Change accordingly.
					heading_title = heading_title.replace( "Επεξεργασία Διαδικασίας: Διαδικασία:", 'Επεξεργασία: ' ); 
				}
		
				// Hide elements not needed
				$( '.hidden_input').each(function() { 
					$(this).closest( 'tr' ).addClass( 'hidden_form_element' );
				});

			};
			
			whenTabPanelsLoad(styleFormElements, nTabs);
			
			
			/** 
			Scrap HTML tags from textarea fields
			**/
			
			function stripHTML(textarea) {
				var newtmp = $(textarea).val().replace(/[\[\]']+/g,''); // remove Brackets []
				return newtmp.trim().replace(/\\n/g, '').replace(/(<([^>]+)>)/ig,""); // first trim \n and spaces and then replace <div> etc tags
			}
				
			// Scrape HTML tags
			function scrapeHTML() {
				setInterval( function () {
					textareas = $('textarea');
					$.each(textareas, function (idx, textarea) {
						if(!(jQuery._data( textarea, "events" ))){
					    	$(textarea).change(function () { // put onChange event handler
					    		$(textarea).val(stripHTML(textarea));
					    	});
					    }
					});
				}, 2000); //run every 2 secs
			}
			
			whenTabPanelsLoad(scrapeHTML, nTabs);
			
			// Sort option fields
			function sortOptions() {
				var sortedClass = 'sorted';
				setInterval(function () {
                    selects = $('select:not(.' + sortedClass + ')');
                    
                    $.each(selects, function (idx, select) {
                        if (!$(select).hasClass( sortedClass )){
                            var options = $(select).find('option');
                            var selected = $(select).val();
                
                            options.sort(function(o1, o2) {
                                if(o1.value == 'Άλλο' || o1.innerText == 'Άλλο') { return 1;}
                                if(o2.value == 'Άλλο' || o2.innerText == 'Άλλο') { return -1;}
                                // return o1.innerText > o2.innerText ? 1 : o1.innerText < o2.innerText ? -1 : 0; 
                                return o1.innerText.localeCompare(o2.innerText, 'el');
                            });
                           
                            $(select).empty().append( options );
                            $(select).val(selected);
                            $(select).addClass( sortedClass);
                        }
                    });
                }, 10000); //run every 10 sec
			}
			
			whenTabPanelsLoad(sortOptions, nTabs);
			
			/*  Τ6225 */
			/* Colorize 2nd and 3rd node level of pfTree */
			function styleLifeEventsTreeNodes() {
			    setInterval(function(){
			        var $lifeEventsTreeWrapperEl = $('.pfTreeInputWrapper');
			        if (!$lifeEventsTreeWrapperEl) return;
			        
			        if ($($lifeEventsTreeWrapperEl).hasClass("colorized")) return;
			
			        var $firstLevelNodes = $lifeEventsTreeWrapperEl.find($('.jstree > .jstree-children > li > .jstree-anchor'));
			        $.each($firstLevelNodes, function(idx, node){
			            $(node).css("font-weight", 700);
			        });
			
			        var $secondLevelNodes = $lifeEventsTreeWrapperEl.find($('.jstree-children > li > .jstree-children'));
			        if (!$secondLevelNodes.length) return;
			        $.each($secondLevelNodes, function (idx, node) {
			            $(node).css("color", "#046ec5 !important");
			        });
			        
			        var $thirdLevelNodes = $secondLevelNodes.find('li > .jstree-children');
			        if (!$secondLevelNodes.length) return;
			        $.each($thirdLevelNodes, function (idx, node) {
			            $(node).css("color", "#003476 !important");
			        });
			
			        $($lifeEventsTreeWrapperEl).addClass("colorized");
			        
			    }, 4000)
			};
			
			whenTabPanelsLoad(styleLifeEventsTreeNodes, nTabs);
		}
	}
    
	
	/**
	 * Services Page Form Input handlers
	 * 
	 * @author [[User:Npappas]]
	 */
	 
	 if (pageIsServicesFormEditPage) {
	 	
	 	// idiotikos - thesmikos foreas checkbox & Dropdown
	 
	 	process_org_owner_is_private = $('input[name="process[process_org_owner_is_private][value]"]');
	 	process_org_owner_private = $('select[name="process[process_org_owner_private]"]');
	 	process_org_owner = $('select[name="process[process_org_owner]"]');
	 	
	 	
	 	var update_checkboxesForeis = function () {
    		if ($(process_org_owner_is_private).is(":checked")) {
    			// enable private
        		$(process_org_owner_private).prop('disabled', false);
        		// disable org
				$(process_org_owner).prop('disabled', 'disabled');
    			
    		}else {
    			// disable private
    			$(process_org_owner_private).prop('disabled', 'disabled');
    			// enable org
        		$(process_org_owner).prop('disabled', false);
    		}
		};
		
		// Ennoma mesa
		
		process_sdg_resource = $('[name="process[process_sdg_resource]"]');
		process_sdg_resource_other = $('[name="process[process_sdg_resource_other]"]');
		
		process_sdg_lack_of_response_rule = $('[name="process[process_sdg_lack_of_response_rule]"]');
		process_sdg_lack_of_response_rule_other = $('[name="process[process_sdg_lack_of_response_rule_other]"]');
		
		var updateSdgResource = function () {
			if($(process_sdg_resource).val() === 'Άλλο'){
				$(process_sdg_resource_other).prop('disabled', false);
			}else {
				$(process_sdg_resource_other).prop('disabled', 'disabled');
			}
		}
		
		var updateSdgLack = function () {
			if($(process_sdg_lack_of_response_rule).val() === 'Άλλο'){
				$(process_sdg_lack_of_response_rule_other).prop('disabled', false);
			}else {
				$(process_sdg_lack_of_response_rule_other).prop('disabled', 'disabled');
			}
		}
		
		var setNACESDG_disabled = function () {
			function setDisabled (elem) {
				// $(elem).prop('disabled', 'disabled');
				$(elem).prop('readonly', true);
			}
			
			process_nace_description = $('[name$="process_nace_description]"]');
			process_sdg_title = $('[name$="process_sdg_title]"]');
			process_sdg_description = $('[name$="process_sdg_description]"]');
			
			$.each(process_nace_description, function(idx, elem) {setDisabled(elem)});
			$.each(process_sdg_title, function(idx, elem) {setDisabled(elem)})
			$.each(process_sdg_description, function(idx, elem) {setDisabled(elem)})
			
			
		}
		
		setNACESDG_disabled();
		

		// run on first load
		$(update_checkboxesForeis); 
		$(updateSdgResource);
		$(updateSdgLack);

		// event listeners onChange
		process_sdg_resource.change(updateSdgResource);
		process_sdg_lack_of_response_rule.change(updateSdgLack);
		process_org_owner_is_private.change(update_checkboxesForeis); 
	 }
} );
})();
Τα cookies μας βοηθούν να παρέχουμε τις υπηρεσίες μας. Χρησιμοποιώντας τις υπηρεσίες μας, συμφωνείτε στην χρήση των cookies από εμάς.