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/
Ответы
Ответ 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;
}