Source: directives/invenioSearchRange.js

/*
 * This file is part of Invenio.
 * Copyright (C) 2017 CERN.
 *
 * Invenio is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * Invenio is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Invenio; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 *
 * In applying this license, CERN does not
 * waive the privileges and immunities granted to it by virtue of its status
 * as an Intergovernmental Organization or submit itself to any jurisdiction.
 */

/**
  * @ngdoc directive
  * @name invenioSearchRange
  * @description
  *    The invenioSearchRange directive
  * @namespace invenioSearchRange
  * @example
  *    Usage:
  *    <div style="width: 220px; margin: 0 auto;" id="year_hist"></div>
  *    <div style="width: 220px; margin: 0 auto;" id="year_select"></div>
  */
function invenioSearchRange(invenioSearchRangeFactory, $window) {

  // Functions

  /**
    * Force apply the attributes to the scope
    * @memberof invenioSearchRange
    * @param {service} scope -  The scope of this element.
    * @param {service} element - Element that this directive is assigned to.
    * @param {service} attrs - Attribute of this element.
    * @param {invenioSearchController} vm - Invenio search controller.
    */
  function link(scope, element, attrs, vm) {

    // Default options for histogram
    var options = {
      height: 70,
      name: 'years',
      histogramId: '#hist',
      selectionId: '#select',
      margins: {
        left: 10,
        right: 10,
        top: 10,
        bottom: 0
      },
      barColor: '#2c3e50',
      selectColor: '#3498db',
      lineColor: '#ccc',
      circleColor: 'white',
      padding: 2
    };

    var getRangeWidth = function() {
      var elem = d3.select(options.histogramId).node();
      return elem.getBoundingClientRect().width;
    };

    angular.merge(options, angular.fromJson(attrs.options));

    var responsive = !options.width;
    if (responsive) {
      var initialWidth = getRangeWidth();
    }

    /**
      * Handle the change of the selected range
      * @memberof link
      * @param {int} from - The first element of the range
      * @param {int} to - The last element of the range
        */
    function changeUserSelection(from, to) {
      if (!isNaN(from) && !isNaN(to)) {
        // Update Args
        var params = {};
        var rangeParams = {
          from: from,
          to: to
        };

        var newRange = rangeParams.from + '--' + rangeParams.to;
        params[options.name] = newRange;
        // Request a new search
        scope.$broadcast('invenio.search.params.change', params);
      }
    }

    /**
      * Render a new histogram
      * @memberof link
      */
    function updateRange() {
      // Don't refresh the histogram if the update is a result of
      // moving the histogram bar
      if (responsive) {
        options.width = getRangeWidth() || initialWidth;
      }

      if (vm.invenioSearchResults.aggregations) {
        var buckets = vm.invenioSearchResults.aggregations[options.name].buckets;
        if (buckets.length > 0) {
          if (vm.invenioSearchArgs[options.name]) {
            // Parse URL parameters
            var args = vm.invenioSearchArgs[options.name].split('--');
            var rMin = +args[0];
            var rMax = (args.length === 2) ? +args[1] : rMin;
            if (!isNaN(rMin) && !isNaN(rMax)) {
              options.selectionRange = {
                min: rMin,
                max: rMax
              };
            }
          }
          invenioSearchRangeFactory(
            options.histogramId,
            options.selectionId,
            buckets,
            options,
            changeUserSelection
          );
        }
      }
    }

    scope.$on('invenio.search.finished', updateRange);
    if (responsive) {
      angular.element($window).bind('resize', updateRange);
    }
  }

  /**
    * Choose template for search loading
    * @memberof invenioSearchSelectBox
    * @param {service} element - Element that this direcive is assigned to.
    * @param {service} attrs - Attribute of this element.
    * @example
    *    Minimal template `template.html` usage
    *     <div id="hist"></div>
    *     <div id="select"></div>
    */
  function templateUrl(element, attrs) {
    return attrs.template;
  }

  ////////////

  return {
    restrict: 'AE',
    require: '^invenioSearch',
    templateUrl: templateUrl,
    link: link,
  };
}

invenioSearchRange.$inject = ['invenioSearchRangeFactory', '$window'];

angular.module('invenioSearch.directives')
  .directive('invenioSearchRange', invenioSearchRange);