javascript - 单击外部 Via knockout 绑定(bind)处理程序,从 bootstrap 3.3.6 关闭 knockout Popover

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

我是 knockout 的新手。我正在使用 knockout 和 bootstrap 3.3.6(最新)。我需要通过 knockout-bootstrap 自定义绑定(bind)处理程序在单击外部时关闭引导弹出窗口。我有一些用于 bootstrap 3 自定义绑定(bind)处理程序的插件。但是我需要在点击正文时关闭弹出窗口。

这是我的 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 推荐最好的 knockout 捆绑处理程序,并帮助我通过 knockout 处理程序在单击外部时关闭弹出窗口。

最佳答案

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

一种更 Knockout 的控制可见性的方法(当然)是使用一个可观察对象,当事物可见时该对象为真,否则为假。你可能有:

this.popoverIsOpen = ko.observable(false);

然后在绑定(bind)处理程序的 update 部分类似

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

我为你的 fiddle 所做的就是制作一个这样的 Controller ,并在 body 上放置一个点击绑定(bind),并始终将其设置为 false:

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

并且在 init 部分,我在显示该值时将其设置为 true,并且我禁用了该按钮,因为我打算从 body 向该按钮发出我自己的点击事件。

$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();
    }
});

您可以在弹出框本身上放置一个点击绑定(bind),以防止点击关闭:

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

Updated fiddle .

关于javascript - 单击外部 Via knockout 绑定(bind)处理程序,从 bootstrap 3.3.6 关闭 knockout Popover,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35946340/

相关文章:

javascript - 在 window.location 中的路径后面附加来自 Angular 的参数

java - 通过 DWR 发送和接收 JSON 对象

javascript - 如何禁用react js的react-bootstrap-date-picker节点模块上的过去和今天的日期?

javascript - 使用 jquery 关闭当前模态并打开新模态

javascript - 为 jQuery 和 knockout.js 生成 javascript 代码,使其成为可重用模块

javascript - 如何为 Knockout.js 的 If 绑定(bind)添加动画?

javascript - html 源中缺少 "&lt;/style&gt;"

javascript - 天然气计算器jquery应用程序

php - JavaScript弹出密码检查

javascript - 强制 knockout 订阅在焦点/模糊后触发