【问题标题】:Twitter Bootstrap Popovers Misaligned with different sized contentTwitter Bootstrap 弹出框与不同大小的内容不一致
【发布时间】:2013-01-28 09:05:42
【问题描述】:

我已经为 twitter bootstrap popovers 创建了一个自定义绑定,我使用它来显示具有两种方式绑定的数据,但如果每个 popover 之间的内容大小不同,则对齐关闭

http://jsfiddle.net/billpull/g6vH2/1

我不确定要在此处发布的相关代码会如此糟糕,只需发布​​整个内容,请查看小提琴以获取演示。

HTML

<!doctype html>
<html>
    <body>
        <br><br><br>
        <div data-bind="foreach: items">
            <span data-bind="text: label"></span>
            <input type="checkbox" data-bind="checked: required" />
            <button data-bind="popover: {template: 'settingsPopover', trigger: 'click'}">settings</button><br>
        </div>
        <script type="text/html" id="settingsPopover">
            <h4><span class="icon-cog">&nbsp;</span> Attributes</h4>
            <label>Label</label>
            <input type="text" data-bind="value: label, valueUpdate:'afterkeydown'" />
            <label class="checkbox">
                <input type="checkbox" data-bind="checked: required" /> Required
            </label>
            <ul data-bind="foreach: options">
                <li data-bind="text: $data"></li>
            </ul>
        </script>
    </body>
</html>

JS

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

// Bind Twitter Popover
ko.bindingHandlers.popover = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var $element = $(element);
        // read popover options 
        var popoverBindingValues = ko.utils.unwrapObservable(valueAccessor());

        // set popover title 
        var popoverTitle = popoverBindingValues.title;

        // set popover template id
        var tmplId = popoverBindingValues.template;

        // set popover trigger
        var trigger = popoverBindingValues.trigger;

        // get template html
        var tmplHtml = $('#' + tmplId).html();

        // create unique identifier to bind to
        var uuid = guid();
        var domId = "ko-bs-popover-" + uuid;

        // create correct binding context
        var childBindingContext = bindingContext.createChildContext(viewModel);

        // create DOM object to use for popover content
        var tmplDom = $('<div/>', {
            "class" : "ko-popover",
            "id" : domId
        }).html(tmplHtml);

        // set content options
        options = {
            content: tmplDom[0].outerHTML,
            title: popoverTitle
        };

        // Need to copy this, otherwise all the popups end up with the value of the last item
        var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options, options);

        // bind popover to element click
        $element.bind(trigger, function (e) {
            $(this).popover(popoverOptions).popover('toggle');

            // if the popover is visible bind the view model to our dom ID
            if($('#' + domId).is(':visible')){
                ko.applyBindingsToDescendants(childBindingContext, $('#' + domId)[0]);
            }
        });

        // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
        return { controlsDescendantBindings: true };
    },
    options: {
        placement: "right",
        title: "",
        html: true,
        content: "",
        trigger: "manual",
        container: 'body'
    }
};

var ItemModel = function (data) {
    var self = this;
    self.label = ko.observable(data.label);
    self.required = ko.observable(data.required);
    self.options = ko.observableArray(ko.utils.arrayMap(data.options, function(option) {
        return option;
    }));
}

var ViewModel = function () {
  var self = this;
  self.initItems = [
      {"label":"Item 1", "required": false, "options": [1,2,3,4,5,6]},
      {"label":"Item 2", "required": true, "options": [1,2,3]},
      {"label":"Item 3", "required": false, "options": []},
      {"label":"Item 4", "required": true, "options": [1,2,3,6]}
   ];

  self.items = ko.observableArray(ko.utils.arrayMap(self.initItems, function (item) {
      return new ItemModel(item);
  }));
};

$(function(){
    ko.applyBindings(new ViewModel);
 });

http://billpull.github.com/knockout-bootstrap/

【问题讨论】:

    标签: twitter-bootstrap knockout.js popover


    【解决方案1】:

    当您将单击绑定到弹出窗口绑定中的元素时,您会初始化引导弹出窗口,然后将绑定应用到后代。这就是为什么 bootstrap popover 错误地计算它的位置(还没有嵌套的 li-s 所以它们的高度为零)。之后,淘汰赛会附加 li-s 元素和弹出框高度变化,您必须重新计算弹出框位置。

    下次单击后您重新初始化引导弹出框但不应用绑定,这种情况下弹出框位置计算正确。

    【讨论】:

    • 你能想办法解决这个问题吗,因为我不知道我是否可以在创建弹出框之前应用绑定。
    • 不幸的是,引导程序和淘汰赛有点不兼容。目前,bootstrap 会在打开时用 html 代码替换弹出框内容,这就是敲除绑定丢失的地方。 open 方法还包含位置计算,这就是为什么在应用 popover.open 和敲除绑定后不能单独重新计算它的原因。所以我建议重写 bootstrap popover - 要么将位置计算剪切为单独的方法,然后在应用敲除绑定后运行它,要么......
    • ...改变popover的逻辑,让open和hide方法只改变popover内容的可见性而不影响dom结构
    【解决方案2】:

    DEMO

    也许您可以为此使用 ko.applyBindingsToNode()。先渲染模板再绑定popover。

    $element.bind(trigger, function (e) {
    
        ko.applyBindingsToNode( tmplDom[0], {template : { name :'settingsPopover', data : viewModel}});            
        options = {
            content: tmplDom[0].outerHTML,
            title: popoverTitle
        };
    
        // Need to copy this, otherwise all the popups end up with the value of the last item
        var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options, options);            
        $(this).popover(popoverOptions).popover('show');        
      //  }
    });
    

    【讨论】:

      【解决方案3】:
      $element.bind(trigger, function (e) {
      
      ko.applyBindingsToNode( tmplDom[0], {template : { name :'settingsPopover', data : viewModel}});            
      options = {
          content: tmplDom[0].outerHTML,
          title: popoverTitle
      };
      
      // Need to copy this, otherwise all the popups end up with the value of the last item
      var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options, options);            
      $(this).popover(popoverOptions).popover('show');        
      //  }
      });
      

      弹出框由于某种原因永远不会关闭! :(

      【讨论】:

        猜你喜欢
        • 2012-08-10
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        相关资源
        最近更新 更多