2013-02-12 32 views
2

我已创建自定义为敲除用于Twitter的引导popovers结合和我使用与在酥料饼的双向结合显示的数据,但是如果内容的大小是每个酥料饼之间不同排列是关闭Twitter的引导Popovers未对齐具有不同尺寸的内容

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/

回答

0

DEMO

可能是你可以使用ko.applyBindingsToNode()这一点。首先渲染模板然后绑定弹出窗口。

$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');   
    // } 
}); 
0

当您绑定点击元素在你的酥料饼的结合,你初始化引导酥料饼,然后appply结合的后代。这就是为什么bootstrap popover不正确地计算它的位置(没有嵌套的li-s,所以它们的高度为零)。在这之后,淘汰赛会添加li-s元素和popover高度更改,并且您必须重新计算popover位置。

下一个后,点击重新初始化引导酥料饼,但不应用绑定,这种情况下酥料饼的位置,正确地计算。

+0

你能想出反正,因为我不知道我是否可以在popover创建之前应用绑定 – BillPull 2013-02-13 19:20:58

+0

不幸的是,bootstrap和knockout有点不兼容,目前引导程序用html代码替换popover内容在打开的时候,这是敲除绑定丢失的地方,另外open方法包含了位置计算,这就是为什么在popover.open和knockout绑定应用后你不能单独重新计算它,所以我建议重写bootstrap popover - 的位置计算,并在应用敲除绑定后运行它或... – Kasheftin 2013-02-14 11:29:36

+0

...更改弹出窗口的逻辑,以便打开和隐藏方法仅更改弹出窗口内容的可见性而不影响dom结构 – Kasheftin 2013-02-14 11:30:15

0
$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');   
// } 
}); 

的酥料饼永远不会关闭出于某种原因! :(