โหลดเนื้อหา Bootstrap popover ด้วย AJAX เป็นไปได้หรือไม่


90

ส่วนที่เหมาะสมของสิ่งที่ฉันพยายามอยู่ที่นี่:

<a href="#" data-content="<div id='my_popover'></div>"> Click here </a>

$(".button").popover({html: true})

$(".button").click(function(){
    $(this).popover('show');
    $("#my_popover").load('my_stuff')
})

เมื่อฉันคลิกฉันเห็นคำขอถูกสร้างขึ้น แต่ไม่ได้เติมข้อมูลที่ป็อปโอเวอร์ ฉันไม่เห็น HTML สำหรับการเพิ่มป๊อปโอเวอร์ใน DOM แต่นั่นอาจเป็นไฟร์บัก

มีใครลองทำแบบนี้บ้าง?


1
ฉันไม่ได้ทำงานกับ bootstrap แต่ฉันคิดว่าอาจเป็นไปได้ว่าองค์ประกอบนั้นไม่มีอยู่เมื่อคุณพยายามเพิ่มเนื้อหาลงไป แต่นั่นเป็นการเดา คุณได้รับข้อผิดพลาดเกี่ยวกับจาวาสคริปต์หรือไม่?
Seth

หากคุณมีป๊อปโอเวอร์หลายรายการและต้องการโหลดเนื้อหาที่แตกต่างกันสำหรับแต่ละป๊อปโอเวอร์คำตอบนี้จะเรียบร้อยมากและช่วยให้คุณรักษาการตั้งค่านอกกรอบสำหรับป๊อปโอเวอร์ได้มากมายสิ่งที่คุณต้องทำคือเก็บ ID ของป๊อปโอเวอร์ เกี่ยวกับแอตทริบิวต์ของลิงก์และอ่านใน'shown.bs.popover'ตัวจัดการ: stackoverflow.com/a/39028723/1371408
Matty J

คำตอบ:


105

ดูโพสต์บล็อกของฉันสำหรับโซลูชันการทำงาน: https://medium.com/cagataygurturk/load-a-bootstrap-popover-content-with-ajax-8a95cd34f6a4

ก่อนอื่นเราควรเพิ่มแอตทริบิวต์ data-poload ให้กับองค์ประกอบที่คุณต้องการเพิ่มป๊อปลงไป เนื้อหาของแอตทริบิวต์นี้ควรเป็น url ที่จะโหลด (สัมบูรณ์หรือสัมพัทธ์):

<a href="#" title="blabla" data-poload="/test.php">blabla</a>

และใน JavaScript ควรอยู่ใน $ (document) .ready ();

$('*[data-poload]').hover(function() {
    var e=$(this);
    e.off('hover');
    $.get(e.data('poload'),function(d) {
        e.popover({content: d}).popover('show');
    });
});

off('hover')ป้องกันการโหลดข้อมูลมากกว่าหนึ่งครั้งและpopover()เชื่อมโยงเหตุการณ์โฮเวอร์ใหม่ หากคุณต้องการให้ข้อมูลรีเฟรชในทุกเหตุการณ์ที่เลื่อนคุณควรลบการปิด

โปรดดูJSFiddle ที่ใช้งานได้ของตัวอย่าง


4
ฉันรู้สึกแปลก ๆ เมื่อฉันวางเมาส์ไว้สองครั้งก่อนที่การโทรของ ajax จะเสร็จสมบูรณ์ ... popvers ของฉันจะ "ติด" เปิด ฉันแก้ไขได้โดยเลื่อน "el.unbind ('hover')" ไปทางขวาก่อน $ .get ()
Luke The Obscure

1
ใช้งานได้ แต่ป๊อปโอเวอร์ก็ยังติดสำหรับฉันแม้ว่าการคลายตัวจะอยู่ก่อนการรับ
Androme

2
หากคุณกำลังพยายามโหลด URL ภายนอกคุณจะพบข้อ จำกัด การเข้าถึงข้ามโดเมน จะได้รับรอบนี้คุณสามารถตั้งค่า popover ของhtmlคุณสมบัติการtrueแล้วตั้งค่าcontentคุณสมบัติการแท็ก iframe HTML content: '<iframe src="http://www.google.com"></iframe>'เช่น นอกจากนี้คุณจะต้องลบล้างmax-widthคุณสมบัติของ popover ของคุณโดยใช้ CSS และส่วนใหญ่จะลบสไตล์ของ iframe โดยใช้ CSS ด้วย
Gavin

1
@FrzKhan คุณสามารถใช้e.off('hover')วิธีนี้
codenamev

3
ไม่ได้ผลเนื่องจากstackoverflow.com/questions/4111194/… เปลี่ยนเป็น .hover (function () {}) ทำงาน
arisalexis

132

ใช้งานได้สำหรับฉัน:

$('a.popup-ajax').popover({
    "html": true,
    "content": function(){
        var div_id =  "tmp-id-" + $.now();
        return details_in_popup($(this).attr('href'), div_id);
    }
});

function details_in_popup(link, div_id){
    $.ajax({
        url: link,
        success: function(response){
            $('#'+div_id).html(response);
        }
    });
    return '<div id="'+ div_id +'">Loading...</div>';
}

1
อัจฉริยะตอบ! และนั่นคือเหตุผลที่แก้ไขเพื่อให้อ่านง่ายขึ้น
itsazzad

2
ทางออกที่ดี ด้วย bootstrap เวอร์ชันปัจจุบัน แต่ดูเหมือนว่า der อาจมีปัญหากับวิธีนี้github.com/twbs/bootstrap/issues/12563ฉันมีปัญหาสองครั้งและวิธีแก้ปัญหาที่รวดเร็วคือเพื่อให้แน่ใจว่าชื่อในแต่ละป๊อปโอเวอร์ นอกจากนี้ยังหมายความว่าฉันไม่เคยเห็นข้อความกำลังโหลดที่คุณใช้อยู่เลย
Rasmus Christensen

ใช้งานได้ยกเว้นฉันต้องใช้ data-link แทน href เมื่อใช้ href เบราว์เซอร์ของฉันจะเปิด url ใน href ในหน้าต่างใหม่
TinusSky

20
สิ่งนี้ไม่ก่อให้เกิดปัญหาการจัดตำแหน่งหรือไม่? เมื่อใช้แนวทางนี้บน 3.3.1 (และใช้ Chrome) ป๊อปโอเวอร์จะจัดแนวเองเมื่อ "กำลังโหลด ... " ปรากฏขึ้น แต่ทันทีที่โหลดเนื้อหาที่แท้จริงของป๊อปโอเวอร์การจัดแนวจะไม่ปรับตาม .. .
แมตต์

5
ทางออกที่ดี ข้อเสียอย่างหนึ่งของการแก้ปัญหานี้คือการโทร ajax ทำสองครั้ง คอมโพเนนต์ป็อปโอเวอร์คือคำแนะนำเครื่องมือซึ่งก่อนอื่นจะตรวจสอบเนื้อหาโดยใช้ hasContent จากนั้นรับเนื้อหาด้วย setContent
Liam

24

เมื่ออ่านวิธีแก้ปัญหาเหล่านี้ทั้งหมดแล้วฉันคิดว่าวิธีนี้จะง่ายกว่ามากหากคุณใช้การโทร ajax แบบซิงโครนัส จากนั้นคุณสามารถใช้สิ่งต่างๆเช่น:

  $('#signin').popover({
    html: true,
    trigger: 'manual',
    content: function() {
      return $.ajax({url: '/path/to/content',
                     dataType: 'html',
                     async: false}).responseText;
    }
  }).click(function(e) {
    $(this).popover('toggle');
  });

1
สิ่งนี้ช่วยฉันได้มากเนื่องจากฉันมีปัญหากับการแสดงผลป๊อปโอเวอร์ในตำแหน่งหนึ่งก่อนที่ ajax จะส่งคืนเนื้อหา (ทำให้โหลดออกจากหน้าจอ) ขอบคุณครับ!
Derek

อาจจะง่ายกว่า แต่ก็หรูหราน้อยกว่าโซลูชันที่โพสต์โดย @Ivan Klass
Ian Kemp

6
async: falseฆ่าสิ่งนี้เพื่อฉัน
mxmissile

แม้ว่าจะง่ายกว่าอย่างแน่นอน แต่ JavaScript และรหัสซิงโครนัสก็ไม่ค่อยเล่นด้วยกัน เนื่องจาก JavaScript เป็นเธรดเดียวสิ่งนี้จะบล็อกโค้ดใด ๆ ไม่ให้ดำเนินการตราบเท่าที่คำขอใช้เวลา
IluTov

1
AJAX แบบซิงโครนัสเลิกใช้งานแล้ว
Barmar

10

ฉันได้อัปเดตคำตอบยอดนิยมแล้ว แต่ในกรณีที่การเปลี่ยนแปลงของฉันไม่ได้รับการอนุมัติฉันขอตอบแยกต่างหาก

ความแตกต่างคือ:

  • กำลังโหลดข้อความที่แสดงในขณะที่กำลังโหลดเนื้อหา ดีมากสำหรับการเชื่อมต่อที่ช้า
  • ลบการกะพริบซึ่งเกิดขึ้นเมื่อเมาส์ออกจากป๊อปโอเวอร์ในครั้งแรก

ก่อนอื่นเราควรเพิ่มแอตทริบิวต์ data-poload ให้กับองค์ประกอบที่คุณต้องการเพิ่มป๊อปลงไป เนื้อหาของแอตทริบิวต์นี้ควรเป็น url ที่จะโหลด (สัมบูรณ์หรือสัมพัทธ์):

<a href="#" data-poload="/test.php">HOVER ME</a>

และใน JavaScript ควรอยู่ใน $ (document) .ready ();

 // On first hover event we will make popover and then AJAX content into it.
$('[data-poload]').hover(
    function (event) {
        var el = $(this);

        // disable this event after first binding 
        el.off(event);

        // add initial popovers with LOADING text
        el.popover({
            content: "loading…", // maybe some loading animation like <img src='loading.gif />
            html: true,
            placement: "auto",
            container: 'body',
            trigger: 'hover'
        });

        // show this LOADING popover
        el.popover('show');

        // requesting data from unsing url from data-poload attribute
        $.get(el.data('poload'), function (d) {
            // set new content to popover
            el.data('bs.popover').options.content = d;

            // reshow popover with new content
            el.popover('show');
        });
    },
    // Without this handler popover flashes on first mouseout
    function() { }
);

off('hover')ป้องกันการโหลดข้อมูลมากกว่าหนึ่งครั้งและpopover()เชื่อมโยงเหตุการณ์โฮเวอร์ใหม่ หากคุณต้องการให้ข้อมูลรีเฟรชในทุกเหตุการณ์ที่เลื่อนคุณควรลบการปิด

โปรดดูJSFiddle ที่ใช้งานได้ของตัวอย่าง


7

รูปแบบของรหัสจากÇağatayGürtürkคุณสามารถใช้ฟังก์ชัน delegate แทนและบังคับซ่อน popover บนโฮเวอร์เอาต์

$('body').delegate('.withajaxpopover','hover',function(event){
    if (event.type === 'mouseenter') {
        var el=$(this);
        $.get(el.attr('data-load'),function(d){
            el.unbind('hover').popover({content: d}).popover('show');
        });
    }  else {
        $(this).popover('hide');
    }
});

สำหรับ jquery ล่าสุด: $ ('* [data-poload]'). on ('mouseenter mouseleave', function (event) {
jpprade

7

วิธีแก้ปัญหาของÇağatayGürtürkนั้นดี แต่ฉันก็พบกับความแปลกประหลาดแบบเดียวกับที่ Luke The Obscure อธิบายไว้:

เมื่อการโหลด ajax กินเวลามากเกินไป (หรือเหตุการณ์ของเมาส์เร็วเกินไป) เราจะมี. popover ('show') และไม่มี. popover ('hide') ในองค์ประกอบที่กำหนดทำให้ popover ยังคงเปิดอยู่

ฉันชอบโซลูชันก่อนโหลดขนาดใหญ่นี้โหลดเนื้อหาป๊อปโอเวอร์ทั้งหมดและเหตุการณ์ต่างๆจะถูกจัดการโดย bootstrap เหมือนในป๊อปโอเวอร์ปกติ (คงที่)

$('.popover-ajax').each(function(index){

    var el=$(this);

    $.get(el.attr('data-load'),function(d){
        el.popover({content: d});       
    });     

});

7

ในปี 2558 นี่คือคำตอบที่ดีที่สุด

$('.popup-ajax').mouseenter(function() {
   var i = this
   $.ajax({
      url: $(this).attr('data-link'), 
      dataType: "html", 
      cache:true, 
      success: function( data{
         $(i).popover({
            html:true,
            placement:'left',
            title:$(i).html(),
            content:data
         }).popover('show')
      }
   })
});

$('.popup-ajax').mouseout(function() {
  $('.popover:visible').popover('destroy')
});

6

วิธีแก้ปัญหาอื่น:

$target.find('.myPopOver').mouseenter(function()
{
    if($(this).data('popover') == null)
    {
        $(this).popover({
            animation: false,
            placement: 'right',
            trigger: 'manual',
            title: 'My Dynamic PopOver',
            html : true,
            template: $('#popoverTemplate').clone().attr('id','').html()
        });
    }
    $(this).popover('show');
    $.ajax({
        type: HTTP_GET,
        url: "/myURL"

        success: function(data)
        {
            //Clean the popover previous content
            $('.popover.in .popover-inner').empty();    

            //Fill in content with new AJAX data
            $('.popover.in .popover-inner').html(data);

        }
    });

});

$target.find('.myPopOver').mouseleave(function()
{
    $(this).popover('hide');
});

แนวคิดต่อไปนี้คือการเรียกใช้การแสดง PopOver ด้วยตนเองด้วยmouseenter & mouseleave events

บนmouseenterหากไม่มีการสร้าง PopOver สำหรับรายการของคุณ ( ถ้า ($ (this) .data ('popover') == null) ) ให้สร้างขึ้น สิ่งที่น่าสนใจคือคุณสามารถกำหนดเนื้อหา PopOver ของคุณเองได้โดยส่งเป็นอาร์กิวเมนต์ ( template ) ไปยังฟังก์ชันpopover () อย่าลืมตั้งค่าพารามิเตอร์html เป็น trueด้วย

ที่นี่ฉันเพิ่งสร้างเทมเพลตที่ซ่อนอยู่ชื่อpopovertemplateและโคลนด้วย JQuery อย่าลืมลบแอตทริบิวต์ id เมื่อคุณโคลนไม่เช่นนั้นคุณจะได้รับรหัสซ้ำใน DOM โปรดสังเกตด้วยว่าstyle = "display: none"เพื่อซ่อนเทมเพลตในเพจ

<div id="popoverTemplateContainer" style="display: none">

    <div id="popoverTemplate">
        <div class="popover" >
            <div class="arrow"></div>
            <div class="popover-inner">
                //Custom data here
            </div>
        </div>
    </div>
</div>

หลังจากขั้นตอนการสร้าง (หรือถ้าสร้างแล้ว) คุณเพียงแค่แสดง popOver ด้วย$ (this) .popover ('show');

จากนั้นก็โทรหา Ajax แบบคลาสสิก เกี่ยวกับความสำเร็จที่คุณจำเป็นต้องทำความสะอาดเนื้อหา popover เก่าก่อนที่จะวางข้อมูลที่สดใหม่จากเซิร์ฟเวอร์ เราจะรับเนื้อหา popover ปัจจุบันได้อย่างไร ด้วยตัวเลือก. popover.in ! .inระดับบ่งชี้ว่า popover จะปรากฏขึ้นในขณะนี้ว่าเป็นเคล็ดลับที่นี่แล้ว!

ในการเสร็จสิ้นในเหตุการณ์mouseleaveเพียงแค่ซ่อน popover


สิ่งเดียวกันสำหรับฉันสิ่งที่ง่ายที่สุด & ดีที่สุด ;-)
Thomas Decaux

ปัญหานี้เกิดขึ้นทุกครั้งที่คุณขอข้อมูลจากเซิร์ฟเวอร์ ควรโหลดข้อมูลเพียงครั้งเดียว
Richard Torcato

2
@Richard Torcato ในมือข้างหนึ่งคุณพูดถูก มันควรจะค่อนข้างง่ายที่จะใส่ผลลัพธ์ลงในแคช ในทางกลับกันบางทีเราอาจต้องการเข้าสู่เซิร์ฟเวอร์เพื่อโหลดข้อมูลใหม่ทุกครั้งที่วางเมาส์ ดังนั้นจึงขึ้นอยู่กับคุณที่จะใช้การแคช
doanduyhai

ฉันรู้ว่าตอนนี้มันเก่าแล้ว แต่ในกรณีที่มีคนมองเรื่องนี้ฉันนึกไม่ออกว่ามันจะทำงานได้ดีขนาดนี้ถ้าคุณมีป๊อปโอเวอร์หลายตัวและคุณเลื่อนดูแต่ละอัน วางเมาส์เหนือ A คำขอที่ส่งไปสำหรับ A วางเมาส์เหนือ B และเลื่อนไปเรื่อย ๆ คำขอที่ส่งสำหรับ B การตอบกลับจาก B มาถึงอัปเดตป็อปโอเวอร์สำหรับ B การตอบกลับสำหรับ A มาถึงอัปเดตป็อปโอเวอร์สำหรับ B (เนื่องจากฟังก์ชันความสำเร็จจะ เพียงแค่ล้างข้อมูลในชั้นเรียนนั้นการดูสิ่งนี้เพื่อเสริมด้านบนอาจช่วยได้แม้ว่าstackoverflow.com/a/34030999/2524589
KSib

3

นี่คือวิธีแก้ปัญหาของฉันซึ่งทำงานได้ดีกับเนื้อหาที่โหลด ajax ด้วย

/*
 * popover handler assigned document (or 'body') 
 * triggered on hover, show content from data-content or 
 * ajax loaded from url by using data-remotecontent attribute
 */
$(document).popover({
    selector: 'a.preview',
    placement: get_popover_placement,
    content: get_popover_content,
    html: true,
    trigger: 'hover'
});

function get_popover_content() {
    if ($(this).attr('data-remotecontent')) {
        // using remote content, url in $(this).attr('data-remotecontent')
        $(this).addClass("loading");
        var content = $.ajax({
            url: $(this).attr('data-remotecontent'),
            type: "GET",
            data: $(this).serialize(),
            dataType: "html",
            async: false,
            success: function() {
                // just get the response
            },
            error: function() {
                // nothing
            }
        }).responseText;
        var container = $(this).attr('data-rel');
        $(this).removeClass("loading");
        if (typeof container !== 'undefined') {
            // show a specific element such as "#mydetails"
            return $(content).find(container);
        }
        // show the whole page
        return content;
    }
    // show standard popover content
    return $(this).attr('data-content');
}

function get_popover_placement(pop, el) {
    if ($(el).attr('data-placement')) {
        return $(el).attr('data-placement');
    }
    // find out the best placement
    // ... cut ...
    return 'left';
}

3

หากเนื้อหาในป๊อปโอเวอร์ไม่มีแนวโน้มที่จะเปลี่ยนแปลงก็ควรดึงข้อมูลเพียงครั้งเดียว นอกจากนี้วิธีแก้ปัญหาบางอย่างที่นี่มีปัญหาว่าหากคุณเลื่อนไปที่ "ตัวอย่าง" หลายรายการอย่างรวดเร็วคุณจะได้รับป๊อปอัปที่เปิดอยู่หลายรายการ โซลูชันนี้กล่าวถึงทั้งสองสิ่งนั้น

$('body').on('mouseover', '.preview', function() 
{
    var e = $(this);
    if (e.data('title') == undefined)
    {
        // set the title, so we don't get here again.
        e.data('title', e.text());

        // set a loader image, so the user knows we're doing something
        e.data('content', '<img src="/images/ajax-loader.gif" />');
        e.popover({ html : true, trigger : 'hover'}).popover('show');

        // retrieve the real content for this popover, from location set in data-href
        $.get(e.data('href'), function(response)
        {
            // set the ajax-content as content for the popover
            e.data('content', response.html);

            // replace the popover
            e.popover('destroy').popover({ html : true, trigger : 'hover'});

            // check that we're still hovering over the preview, and if so show the popover
            if (e.is(':hover'))
            {
                e.popover('show');
            }
        });
    }
});

3

ฉันคิดว่าโซลูชันของฉันง่ายกว่าด้วยฟังก์ชันเริ่มต้น

http://jsfiddle.net/salt/wbpb0zoy/1/

$("a.popover-ajax").each(function(){
		 $(this).popover({
			trigger:"focus",
			placement: function (context, source) {
                  var obj = $(source);
				  $.get(obj.data("url"),function(d) {
                        $(context).html( d.titles[0].title)
                  });	
			},
			html:true,
			content:"loading"
		 });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>


<ul class="list-group">
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Cras justo odio</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Dapibus ac facilisis in</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Morbi leo risus</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Porta ac consectetur ac</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Vestibulum at eros</a></li>
</ul>


2

มีคำตอบมากมายที่นี่ แต่ฉันก็ไม่พบว่าคำตอบเหล่านั้นเป็นสิ่งที่ฉันต้องการ ฉันได้ขยายคำตอบของ Ivan Klass เพื่อให้ทั้ง Bootstrap 4 เหมาะสมและแคชอย่างชาญฉลาด

โปรดทราบว่าตัวอย่างข้อมูลจะไม่โหลดที่อยู่ระยะไกลเนื่องจากนโยบาย CORS ของ Stackoverflow

var popoverRemoteContents = function(element) {
  if ($(element).data('loaded') !== true) {
    var div_id = 'tmp-id-' + $.now();
    $.ajax({
      url: $(element).data('popover-remote'),
      success: function(response) {
        $('#' + div_id).html(response);
        $(element).attr("data-loaded", true);
        $(element).attr("data-content", response);
        return $(element).popover('update');
      }
    });
    return '<div id="' + div_id + '">Loading...</div>';
  } else {
    return $(element).data('content');
  }
};

$('[data-popover-remote]').popover({
  html: true,
  trigger: 'hover',
  content: function() {
    return popoverRemoteContents(this);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>

<span data-popover-remote="http://example.com/">Remote Popover test with caching</span>


ฉันสามารถปรับตัวนี้ให้เข้ากับโซลูชันที่ฉันต้องการได้อย่างง่ายดาย ขอขอบคุณ!
Nieminen

1
ทางออกที่ดีเพียงแค่ต้องเพิ่ม "sanitize: false" เพื่อ popover config เพื่อจัดการ css ของฉัน!
Guillaume

1

คำตอบที่คล้ายกันนี้ได้รับในชุดข้อความนี้: การตั้งค่าเนื้อหาข้อมูลและการแสดงป๊อปโอเวอร์ - เป็นวิธีที่ดีกว่าในการทำสิ่งที่คุณหวังว่าจะบรรลุ มิฉะนั้นคุณจะต้องใช้ตัวเลือก live: true ในตัวเลือกของวิธีการป๊อปโอเวอร์ หวังว่านี่จะช่วยได้


1

ฉันลองวิธีแก้ปัญหาโดยÇağatayGürtürk แต่ก็มีความแปลกประหลาดเช่นเดียวกับ Luke the Obscure จากนั้นก็ทดลองแก้โดยอาสากุสุมา ใช้งานได้ แต่ฉันเชื่อว่า Ajax อ่านทุกไฟล์ครั้งที่มีการแสดงป๊อปโอเวอร์ การเรียกเพื่อเลิกผูก ('hover') ไม่มีผลใด ๆ นั่นเป็นเพราะ delegate กำลังตรวจสอบเหตุการณ์ในคลาสเฉพาะ - แต่คลาสนั้นไม่มีการเปลี่ยนแปลง

นี่คือวิธีแก้ปัญหาของฉันโดยอ้างอิงจาก Asa Kusuma's อย่างใกล้ชิด การเปลี่ยนแปลง:

  • แทนที่delegateด้วยonเพื่อให้ตรงกับไลบรารี JQuery ใหม่
  • ลบคลาส 'withajaxpopover' แทนที่จะยกเลิกการผูกเหตุการณ์โฮเวอร์ (ซึ่งไม่เคยผูกมัด)
  • เพิ่ม "ทริกเกอร์: โฮเวอร์" ไปที่ป๊อปโอเวอร์เพื่อให้ Bootstrap จัดการได้อย่างสมบูรณ์โดยเริ่มจากการใช้ครั้งที่สอง
  • ฟังก์ชันการโหลดข้อมูลของฉันส่งคืน JSon ซึ่งทำให้ง่ายต่อการระบุทั้งหัวเรื่องและเนื้อหาสำหรับป็อปโอเวอร์
    / * เป้าหมาย: แสดงคำแนะนำเครื่องมือ / ป็อปโอเวอร์ที่ดึงเนื้อหาจากไฟล์
              สมัครครั้งแรกเท่านั้น

        วิธีการ: ดึงเนื้อหาที่เหมาะสมและลงทะเบียนคำแนะนำเครื่องมือ / popover ในครั้งแรก 
              เมาส์เข้าสู่องค์ประกอบ DOM ด้วยคลาส "withajaxpopover" ลบไฟล์
              คลาสจากองค์ประกอบดังนั้นเราจะไม่ทำเช่นนั้นในครั้งต่อไปที่เมาส์เข้า
              อย่างไรก็ตามนั่นจะไม่แสดงคำแนะนำเครื่องมือ / ป๊อปโอเวอร์เป็นครั้งแรก
              (เนื่องจากมีการป้อนเมาส์ไว้แล้วเมื่อลงทะเบียนคำแนะนำเครื่องมือ)
              เราจึงต้องแสดง / ซ่อนมันเอง
    * /
    $ (ฟังก์ชัน () {
      $ ('body'). on ('hover', '.withajaxpopover', function (event) {
          ถ้า (event.type === 'mouseenter') {
              var el = $ (นี้);
              $ .get (el.attr ('data-load'), ฟังก์ชัน (d) {
                  el.removeClass ('withajaxpopover')
                  el.popover ({ทริกเกอร์: 'hover', 
                              ชื่อเรื่อง: d.title, 
                              เนื้อหา: d.content}). popover ('แสดง');
              });
          } else {
              $ (this) .popover ('ซ่อน');
          }
      });
    });

1

ฉันลองทำตามคำแนะนำที่นี่และอยากจะนำเสนอของฉัน (ซึ่งแตกต่างกันเล็กน้อย) - ฉันหวังว่ามันจะช่วยใครบางคนได้ ฉันต้องการแสดงป๊อปอัปในคลิกแรกและซ่อนไว้ในคลิกที่สอง (แน่นอนว่าเมื่ออัปเดตข้อมูลทุกครั้ง) ฉันใช้ตัวแปรพิเศษvisableเพื่อทราบว่าป๊อปโอเวอร์สามารถมองเห็นได้หรือไม่ นี่คือรหัสของฉัน: HTML:

<button type="button" id="votingTableButton" class="btn btn-info btn-xs" data-container="body" data-toggle="popover" data-placement="left" >Last Votes</button>

Javascript:

$('#votingTableButton').data("visible",false);

$('#votingTableButton').click(function() {  
if ($('#votingTableButton').data("visible")) {
    $('#votingTableButton').popover("hide");
    $('#votingTableButton').data("visible",false);          
}
else {
    $.get('votingTable.json', function(data) {
        var content = generateTableContent(data);
        $('#votingTableButton').popover('destroy');
        $('#votingTableButton').popover({title: 'Last Votes', 
                                content: content, 
                                trigger: 'manual',
                                html:true});
        $('#votingTableButton').popover("show");
        $('#votingTableButton').data("visible",true);   
    });
}   
});

ไชโย!


1
<button type="button" id="popover2" title="" data-content="<div id='my_popover' style='height:250px;width:300px;overflow:auto;'>Loading...Please Wait</div>" data-html="true" data-toggle="popover2" class="btn btn-primary" data-original-title="A Title">Tags</button>

$('#popover2').popover({ 
    html : true,
    title: null,
    trigger: "click",
    placement:"right"
});

$("#popover2").on('shown.bs.popover', function(){
    $('#my_popover').html("dynamic content loaded");

});

1

นี่คือวิธีการแก้ไขปัญหาบางประการ:

  1. ปัญหาการจัดตำแหน่งหลังจากอัปเดตเนื้อหาโดยเฉพาะอย่างยิ่งหากตำแหน่งอยู่ "บนสุด" ที่สำคัญคือการโทร._popper.update()ซึ่งจะคำนวณตำแหน่งของป๊อปโอเวอร์ใหม่
  2. ความกว้างเปลี่ยนไปหลังจากอัปเดตเนื้อหา มันไม่ได้ทำลายอะไรมันดูสั่นสะเทือนสำหรับผู้ใช้ เพื่อลดสิ่งนั้นฉันตั้งค่าความกว้างของป๊อปโอเวอร์เป็น 100% (ซึ่งต่อยอดด้วยmax-width)
var e = $("#whatever");
e.popover({
    placement: "top",
    trigger: "hover",
    title: "Test Popover",
    content: "<span class='content'>Loading...</span>",
    html: true
}).on("inserted.bs.popover", function() {
    var popover = e.data('bs.popover');
    var tip = $(popover.tip);
    tip.css("width", "100%");
    $.ajax("/whatever")
        .done(function(data) {
            tip.find(".content").text(data);
            popover._popper.update();
        }).fail(function() {
            tip.find(".content").text("Sorry, something went wrong");
        });
});

ฉันชอบแนวคิด แต่น่าเสียดายที่มันไม่ได้ผลสำหรับฉัน ... (คือการอัปเดตตำแหน่งและความกว้าง 100%) ไม่แน่ใจว่าสิ่งเหล่านี้มีการเปลี่ยนแปลงด้วย Bootstrap 4 หรือไม่?
Ben ในแคลิฟอร์เนีย

ความกว้าง 100% อาจขึ้นอยู่กับการจัดวางองค์ประกอบของคุณ ... กล่องยังคงขยับขยายหลังจากโหลดเนื้อหาแล้วหรือไม่
Gabriel Luci

สำหรับตำแหน่งคุณสามารถตั้งค่าเบรกพอยต์ที่popover._popper.update()และให้แน่ใจว่าpopover, _popperและupdateทุกคนมีค่าที่คาดหวัง เป็นไปได้อย่างแน่นอนว่าสิ่งเหล่านั้นมีการเปลี่ยนแปลง
Gabriel Luci

ขวา - ช่องจะกว้างขึ้นหลังจากเนื้อหาใหม่ และฉันพยายามเขียนค่าบางอย่างลงในคอนโซลและไม่ได้กำหนด
Ben ในแคลิฟอร์เนีย

1
- คุณถูก. ปรากฎว่าฉันพยายามทำบางสิ่งที่ซับซ้อนขึ้นในเวลาเดียวกัน แต่มันก็ไม่ได้ผล แต่ตอนนี้ฉันสามารถรวมเข้าด้วยกันได้แล้ว นี่คือซอ: jsfiddle.net/udfz5wrv/1 ช่วยให้คุณใช้ตัวเลือก (หากคุณต้องการผูกตัวจัดการ ฯลฯ ) เข้าถึงข้อมูลจากตัวเลือกแสดงสปินเนอร์โหลด bootstrap ฯลฯ
Ben ใน CA

0
$("a[rel=popover]").each(function(){
        var thisPopover=$(this);
                var thisPopoverContent ='';
                if('you want a data inside an html div tag') {
                thisPopoverContent = $(thisPopover.attr('data-content-id')).html();
                }elseif('you want ajax content') {
                    $.get(thisPopover.attr('href'),function(e){
                        thisPopoverContent = e;
                    });
            }
        $(this).attr(   'data-original-title',$(this).attr('title') );
        thisPopover.popover({
            content: thisPopoverContent
        })
        .click(function(e) {
            e.preventDefault()
        });

    });

โปรดทราบว่าฉันใช้แท็ก href เดียวกันและทำให้มันไม่เปลี่ยนหน้าเมื่อคลิกนี่เป็นสิ่งที่ดีสำหรับ SEO และหากผู้ใช้ไม่มีจาวาสคริปต์!


0

ฉันชอบวิธีแก้ปัญหาของÇağatay แต่ฉันไม่ได้ซ่อนป๊อปอัปไว้ที่เมาส์เอาท์ ฉันได้เพิ่มฟังก์ชันพิเศษนี้ด้วยสิ่งนี้:

// hides the popup
$('*[data-poload]').bind('mouseout',function(){
   var e=$(this);
   e.popover('hide'); 
});

0

ฉันใช้โซลูชันดั้งเดิม แต่ทำการเปลี่ยนแปลงสองสามอย่าง:

ก่อนอื่นฉันใช้getJSON()แทนget()เพราะฉันกำลังโหลดสคริปต์ json ต่อไปฉันได้เพิ่มพฤติกรรมทริกเกอร์ของการวางเมาส์เพื่อแก้ไขปัญหาป๊อปอัป

$('*[data-poload]').on('mouseover',function() {
    var e=$(this);
    $.getJSON(e.data('poload'), function(data){
        var tip;
        $.each(data, function (index, value) {
           tip = this.tip;
           e.popover({content: tip, html: true, container: 'body', trigger: 'hover'}).popover('show');
        });
    });
});

0

ฉันเพิ่ม html: true ดังนั้นจึงไม่แสดงเอาต์พุต html ดิบในกรณีที่คุณต้องการจัดรูปแบบผลลัพธ์ของคุณ คุณยังสามารถเพิ่มการควบคุมอื่น ๆ

    $('*[data-poload]').bind('click',function() {
        var e=$(this);
        e.unbind('click');
        $.get(e.data('poload'),function(d) {
            e.popover({content: d, html: true}).popover('show', {

            });
        });
    });

0

แสดง ajax popover บนองค์ประกอบคงที่ด้วยทริกเกอร์โฮเวอร์:

$('.hover-ajax').popover({
    "html": true,
    trigger: 'hover',
    "content": function(){
        var div_id =  "tmp-id-" + $.now();
        return details_in_popup($(this).attr('href'), div_id);
    }
});

function details_in_popup(link, div_id){
    $.ajax({
        url: link,
        success: function(response){
            $('#'+div_id).html(response);
        }
    });
    return '<div id="'+ div_id +'">Loading...</div>';
}

Html:

<span class="hover-ajax" href="http://domain.tld/file.php"> Hey , hoover me ! </span>

0
  $('[data-poload]').popover({
    content: function(){
      var div_id =  "tmp-id-" + $.now();
      return details_in_popup($(this).data('poload'), div_id, $(this));
    },
    delay: 500,

    trigger: 'hover',
    html:true
  });

  function details_in_popup(link, div_id, el){
      $.ajax({
          url: link,
          cache:true,
          success: function(response){
              $('#'+div_id).html(response);
              el.data('bs.popover').options.content = response;
          }
      });
      return '<div id="'+ div_id +'"><i class="fa fa-spinner fa-spin"></i></div>';
  }   

โหลดเนื้อหา Ajax ครั้งเดียว! ดูel.data('bs.popover').options.content = response;


0

ฉันทำได้และมันก็ทำงานได้อย่างสมบูรณ์แบบด้วย ajax และการโหลดเนื้อหา popover

var originalLeave = $.fn.popover.Constructor.prototype.leave;
        $.fn.popover.Constructor.prototype.leave = function(obj){
            var self = obj instanceof this.constructor ?
                obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
            var container, timeout;

            originalLeave.call(this, obj);

            if(obj.currentTarget) {
                container = $(obj.currentTarget).siblings('.popover')
                timeout = self.timeout;
                container.one('mouseenter', function(){
                    //We entered the actual popover – call off the dogs
                    clearTimeout(timeout);
                    //Let's monitor popover content instead
                    container.one('mouseleave', function(){
                        $.fn.popover.Constructor.prototype.leave.call(self, self);
                    });
                })
            }
        };
        var attr = 'tooltip-user-id';
        if ($('a['+ attr +']').length)
            $('a['+ attr +']').popover({
                html: true,
                trigger: 'click hover',
                placement: 'auto',
                content: function () {
                    var this_ = $(this);
                    var userId = $(this).attr(attr);
                    var idLoaded = 'tooltip-user-id-loaded-' + userId;
                    var $loaded = $('.' + idLoaded);
                    if (!$loaded.length) {
                        $('body').append('<div class="'+ idLoaded +'"></div>');
                    } else if ($loaded.html().length) {
                        return $loaded.html();
                    }
                    $.get('http://example.com', function(data) {
                        $loaded.html(data);
                        $('.popover .popover-content').html(data);
                        this_.popover('show');
                    });
                    return '<img src="' + base_url + 'assets/images/bg/loading.gif"/>';
                },
                delay: {show: 500, hide: 1000},
                animation: true
            });

คุณสามารถตรวจสอบออกhttp://kienthuchoidap.com ไปที่สิ่งนี้และวางเมาส์เหนือชื่อผู้ใช้ของผู้ใช้


0

สำหรับฉันงานเปลี่ยน data-content befora load popover:

$('.popup-ajax').data('content', function () {
    var element = this;
    $.ajax({
        url: url,
        success: function (data) {

            $(element).attr('data-content', data)

            $(element).popover({
                html: true,
                trigger: 'manual',
                placement: 'left'
            });
            $(element).popover('show')
        }})
})

0

สิ่งนี้ใช้ได้ผลสำหรับฉันรหัสนี้สามารถแก้ไขปัญหาการจัดตำแหน่งได้:

<a class="ajax-popover" data-container="body" data-content="Loading..." data-html="data-html" data-placement="bottom" data-title="Title" data-toggle="popover" data-trigger="focus" data-url="your_url" role="button" tabindex="0" data-original-title="" title="">
  <i class="fa fa-info-circle"></i>
</a>

$('.ajax-popover').click(function() {
  var e = $(this);
  if (e.data('loaded') !== true) {
    $.ajax({
      url: e.data('url'),
      dataType: 'html',
      success: function(data) {
        e.data('loaded', true);
        e.attr('data-content', data);
        var popover = e.data('bs.popover');
        popover.setContent();
        popover.$tip.addClass(popover.options.placement);
        var calculated_offset = popover.getCalculatedOffset(popover.options.placement, popover.getPosition(), popover.$tip[0].offsetWidth, popover.$tip[0].offsetHeight);
        popover.applyPlacement(calculated_offset, popover.options.placement);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        return instance.content('Failed to load data');
      }
    });
  }
});

ในกรณีปลายทางที่ฉันใช้ส่งคืน html (รางบางส่วน)

ฉันใช้รหัสบางส่วนจากที่นี่https://stackoverflow.com/a/13565154/3984542

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.