Skip to content

Instantly share code, notes, and snippets.

@martinnormark
Last active November 29, 2016 10:58
Show Gist options
  • Save martinnormark/4466472 to your computer and use it in GitHub Desktop.
Save martinnormark/4466472 to your computer and use it in GitHub Desktop.
Backbone implementation of the Twitter Bootstrap Popover view
(function () {
App.Views.PopoverView = Backbone.View.extend({
initialize: function (options) {
_.bindAll(this, "render", "setContent", "show", "hide", "toggle", "destroy", "remove");
this.offsetTop = 30;
this.offsetLeft = 0;
if (options && options.header) {
this.Header = options.header;
}
if (options && options.content) {
this.Content = options.content;
}
if (options && options.placement) {
this.Placement = options.placement;
}
if (options && options.trigger) {
this.Trigger = options.trigger;
}
if (options && options.delay) {
this.Delay = options.delay;
}
if (options && options.offsetTop && $.isNumeric(options.offsetTop)) {
this.offsetTop += options.offsetTop;
}
if (options && options.offsetLeft && $.isNumeric(options.offsetLeft)) {
this.offsetLeft += options.offsetLeft;
}
},
render: function (show) {
var that = this;
this.popoverElement = $("<div />").addClass("popover-dummy").css("position", "absolute").appendTo($(document.body));
this.popover = this.popoverElement.popover({
title: this.Header,
content: this.Content || "",
placement: this.Placement || "left",
trigger: this.Trigger || "click",
delay: this.Delay || 0
}).data("popover");
if (show === true) {
this.show();
}
return this;
},
setContent: function (el) {
this.$body.empty().append(el);
},
show: function () {
var position = this.$el.offset(),
height = this.$el.height();
this.popoverElement.css("top", position.top + (height / 2));
this.popoverElement.css("left", position.left + this.offsetLeft);
this.popoverElement.popover("show");
this.$body = this.popover.$tip.find(".popover-content");
if (!this.Content) {
this.setContent(new App.Views.WaitSpinnerView().render().$el);
}
if (this.popover.options.placement === "left" || this.popover.options.placement === "right") {
this.popover.$tip.find(".arrow").css("top", this.offsetTop);
}
$("<button type=\"button\" class=\"close\" data-dismiss=\"modal\">×</button>")
.appendTo(this.popover.$tip.find(".popover-title"))
.one("click", this.remove);
},
hide: function () {
this.popoverElement.popover("hide");
},
toggle: function () {
this.popoverElement.popover("toggle");
},
destroy: function () {
this.popoverElement.popover("destroy");
this.popoverElement.remove();
this.popoverElement = null;
},
remove: function () {
this.destroy();
}
});
})();
@thadk
Copy link

thadk commented Aug 19, 2013

I added html attribute to passthrough to bootstrap, my button is #button

this.popoverView = new App.Views.PopoverView({
          el: '#Button',
          content: InteriorView.render().el,
          html: true, /*XSS warning from bootstrap, avoid using this technique on user data*/
          placement: 'bottom'
        });

events: {
  "click #Button": "showPopover"
},
showPopover: function () {
  this.popoverView.render(true);
},

It rendered mostly like a normal popover, but hasn't centered perfectly for me yet. For me, it successfully skirts the problem of the Backbone events getting detached when bootstrap does a $.remove() on the content element for the first time.

Make sure to remove or redefine the Spinner.

@natalan
Copy link

natalan commented Feb 11, 2015

Use .data("bs.popover") instead of .data("popover") in Bootstrap 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment