1 // TODO don't populate default attributes? 2 3 /** 4 * @private 5 * @namespace 6 */ 7 pv.Scene = pv.SvgScene = {}; 8 9 /** 10 * Updates the display for the specified array of scene nodes. 11 * 12 * @param scenes {array} an array of scene nodes. 13 */ 14 pv.SvgScene.updateAll = function(scenes) { 15 if (!scenes.length) return; 16 if ((scenes[0].reverse) 17 && (scenes.type != "line") 18 && (scenes.type != "area")) { 19 var reversed = pv.extend(scenes); 20 for (var i = 0, j = scenes.length - 1; j >= 0; i++, j--) { 21 reversed[i] = scenes[j]; 22 } 23 scenes = reversed; 24 } 25 this.removeSiblings(this[scenes.type](scenes)); 26 }; 27 28 /** 29 * Creates a new SVG element of the specified type. 30 * 31 * @param type {string} an SVG element type, such as "rect". 32 * @return a new SVG element. 33 */ 34 pv.SvgScene.create = function(type) { 35 return document.createElementNS(pv.ns.svg, type); 36 }; 37 38 /** 39 * Expects the element <i>e</i> to be the specified type. If the element does 40 * not exist, a new one is created. If the element does exist but is the wrong 41 * type, it is replaced with the specified element. 42 * 43 * @param type {string} an SVG element type, such as "rect". 44 * @return a new SVG element. 45 */ 46 pv.SvgScene.expect = function(type, e) { 47 if (!e) return this.create(type); 48 if (e.tagName == "a") e = e.firstChild; 49 if (e.tagName == type) return e; 50 var n = this.create(type); 51 e.parentNode.replaceChild(n, e); 52 return n; 53 }; 54 55 /** TODO */ 56 pv.SvgScene.append = function(e, scenes, index) { 57 e.$scene = {scenes:scenes, index:index}; 58 e = this.title(e, scenes[index]); 59 if (!e.parentNode) scenes.$g.appendChild(e); 60 return e.nextSibling; 61 }; 62 63 /** 64 * Applies a title tooltip to the specified element <tt>e</tt>, using the 65 * <tt>title</tt> property of the specified scene node <tt>s</tt>. Note that 66 * this implementation does not create an SVG <tt>title</tt> element as a child 67 * of <tt>e</tt>; although this is the recommended standard, it is only 68 * supported in Opera. Instead, an anchor element is created around the element 69 * <tt>e</tt>, and the <tt>xlink:title</tt> attribute is set accordingly. 70 * 71 * @param e an SVG element. 72 * @param s a scene node. 73 */ 74 pv.SvgScene.title = function(e, s) { 75 var a = e.parentNode, t = String(s.title); 76 if (a && (a.tagName != "a")) a = null; 77 if (t) { 78 if (!a) { 79 a = this.create("a"); 80 if (e.parentNode) e.parentNode.replaceChild(a, e); 81 a.appendChild(e); 82 } 83 a.setAttributeNS(pv.ns.xlink, "title", t); 84 return a; 85 } 86 if (a) a.parentNode.replaceChild(e, a); 87 return e; 88 }; 89 90 /** TODO */ 91 pv.SvgScene.dispatch = function(e) { 92 var t = e.target.$scene; 93 if (t) { 94 t.scenes.mark.dispatch(e.type, t.scenes, t.index); 95 e.preventDefault(); 96 } 97 }; 98 99 /** TODO */ 100 pv.SvgScene.removeSiblings = function(e) { 101 while (e) { 102 var n = e.nextSibling; 103 e.parentNode.removeChild(e); 104 e = n; 105 } 106 }; 107