如何获取Knockout.js来设置属性的namespaceURI? [英] How can I get Knockout.js to set the namespaceURI for attributes?

查看:81
本文介绍了如何获取Knockout.js来设置属性的namespaceURI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在svg中,如果我使用敲除为a节点设置xlink:href属性,则该属性的名称空间设置不正确,因此在单击时a不能用作链接./p>

例如,考虑以下包含两个链接省略号的svg.一个具有其xlink:href属性的硬编码,另一个是通过data-bind属性的剔除设置的:

<svg width="5cm" height="6cm" viewBox="0 0 5 6" version="1.1" 
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <rect x=".01" y=".01" width="4.98" height="5.98"  
        fill="none" stroke="blue"  stroke-width=".03"/> 
  <a xlink:href="#hardcoded"> 
    <ellipse data-bind="attr: blue" /> 
  </a> 
  <a data-bind="attr: { 'xlink:href': href }"> 
    <ellipse data-bind="attr: red" /> 
  </a> 
</svg>

启动淘汰赛非常简单:

ko.applyBindings( { 
  blue: { cx:2.5, cy:1.5, rx:2, ry:1, fill:"blue" },
  href: '#foo', 
  red: { cx:2.5, cy:4.5, rx:2, ry:1, fill:"red" },
});

但是只有硬编码的链接有效.如果添加一些代码以查看属性节点的namespaceURI值,则可以看到 剔除设置的xlink:href属性具有null名称空间URI,而硬编码设置为http://www.w3.org/1999/xlink.

Array.forEach( document.getElementsByTagName('a'), function(a){
  a.setAttribute('title', 'xlink:href namespaceURI = ' + a.getAttributeNode('xlink:href').namespaceURI);
});

您可以在小提琴中查看所有这些内容.

是否有一种简单的方法可以告诉敲除属性的正确名称空间,还是我需要编写自定义绑定?

解决方案

我的后备解决方案是添加此自定义绑定:

ko.bindingHandlers['attr-ns'] = {
  update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    ko.utils.objectForEach( ko.unwrap( valueAccessor() ), function(name, value){
      var prefixLen = name.indexOf(':');
      var prefix    = name.substr( 0, prefixLen );
      var namespace = prefixLen < 0 ? null : element.lookupNamespaceURI( prefix );

      element.setAttributeNS( namespace, name, ko.unwrap( value ) );
    });
  }
};

并更改模板以使用我定义的attr-ns绑定:

<a data-bind="attr-ns: { 'xlink:href': href }">
  <ellipse data-bind="attr: red" />
</a>

这似乎行得通,但是如果不需要的话,我宁愿不这样做.更多的自定义代码=更多可能出错的地方.

您可以在小提琴中查看此解决方案.

In an svg, if I use knockout to set the xlink:href attribute for an a node, the attribute's namespace isn't set correctly, so the a doesn't work as a link when clicked.

For example, consider the following svg that contains two linked ellipses. One has its xlink:href attribute hardcoded, the other is set by knockout via the data-bind attribute:

<svg width="5cm" height="6cm" viewBox="0 0 5 6" version="1.1" 
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <rect x=".01" y=".01" width="4.98" height="5.98"  
        fill="none" stroke="blue"  stroke-width=".03"/> 
  <a xlink:href="#hardcoded"> 
    <ellipse data-bind="attr: blue" /> 
  </a> 
  <a data-bind="attr: { 'xlink:href': href }"> 
    <ellipse data-bind="attr: red" /> 
  </a> 
</svg>

Getting knockout to run is pretty easy:

ko.applyBindings( { 
  blue: { cx:2.5, cy:1.5, rx:2, ry:1, fill:"blue" },
  href: '#foo', 
  red: { cx:2.5, cy:4.5, rx:2, ry:1, fill:"red" },
});

But only the link for the hardcoded one works. If I add some code to view the namespaceURI value for the attribute node, I can see that the xlink:href attribute set by knockout has a null namespaceURI, as opposed to the hardcoded one, which is set to http://www.w3.org/1999/xlink.

Array.forEach( document.getElementsByTagName('a'), function(a){
  a.setAttribute('title', 'xlink:href namespaceURI = ' + a.getAttributeNode('xlink:href').namespaceURI);
});

You can view all this in a fiddle.

Is there an easy way to tell knockout what the correct namespace should be for an attribute, or do I need to write a custom binding?

解决方案

My fallback solution is to add this custom binding:

ko.bindingHandlers['attr-ns'] = {
  update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    ko.utils.objectForEach( ko.unwrap( valueAccessor() ), function(name, value){
      var prefixLen = name.indexOf(':');
      var prefix    = name.substr( 0, prefixLen );
      var namespace = prefixLen < 0 ? null : element.lookupNamespaceURI( prefix );

      element.setAttributeNS( namespace, name, ko.unwrap( value ) );
    });
  }
};

and change the template to use the attr-ns binding I defined:

<a data-bind="attr-ns: { 'xlink:href': href }">
  <ellipse data-bind="attr: red" />
</a>

This seems to work ok, but I'd rather not do this if I don't have to. More custom code = more that could go wrong.

You can view this solution in a fiddle.

这篇关于如何获取Knockout.js来设置属性的namespaceURI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆