Расширение всплывающей подсказки пользовательского интерфейса JQuery с использованием options.items и заголовка - PullRequest
8 голосов
/ 25 апреля 2019

Я написал следующее расширение для виджета всплывающей подсказки JQuery UI , которое позволяет всплывающей подсказке иметь контекст при получении ее содержимого из HTML-кода HTMLElement. Тем не менее, у меня есть жестко закодированный атрибут title, но я бы хотел использовать любой атрибут, определенный в options.items . Например, если они хотят, чтобы во всплывающей подсказке использовался тег alt, расширение заполняет этот атрибут содержимым html.

Также я ищу способ jquery ui для правильного экранирования contentId конкатенации строк

$(function() {
    (function() {
        var cache = {};
        $.widget("custom.tooltipContent", $.ui.tooltip, {
            _init: function() {
                this._super();

                this.options.content = function() {
                    return $(this).attr("title");
                };

                this.element.attr("title", function() {
                    var contentId = $(this).attr("data-tooltip-content");

                    if (!cache[contentId]) {
                        cache[contentId] = $("[data-tooltip-content-id=" + contentId + "]").remove().html();
                    }

                    return cache[contentId];
                });
            }
        });
    })();
});

http://jsfiddle.net/5d7sqx89/1/

Ответы [ 2 ]

4 голосов
/ 22 июня 2019

Вместо опций заголовка или предметов я бы предложил вам использовать новую опцию. Вы можете назвать это itemsData. Это для того, чтобы избежать разбора содержимого элементов как селектора.

$("span").tooltipContent({
      itemsData: "data-tooltip-content",
      show: {
          effect: "slideDown",
          delay: 50
      }
 })

itemsData: селектор данных, отображаемых в соответствии с вашим шаблоном:

     data-tooltip-content  --> data-tooltip-content-id

(function () {
    $.widget("custom.tooltipContent", $.ui.tooltip, {
        _init: function () {
            this._super();
            var _self = this;
            var datasetName = 'tooltipContent';

            // this in order to fire always content function...
            _self.options.items = (_self.options.items.indexOf('[title]') != -1) ? '[data-tooltip-content]' :  _self.options.items;

            // normalize itemsData
            _self.options.itemsData = _self.options.itemsData || "data-tooltip-content";

            // get the html to be displayed later and save it into a data attribute
            var contentSelector = "[" + _self.options.itemsData + "-id=" + _self.element.data(datasetName) + "]";
            _self.element.data(datasetName, $(contentSelector).html());

            this.options.content = function () {
                return _self.element.data(datasetName);
            };
        }
    });
})();

$("span").tooltipContent({
    itemsData: "data-tooltip-content",
    show: {
        effect: "slideDown",
        delay: 50
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>


<span id="test1" data-tooltip-content="x">Help 1</span>
<span id="test2" data-tooltip-content="x">Help 1</span>
<span id="test3" data-tooltip-content="y">Help 2</span>
<span id="test4" data-tooltip-content="y">Help 2</span>

<div style="display:none" data-tooltip-content-id="x">
    Shared content for <b>help 1</b>
</div>

<div style="display:none" data-tooltip-content-id="y">
    <table style="width:100%">
        <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Age</th>
        </tr>
        <tr>
            <td>Jill</td>
            <td>Smith</td>
            <td>50</td>
        </tr>
        <tr>
            <td>Eve</td>
            <td>Jackson</td>
            <td>94</td>
        </tr>
    </table>
</div>

Другой подход может быть основан на том, как кнопка начальной загрузки открывает модал. Теперь ваш атрибут data-tooltip-content должен содержать селектор отображаемых данных:

<span id="test1" data-tooltip-content="#x">Help 1</span>
<span id="test2" data-tooltip-content="#x">Help 1</span>
<span id="test3" data-tooltip-content="#y">Help 2</span>
<span id="test4" data-tooltip-content="#y">Help 2</span>

<div id="x" style="display:none">
    Shared content for <b>help 1</b>
</div>

<div id="y" style="display:none">
    <table style="width:100%">
.......................

Код теперь стал проще.

(function () {
    $.widget("custom.tooltipContent", $.ui.tooltip, {
        _init: function () {
            this._super();
            var _self = this;
            var datasetName = 'tooltipContent';

            // this in order to fire always content function...
            _self.options.items = (_self.options.items.indexOf('[title]') != -1) ? '[data-tooltip-content]' :  _self.options.items;

            // get the html to be displayed later and save it into a data attribute
            var html = '';
            if (_self.options.itemsData === undefined) {
                html = _self.element.attr('title') || '';
            } else {
                html = $(_self.element.data(datasetName)).html();
            }

            _self.element.data(datasetName, html);

            this.options.content = function () {
                return _self.element.data(datasetName);
            };
        }
    });
})();


$("span").tooltipContent({
    items: "span[id^=test]", // optional
    itemsData: "data-tooltip-content",
    show: {
        effect: "slideDown",
        delay: 50
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>


<span id="test1" data-tooltip-content="#x">Help 1</span>
<span id="test2" data-tooltip-content="#x">Help 1</span>
<span id="test3" data-tooltip-content="#y">Help 2</span>
<span id="test4" data-tooltip-content="#y">Help 2</span>

<div id="x" style="display:none">
    Shared content for <b>help 1</b>
</div>

<div id="y" style="display:none">
    <table style="width:100%">
        <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Age</th>
        </tr>
        <tr>
            <td>Jill</td>
            <td>Smith</td>
            <td>50</td>
        </tr>
        <tr>
            <td>Eve</td>
            <td>Jackson</td>
            <td>94</td>
        </tr>
    </table>
</div>
1 голос
/ 25 июня 2019

Я не уверен, должен ли это быть виджет. Я бы сделал следующее:

$(function() {
  $("span").tooltip({
    items: "[data-tooltip-rel]",
    content: function() {
      var id = $(this).attr("data-tooltip-rel");
      var cont = $("[data-tooltip-content-id='" + id + "']");
      return cont.html();
    }
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<span id="test" data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="y">Help 2</span>
<span data-tooltip-rel="y">Help 2</span>

<div style="display:none" data-tooltip-content-id="x">
  Shared content for <b>help 1</b>
</div>

<div style="display:none" data-tooltip-content-id="y">
  <table style="width:100%">
    <tr>
      <th>Firstname</th>
      <th>Lastname</th>
      <th>Age</th>
    </tr>
    <tr>
      <td>Jill</td>
      <td>Smith</td>
      <td>50</td>
    </tr>
    <tr>
      <td>Eve</td>
      <td>Jackson</td>
      <td>94</td>
    </tr>
  </table>
</div>

Если вы считаете, что вам нужен пользовательский виджет, вы можете сделать это.

$(function() {
  $.widget("custom.tooltipContent", $.ui.tooltip, {
    options: {
      items: "[data-tooltip-rel]",
      content: function() {
        return $("[data-tooltip-content-id='" + $(this).attr("data-tooltip-rel") + "']").html();
      }
    }
  });
  $("span").tooltipContent();
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<span id="test" data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="y">Help 2</span>
<span data-tooltip-rel="y">Help 2</span>

<div style="display:none" data-tooltip-content-id="x">
  Shared content for <b>help 1</b>
</div>

<div style="display:none" data-tooltip-content-id="y">
  <table style="width:100%">
    <tr>
      <th>Firstname</th>
      <th>Lastname</th>
      <th>Age</th>
    </tr>
    <tr>
      <td>Jill</td>
      <td>Smith</td>
      <td>50</td>
    </tr>
    <tr>
      <td>Eve</td>
      <td>Jackson</td>
      <td>94</td>
    </tr>
  </table>
</div>

Надеюсь, это поможет.

...