2012-02-03 13 views
12

Estoy tratando de desarrollar un mapa SVG interactivo y parece que no se puede obtener Prototype para extender elementos SVG en línea. Aquí está mi código de ejemplo (datos de la trayectoria removidos porque es enorme):¿Puede Prototype extender elementos 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> 

El resultado de la ejecución es decir:

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

$() es simplemente niegan a extender el elemento que se le pasa si es parte del elemento SVG. ¿Hay algo sobre la interacción de Prototype con elementos XML que no entiendo, o hay una mejor manera de hacerlo?

+1

pregunta fascinante. No tengo idea de cómo los navegadores implementan elementos SVG; claramente no son nodos DOM. – Pointy

+1

JSFiddle Demo: http://jsfiddle.net/SMTsm/ –

+1

(Demostración ligeramente diferente: http://jsfiddle.net/SMTsm/2/) –

Respuesta

10

El prototipo aumenta los elementos a través de su método Element.addMethods. Si nos fijamos en la the source code se puede ver esta parte relevante:

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

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

Aquí se favorece la HTMLElement.prototype el que los elementos SVG no heredan. Vuelve a Element.prototype en esos navegadores (tos IE tos) que tampoco son compatibles con SVG. También tiene la opción de editar directamente la fuente y duplicar todas las acciones de copia en SVGElement.


Eso suena como un montón de trabajo cuando se da cuenta de que se puede utilizar un truco más simple. Los métodos estáticos Element.* aún funcionan cuando se usan directamente. En lugar de $('counties').identify(), use Element.identify('counties'). En la que podría hacer algo como esto:

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

Puede adoptar el buen equivalente funcional que es:

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

La desventaja es que pierde la capacidad de utilizar el método de encadenamiento.

+0

¡Brillante! Esto es exactamente lo que necesitaba. –

6

La sugerencia de clockworkgeek de cambiar el código fuente del prototipo funcionó muy bien para mí. .. En prototipo v 1.7, todo lo que necesita es cambiar la parte correspondiente a

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

En prototipo v 1.7.1, los cambios que se necesitan son:

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

he encontrado la solución lista para usar en this blog post

+0

¿Puedes hacer esto sin alterar la fuente? ¿No puedo extender selectivamente los elementos Svg? – kstubs

Cuestiones relacionadas