diff --git a/apps/projects/static/projects/js/project_questions/services.js b/apps/projects/static/projects/js/project_questions/services.js index 8589db544..55cef3a3a 100644 --- a/apps/projects/static/projects/js/project_questions/services.js +++ b/apps/projects/static/projects/js/project_questions/services.js @@ -39,7 +39,92 @@ angular.module('project_questions') } } - function initCheckbox(values, parent) { + /* public methods */ + + service.init = function(project_id, summary_url) { + service.summary_url = summary_url; + + $http.get(urls.projects + project_id + '/').success(function(response) { + service.project = response; + + // get the question entity and the catalog (for the overview) + $http.get(urls.catalog + service.project.catalog + '/').success(function(response) { + future.catalog = response; + + service.initQuestionEntity($location.path().replace(/\//g,'')).then(function() { + service.catalog = angular.copy(future.catalog); + + // enable back/forward button of browser + $rootScope.$on('$locationChangeSuccess', function (scope, next, current) { + var entity_id = parseInt($location.path().replace(/\//g,''), 10); + if (entity_id !== service.entity.id) { + service.initQuestionEntity(entity_id); + } + }); + }); + }); + }); + }; + + service.initQuestionEntity = function(entity_id) { + + return service.fetchQuestionEntity(entity_id) + .then(function() { + return service.checkConditions(); + }) + .then(function() { + return service.fetchValues(); + }) + .then(function () { + // initialize values + service.initValues(); + + // copy entity + service.entity = angular.copy(future.entity); + + // copy values + if (service.entity.is_set) { + // copy valuesets + service.valuesets = angular.copy(future.valuesets); + + // activate fist valueset + if (service.valuesets.length > 0) { + service.values = service.valuesets[0].values; + } else { + service.values = null; + } + } else { + // copy values + service.values = angular.copy(future.values); + } + + // focus the first field + if (service.values) { + var first_question = service.entity.questions[0]; + + if (first_question.attribute.is_collection) { + service.focusField(first_question.attribute.id, 0); + } else { + service.focusField(first_question.attribute.id); + } + } + + // set browser location, scroll to top and set back flag + $location.path('/' + service.entity.id + '/'); + $window.scrollTo(0, 0); + back = false; + + }, function () { + // navigate to another question entity when checkConditions returned $q.reject + if (back) { + return service.initQuestionEntity(future.entity.prev); + } else { + return service.initQuestionEntity(future.entity.next); + } + }); + }; + + service.initCheckbox = function(values, parent) { var checkbox_values = []; angular.forEach(parent.attribute.options, function(option) { @@ -61,72 +146,9 @@ angular.module('project_questions') }); return checkbox_values; - } - - function initWidget(question, value) { - - if (question.widget_type === 'radio') { - value.input = {}; - - angular.forEach(question.attribute.options, function(option) { - if (option.additional_input) { - if (value.option === option.id) { - value.input[option.id] = value.text; - } else { - value.input[option.id] = ''; - } - } - }); - } - - if (question.widget_type === 'range') { - if (!value.text) { - value.text = '0'; - } - } - - if (question.widget_type === 'date') { - $timeout(function() { - $('.datepicker').datetimepicker({ - format: 'YYYY-MM-DD' - }).on('dp.change', function () { - $('.datepicker input').trigger('input'); - }); - }); - } - } - - function checkCondition(condition, value) { - if (condition.relation === 'eq') { - if (angular.isDefined(condition.target_option) && condition.target_option !== null) { - return (condition.target_option == value.option); - } else if (angular.isDefined(condition.target_text) && condition.target_text !== null) { - return (condition.target_text == value.text); - } else { - return true; - } - } else if (condition.relation === 'neq') { - if (angular.isDefined(condition.target_option) && condition.target_option !== null) { - return (condition.target_option != value.option); - } else if (angular.isDefined(condition.target_text) && condition.target_text !== null) { - return (condition.target_text != value.text); - } else { - return true; - } - } - } - - function focusField(attribute_id, index) { - $timeout(function() { - if (angular.isDefined(index)) { - angular.element('#id_' + attribute_id.toString() + '_' + index.toString()).focus(); - } else { - angular.element('#id_' + attribute_id.toString()).focus(); - } - }); - } + }; - function fetchQuestionEntity(entity_id) { + service.fetchQuestionEntity = function(entity_id) { var promise; // fetch the current (or the first) question entity from the server @@ -152,9 +174,9 @@ angular.module('project_questions') future.entity.help = $sce.trustAsHtml(future.entity.help); } }); - } + }; - function checkConditions() { + service.checkConditions = function() { if (future.entity.attribute_entity.conditions.length) { var promises = []; @@ -188,9 +210,9 @@ angular.module('project_questions') } else { return $q.when(); } - } + }; - function fetchValues() { + service.fetchValues = function() { future.values = {}; if (future.entity.is_set) { @@ -262,9 +284,9 @@ angular.module('project_questions') future.values[question.attribute.id] = response; }); } - } + }; - function initValues() { + service.initValues = function() { if (future.entity.is_set) { // loop over valuesets and questions to init values and widgets angular.forEach(future.valuesets, function(valueset) { @@ -274,7 +296,7 @@ angular.module('project_questions') if (angular.isUndefined(valueset.values[question.attribute.id])) { valueset.values[question.attribute.id] = []; } - valueset.values[question.attribute.id] = initCheckbox(valueset.values[question.attribute.id],question); + valueset.values[question.attribute.id] = service.initCheckbox(valueset.values[question.attribute.id],question); } else { if (angular.isUndefined(valueset.values[question.attribute.id])) { valueset.values[question.attribute.id] = [factory('values', question)]; @@ -282,7 +304,7 @@ angular.module('project_questions') } angular.forEach(valueset.values[question.attribute.id], function(value) { - initWidget(question, value); + service.initWidget(question, value); }); }); }); @@ -290,7 +312,7 @@ angular.module('project_questions') var question = future.entity.questions[0]; if (question.widget_type === 'checkbox') { - future.values[question.attribute.id] = initCheckbox(future.values[question.attribute.id], question + future.values[question.attribute.id] = service.initCheckbox(future.values[question.attribute.id], question ); } else { if (future.values[question.attribute.id].length < 1) { @@ -299,24 +321,110 @@ angular.module('project_questions') } angular.forEach(future.values[question.attribute.id], function(value) { - initWidget(question, value); + service.initWidget(question, value); }); } - } + }; + + service.initWidget = function(question, value) { - function focusFirstField() { - if (service.values) { - var first_question = service.entity.questions[0]; + if (question.widget_type === 'radio') { + value.input = {}; - if (first_question.attribute.is_collection) { - focusField(first_question.attribute.id, 0); + angular.forEach(question.attribute.options, function(option) { + if (option.additional_input) { + if (value.option === option.id) { + value.input[option.id] = value.text; + } else { + value.input[option.id] = ''; + } + } + }); + } + + if (question.widget_type === 'range') { + if (!value.text) { + value.text = '0'; + } + } + + if (question.widget_type === 'date') { + $timeout(function() { + $('.datepicker').datetimepicker({ + format: 'YYYY-MM-DD' + }).on('dp.change', function () { + $('.datepicker input').trigger('input'); + }); + }); + } + }; + + service.checkCondition = function(condition, value) { + if (condition.relation === 'eq') { + if (angular.isDefined(condition.target_option) && condition.target_option !== null) { + return (condition.target_option == value.option); + } else if (angular.isDefined(condition.target_text) && condition.target_text !== null) { + return (condition.target_text == value.text); } else { - focusField(first_question.attribute.id); + return true; + } + } else if (condition.relation === 'neq') { + if (angular.isDefined(condition.target_option) && condition.target_option !== null) { + return (condition.target_option != value.option); + } else if (angular.isDefined(condition.target_text) && condition.target_text !== null) { + return (condition.target_text != value.text); + } else { + return true; } } - } + }; + + service.focusField = function(attribute_id, index) { + $timeout(function() { + if (angular.isDefined(index)) { + angular.element('#id_' + attribute_id.toString() + '_' + index.toString()).focus(); + } else { + angular.element('#id_' + attribute_id.toString()).focus(); + } + }); + }; + + service.getValueSetIndex = function() { + var filter = $filter('filter')(service.valuesets, function(valueset, index, array) { + valueset.index = index; + return valueset.values == service.values; + }); + + if (angular.isDefined(filter[0])) { + return filter[0].index; + } else { + return null; + } + }; + + service.getPrevActiveValueSetIndex = function(index) { + var prev_active_index = null; + for (var i = index - 1; i >= 0; i--) { + if (angular.isUndefined(service.valuesets[i].removed) || !service.valuesets[i].removed) { + prev_active_index = i; + break; + } + } + return prev_active_index; + }; + + service.getNextActiveValueSetIndex = function(index) { + var next_active_index = null; + for (i = index + 1; i < service.valuesets.length; i++) { + if (angular.isUndefined(service.valuesets[i].removed) || !service.valuesets[i].removed) { + next_active_index = i; + break; + } + } + return next_active_index; + }; - function storeValue(value, collection_index, set_index) { + service.storeValue = function(value, collection_index, set_index) { var promise; if (value.removed) { @@ -343,9 +451,9 @@ angular.module('project_questions') } return promise; - } + }; - function storeValues() { + service.storeValues = function() { var promises = []; if (service.entity.is_set) { @@ -354,7 +462,7 @@ angular.module('project_questions') angular.forEach(service.valuesets, function(valueset) { angular.forEach(service.entity.attributes, function(attribute_id) { angular.forEach(valueset.values[attribute_id], function(value, collection_index) { - promises.push(storeValue(value, collection_index, set_index)); + promises.push(service.storeValue(value, collection_index, set_index)); }); }); @@ -365,123 +473,12 @@ angular.module('project_questions') } else { angular.forEach(service.entity.attributes, function(attribute_id) { angular.forEach(service.values[attribute_id], function(value, collection_index) { - promises.push(storeValue(value, collection_index, 0)); + promises.push(service.storeValue(value, collection_index, 0)); }); }); } return $q.all(promises); - } - - function getValueSetIndex() { - var filter = $filter('filter')(service.valuesets, function(valueset, index, array) { - valueset.index = index; - return valueset.values == service.values; - }); - - if (angular.isDefined(filter[0])) { - return filter[0].index; - } else { - return null; - } - } - - function getPrevActiveValueSetIndex(index) { - var prev_active_index = null; - for (var i = index - 1; i >= 0; i--) { - if (angular.isUndefined(service.valuesets[i].removed) || !service.valuesets[i].removed) { - prev_active_index = i; - break; - } - } - return prev_active_index; - } - - function getNextActiveValueSetIndex(index) { - var next_active_index = null; - for (i = index + 1; i < service.valuesets.length; i++) { - if (angular.isUndefined(service.valuesets[i].removed) || !service.valuesets[i].removed) { - next_active_index = i; - break; - } - } - return next_active_index; - } - - /* public methods */ - - service.init = function(project_id, summary_url) { - service.summary_url = summary_url; - - $http.get(urls.projects + project_id + '/').success(function(response) { - service.project = response; - - // get the question entity and the catalog (for the overview) - $http.get(urls.catalog + service.project.catalog + '/').success(function(response) { - future.catalog = response; - - service.initQuestionEntity($location.path().replace(/\//g,'')).then(function() { - service.catalog = angular.copy(future.catalog); - - // enable back/forward button of browser - $rootScope.$on('$locationChangeSuccess', function (scope, next, current) { - var entity_id = parseInt($location.path().replace(/\//g,''), 10); - if (entity_id !== service.entity.id) { - service.initQuestionEntity(entity_id); - } - }); - }); - }); - }); - }; - - service.initQuestionEntity = function(entity_id) { - - return fetchQuestionEntity(entity_id) - .then(function() { - return checkConditions(); - }) - .then(function() { - return fetchValues(); - }) - .then(function() { - return initValues(); - }) - .then(function() { - focusFirstField(); - }) - .then(function () { - // copy entity - service.entity = angular.copy(future.entity); - - if (service.entity.is_set) { - // copy valuesets - service.valuesets = angular.copy(future.valuesets); - - // activate fist valueset - if (service.valuesets.length > 0) { - service.values = service.valuesets[0].values; - } else { - service.values = null; - } - } else { - // copy values - service.values = angular.copy(future.values); - } - - // set browser location, scroll to top and set back flag - $location.path('/' + service.entity.id + '/'); - $window.scrollTo(0, 0); - back = false; - - }, function () { - // // navigate to another question entity when checkConditions returned $q.reject - // if (back) { - // return service.initQuestionEntity(future.entity.prev); - // } else { - // return service.initQuestionEntity(future.entity.next); - // } - }); }; service.prev = function() { @@ -500,18 +497,6 @@ angular.module('project_questions') service.jump = function(section, subsection, entity) { var next_entity_id = null; - // angular.forEach(service.catalog.sections, function (catalog_section) { - // catalog_section.active = (catalog_section === section); - - // angular.forEach(catalog_section.subsections, function (catalog_subsection) { - // catalog_subsection.active = (catalog_subsection === subsection); - - // angular.forEach(catalog_subsection.entities, function (catalog_entity) { - // catalog_entity.active = (catalog_entity === entity); - // }); - // }); - // }); - if (angular.isUndefined(subsection)) { next_entity_id = section.subsections[0].entities[0].id; } else if (angular.isUndefined(entity)) { @@ -526,12 +511,12 @@ angular.module('project_questions') }; service.save = function(proceed) { - storeValues().then(function() { + service.storeValues().then(function() { if (angular.isDefined(proceed) && proceed) { if (service.entity.is_set && service.entity.attribute_entity.is_collection) { - var index = getValueSetIndex(); + var index = service.getValueSetIndex(); - var new_index = getNextActiveValueSetIndex(index); + var new_index = service.getNextActiveValueSetIndex(index); if (new_index === null) { if (service.entity.next === null) { $window.location = service.summary_url; @@ -563,10 +548,10 @@ angular.module('project_questions') service.values[question.attribute.id].push(value); } - initWidget(question, value); + service.initWidget(question, value); // focus the new value - focusField(question.attribute.id, service.values[question.attribute.id].length - 1); + service.focusField(question.attribute.id, service.values[question.attribute.id].length - 1); }; service.removeValue = function(attribute_id, index) { @@ -650,7 +635,7 @@ angular.module('project_questions') service.removeValueSet = function() { // find current valueset - var index = getValueSetIndex(); + var index = service.getValueSetIndex(); // flag it for removal service.valuesets[index].removed = true; @@ -663,11 +648,11 @@ angular.module('project_questions') }); // look for an non-removed valueset before the current one - var new_index = getPrevActiveValueSetIndex(index); + var new_index = service.getPrevActiveValueSetIndex(index); // if no was found, look for an non-removed valueset after the current one if (new_index === null) { - new_index = getNextActiveValueSetIndex(index); + new_index = service.getNextActiveValueSetIndex(index); } // if there is still now new_index, set service.values to null, otherwise activate the valueset