Prototype可以扩展SVG元素吗?

时间:2012-02-03 23:26:20

标签: javascript svg prototypejs

我正在尝试开发一个交互式SVG地图,似乎无法让Prototype扩展内联SVG元素。这是我的示例代码(删除路径数据,因为它很大):

<svg id="map" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="330" height="500" viewBox="-16037,-19651 28871,44234">
    <g id="state_outline">
        <path id="state" fill="white" stroke-width="200" d="..." />
        <path id="water" fill="#a0a0ff" d="..." />
    </g>
    <g id="counties">
        <path class="county" id="adams" d="..." />
        ...
    </g>
</svg>

<div id="nottamap"></div>       

<script type="text/javascript">
    console.log($('nottamap'));
    console.log($('nottamap').identify());
    console.log($('counties'));
    console.log($('counties').identify());
</script>

运行的结果是:

<div id="nottamap">
nottamap
<g id="counties">
$("counties").identify is not a function

$()只是拒绝扩展传递给它的元素,如果它是SVG元素的一部分。有没有关于Prototype与XML元素的交互,我不理解,还是有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:10)

Prototype通过它的Element.addMethods方法扩充元素。如果您查看the source code,可以看到相关部分:

var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
  Element.prototype;

if (F.ElementExtensions) {
  copy(Element.Methods, elementPrototype);
  copy(Element.Methods.Simulated, elementPrototype, true);
}

这里有利于HTMLElement.prototype哪些SVG元素不会继承。在那些也不支持SVG的浏览器( cough IE cough )中,它会回退到Element.prototype。您可以选择直接编辑源代码并将所有复制操作复制到SVGElement


当你意识到可以使用更简单的黑客时,这听起来像是很多工作。静态Element.*方法在直接使用时仍然有效。而不是$('counties').identify()使用Element.identify('counties')。你可以在哪里做这样的事情:

$$('.classname').invoke('hide');

你可以采用很好的功能等价物:

$$('.classname').each(Element.hide);
// or replace Element.hide with Effect.fade or any other effect

缺点是你失去了使用方法链的能力。

答案 1 :(得分:6)

clockworkgeek改变原型源代码的建议对我来说非常有用。在原型v.7.7中,只需将相关部分更改为

即可
var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
  Element.prototype;

if (F.ElementExtensions) {
  if (window.SVGElement) {
    copy(Element.Methods, SVGElement.prototype);
    copy(Element.Methods.Simulated, SVGElement.prototype, true);
  }
  copy(Element.Methods, elementPrototype);
  copy(Element.Methods.Simulated, elementPrototype, true);
}

在原型v.1.7.1中,所需的更改是:

var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
  Element.prototype;

if (F.ElementExtensions) {
  if (window.SVGElement) {
    mergeMethods(SVGElement.prototype, Element.Methods);
    mergeMethods(SVGElement.prototype, Element.Methods.Simulated, true);
  }
  mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
  mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
}

我在this blog post

中找到了现成的解决方案