Gaining Reference to all elements of a loaded(Snap.load) element to animate color

2,011 views
Skip to first unread message

Thomas Murphy

unread,
Feb 19, 2014, 4:24:27 PM2/19/14
to sna...@googlegroups.com
Hi all,

I'm having trouble understanding how to get a reference to an element initiated during Snap.load.

I'm working with a structure like this.

Snap.load('/path/to/my/element.svg', function(f){
    mySnap
.add(f);
}



This works fine, but if I try something like

f.attr({


class: 'myClass'


});



while within the load call, I get the error Object #<w> has no method 'attr'


I'm misunderstanding something about the nature of the SVG object being loaded, and the docs seem scare on this issue.

Thomas Shinnick

unread,
Feb 19, 2014, 6:30:44 PM2/19/14
to sna...@googlegroups.com

Snap.load()  loads an SVG file, but doesn't put it any particular place.  It is not yet found in the page as a DOM element, but is a "DOM fragment".  It is only partially a 'citizen' !  It doesn't yet have all the rights and APIs of a DOM citizen.  :-)

The error
      TypeError: f.attr is not a function
          f.attr({class: 'class1'});
is speaking true - the fragment doesn't have that API .attr()  

Snap  loads a file and says it is a Snap 'Fragment'  (paralleling HTML's DOMFragment).   (The variable name 'f' was rather too short for 'frag' or 'fragment', a little...) 

This thing doesn't have all the APIs that a Snap 'Element' has.  It does have a couple of them though:
      node
          DocumentFragment { children=HTMLCollection, firstElementChild=svg, lastElementChild=svg, more...}
      select
          function()
      selectAll
          function()
      __proto__
          Fragment { select=function(), selectAll=function()}

You can use  .selectAll()  to get to the elements within your fragment.

      var list = f.selectAll('*');
      console.log(list);
      for(var i=0 ; i < list.length ; i++) {
        list[i].attr({'class': 'class1'});
      }


(You could also be more selective by saying .selectAll('path') for example.  (lookup CSS selectors) )

But of course 'f' is still just a fragment, and not yet part of the page.  You need to insert the fragment at the desired place in your page.  Perhaps you have a <div> with an .id where you want to put it.

    var previewDiv = document.getElementById("preview_div");

    previewDiv.appendChild(f.node);

or equivalently for the second statement:

    Snap(previewDiv).append(f);


Snap.svg does not replace the web page DOM system but has to coexist with it.  Snap didn't come up with the "it's only a fragment for now" thing. You will find yourself having to consult the "other world" a lot.  And I nearly live in the browser debuggers.... :-/
Reply all
Reply to author
Forward
0 new messages