let MuestreoDinamicoController = {
	user: '',
	idCliente: '',
	dateFormat: '',
	numPregPerf: '',
	splitCharacter: '',
	typeColors: null,
	colorsHex: [],
	poll: '',
	idPoll: '',
	isPerf: null,
	idMission: '',
	stampMision: '',
	project: '',
	questionsFlag: false,
	questions: [],
	results: [],
	participantsNumber: [],
	data: [],
	answersData: [],
	answersChart: [],
	genderData: [],
	genderChart: [],
	ageData: [],
	ageChart: [],
	statesData: [],
	statesChart: [],
	NSEData: [],
	NSEChart: [],
	fullPageGraph: null,
	targetsSurvey: [],
	targetsSurveyArray: [],
	questionsSQArray: [],
	surveyValues: null,
	columnName: null,
	columnNameK: null,
	renderSurveyValuesFlag: false,
	columnNameArray: [],
	filterByProfiling: [],
	graphsToReport: [],
	defaultTemplate: null,
	isContinuing: '0',
	startDate: '',
	endDate: '',
	suffix: '',

	reset() {
		let self = this;

		self.user = '';
		self.idCliente = '';
		self.dateFormat = '';
		self.numPregPerf = '';
		self.splitCharacter = '';
		self.typeColors = null;
		self.colorsHex = [];
		self.answersOrder = 'default';
		self.poll = '';
		self.idPoll = '';
		self.isPerf = null;
		self.idMission = '';
		self.stampMision = '';
		self.project = '';
		self.questionsFlag = false;
		self.questions = [];
		self.results = [];
		self.participantsNumber = [];
		self.data = [];
		self.answersData = [];
		self.answersChart = [];
		self.genderData = [];
		self.genderChart = [];
		self.ageData = [];
		self.ageChart = [];
		self.statesData = [];
		self.statesChart = [];
		self.NSEData = [];
		self.NSEChart = [];
		self.fullPageGraph = null;
		self.targetsSurvey = [];
		self.targetsSurveyArray = [];
		self.questionsSQArray = [];
		self.surveyValues = null;
		self.columnName = null;
		self.columnNameK = null;
		self.renderSurveyValuesFlag = false;
		self.columnNameArray = [];
		self.filterByProfiling = [];
		self.graphsToReport = [];
		self.defaultTemplate = null;
		self.isContinuing = '0';
		self.startDate = '';
		self.endDate = '';
		self.suffix = '';
	},

	setEvents(suffix = '') {
		let self = this;
		self.reset();
		self.suffix = suffix;

		// Información de administrador
		let userAdmin = JSON.parse(sessionStorage['STCMBackEnd:user']);
		let email = userAdmin.email;
		let email_split = email.split('@');
		self.user = email_split[0].replace('.', '_');
		self.idCliente = userAdmin.idCliente;
		self.dateFormat = userAdmin.formatoFecha;

		// Valores de configuración
		let config = JSON.parse(atob(sessionStorage.getItem('STCMBackEnd:config')));
		self.numPregPerf = config.numPregPerfEnMostreo;
		self.splitCharacter = config.splitCharacter;

		// Plantilla por defecto
		if(self.suffix === '') {
			self.getPlantillaReportesByDefault();
		}

		// Reducción de Header
		headerSectionHeight(0);

		let jsonsubopt = {};
		let nav = '';
		if(self.suffix === '') {
			// Añadir titulo
			$('#page-title').text(pf.const.language.RSC2426);

			// Opciones de header
			jsonsubopt = {
				survey: 'poll',
				question: 'question',
				report: 'ddreport' + self.suffix,
				//showProfiles: 'showProfiles',
				startEndDate: {
					class: 'form-group m-0 ml-1',
					style: 'max-width: 145px; line-height: initial;'
				},
				startEndTime: {
					class: 'form-group m-0 ml-1',
					style: 'min-width: 105px; line-height: initial;'
				}
			};

			nav = `
				<div class="d-flex justify-content-end align-items-end row m-0">
					${createSubOptionSurvey(jsonsubopt.survey)}
					${createSubOptionQuestion(jsonsubopt.question)}
					${createSubOptionStartEndDateTime(jsonsubopt.startEndDate.class, jsonsubopt.startEndTime.class, jsonsubopt.startEndDate.style, jsonsubopt.startEndTime.style)}
					<div>
						<button id="dropdownFilters" type="button" class="btn-nav btn d-flex align-items-center ma-le-5 secondary-button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
							<span class="ml-1">${pf.const.language.RSC1076}</span>

							<span id="svgContainerPage" class="ml-2">
								<svg class="bi bi-chevron-down" width="12" height="12" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
									<path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 01.708 0L8 10.293l5.646-5.647a.5.5 0 01.708.708l-6 6a.5.5 0 01-.708 0l-6-6a.5.5 0 010-.708z" clip-rule="evenodd"/>
								</svg>
							</span>
						</button>

						<div id="profileContainerPage" class="dropdown-menu dropdown-menu-right shadow menu-actions" aria-labelledby="dropdownFilters">
							<div class="dropdown-item form-check form-check-inline">
								<input id="showProfiles" type="checkbox" class="form-check-input">
								<label for="showProfiles" class="form-check-label c-pointer">${pf.const.language.RSC2429}</label>
							</div>

							<div class="lastElement text-right">
								<span id="loadWithFilters" class="main-color-text c-pointer spanDisabled">${pf.const.language.RSC2523}</span>
							</div>
						</div>
					</div>
					${createSubOptionGetReport(jsonsubopt.report)}
				</div>
			`;
		} else if(self.suffix === '-me-sam-dyn') {
			// Opciones de header
			jsonsubopt = {
				survey: 'poll',
				question: 'question' + self.suffix,
				report: 'ddreport' + self.suffix,
				startEndDate: {
					class: 'form-group m-0 ml-1',
					style: 'max-width: 145px; line-height: initial;'
				},
				startEndTime: {
					class: 'form-group m-0 ml-1',
					style: 'min-width: 105px; line-height: initial;'
				}
			};

			nav = `
				<div class="d-flex justify-content-end align-items-end row m-0">
					${createSubOptionQuestion(jsonsubopt.question, self.suffix)}
					${createSubOptionStartEndDateTime(jsonsubopt.startEndDate.class, jsonsubopt.startEndTime.class, jsonsubopt.startEndDate.style, jsonsubopt.startEndTime.style, self.suffix)}
					<div>
						<button id="dropdownFilters" type="button" class="btn-nav btn d-flex align-items-center ma-le-5 secondary-button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
							<span class="ml-1">${pf.const.language.RSC1076}</span>

							<span id="svgContainerPage" class="ml-2">
								<svg class="bi bi-chevron-down" width="12" height="12" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
									<path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 01.708 0L8 10.293l5.646-5.647a.5.5 0 01.708.708l-6 6a.5.5 0 01-.708 0l-6-6a.5.5 0 010-.708z" clip-rule="evenodd"/>
								</svg>
							</span>
						</button>

						<div id="profileContainerPage" class="dropdown-menu dropdown-menu-right shadow menu-actions" aria-labelledby="dropdownFilters">
							<div class="dropdown-item form-check form-check-inline">
								<input id="showProfiles" type="checkbox" class="form-check-input">
								<label for="showProfiles" class="form-check-label c-pointer">${pf.const.language.RSC2429}</label>
							</div>

							<div class="lastElement text-right">
								<span id="loadWithFilters" class="main-color-text c-pointer spanDisabled">${pf.const.language.RSC2523}</span>
							</div>
						</div>
					</div>
					${createSubOptionGetReport(jsonsubopt.report)}
				</div>
			`;
		}

		// Acciones de página (flex-row-reverse)s
		$('#page-actions' + self.suffix).html(nav);

		// Botón principal
		$('#ddreport' + self.suffix).addClass('main-button');

		// Eventos de dropdown de página
		dropDownPageEvents();

		// Secciones ocultas al cargar
		$('#startTime' + self.suffix).parent().hide();
		$('#endTime' + self.suffix).parent().hide();
		$('#poll').parent().removeClass('col-2');
		$('#poll').parent().removeClass('col-sm-3');
		$('#question' + self.suffix).parent().removeClass('col-2');
		$('#question' + self.suffix).parent().removeClass('col-sm-3');
		$('#startDate' + self.suffix).parent().hide();
		$('#endDate' + self.suffix).parent().hide();

		// Inputs de fecha y hora
		let now = new Date();
		let nYear = now.getFullYear();
		let nMonth = now.getMonth() + 1;
		if(nMonth < 10) {
			nMonth = '0' + nMonth;
		}
		let nDay = now.getDate();
		if(nDay < 10) {
			nDay = '0' + nDay;
		}
		let today = nYear + '-' + nMonth + '-' + nDay;
		self.startDate = today;
		self.endDate = today;

		$('#startDate' + self.suffix).val(self.startDate);
		$('#endDate' + self.suffix).val(self.endDate);

		$('#poll').attr('placeholder', pf.const.language.RSC177);

		self.loadLang();
		self.applyEvents();
	},

	loadLang() {
		pf.rsc.translateByTag('text');

		// TITLES
		$('.acceptTitle').attr('title', pf.const.language.RSC141);
	},

	applyEvents() {
		let self = this;

		// En caso de venir de edición de misiones
		if(self.suffix === '-me-sam-dyn') {
			// Desactivar el botón de carga de pregunta
			$('#loadSurvey').prop('disabled', true);
			// Desactivar botón en filtros
			$('#loadWithFilters').addClass('spanDisabled');
			// Activar el botón de modal de preguntas
			$('#searchQuestion' + self.suffix).prop('disabled', false);
		}

		// Misiones
		$('#searchPoll').on('click', function() {
			if(self.poll === '') {
				// Parámetro de cliente
				let parameters = {
					idCliente: self.idCliente
				}
				ajaxComunCallWithCallback('getAllSurveysWithMissions', parameters, function(ajaxReturn) {
					if(ajaxReturn) {
						self.poll = ajaxReturn.result;

						self.renderPoll();
					}
				});
			} else {
				$('#pollTable').modal('show', true);
			}
		});

		// Preguntas
		$('#searchQuestion' + self.suffix).on('click', function() {
			if(self.questions.length === 0) {
				let parameters = {
					survey: self.idPoll
				};
				ajaxComunCallWithCallback('getQuestionsSurvey', parameters, function(ajaxReturn) {
					if(ajaxReturn) {
						// Array de tipos de preguntas aceptadas
						let types = ['!', '3', '4', '5', 'A', 'B', 'F', 'L', 'M', 'O', 'P', 'R', 'Y'];

						let size = ajaxReturn.result.length;
						for(let i = 0; i < size; i++) {
							if(types.includes(ajaxReturn.result[i].type)) {
								// Limpieza de marcas de html
								let textWithTags = ajaxReturn.result[i].question;
								let textWithoutTags = textWithTags.replace(/<[^>]*>?/g, '');

								let questionsSQ = {};
								if(ajaxReturn.result[i].type == 'A' || ajaxReturn.result[i].type == 'B' || ajaxReturn.result[i].type == 'F') {
									let sizeK = ajaxReturn.result[i].valuesSQ.length;
									for(let j = 0; j < sizeK; j++) {
										let valuesSQArray = ajaxReturn.result[i].valuesSQ[j].split('|');

										questionsSQ[valuesSQArray[0]] = {
											name: valuesSQArray[1],
											data: []
										};
									}
								}

								let obj = {
									type: ajaxReturn.result[i].type,
									columnName: ajaxReturn.result[i].columnName,
									title: ajaxReturn.result[i].title,
									group_name: ajaxReturn.result[i].group_name,
									question: textWithoutTags.trim(),
									checked: false,
									questionsSQ: questionsSQ
								}
								self.questions.push(obj);
							}
						}

						self.renderQuests();
					}
				});
			} else {
				$('#questTable' + self.suffix).modal('show', true);
			}
		});

		// Cargar datos de página a través de los filtros
		$('#loadWithFilters').on('click', function() {
			// En caso de que esté desactivado
			if($('#loadWithFilters').hasClass('spanDisabled')) {
				return false;
			}

			$('#accept' + self.suffix).trigger('click');
		});

		// Gráficas
		$('#accept' + self.suffix).on('click', function() {
			let selectedQuestions = false;
			let size = self.questions.length;
			for(let i = 0; i < size; i++) {
				if(self.questions[i].checked) {
					selectedQuestions = true;
					break;
				}
			}

			if(selectedQuestions) {
				$('#closeQuest' + self.suffix).trigger('click');

				// Datos para filtrado de pregunta
				let parameters = {
					survey: self.idPoll
				};
				ajaxComunCallWithCallback('getTargetsSurvey', parameters, function(ajaxReturn) {
					if(ajaxReturn) {
						// Array de tipos de preguntas aceptadas
						let types = ['!', '3', '4', '5', 'A', 'B', 'F', 'L', 'M', 'O', 'P', 'R', 'Y'];
						self.targetsSurvey = [];
						self.targetsSurveyArray = [];
						let size = ajaxReturn.result.length;
						for(let j = 0; j < size; j++) {
							if(!types.includes(ajaxReturn.result[j].type)) {
								continue;
							} else if(ajaxReturn.result[j].type == 'A' || ajaxReturn.result[j].type == 'B' || ajaxReturn.result[j].type == 'F') {
								ajaxReturn.result[j].value = {};
								ajaxReturn.result[j].code = {};
								let sizeK = ajaxReturn.result[j].valuesSQ.length;
								for(let f = 0; f < sizeK; f++) {
									let columnNameKArray = ajaxReturn.result[j].valuesSQ[f].split('|');
									let columnNameK = columnNameKArray[0];
									ajaxReturn.result[j].value[columnNameK] = [];
									ajaxReturn.result[j].code[columnNameK] = [];
								}
							} else {
								ajaxReturn.result[j].value = [];
								ajaxReturn.result[j].code = [];
							}

							self.targetsSurvey.push(ajaxReturn.result[j]);
						}

						self.requestGraphs();

						// Activar botón en filtros
						$('#loadWithFilters').removeClass('spanDisabled');
					}
				});
			} else {
				let alertTitle = pf.const.language.RSC2426;
				let alertContent = pf.const.language.RSC2430;
				pf.utils.showInfoDialog(alertTitle, alertContent);
			}
		});

		// Reporte
		$('#ddreport' + self.suffix).on('click', function() {
			// Parámetros de reporte
			let parameters = {
				mission: self.idMission,
				reportData: self.graphsToReport,
				defaultTemplate: self.defaultTemplate
			};

			let reportGenerator = new ReportGeneratorController('dinamic', parameters);
			reportGenerator.generateDinamicReport();
		});

		// Fecha de inicio
		$('#startDate' + self.suffix).on('change', function() {
			self.startDate = $('#startDate' + self.suffix).val();
			if(self.startDate > self.endDate) {
				$('#startDate' + self.suffix).val(self.endDate);
				self.startDate = $('#startDate' + self.suffix).val();
			}
		});

		// Fecha de fin
		$('#endDate' + self.suffix).on('change', function() {
			self.endDate = $('#endDate' + self.suffix).val();
			if(self.endDate < self.startDate) {
				$('#endDate' + self.suffix).val(self.startDate);
				self.endDate = $('#endDate' + self.suffix).val();
			}
		});
	},

	getPlantillaReportesByDefault() {
		let self = this;

		ajaxComunCallWithCallback('getPlantillaReportesByDefault', {}, function(ajaxReturn) {
			if(ajaxReturn) {
				let values = ajaxReturn.result[0];
				self.defaultTemplate = values;

				self.typeColors = values.rangoColores;

				if(self.typeColors == '1') {
					self.colorsHex[0] = values.colorInicio;
					self.colorsHex[1] = values.colorFinal;
				} else {
					self.colorsHex = values.coloresComponenRango;
				}

				self.answersOrder = values.answersOrder;
			}
		});
	},

	renderPoll() {
		let self = this;

		let table = `
			<thead>
				<tr>
					<th scope="col" title="${pf.const.language.RSC177}">${pf.const.language.RSC177}</th>
					<th scope="col" title="${pf.const.language.RSC176}">${pf.const.language.RSC176}</th>
					<th scope="col" title="${pf.const.language.RSC114}">${pf.const.language.RSC114}</th>
					<th scope="col" title="${pf.const.language.RSC116}">${pf.const.language.RSC116}</th>
					<th scope="col" title="${pf.const.language.RSC117}">${pf.const.language.RSC117}</th>
					<th scope="col" title="${pf.const.language.RSC549}">${pf.const.language.RSC549}</th>
				</tr>
			</thead>

			<thead class="filtersPoll">
				<tr>
					<td>mision</td>
					<td>proyecto</td>
					<td>active</td>
					<td>startdate</td>
					<td>expires</td>
					<td>country</td>
				</tr>
			</thead>

			<tbody>
		`;

		// Obtener países permitidos
		let allowedCountries = JSON.parse(atob(sessionStorage['STCMBackEnd:userCountries']));

		let size = self.poll.length;
		for(let i = 0; i < size; i++) {
			// Control de países permitidos
			if(self.poll[i].countries != '' && allowedCountries.indexOf(self.poll[i].countries) == -1) {
				continue;
			}

			if(self.poll[i].idmision == '') {
				continue;
			}

			// Formato de fecha, el servicio devuelve AAAA-MM-DD HH:MM:SS
			let startDate = '-';
			let startDateOrder = '';
			if(self.poll[i].startdate != '') {
				// Para ordenación en columna
				startDateOrder = self.poll[i].startdate.replace(' ', '');

				let dateTimeArrayStart = self.poll[i].startdate.split(' ');
				let dateStart = dateTimeArrayStart[0].replace(/-/g, '/');
				if(self.dateFormat === 'DDMMAAAA') {
					startDate = modifyDateFormat(dateStart);
				} else {
					startDate = dateStart;
				}
			}

			let endDate = '-';
			let endDateOrder = '';
			if(self.poll[i].expires != '') {
				// Para ordenación en columna
				endDateOrder = self.poll[i].expires.replace(' ', '');

				let dateTimeArrayEnd = self.poll[i].expires.split(' ');
				let dateEnd = dateTimeArrayEnd[0].replace(/-/g, '/');
				if(self.dateFormat === 'DDMMAAAA') {
					endDate = modifyDateFormat(dateEnd);
				} else {
					endDate = dateEnd;
				}
			}

			table += `
				<tr id="sid${self.poll[i].sid}" class="c-pointer" data-perf="${self.poll[i].perfilacion}" data-mission="${self.poll[i].idmision}" data-stamp="${self.poll[i].stampMision}" data-project="${self.poll[i].idProject}" data-surveyname="${self.poll[i].surveyls_title}" data-continuing="${self.poll[i].continuingMission}">
					<td class="text-truncate" title="${self.poll[i].idmision}">${self.poll[i].idmision}</td>
					<td class="text-truncate" title="${self.poll[i].NombreProyecto}">${self.poll[i].NombreProyecto}</td>
					<td class="text-center">
						<span class="d-none">${(self.poll[i].active == '1' ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" disabled ${(self.poll[i].active == '1' ? 'checked' : '')}>
					</td>
					<td class="text-truncate" title="${startDate}">
						<span class="d-none">${startDateOrder}</span>
						${startDate}
					</td>
					<td class="text-truncate" title="${endDate}">
						<span class="d-none">${endDateOrder}</span>
						${endDate}
					</td>
					<td class="country text-truncate" title="${self.poll[i].countries}">${self.poll[i].countries}</td>
				</tr>
			`;
		}

		table += `
			</tbody>
		`;

		$('#tablePoll').html(table);

		// Setup - add a text input to each footer cell
		$('#tablePoll .filtersPoll td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title == 'active') {
				value = optionsSelectAllYesNo();
			}

			$(this).html(value);
		});

		let tablePoll = $('#tablePoll').DataTable({
			language: pf.const.language_table,
			scrollY: 300,
			scroller: false,
			paging: true,
			pageLength: 25,
			columnDefs: [
				{width: '60px', targets: 2}
			],
			autoWidth: false,
			aaSorting: []
		});

		// Ajuste de columnas
		setTimeout(function() {
			tablePoll.columns.adjust();
		}, 200);

		// Ocultar botones de tabla
		hideTableButtons('tablePoll');

		// Apply the search
		applyTheSearch(tablePoll, 'filtersPoll');

		$('#tablePoll tbody').off().on('click', 'tr', function() {
			// Desactivar el botón de carga de pregunta
			$('#loadSurvey').prop('disabled', true);
			// Desactivar botón en filtros
			$('#loadWithFilters').addClass('spanDisabled');
			// Activar el botón de modal de preguntas
			$('#searchQuestion').prop('disabled', false);

			//Limpieza de preguntas
			self.questions = [];

			// Limpieza del contenedor de resultados
			$('#resultsContainer').html('');

			// Misión continua
			if($(this).data('continuing') == '1') {
				self.isContinuing = '1';
				$('#startDate' + self.suffix).parent().show();
				$('#endDate' + self.suffix).parent().show();
			} else {
				self.isContinuing = '0';
				$('#startDate' + self.suffix).parent().hide();
				$('#endDate' + self.suffix).parent().hide();
			}

			// Datos de misión
			self.idPoll = $(this).attr('id').replace('sid', '');
			self.isPerf = $(this).data('perf');
			self.idMission = $(this).data('mission');
			self.stampMision = $(this).data('stamp');
			self.project = $(this).data('project');

			$('#poll').val(self.idMission);
			$('#poll').attr('title', self.idMission);
			$('#tablePoll tbody tr').css('outline-width', 'initial');
			$('#tablePoll tbody tr').css('outline-style', 'none');
			$('#tablePoll tbody tr').css('outline-color', '#000');
			$('#tablePoll tbody tr').css('font-weight', 'normal');
			$(this).css('outline-width', 'thin');
			$(this).css('outline-style', 'solid');
			$(this).css('outline-color', '#f00');
			$(this).css('font-weight', 'bold');
			$('#closePool').trigger('click');
		});
	},

	renderQuests() {
		let self = this;

		if(self.questionsFlag) {
			$('#tableQuest' + self.suffix).dataTable().fnDestroy();
		} else {
			self.questionsFlag = true;
		}

		let table = `
			<thead>
				<tr>
					<th scope="col" title="${pf.const.language.RSC1316}">${pf.const.language.RSC1316}</th>
					<th scope="col" title="${pf.const.language.RSC366}">${pf.const.language.RSC366}</th>
					<th scope="col" title="${pf.const.language.RSC122}">${pf.const.language.RSC122}</th>
					<th scope="col" title="${pf.const.language.RSC111}">${pf.const.language.RSC111}</th>
				</tr>
			</thead>

			<thead class="filtersQuest">
				<tr>
					<td>seleccion</td>
					<td>columnName</td>
					<td>section</td>
					<td>question</td>
				</tr>
			</thead>

			<tbody>
		`;

		let size = self.questions.length;
		for(let i = 0; i < size; i++) {
			table += `
				<tr class="c-pointer" data-index="${i}">
					<td class="text-center">
						<input type="checkbox" class="selection" data-index="${i}" ${(self.questions[i].checked ? 'checked' : '')}>
					</td>
					<td title="${self.questions[i].columnName}">${self.questions[i].columnName}</td>
					<td title="${self.questions[i].group_name}">${self.questions[i].group_name}</td>
					<td title="${self.questions[i].question}">${self.questions[i].question}</td>
				</tr>
			`;
		}

		table += `
			</tbody>
		`;

		$('#tableQuest' + self.suffix).html(table);

		// Setup - add a text input to each footer cell
		$('#tableQuest' + self.suffix + ' .filtersQuest td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title == 'seleccion') {
				value = `<input type="text" class="form-control form-control-sm" disabled>`;
			}

			$(this).html(value);
		});

		let tableQuest = $('#tableQuest' + self.suffix).DataTable({
			language: pf.const.language_table,
			scrollY: 300,
			scroller: false,
			paging: true,
			pageLength: 25,
			columnDefs: [
				{width: '30px', orderable: false, targets: 0},
				{width: '45px', targets: 1}
			],
			autoWidth: false,
			aaSorting: []
		});

		// Ajuste de columnas
		setTimeout(function() {
			tableQuest.columns.adjust();
		}, 200);

		// Ocultar botones de tabla
		hideTableButtons('tableQuest' + self.suffix);

		// Apply the search
		applyTheSearch(tableQuest, 'filtersQuest');

		// Seleccionar por tr
		$('#tableQuest' + self.suffix + ' tbody tr').off().on('click', function() {
			let index = $(this).data('index');
			let checked = $(this).find('.selection').prop('checked');

			if(!checked) {
				$(this).find('.selection').prop('checked', true);
				self.questions[index].checked = true;
			} else {
				$(this).find('.selection').prop('checked', false);
				self.questions[index].checked = false;
			}
		});

		// Seleccionar por checbox
		$('.selection').off().on('click', function() {
			let index = $(this).data('index');
			let checked = $(this).prop('checked');

			if(checked) {
				$(this).prop('checked', false);
				self.questions[index].checked = false;
			} else {
				$(this).prop('checked', true);
				self.questions[index].checked = true;
			}
		});
	},

	requestGraphs() {
		let self = this;

		self.columnNameArray = [];
		let titleArray = [];
		let questName = [];
		let typeArray = [];
		self.questionsSQArray = [];
		let size = self.questions.length;
		for(let i = 0; i < size; i++) {
			if(self.questions[i].checked) {
				self.columnNameArray.push(self.questions[i].columnName);
				titleArray.push(self.questions[i].title);
				questName.push(self.questions[i].question);
				typeArray.push(self.questions[i].type);
				self.questionsSQArray.push(self.questions[i].questionsSQ);
			}
		}

		let parameters = {
			survey: self.idPoll,
			questions: JSON.stringify(self.columnNameArray),
			param4: self.numPregPerf,
			titles: JSON.stringify(titleArray),
			isPerf: self.isPerf,
			types: JSON.stringify(typeArray),
			continuingMission: self.isContinuing,
			startDate: self.startDate,
			endDate: self.endDate
		};
		// getAnalyticsMuestra
		ajaxComunCallWithCallback('getAnalyticsMuestraDinamic', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				self.results = ajaxReturn.result;

				// Activar botón de reporte
				$('#ddreport' + self.suffix).prop('disabled', false);

				// Limpieza de parámetros de resultados
				self.participantsNumber = [];
				self.data = [];
				self.answersData = [];
				self.answersChart = [];
				self.genderData = [];
				self.genderChart = [];
				self.ageData = [];
				self.ageChart = [];
				self.statesData = [];
				self.statesChart = [];
				self.NSEData = [];
				self.NSEChart = [];
				self.filterByProfiling = [];
				self.graphsToReport = [];

				// Limpieza del contenedor de resultados
				$('#resultsContainer').html('');

				let size = self.results.length;
				for(let i = 0; i < size; i++) {
					// Nombre para gráfica de reporte
					let qObj = {
						name: questName[i],
						data: {}
					};
					self.graphsToReport.push(qObj);

					let resultContainer = `
						<div class="row p-2 glass-effect">
							<div class="col-12 p-0">
								<!-- Header -->
								<div class="d-flex justify-content-between p-0 c-pointer">
									<div class="d-flex align-items-center">
										<span class="section-title mx-3">${questName[i]}</span>
									</div>

									<button type="button" class="btn btn-link text-body text-decoration-none arrow" data-toggle="collapse" data-target="#containerCollapse${i}" data-arrow="down" data-sub="1">
										${stcmbackend.svg.chevronDown}
									</button>
								</div>

								<!-- Body -->
								<div id="containerCollapse${i}" class="m-0 p-2 collapse show">
									<div id="mGraphs${i}" class="mx-0">
										<!-- Gráfica de Respuestas -->
										<div id="respChart${i}" class="mb-3">
											<div class="card h-100 px-0">
												<div id="resp${i}" class="card-header d-flex justify-content-between">
													<p class="title-secondary">${pf.const.language.RSC499}</p>

													<!-- Selección de perfilación -->
													<select id="profiles${i}" class="form-control ml-2 profilesSelector wi-180" data-index="${i}">
														<option value="answers">${pf.const.language.RSC119}</option>
														<option value="gender">${pf.const.language.RSC151}</option>
														<option value="ageRange">${pf.const.language.RSC1917}</option>
														<option value="states">${pf.const.language.RSC153}</option>
														<option value="nse">${pf.const.language.RSC598}</option>
													</select>
												</div>

												<div class="card-body">	
													<div id="graphAnswersContainer${i}" class="graphics c-pointer" data-index="${i}" data-type="graphAnswers">
														<canvas id="graphAnswers${i}" class="he-350 bg-white"></canvas>
													</div>
													<div id="graphAnswersProfileContainer${i}" class="graphicsProfile c-pointer d-none" data-index="${i}">
														<canvas id="graphAnswersProfile${i}" class="he-350 bg-white"></canvas>
													</div>
												</div>
											</div>
										</div>

										<!-- Gráfica de Género -->
										<div id="genderChart${i}" class="mb-3">
											<div class="card h-100 px-0">
												<div class="card-header">
													<span class="title-secondary">${pf.const.language.RSC147}</span> (%)
												</div>

												<div class="card-body graphics c-pointer" data-index="${i}" data-type="graphGender">
													<canvas id="graphGender${i}" class="he-350 bg-white"></canvas>
												</div>
											</div>
										</div>

										<!-- Gráfica de Edades -->
										<div id="ageChart${i}" class="mb-3">
											<div class="card h-100 px-0">
												<div class="card-header">
													<span class="title-secondary">${pf.const.language.RSC148}</span> (%)
												</div>

												<div class="card-body graphics c-pointer" data-index="${i}" data-type="graphAge">
													<canvas id="graphAge${i}" class="he-350 bg-white"></canvas>
												</div>
											</div>
										</div>

										<!-- Gráfica de Estados -->
										<div id="statesChart${i}" class="mb-3">
											<div class="card h-100 px-0">
												<div class="card-header">
													<span class="title-secondary">${pf.const.language.RSC149}</span> (%)
												</div>

												<div class="card-body graphics c-pointer" data-index="${i}" data-type="graphStates">
													<canvas id="graphStates${i}" class="he-350 bg-white"></canvas>
												</div>
											</div>
										</div>

										<!-- Gráfica de NSE -->
										<div id="NSEChart${i}" class="mb-3">
											<div class="card h-100 px-0">
												<div class="card-header">
													<span class="title-secondary">${pf.const.language.RSC1000}</span> (%)
												</div>

												<div class="card-body graphics c-pointer" data-index="${i}" data-type="graphNSE">
													<canvas id="graphNSE${i}" class="he-350 bg-white"></canvas>
												</div>
											</div>
										</div>
									</div>

									<div id="filtersTable${i}" class="accordion mx-0">
										<div class="card p-0 m-0 mb-3">
											<div class="card-header d-flex justify-content-between">
												<div>
													<span class="title-secondary mr-3">${pf.const.language.RSC1076}</span>

													<button type="button" class="btn btn-outline-secondary filterQuestion" data-index="${i}">${pf.const.language.RSC1857}</button>
												</div>

												<button type="button" class="btn btn-link text-body text-decoration-none arrow" data-toggle="collapse" data-target="#filtersCollapse${i}" data-arrow="down" data-sub="3">
													${stcmbackend.svg.chevronDown}
												</button>
											</div>

											<div id="filtersCollapse${i}" class="card-body collapse show px-0">
												<div class="card-body">
													<div id="filtersContainer${i}" class="basicTable m-0 p-0"></div>
												</div>
											</div>
										</div>
									</div>

									<div id="resultTable${i}" class="accordion mx-0">
										<div class="card p-0 m-0">
											<div class="card-header d-flex justify-content-between">
												<div class="d-flex align-items-center">
													<span class="title-secondary mr-3">${pf.const.language.RSC155}</span>
												</div>

												<button type="button" class="btn btn-link text-body text-decoration-none arrow" data-toggle="collapse" data-target="#tableCollapse${i}" data-arrow="down" data-sub="1">
													${stcmbackend.svg.chevronDown}
												</button>
											</div>

											<div id="tableCollapse${i}" class="card-body collapse show pt-0 px-0">
												<div class="d-flex justify-content-end p-3">
													<!-- Botón descargar excel -->
													<button id="exportQuestion${i}" type="button" class="btn button-excel secondary-button ma-le-5" title="${pf.const.language.RSC47}">
														${stcmbackend.svg.download}
														<span>${pf.const.language.RSC47}</span>
													</button>
												</div>

												<div class="card-body pt-0">
													<div class="row p-0">
														<div class="col-6">
															<select id="groupBy${i}" class="form-control mb-2"></select>
														</div>

														<div class="col-6">
															<select id="nestBy${i}" class="form-control mb-2"></select>
														</div>
													</div>

													<div id="registersContainer${i}" class="basicTable m-0 p-0"></div>
												</div>
											</div>
										</div>
									</div>
								</div>
							</div>
						</div>
					`;

					$('#resultsContainer').append(resultContainer);

					if(self.results[i].type == 'A' || self.results[i].type == 'B' || self.results[i].type == 'F' || self.results[i].type == 'R') {
						$('#profiles' + i).hide();
					}

					// Filtro por perfilación
					let objProfiling = {
						gender: [],
						selectedGender: [],
						ageRange: [],
						selectedAgeRange: [],
						states: [],
						selectedStates: [],
						nse: [],
						selectedNse: [],
					}

					// Género
					for(let a = 0; a < self.results[i].gender.labels.length; a++) {
						let obj = {
							code: self.results[i].gender.labels[a],
							answer: self.results[i].gender.labels[a]
						};

						objProfiling.gender.push(obj);
					}

					// Rango de edad
					for(let a = 0; a < self.results[i].ageRange.labels.length; a++) {
						let obj = {
							code: self.results[i].ageRange.labels[a],
							answer: self.results[i].ageRange.labels[a]
						};

						objProfiling.ageRange.push(obj);
					}

					// Estados
					for(let a = 0; a < self.results[i].states.labels.length; a++) {
						let obj = {
							code: self.results[i].states.labels[a],
							answer: self.results[i].states.labels[a]
						};

						objProfiling.states.push(obj);
					}

					// NSE
					for(let a = 0; a < self.results[i].nse.labels.length; a++) {
						let obj = {
							code: self.results[i].nse.labels[a],
							answer: self.results[i].nse.labels[a]
						};

						objProfiling.nse.push(obj);
					}

					self.filterByProfiling.push(objProfiling);

					self.targetsSurveyArray.push(self.targetsSurvey);
					self.renderTargetsSurvey(i);

					// Número de participantes
					let participants = [];
					let pSize = 0;
					if(self.results[i].data != undefined) {
						pSize = self.results[i].data.length;
					}

					for(let j = 0; j < pSize; j++) {
						if(participants.indexOf(self.results[i].data[j].user) == -1) {
							participants.push(self.results[i].data[j].user);
						}
					}
					self.participantsNumber.push(participants.length);

					// Si no hay resultados en la encuesta/pregunta
					if(self.results[i].length == 0) {
						let errorTitle = pf.const.language.RSC35;
						let errorContent = pf.const.language.RSC529;
						pf.utils.showInfoDialog(errorTitle, errorContent);
						return;
					}

					// Datos para gráfica de respuestas
					let answers = self.results[i].answers;
					self.data.push(self.results[i].data);

					// Para gráficas Stacked
					let SQSize = Object.keys(self.questionsSQArray[i]).length;
					if(self.results[i].type == 'A' || self.results[i].type == 'B' || self.results[i].type == 'F') {
						let dSize = self.results[i].data.length;
						for(let p = 0; p < dSize; p++) {
							self.questionsSQArray[i][self.results[i].data[p].question].data.push(self.results[i].data[p]);
						}

						// Rango de colores
						let gradient = [];
						if(SQSize == 2) {
							gradient = self.colorsHex;
						} else {
							if(self.typeColors == 1) {
								gradient = generateColors(self.colorsHex[0], self.colorsHex[1], SQSize);
							} else {
								gradient = arrayColors(self.colorsHex, SQSize);
							}
						}

						let labelsData = [];
						let lSize = self.results[i].answers.labels.length;
						for(let j = 0; j < lSize; j++) {
							labelsData.push(0);
						}

						let datasetArray = [];
						let count = 0;
						for(let questionsSQ in self.questionsSQArray[i]) {
							let labelsDataSQ = [...labelsData];
							let dSizeSQ = self.questionsSQArray[i][questionsSQ].data.length;
							for(let n = 0; n < dSizeSQ; n++) {
								let index = self.results[i].answers.labels.indexOf(self.questionsSQArray[i][questionsSQ].data[n].answer);
								labelsDataSQ[index]++;
							}

							for(let m = 0; m < lSize; m++) {
								labelsDataSQ[m] = (labelsDataSQ[m] * 100 / self.participantsNumber[i]).toFixed(1);
							}

							let obj = {
								label: self.questionsSQArray[i][questionsSQ].name,
								data: labelsDataSQ,
								backgroundColor: gradient[count]
							};

							datasetArray.push(obj);
							count++;
						}

						self.results[i].answers.datasets = datasetArray;
						answers = self.results[i].answers;
					} else if(self.results[i].type == 'R') {
						let labels = self.results[i].answers.labels;
						
						let labelsObj = [];
						let labelsLabels = [];
						for(let l = 0; l < labels.length; l++) {
							let labelsOptions = [];
							for(let l in labels) {
								labelsOptions.push(0);
							}

							let obj = {
								labelName: labels[l],
								ranking: labelsOptions
							};
							labelsObj.push(obj);
							labelsLabels.push(l + 1);
						}

						let labelsObjIndex = 0;
						let rankingControl = self.participantsNumber[i];
						let dSize = self.data[i].length;
						for(let r = 0; r < dSize; r++) {
							if(r == rankingControl) {
								rankingControl += self.participantsNumber[i];
								labelsObjIndex++;
							}

							let index = labels.indexOf(self.data[i][r].answer);
							labelsObj[labelsObjIndex].ranking[index]++;
						}

						// Rango de colores
						let gradient = [];
						if(labels.length == 2) {
							gradient = self.colorsHex;
						} else {
							if(self.typeColors == 1) {
								gradient = generateColors(self.colorsHex[0], self.colorsHex[1], labels.length);
							} else {
								gradient = arrayColors(self.colorsHex, labels.length);
							}
						}

						let datasetArray = [];
						let count = 0;
						for(let label in labelsObj) {
							for(let m = 0; m < labels.length; m++) {
								labelsObj[label].ranking[m] = (labelsObj[label].ranking[m] * 100 / self.participantsNumber[i]).toFixed(1);
							}

							let obj = {
								label: labelsObj[label].labelName,
								data: labelsObj[label].ranking,
								backgroundColor: gradient[count]
							};

							datasetArray.push(obj);
							count++;
						}

						self.results[i].answers.datasets = datasetArray;
						answers = self.results[i].answers;
					}
					// Fin gráficas Stacked

					if(ajaxReturn.perf || !$('#showProfiles').prop('checked')) {
						// Visibilidad de gráficas
						$('#genderChart' + i).hide();
						$('#ageChart' + i).hide();
						$('#statesChart' + i).hide();
						$('#NSEChart' + i).hide();

						// Gráfica de respuestas
						self.createGraphs(answers, 0, i);
					} else {
						// Gráfica de respuestas
						self.createGraphs(answers, 0, i);

						// Gráfica de género
						let gender = self.results[i].gender;
						self.createGraphs(gender, 1, i);

						// Gráfica de edad
						let age = self.results[i].ageRange;
						self.createGraphs(age, 2, i);

						// Gráfica de estados
						let states = self.results[i].states;
						self.createGraphs(states, 3, i);

						// Gráfica de NSE
						let nse = self.results[i].nse;
						self.createGraphs(nse, 4, i);
					}

					if(ajaxReturn.perf) {
						self.renderData(true, i);
					} else {
						self.renderData(false, i);
					}
				}

				// Eventos de gráficas
				self.graphsEvents();

				// Collapse
				addEventArrowTableHeader();
			}
		});
	},

	renderTargetsSurvey(index) {
		let self = this;

		let table = `
			<table id="registersFilters${index}" class="table table-hover mt-0">
				<thead>
					<tr>
						<th scope="col" title="${pf.const.language.RSC122}">${pf.const.language.RSC122}</th>
						<th scope="col" title="${pf.const.language.RSC111}">${pf.const.language.RSC111}</th>
						<th scope="col" title="${pf.const.language.RSC349}">${pf.const.language.RSC349}</th>
					</tr>
				</thead>

				<thead class="filtersResult${index}">
					<tr>
						<td>section</td>
						<td>question</td>
						<td>value</td>
					</tr>
				</thead>

				<tbody>
					<tr id="gender_${index}" data-inputCode="">
						<td class="align-middle" title=""></td>
						<td class="align-middle" title="${pf.const.language.RSC151}">${pf.const.language.RSC151}</td>
						<td>
							<div class="input-group new-input-style">
								<input type="text" class="form-control-sm inputGrid inputGender" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
								<div class="input-group-append">
									<button type="button" class="btn btn-outline-secondary searchProfiling py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-index="${index}" data-profiling="gender">
										${stcmbackend.svg.threeDotsSmall}
									</button>
								</div>
							</div>
						</td>
					</tr>
					<tr id="ageRange_${index}" data-inputCode="">
						<td class="align-middle" title=""></td>
						<td class="align-middle" title="${pf.const.language.RSC1917}">${pf.const.language.RSC1917}</td>
						<td>
							<div class="input-group new-input-style">
								<input type="text" class="form-control-sm inputGrid inputAgeRange" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
								<div class="input-group-append">
									<button type="button" class="btn btn-outline-secondary searchProfiling py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-index="${index}" data-profiling="ageRange">
										${stcmbackend.svg.threeDotsSmall}
									</button>
								</div>
							</div>
						</td>
					</tr>
					<tr id="states_${index}" data-inputCode="">
						<td class="align-middle" title=""></td>
						<td class="align-middle" title="${pf.const.language.RSC153}">${pf.const.language.RSC153}</td>
						<td>
							<div class="input-group new-input-style">
								<input type="text" class="form-control-sm inputGrid inputStates" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
								<div class="input-group-append">
									<button type="button" class="btn btn-outline-secondary searchProfiling py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-index="${index}" data-profiling="states">
										${stcmbackend.svg.threeDotsSmall}
									</button>
								</div>
							</div>
						</td>
					</tr>
					<tr id="nse_${index}" data-inputCode="">
						<td class="align-middle" title=""></td>
						<td class="align-middle" title="${pf.const.language.RSC598}">${pf.const.language.RSC598}</td>
						<td>
							<div class="input-group new-input-style">
								<input type="text" class="form-control-sm inputGrid inputNSE" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
								<div class="input-group-append">
									<button type="button" class="btn btn-outline-secondary searchProfiling py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-index="${index}" data-profiling="nse">
										${stcmbackend.svg.threeDotsSmall}
									</button>
								</div>
							</div>
						</td>
					</tr>
		`;

		let size = self.targetsSurveyArray[index].length;
		for(let i = 0; i < size; i++) {
			let qidArray = self.targetsSurveyArray[index][i].columnName.split('X');
			let qid = qidArray.pop();

			// Array de tipos respuesta que no saldrán en la tabla
			let answersArray = ['R'];
			if(answersArray.indexOf(self.targetsSurveyArray[index][i].type) != -1 || self.targetsSurveyArray[index][i].question.includes('SOCIAL_LABS_')) {
				continue;
			}

			// La pregunta origen no sale en la tabla
			if(self.columnNameArray[index] == self.targetsSurveyArray[index][i].columnName) {
				continue;
			}

			let buttonClass = 'searchValues';
			if(self.targetsSurveyArray[index][i].type == '5' || self.targetsSurveyArray[index][i].type == 'A') {
				buttonClass = 'fiveValues';
			} else if(self.targetsSurveyArray[index][i].type == 'B') {
				buttonClass = 'tenValues';
			}

			// Limpieza de marcas de html
			let textWithTags = self.targetsSurveyArray[index][i].question;
			let tagsWithoutTags = textWithTags.replace(/<[^>]*>?/g, '');

			// Pregunta tipo array
			if(self.targetsSurveyArray[index][i].type == 'A' || self.targetsSurveyArray[index][i].type == 'B' || self.targetsSurveyArray[index][i].type == 'F') {
				let sizeK = self.targetsSurveyArray[index][i].valuesSQ.length;
				for(let j = 0; j < sizeK; j++) {
					let valuesSQArray = self.targetsSurveyArray[index][i].valuesSQ[j].split('|');
					let columnNameK = valuesSQArray[0];
					let questionKTitle = tagsWithoutTags.trim() + '\n' + valuesSQArray[1].replace(';', ' ');
					let questionK = tagsWithoutTags.trim() + '<br>' + valuesSQArray[1].replace(';', '');

					table += `
						<tr id="${columnNameK}_${index}" data-inputCode="">
							<td class="align-middle" title="${self.targetsSurveyArray[index][i].group_name}">${self.targetsSurveyArray[index][i].group_name}</td>
							<td class="align-middle" title="${questionKTitle}">${questionK}</td>
							<td>
								<div class="input-group new-input-style">
									<input type="text" class="form-control-sm inputGrid inputValue" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
									<div class="input-group-append">
										<button type="button" class="btn btn-outline-secondary ${buttonClass} py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-qid="${qid}" data-columnName="${self.targetsSurveyArray[index][i].columnName}" data-columnNameK="${columnNameK}" data-index="${index}" data-type="${self.targetsSurveyArray[index][i].type}">
											${stcmbackend.svg.threeDotsSmall}
										</button>
									</div>
								</div>
							</td>
						</tr>
					`;
				}
			} else {
				// El atributo data-inputCode suplira a la columna de código
				table += `
					<tr id="${self.targetsSurveyArray[index][i].columnName}_${index}" data-inputCode="">
						<td class="align-middle" title="${self.targetsSurveyArray[index][i].group_name}">${self.targetsSurveyArray[index][i].group_name}</td>
						<td class="align-middle" title="${tagsWithoutTags.trim()}">${tagsWithoutTags.trim()}</td>
						<td>
							<div class="input-group new-input-style">
								<input type="text" class="form-control-sm inputGrid inputValue" title="" placeholder="${pf.const.language.RSC349}" aria-label="Valores" disabled>
								<div class="input-group-append">
									<button type="button" class="btn btn-outline-secondary ${buttonClass} py-0 px-1" data-toggle="modal" data-target="#valuesTable" data-qid="${qid}" data-columnName="${self.targetsSurveyArray[index][i].columnName}" data-index="${index}" data-type="${self.targetsSurveyArray[index][i].type}">
										${stcmbackend.svg.threeDotsSmall}
									</button>
								</div>
							</div>
						</td>
					</tr>
				`;
			}
		}

		table += `
				</tbody>
			</table>
		`;

		$('#filtersContainer' + index).append(table);

		// Setup - add a text input to each footer cell
		$('#registersFilters' + index + ' .filtersResult' + index + ' td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm" disabled>`;

			if(title === 'section' || title === 'question') {
				value = `<input type="text" class="form-control form-control-sm">`;
			}

			$(this).html(value);
		});

		let dataTable = $('#registersFilters' + index).DataTable({
			retrieve: true,
			language: self.language,
			pageLength: 25,
			autoWidth: false,
			columnDefs: [
				{width: '200px', targets: 0},
				{width: '150px', targets: 2}
			],
			aaSorting: []
		});

		// Ocultar botones de tabla
		hideTableButtons('registersFilters' + index);

		// Apply the search
		applyTheSearch(dataTable, 'filtersResult' + index);

		self.eventTargetsSurvey(index);

		$('#registersFilters' + index).on('draw.dt', function() {
			self.eventTargetsSurvey(index);
		});
	},

	eventTargetsSurvey(index) {
		let self = this;

		// Valores de perfilación
		$('.searchProfiling').off().on('click', function() {
			let index = $(this).data('index');
			let profiling = $(this).data('profiling');

			switch(profiling) {
				case 'gender':
					self.surveyValues = self.filterByProfiling[index].gender;
					break;
				case 'ageRange':
					self.surveyValues = self.filterByProfiling[index].ageRange;
					break;
				case 'states':
					self.surveyValues = self.filterByProfiling[index].states;
					break;
				case 'nse':
					self.surveyValues = self.filterByProfiling[index].nse;
					break;
			}

			self.renderSurveyValues(index, profiling);
		});

		// Valores de modal
		$('.searchValues').off().on('click', function() {
			let qid = $(this).attr('data-qid');
			let index = $(this).data('index');
			let type = $(this).data('type');
			let survey = self.idPoll;
			self.columnName = $(this).attr('data-columnName');
			self.columnNameK = $(this).attr('data-columnNameK');
			self.requestSurveyValues(qid, survey, index, type);
		});

		// Valores de modal para preguntas tipo '5' y 'A'
		$('.fiveValues').off().on('click', function() {
			let index = $(this).data('index');
			self.surveyValues = [
				{code: '1', answer: '1'},
				{code: '2', answer: '2'},
				{code: '3', answer: '3'},
				{code: '4', answer: '4'},
				{code: '5', answer: '5'}
			];
			self.columnName = $(this).attr('data-columnName');
			self.columnNameK = $(this).attr('data-columnNameK');

			self.renderSurveyValues(index);
		});

		// Valores de modal para preguntas tipo 'B'
		$('.tenValues').off().on('click', function() {
			let index = $(this).data('index');
			self.surveyValues = [
				{code: '1', answer: '1'},
				{code: '2', answer: '2'},
				{code: '3', answer: '3'},
				{code: '4', answer: '4'},
				{code: '5', answer: '5'},
				{code: '6', answer: '6'},
				{code: '7', answer: '7'},
				{code: '8', answer: '8'},
				{code: '9', answer: '9'},
				{code: '10', answer: '10'}
			];
			self.columnName = $(this).attr('data-columnName');
			self.columnNameK = $(this).attr('data-columnNameK');

			self.renderSurveyValues(index);
		});
	},

	requestSurveyValues(qid, survey, index, type) {
		let self = this;

		let parameters = {
			survey: survey,
			qid: qid
		};
		ajaxComunCallWithCallback('getTargetsSurveyByQID', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				if(type == 'M') {
					self.surveyValues = [];
					for(let i = 0; i < ajaxReturn.result.length; i++) {
						let obj = {
							code: ajaxReturn.result[i].title,
							answer: ajaxReturn.result[i].answer
						}
						self.surveyValues.push(obj);
					}
				} else {
					self.surveyValues = ajaxReturn.result;
				}

				self.renderSurveyValues(index);
			}
		});
	},

	renderSurveyValues(index, profiling = '') {
		let self = this;

		if(self.renderSurveyValuesFlag) {
			$('#tableValues').dataTable().fnDestroy();
		} else {
			self.renderSurveyValuesFlag = true;
		}

		// Nombre/code sacado del modal
		let table = `
			<thead>
				<tr>
					<th scope="col">
						${pf.const.language.RSC406}
						<input id="selectionAll" type="checkbox" class="align-middle" ${(false ? 'checked' : '')}>
					</th>
					<th scope="col">${pf.const.language.RSC127}</th>
				</tr>
			</thead>

			<thead class="filtersValue">
				<tr>
					<td>checkbox</td>
					<td>answerName</td>
				</tr>
			</thead>

			<tbody>
		`;

		let controlChecks = [];
		let typeK = false;
		if(profiling == '') {
			let questionSize = self.targetsSurveyArray[index].length;
			for(let i = 0; i < questionSize; i++) {
				if(self.targetsSurveyArray[index][i].columnName == self.columnName && self.targetsSurveyArray[index][i].type != 'F' && self.targetsSurveyArray[index][i].type != 'A' && self.targetsSurveyArray[index][i].type != 'B') {
					controlChecks = self.targetsSurveyArray[index][i].code;
				} else if(self.targetsSurveyArray[index][i].columnName == self.columnName && (self.targetsSurveyArray[index][i].type == 'F' || self.targetsSurveyArray[index][i].type == 'A' || self.targetsSurveyArray[index][i].type == 'B')) {
					typeK = true;
					controlChecks = self.targetsSurveyArray[index][i].code[self.columnNameK];
				}
			}
		} else {
			//selected: []
			switch(profiling) {
				case 'gender':
					controlChecks = self.filterByProfiling[index].selectedGender;
					break;
				case 'ageRange':
					controlChecks = self.filterByProfiling[index].selectedAgeRange;
					break;
				case 'states':
					controlChecks = self.filterByProfiling[index].selectedStates;
					break;
				case 'nse':
					controlChecks = self.filterByProfiling[index].selectedNse;
					break;
			}
		}

		let size = self.surveyValues.length;
		for(let i = 0; i < size; i++) {
			let checked = false;
			if(typeK) {
				checked = (controlChecks.indexOf(String(self.surveyValues[i].code)) != -1 ? true : false);
			} else if(profiling != '') {
				checked = (controlChecks.indexOf(self.surveyValues[i].code) != -1 ? true : false);
			} else {
				checked = (controlChecks.indexOf(self.surveyValues[i].code) != -1 ? true : false);
			}

			let answer = self.surveyValues[i].answer;
			switch(answer) {
				case 'Y':
					answer = pf.const.language.RSC120;
					break;
				case 'N':
					answer = pf.const.language.RSC121;
					break;
				case 'M':
					answer = pf.const.language.RSC556;
					break;
				case 'F':
					answer = pf.const.language.RSC557;
					break;
			}
			let code = self.surveyValues[i].code || self.surveyValues[i].title;

			table += `
				<tr class="c-pointer check-select" data-value="${self.surveyValues[i].answer}" data-code="${code}">
					<td class="text-center">
						<span class="d-none">${(checked ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" class="selection" ${(checked ? 'checked' : '')}>
					</td>
					<td class="value">${answer}</td>
				</tr>
			`;
		}

		table += `
			</tbody>
		`;

		$('#tableValues').html(table);

		// Setup - add a text input to each footer cell
		$('#tableValues .filtersValue td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title == 'checkbox') {
				value = `<input type="text" class="form-control form-control-sm" disabled>`;
			}

			$(this).html(value);
		});

		let ObjetiveTable = $('#tableValues').DataTable({
			language: pf.const.language_table,
			scrollY: 300,
			scroller: false,
			paging: true,
			pageLength: 25,
			autoWidth: false,
			columnDefs: [
				{width: '130px', targets: 0}
			],
			ordering: false,
			aaSorting: []
		});

		setTimeout(function() {
			ObjetiveTable.columns.adjust();
		}, 200);

		// Apply the search
		applyTheSearch(ObjetiveTable, 'filtersValue');

		// Ocultar botones de tabla
		hideTableButtons('tableValues');

		if($('.selection').length == $('.selection:checked').length) {
			$('#selectionAll').prop('checked', true);
		} else {
			$('#selectionAll').prop('checked', false);
		}

		// Selección de múltiples encuestas
		self.selectionMult(index, profiling);

		$('#tableValues').on('draw.dt', function() {
			self.selectionMult(index, profiling);
		});
	},

	selectionMult(index, profiling) {
		let self = this;

		// Selección por tr
		$('.check-select').off().on('click', function() {
			let checkedComp = $(this).find('.selection').prop('checked');
			if(checkedComp) {
				$(this).find('.selection').prop('checked', false);
			} else {
				$(this).find('.selection').prop('checked', true);
			}

			if($('.selection').length == $('.selection:checked').length) {
				$('#selectionAll').prop('checked', true);
			} else {
				$('#selectionAll').prop('checked', false);
			}
		});

		// Selección por input
		$('.selection').off().on('click', function() {
			let checkedComp = $(this).prop('checked');
			if(checkedComp) {
				$(this).prop('checked', false);
			} else {
				$(this).prop('checked', true);
			}

			if($('.selection').length == $('.selection:checked').length) {
				$('#selectionAll').prop('checked', true);
			} else {
				$('#selectionAll').prop('checked', false);
			}
		});

		// La id del elemento principal modifica los elementos secundarios a través de su clase
		$('#selectionAll').on('click', function() {
			$('.selection').prop('checked', this.checked);
		});

		$('#selectValues' + self.suffix).off().on('click', function() {
			let valueArray = [];
			let codeArray = [];
			let nameArray = [];

			$('#tableValues tr').each(function() {
				let cheked = $(this).find('.selection');
				if(cheked.prop('checked')) {
					valueArray.push($(this).attr('data-value'));
					codeArray.push($(this).attr('data-code'));
					nameArray.push($(this).find('.value').text());
				}
			});

			let typeK = false;
			if(profiling == '') {
				let size = self.targetsSurveyArray[index].length;
				for(let i = 0; i < size; i++) {
					if(self.columnName == self.targetsSurveyArray[index][i].columnName && self.targetsSurveyArray[index][i].type != 'A' && self.targetsSurveyArray[index][i].type != 'B' && self.targetsSurveyArray[index][i].type != 'F') {
						self.targetsSurveyArray[index][i].value = valueArray;
						self.targetsSurveyArray[index][i].code = codeArray;
					} else if(self.columnName == self.targetsSurveyArray[index][i].columnName && (self.targetsSurveyArray[index][i].type == 'A' || self.targetsSurveyArray[index][i].type == 'B' || self.targetsSurveyArray[index][i].type == 'F')) {
						typeK = true;
						self.targetsSurveyArray[index][i].value[self.columnNameK] = valueArray;
						self.targetsSurveyArray[index][i].code[self.columnNameK] = codeArray;
					}
				}
			} else {
				switch(profiling) {
					case 'gender':
						self.filterByProfiling[index].selectedGender = codeArray;
						break;
					case 'ageRange':
						self.filterByProfiling[index].selectedAgeRange = codeArray;
						break;
					case 'states':
						self.filterByProfiling[index].selectedStates = codeArray;
						break;
					case 'nse':
						self.filterByProfiling[index].selectedNse = codeArray;
						break;
				}
			}

			if(typeK) {
				$('#' + self.columnNameK + '_' + index).find('.inputValue').val(nameArray);
				$('#' + self.columnNameK + '_' + index).find('.inputValue').attr('title', nameArray);
				$('#' + self.columnNameK + '_' + index).attr('data-inputCode', codeArray);
			} else if(profiling != '') {
				$('#' + profiling + '_' + index).find('input').val(nameArray);
				$('#' + profiling + '_' + index).find('input').attr('title', nameArray);
				$('#' + profiling + '_' + index).attr('data-inputCode', codeArray);
			} else {
				$('#' + self.columnName + '_' + index).find('.inputValue').val(nameArray);
				$('#' + self.columnName + '_' + index).find('.inputValue').attr('title', nameArray);
				$('#' + self.columnName + '_' + index).attr('data-inputCode', codeArray);
			}

			$('#closeValues').trigger('click');
		});
	},

	// GRÁFICAS
	createGraphs(data, n, index) {
		let self = this;

		let ctx;
		let quantity = data.labels.length;
		let gradient = [];
		if(quantity == 2) {
			gradient = self.colorsHex;
		} else {
			if(self.typeColors == 1) {
				gradient = generateColors(self.colorsHex[0], self.colorsHex[1], quantity);
			} else {
				gradient = arrayColors(self.colorsHex, quantity);
			}
		}
	
		data = self.answersOrderDataTemplate(data, self.results[index].type);

		let options = '';
		if(typeof data.options == 'object') {
			options = data.options;
		} else {
			options = JSON.parse(data.options);
		}

		options.title.display = true;
		options.title.text = pf.const.language.RSC443 + ': ' + self.participantsNumber[index];
		options.layout.padding.top = 0;
		options.title.padding = 15;

		if((self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && n == 0) {
			options.legend.display = true;
			options.scales.xAxes[0]['stacked'] = true;
			options.scales.yAxes[0]['stacked'] = true;
		} else if(n == 0) {
			options.legend.display = false;
			options.scales.xAxes[0]['stacked'] = false;
			options.scales.yAxes[0]['stacked'] = false;
		}

		switch(n) {
			case 0:
				self.answersData[index] = data;
				if(!$.isEmptyObject(self.answersChart[index])) {
					self.answersChart[index].destroy();
				}

				if(self.results[index].type != 'A' && self.results[index].type != 'B' && self.results[index].type != 'F' && self.results[index].type != 'R') {
					data.datasets.backgroundColor = gradient;
					if(data.labels[data.labels.length - 1] == '-oth-') {
						data.labels[data.labels.length - 1] = pf.const.language.RSC128;
					}
				}

				ctx = document.getElementById('graphAnswers' + index).getContext('2d');
				break;
			case 1:
				self.genderData[index] = data;
				if(!$.isEmptyObject(self.genderChart[index])) {
					self.genderChart[index].destroy();
				}
				data.datasets.backgroundColor = self.colorsHex;
				ctx = document.getElementById('graphGender' + index).getContext('2d');
				break;
			case 2:
				self.ageData[index] = data;
				if(!$.isEmptyObject(self.ageChart[index])) {
					self.ageChart[index].destroy();
				}
				data.datasets.backgroundColor = gradient;
				ctx = document.getElementById('graphAge' + index).getContext('2d');
				break;
			case 3:
				self.statesData[index] = data;
				if(!$.isEmptyObject(self.statesChart[index])) {
					self.statesChart[index].destroy();
				}
				data.datasets.backgroundColor = gradient;
				ctx = document.getElementById('graphStates' + index).getContext('2d');
				break;
			case 4:
				self.NSEData[index] = data;
				if(!$.isEmptyObject(self.NSEChart[index])) {
					self.NSEChart[index].destroy();
				}
				data.datasets.backgroundColor = gradient;
				ctx = document.getElementById('graphNSE' + index).getContext('2d');
				break;
		}

		options['tooltips'] = {
			enabled: false
		};

		if(n == 1) {
			options['plugins'] = {
				datalabels: {
					color: 'black',
					font: {
						weight: 'bold',
						size: 16
					},
					clamp: true,
					formatter(value, context) {
						return value;
					}
				}
			};
		} else {
			// Control de tamaño máximo de columna
			options.scales.xAxes[0]['maxBarThickness'] = 150;

			if((self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && n == 0) {
				options['plugins'] = {
					datalabels: {
						color: 'black',
						font: {
							weight: 'bold',
							size: 16
						},
						formatter(value, context) {
							return value;
						}
					}
				};
			} else {
				// Radio de ángulos
				options.cornerRadius = 6;

				options['plugins'] = {
					datalabels: {
						color: 'black',
						font: {
							weight: 'bold',
							size: 16
						},
						anchor: 'end',
						align: 'end',
						formatter(value, context) {
							return value;
						}
					}
				};
			}
		}

		if(n !== 1) {
			// Ancho de columnas
			options.scales.xAxes[0]['barPercentage'] = 0.5;

			// Ticks X en horizontal con salto de linea
			// Ancho del contenedor de la gráfica
			let divParentWidth = $('#graphAnswers' + index).parent().css('width');
			// Número de columnas de la gráfica
			let nColumns = quantity;
			// Ancho del contenedor entre el número de columnas
			let maxwidth = Math.floor(parseInt(divParentWidth) / nColumns);
			// Ancho de la columna entre el tamaño de la fuente
			let maxwidthFont = Math.ceil(maxwidth / self.fontSize) + 2;

			// Etiquetas del eje X
			let xLabels = data.labels;
			// Comprobación de la primera palabra de los labels para ejecutar formato horizontal o diagonal
			let controlH = true;
			let xSize = xLabels.length;
			// Utilización de caracter de corte si lo hay
			if(self.splitCharacter != '') {
				for(let i = 0; i < xSize; i++) {
					if(xLabels[i] == null || xLabels[i] == undefined) {
						continue;
					}

					let indexCut = xLabels[i].toString().indexOf(self.splitCharacter);
					if(indexCut != -1) {
						xLabels[i] = xLabels[i].toString().slice(0, indexCut);
					}
				}
			}

			for(let i = 0; i < xSize; i++) {
				if(xLabels[i] == null || xLabels[i] == undefined) {
					continue;
				}

				let words = xLabels[i].toString().split(' ');
				let wSize = words.length;
				for(let j = 0; j < wSize; j++) {
					if(words[j].length > maxwidthFont) {
						controlH = false;
						break;
					}
				}
				if(!controlH) {
					break;
				}
			}

			if(controlH) {
				options.scales.xAxes[0].ticks['minRotation'] = 0;
				options.scales.xAxes[0].ticks['maxRotation'] = 0;

				options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
					let formmatedvalue = formatLabel(value, maxwidthFont);
					return formmatedvalue;
				}
			} else {
				options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
					if(value == null || value == undefined) {
						return value;
					} else if(value.length < 18) {
						return value;
					} else {
						return value.substr(0, 14) + '...';
					}
				};
			}
		}

		Chart.defaults.global.defaultFontSize = 16;
		Chart.defaults.global.defaultFontFamily = 'Arial';

		let graphElement = {
			// The type of chart we want to create
			type: data.type,
			// The data for our dataset
			data: {
				datasets: (self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && n == 0 ? data.datasets : [data.datasets],
				labels: data.labels
			},
			// Configuration options go here
			options: options
		};

		if(n == 0) {
			let dataArray = [];
			let dataGraph = [data.datasets];
			let type = 'normal';
			let subLabels = [];

			if(self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') {
				dataGraph = data.datasets;
				type = 'stacked';
			}

			for(let a = 0; a < dataGraph.length; a++) {
				dataArray.push(dataGraph[a].data);
				if(type == 'stacked') {
					subLabels.push(dataGraph[a].label);
				}
			}

			// Guardado de gráficas de respuesta para reporte
			let obj = {
				type: type,
				colors: gradient,
				data: dataArray,
				labels: data.labels,
				subLabels: subLabels
			};

			self.graphsToReport[index].data = obj;
		}

		let graph = new Chart(ctx, graphElement);

		switch(n) {
			case 0:
				self.answersChart[index] = graph;
				break;
			case 1:
				self.genderChart[index] = graph;
				break;
			case 2:
				self.ageChart[index] = graph;
				break;
			case 3:
				self.statesChart[index] = graph;
				break;
			case 4:
				self.NSEChart[index] = graph;
				break;
		}
	},

	// TABLA DE RESULTADOS
	renderData(perf = false, index) {
		let self = this;

		$('#resultTable').show();
		let excelTitle = self.idMission + ' - ' + self.questions[index].question;

		let gdpr = sessionStorage['STCMBackEnd:GDPR'];

		let nameSurnameHead = `
			<th scope="col" title="${pf.const.language.RSC123}">${pf.const.language.RSC123}</th>
			<th scope="col" title="${pf.const.language.RSC1626}">${pf.const.language.RSC1626}</th>
			<th scope="col" title="${pf.const.language.RSC1627}">${pf.const.language.RSC1627}</th>
		`;
		let nameSurnameFilter = `
			<td data-name="userName">userName</td>
			<td data-name="userApellido">userApellido</td>
			<td data-name="userApellido2">userApellido2</td>
		`;

		// Control GDPR
		if(gdpr == '1') {
			nameSurnameHead = '';
			nameSurnameFilter = '';
		}

		let table = `
			<table id="registers${index}" class="table table-hover tRegs">
				<thead>
					<tr>
						${nameSurnameHead}
						<th scope="col" title="${pf.const.language.RSC136}">${pf.const.language.RSC136}</th>
						<th scope="col" title="${pf.const.language.RSC124}">${pf.const.language.RSC124}</th>
						<th scope="col" title="${pf.const.language.RSC309}">${pf.const.language.RSC309}</th>
						<th scope="col" title="${pf.const.language.RSC125}">${pf.const.language.RSC125}</th>
						<th scope="col" title="${pf.const.language.RSC126}">${pf.const.language.RSC126}</th>
						<th scope="col" title="${pf.const.language.RSC127}">${pf.const.language.RSC127}</th>
						<th scope="col" title="${pf.const.language.RSC128}">${pf.const.language.RSC128}</th>
		`;

		$.each(self.data[index][0], function(key, value) {
			if(key.indexOf('perf') !== -1 && key.indexOf('Desc') !== -1) {
				table += `<th scope="col" title="${value}">${value}</th>`;
			}
		});

		table += `
				</tr>
			</thead>

			<thead class="filtersResult${index}">
				<tr>
					${nameSurnameFilter}
					<td data-name="userEmail">userEmail</td>
					<td data-name="consejero">consejero</td>
					<td data-name="staff">staff</td>
					<td data-name="clabe">clabe</td>
					<td data-name="enabled">enabled</td>
					<td data-name="answer">answer</td>
					<td data-name="answerothers">answerothers</td>
		`;

		$.each(self.data[index][0], function(key, value) {
			if(key.indexOf('perf') !== -1 && key.indexOf('Desc') === -1 && key != 'perf002Range') {
				table += `<td data-name="${key}">${key}</td>`;
			}
		});

		table += `
				</tr>
			</thead>

			<tbody>
		`;

		let size = self.data[index].length;
		for(let i = 0; i < size; i++) {
			if(self.data[index][i].question.indexOf('comment') != -1) {
				continue;
			}

			let answerothers = (self.data[index][i].answerothers == '' ? '-' : self.data[index][i].answerothers);

			if(self.data[index][i].answer == '-oth-') {
				self.data[index][i].answer = pf.const.language.RSC128;
			}

			let nameSurnameBody = `
				<td class="text-truncate" title="${self.data[index][i].userName}">${self.data[index][i].userName}</td>
				<td class="text-truncate" title="${(self.data[index][i].userApellido != null ? self.data[index][i].userApellido : '-')}">${(self.data[index][i].userApellido != null ? self.data[index][i].userApellido : '-')}</td>
				<td class="text-truncate" title="${(self.data[index][i].userApellido2 != null ? self.data[index][i].userApellido2 : '-')}">${(self.data[index][i].userApellido2 != null ? self.data[index][i].userApellido2 : '-')}</td>
			`;

			// Control GDPR
			if(gdpr == '1') {
				nameSurnameBody = '';
			}

			// Respuesta para preguntas de array
			let answer = '';
			if(self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F') {
				answer = self.data[index][i].answer + ' - ' + self.questionsSQArray[index][self.data[index][i].question].name;
			} else if(self.data[index][i].answer != 'Others') {
				answer = self.data[index][i].answer;
			}

			table += `
				<tr>
					${nameSurnameBody}
					<td class="text-truncate" title="${self.data[index][i].userEmail}">${self.data[index][i].userEmail}</td>
					<td class="text-center">
						<span class="d-none">${(self.data[index][i].consejero == '1' ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" disabled ${(self.data[index][i].consejero == '1' ? 'checked' : '')}>
					</td>
					<td class="text-center">
						<span class="d-none">${(self.data[index][i].staff == '1' ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" disabled ${(self.data[index][i].staff == '1' ? 'checked' : '')}>
					</td>
					<td class="text-center">
						<span class="d-none">${(self.data[index][i].clabe == '1' ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" disabled ${(self.data[index][i].clabe == '1' ? 'checked' : '')}>
					</td>
					<td class="text-center">
						<span class="d-none">${(self.data[index][i].enabled == '1' ? pf.const.language.RSC120 : pf.const.language.RSC121)}</span>
						<input type="checkbox" disabled ${(self.data[index][i].enabled == '1' ? 'checked' : '')}>
					</td>
					<td class="text-truncate" title="${answer}">${answer}</td>
					<td class="text-truncate" title="${answerothers}">${answerothers}</td>
			`;

			$.each(self.data[index][i], function(key, value) {
				if(key.indexOf('perf') !== -1 && key.indexOf('Desc') === -1 && key != 'perf002Range') {
					if(value == null) {
						value = '-';
					}
					table += `<td class="text-truncate" title="${value}">${value}</td>`;
				}
			});

			table += `
				</tr>
			`;
		}

		table += `
				</tbody>
			</table>
		`;

		$('#registersContainer' + index).html(table);

		// Setup - add a text input to each footer cell
		$('#registers' + index + ' .filtersResult' + index + ' td').each(function() {
			let title = $(this).text();
			let value = `<input type="text" class="form-control form-control-sm">`;

			if(title == 'consejero' || title == 'staff' || title == 'clabe' || title == 'enabled') {
				value = optionsSelectAllYesNo();
			}

			$(this).html(value);
		});

		// Opción paginado
		let columnDefs = [
			{width: '60px', targets: 4},
			{width: '40px', targets: 5},
			{width: '40px', targets: 6},
			{width: '40px', targets: 7}
		];

		// Control GDPR
		if(gdpr == '1') {
			columnDefs = [
				{width: '60px', targets: 1},
				{width: '40px', targets: 2},
				{width: '40px', targets: 3},
				{width: '40px', targets: 4}
			];
		}

		let dataTable = $('#registers' + index).DataTable({
			retrieve: true,
			language: pf.const.language_table,
			pageLength: 25,
			autoWidth: false,
			columnDefs: columnDefs,
			dom: 'Bfrtip',
			buttons: [{
				extend: 'excelHtml5',
				text: pf.const.language.RSC129,
				className: 'd-none',
				title: excelTitle,
				customize(xlsx) {
					dataTablesExcelCustomize(xlsx);
				}
			}],
			rowGroup: {
				endRender(rows, group) {
					// Paginado
					return group + ': ' + pf.const.language.RSC146 + ' (' + rows.count() + ')';
				},
				dataSrc: 0
			},
			order: [[0, 'asc']]
		});

		// Ocultar botones de tabla
		hideTableButtons('registers' + index);

		// Apply the search
		let filter = 'filtersResult' + index;
		applyTheSearch(dataTable, filter);

		dataTable.rowGroup().disable().draw();
		$('#nestBy' + index).hide();

		// Creación de select principal de agrupamiento
		// Arrays de datos
		let name = [];

		$.each($('#registers' + index + ' thead th'), function() {
			name.push($(this).text());
		});

		let options1 = `<option value="-1">${pf.const.language.RSC130}</option>`;
		for(let i = 0; i < name.length; i++) {
			options1 += `<option value="${i}">${name[i]}</option>`;
		}
		$('#groupBy' + index).html(options1);

		// Función de agrupamiento anidado
		function nestBy() {
			$('#nestBy' + index).html('');
			let options2 = `<option value="-1">${pf.const.language.RSC131}</option>`;
			for(let i = 0; i < name.length; i++) {
				if(i == $('#groupBy' + index).val()) {
					continue;
				} else {
					options2 += `<option value="${i}">${name[i]}</option>`;
				}
			}
			$('#nestBy' + index).html(options2);

			// Evento de anidado
			$('#nestBy' + index).off().on('change', function() {
				let valueGroup = $('#groupBy' + index).val();

				if($('#nestBy' + index).val() === '-1') {
					dataTable.rowGroup().dataSrc(valueGroup);
					dataTable.order([[valueGroup, 'asc']]).draw();
				} else {
					let valueNest = $('#nestBy' + index).val();
					dataTable.rowGroup().dataSrc([valueGroup, valueNest]);
					dataTable.order([[valueGroup, 'asc'], [valueNest, 'asc']]).draw();
				}
			});
		}

		// Evento de agrupamiento
		$('#groupBy' + index).on('change', function() {
			if($('#groupBy' + index).val() === '-1') {
				dataTable.rowGroup().disable().draw();
				$('#nestBy' + index).hide();
			} else {
				let value = $('#groupBy' + index).val();

				dataTable.rowGroup().enable().draw();
				$('#nestBy' + index).show();

				dataTable.rowGroup().dataSrc(value);
				dataTable.order([[value, 'asc']]).draw();

				// Recreación de agrupamiento secundario
				nestBy();
			}
		});

		$('#exportQuestion' + index).off().on('click', function() {
			$('#resultTable' + index + ' .buttons-excel').trigger('click');
		});
	},

	// Gráfica a pantalla completa
	graphsEvents() {
		let self = this;

		let quantity = 0;

		$('.graphics').off().on('click', function() {
			let index = $(this).data('index');
			let graph = $(this).data('type');

			$('#graphicsViewer').show();
			let data = '';
			let titleText = '';
			let participants = pf.const.language.RSC443 + ': ' + self.participantsNumber[index];

			let ctx = document.getElementById('graphViewer').getContext('2d');
			switch(graph) {
				case 'graphAnswers':
					data = self.answersData[index];
					quantity = data.labels.length;
					titleText = $('#resp' + index + 'p').text();
					break;
				case 'graphGender':
					data = self.genderData[index];
					titleText = pf.const.language.RSC147 + ' (%)';
					break;
				case 'graphAge':
					data = self.ageData[index];
					quantity = data.labels.length;
					titleText = pf.const.language.RSC148 + ' (%)';
					break;
				case 'graphStates':
					data = self.statesData[index];
					quantity = data.labels.length;
					titleText = pf.const.language.RSC149 + ' (%)';
					break;
				case 'graphNSE':
					data = self.NSEData[index];
					quantity = data.labels.length;
					titleText = pf.const.language.RSC1000 + ' (%)';
					break;
				default:
					break;
			}

			if(typeof data.options === 'string') {
				data.options = JSON.parse(data.options);
			}

			data.options.title.display = true;
			data.options.title.text = [titleText, participants];
			data.options.layout.padding.top = 0;
			data.options.title.padding = 15;
			data.options['tooltips'] = {
				enabled: false
			};
			if((self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && graph == 'graphAnswers') {
				data.options.legend.display = true;
				data.options.scales.xAxes[0]['stacked'] = true;
				data.options.scales.yAxes[0]['stacked'] = true;
			} else if(graph == 'graphAnswers') {
				data.options.legend.display = false;
				data.options.scales.xAxes[0]['stacked'] = false;
				data.options.scales.yAxes[0]['stacked'] = false;
			}

			if(graph == 'graphGender') {
				data.options['plugins'] = {
					datalabels: {
						color: 'black',
						font: {
							weight: 'bold',
							size: 16
						},
						clamp: true,
						formatter(value, context) {
							return value;
						}
					}
				};
			} else {
				// Control de tamaño máximo de columna
				data.options.scales.xAxes[0]['maxBarThickness'] = 150;

				if((self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && graph == 'graphAnswers') {
					data.options['plugins'] = {
						datalabels: {
							color: 'black',
							font: {
								weight: 'bold',
								size: 16
							},
							formatter(value, context) {
								return value;
							}
						}
					};
				} else {
					// Radio de ángulos
					data.options.cornerRadius = 6;
	
					data.options['plugins'] = {
						datalabels: {
							color: 'black',
							font: {
								weight: 'bold',
								size: 16
							},
							anchor: 'end',
							align: 'end',
							formatter(value, context) {
								return value;
							}
						}
					};
				}
			}

			Chart.defaults.global.defaultFontSize = 16;
			Chart.defaults.global.defaultFontFamily = 'Arial';

			if(graph != 'graphGender') {
				// Ancho de columnas
				data.options.scales.xAxes[0]['barPercentage'] = 0.5;
				// Ticks X en horizontal con salto de linea
				// Ancho del contenedor de la gráfica
				let divParentWidth = $('#graphViewer').parent().css('width');
				// Número de columnas de la gráfica
				let nColumns = quantity;
				// Ancho del contenedor entre el número de columnas
				let maxwidth = Math.floor(parseInt(divParentWidth) / nColumns);
				// Ancho de la columna entre el tamaño de la fuente
				let maxwidthFont = Math.ceil(maxwidth / self.fontSize) + 2;

				// Etiquetas del eje X
				let xLabels = data.labels;
				// Comprobación de la primera palabra de los labes para ejecutar formato horizontal o diagonal
				let controlH = true;
				let xSize = xLabels.length;
				// Utilización de caracter de corte si lo hay
				if(self.splitCharacter != '') {
					for(let i = 0; i < xSize; i++) {
						if(xLabels[i] == null || xLabels[i] == undefined) {
							continue;
						}

						let indexCut = xLabels[i].toString().indexOf(self.splitCharacter);
						if(indexCut != -1) {
							xLabels[i] = xLabels[i].toString().slice(0, indexCut);
						}
					}
				}

				for(let i = 0; i < xSize; i++) {
					if(xLabels[i] == null || xLabels[i] == undefined) {
						continue;
					}

					let words = xLabels[i].toString().split(' ');
					let wSize = words.length;
					for(let j = 0; j < wSize; j++) {
						if(words[j].length > maxwidthFont) {
							controlH = false;
							break;
						}
					}
					if(!controlH) {
						break;
					}
				}

				if(controlH) {
					data.options.scales.xAxes[0].ticks['minRotation'] = 0;
					data.options.scales.xAxes[0].ticks['maxRotation'] = 0;

					data.options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
						let formmatedvalue = formatLabel(value, maxwidthFont);

						return formmatedvalue;
					}
				}
			}

			if(screen.width < 380) {
				data.options.scales.xAxes[0].ticks.fontSize = 12;
			}

			self.fullPageGraph = new Chart(ctx, {
				// The type of chart we want to create
				type: data.type,
				// The data for our dataset
				data: {
					labels: data.labels,
					datasets: (self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F' || self.results[index].type == 'R') && graph == 'graphAnswers' ? data.datasets : [data.datasets]
				},
				// Configuration options go here
				options: data.options
			});
		});

		$('#downloadGraph').off().on('click', function() {
			/*Get image of canvas element*/
			let url_base64jp = document.getElementById('graphViewer').toDataURL('image/jpg');
			/*get download button (tag: <a></a>) */
			let a = document.getElementById('downloadGraph');
			/*insert chart image url to download button (tag: <a></a>) */
			a.href = url_base64jp;
		});

		$('#closeGraphic').off().on('click', function() {
			self.fullPageGraph.destroy();

			$('#graphicsViewer').hide();
		});

		// Modificación de gráfica de respuestas segun datos de perfilación
		$('.profilesSelector').off().on('change', function() {
			let value = $(this).val();
			let index = $(this).data('index');

			self.answersChart[index].destroy();

			let answers = self.results[index].answers;

			if(value === 'answers') {
				$('#graphAnswersContainer' + index).removeClass('d-none');
				$('#graphAnswersProfileContainer' + index).addClass('d-none');
				self.createGraphs(answers, 0, index);
				self.graphsEvents();
			} else {
				$('#graphAnswersContainer' + index).addClass('d-none');
				$('#graphAnswersProfileContainer' + index).removeClass('d-none');
				self.createProfileGraphs(value, index);
			}
		});

		$('.filterQuestion').off().on('click', function() {
			let index = $(this).data('index');

			self.LoadSurveyParticipantsFiltered(index);
		});
	},

	LoadSurveyParticipantsFiltered(index) {
		let self = this;

		let query = '';

		let sizeT = self.targetsSurveyArray[index].length;
		for(let t = 0; t < sizeT; t++) {
			if(self.targetsSurveyArray[index][t].code.length == 0) {
				continue;
			}

			if(self.targetsSurveyArray[index][t].type == 'A' || self.targetsSurveyArray[index][t].type == 'B' || self.targetsSurveyArray[index][t].type == 'F') {
				let sqControl = false;
				let sizeK = self.targetsSurveyArray[index][t].valuesSQ.length;
				for(let j = 0; j < sizeK; j++) {
					let valuesSQArray = self.targetsSurveyArray[index][t].valuesSQ[j].split('|');
					let columnNameK = valuesSQArray[0];
					if(self.targetsSurveyArray[index][t].code[columnNameK].length > 0 && self.targetsSurveyArray[index][t].code[columnNameK][0] != '') {
						if(query === '') {
							query += ' survey_' + self.idPoll + '.' + columnNameK + ' IN (\'' + self.targetsSurveyArray[index][t].code[columnNameK].toString().replace(/,/g, '\',\'') + '\') ';
						} else {
							query += 'AND survey_' + self.idPoll + '.' + columnNameK + ' IN (\'' + self.targetsSurveyArray[index][t].code[columnNameK].toString().replace(/,/g, '\',\'') + '\') ';
						}

						sqControl = true;
					}
				}

				if(!sqControl) {
					continue;
				}
			} else if(self.targetsSurveyArray[index][t].type == 'M') {
				if(self.targetsSurveyArray[index][t].code.length > 0 && self.targetsSurveyArray[index][t].code[0] != '') {
					for(let m = 0; m < self.targetsSurveyArray[index][t].code.length; m++) {
						if(query === '') {
							query += ' survey_' + self.idPoll + '.' + self.targetsSurveyArray[index][t].columnName + self.targetsSurveyArray[index][t].code[m] + ' IN (\'Y\') ';
						} else {
							query += 'AND survey_' + self.idPoll + '.' + self.targetsSurveyArray[index][t].columnName + self.targetsSurveyArray[index][t].code[m] + ' IN (\'Y\') ';
						}
					}
				}
			} else {
				if(self.targetsSurveyArray[index][t].code.length > 0 && self.targetsSurveyArray[index][t].code[0] != '') {
					if(query === '') {
						query += ' survey_' + self.idPoll + '.' + self.targetsSurveyArray[index][t].columnName + ' IN (\'' + self.targetsSurveyArray[index][t].code.toString().replace(/,/g, '\',\'') + '\') ';
					} else {
						query += 'AND survey_' + self.idPoll + '.' + self.targetsSurveyArray[index][t].columnName + ' IN (\'' + self.targetsSurveyArray[index][t].code.toString().replace(/,/g, '\',\'') + '\') ';
					}
				}
			}
		}

		// Parámetros de perfilación
		let profilingParameters = {
			selectedGender: self.filterByProfiling[index].selectedGender,
			selectedAgeRange: self.filterByProfiling[index].selectedAgeRange,
			selectedStates: self.filterByProfiling[index].selectedStates,
			selectedNse: self.filterByProfiling[index].selectedNse
		}

		let parameters = {
			survey: self.idPoll,
			whereQuery: query,
			maxRows: 0,
			havingQuery: '',
			havingQueryColumnID: '',
			inclusivo: 1,
			cpgList: 0,
			profilingParameters: JSON.stringify(profilingParameters),
			questions: self.columnNameArray[index],
			param4: self.numPregPerf,
			isPerf: self.isPerf,
			title: self.questions[index].title,
			continuingMission: self.isContinuing,
			startDate: self.startDate,
			endDate: self.endDate
		};
		ajaxComunCallWithCallback('getAnswersSurveyByQueryDinamic', parameters, function(ajaxReturn) {
			if(ajaxReturn) {
				// Si no hay resultados en la encuesta/pregunta
				if(ajaxReturn.result.length == 0) {
					let errorTitle = pf.const.language.RSC35;
					let errorContent = pf.const.language.RSC529;
					pf.utils.showInfoDialog(errorTitle, errorContent);
					return;
				}

				self.results[index] = ajaxReturn.result[0];

				// Número de participantes
				let participants = [];
				let pSize = 0;
				if(self.results[index].data != undefined) {
					pSize = self.results[index].data.length;
				}

				for(let j = 0; j < pSize; j++) {
					if(participants.indexOf(self.results[index].data[j].user) == -1) {
						participants.push(self.results[index].data[j].user);
					}
				}
				self.participantsNumber[index] = participants.length;

				// Datos para gráfica de respuestas
				let answers = self.results[index].answers;
				self.data[index] = self.results[index].data;

				// Para gráficas Stacked
				let SQSize = Object.keys(self.questionsSQArray[index]).length;
				// Limpieza de 'data' de self.questionsSQArray[index]
				for(let data in self.questionsSQArray[index]) {
					self.questionsSQArray[index][data].data = [];
				}

				if(self.results[index].type == 'A' || self.results[index].type == 'B' || self.results[index].type == 'F') {
					let dSize = self.results[index].data.length;
					for(let p = 0; p < dSize; p++) {
						self.questionsSQArray[index][self.results[index].data[p].question].data.push(self.results[index].data[p]);
					}

					// Rango de colores
					let gradient = [];
					if(SQSize == 2) {
						gradient = self.colorsHex;
					} else {
						if(self.typeColors == 1) {
							gradient = generateColors(self.colorsHex[0], self.colorsHex[1], SQSize);
						} else {
							gradient = arrayColors(self.colorsHex, SQSize);
						}
					}

					let labelsData = [];
					let lSize = self.results[index].answers.labels.length;
					for(let j = 0; j < lSize; j++) {
						labelsData.push(0);
					}

					let datasetArray = [];
					let count = 0;
					for(let questionsSQ in self.questionsSQArray[index]) {
						let labelsDataSQ = [...labelsData];
						let dSizeSQ = self.questionsSQArray[index][questionsSQ].data.length;
						for(let n = 0; n < dSizeSQ; n++) {
							let index2 = self.results[index].answers.labels.indexOf(self.questionsSQArray[index][questionsSQ].data[n].answer);
							labelsDataSQ[index2]++;
						}

						for(let m = 0; m < lSize; m++) {
							labelsDataSQ[m] = (labelsDataSQ[m] * 100 / self.participantsNumber[index]).toFixed(1);
						}

						let obj = {
							label: self.questionsSQArray[index][questionsSQ].name,
							data: labelsDataSQ,
							backgroundColor: gradient[count]
						};

						datasetArray.push(obj);
						count++;
					}

					self.results[index].answers.datasets = datasetArray;
					answers = self.results[index].answers;
				} else if(self.results[index].type == 'R') {
					let labels = self.results[index].answers.labels;

					let labelsObj = [];
					let labelsLabels = [];
					for(let l = 0; l < labels.length; l++) {
						let labelsOptions = [];
						for(let l in labels) {
							labelsOptions.push(0);
						}

						let obj = {
							labelName: labels[l],
							ranking: labelsOptions
						};
						labelsObj.push(obj);
						labelsLabels.push(l + 1);
					}

					let labelsObjIndex = 0;
					let rankingControl = self.participantsNumber[index];
					let dSize = self.data[index].length;
					for(let r = 0; r < dSize; r++) {
						if(r == rankingControl) {
							rankingControl += self.participantsNumber[index];
							labelsObjIndex++;
						}

						let index2 = labels.indexOf(self.data[index][r].answer);
						labelsObj[labelsObjIndex].ranking[index2]++;
					}

					// Rango de colores
					let gradient = [];
					if(labels.length == 2) {
						gradient = self.colorsHex;
					} else {
						if(self.typeColors == 1) {
							gradient = generateColors(self.colorsHex[0], self.colorsHex[1], labels.length);
						} else {
							gradient = arrayColors(self.colorsHex, labels.length);
						}
					}

					let datasetArray = [];
					let count = 0;
					for(let label in labelsObj) {
						for(let m = 0; m < labels.length; m++) {
							labelsObj[label].ranking[m] = (labelsObj[label].ranking[m] * 100 / self.participantsNumber[index]).toFixed(1);
						}

						let obj = {
							label: labelsObj[label].labelName,
							data: labelsObj[label].ranking,
							backgroundColor: gradient[count]
						};

						datasetArray.push(obj);
						count++;
					}

					self.results[index].answers.datasets = datasetArray;
					answers = self.results[index].answers;
				}
				// Fin gráficas Stacked

				$('#profiles' + index).val('answers');
				$('#graphAnswersContainer' + index).removeClass('d-none');
				$('#graphAnswersProfileContainer' + index).addClass('d-none');
				
				if(ajaxReturn.perf || !$('#showProfiles').prop('checked')) {
					// Gráfica de respuestas
					self.createGraphs(answers, 0, index);
				} else {
					// Gráfica de respuestas
					self.createGraphs(answers, 0, index);

					// Gráfica de género
					let gender = self.results[index].gender;
					self.createGraphs(gender, 1, index);

					// Gráfica de edad
					let age = self.results[index].ageRange;
					self.createGraphs(age, 2, index);

					// Gráfica de estados
					let states = self.results[index].states;
					self.createGraphs(states, 3, index);

					// Gráfica de NSE
					let nse = self.results[index].nse;
					self.createGraphs(nse, 4, index);
				}

				if(ajaxReturn.perf) {
					self.renderData(true, index);
				} else {
					self.renderData(false, index);
				}

				// Eventos de gráficas
				self.graphsEvents();
			}
		});
	},

	// Recreación de gráfica de respuestas por preguntas de perfilamiento
	createProfileGraphs(value, index) {
		let self = this;

		// Datos de pregunta
		let labelsProfile = self.results[index][value].labels;
		let answers = self.results[index].answers;
		let labels = self.results[index].answers.labels;
		let data = self.results[index].data;

		// Cantidad de participantes
		let quantity = labelsProfile.length;

		// Colores por cantidad de elementos en perfilación
		let gradient = [];
		if(quantity == 2) {
			gradient = self.colorsHex;
		} else {
			if(self.typeColors == 1) {
				gradient = generateColors(self.colorsHex[0], self.colorsHex[1], quantity);
			} else {
				gradient = arrayColors(self.colorsHex, quantity);
			}
		}

		// Parámetro al que corresponde la perfilación
		let profile = '';
		switch(value) {
			case 'gender':
				profile = 'perf003';
				break;
			case 'ageRange':
				profile = 'perf002Range';
				break;
			case 'states':
				profile = 'perf001';
				break;
			case 'nse':
				profile = 'perf004';
				break;
		}

		// Creación de array de objetos separado por respuestas y variables de perfilación
		let result = [];
		let lSize = labels.length;
		for(let i = 0; i < lSize; i++) {
			let obj = {
				label: labels[i],
				subLabel: []
			};
			result.push(obj);

			let pSize = labelsProfile.length;
			for(let j = 0; j < pSize; j++) {
				let obj = {
					label: labelsProfile[j],
					value: 0
				};
				result[i].subLabel.push(obj);
			}
		}

		// Valores
		let aSize = data.length;
		let rSize = result.length;
		let slSize = result[0].subLabel.length;
		for(let i = 0; i < aSize; i++) {
			for(let j = 0; j < rSize; j++) {
				for(let n = 0; n < slSize; n++) {
					// Modificación para las preguntas tipo 'Y' Si/No
					if(data[i].answer == 'Y' && data[i].tipoPregunta == 'Y') {
						data[i].answer = 'YES';
					}
					if(data[i].answer == 'N' && data[i].tipoPregunta == 'Y') {
						data[i].answer = 'NO';
					}

					if(data[i].answer == result[j].label && data[i][profile] == result[j].subLabel[n].label) {
						result[j].subLabel[n].value++;
						continue;
					}
				}
			}
		}

		// Creación de array de objetos para gráfica
		let datasets = [];
		let pSize = labelsProfile.length;
		for(let i = 0; i < pSize; i++) {
			let obj = {
				label: labelsProfile[i],
				backgroundColor: gradient[i],
				data: []
			};
			datasets.push(obj);
		}

		// Valores en porcentaje
		for(let i = 0; i < rSize; i++) {
			// Total por respuesta en pregunta
			let newTotal = 0;
			for(let part in result[i].subLabel) {
				newTotal += result[i].subLabel[part].value;
			}

			for(let j = 0; j < slSize; j++) {
				// Porcentaje del total
				//let percent = (result[i].subLabel[j].value * 100 / self.participantsNumber[index]).toFixed(1);
				// Porcentaje de la pregunta
				let percent = (result[i].subLabel[j].value * 100 / newTotal).toFixed(1);
				if(parseInt(percent) == parseFloat(percent)) {
					percent = parseInt(percent);
				}

				datasets[j].data.push(percent);
			}
		}

		// Gráfica
		let options = '';
		if(typeof answers.options == 'object') {
			options = answers.options;
		} else {
			options = JSON.parse(answers.options);
		}

		options.title.display = true;
		options.title.text = pf.const.language.RSC443 + ': ' + self.participantsNumber[index];
		options.layout.padding.top = 0;
		options.title.padding = 15;
		options.legend.display = true;

		let ctx = document.getElementById('graphAnswersProfile' + index).getContext('2d');

		options['tooltips'] = {
			enabled: false
		};

		options['plugins'] = {
			datalabels: {
				color: 'black',
				font: {
					weight: 'bold',
					size: 16
				},
				anchor: 'end',
				align: 'end',
				formatter(value, context) {
					return value;
				}
			}
		};

		// Ancho de columnas
		options.scales.xAxes[0]['barPercentage'] = 0.5;

		// Ticks X en horizontal con salto de linea
		// Ancho del contenedor de la gráfica
		let divParentWidth = $('#graphAnswersProfile' + index).parent().css('width');
		// Número de columnas de la gráfica
		let nColumns = lSize;
		// Ancho del contenedor entre el número de columnas
		let maxwidth = Math.floor(parseInt(divParentWidth) / nColumns);
		// Ancho de la columna entre el tamaño de la fuente
		let maxwidthFont = Math.ceil(maxwidth / self.fontSize) + 2;

		// Etiquetas del eje X
		let xLabels = labels;
		// Comprobación de la primera palabra de los labels para ejecutar formato horizontal o diagonal
		let controlH = true;
		let xSize = xLabels.length;
		// Utilización de caracter de corte si lo hay
		if(self.splitCharacter != '') {
			for(let i = 0; i < xSize; i++) {
				if(xLabels[i] == null || xLabels[i] == undefined) {
					continue;
				}

				let indexCut = xLabels[i].toString().indexOf(self.splitCharacter);
				if(indexCut != -1) {
					xLabels[i] = xLabels[i].toString().slice(0, indexCut);
				}
			}
		}

		for(let i = 0; i < xSize; i++) {
			if(xLabels[i] == null || xLabels[i] == undefined) {
				continue;
			}

			let words = xLabels[i].toString().split(' ');
			let wSize = words.length;
			for(let j = 0; j < wSize; j++) {
				if(words[j].length > maxwidthFont) {
					controlH = false;
					break;
				}
			}
			if(!controlH) {
				break;
			}
		}

		if(controlH) {
			options.scales.xAxes[0].ticks['minRotation'] = 0;
			options.scales.xAxes[0].ticks['maxRotation'] = 0;

			options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
				let formmatedvalue = formatLabel(value, maxwidthFont);
				return formmatedvalue;
			}
		} else {
			options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
				if(value == null || value == undefined) {
					return value;
				} else if(value.length < 18) {
					return value;
				} else {
					return value.substr(0, 14) + '...';
				}
			};
		}

		Chart.defaults.global.defaultFontSize = 16;
		Chart.defaults.global.defaultFontFamily = 'Arial';

		// Radio de ángulos
		options.cornerRadius = 6;

		let graphElement = {
			// The type of chart we want to create
			type: 'bar',
			// The data for our dataset
			data: {
				datasets: datasets,
				labels: labels
			},
			// Configuration options go here
			options: options
		};

		// Guardado de gráficas de respuesta para reporte
		let dataArray = [];
		let dataGraph = datasets;
		let subLabels = [];

		for(let a = 0; a < dataGraph.length; a++) {
			dataArray.push(dataGraph[a].data);
			subLabels.push(dataGraph[a].label);
		}

		let obj = {
			type: 'grouped',
			colors: gradient,
			data: dataArray,
			labels: labels,
			subLabels: subLabels
		};

		self.graphsToReport[index].data = obj;

		let graph = new Chart(ctx, graphElement);

		self.answersChart[index] = graph;

		// Gráfica a pantalla completa
		$('#graphAnswersProfile' + index).off().on('click', function() {
			$('#graphicsViewer').show();
			let ctx = document.getElementById('graphViewer').getContext('2d');

			options.title.display = true;
			options.title.text = pf.const.language.RSC443 + ': ' + self.participantsNumber[index];
			options.layout.padding.top = 0;
			options.title.padding = 15;
			options.legend.display = true;

			options['tooltips'] = {
				enabled: false
			};

			options['plugins'] = {
				datalabels: {
					color: 'black',
					font: {
						weight: 'bold',
						size: 16
					},
					anchor: 'end',
					align: 'end',
					formatter(value, context) {
						return value;
					}
				}
			};

			Chart.defaults.global.defaultFontSize = 16;
			Chart.defaults.global.defaultFontFamily = 'Arial';

			// Ancho de columnas
			options.scales.xAxes[0]['barPercentage'] = 0.5;
			// Ticks X en horizontal con salto de linea
			// Ancho del contenedor de la gráfica
			let divParentWidth = $('#graphViewer').parent().css('width');
			// Número de columnas de la gráfica
			let nColumns = lSize;
			// Ancho del contenedor entre el número de columnas
			let maxwidth = Math.floor(parseInt(divParentWidth) / nColumns);
			// Ancho de la columna entre el tamaño de la fuente
			let maxwidthFont = Math.ceil(maxwidth / self.fontSize) + 2;

			// Etiquetas del eje X
			let xLabels = labels;
			// Comprobación de la primera palabra de los labes para ejecutar formato horizontal o diagonal
			let controlH = true;
			let xSize = xLabels.length;
			// Utilización de caracter de corte si lo hay
			if(self.splitCharacter != '') {
				for(let i = 0; i < xSize; i++) {
					if(xLabels[i] == null || xLabels[i] == undefined) {
						continue;
					}

					let indexCut = xLabels[i].toString().indexOf(self.splitCharacter);
					if(indexCut != -1) {
						xLabels[i] = xLabels[i].toString().slice(0, indexCut);
					}
				}
			}

			for(let i = 0; i < xSize; i++) {
				if(xLabels[i] == null || xLabels[i] == undefined) {
					continue;
				}

				let words = xLabels[i].toString().split(' ');
				let wSize = words.length;
				for(let j = 0; j < wSize; j++) {
					if(words[j].length > maxwidthFont) {
						controlH = false;
						break;
					}
				}
				if(!controlH) {
					break;
				}
			}

			if(controlH) {
				options.scales.xAxes[0].ticks['minRotation'] = 0;
				options.scales.xAxes[0].ticks['maxRotation'] = 0;

				options.scales.xAxes[0].ticks['callback'] = function(value, index, values) {
					let formmatedvalue = formatLabel(value, maxwidthFont);

					return formmatedvalue;
				}
			}

			if(screen.width < 380) {
				options.scales.xAxes[0].ticks.fontSize = 12;
			}

			// Radio de ángulos
			options.cornerRadius = 6;

			self.fullPageGraph = new Chart(ctx, {
				// The type of chart we want to create
				type: 'bar',
				// The data for our dataset
				data: {
					datasets: datasets,
					labels: labels
				},
				// Configuration options go here
				options: options
			});
		});
	},

	answersOrderDataTemplate(data, type) {
		let self = this;

		if (self.answersOrder == 'default' || self.answersOrder == undefined) return data;
		
		let orderType = '';
		let dataAux = data;

		switch (self.answersOrder) {
			case 'big_to_small':
				orderType = 'greater';
				break;
			case 'small_to_big':
				orderType = 'smaller';
				break;
		}

		let response;
		if (type == 'A' || type == 'B' || type == 'F') {
			response = self.sortWithSubquestions(data.datasets, orderType);
			self.setOrderSubquestions(data.datasets, response.indices);
		}
		else if (type == 'R') {
			return data;
		}
		else {
			response = self.sortWithIndexGeneric(data.datasets.data, orderType);
		}
		
		dataAux.labels = self.setOrderArray(response.indices, data.labels);
		dataAux.datasets.data = response.data;

		return dataAux;
	},

	setOrderSubquestions(array, indices) {
		let self = this;
		for (var i = 0; i < array.length; ++i) {
			array[i].data = self.setOrderArray(indices, array[i].data);
		}

		return array;
	},

	setOrderArray(indices, array) {
		let arrayResult = [];
		for (var i = 0; i < indices.length; i++) {
			arrayResult.push(array[indices[i]]);
		}

		return arrayResult;
	},

	sortWithIndexGeneric(array, type) {
		let indexedTest = array.map(function (e, i) { return { index: i, value: e } });

		if (type == 'greater') indexedTest.sort(function (x, y) { return x.value < y.value ? 1 : x.value == y.value ? 0 : -1 });
		else indexedTest.sort(function (x, y) { return x.value > y.value ? 1 : x.value == y.value ? 0 : -1 });

		let indices = indexedTest.map(function (e) { return e.index });

		return {
			data: indexedTest.map(function (e) { return e.value }),
			indices: indices
		}
	},

	singleSort(array, orderType) {
		if (orderType == 'greater') array.sort(function (x, y) { return x < y ? 1 : x == y ? 0 : -1 });
		else array.sort(function (x, y) { return x > y ? 1 : x == y ? 0 : -1 });

		return array;
	},

	sortWithSubquestions(array, orderType) {
		var self = this;
		let arrayAux = [];

		for (var i = 0; i < array.length; ++i) {
			for (var j = 0; j < array[i].data.length; ++j) {
				if (arrayAux[j] === undefined) {
					arrayAux[j] = 0;
				}
				arrayAux[j] += parseFloat(array[i].data[j]);
			}
		}

		for (var i = 0; i < arrayAux.length; ++i) {
			arrayAux[i] = parseFloat(arrayAux[i]).toFixed(1);
		}

		let result = arrayAux.map(i => parseFloat(i));

		return self.sortWithIndexGeneric(result, orderType);
	}


};