Rater.js - Половина вместо полных звезд для прогресса - PullRequest
0 голосов
/ 03 ноября 2019

Хай там! Я планирую использовать Rater.js в своем проекте, и до сих пор я доволен библиотекой. Есть только одна проблема, которую я не могу решить в одиночку. Pls. взгляните на

https://jsfiddle.net/herbert_hinterberger/r1cgnpt3/.

В самом низу скрипта я определил step_size: 1.

(".rating").rate();

//or for example
var options = {
  max_value: 5,
  step_size: 1,
}

Теперь я ожидаю, чтопри наведении курсора на звезды выбираются только полные звезды. Но все же, пол звездочки тоже выбраны. Любая идея, что я делаю неправильно?

Ответы [ 2 ]

1 голос
/ 03 ноября 2019

В вашем примере кода вы звоните $(".rating").rate(); без параметров (номер строки 499). Прокомментировав это, вы получите что-то вроде ниже

/*
 * A highly customizable rating widget that supports images, utf8 glyphs and other html elements!
 * https://github.com/auxiliary/rater
 */
; (function ($, window) {
  $.fn.textWidth = function () {
    var html_calc = $('<span>' + $(this).html() + '</span>');
    html_calc.css('font-size', $(this).css('font-size')).hide();
    html_calc.prependTo('body');
    var width = html_calc.width();
    html_calc.remove();

    if (width == 0) {
      var total = 0;
      $(this).eq(0).children().each(function () {
        total += $(this).textWidth();
      });
      return total;
    }
    return width;
  };

  $.fn.textHeight = function () {
    var html_calc = $('<span>' + $(this).html() + '</span>');
    html_calc.css('font-size', $(this).css('font-size')).hide();
    html_calc.prependTo('body');
    var height = html_calc.height();
    html_calc.remove();
    return height;
  };

  /*
   * IE8 doesn't support isArray!
   */
  Array.isArray = function (obj) {
    return Object.prototype.toString.call(obj) === "[object Array]";
  };

  /*
   * Utf-32 isn't supported by default, so we have to use Utf-8 surrogates
   */
  String.prototype.getCodePointLength = function () {
    return this.length - this.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length + 1;
  };

  String.fromCodePoint = function () {
    var chars = Array.prototype.slice.call(arguments);
    for (var i = chars.length; i-- > 0;) {
      var n = chars[i] - 0x10000;
      if (n >= 0)
        chars.splice(i, 1, 0xD800 + (n >> 10), 0xDC00 + (n & 0x3FF));
    }
    return String.fromCharCode.apply(null, chars);
  };

  /*
   * Starting the plugin itself
   */
  $.fn.rate = function (options) {
    if (options === undefined || typeof options === 'object') {
      return this.each(function () {
        if (!$.data(this, "rate")) {
          $.data(this, "rate", new Rate(this, options));
        }
      });
    }
    else if (typeof options === 'string') {
      var args = arguments;
      var returns;
      this.each(function () {
        var instance = $.data(this, "rate");
        if (instance instanceof Rate && typeof instance[options] === 'function') {
          returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
        }
        if (options === 'destroy') {
          // Unbind all events and empty the plugin data from instance
          $(instance.element).off();
          $.data(this, 'rate', null);
        }
      });

      return returns !== undefined ? returns : this;
    }
  };

  function Rate(element, options) {
    this.element = element;
    this.settings = $.extend({}, $.fn.rate.settings, options);
    this.set_faces = {}; // value, symbol pairs
    this.build();
  }

  Rate.prototype.build = function () {
    this.layers = {};
    this.value = 0;
    this.raise_select_layer = false;

    if (this.settings.initial_value) {
      this.value = this.settings.initial_value;
    }
    if ($(this.element).attr("data-rate-value")) {
      this.value = $(this.element).attr("data-rate-value");
    }

    /*
     * Calculate the selected width based on the initial value
     */
    var selected_width = this.value / this.settings.max_value * 100;

    /*
     * Let's support single strings as symbols as well as objects
     */
    if (typeof this.settings.symbols[this.settings.selected_symbol_type] === 'string') {
      var symbol = this.settings.symbols[this.settings.selected_symbol_type];
      this.settings.symbols[this.settings.selected_symbol_type] = {};
      this.settings.symbols[this.settings.selected_symbol_type]['base'] = symbol;
      this.settings.symbols[this.settings.selected_symbol_type]['selected'] = symbol;
      this.settings.symbols[this.settings.selected_symbol_type]['hover'] = symbol;
    }

    /*
     * Making the three main layers (base, select, hover)
     */
    var base_layer = this.addLayer("base-layer", 100, this.settings.symbols[
      this.settings.selected_symbol_type]["base"], true);

    var select_layer = this.addLayer("select-layer", selected_width,
      this.settings.symbols[this.settings.selected_symbol_type]["selected"], true);

    var hover_layer = this.addLayer("hover-layer", 0, this.settings.symbols[
      this.settings.selected_symbol_type]["hover"], false);

    /* var face_layer = this.addLayer("face-layer", 1, this.settings
        .symbols[this.settings.face_layer_symbol_type][0], true); */

    this.layers["base_layer"] = base_layer;
    this.layers["select_layer"] = select_layer;
    this.layers["hover_layer"] = hover_layer;

    /*
     * Bind the container to some events
     */
    $(this.element).on("mousemove", $.proxy(this.hover, this));
    $(this.element).on("click", $.proxy(this.select, this));
    $(this.element).on("mouseleave", $.proxy(this.mouseout, this));

    /*
     * Set the main element as unselectable
     */
    $(this.element).css({
      "-webkit-touch-callout": "none",
      "-webkit-user-select": "none",
      "-khtml-user-select": "none",
      "-moz-user-select": "none",
      "-ms-user-select": "none",
      "user-select": "none",
    });

    /*
     * Update custom input field if provided
     */
    if (this.settings.hasOwnProperty("update_input_field_name")) {
      this.settings.update_input_field_name.val(this.value);
    }
  }

  /*
   * Function to add a layer
   */
  Rate.prototype.addLayer = function (layer_name, visible_width, symbol, visible) {
    var layer_body = "<div>";
    for (var i = 0; i < this.settings.max_value; i++) {
      if (Array.isArray(symbol)) {
        if (this.settings.convert_to_utf8) {
          symbol[i] = String.fromCodePoint(symbol[i]);
        }
        layer_body += "<span>" + (symbol[i]) + "</span>";
      }
      else {
        if (this.settings.convert_to_utf8) {
          symbol = String.fromCodePoint(symbol);
        }
        layer_body += "<span>" + symbol + "</span>";
      }
    }
    layer_body += "</div>";
    var layer = $(layer_body).addClass("rate-" + layer_name).appendTo(this.element);

    $(layer).css({
      width: visible_width + "%",
      height: $(layer).children().eq(0).textHeight(),
      overflow: 'hidden',
      position: 'absolute',
      top: 0,
      display: visible ? 'block' : 'none',
      'white-space': 'nowrap'
    });
    $(this.element).css({
      width: $(layer).textWidth() + "px",
      height: $(layer).height(),
      position: 'relative',
      cursor: this.settings.cursor,
    });

    return layer;
  }

  Rate.prototype.updateServer = function () {
    if (this.settings.url != undefined) {
      $.ajax({
        url: this.settings.url,
        type: this.settings.ajax_method,
        data: $.extend({}, { value: this.getValue() }, this.settings.additional_data),
        success: $.proxy(function (data) {
          $(this.element).trigger("updateSuccess", [data]);
        }, this),
        error: $.proxy(function (jxhr, msg, err) {
          $(this.element).trigger("updateError", [jxhr, msg, err]);
        }, this)
      });
    }
  }

  Rate.prototype.getValue = function () {
    return this.value;
  }

  Rate.prototype.hover = function (ev) {
    var pad = parseInt($(this.element).css("padding-left").replace("px", ""));
    var x = ev.pageX - $(this.element).offset().left - pad;
    var val = this.toValue(x, true);

    if (val != this.value) {
      this.raise_select_layer = false;
    }

    if (!this.raise_select_layer && !this.settings.readonly) {
      var visible_width = this.toWidth(val);
      this.layers.select_layer.css({ display: 'none' });
      if (!this.settings.only_select_one_symbol) {
        this.layers.hover_layer.css({
          width: visible_width + "%",
          display: 'block'
        });
      }
      else {
        var index_value = Math.floor(val);
        this.layers.hover_layer.css({
          width: "100%",
          display: 'block'
        });
        this.layers.hover_layer.children("span").css({
          visibility: 'hidden',
        });
        this.layers.hover_layer.children("span").eq(index_value != 0 ? index_value - 1 : 0).css({
          visibility: 'visible',
        });
      }
    }
  }

  /*
   * Event for when a rating has been selected (clicked)
   */
  Rate.prototype.select = function (ev) {
    if (!this.settings.readonly) {
      var old_value = this.getValue();
      var pad = parseInt($(this.element).css("padding-left").replace("px", ""));
      var x = ev.pageX - $(this.element).offset().left - pad;
      var selected_width = this.toWidth(this.toValue(x, true));
      this.setValue(this.toValue(selected_width));
      this.raise_select_layer = true;
    }
  }

  Rate.prototype.mouseout = function () {
    this.layers.hover_layer.css({ display: 'none' });
    this.layers.select_layer.css({ display: 'block' });
  }

  /*
   * Takes a width (px) and returns the value it resembles
   */
  Rate.prototype.toWidth = function (val) {
    return val / this.settings.max_value * 100;
  }

  /*
   * Takes a value and calculates the width of the selected/hovered layer
   */
  Rate.prototype.toValue = function (width, in_pixels) {
    var val;
    if (in_pixels) {
      val = width / this.layers.base_layer.textWidth() * this.settings.max_value;
    }
    else {
      val = width / 100 * this.settings.max_value;
    }

    // Make sure the division doesn't cause some small numbers added by
    // comparing to a small arbitrary number.
    var temp = val / this.settings.step_size;
    if (temp - Math.floor(temp) < 0.00005) {
      val = Math.round(val / this.settings.step_size) * this.settings.step_size;
    }
    val = (Math.ceil(val / this.settings.step_size)) * this.settings.step_size;
    val = val > this.settings.max_value ? this.settings.max_value : val;
    return val;
  }

  Rate.prototype.getElement = function (layer_name, index) {
    return $(this.element).find(".rate-" + layer_name + " span").eq(index - 1);
  }

  Rate.prototype.getLayers = function () {
    return this.layers;
  }

  Rate.prototype.setFace = function (value, face) {
    this.set_faces[value] = face;
  }

  Rate.prototype.setAdditionalData = function (data) {
    this.settings.additional_data = data;
  }

  Rate.prototype.getAdditionalData = function () {
    return this.settings.additional_data;
  }

  Rate.prototype.removeFace = function (value) {
    delete this.set_faces[value];
  }

  Rate.prototype.setValue = function (value) {
    if (!this.settings.readonly) {
      if (value < 0) {
        value = 0;
      }
      else if (value > this.settings.max_value) {
        value = this.settings.max_value;
      }

      var old_value = this.getValue();
      this.value = value;

      /*
       * About to change event, should support prevention later
       */
      var change_event = $(this.element).trigger("change", {
        "from": old_value,
        "to": this.value
      });

      /*
       * Set/Reset faces
       */
      $(this.element).find(".rate-face").remove();
      $(this.element).find("span").css({
        visibility: 'visible'
      });
      var index_value = Math.ceil(this.value);
      if (this.set_faces.hasOwnProperty(index_value)) {
        var face = "<div>" + this.set_faces[index_value] + "</div>";
        var base_layer_element = this.getElement('base-layer', index_value);
        var select_layer_element = this.getElement('select-layer', index_value);
        var hover_layer_element = this.getElement('hover-layer', index_value);

        var left_pos = base_layer_element.textWidth() * (index_value - 1)
          + (base_layer_element.textWidth() - $(face).textWidth()) / 2;

        $(face).appendTo(this.element).css({
          display: 'inline-block',
          position: 'absolute',
          left: left_pos,
        }).addClass("rate-face");

        base_layer_element.css({
          visibility: 'hidden'
        });
        select_layer_element.css({
          visibility: 'hidden'
        });
        hover_layer_element.css({
          visibility: 'hidden'
        });
      }

      /*
       * Set styles based on width and value
       */
      if (!this.settings.only_select_one_symbol) {
        var width = this.toWidth(this.value);
        this.layers.select_layer.css({
          display: 'block',
          width: width + "%",
          height: this.layers.base_layer.css("height")
        });
        this.layers.hover_layer.css({
          display: 'none',
          height: this.layers.base_layer.css("height")
        });
      }
      else {
        var width = this.toWidth(this.settings.max_value);
        this.layers.select_layer.css({
          display: 'block',
          width: width + "%",
          height: this.layers.base_layer.css("height")
        });
        this.layers.hover_layer.css({
          display: 'none',
          height: this.layers.base_layer.css("height")
        });
        this.layers.select_layer.children("span").css({
          visibility: 'hidden',
        });
        this.layers.select_layer.children("span").eq(index_value != 0 ? index_value - 1 : 0).css({
          visibility: 'visible',
        });
      }

      // Update the data-rate-value attribute
      $(this.element).attr("data-rate-value", this.value);

      if (this.settings.change_once) {
        this.settings.readonly = true;
      }
      this.updateServer();

      /*
       * After change event
       */
      var change_event = $(this.element).trigger("afterChange", {
        "from": old_value,
        "to": this.value
      });

      /*
       * Update custom input field if provided
       */
      if (this.settings.hasOwnProperty("update_input_field_name")) {
        this.settings.update_input_field_name.val(this.value);
      }

    }
  }

  Rate.prototype.increment = function () {
    this.setValue(this.getValue() + this.settings.step_size);
  }

  Rate.prototype.decrement = function () {
    this.setValue(this.getValue() - this.settings.step_size);
  }

  $.fn.rate.settings = {
    max_value: 5,
    step_size: 0.5,
    initial_value: 0,
    symbols: {
      utf8_star: {
        base: '\u2606',
        hover: '\u2605',
        selected: '\u2605',
      },
      utf8_hexagon: {
        base: '\u2B21',
        hover: '\u2B22',
        selected: '\u2B22',
      },
      hearts: '&hearts;',
      fontawesome_beer: '<i class="fa fa-beer"></i>',
      fontawesome_star: {
        base: '<i class="fa fa-star-o"></i>',
        hover: '<i class="fa fa-star"></i>',
        selected: '<i class="fa fa-star"></i>',
      },
      utf8_emoticons: {
        base: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
        hover: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
        selected: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
      },
    },
    selected_symbol_type: 'utf8_star', // Must be a key from symbols
    convert_to_utf8: false,
    cursor: 'default',
    readonly: false,
    change_once: false, // Determines if the rating can only be set once
    only_select_one_symbol: false, // If set to true, only selects the hovered/selected symbol and nothing prior to it
    ajax_method: 'POST',
    additional_data: {}, // Additional data to send to the server
    //update_input_field_name = some input field set by the user
  };

}(jQuery, window));


//$(".rating").rate();

//or for example
var options = {
  max_value: 5,
  step_size: 1,
}
$(".rating").rate(options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rating" data-rate-value=6></div>
0 голосов
/ 03 ноября 2019

Вы указываете параметры на более ранней стадии в своем коде.

См. Здесь:

$.fn.rate.settings = {
    max_value: 5,
    step_size: 0.5,

Я протестировал в вашей скрипте, и он работает при обновлении до 1 step_size.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...