I have almost identical multiple divs on a page. They all have graphs inside I want some of them to have popovers when they are hovered.
I want to decide for each div if the popover is displayable or not. Is there a property that I can include inside options such as "diplay: false" ?
HTML
<div id="{{graph.id}}" data-ng-repeat="graph in graphs" data-placement="top" data-original-title="Parameters"></div>
JS
var options = {
html: true,
placement: 'top',
trigger : 'hover',
content: function() {
return $('#info-chart-' + currentObj.id).html();
}
}
$(currentObj.id).popover(options);
You can add some class to those elements on which you don't want popup like nopop class.
<div id="{{graph.id}}" class="nopop" data-ng-repeat="graph in graphs" data-placement="top" data-original-title="Parameters"></div>
Now change the jquery code.
$(currentObj.id).not(".nopop").popover(options);
You can check here --> JsFiddle
Related
I have a container with some details and a button inside it. and the container has popover behavior when we hover over it. the problem is I need to disable popover behavior while hovering over the button inside it. heres the fiddle Thanks in advance.
<div class="container">
<p>name: </p>
<p>age: </p>
<p>department:</p>
<button class="btn btn-primary">Connect</button>
</div>
$('.container').popover({
trigger: "hover",
content: "sample content"
})
Add below codes into JavaScript block.
$('.container button').mouseover(function(e) {
$('.container').popover('hide');
});
$('.container button').mouseout(function(e) {
$('.container').popover('show');
});
You can do like this:
$('.container button').hover(function(){
$('.container').popover('hide');
},function(){
$('.container').popover('show');
});
Fiddle: https://jsfiddle.net/fwcrt2hy/
I suggest...
$('.container p').popover({
trigger: "hover",
content: "sample content"
});
(i.e. changing the selector to .container p) because the only content in your .container besides the <button> is paragraph (<p>) elements.
Possible Drawbacks
If your .container has padding, the padding area will not trigger the popover behavior.
You can use selector option within popover() method. If a selector is provided, popover objects will be delegated to the specified targets. In practice, this is used to enable dynamic HTML content to have popovers added.
$(function () {
$('.container').popover({
trigger: "hover",
content: "sample content",
selector: 'p' //added this line
})
});
Source: https://getbootstrap.com/docs/4.0/components/popovers/#options
I have a button:
<button type="button" class="btn btn-sm btn-primary" data-bind="attr: { 'data-target': '#MoreOptions' + Provider() }" data-toggle="collapse">More Options</button>
That controls when this div is open or closed to show 'more options'.
<div class="panel-collapse" data-bind="attr: { id: 'MoreOptions' + Provider() }, css: { collapse: $root.IsCollapsed }">---</div>
And I use a Knockout.js observable to keep it open when the data refreshes inside the div. I don't want a data refresh to collapse the div. The issue is when I do this and keep the div open, the button thinks that the div is closed. So the next time the user clicks the button, the div closes real quick and opens back up again, requiring two clicks on the button to get the div to close.
The expected behavior is to keep the div open during a data refresh, but have the button know that the div is open and close it with just one click.
I've set the CSS collapse with knockout in the div and I'm looking for a similar way to set the button for it to know that the div is not collapsed.
I've noticed that when the button is clicked to expand the div, the aria-expanded attribute is set to true where it didn't exist when the button is initially rendered; and when the button is clicked to collapse the div, the CSS property 'collapsed' is added to the button. I've played around with adding and changing these via knockout with no success.
It should be noted that the button is refreshed with the data.
I've decided to remove the bootstrap toggle button functionality and just go with the jQuery toggle in combination with knockout. The jQuery way just offers more control.
<button type="button" class="btn btn-sm btn-primary"
data-bind="click: $root.ChangeMoreOptions">
More Options
</button>
<div id="MoreOptionsDiv" style="padding-top: 10px; display: none;">
--- content ---
</div>
Knockout:
//Open or close div
self.ChangeMoreOptions = function () {
if (self.IsCollapsed() === true) {
$('#MoreOptionsDiv').slideToggle('slow', function () {
// Animation complete.
});
self.IsCollapsed(false);
} else {
$('#MoreOptionsDiv').slideToggle('slow', function () {
// Animation complete.
});
self.IsCollapsed(true);
}
}
//Keep div open on refresh if it is already open
//Search for 'none' in the style display: none
self.FixMoreOptions = function () {
if (($('#MoreOptionsDiv').attr('style').search('none') > -1)
&& (self.IsCollapsed() === false)) {
//Toggle closed div back to open
$('#MoreOptionsDiv').slideToggle('slow', function () {
// Animation complete.
});
}
}
i am quite new with this delegate thing for dynamic elements. so today i tested again with a generated dynamic template from some example in stackover for popover.
here is my dynamic html content.
<a id="testpop" class="btn btn-primary" data-placement="top" data-popover-content="#a1" data-toggle="popover" data-trigger="focus" href="#" tabindex="0">Popover Example</a>
<!-- Content for Popover #1 -->
<div class="hidden" id="a1">
<div class="popover-heading">
This is the heading for #1
</div>
<div class="popover-body">
This is the body for #1
</div>
</div>
and then, i have this script on my js
$('#resultContent').on('click','#testpop', function(e) { //use on if jQuery 1.7+
// Enables popover #2
$("[data-toggle=popover]").popover({
html : true,
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
});
resultContent is the div here where i add .html all my html codes.
i manage to attached the delegate event (i think) but is acting strange as my 1st click on the testpop button, the popover won't show. Until i press the 2nd and 3rd time only it will pop up. Am i doing this delegating wrong?
credits for this test code: HTML inside Twitter Bootstrap popover
You forgot to add a trigger in the popover options. The data-trigger in the element doesn't do too much when you really only initialize the popover() once you click the element. In fact, your JS code would propably work better like so:
$("[data-toggle=popover]").popover({
html : true,
trigger: 'click',
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
EDIT
Popover should generally be initialized on page load:
$("[data-toggle=popover]").popover();
Putting it inside a click event will not enable popover on the element until you click it first.
Removing the click event from your original JS code should enable it on page load.
If however, the element you mean to attach the popover to is dynamically added to the DOM after page load, you should reinitalize the popover after adding it.
Wrapping the popover in a function would make that much easier.
function addPopover(selector){
$(selector).popover({
html : true,
trigger: 'click',
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
}
And whenever you add an element to the page that should have a popover, you simply call the function, with a selector for the element. Example for the element you have in your code:
addPopover("[data-toggle=popover]");
In your code, you are configuring the popover on click event of the button.
So, this is how it happens.
Click the anchor link
Initialize the popover with options. (This doesnt mean it displays the popover, it is just a initialization)
Click on the popover again (Popover is already bound because of the earlier call and then it shows)
Also, you need to ensure the popover is not bound to the element again and again to avoid repeated popover bindings.
$('#resultContent').on('click', '#testpop', function(e) { //use on if jQuery 1.7+
// Enables popover #2
$("[data-toggle=popover]").popover({
html: true,
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
}).popover('show');
// Explicitly show the popover.
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div id="resultContent">
<a id="testpop" class="btn btn-primary" data-placement="bottom" data-popover-content="#a1" data-toggle="popover" data-trigger="focus" href="#" tabindex="0">Popover Example</a>
</div>
<!-- Content for Popover #1 -->
<div class="hidden" id="a1">
<div class="popover-heading">
This is the heading for #1
</div>
<div class="popover-body">
This is the body for #1
</div>
</div>
I have a link which opens a popover, and in the popover I load content from a div.
The content is some sharethis.com buttons and the javascript which is presented by sharethis to be added to the page.
So the set up looks like this :
Button and content :
<i class="fa fa-share"></i> Share
<div id="share_this_btns" class="hidden">
<script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script>
<script type="text/javascript">stLight.options({publisher: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx", doNotHash: false, doNotCopy: false, hashAddressBar: false});</script>
<div class="margin-10"><span class='st_facebook_hcount margin-10' displayText='Facebook'></span></div>
<div class="margin-10"><span class='st_twitter_hcount margin-10' displayText='Tweet'></span></div>
<span class='st_pinterest_hcount' displayText='Pinterest'></span>
</div>
Popover init
$('#shareHead').popover({
title : "Share",
html : true,
content : function(){
return $('#share_this_btns').html();
},
placement : 'bottom'
});
The buttons turn up just fine and also show the count - however, they can't be clicked.
I have also tried putting the script tags outside of the content div, and removing them completely (as there is a second instance of the sharethis script, but with a different publisher ID).
Can you please advise?
EDIT//
It seems to work every now and then without me changing anything. So the scripts seem to run, maybe it is an issue with how the elements are layered?
Ok I figured it out. I cannot just load sharethis data into the popover, so what I did is this :
I added the normal tags provided by sharethis, and the reinitialised the buttons by calling stButtons.locateElements();
For that, I made a custom callback (courtesy of https://stackoverflow.com/a/14727204/1206437 ) where I call this init.
After that, however, the popover isn't positioned correctly because the width changes after the load. So I also wrote a function that resizes everything. It has to be in a setTimeout because locateElements() doesn't seem to have a callback, and so the width changes again after the numbers of tweets and shares are loaded.
The two sharethis scripts are already loaded in the header.
The final body code looks like this :
Button that opens popover
<div id="btnParent_head">
<button class="btn btn-white opaque30 btn-large marginR10" id="shareHead"><i class="fa fa-share"></i> Share</button>
<i class="fa fa-thumbs-o-up"></i> Pledge
<button href="#contact" id="contactHead" data-fancybox-href="#contactBox" class="btn btn-white opaque30 btn-large marginL10"><i class="fa fa-envelope"></i> Contact</button>
</div>
Javascript/JQuery
$(document).load(function(){
$('#shareHead').popover({
title : "Share",
html : true,
content : function(){
var text = '';
text += '<div class="margin-10"><span class="st_facebook_hcount margin-10" displayText="Facebook"></span></div>';
text += "<div class='margin-10'><span class='st_twitter_hcount margin-10' displayText='Tweet'></span></div>";
text += "<span class='st_pinterest_hcount' displayText='Pinterest'></span>";
return text;
},
placement : 'bottom',
callback : function(){
reloadStBtns(resizePopover,$('#btnParent_head .popover'),$('#shareHead'));
}
});
});
var tmp = $.fn.popover.Constructor.prototype.show;
$.fn.popover.Constructor.prototype.show = function () {
tmp.call(this);
if (this.options.callback) {
this.options.callback();
}
}
function reloadStBtns(callback,popover,parent) {
stButtons.locateElements();
setTimeout(function(){
callback(popover,parent);
},500);
}
function resizePopover(popover, parent) {
var i_width = parent.outerWidth();
var i_swidth = popover.outerWidth();
var i_nleft = (i_width - i_swidth)/2
popover.css({'left':i_nleft});
}
I wish there was a better solution than doing the setTimeout, but I couldn't find anything.
It doesn't look like you have linked the share buttons up to anything. Try wrapping each span pointing to a resource in an anchor tag e.g.:
<span class='st_facebook_hcount margin-10' displayText='Facebook'></span>
Also, it doesn't actually matter where your Javascript goes, however you should put it all at the end of your document as it will make your page load faster.
my php spits out all my cars in a loop so each car gets the same div id's and classes but different information
MY PROBLEM is that my plug in only works for the same div which is the first
thats because all of them are named the same
how can i make this function intelligent to know which div content is supposed to hide or show
check out my example http://jsfiddle.net/S2HEw/
(function ($) {
$.fn.showHide = function (options) {
//default vars for the plugin
var defaults = {
speed: 1000,
easing: '',
changeText: 0,
showText: 'Show',
hideText: 'Hide'
};
var options = $.extend(defaults, options);
$(this).click(function () {
// optionally add the class .toggleDiv to each div you want to automatically close
$('.toggleDiv:hidden').slideUp(options.speed, options.easing);
// this var stores which button you've clicked
var toggleClick = $(this);
// this reads the rel attribute of the button to determine which div id to toggle
var toggleDiv = $(this).attr('rel');
// here we toggle show/hide the correct div at the right speed and using which easing effect
$(toggleDiv).slideToggle(options.speed, options.easing, function() {
// this only fires once the animation is completed
if(options.changeText==1){
$(toggleDiv).is(":visible") ? toggleClick.text(options.hideText) : toggleClick.text(options.showText);
}
});
return false;
});
};
})(jQuery);
$(document).ready(function(){
$('.show_hide').showHide({
speed: 250, // speed you want the toggle to happen
easing: '', // the animation effect you want. Remove this line if you dont want an effect and if you haven't included jQuery UI
changeText: 1, // if you dont want the button text to change, set this to 0
showText: 'View',// the button text to show when a div is closed
hideText: 'Close' // the button text to show when a div is open
});
});
the html, there is many of this ones, all of them with the same name and thats why my toggle button fails,
<a class="show_hide" href="#" rel="#slidingDiv">View</a>
<div id="slidingDiv" class="toggleDiv" style="display: none;">
<div class="right">
</div>
</div>
note that i cant update my php loop so i really need to find a way for jquery to know which div it is working with even they all have the same div id? i can have php do a increasing number and append it to the class and then on the jquery side ?? see this is where im stuck
i have no idea how to make this work dynamically
You have duplicate ids for the slidingDiv elements. id of an element must be unique in a document
From doc for id-attribure
The id attribute specifies its element's unique identifier (ID). The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.
<!-- DIV 1-->
<a class="show_hide" href="#" rel="#slidingDiv1">View</a>
<div id="slidingDiv1" class="toggleDiv" style="display: none;">
<div class="right">
DIV 1
</div>
</div>
<!-- DIV 2-->
<a class="show_hide" href="#" rel="#slidingDiv2">View</a>
<div id="slidingDiv2" class="toggleDiv" style="display: none;">
<div class="right">
DIV 2
</div>
</div>
<!-- DIV 3-->
<a class="show_hide" href="#" rel="#slidingDiv3">View</a>
<div id="slidingDiv3" class="toggleDiv" style="display: none;">
<div class="right">
DIV 3
</div>
</div>
Also, need to use :visible instead of :hidden
$('.toggleDiv:visible').slideUp(options.speed, options.easing);
Demo: Fiddle