Подтвердить что ты не робот

Popover скрывает родительский элемент, если используется с Prototype JS

После обновления до bootstrap 2.3.0 я заметил странное поведение всплывающей подсказки.

Если вы введете поле и попытаетесь перейти от него, всплывающая подсказка исчезнет и скроет поле ввода. Эта проблема возникает только с последней версией бутстрапа, не уверен, что именно было изменено, но 2.2.2 хорошо работает с Prototype.

jQuery.noConflict();
jQuery('input[data-content]').popover({
    trigger: 'focus'
});

Вот рабочий пример: http://jsfiddle.net/U6EDs/4/

4b9b3361

Ответ 1

Этот вопрос github https://github.com/twitter/bootstrap/issues/6921 описывает то, что вы видите. Я копирую информацию из этой проблемы.

эти строки в bootstrap-tooltip.js вызывают проблему:

  , hide: function () {
  var that = this
    , $tip = this.tip()
    , e = $.Event('hide')   ///this line

  this.$element.trigger(e)  /// this line
  if (e.isDefaultPrevented()) return //and this line 

PrototypeJS добавляет методы прототипу элемента, поэтому, когда jQuery пытается вызвать метод hide() для элемента, он фактически запускает метод PrototypeJS hide(), который эквивалентен методу jQuery hide() и устанавливает стиль элемент display:none;

У вас есть несколько вариантов

  • удалите строки, отмеченные выше, в файле js
  • переименуйте событие в нечто другое (не скрывайте)
  • используйте прототип PrototypeJS BootStrap (в настоящее время работает с 2.3.2)

http://github.com/jwestbrook/bootstrap-prototype

***** ОТКАЗ ***

Я разработчик, который в настоящее время переносит компоненты BootStrap JS в PrototypeJS

Ответ 2

Я знаю, что это старый вопрос, но я просто столкнулся с этим (снова), и вышеупомянутые ответы не будут работать для меня. Я закончил поиск решения без взлома в каких-либо библиотеках. Идея состоит в том, чтобы показать элемент после его скрытия. Нет мерцания, и он работает хорошо.

jQuery(function () {
    jQuery.noConflict();
        jQuery('input[data-content]').popover({
            trigger: 'focus'
        }).on('hidden.bs.popover', function(){
            jQuery(this).show();
        });
});

Вы можете использовать ту же технику для всплывающих подсказок, просто используйте on('hidden.bs.tooltip'), ...

Примечание. Я использую Bootstrap 3.0.0 для большей части моего личного тестирования. Вот обновленная скрипка из вопроса, который использует BS 2.3: http://jsfiddle.net/calypsonian/U6EDs/13/

Ответ 3

Я потратил некоторое время на изучение этого.

Вот почему это происходит.

Стратегия прототипа состоит в расширять классы элементов DOM с новыми поведением, например, "скрыть". Эквивалент:

HTMLElement.prototype.hide = function(...) {...};

jQuery делает предположение, что если элемент имеет функцию с тем же именем, что и событие, тогда считается, что элемент по умолчанию элемента, когда это событие запущено. Например, это полезно для фокусов событий, "размытия" и т.д., Где есть событие с таким именем "фокус" и функция соответствия элемента .focus(). Когда вы вызываете jQuery event.preventDefault(), это не фактически блокировка по умолчанию. Вместо этого он обратный - если вы не вызываете event.preventDefault(), тогда jQuery ищет функцию с тем же именем, что и событие, а затем вызывает ее, если она существует.

Здесь jQuery src, который вручную вызывает функцию "по умолчанию": https://github.com/jquery/jquery/blob/d837f119c3729565103005d5d7fa89e1dd8110cb/src/event.js#L338

Таким образом, у нас есть наша проблема. Прототип расширяет базовый прототип HTMLElement новыми функциями (а именно, "скрыть" ). jQuery рассматривает эти функции как поведение по умолчанию при запуске события с таким же именем. Bootstrap JS запускает одноименное событие ('hide'), которое по ошибке заставляет jQuery вызывать функцию Prototype Element.hide().

Я собираюсь изучить решение, основанное на этой информации. Возможно, что-то вроде:

jQuery(window).load(function() {
    // Defer this code until after the window 'load' event finishes firing
    setTimeout(function() {
        window.HTMLElement &&
        window.HTMLElement.prototype.hide &&
        delete window.HTMLElement.prototype.hide;
    }, 0);
});

Ответ 4

Для меня лучше (без изменения исходного кода Bootstrap) - предотвратить событие и вручную удалить класс "in", который скрывает подсказку:

jQuery("input").on('hide.bs.tooltip', function(e) {
    e.preventDefault();
    $("div.tooltip.in").removeClass('in');

});

Только проблема заключается в том, что он предотвращает запуск события "hidden.bs.tooltip". Но если вы не возражаете, я предлагаю использовать это решение, поскольку оно не вызывает мерцание.

Ответ 5

Вы можете показать это снова на событии mouseleave, например,

jQuery(function(){  
    jQuery('[data-toggle="popover"]').popover().on('mouseleave',function(){
       $(this).show(0); // show it again when mouse leave event fires
    });
});

Live Demo

Ответ 6

Я добавил важный стиль CSS, чтобы переопределить стиль элемента, который добавляет прототип. Это работает для меня, потому что ничто не должно скрывать элемент.

#elemId{
  display: block!important; /* or whatever the original display was */
}

Ответ 7

Я "исправил" ошибку, отредактировав Bootstrap JS таким образом:
(строка комментария this.$element.trigger(e))

, hide: function () {
  var that = this
    , $tip = this.tip()
    , e = $.Event('hide')

  this.$tip.trigger(e)
//this.$element.trigger(e)
  if (e.isDefaultPrevented()) return

Ответ 8

Одно из возможных решений - всегда показывать элемент через CSS.

[data-toggle=tooltip] {
    display: block!important;
}