关闭击倒Popover从bootstrap 3.3.6点击外面通过击倒绑定处理程序

时间:2016-03-11 17:26:45

标签: javascript jquery knockout.js twitter-bootstrap-3

我是淘汰赛的新手。我正在使用淘汰赛和bootstrap 3.3.6(最新)。我需要通过knockout-bootstrap自定义绑定处理程序单击外侧关闭bootstrap popover。我为bootstrap 3自定义绑定处理程序获得了一些插件。但是我需要在点击身体时关闭弹出窗口。

这是我的sample Fiddle

    var guid = (function(s4) {
  return function() {
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
  };
})(function() {
  return Math.floor((1 + Math.random()) * 0x10000)
    .toString(16)
    .substring(1);
});

// Outer HTML
if (!$.fn.outerHtml) {
  $.fn.outerHtml = function () {
    if (this.length === 0) {
      return false;
    }
    var elem = this[0], name = elem.tagName.toLowerCase();
    if (elem.outerHTML) {
      return elem.outerHTML;
    }
    var attrs = $.map(elem.attributes, function (i) {
      return i.name + '="' + i.value + '"';
    });
    return "<" + name + (attrs.length > 0 ? " " + attrs.join(" ") : "") + ">" + elem.innerHTML + "</" + name + ">";
  };
}


// Bind Bootstrap Popover
ko.bindingHandlers.popover = {
  init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var $element = $(element);
    var popoverBindingValues = ko.utils.unwrapObservable(valueAccessor());
    var template = popoverBindingValues.template || false;
    var options = popoverBindingValues.options || {title: 'popover',placement:'bottom'};
    var data = popoverBindingValues.data || false;
    var controlDescendants = popoverBindingValues.controlDescendants;
    if (template !== false) {
      if (data) {
        options.content = "<!-- ko template: { name: template, if: data, data: data } --><!-- /ko -->";
      }
      else {
        options.content = $('#' + template).html();
      }
      options.html = true;
    }
    $element.on('shown.bs.popover', function(event) {

      var popoverData = $(event.target).data();
      var popoverEl = popoverData['bs.popover'].$tip;
      var options = popoverData['bs.popover'].options || {};
      var button = $(event.target);
      var buttonPosition = button.position();
      var buttonDimensions = {
        x: button.outerWidth(),
        y: button.outerHeight()
      };

      ko.cleanNode(popoverEl[0]);
      if (data) {
        ko.applyBindings({template: template, data: data}, popoverEl[0]);
      }
      else {
        ko.applyBindings(viewModel, popoverEl[0]);
      }

      var popoverDimensions = {
        x: popoverEl.outerWidth(),
        y: popoverEl.outerHeight()
      };

      popoverEl.find('button[data-dismiss="popover"]').click(function() {
        button.popover('hide');
      });

      switch (options.placement) {
        case 'right':
          popoverEl.css({
            left: buttonDimensions.x + buttonPosition.left,
            top: (buttonDimensions.y / 2 + buttonPosition.top) - popoverDimensions.y / 2
          });
          break;
        case 'left':
          popoverEl.css({
            left: buttonPosition.left - popoverDimensions.x,
            top: (buttonDimensions.y / 2 + buttonPosition.top) - popoverDimensions.y / 2
          });
          break;
        case 'top':
          popoverEl.css({
            left: buttonPosition.left + (buttonDimensions.x / 2 - popoverDimensions.x / 2),
            top: buttonPosition.top - popoverDimensions.y
          });
          break;
        case 'bottom':
          popoverEl.css({
            left: buttonPosition.left + (buttonDimensions.x / 2 - popoverDimensions.x / 2),
            top: buttonPosition.top + buttonDimensions.y
          });
          break;
      }
    });

    $element.popover(options);
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
      $element.popover('destroy');
    });

    return { controlsDescendantBindings: typeof controlDescendants == 'undefined' ? true : controlDescendants };

  }
};

var ViewModel = function() {
  this.exampleText = ko.observable(" I am trying to close popover on click of out side using knockout binding handler, Please let me know how to do this");
};

ko.applyBindings(new ViewModel());

<body>
       <div class="division">
       <button data-bind="popover:{template:'settingsPopover',trigger:'click',placement:'bottom'}">settings</button>
       </div>

        <script type="text/html" id="settingsPopover">
            <div data-bind="text: $data.exampleText" type="text"> </div>


        </script>
        </body>

请为bootstrap 3.3.6建议最好的淘汰捆绑处理程序,并帮助我通过淘汰处理程序点击外侧点击弹出窗口。

1 个答案:

答案 0 :(得分:1)

这个插件的棘手之处在于它隐含地附加了按钮的点击事件。它希望该按钮用于切换弹出窗口的可见性,并且不会为您提供任何覆盖它的方法。

控制可见性的更多Knockout方法(当然)是可观察的,当事物可见时为真,否则为假。你可能有:

this.popoverIsOpen = ko.observable(false);

然后在绑定处理程序的update部分,如

var openControl = ko.unwrap(valueAccessor());
$element.popover(openControl ? 'show' : 'hide');

我为你的小提琴所做的是做一个这样的控制器,然后在主体上放置一个点击装订,总是将它设置为假:

<body data-bind="click: popoverIsOpen.bind($data, false)">

init部分,我在显示时将值设置为true,并且我禁用了按钮,因为我要将自己的点击事件发送到正文中的按钮

$element.on('shown.bs.popover', function(event) {
  $element.prop('disabled', true);
  openControl(true);

我添加了一个订阅,如果新值为false,则重新启用该按钮并通过触发按钮关闭弹出窗口。

openControl.subscribe(function (newValue) {
    if (!newValue) {
      $element.prop('disabled', false);
      $element.click();
    }
});

您可以在弹出窗口上放置一个点击装订,以防止其中的点击关闭:

click: function (d,e) {e.stopPropagation();}

Updated fiddle