Twitter bootstrap 淘汰Twitter引导Popover绑定

Twitter bootstrap 淘汰Twitter引导Popover绑定,twitter-bootstrap,knockout.js,popover,knockout-2.0,Twitter Bootstrap,Knockout.js,Popover,Knockout 2.0,我正在尝试为引用模板的twitter boostrap popover创建一个自定义绑定,但在创建popover后,绑定popover中内容的部分遇到了问题 我以前见过这个问题,但我觉得它们大部分都很混乱,我非常接近于一个可重用的解决方案,它可以按照我的意愿使用模板 //绑定Twitter Popover ko.bindingHandlers.popover={ init:function(元素、valueAccessor、allBindingsAccessor、viewModel、bindi

我正在尝试为引用模板的twitter boostrap popover创建一个自定义绑定,但在创建popover后,绑定popover中内容的部分遇到了问题

我以前见过这个问题,但我觉得它们大部分都很混乱,我非常接近于一个可重用的解决方案,它可以按照我的意愿使用模板

//绑定Twitter Popover
ko.bindingHandlers.popover={
init:function(元素、valueAccessor、allBindingsAccessor、viewModel、bindingContext){
var tmplId=ko.utils.unwrapobbservable(valueAccessor());
var tmplHtml=$('#'+tmplId.html();
var uuid=guid();
var domId=“ko bs popover-”+uuid;
变量tmplDom=$(''{
“类”:“ko popover”,
“id”:多米德
}).html(tmplHtml);
选项={
内容:tmplDom[0]。outerHTML
};
var popoverOptions=ko.utils.extend(ko.bindingHandlers.popover.options,options);
log($(元素));
控制台日志(元素);
$(元素)。绑定('单击',函数(){
$(this.popover(popover选项).popover('toggle');
applyBindings(bindingContext,document.getElementById(domId));
});
},
选项:{
位置:“对”,
标题:“,
是的,
内容:“,
触发器:“手动”
}
};
==编辑

基于下面的答案更新了代码,允许您在不使用额外的withProperties绑定的情况下执行此操作

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

        // 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
        };

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

        // bind popover to element click
        $(element).bind(trigger, function () {
            $(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]);
            }
        });

        return { controlsDescendantBindings: true };
    },
    options: {
        placement: "right",
        title: "",
        html: true,
        content: "",
        trigger: "manual"
    }
};
//绑定Twitter Popover
ko.bindingHandlers.popover={
init:function(元素、valueAccessor、allBindingsAccessor、viewModel、bindingContext){
//阅读弹出框选项
var popooverbindingvalues=ko.utils.unwrapObservable(valueAccessor());
//设置popover模板id
var tmplId=popoverBindingValues.template;
//设置popover触发器
var trigger=popooverbindingvalues.trigger;
//获取模板html
var tmplHtml=$('#'+tmplId.html();
//创建要绑定到的唯一标识符
var uuid=guid();
var domId=“ko bs popover-”+uuid;
//创建正确的绑定上下文
var childBindingContext=bindingContext.createChildContext(viewModel);
//创建用于popover内容的DOM对象
变量tmplDom=$(''{
“类”:“ko popover”,
“id”:多米德
}).html(tmplHtml);
//设置内容选项
选项={
内容:tmplDom[0]。outerHTML
};
//需要复制此项,否则所有弹出窗口都以最后一项的值结束
var popoverOptions=$.extend({},ko.bindingHandlers.popover.options);
popoverOptions.content=options.content;
//将弹出框绑定到元素单击
$(元素).绑定(触发器,函数(){
$(this.popover(popover选项).popover('toggle');
//如果popover可见,则将视图模型绑定到dom ID
if($('#'+domId).is(':visible')){
ko.ApplyBindingsTo后代(childBindingContext,$('#'+domId)[0]);
}
});
返回{ControlsDescentBindings:true};
},
选项:{
位置:“对”,
标题:“,
是的,
内容:“,
触发器:“手动”
}
};

您需要使用我的老朋友

然后,需要将数据绑定属性添加到正在生成的html中:

    var tmplDom = $('<div/>', {
        "class": "ko-popover",
        "id": domId,
        "data-bind": "withProperties: { label: '" + viewModel.label() + "', required: '" + viewModel.required() + "' }"
我还必须在弹出窗口可见时对其应用绑定,否则它似乎试图绑定到整个页面

$(element).bind('click', function () {
            $(this).popover(popoverOptions).popover('toggle');
            // If you apply this when the popup isn't visible, I think that it tries to bind to thewhole pageand throws an error
            if($('#' + domId).is(':visible'))
            {
                ko.applyBindings(viewModel, $('#' + domId)[0]);
            }
        });

这似乎也是双向的,因为您可以更改弹出窗口中的值,并更新非弹出窗口元素,但我不会撒谎,我没想到会发生这种情况

我在这里改编了另一个答案:

这对我来说效果更好,尤其是对于一个简单的popover

ko.bindingHandlers.popover = {
    init: function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor()),
            options = {};

        ko.utils.extend(options, ko.bindingHandlers.popover.options);
        ko.utils.extend(options, local);

        $(element).popover(options);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).popover("destroy");
        });
    },
    options: {
        placement: "top"
    }
};
那么绑定是:

<span data-bind="popover: { content: mySimpleTextContent }"></span>


显然,您可以覆盖其他选项。

这里还有一个版本的Knockout-popover绑定,它使用文档中定义的html模板

看看这把小提琴:

(函数(){
var templateEngine=new ko.nativeTemplateEngine();
ko.bindingHandlers.customPopover={
init:函数(元素、valueAccessor、allBindings、viewModel、bindingContext){
var placement=allBindings.get(“placement”)| |“top”,
触发器=所有绑定。获取(“触发器”)| |“单击”,
templateName=allBindings.get(“customPopover”)| | null,
$element=$(element);
$element.popover({placement:placement,trigger:trigger,html:true,content:“});
$element.on(“inserted.bs.popover”),函数(){
var container=$element.next().find(“.popover内容”)[0];
if(模板名){
renderTemplate(templateName,viewModel,{templateEngine:templateEngine},容器);
}
否则{
container.innerHTML=$element.attr(“数据内容”);
}
});
ko.utils.domNodeDisposal.addDisposeCallback(元素,函数(){
$element.popover(“销毁”);
});
}
};
})();
var模型={
链接文本:“单击我!”,
innerText:“一些奇特的文本”
};
ko.应用绑定(模型)

略微修改了的示例。内容绑定到一个可观察的对象

var模型={
链接文本:“悬停我!”,
innerText:ko.observable(“请等一下…”)
};
ko.bindingHandlers.popover={
init:函数(元素、valueAccessor、allBindings、viewModel、bindingContext){
变量$element=$(element);
var placement=allBindings.get(“placement”)| |“top”;
var trigger=allBindings.get(“trigger”)| |“hover”;
var content=allBindings.get(“popover”);
$elem
$(element).bind('click', function () {
            $(this).popover(popoverOptions).popover('toggle');
            // If you apply this when the popup isn't visible, I think that it tries to bind to thewhole pageand throws an error
            if($('#' + domId).is(':visible'))
            {
                ko.applyBindings(viewModel, $('#' + domId)[0]);
            }
        });
ko.bindingHandlers.popover = {
    init: function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor()),
            options = {};

        ko.utils.extend(options, ko.bindingHandlers.popover.options);
        ko.utils.extend(options, local);

        $(element).popover(options);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).popover("destroy");
        });
    },
    options: {
        placement: "top"
    }
};
<span data-bind="popover: { content: mySimpleTextContent }"></span>