$(document).ready(function($){ 'use strict';

	// tooltips
	$('.ttip').tooltip();

	// DATATABLES

	var custom_controls = $('.datatables-custom-controls');
	var bulk_action_modal_obj = $('select[name="action"].bulk-action');
	var custom_filters = $('.datatables-custom-filters');
	custom_filters.find('.bulk-action').on('change', function(){
		checkme('.domainmanage');
	});

	// gestione bulk action per i modali
	bulk_action_modal_obj.on('change', function(e){

		checkme('.domainmanage');
		checkme('.marketplacemanager', false);

		var load_modal = true;
		var selectbox = $(e.currentTarget);
		var modal_id = '#confirm-modal-' + selectbox.val();
		var action = selectbox.val();
		isDevMode() && console.log('count selected IDs', ids.length)
		isDevMode() && console.log('bulk action', action)
		isDevMode() && console.log('bulk dns limit', dns_bulk_limit)
		if(ids.length>0){ // se ci sono domini selezionati faccio qualcosa, altrimenti no

			// gestione DNS
			if( action === 'dns' && ids.length > dns_bulk_limit ){ // errore, ho raggiunto il limite imposto per il cambio bulk dns
				var url_to_dns_bulk_limit = web_root + web_lang + '/registration/get_dns_bulk_limit/'; // url verifica limite dns
				var url = url_to_dns_bulk_limit + parseInt(ids.length); // appendo il numero di id selezionati
				$('body').find(bulk_action_modal_obj).each(function(){
		  			$(this).attr('href', '#confirm-modal-dns-error');
		  		});
		  		$('#confirm-modal-dns-error .modal-body').load(url, function(response, status, xhr) {});
		  		load_modal = false;
		  		$('#confirm-modal-dns-error').modal(); // apro un modale custom per indicare l'errore
		  	}

			// gestione TAGS
			if( action == 'tags'){}

			// gestione particolare AUTHCODE?
			if( action == 'authcode'){}

			if(ids.length>0 && ids.length!='undefined'){

				if( action === 'custom-dns'){
					// isDevMode() && console.log("sono in bulk_action_modal_obj e sto lavorando per il conteggio dei SOLI Custom-DNS");
					// conto solo i domini con nidomans.com:
					// devo scorrere tutti gli id e mettere in un array solo quelli che hanno la colonna DNS1 con nidomans
					// per farlo controllo faccio una chiamata ajax passando tutti gli ID e mi faccio restituire il json con
					// l'oggetto ids con i soli elementi a cui fanno riferimento valori con DNS nidomans
					$.post(source_domain_manager, { registration_id: ids.items }, function(registrations_nidomans_items){
						custom_dns.items = registrations_nidomans_items;
						length = parseInt(Object.keys(custom_dns.items).length);
						custom_dns.length = length;
						// ora devo solo dire al counter di aggiornare il valore e sovrascriverlo!
						$("#confirm-modal-custom-dns").find(".domain-count").text(length);
					});
				} else {
				  $('.domain-count').html(parseInt(ids.length));
				}

			}

			if(load_modal) $(modal_id).modal(); // apro il modale?

		}else{
			bulk_action_modal_obj.find("option").prop("selected", false); // rimuovo la selezione
		}

		// ripristino la selezione a quella di default una volta che il modale viene dismesso
		$(modal_id).on('hidden', function () {
			bulk_action_modal_obj.find("option").prop("selected", false);
		});

	});

	// inizializzazione generale
	if( $('.datatable').length ){
		$('.datatable').dataTable( {
			"sPaginationType": "bootstrap",
			"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
			"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"ip>',
			"iDisplayLength": limit_table_rows
		});
	}
	if( $('.domainsearch').length ){
		$('.domainsearch').dataTable( {
			"sPaginationType": "bootstrap",
			"iDisplayLength": limit_table_rows,
			"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
			"aoColumns": [
				{ "bSortable": false },
				null,
				null,
				null,
				{ "bSortable": false }
			],
			"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
			"fnInitComplete": function(oSettings, json) {
				$('#domactions').html('<i class="icon-hand-up"></i> <button class="btn btn-primary" type="submit"><i class="icon-pushpin"></i> prosegui con i domini selezionati</button>');
				this.fnSetFilteringDelay(1000);
			}
		});
	}
	if( $('.domainmanage').length ){
		$('.domainmanage').dataTable( {
			"iDisplayLength": limit_table_rows,
			"sPaginationType": "bootstrap",
			"aoColumns": [
				{ "bSortable": false }, // domain id
				null,
				{ "sType": "natural" }, // date valid until
				null,
				null,
				null
			],
			"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
			"fnInitComplete": function(oSettings, json) {
				var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
				custom_controls.find('#datatables-bottom-controls').remove();
				$('#domactions-top, #domactions-bottom').append( controls );
				this.fnSetFilteringDelay(1000);
			}
		});
	}

	// Seleziona/Deseleziona tutte le checkbox di una tabella (DataTable)
	// commento perchè non corretta
	/*$('body').delegate('#select_items', 'click', function(){
		var nodes = $('.domainsearch').dataTable().fnGetNodes();
		isDevMode() && console.log('select_items checked? ', this.checked);
		$('.s-item', nodes).attr('checked', this.checked);
		$(nodes).each(function(i,e){
			isDevMode() && console.log($(e).val()+' checked?', $(e).prop('checked'));
			if( $(e).is(':checked') ){
				//$(e).attr('checked', true);
				isDevMode() && console.log($(e).val(), 'is checked');
			} else {
				//$(e).attr('checked', false);
				isDevMode() && console.log($(e).val(), 'not checked');
			}
		});
	});*/

	// nuova versione
	$('.select_items').on('click', function(e){

		var obj=e.currentTarget;
		var parents=$(obj).parentsUntil("div.widget-content");
		var last = parents.length-1;
		var parent = parents[last];
		toggle_check(obj, '.s-item:enabled', parent);

	});

	// Seleziona/Deseleziona tutte le checkbox di una tabella (NO DataTable)
	if( $('input.select-all').length ){
		$('input.select-all').click(function(){
			var checked_status = this.checked;
			$('input.takeaction').each(function()
			{
				this.checked = checked_status;
			});
		});
	}

	// tags
	if( $('.tagContainer').length ){
		$('.tagContainer .tag').click(function(){
			$(this).toggleClass('off');
			// gestione tags
			if($(this).hasClass('off'))
				set_tags($(this).text(),'off');
			else
				set_tags($(this).text(),'on');
		});
	}

	//selezione fatturazione
	selezione_elemento('invoice-profile');
	// selezione profilo anagrafica
	selezione_elemento('contact-profile');
	// selezione profilo fatturazione
	selezione_elemento('billing-profile');
	// selezione profilo di pagamento
	selezione_elemento('payment_account-profile');
	// selezione profilo DNS
	selezione_elemento('dns-set');

	// preferenze DNS (default o personali)
	if( $('input[name="dnsprofile"]').length ){
		$('input[name="dnsprofile"]:checked').val() != 'nidoma'? ( $('input[name="dnsprofile"]:checked').val() != 'personal'? null : $('.dns-sets').show().removeClass('hide') ) : $('.dns-sets').hide();
		$('input[name="dnsprofile"]').change(function() {
			$('input[name="dnsprofile"]:checked').val() != 'nidoma'? ( $('input[name="dnsprofile"]:checked').val() != 'personal'? null : $('.dns-sets').show().removeClass('hide') ) : $('.dns-sets').hide();
		});
	}

	add_hosts_manager(); // gestore del bottone aggiungi host

	// scorro tutti gli elementi e vado ad impostare per ognuno il relativo countdown
	//$(document).ready(function($) {
		if( $('.countdown-min').length ){
			$('.countdown-min').each(function(){
				setCountdown($(this));
			});
		}
		if( $('.countdown').length ){
			$('.countdown').each(function(){
				setCountdown($(this), false);
			});
		}
	//});

	// countdown circolare
	if( $('#countdown_clock').length ){
		$('#countdown_clock').circularCountdown({
			strokeDaysBackgroundColor:'rgba(0,0,0,0.06)',
			strokeDaysColor:'rgba(199,101,74,0.8)',
			strokeHoursBackgroundColor:'rgba(0,0,0,0.06)',
			strokeHoursColor:'rgba(235,136,90,0.8)',
			strokeMinutesBackgroundColor:'rgba(0,0,0,0.06)',
			strokeMinutesColor:'rgba(255,175,103,0.8)',
			strokeSecondsBackgroundColor:'rgba(0,0,0,0.06)',
			strokeSecondsColor:'rgba(255,229,145,0.8)',
			strokeWidth:23,
			strokeBackgroundWidth:23,
			countdownEasing:'easeOutBounce',
			countdownTickSpeed:'slow',
			backgroundShadowColor: 'rgba(0,0,0,0.2)',
			backgroundShadowBlur: 0,
			strokeShadowColor: 'rgba(0,0,0,0.2)',
			strokeShadowBlur: 0
		});
	}

	// refresh pagina
	$('body').on('click', '.page-refresh', function(e) {
		//isDevMode() && console.log("ho forzato l'aggiornamento dei dati dell'asta");
		e.preventDefault();
		reloadAuctionWidget();
	});

	// intercetto la chiusura del modale dell'offerta asta
	$('#offer-submit-form').on('hidden', function () {
		clean_incrase_bid();
	});
	
	// modale conferma offerta
	if( $('#offer-submit-btn').length ){
		$('#offer-submit-form').on("keyup", function(e) {
		  var code = e.keyCode || e.which;
		  if (code  == 27) { // ESC
		  }
		  if (code  == 13) { // INVIO
			e.preventDefault();
			return false;
		  }
		});
		$('#offer-submit-btn').click(function() {
			$("#offer-submit-form").submit(function(e){
				e.preventDefault();
			});
			if ($('#offer-max').hasClass('parsley-success')) {
				$('#offer-submit').modal('hide');
				$('#offer-review').modal('show');

				// recupero i dati dell'offerta per il riepilogo
				var new_offer = $('input[id=offer-max]').val();
				var max_offer = $("#offer-current").text();
				var domain = $("#offering-domain").text();
				var until_date = $("#time-left").countdown("option", "until");
				
				// espongo i dati del riepilogo
				$('#offer-current-review').text(max_offer);
				$('#offer-current span').html(parseFloat(new_offer).toFixed(2));	//in order to add .00
				$("#offering-domain-review").text(domain);
				// a differenza degli altri qui mi basta aggiornare l'until date perché è già stata calcolata correttamente nello step precedente
				$("#time-left-review").countdown('destroy'); // reset del countdown
				$("#time-left-review").countdown({until: until_date, compact: true})// aggiorno il count down

				// inserisco i dati per il post
				$("input[name='offer']").val(new_offer);
				$("input[name='domain']").val(domain);

			}
		});
	}

	// loading layer - BEGIN
	$('.loading-layer').click(function() {
		loadlayer();
	});
	if( $('.loading-layer-form').length ){
		$('.loading-layer-form button.btn-primary').click(function() {
			if ($( '#'+$(this).parentsUntil('form').parent().prop('id') ).parsley( 'isValid' )) {
				loadlayer();
			}
		});
	}
	$('#order_confirm .btn-primary').click(function() {
		loadlayer();
	});
	// loading layer - END

	// eseguo il reset dei dati del modale nel caso in cui sia stato cliccato il tasto annulla ("data-dismiss")
	$("button[data-dismiss]").click(function(e){
		clean_incrase_bid();
		if (typeof $msg_obj != 'undefined') {
			if (e.target.form != null && e.target.form != 'undefined'){
				var form_id = e.target.form.getAttribute("id");
				form_reset(form_id);
				$(e.target.form).find(".alert").replaceWith($msg_obj); // sostituisco il messaggio attuale con il messaggio originale
			}
		}
	});

	// eseguo una copia del messaggio di info originale del modale
	var $msg_obj;
	$("button.btn, .btn-primary").click(function(e){
		if( $(this).attr('id')==='add-tags'){
			var data = $("input[name^=add-tag]");
			var list = '';
			$.each(data, function(key, object) {
				//alert($(this).val());// get the value using jquery format
				//alert(object.value);// get the value using javascript value property
				//list += $(this).val() + ',';
				$('#domain-manage-actions').append("<input type='hidden' class='hidden_tags' name='tags[]' value='"+ $(this).val() +"'/>");
			});

		}
		else{
			$(".hidden_tags").remove();
		}
		if (typeof $msg_obj == 'undefined') {
			$msg_obj = $(e.target.form).find(".alert").clone();
		}
	});

	// controllo che siano stati attivati i termini di servizio e il contratto di registrazione domini
	$("input[name=service], input[name=contract], input[name=domains_list_rights]").click(function(e){
		var proceed = false;

		if ($("input[name=service]").length && $("input[name=contract]").length && $("input[name=domains_list_rights]").length){ // caso in cui ci siano tre checbox da verificare
			if ($("input[name=service]").is(":checked") && $("input[name=contract]").is(":checked") && $("input[name=domains_list_rights]").is(":checked")){
				proceed = true;
			}
		} else if ($("input[name=service]").length && $("input[name=contract]").length){ // caso in cui ci siano due checbox da verificare
			if ($("input[name=service]").is(":checked") && $("input[name=contract]").is(":checked")){
				proceed = true;
			}
		} else if ($("input[name=service]").length && $("input[name=domains_list_rights]").length){ // caso in cui ci siano due checbox da verificare
			if ($("input[name=service]").is(":checked") && $("input[name=domains_list_rights]").is(":checked")){
				proceed = true;
			}
		} else if ($("input[name=service]").length){ // caso checbox singolo
			if ($("input[name=service]").is(":checked")){
				proceed = true;
			}
		}

		if (proceed){
			$(".form-actions > button").removeClass("disabled");
			$(".form-actions > button").prop("disabled", false);
		}else{
			$(".form-actions > button").prop("enabled", true);
			$(".form-actions > button").addClass("disabled");
		}

	});

	// se clicco al di fuori del modale devo riprendere il timer
	if ( $('.form-horizontal').length ){
		$('.form-horizontal').focusin(function(){
			$('.modal-backdrop').click(function(){
				if (typeof timer != 'undefined') timer.resume();
			});
		});
	}

	// modale imposta offerta
    $( "body" ).on( "click", 'a[href="#offer-submit"]', function(ev) {
    	ev.preventDefault();
		
		var row = $(this).parentsUntil('tbody', 'tr');
		var offer;
		var offermax;
		var currency;
		var domain;
		var date;
		var incrase_value;
		var timestamp;
		if (row.length>0){ // caso tabella riepilogo aste

			// recupero i dati che mi servono dalle relative celle nel datatable
			offer	 		= row.find('td:first').next().find('.offer').text().split(' ')[1];
			offermax 		= row.find('td:first').next().next().find('.offer').text().split(' ')[1];
			currency		= row.find('td:first').next().find('.offer').text().split(' ')[0];
			domain 			= row.find('td:first').text();
			date 			= row.find('td:last').prev().find(".end-auction-date").text();
			date 			= date.replace(',', '')+':00';
			incrase_value 	= row.find('td:first').next().next().find('.offer-rise').attr('rise-value');

		}else if($('#countdown_timer').length>0){ // caso dettaglio aste

			// esplodo in una stringa offerta_attuale;offerta_tua
			offer 			= $('#bestoffer').text().replace(/[^\.\d]+/, '').trim(); // offerta attuale
			offermax 		= $('#offermax').text().replace(/[^\.\d]+/, '').trim(); // offerta massima attuale
			domain 			= $('#domain_name').text();
			currency 		= $('.note:first').text();
			date			= $('#auction-endat-datetime').text();
			incrase_value 	= $('.plan-actions .btn-primary').attr('rise-value');
			
		}else{ // caso in cui venga modificata l'offerta massima
			return;
		}
		isDevMode() && console.log('offer: ' 			+ offer);
		isDevMode() && console.log('offermax: ' 		+ offermax);
		isDevMode() && console.log('currency: ' 		+ currency);
		isDevMode() && console.log('domain: ' 			+ domain);
		isDevMode() && console.log('date: ' 			+ date);
		isDevMode() && console.log('incrase value: '	+ incrase_value);
		populateOfferModal(domain, offer, offermax, date, currency, incrase_value);
		// nel caso in cui ci sia stata una variazione del time aggiorno anche quello come prima cosa
		if (typeof reloadAuctionWidget === "function") { // safe to use the function
			reloadAuctionWidget();
		}
    });

	// controllo aggiuntivo nuova password modulo preferenze utente
	$( '#edit-profile' ).parsley( 'addListener', {
		onFormSubmit: function (isFormValid, event, ParsleyForm) {
			var data_minlength=8;
			$.each(ParsleyForm.items, function(i,e){
				if (e.$element[0].getAttribute('data-minlength') !== null){
					data_minlength = e.$element[0].getAttribute('data-minlength');
				}
			});

			// se viene specificata la nuova password mi assicuro che prima venga inserita correttamente quella vecchia
	        if ( $( '#newpassword' ).val().length > 0 ) { // nuvova password inserita
	        	$( '#newpassword' ).parsley( 'addConstraint', {required: 'required'} );
	        	$( '#password1' ).parsley( 'addConstraint', {required: 'required', minlength: data_minlength} );
	        	$( '#password2' ).parsley( 'addConstraint', {required: 'required', minlength: data_minlength} );
	        	$( '#password1' ).parsley( 'validate' );
	        	$( '#password2' ).parsley( 'validate' );
	        } else { // non è stato impostata la nuova password rimuovo gli attributi precedenti
	        	$( '#password1' ).parsley( 'removeConstraint', 'required' );
	        	$( '#password2' ).parsley( 'removeConstraint', 'required' );
	        	$( '#newpassword' ).parsley( 'removeConstraint', 'required' );
	        	$( '#password1' ).val('');
	        	$( '#password2' ).val('');
	        }

	        //isDevMode() && console.log('è valido?: ' + $( '#edit-profile' ).parsley( 'isValid' ));

	        if (!$( '#edit-profile' ).parsley( 'isValid' ))
	        	event.preventDefault();

	    }
	} );

	// fix per IE8 per la funzione trim()
	if(typeof String.prototype.trim !== 'function') {
		  String.prototype.trim = function() {
		    return this.replace(/^\s+|\s+$/g, '');
		  }
	}

	var forms = new Array('domain-booking','contact-profile-new', 'dns-set-new');
	for(var i=0; i<forms.length; i++){
		$('#'+forms[i]).keypress(function(e) {
		  if (e.which  == 13) { // INVIO
			return false;
		  }
		});
	}

	// centra l'immagine nello slideshow
    var slidehome = $('#slidehome');
	if ( slidehome.length ){
		slideAdjust( slidehome );
		$(window).resize(function(){
			slideAdjust( slidehome );
		});
        slidehome.carousel();
	}

	// mostra/nascondi elemento
	if($(".toggle-trigger").length){
		$(".toggle-trigger").click(function(){
			$(this).parent().find(".toggle-show-hide").toggleClass('hide');
			$(this).parent().find(".toggle-trigger").children().toggleClass('icon-minus');
		});
	}

	// icona caricamento ajax
	$(document).ajaxSend(function(event, request, settings) {
		$('#loading-indicator').show();
	});

	$(document).ajaxComplete(function(event, request, settings) {
		$('#loading-indicator').hide();
	});

	/**
	 * Case CC IT:
	 * 1. il codice fiscale deve essere obbligatorio
	 * 2. nascondo il codice fiscale nel caso in cui l'anagrafica è straniera
	 * Case CC ES:
	 * 1. straniero, allora a prescindere chiedo il DocNumber
	 * 2. spagnolo, allora chiedo il RegCode se è un privato, altrimenti il DocNumber
	 * caso in cui mostrare il codice fiscale:
	 * 1. Nazionalità: IT - CountryCode: IT
	 */
	$('#address_country, #address_tld').change(function(){
		var cc = $("#address_country option:selected").val();
		var tld = $("#address_tld option:selected").val();
		var user_type = $("#address_usertype_private:checked").val() ? $("#address_usertype_private:checked").val() : $("#address_usertype_company:checked").val();
		isDevMode() && console.log("ho selezionato TLD: " + tld + " - CC: " + cc + " - type: " + user_type);
		switch(tld){
			case 'it':
			case 'es':
                        case 'de':
				$('#address_codfisc').parentsUntil('.control-group').parent().show();
				break;
			default:
				$('#address_codfisc').parentsUntil('.control-group').parent().hide();
		}
	});

	// gestisco il reset del modale per la gestione dei tag del dominio
	/*$('#confirm-modal-tags').on('show', function () {
		reset_choose_domain_tags();
	});*/

	if ($("#controls3 select").length>0){
		$("#controls3 select").change(function(){
			registration_filter(this.name, this.value);
		});
	}

	//gestisco la conferma cancellazione profilo anagrafico
	if ($("a[href='#confirm-modal-delete-profile']").length > 0){
		$("a[href='#confirm-modal-delete-profile']").click(function(){
			var id = $(this).attr('id');
			$('input[name="id"]').val(id);
		});
	}

  //
  $('#custom_dns_action_erase').on('change', function() {
    if( this.checked ){
      $('#custom_dns_action_erase_alert').removeClass('hide');
      $('#custom-dns-zones').addClass('hide');
    } else {
      $('#custom_dns_action_erase_alert').addClass('hide');
      $('#custom-dns-zones').removeClass('hide');
    }
  });
  $('#custom-dns-zones a').click(function(e){ e = $(this);
    if('collapse'===e.data('toggle')){
      var icon = e.find('i');
      if(icon.hasClass('icon-plus')){
        icon.removeClass('icon-plus').addClass('icon-minus');
      } else {
        icon.removeClass('icon-minus').addClass('icon-plus');
      }
    }
  });

}); // end $.function

$(function () {
	$('.subnavbar').find ('li').each (function (i) {
		var mod = i % 3;
		if (mod === 2) {
			$(this).addClass ('subnavbar-open-right');
		}
	});
});

/**
 * comportamento selezione della bulk action
 * @param id
 */
function selezione_elemento(id){
	if( $('#'+id+'-select').length ){
		$('.'+id+'').hide();
		id_selected_value = $('#'+id+'-select').find(':selected').val();
		$('#'+id+'-' + id_selected_value).show().removeClass('hide');
		$('#'+id+'-select').change(function() {
			id_selected_value = $('#'+id+'-select').find(':selected').val();
			if($(this).find(':selected').val() != id+'-modal' ){
				// verifico se c'è un elemento che finisce con un ID
				html_id = id.substr(0, id.lastIndexOf('-'));
				pattern_child = new RegExp(html_id + "-([0-9]+)");
				matches = id.match(pattern_child);
				if(matches == null || !matches[1]){ // non finisce con un ID?
					$('.'+id+'').hide();
					$('#'+id+'-' + id_selected_value).show().removeClass('hide');
				}else{ // finisce con un ID
					$('#'+id+'-' + id_selected_value).siblings().hide();
					$('#'+id+'-' + id_selected_value).show().removeClass('hide');
				}
			}else{
				$('#'+id+'-modal').modal();
			}
			if(id=='dns-set'){
				$('#dns_id').remove();
				if( $('#domain-manage-actions').length > 0){
					if($('#'+id+'-select').val()){
						$('#dns').prop('disabled', false);
						$('#domain-manage-actions').append("<input type='hidden' id='dns_id' name='dns_id' value='"+$('#'+id+'-select').val()+"'/>");
					}else{
						$('#dns').attr('disabled',true);
						$('#dns_id').remove();
					}
				}
			}
		});
	}
}

/**
 * mostra un layer con il loader
 */
function loadlayer(){
    $('#loaderbg').css({ opacity: 0.3 });
	$('#loader').fadeIn('medium');
}

/**
 * nasconde il layer del loader
 */
function unloadlayer(){
    $('#loaderbg').css({ opacity: 0 });
	$('#loader').fadeOut('medium');
}

/**
 *
 * @param id
 */
function openModal(id){
	$('#' + id + '-modal').modal();
}

/**
 * gestisce i messaggi di stato dei modali. nel caso di successo il messaggio di stato viene spostato al nodo specificato.
 * @param msg_id
 * @param modal_id
 * @param destination_id
 * @param message
 * @param is_error
 * @return {boolean}
 */
function widget_message(msg_id, modal_id, destination_id, message, is_error){

	message = message || '';
	is_error = is_error || false;

	widget_content = $("#" + modal_id).parentsUntil(".widget");
	destination = $('#' + destination_id);
	message_content = $('#' + msg_id);
	new_html_content = message;

	$msg_obj = destination.find('#' + msg_id);
	if ($msg_obj.length > 0 && is_error == true) { // caso in cui però il messaggio si trova nella stessa finestra del modale
		return false;
	}

	// clono il contentuo del messaggio e lo ripresento nel widget
	var $obj = message_content.html(new_html_content).clone();

	// rimuovo il messaggio nel modale
	message_content.remove();
	// resetto il contenuto del modale solo nel caso in cui non sia in stato di errore
	if (is_error == false)
		form_reset(modal_id);
	// ricopio il contenuto del messaggio dell'operazione in cima all'id dell'elemento destinato
	if (destination.find('fieldset').length > 0) { // caso in cui debba inserire il contenuto nel modale
//		destination.find('fieldset').before($obj); // vecchia versione
		widget_content.prepend($obj);
	}else{ // caso inserimento nel widget
		destination.children().first().before($obj);
	}

}

/**
 * esegue un reset di tutti i fields presenti ed eventuali errori del modulo parsley
 * @param id
 */
function form_reset(id){
	if( !id ) return;
    id = $('#'+id);
	id.parsley('reset');
	id.find('input[type=text], textarea').val('');
}

/**
 * attivo/disattivo un elenco di checkbox. se specificato vengono filtrati solo gli elementi che hanno come padre un determinato nodo
 * @param obj
 * @param selector
 * @param parent
 */
function toggle_check(obj, selector, parent){
	var destination;
	if (parent){ // controllo di modificare solo gli elementi figli di parent
		destination = $(parent).find(selector);
	}else // modifico tutti quelli del match del selettore
		destination = selector;

	if ($(obj).is(':checked')){ // attivati
		$(destination).prop('checked', true);
	}else{ // disattivati
		$(destination).prop('checked', false);
	}
}

/**
 *
 * @param obj
 * @param compact
 * @param date
 */
function setCountdown(obj, compact, date){
	if (typeof compact == 'undefined')
		compact = true;
	date = date ? date : obj.text().trim();
	if (!date) return;
	isDevMode() && console.log("setCountdown for date: ", date);
	array = date.split(' ');
	tmp1 = array[0].split('-');
	tmp2 = array[1].split(':');
	h = tmp2[0];
	i = tmp2[1];
	s = tmp2[2];
	d = tmp1[2];
	m = tmp1[1];
	Y = tmp1[0];
	$(obj).countdown('destroy'); // reset del countdown
	// applico la nuova configurazione
	server_time = core.server_time;
	isDevMode() && console.log('lavoro con core.server_time', core.server_time);
	server_timezone = parseInt(core.server_timezone)/100;
	timezone_diff_timestamp = (3600*server_timezone*1000);
	server_timestamp = core.server_timestamp*1000;
	expire_auction_utc_timestamp = Date.UTC(Y, m-1, d, h, i, s);
	client_timestamp = Date.now();
	isDevMode() && console.log("server timestamp: ", server_timestamp + '( ' + server_time + ' )');
	isDevMode() && console.log("client timestamp: ", client_timestamp + '( ' + new Date() + ' )');
	isDevMode() && console.log("expire auction timestamp: ", expire_auction_utc_timestamp + '( ' + new Date(expire_auction_utc_timestamp) + ' )');
	isDevMode() && console.log("timestamp diff: ", client_timestamp + '[Client] ('+expire_auction_utc_timestamp+'[CloseAuction]-'+'('+server_timestamp+'[serverTime]+'+timezone_diff_timestamp+'[server TimeZone])');
	rebuilded_timestamp = client_timestamp + (expire_auction_utc_timestamp-(server_timestamp+timezone_diff_timestamp));
	isDevMode() && console.log("rebuilded timestamp: ", rebuilded_timestamp);
	isDevMode() && console.log("rebuilded date: ", new Date(rebuilded_timestamp));
	until_date = new Date(rebuilded_timestamp); // UTC // until_date = (diff timestamp server (+timezone server) e data expire) + data client
	$(obj).countdown({serverSync: server_time, until: until_date, compact: compact, description: ''});
}

/**
 *
 * @param obj
 * @param date
 * @param compact
 */
function updateCountdown(obj, date, compact){
	return setCountdown(obj, compact, date);
}

/**
 *
 * @param timestamp
 */
function updateCircularCountdown(timestamp){
	date = getDate(timestamp);
	$('#countdown_clock').circularCountdown('update', {until: date});
}

/**
 *
 * @param timestamp
 * @return {Date}
 */
function getDate(timestamp){
	var date = new Date(timestamp*1000); // Multiply by 1000 because JS works in milliseconds instead of the UNIX seconds
	var year = date.getUTCFullYear();
	var month = date.getUTCMonth(); // getMonth() is zero-indexed
	var day = date.getUTCDate();
	var hours = date.getUTCHours();
	var minutes = date.getUTCMinutes();
	var seconds = date.getUTCSeconds();
	month = (month < 10) ? '0' + month : month;
	day = (day < 10) ? '0' + day : day;
	hours = (hours < 10) ? '0' + hours : hours;
	minutes = (minutes < 10) ? '0' + minutes : minutes;
	seconds = (seconds < 10) ? '0' + seconds: seconds;
	//isDevMode() && console.log('UTC getDate', year+',' +month+',' +day+',' +hours+','+ minutes+',' +seconds);
	return new Date(year, month, day, hours, minutes, seconds);
}

/**
 * popolo il modale per aumentare l'offerta di una specifica asta
 * @param domain
 * @param offer
 * @param offermax
 * @param date
 * @param currency
 * @param incrase_value
 */
function populateOfferModal(domain, offer, offermax, date, currency, incrase_value){
	if (offer)
		$('#offer-max').parsley( 'updateConstraint', { min: parseFloat(offer) + parseInt(incrase_value) } );  //offer consistently with method logic
	if (offermax)
		$('#offermax-current').text(currency + ' ' + offermax);
	if (domain)
		$('#offering-domain').text(domain);
	if (date)
		$('#time-left').text(date);
	if (offer)
		$('#offer-current').text(currency + ' ' + offer);
	setCountdown( $('#time-left') );
}

function slideAdjust( el ){
    var half_height = $(el).outerHeight();
    half_height = half_height>0? -(half_height/2):0;
    $(el).find('.item img').each(function(){
        var img = $(this);
        $.loadImage( img.attr('src') ).done(function(image) {
            //img.css({ 'margin-top': '-'+parseInt((img.actual('height')/2)+half_height)+'px' });
        });
    });
}

$.loadImage = function(url) { // Define a "worker" function that should eventually resolve or reject the deferred object
    var loadImage = function(deferred) {
        var image = new Image();
        image.onload = loaded; // Set up event handlers to know when the image has loaded or fails to load due to an error or abort
        image.onerror = errored; // URL returns 404, etc
        image.onabort = errored; // IE may call this if user clicks "Stop"
        image.src = url; // Setting the src property begins loading the image
        function loaded() {
            unbindEvents(); // Calling resolve means the image loaded successfully and is ready to use.
            deferred.resolve(image);
        }
        function errored() {
            unbindEvents(); // Calling reject means we failed to load the image (e.g. 404, server offline, etc).
            deferred.reject(image);
        }
        function unbindEvents() { // Ensures the event callbacks only get called once.
            image.onload = null;
            image.onerror = null;
            image.onabort = null;
        }
    };
    // Create the deferred object that will contain the loaded image. We don't want callers to have access to the resolve() and reject() methods, so convert to "read-only" by calling `promise()`
    return $.Deferred(loadImage).promise();
};

function precise_round(value, decPlaces){
    var val = value * Math.pow(10, decPlaces);
    var fraction = (Math.round((val-parseInt(val))*10)/10);

    //this line is for consistency with .NET Decimal.Round behavior
    // -342.055 => -342.06
    if(fraction == -0.5) fraction = -0.6;

    val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
    return val;
}

/**
 * funzione custom che in base al tipo di bulk_action selezionata esegue una determinata operazione all'interno del relativo modale
 * @param bulk_action
 * @param e
 */
function actionModal(bulk_action, e){
	bulk_action = bulk_action || $('select[name=action]').val();
	switch(bulk_action){
		case 'tags':
			manage_modal_tags(e);
		break;
		case "tech":
			if(ids.length>0){
				get_eppcontactid('tech');
			}
		break;
		case "custom-dns":
			$.each($(".custom-dns-sets input[name^='custom_dns']"), function(i,e){ e = $(e);
				if('custom_dns_action'===e.attr('name') && !e.prop('checked')){ return true; }
				$('#domain-manage-actions').append("<input type='hidden' name='"+e.attr('name')+"' value='"+e.val()+"'/>");
			});
		break;
		case 'domain-redirect':
			$('#domain-manage-actions').append("<input type='hidden' name='"+bulk_action+"-url' value='"+$('#'+bulk_action+"-url").val()+"'/>");
		break;
	}
}


/**
 * gestisce quali tag attribuire ad un dominio all'interno del modale
 * @param e
 */
function manage_modal_tags(e){
	if(!e) return;
	
	tag_obj = $(e.currentTarget);
	
	if(!tag_obj) return;
	
	// cerco tutti i tag presenti nel container e li rendo disponibili alla selezione
	tag_val = tag_obj.text();
	rows = $('input[name="add-tag[]"]').length-1; // numero di tag ammessi

	if(typeof choosen == 'undefined') // inizializzo l'oggetto
		choosen = new Object();

	if(typeof d == 'undefined') // inizializzo la variabile
		d = new Array();
	
	total_tags = tag_obj.parent().find(".tag").length;
	isDevMode() && console.info("total tags: ", total_tags);

	if( !tag_obj.hasClass('off') && $(choosen[tag_val]).length >0 && c>0 ){ // posso rimuovere
		isDevMode() && console.log('entro rimuovo: ' + c + ' > 0');
		obj_index=$('input[name="add-tag[]"]').index(choosen[tag_val]); // posizione in cui andrò ad aggiungere il prossimo input
		isDevMode() && console.log("in d ho:");
		isDevMode() && console.log(d);
		isDevMode() && console.log("e sto cercando di buttare dentro " + obj_index);
		isDevMode() && console.info(d.push(obj_index)); // lo inserisco nella coda degli elementi eliminati
		isDevMode() && console.log(d);
		isDevMode() && console.log('devo ripristinare alla posizione ' + obj_index + ' per ' + tag_val);
		$(choosen[tag_val]).val(''); // rimuovo il valore associato all'input
		tag_obj.toggleClass('off'); // applico la classe css
		isDevMode() && console.log('c: ', c);
		//delete choosen[tag_val]; // rimuovo l'elemento
		// TODO: se il numero di elementi eliminati combacia con quello dei tag inattivi, allora posso ripristinare il puntatore alla prima posizione
		if(d.length == total_tags){
			isDevMode() && console.info("ho eliminato tutti gli elementi! azzero il puntatore");
			d = new Array();
			c=0; // reinizializzo il contatore
		}
	}else{ // aggiungo
		if(typeof c == 'undefined') c=0; // inizializzo il contatore
		r=false;
		if(d.length>0){ // ci sono degli elementi nella coda di quelli rimossi?
			r = d.pop(); // recupero l'ultimo inserito
			isDevMode() && console.info("eseguo il pop per " + r);
		}
		if( c <= rows || r !== false ){ // fin tanto che non supero il massimo consentito o ci sono elementi rimossi in coda, posso continuare
			if(r !== false){ // devo sostituire un elmento eliminato precedentemente?
				tmp=c; // salvo il contenuto di c per non sovrascriverlo
				isDevMode() && console.log('posizione precedente: ' + tmp);
				c=r; // posizione dell'elemento precedentemente eliminato
				isDevMode() && console.log('nuova posizione: ' + c);
			}
			isDevMode() && console.log('aggiungo un elemento - array: ' + c + ' <= ' + rows);
			tag_obj.toggleClass('off'); // applico la classe css
			choosen[tag_val] = $('input[name="add-tag[]"]').eq(c); // assegno il valore nell'oggetto
			$('input[name="add-tag[]"]').eq(c).val(tag_val); // assegno il valore del tag al corrispettivo campo di input
			c=c+1; // aumento il contatore
			if(r !== false){
				c=tmp; // riallineo il contatore all'ultima posizione nota
				isDevMode() && console.log("posizione rissegnata: " + c);
			}
		}
	}
}

/**
 * resetto i tag presenti nel modale seleziona tag
 */
function reset_choose_domain_tags(){
	$('#choose_tags.tagContainer > .tag').remove(); // svuoto l'elenco dei tag
	$('input[name="add-tag[]"]').val(''); // azzero i valori degli input a prescindere
	delete rows;
	delete r;
	delete d;
	delete c;
	delete obj_index;
	delete choosen;
	isDevMode() && console.log("RESET TAGs");
}

/**
 * inizializzo dei datatable con dei valori di default per poi eventualmente modificarli
 * @returns DataTableObject
 * @param table_name string
 * @param currentSource string
 */
function initTable(table_name, currentSource){
	params = core.getDataTableParams(); // parametri che sono da passare al datatable
	var custom_controls = $('.datatables-custom-controls');
	var tableobj;
	var prev_value;
	switch(table_name){
		case 'transfer':
			tableobj = $('.domainimport').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aoColumns": [
		              { "bSortable": false }, // id
		              null, // domain name
		              { "sType": "numeric-comma" }, // price
		              { "bSortable": false }, // authcode
		              { "bSortable": false }, // dns_set
				 ],
				"iDisplayLength": limit_table_rows,
				"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
				"fnInitComplete": function(oSettings, json) {
					var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
					custom_controls.find('#datatables-bottom-controls').remove();
					$('#domactions-bottom').append( controls );
					var options = $($(".dns_id_selector").get(0)).find("option");
					var cloned = options.clone(); // mi basta solo il primo
					$("#dns_id_all").html(cloned);
					$("#dns_id_all").on('change', function(e){
						var value = $(e.currentTarget).val();
						$.each($(".dns_id_selector"), function(i,e){
							$(e).prop('selectedIndex',0);
							$(e).find("option[value='" + value + "']").prop("selected", true);
							var domain_id = $(e).attr("name").match('[0-9]+').pop();
							dnsses.setItem(domain_id, value);
						});
					});
					$("#dns_id_all.set-default").find("option").prop("selected", false); // clear selected if set-default (if I have an active session, I must set the bulk dns set selector to the default one)
					$(".dns_id_selector").on('change', function(){
						var value = $(this).val();
						var domain_id = $(this).attr("name").match('[0-9]+').pop();
						dnsses.setItem(domain_id, value);
					});
				},
				'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'marketplace':
			tableobj = $('.marketplaceimport').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aoColumns": [
		              { "bSortable": false }, // id
		              null, // domain name
		              null, // for review?
				],
	            "iDisplayLength": limit_table_rows,
	            "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
	            "fnInitComplete": function(oSettings, json) {
	            	var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
	            	custom_controls.find('#datatables-bottom-controls').remove();
	            	$('#domactions-bottom').append( controls );
	            },
	            'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'registration_manager':
			tableobj =  $('.registration-manager').dataTable( {
				"bDestroy": true,
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"aoColumns": [
					{ "bSortable": false }, // domain id
					null, 					// domain name
					null,					//anagrafica associata
					{"sType": "natural"},	// date created at
					{"sType": "natural"},	// date valid until
					null, 					// renew manual/auto
					null, 					// dns
					null, 					// tags
					null, 					// status
					{ "bSortable": false } 					// for sale (YES/NO)
				],
				"aaSorting": [[ 0, "desc" ]],
				"sPaginationType": "bootstrap",
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
				"fnServerParams": function ( aoData ) {
					for(var key in params) {
						value = params[key];
						aoData.push( { "name":key, "value":value } );
					}
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
				"fnInitComplete": function(oSettings, json) {
			    	var controls1 = $('#controls1');
					var controls2 = $('#controls2');
					$('#domactions-top').append( controls1 );
					$('#domactions-bottom').append( controls2 );

					controls1.change(function(){
						controls2.find('select').val(controls1.find('select').val());
					});

					controls2.change(function(){
						controls1.find('select').val(controls2.find('select').val());
					});
					this.fnSetFilteringDelay(1000);
			    },
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function() {
					unloadlayer();
				},
				"fnDrawCallback": function(oSettings, json) {

					// x prima cosa popolare i check se cliccati precedentemente
					checkme('.registration_manager');

					// gestione click singolo sui checkbox
					$(".checkboxesX").click(function () {
						if (this.checked) {
							ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
						}
						else {
							ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
						}
						checkme('.registration_manager');
					});

					// gestione click su check seleziona/deseleziona tutti
					$("#selectall").click(function () {
						var valore = this.checked;
						$('.checkboxesX').each(function () {
							if (this.disabled) return;
							this.checked = valore;
							if (valore)
								ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
							else
								ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
						});
					});

					// appendo ogni volta il filtro
					var controls1 = $('#controls1');
					var controls2 = $('#controls2');
					var controls3 = $('#controls3');
					$('#domactions-top').append( controls1 );
					$('#domactions-bottom').append( controls2 );
					$('#tags').append( controls3 );
					$('#controls1').change(function(){
						$('#controls2 select').val($('#controls1 select').val());
					});
					$('#controls2').change(function(){
						$('#controls1 select').val($('#controls2 select').val());
					});

					unloadlayer();

				},
				'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			} );
			break;
                
                case 'dns_queue_manager':
			tableobj =  $('.dns-queue-manager').dataTable( {
				"bDestroy": true,
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"aoColumns": [
					{ "bSortable": false }, // domain id
					null, 					// domain name
					null, 					// status
					null,	 				// dns
					{"sType": "natural"}, 	// expire
				],
				"aaSorting": [[ 0, "desc" ]],
				"sPaginationType": "bootstrap",
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
				"fnServerParams": function ( aoData ) {
					for(var key in params) {
						value = params[key];
						aoData.push( { "name":key, "value":value } );
					}
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
				"fnInitComplete": function(oSettings, json) {
			    	var controls1 = $('#controls1');
					var controls2 = $('#controls2');
					$('#domactions-top').append( controls1 );
					$('#domactions-bottom').append( controls2 );

					controls1.change(function(){
						controls2.find('select').val(controls1.find('select').val());
					});

					controls2.change(function(){
						controls1.find('select').val(controls2.find('select').val());
					});
					this.fnSetFilteringDelay(1000);
			    },
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function() {
					unloadlayer();
				},
				"fnDrawCallback": function(oSettings, json) {

					// x prima cosa popolare i check se cliccati precedentemente
					checkme('.dns-queue-manager');

					// gestione click singolo sui checkbox
					$(".checkboxesX").click(function () {
						if (this.checked) {
							ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
						}
						else {
							ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
						}
						checkme('.dns-queue-manager');
					});

					// gestione click su check seleziona/deseleziona tutti
					$("#selectall").click(function () {
						var valore = this.checked;
						$('.checkboxesX').each(function () {
							if (this.disabled) return;
							this.checked = valore;
							if (valore)
								ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
							else
								ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
						});
					});

					// appendo ogni volta il filtro
					var controls1 = $('#controls1');
					var controls2 = $('#controls2');
					var controls3 = $('#controls3');
					$('#domactions-top').append( controls1 );
					$('#domactions-bottom').append( controls2 );
					$('#tags').append( controls3 );
					$('#controls1').change(function(){
						$('#controls2 select').val($('#controls1 select').val());
					});
					$('#controls2').change(function(){
						$('#controls1 select').val($('#controls2 select').val());
					});

					unloadlayer();

				},
				'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			} );
			break;
                
		case 'marketplace_manager':
			tableobj = $('.marketplacemanager').dataTable( {
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 2, "desc" ]],
				"aoColumns": [
		              { "bSortable": false }, // id
		              null, // domain name
		              { "sType": "natural" }, // create date
		              { "sType": "sort-numbers-ignore-text" }, // price => devo ignorare il testo nelle righe vuote per il sort
		              { "sType": "sort-numbers-ignore-text" }, // target price => devo ignorare il testo nelle righe vuote per il sort
		              null, // sell type
		              null, // tags
		              null, // template thumb
				],
			    "iDisplayLength": limit_table_rows,
			    "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
			    "fnServerParams": function ( aoData ) {
					for(var key in params) {
						value = params[key];
						aoData.push( { "name":key, "value":value } );
					}
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
			        $.ajax( {
			            "dataType": 'json',
			            "type": "POST",
			            "url": currentSource,
			            "data": aoData,
			            "success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
			        });
			    },
			    "fnInitComplete": function(oSettings, json) {
			    	var controls1 = $('#controls1');
					var controls2 = $('#controls2');
					$('#domactions-top').append( controls1 );
					$('#domactions-bottom').append( controls2 );

					controls1.change(function(){
						controls2.find('select').val(controls1.find('select').val());
					});

					controls2.change(function(){
						controls1.find('select').val(controls2.find('select').val());
					});
					this.fnSetFilteringDelay(1000);
			    },
			    // gestisco il loader del layer
			    "fnPreDrawCallback": function() {
		            loadlayer();
		            return true;
		        },
		        "fnDrawCallback": function() {
		            unloadlayer();
		        },
		        // fine loader
			    'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'negotiations_for_sell':
			tableobj = $('.negotiations_for_sell').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 3, "desc" ]],
				"aoColumns": [
				    null, // domain name
				    null, // status
				    { "sType": "natural" }, // create date
				    { "sType": "sort-numbers-ignore-text" }, // update date
				    null, // sell type
				    { "sType": "sort-numbers-ignore-text" }, // price => devo ignorare il testo nelle righe vuote per il sort
				    { "sType": "sort-numbers-ignore-text" }, // target price => devo ignorare il testo nelle righe vuote per il sort
				    { "sType": "sort-numbers-ignore-text" }, // best offer price => devo ignorare il testo nelle righe vuote per il sort
				    null, // tag
				    { "bSortable": false }, // actions
				],
			    "iDisplayLength": limit_table_rows,
			    "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
			    "fnInitComplete": function(oSettings, json) {
			    	var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
			    	custom_controls.find('#datatables-bottom-controls').remove();
			    	$('#domactions-bottom').append( controls );
					this.fnSetFilteringDelay(1000);
			    },
			    'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'negotiations_for_buy':
			tableobj = $('.negotiations_for_buy').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 3, "desc" ]],
				"aoColumns": [
		            null, // domain name
		            null, // status
		            { "sType": "natural" }, // create date
		            { "sType": "sort-numbers-ignore-text" }, // update date
		            { "sType": "sort-numbers-ignore-text" }, // current selling price => devo ignorare il testo nelle righe vuote per il sort
		            { "sType": "sort-numbers-ignore-text" }, // your offer => devo ignorare il testo nelle righe vuote per il sort
		            { "sType": "sort-numbers-ignore-text" }, // current best offer price => devo ignorare il testo nelle righe vuote per il sort
		            { "bSortable": false }, // actions
	            ],
	            "iDisplayLength": limit_table_rows,
	            "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
	            "fnInitComplete": function(oSettings, json) {
	            	var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
	            	custom_controls.find('#datatables-bottom-controls').remove();
	            	$('#domactions-bottom').append( controls );
					this.fnSetFilteringDelay(1000);
	            },
	            'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'appraisal_archive':
			tableobj = $('.appraisal_archive').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 4, "desc" ]],
				"aoColumns": [
		            null, // domain name
		            null, // service
		            null, // status
		            { "sType": "natural" }, // create date
		            { "sType": "natural" }, // update date
		            { "sType": "sort-numbers-ignore-text" }, // appraisal price => devo ignorare il testo nelle righe vuote per il sort
		            { "bSortable": false }, // actions
	            ],
	            "iDisplayLength": limit_table_rows,
	            "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
	            "fnInitComplete": function(oSettings, json) {
	            	var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
	            	custom_controls.find('#datatables-bottom-controls').remove();
	            	$('#domactions-bottom').append( controls );
					this.fnSetFilteringDelay(1000);
	            },
	            'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'billing_archive':
			tableobj = $('.billingarchive').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 1, "desc" ]],
				"aoColumns": [
		              { "sType": "natural" }, // document date
		              { "sType": "string" }, // loaded credit date
		              { "sType": "numeric-comma" }, // invoice amount
		              { "sType": "numeric-comma" }, // document name
		              null, // billing address
		              { "bSortable": false }, // download address
              	],
              "iDisplayLength": limit_table_rows,
              "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
              "fnInitComplete": function(oSettings, json) {
            	  var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
            	  custom_controls.find('#datatables-bottom-controls').remove();
            	  $('#domactions-bottom').append( controls );
				  this.fnSetFilteringDelay(1000);
              },
              'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'credit_table':
			tableobj = $('.credit_table').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 0, "desc" ]],
				"aoColumns": [
		              { "sType": "string" }, // date request
		              { "sType": "natural" }, // payment type
		              { "sType": "numeric-comma" }, // amount
		              { "sType": "numeric-comma" }, // amount confirmed
		              { "sType": "natural" }, // date confirmed
		              null, // billing
		              { "bSortable": false }, // actions
				],
	            "iDisplayLength": limit_table_rows,
	            "sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
	            "fnInitComplete": function(oSettings, json) {
	            	var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
	            	custom_controls.find('#datatables-bottom-controls').remove();
	            	$('#domactions-bottom').append( controls );
					this.fnSetFilteringDelay(1000);
	            },
	            'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'docs':
			tableobj = $('.docs').dataTable( {
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 0, "desc" ]],
				"aoColumns": [
		              { "sType": "natural" }, // document date
		              null, // document name
		              null, // document related object (string)
		              { "bSortable": false }, // actions
				],
				"iDisplayLength": limit_table_rows,
				"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
				"fnInitComplete": function(oSettings, json) {
					var controls = custom_controls.find('#datatables-bottom-controls').clone( true );
					custom_controls.find('#datatables-bottom-controls').remove();
					$('#domactions-bottom').append( controls );
					this.fnSetFilteringDelay(1000);
				},
				'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'marketplace_search':
			tableobj = $('.marketplace_search').dataTable( {
	    		"bProcessing": false,
	    		"bServerSide": true,
	    		"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"aaSorting": [[ 3, "asc" ]],
				"aoColumns": [
					{ "sType": 'html' },
					{ "sType": 'num-html' },
					{ "sType": 'text' },
				],
			    // gestisco il loader del layer
			    "fnPreDrawCallback": function() {
		            loadlayer();
		            return true;
		        },
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				"fnInitComplete": function(oSettings, json) {
					//NOTA:...il delay parte cmq a prescindere dal carattere!!!
					this.fnSetFilteringEnterPress(); //prima limito i caratteri
					this.fnSetFilteringDelay(1000); //poi imposto il delay
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
			});
			break;
		case 'booking-list':
			tableobj = $('.bookings').dataTable({
				"bProcessing": false,
				"bServerSide": true,
				"bDestroy": true,
				"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"aaSorting": [[ 1, "desc" ]],
				"aoColumns": [
					{ "sType": "natural" }, // domain name
					{ "sType": "natural" }, // date created at,
					{ "sType": "natural" }, // date droptime at,
					{ "sType": "natural" }, // offerta
					{ "sType": "natural" }, // offermax
					{ "bSortable": false }, // status,
					{ "bSortable": false } // action
				],
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				"fnInitComplete": function(oSettings, json) {
					this.fnSetFilteringDelay(1000);
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
			});
			break;
		case 'registration_push':
			tableobj = $('.registration-push').dataTable( {
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"aaSorting": [[ 1, "desc" ]],
				"aoColumns": [
                    { "bSortable": false }, // registration id
					{ "sType": "natural" }, // domain name
					{ "sType": "natural" }, // customer,
					{ "sType": "natural" }, // status,
					{ "sType": "natural" }, // created_at,
					{ "sType": "natural" }, // accepted_at,
					{ "sType": "natural" }, // deleted_at,
				],
				"iDisplayLength": limit_table_rows,
				"sDom": '<"dt-topbar"lf>r<"#domactions-top">t<"dt-bottombar"<"#domactions-bottom">ip>',
				"fnServerParams": function ( aoData ) {
					for(var key in params) {
						value = params[key];
						aoData.push( { "name":key, "value":value } );
					}
				},
                "fnServerData": function ( sSource, aoData, fnCallback ) {
                    $.ajax( {
                        "dataType": 'json',
                        "type": "POST",
                        "url": currentSource,
                        "data": aoData,
                        "success": fnCallback,
                        "error": handleAjaxError, // this sets up jQuery to give me errors
                        "timeout": 20000, //milliseconds
                    });
                },
                "fnInitComplete": function(oSettings, json) {
                    var controls1 = $('#controls1');
                    var controls2 = $('#controls2');
                    $('#domactions-top').append( controls1 );
                    $('#domactions-bottom').append( controls2 );

                    controls1.change(function(){
                        controls2.find('select').val(controls1.find('select').val());
                    });

                    controls2.change(function(){
                        controls1.find('select').val(controls2.find('select').val());
                    });
                    this.fnSetFilteringDelay(1000);
                },
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				// fine loader
                'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case 'registration-limbo':
			tableobj = $('#registration-limbo').dataTable( {
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"aaSorting": [[ 2, "asc" ]],
				"aoColumns": [
					{ "sType": "natural" }, // domain_name
					{ "sType": "natural", "sClass": "txtmid" }, // type,
					{ "sType": "natural", "sClass": "txtmid" }, // created at,
					{ "sType": "natural", "sClass": "txtdx" }, // amount,
				],
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				"fnInitComplete": function(oSettings, json) {
					this.fnSetFilteringDelay(1000);
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
				'bRetrieve': true // FONDAMENTALE: serve a richiamare questo datatable
			});
			break;
		case "activeAuctionsDataTable":
			tableobj = $('.' + table_name).dataTable( {
				"bProcessing": false,
				"bServerSide": true,
				"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
				"aaSorting": [[ 1, "asc" ]],
				"aoColumns": [
					{ "sWidth": "5%", "sClass": "center", "bSortable": false }, // Checkbox
					{ "sType": "string", "sWidth": "40%" }, // domain_name
					{ "sType": "numeric", "sWidth": "15%", "sClass": "center" }, //ultimo prezzo,
					{ "sWidth": "15%" }, //time last,
					{ "sWidth": "15%", "sClass": "center", "bSortable": false}, //entra in asta,
				],
				// gestisco il loader del layer
				"fnPreDrawCallback": function() {
					loadlayer();
					return true;
				},
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				"fnInitComplete": function(oSettings, json) {
					$('#domactions').html('<p style="margin:5px 0;"><i class="icon-hand-up"></i> <button class="btn btn-primary" type="submit"><i class="icon-pushpin"></i> prosegui con i domini selezionati</button></p>');
					this.fnSetFilteringDelay(1000);
					$('.ttip').tooltip();
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
			});
		break;

		default:
			tableobj = $('.' + table_name).dataTable( {
	    		"bProcessing": false,
	    		"bServerSide": true,
	    		"sAjaxSource": currentSource,
				"sPaginationType": "bootstrap",
				"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
				"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
				"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
			    // gestisco il loader del layer
			    "fnPreDrawCallback": function() {
		            loadlayer();
		            return true;
		        },
				"fnDrawCallback": function(oSettings, json) {
					// codice richiamato ad ogni aggiornamento di datatable
					unloadlayer();
				},
				"fnInitComplete": function(oSettings, json) {
					this.fnSetFilteringDelay(1000);
					$('.ttip').tooltip();
				},
				"fnServerData": function ( sSource, aoData, fnCallback ) {
					$.ajax( {
						"dataType": 'json',
						"type": "POST",
						"url": currentSource,
						"data": aoData,
						"success": fnCallback,
						"error": handleAjaxError, // this sets up jQuery to give me errors
						"timeout": 20000, //milliseconds
					});
				},
			});
	}
	return tableobj;
}

/**
 *
 */
function add_hosts_manager(){
	var new_dns_hosts = $('#new-dns-hosts');
	var max_hosts = dns_hosts_limit;
	var formid = '#dns-set-new';
	if( new_dns_hosts.length ){
		$('.dns-host-add').on('click', function(e) {
			e.preventDefault();
			$( formid ).parsley().destroy(); // distruggo il parsley
			var clone = new_dns_hosts.children("li:first-child").clone(); // clono l'elemento
			$(clone).children("input").attr('value', ''); // rimuovo il valore memorizzato al clone
			$(clone).children("input").val(''); // rimuovo eventuale testo al clone
			new_dns_hosts.append(clone); // appendo il clone
			$( formid ).parsley(); // reinizializzo con il nuovo campo
			if($('input[name="dns-host[]"]').length >= max_hosts) {
				$('.dns-host-add').hide();
			}
			else
				$('.dns-host-add').show();
		});
		new_dns_hosts.delegate('.dns-host-remove', 'click', function(e) {
			e.preventDefault();
			if( new_dns_hosts.children("li").length == 2 ) return; // limito ad avere sempre almeno una coppia di host
			$(this).parent().empty().remove();
			$( formid ).parsley().destroy(); // distruggo il parsley
			$( formid ).parsley(); // reinizializzo con il nuovo campo
			if($('input[name="dns-host[]"]').length >= max_hosts) {
				$('.dns-host-add').hide();
			}
			else
				$('.dns-host-add').show();
		});

	}
}

//controlla per ogni checkbox presente nella pagina: se presente in ids allora check, se non presente allora non check
if (typeof checkme !== 'function') // solo se non è stata precedentemente definita
function checkme(DataTable_id, _limit){
	var error = false;
	var limit = _limit ? _limit : (_limit === false ? '' : 15);
	var checkboxes = $(DataTable_id).find('.checkboxesX');
	if (checkboxes.length === 0) return false;
	$(checkboxes.get().reverse()).each(function(){
  		if( ids.length === "undefined" || ids.length ){
  			ids.hasItem(this.value) ? $(this).prop('checked', true) : $(this).prop('checked', false);
  	  	}
  	  	else{
  	  	  	if(ids.hasItem(this.value)){
	  	  		$(this).prop('checked', false);
	  	  		ids.removeItem( this.value);
				error = true;
  	  	  	}
  	  	}
  	});

  	if($(".checkboxesX:checked").length === 0) {
        $("#selectall").removeAttr("checked");
    }
	if($(".checkboxesX").length === $(".checkboxesX:checked").length && $(".checkboxesX:checked").length>0) {
		$("#selectall").prop("checked", "checked");
	} else {
		$("#selectall").removeAttr("checked");
	}

}

/**
 * popolo il modale con l'elenco dei contatti relativi alle registrazioni selezionate
 * @param type
 */
function get_eppcontactid(type){
	if (!type) return;
	$.ajax({
	    type: "GET",
	    url: '{/literal}{url_for action=ajax}{literal}' + '?act=' + type,
	    async: false,
	    dataType: "json",
		success: function(contacts){
			for(var tld in contacts) {
				isDevMode() && console.log(tld);
				isDevMode() && console.log(contacts);
			}
		}
	});
}

/**
 * funzione che popola in base agli elementi presenti nell'hash "ids" dei campi di input da appendere alla fine del modulo
 * @param event
 * @return {boolean}
 */
function fill_bulk_operation_data(event){
	field_name = event.data.name;
	operation_name = event.data.operation;
	html_append_form_data = event.data.form_data.clone(); // clono altrimenti rimuovo gli elementi
	if(ids.length > 0){
		$('[name=operation]').val(operation_name); // imposto il nome dell'operazione in base all'id del bottone del modale cliccato
		// aggiungo al form tutti gli elementi sezionati in modo da passarli come parametri
		if(html_append_form_data){
			if ($('.datatables-custom-controls').length){ // hidden data
				$('.datatables-custom-controls').append(html_append_form_data);
			}else{ // not hidden data
				$('#domain-manage-actions').append(html_append_form_data);
			}
		}
		ids.each(function(key,item){
			duplicate = false;
			$('input[name="'+field_name+'[]"]').each(function(){
				if($(this).val() == key){ // inserisco solo i campi che non ci sono
					duplicate = true;
				}
			});
			if(!duplicate){ // elemento unico?
				$('#domain-manage-actions').append("<input type='hidden' name='"+field_name+"[]' value='"+key+"'/>");
			}
		});
		$('#domain-manage-actions').submit();
		return true;
	}
	return false;
}

/**
 * gestione degli errori del modulo parsley
 * @param form
 */
function parsley_check_errors(form){
	$( form ).parsley( 'addListener', {
		onFieldError: function ( elem ) {
			unloadlayer();
		},
		onFieldValidate: function ( elem ) {
	        // if field is not visible, do not apply Parsley validation!
	        if ( !$( elem ).is( ':visible' ) ) {
	            return true;
	        }
	        return false;
	    },
	    onFormSubmit: function ( isFormValid, event, ParsleyForm ) {
			if(!isFormValid){
				unloadlayer();
			}
		}
	} );
}

/**
 * gestore della label in funzione del tipo di offerta
 * @param sell_type_selector
 * @param match_offer_min
 * @param match_offer_free
 * @param minimum_price
 * @param sold_price
 * @param form_price_container
 * @param form_target_price_container
 */
function change_price_offer_label(sell_type_selector, match_offer_min, match_offer_free, minimum_price, sold_price, form_price_container, form_target_price_container){
	//gestisco la label del campo prezzo in funzione della tipologia selezionata
	$( '#'+sell_type_selector ).change(function(){
		sell_type = $(this).val();
		$("#"+form_target_price_container).hide();
		if ( sell_type == match_offer_min ){ // prezzo minimo
			$("#"+form_target_price_container).show();
			$("#"+minimum_price).show();
			$("#"+sold_price).hide();
		}else{ // prezzo fisso
			$("#"+minimum_price).hide();
			$("#"+sold_price).show();
			$("#"+form_price_container).hide();
		}
		if( sell_type == match_offer_free ){ // offerta libera?
			$("#"+form_price_container).hide();
			$("#"+form_target_price_container).show();
		}else{ // prezzo fiso o minimo
			$("#"+form_price_container).show();
		}
	});
}

/**
 * appende al form specificato dei campi di input nascosti con i relativi valori nell'hash table
 * @param form_selector
 * @param input_name
 */
function form_append_ids(form_selector,input_name){
	$(form_selector).submit(function(){
		//input = $("input[name='"+input_name+"']");
		$(form_selector + " input[name='marketplace_id[]']").remove(); // prima rimuovo eventuali ID rimasti da una selezione precedente
		ids.each(function(key,item){
			//input.each(function(){
				//isDevMode() && console.log($(this).attr("value") + '=' + key);
				//if($(this).attr("value") != key){ // non è già presente
					//isDevMode() && console.log("inserisco " + key);
					$(form_selector).append("<input type='hidden' name='"+input_name+"[]' value='"+key+"' />");
				//}
			//});
		});
		//return false;
	});
}

if (typeof checkme !== 'set_tags') // solo se non è stata precedentemente definita
function set_tags(tag_text, flag){
	core.addDataTableParams('flag', flag);
	core.addDataTableParams('search_tag', tag_text);
	core.dataTable.fnDraw();
}

/**
 *
 * @param td
 * @param status
 */
function payment_note(td, status){
	var context = td.find("a");
	var id_attr = context.attr("id");
	var pos_to_start = id_attr.lastIndexOf("-")+1;
	var object_id = id_attr.substr(pos_to_start);
	var source = context.attr("href") + "?echo=1&status="+status;
	var new_source = context.attr("href");
	$.get( source, function( url ) {
        $( context ).attr( "href", source + '?url=' + url );
    }).then(
		function(url) { // success
			// nascondo l'icona dello spinner e mostro quella del download
			if(url){ // ho l'url?
				$(context).attr("href", new_source + '?url=' + url + '&status=' + status); // imposto la nuova url
				$("#payment_note-icon-spinner-"+object_id).hide();
				$("#payment_note-icon-download-"+object_id).show();
			}else{ // non ho un valore?
				$(context).attr("href", new_source + '?status=' + status); // imposto la nuova url
				$("#payment_note-"+object_id).hide();
				$("#payment_note-not-avail-text-"+object_id).show();
			}
			return true;
		},
		function() { // error
			// mostro un'incona d'errore
			$("#payment_note-icon-spinner-"+object_id).attr("class", "icon-exclamation-sign");
			return false;
		}
	);
}

/**
 *
 * @param td
 * @param status
 */
function gateway_invoice(td, status){
	var context = td.find("a");
	var id_attr = context.attr("id");
	var pos_to_start = id_attr.lastIndexOf("-")+1;
	var object_id = id_attr.substr(pos_to_start);
	var source = context.attr("href") + "?echo=1&status="+status;
	var new_source = context.attr("href");
	$.get( source, function( url ) {
		$( context ).attr( "href", source + '?url=' + url );
	}).then(
		function(url) { // success
			// nascondo l'icona dello spinner e mostro quella del download
			if(url){ // ho l'url?
				$(context).attr("href", new_source + '?url=' + url + '&status=' + status); // imposto la nuova url
				$("#gateway_commission_invoice-icon-spinner-"+object_id).hide();
				$("#gateway_commission_invoice-icon-download-"+object_id).show();
			}else{ // non ho un valore?
				$(context).attr("href", new_source + '?status=' + status); // imposto la nuova url
				$("#gateway_commission_invoice-"+object_id).hide();
				$("#gateway_commission_invoice-not-avail-text-"+object_id).show();
			}
			return true;
		},
		function() { // error
			// mostro un'incona d'errore
			$("#gateway_commission_invoice-icon-spinner-"+object_id).attr("class", "icon-exclamation-sign");
			return false;
		}
	);
}

/**
 *
 * @param td
 * @param status
 * @return {boolean}
 */
function seller_invoice(td, status){
	var context = td.find("a");
	var id_attr = context.attr("id");
	if(!id_attr) return false;
	var pos_to_start = id_attr.lastIndexOf("-")+1;
	var object_id = id_attr.substr(pos_to_start);
	href = context.attr("href");
	uri_stop_pos = href.indexOf("#");
	uri = href.substr(0, uri_stop_pos);
	modal_id = href.substr(uri_stop_pos);
	var source = uri + "?echo=1&status="+status;
	var new_source = uri;
	$.get( source, function( url ) {
		$( context ).attr( "href", source + '?url=' + url );
	}).then(
		function(show_upload) { // success
			// nascondo l'icona dello spinner e mostro quella dell'upload
			if(show_upload == '1'){ // posso mostrare l'upload?
				$(context).attr("href", modal_id); // imposto la nuova url
				$("#seller_upload_invoice-icon-spinner-"+object_id).hide();
				$("#seller_upload_invoice-icon-upload-"+object_id).show();
			}else{ // non ho un valore?
				$(context).attr("href", modal_id); // imposto la nuova url
				$("#seller_upload_invoice-"+object_id).hide();
				$("#seller_upload_invoice-not-avail-text-"+object_id).show();
			}
			return true;
		},
		function() { // error
			// mostro un'incona d'errore
			$("#seller_upload_invoice-icon-upload-"+object_id).attr("class", "icon-exclamation-sign");
			return false;
		}
	);
}

/**
 *
 * @param key
 * @param value
 */
function registration_filter(key, value){
	var controls1 = $('#controls1');
	var controls2 = $('#controls2');
	var controls3 = $('#controls3');
	var list_length = $('[name=domain-manage-list_length]').val();
	$('#backup').append( controls1 );
	$('#backup').append( controls2 );
	$('#backup').append( controls3 );
	registrationTable = initTable('registration_manager');
	core.addDataTableParams(key, value);
	core.dataTable.fnDraw(); // ridisegno la datatable con i nuovi id selezionati
}

/**
 *
 * @param use_prev_value
 */
function clean_incrase_bid(use_prev_value){
	use_prev_value = use_prev_value ? use_prev_value : false;
	if($('#offer-max').length > 0){
		$('#offer-max').removeClass("parsley-error");
		$('#offer-max').removeClass("parsley-success");
		$('.parsley-errors').html('');
		//isDevMode() && console.log('devo usare il valore del bid precedente: ', use_prev_value);
		if(use_prev_value){
//			isDevMode() && console.log("pulisco e provo il valore");
			prev_val = $('#offer-max').val();
			//isDevMode() && console.log('valore bid precedente: ', prev_val);
			if(prev_val){
				$('#offer-max').val(99999999);
				$('#offer-submit-form').parsley('validate');
				$('#offer-max').val(prev_val);
				$('#offer-submit-form').parsley('validate');
			}
		}else{
//			isDevMode() && console.log("pulisco e resetto il valore di offerta");
			$('#offer-max').trigger("reset");
			$('#offer-max').val('');
		}
	}
}

/**
 * @param xhr
 * @param textStatus
 * @param error
 */
function handleAjaxError( xhr, textStatus, error ) {
	//isDevMode() && console.error(error);
	$("#datatable_message").show();
	unloadlayer();
	result = core.initUserSessionData();
	result.done(function(response, status, xhr){
		//isDevMode() && console.log('is user logged: ', core.isUserLogged());
		if(core.isUserLogged() == false){
			core.redirect(core.getLoginUrl());
		}
	});
}

/**
 * 
 * @param {string} url
 * @param {object} params
 * @returns {XMLHttpRequest|start_download.xhr}
 */
function start_download(url, params){
	var xhr = new XMLHttpRequest();
	xhr.open('POST', url, true);
	xhr.responseType = 'arraybuffer';
	xhr.onload = function () {
		if (this.status === 200) {
			var filename = "";
			var disposition = xhr.getResponseHeader('Content-Disposition');
			if (disposition && disposition.indexOf('attachment') !== -1) {
				var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
				var matches = filenameRegex.exec(disposition);
				if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
			}
			var type = xhr.getResponseHeader('Content-Type');

			var blob = new Blob([this.response], { type: type });
			if (typeof window.navigator.msSaveBlob !== 'undefined') {
				// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
				window.navigator.msSaveBlob(blob, filename);
			} else {
				var URL = window.URL || window.webkitURL;
				var downloadUrl = URL.createObjectURL(blob);

				if (filename) {
					// use HTML5 a[download] attribute to specify filename
					var a = document.createElement("a");
					// safari doesn't support this yet
					if (typeof a.download === 'undefined') {
						window.location = downloadUrl;
					} else {
						a.href = downloadUrl;
						a.download = filename;
						document.body.appendChild(a);
						a.click();
					}
				} else {
					window.location = downloadUrl;
				}

				setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
			}
		}
	};
	xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	xhr.send($.param(params));
	return xhr;
}

/**
 * 
 * @param {jqXHR} jqXHR_validation_response
 * @param {string} modal_id
 * @returns {boolean}
 */
function validate_modal_parsley(jqXHR_validation_response, modal_id){
	// parslay validate before sending form
	var valid_request = jqXHR_validation_response.status == 200;
	isDevMode() && console.info('jqXHR status: ', jqXHR_validation_response.status);
	if(!valid_request){
		console.error('jqXHR: ', jqXHR_validation_response);
	}
	var json_string = jqXHR_validation_response.responseText;
	isDevMode() && console.info('json string: ', json_string);
	if(typeof json_string == 'undefined'){
		console.error('jqXHR: ', jqXHR_validation_response);
		return false;
	}
	var errors = JSON.parse(json_string);
	var array_error_names = Object.keys(errors);
	var valid = array_error_names.length == 0;
	isDevMode() && console.info("is form valid: ", valid);
	if(false == valid) isDevMode() && console.log('array errors', array_error_names);
	var modal = $('#'+modal_id);
	modal.find('.parsley-validated').each(function(){
		var current_field = $(this).attr("name");
		isDevMode() && console.log('curr field name: ', current_field);
		if(
			$.inArray(current_field, array_error_names) !== -1 ||
			$(this).parsley('validate') === false
		){ // show the error message
			var error_msg = errors[current_field];
			if(error_msg){
				isDevMode() && console.warn(current_field, error_msg);
				var span_error = $("#"+current_field).parent().parent().find("span.error-msg");
				$("#"+current_field).addClass("parsley-error");
				span_error.html(error_msg);
			}
		}else{ // correct input: removing error classes and messages
			$("#"+current_field).removeClass("parsley-error");
			span_error = $("#"+current_field).parent().parent().find("span.error-msg");
			span_error.html('');
		}
	});
	
	if(valid){ // rimuovo tutti i messaggi d'errore?
		modal.find("span.error-msg").html('');
	}

	return valid;
}

/**
 * @return string
 * @param text
 */
function escapeHtml(text) {
  if(typeof text == 'undefined'){
	text = '';
  }
  var map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

/**
 *
 * @param jsonString
 * @returns string|boolean
 */
function tryParseJSON(jsonString){
	try {
		var o = JSON.parse(jsonString);

		// Handle non-exception-throwing cases:
		// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
		// but... JSON.parse(null) returns null, and typeof null === "object",
		// so we must check for that, too. Thankfully, null is falsey, so this suffices:
		if (o && typeof o === "object") {
			return o;
		}
	}
	catch (e) { }

	return false;
}

/**
 *
 * @returns {boolean | * | jQuery}
 */
function isDevMode(){
	return is_dev_mode === '1';
}

/**
 *
 * @param source_datatype
 * @param source_datatable
 * @param type
 * @param form_id
 * @param button_localized
 * @param params
 * @param timeout
 */
function render_datatable(source_datatype, source_datatable, type, form_id, button_localized, params = [], timeout=10000){
	let default_sort = [
		{ "bSortable": false }, //domain_id
		{ "sType": "natural" }, //domain_name
		{ "sType": "natural" }, //created_at
		{ "sType": "natural" }, //bookable_until
		{ "bSortable": false }  //actions
	];
	let domainers_sort = [
		{ "bSortable": false }, //domain_id
		{ "sType": "natural" }, //domain_name
		{ "sType": "natural" }, //creation year
		{ "sType": "natural" }, //extension
		{ "sType": "natural" }, //character length
		{ "sType": "natural" }, //partner selected
		{ "sType": "natural" }, //booking-until date
		{ "bSortable": false }  //actions
	];
	let seo_sort = [
		{ "bSortable": false }, //domain_id
		{ "sType": "natural" }, //domain_name
		{ "sType": "natural" }, //media ricerche mensili
		{ "sType": "natural" }, //concorrenza
		{ "sType": "natural" }, //offerte di gamma alta
		{ "bSortable": false }  //actions
	];
	let defaultdoms_sort = [
		{ "bSortable": false }, //domain_id
		{ "sType": "natural" }, //domain_name
		{ "sType": "natural" }, //creation year
		{ "sType": "natural" }, //extension
		{ "sType": "natural" }, //character length
		{ "sType": "natural" }, //partner selected
		{ "sType": "natural" }, //booking-until date
		{ "bSortable": false }  //actions
	];
	let recommended_sort = [
		{ "bSortable": false }, //domain_id
		{ "sType": "natural" }, //domain_name
		{ "sType": "natural" }, //year
		{ "sType": "natural" }, //Extensions
		{ "sType": "natural" }, //length
		{ "bSortable": false }  //actions
	];
	let aoColumns;
	let bLengthChange = true;
	let aaSorting = [[ 1, "asc" ]];
	if(type === 'Seo') aoColumns = seo_sort;
	else if(type === 'Domainers') aoColumns = domainers_sort;
	else if(type === 'Defaultdoms') aoColumns = defaultdoms_sort;
	else if(type === 'Recommended'){
		aoColumns = recommended_sort;
		limit_table_rows=100;
		aaSorting = [];
		bLengthChange = false;
	}
	else aoColumns = default_sort;
	let currentSource = source_datatable.replace(/(act=)([\w]+)/,'$1'+'list_'+type);
	$.get( source_datatype.replace(/(type=)([\w]+)/,'$1'+type), function( html ) {}).then(
		function(content) { // success
			$("#"+form_id).html(content);
			let table_class = '.bookableTable'+type;
			if( $(table_class).length ){
				dt = $(table_class).dataTable( {
					"bProcessing": true,
					"bServerSide": true,
					"sAjaxSource": currentSource,
					"sPaginationType": "bootstrap",
					"oLanguage": { "sUrl": web_root + "media/js/fe/dataTables." + web_lang + ".txt"	},
					"sDom": '<"dt-topbar"lf>rt<"dt-bottombar"<"#domactions">ip>',
					"iDisplayLength": limit_table_rows, // seleziono il numero di elementi da visualizzare
					"aaSorting": aaSorting,
					"aoColumns": aoColumns,
					"bLengthChange": bLengthChange,
					"fnPreDrawCallback": function() {
						loadlayer(); // gestisco il loader del layer
						return true;
					},
					"fnDrawCallback": function(oSettings, json) {
						unloadlayer();
						datatable_checkboxes(table_class);
					},
					"fnInitComplete": function(oSettings, json) {
						$('#domactions').html('<i class="icon-hand-up"></i><button type="submit" class="btn btn-primary"><i class="icon-pushpin"></i> '+button_localized+'</button>');
						$('.ttip').tooltip();
						$(".collapse:visible").collapse('show'); /* by default apro il widget visible con i filtri */
						//NOTA:...il delay parte cmq a prescindere dal carattere!!!
						this.fnSetFilteringEnterPress(); //prima limito i caratteri
						this.fnSetFilteringDelay(1000); //poi imposto il delay
					},
					"fnServerData": function ( sSource, aoData, fnCallback ) {
						$.ajax( {
							"dataType": 'json',
							"type": "POST",
							"url": sSource,
							"data": aoData,
							"success": fnCallback,
							"error": handleAjaxError, // this sets up jQuery to give me errors
							"timeout": timeout, //milliseconds
						});
					},
					"fnServerParams": function (aoData) {
						for (var key in params) {
							value = params[key];
							aoData.push({"name": key, "value": value});
						}
					},
				});
			}
		},
		function() { // error
			$("#widget_error_message").show();
		}
	);
}

/**
 * codice richiamato ad ogni aggiornamento di datatable x prima cosa popolare i check se cliccati precedentemente
 * N.B. it works only with previously global ids = new core.HashTable(); inizialized
 * @param table_class
 */
function datatable_checkboxes(table_class){
	checkme(table_class);
	// gestione click singolo sui checkbox
	$(".checkboxesX").click(function(){
		if(this.checked){
			ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
		}
		else{
			ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
		}
		checkme(table_class);
	});
	// gestione click su check seleziona/deseleziona tutti
	$("#selectall").click(function () {
		let valore = this.checked;
		$('.checkboxesX').each( function() {
			this.checked = valore;
			if (valore)
				ids.hasItem(this.value) ? '' : ids.setItem(this.value, true);
			else
				ids.hasItem(this.value) ? ids.removeItem(this.value) : '';
		});
	});
}

/**
 *
 * @param $form
 * @return {{}}
 */
function getFormData($form){
	let unindexed_array = $form.serializeArray();
	let indexed_array = {};
	$.map(unindexed_array, function(n, i){
		indexed_array[n['name']] = n['value'];
	});
	return indexed_array;
}