programas.directive.js 8.49 KB
(function() {
  'use strict';

  angular
    .module('dialoga')
    .directive('programaList', programaList);

  /** @ngInject */
  function programaList() {

    /** @ngInject */
    function ProgramaListController($scope, $element, $location, $filter, $log) {
      $log.debug('ProgramaListController');

      // alias
      var vm = this;

      // dependencies
      vm.$scope = $scope;
      vm.$element = $element;
      vm.$location = $location;
      vm.$filter = $filter;
      vm.$log = $log;
      vm.defaultLimit = 6;

      // initialization
      vm.init();
    }

    ProgramaListController.prototype.init = function () {
      var vm = this;

      if(!vm.article){
        vm.$log.warn('no article to display. Tip: use a ng-if before use this directive');
        return;
      }

      vm.categories = vm.article.categories;
      vm.programs = vm.article.children;
      vm.orderCriteries = [
        { label: 'Aleatório', name: 'aleatorio' },
        { label: 'Título', name: 'titulo' },
        { label: 'Tema', name: 'tema' }
      ];

      vm.filtredProgramList = vm.getFiltredPrograms();
      vm.search = vm.$location.search();

      // Add initial values for the filter
      vm.query = (vm.search && vm.search.filtro) ? vm.search.filtro : null;
      vm.limitTo = (vm.search && vm.search.limite) ? parseInt(vm.search.limite, 10) : vm.defaultLimit;
      vm.categoryFilter = (vm.search && vm.search.tema) ? vm.getCategoryBySlug(vm.search.tema) : null;
      vm.orderCriteria = (vm.search && vm.search.ordem) ? { name: vm.search.ordem } : null;
      vm.reverse = (vm.search && vm.search.reverso) ? true : false;

      if (!angular.equals({}, vm.search)) {
        var $el = vm.$element;
        angular.element('body').animate({scrollTop: $el.offset().top}, 'slow');
      }

      // update window location params
      vm.$scope.$watch('vm.query', function(newValue, oldValue){
        vm.search.filtro = newValue ? newValue : null;
        vm.$location.search('filtro', vm.search.filtro);
        vm.filtredProgramList = vm.getFiltredPrograms();
      });

      vm.$scope.$watch('vm.limitTo', function(newValue, oldValue){
        vm.search.limite = (newValue && newValue !== vm.defaultLimit)  ? newValue : null;
        vm.$location.search('limite', vm.search.limite);
        vm.filtredProgramList = vm.getFiltredPrograms();
      });

      vm.$scope.$watch('vm.categoryFilter', function(newValue, oldValue){
        vm.search.tema = newValue ? newValue.slug : null;
        vm.$location.search('tema', vm.search.tema);
        vm.filtredProgramList = vm.getFiltredPrograms();
      });

      vm.$scope.$watch('vm.orderCriteria', function(newValue, oldValue){
        vm.search.ordem = (newValue && newValue.name) ? newValue.name : null;
        vm.$location.search('ordem', vm.search.ordem);
        vm.filtredProgramList = vm.getFiltredPrograms();
      });

      vm.$scope.$watch('vm.reverse', function(newValue, oldValue){
        vm.search.reverso = newValue ? newValue : null;
        vm.$location.search('reverso', vm.search.reverso);
        vm.filtredProgramList = vm.getFiltredPrograms();
      });

    };

    ProgramaListController.prototype.resetFilterValues = function () {
      var vm = this;

      vm.query = null;
      vm.limitTo = vm.defaultLimit;
      vm.categoryFilter = null;
      vm.orderCriteria = null;
    };

    ProgramaListController.prototype.getIconClasses = function (category) {
      var vm = this;

      vm.$log.debug('[TODO] getIconClasses of category:', category);
      return 'glyphicon glyphicon-exclamation-sign';
    };

    ProgramaListController.prototype.getCategoryBySlug = function (categorySlug) {
      var vm = this;
      var result = null;

      angular.forEach(vm.categories, function (value, key){
        if(value.slug === categorySlug){
          result = value;
        }
      })
      return result;
    }

    ProgramaListController.prototype.filterByCategory = function (category, $event) {
      var vm = this;

      $event.stopPropagation();

      if(category !== vm.categoryFilter){

        // selected new filter
        vm.categoryFilter = category;
      }else{
        vm.categoryFilter = null;
      }
    };

    ProgramaListController.prototype.showAll = function ($event) {
      var vm = this;

      $event.stopPropagation();

      vm.resetFilterValues();
      vm.limitTo = vm.programs.length;
    };

    ProgramaListController.prototype.getFiltredPrograms = function () {
      var vm = this;

      var input = vm.programs;
      var output = input;
      var query = vm.query;
      var categoryFilter = vm.categoryFilter;
      var orderCriteria = vm.orderCriteria ? vm.orderCriteria : { name : 'aleatorio'};
      var filter = vm.$filter('filter');
      var orderBy = vm.$filter('orderBy');
      var limitTo = vm.$filter('limitTo');
      var limit = vm.limitTo ? vm.limitTo : 4;

      if(categoryFilter){
        output = _filterByCategory(output, categoryFilter);
      }

      if(query){
        output = filter(output, query, false);
      }

      switch(orderCriteria.name) {
        case 'titulo':
          output = orderBy(output, 'title', vm.reverse);
          break;
        case 'tema':
          output = orderBy(output, 'categories[0].name', vm.reverse);
          break;
        case 'more_participants':
          $log.info('Criteria not handled yet: ', orderCriteria);
          break;
        case 'aleatorio':
        default:
          // shuffling
          // if(!vm._isShuffled){
            output = vm.filterShuffle(output);
          //   vm._isShuffled = true;
          // }

          if(vm.reverse){
            output = output.slice().reverse();
          }

          break;
      }

      output = limitTo(output, limit);

      return output;
    };

    ProgramaListController.prototype.filterShuffle = function (input) {
      var result = [];
      var resultByCategory = {};

      // divide by categories
      for (var i = 0; i < input.length; i++) {
        var program = input[i];
        var categorySlug = program.categories[0].slug;

        if(!resultByCategory[categorySlug]){
          resultByCategory[categorySlug] = [];
        }

        resultByCategory[categorySlug].push(program);
      }

      // shuffle each array
      for (var prop in resultByCategory){
        if( resultByCategory.hasOwnProperty( prop ) ) {
          var categoryWithPrograms = resultByCategory[prop];
          resultByCategory[prop] = shuffle(categoryWithPrograms);
        }
      }

      // Concat all into result array
      // > while has program at Lists on resultByCategory
      var hasProgram = true;
      while (hasProgram) {

        var foundProgram = false;
        // each categoryList with array of program
        for (var prop in resultByCategory){

          if( resultByCategory.hasOwnProperty( prop ) ) {
            var categoryWithPrograms = resultByCategory[prop];

            if (categoryWithPrograms.length > 0 ) {
              var pivotProgram = categoryWithPrograms.pop();
              result.push(pivotProgram);
              foundProgram = true;
            }
          }
        }

        if(!foundProgram){
          hasProgram = false;
        }
      }

      return result;
    }

    var directive = {
      restrict: 'E',
      templateUrl: 'app/components/programas/programas.html',
      scope: {
        article: '='
      },
      controller: ProgramaListController,
      controllerAs: 'vm',
      bindToController: true
    };

    return directive;
  }

  function _filterByCategory (input, category){
    input = input || [];

    if(!category){
      // no filter
      return input;
    }

    var out = [];
    for (var i = 0; i < input.length; i++) {
      var program = input[i];
      if(program.categories[0].slug === category.slug){
        out.push(program);
      }
    }

    return out;
  }

  function _filterByCriteria (input, criteria, reverse){
    var vm = this;
    input = input || [];
    criteria = criteria || {};
    reverse = reverse || false;

    var out = [];



    return out;
  }

  // -> Fisher–Yates shuffle algorithm
  function shuffle (array) {
    var currentIndex = array.length, temporaryValue, randomIndex ;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

      // Pick a remaining element...
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;

      // And swap it with the current element.
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }

    return array;
  }


})();