~doctormo/smil/seperate-enable

« back to all changes in this revision

Viewing changes to smil.user.js

  • Committer: David
  • Date: 2008-03-12 00:11:07 UTC
  • Revision ID: leunen.d@gmail.com-20080312001107-lft6ltxjdkqb813n
failed attempt to workaround the use bug

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
@id {7eeff186-cfb4-f7c3-21f2-a15f210dca49}
 
3
@name FakeSmile
 
4
@version 0.1
 
5
@description SMIL implementation in ECMAScript
 
6
@creator David Leunen (leunen.d@gmail.com)
 
7
@homepageURL http://leunen.d.free.fr/fakesmile
 
8
@updateURL http://leunen.d.free.fr/fakesmile/update.rdf
 
9
@ff_min_version 2.0
 
10
@ff_max_version 2.0.0.*
 
11
*/
1
12
// ==UserScript==
2
13
// @name           smil
3
14
// @namespace      svg.smil
4
15
// ==/UserScript==
5
16
 
6
17
var mpf = 25; // milliseconds per frame
 
18
var workaroundUses = false;
7
19
 
8
20
var svgns="http://www.w3.org/2000/svg";
9
21
var xlinkns="http://www.w3.org/1999/xlink";
13
25
var animations = new Array(); // running animators
14
26
var timeZero;
15
27
 
 
28
function registerInstance(instance) {
 
29
  var corr = instance.correspondingElement;
 
30
  var instList = corr.instanceList;
 
31
  if (!instList) {
 
32
    instList = new Array();
 
33
    corr.instanceList = instList;
 
34
  }
 
35
  instList.push(instance);
 
36
  var children = instance.childNodes;
 
37
  for(var i=0; i<children.length ;i++)
 
38
    registerInstance(children.item(i));
 
39
}
 
40
 
16
41
/**
17
42
 * if declarative animations are not supported,
18
43
 * the document animations are fetched and registered
24
49
    var svgs = document.getElementsByTagNameNS(svgns,"svg");
25
50
    if (svgs.length==0)
26
51
      return;
27
 
    
28
 
    // because events are not dispatched to used elements in gecko
 
52
 
29
53
    var uses = document.getElementsByTagNameNS(svgns,"use");
30
 
    var newIds = new Object();
31
54
    for(var i=uses.length-1; i>=0 ;i--) {
32
55
      var use = uses.item(i);
33
 
      var href = use.getAttributeNS(xlinkns, "href");
34
 
      var ref = document.getElementById(href.substring(1));
35
 
      var clone = ref.cloneNode(true);
36
 
      var suff = "workaroundUseBug"+i;
37
 
      var all = clone.getElementsByTagName("*");
38
 
      var useId = use.id;
39
 
      if (!useId) {
40
 
        var oldId = clone.id;
41
 
        if (oldId) {
42
 
          var newId = oldId+suff;
43
 
          newIds[oldId] = newId;
44
 
          clone.setAttribute("id", newId);
45
 
        }
46
 
      } else
47
 
        clone.setAttribute("id", useId);
48
 
      for(var j=0; j<all.length ;j++) {
49
 
        var elem = all[j];
50
 
        var oldId = elem.id;
51
 
        if (oldId) {
52
 
          var newId = oldId+suff;
53
 
          newIds[oldId] = newId;
54
 
          elem.setAttribute("id", newId);
55
 
        }
56
 
      }
 
56
      if(use.instanceRoot) {
 
57
        registerInstance(use.instanceRoot);
 
58
      } 
 
59
    }
 
60
    
 
61
    
 
62
    if (workaroundUses) {
 
63
      // because events are not dispatched to used elements in gecko
 
64
      var uses = document.getElementsByTagNameNS(svgns,"use");
 
65
      var newIds = new Object();
 
66
      for(var i=uses.length-1; i>=0 ;i--) {
 
67
        var use = uses.item(i);
 
68
        var href = use.getAttributeNS(xlinkns, "href");
 
69
        var ref = document.getElementById(href.substring(1));
 
70
        var clone = ref.cloneNode(true);
 
71
        var suff = "workaroundUseBug"+i;
 
72
        var all = clone.getElementsByTagName("*");
 
73
        var useId = use.id;
 
74
        if (!useId) {
 
75
          var oldId = clone.id;
 
76
          if (oldId) {
 
77
            var newId = oldId+suff;
 
78
            newIds[oldId] = newId;
 
79
            clone.setAttribute("id", newId);
 
80
          }
 
81
        } else
 
82
          clone.setAttribute("id", useId);
 
83
        for(var j=0; j<all.length ;j++) {
 
84
          var elem = all[j];
 
85
          var oldId = elem.id;
 
86
          if (oldId) {
 
87
            var newId = oldId+suff;
 
88
            newIds[oldId] = newId;
 
89
            elem.setAttribute("id", newId);
 
90
          }
 
91
        }
 
92
        for(var j=0; j<all.length ;j++) {
 
93
          var elem = all[j];
 
94
          var href = elem.getAttributeNS(xlinkns, "href");
 
95
          if (href && newIds[href.substring(1)])
 
96
            elem.setAttributeNS(xlinkns, "href", newIds[href.substring(1)]);
 
97
          var begin = elem.getAttribute("begin");
 
98
          if (begin) {
 
99
            for(var oldId in newIds) {
 
100
              if(newIds.hasOwnProperty(oldId))
 
101
                begin = begin.replace(oldId+".", newIds[oldId]+".");
 
102
            }
 
103
            //console.log(begin);
 
104
            elem.setAttribute("begin", begin);
 
105
          }
 
106
          var end = elem.getAttribute("end");
 
107
          if (end) {
 
108
            for(var oldId in newIds) {
 
109
              if(newIds.hasOwnProperty(oldId))
 
110
                end = end.replace(oldId+".", newIds[oldId]+".");
 
111
            }
 
112
            elem.setAttribute("end", end);
 
113
          }
 
114
        }
 
115
 
 
116
        if(use.hasAttribute("opacity"))
 
117
          clone.setAttribute("opacity", use.getAttribute("opacity"));
 
118
        if(use.hasAttribute("transform"))
 
119
          clone.setAttribute("transform", use.getAttribute("transform"));
 
120
        if(use.hasAttribute("display"))
 
121
          clone.setAttribute("display", use.getAttribute("display"));
 
122
        use.parentNode.insertBefore(clone,use);
 
123
        use.parentNode.removeChild(use);
 
124
      } 
 
125
 
 
126
      var all = document.getElementsByTagName("*");
57
127
      for(var j=0; j<all.length ;j++) {
58
128
        var elem = all[j];
59
129
        var href = elem.getAttributeNS(xlinkns, "href");
77
147
          elem.setAttribute("end", end);
78
148
        }
79
149
      }
80
 
 
81
 
      if(use.hasAttribute("opacity"))
82
 
        clone.setAttribute("opacity", use.getAttribute("opacity"));
83
 
      if(use.hasAttribute("transform"))
84
 
        clone.setAttribute("transform", use.getAttribute("transform"));
85
 
      if(use.hasAttribute("display"))
86
 
        clone.setAttribute("display", use.getAttribute("display"));
87
 
      use.parentNode.insertBefore(clone,use);
88
 
      use.parentNode.removeChild(use);
89
 
    } 
90
 
       
91
 
    var all = document.getElementsByTagName("*");
92
 
    for(var j=0; j<all.length ;j++) {
93
 
      var elem = all[j];
94
 
      var href = elem.getAttributeNS(xlinkns, "href");
95
 
      if (href && newIds[href.substring(1)])
96
 
        elem.setAttributeNS(xlinkns, "href", newIds[href.substring(1)]);
97
 
      var begin = elem.getAttribute("begin");
98
 
      if (begin) {
99
 
        for(var oldId in newIds) {
100
 
          if(newIds.hasOwnProperty(oldId))
101
 
            begin = begin.replace(oldId+".", newIds[oldId]+".");
102
 
        }
103
 
        //console.log(begin);
104
 
        elem.setAttribute("begin", begin);
105
 
      }
106
 
      var end = elem.getAttribute("end");
107
 
      if (end) {
108
 
        for(var oldId in newIds) {
109
 
          if(newIds.hasOwnProperty(oldId))
110
 
            end = end.replace(oldId+".", newIds[oldId]+".");
111
 
        }
112
 
        elem.setAttribute("end", end);
113
 
      }
114
150
    }
115
 
    
116
151
 
117
152
    var animates = document.getElementsByTagNameNS(svgns,"*");
118
153
    for(var j=0; j<animates.length ;j++) {
208
243
        if(element==null)
209
244
          continue;
210
245
        var event = time.substring(io+1);
211
 
        //console.log(element);
212
246
        
213
 
        var call = function() {func.call(me, offset)}; 
 
247
        var call = funk(func, me, offset); 
214
248
        element.addEventListener(event, call, false);
 
249
        if (element.instanceList) {
 
250
          for(var j=0; j<element.instanceList.length  ;j++) {
 
251
            if(element.instanceList[j].addEventListener)
 
252
              element.instanceList[j].addEventListener(event, call, false);
 
253
          }
 
254
        }
215
255
      } else {
216
256
        time = toMillis(time);
217
257
        func.call(me, time);
246
286
   * not called when repeating
247
287
   */
248
288
  begin : function(offset) {
249
 
    //console.log(this.anim);
250
289
    if (this.restart=="never" || (this.running && this.restart=="whenNotActive"))
251
290
      return;
252
 
    if (offset!=null) {
 
291
    if (offset!=null && offset>=0) {
253
292
      var me = this;
254
293
      var myself = this.begin;
255
294
      var call = function() {myself.call(me)};
257
296
      return;
258
297
    }
259
298
 
 
299
    this.startTime = new Date();
 
300
    if (offset && offset<0)
 
301
      this.startTime.setTime(this.startTime.getTime()+offset);
260
302
    this.stop();
261
303
    this.running = true;
262
304
    this.recordInitVal();
263
305
    if (this.anim.nodeName=="set")
264
306
      this.step(this.to);
265
 
    // what does dur="indefinite" mean anyway ?
266
 
    // it makes sense for <set> only, I think.
267
 
    var dur = this.dur;
268
 
    if (dur==null || dur=="" || dur=="indefinite") {
269
 
      for(var i=0; i<this.beginListeners.length ;i++)
270
 
        this.beginListeners[i].call();
271
 
      return;
272
 
    }
273
307
    this.iteration = 0;
274
 
    this.start();
275
 
    if (offset && offset<0)
276
 
      this.iterBegin.setTime(this.iterBegin.getTime()+offset);
277
 
    this.startTime = new Date();
 
308
    this.start(this.startTime);
278
309
    animations.push(this);
279
310
    for(var i=0; i<this.beginListeners.length ;i++)
280
311
      this.beginListeners[i].call();
293
324
  /**
294
325
   * called when started or repeating
295
326
   */
296
 
  start : function() {
297
 
    this.iterBegin = new Date();
 
327
  start : function(when) {
 
328
    this.iterBegin = when;
298
329
    if (this.from)
299
330
      this.currFrom = this.from;
300
331
    else
329
360
    var anim = this.anim;
330
361
    
331
362
    var dur = this.computedDur;
 
363
    if (isNaN(dur))
 
364
      return true;
332
365
    var values = this.values;
333
366
 
334
367
    var beginTime = this.iterBegin;
380
413
  step : function(value) {
381
414
    var attributeType = this.attributeType;
382
415
    var attributeName = this.attributeName;
383
 
    if (attributeType=="CSS")
 
416
    if (attributeType=="CSS") {
 
417
      // workaround a gecko and webkit bug
 
418
      if (attributeName=="font-size" && !isNaN(value))
 
419
        value += "px";
384
420
      this.target.style.setProperty(attributeName, value, "");
385
 
    else if (attributeType=="XML")
 
421
    } else if (attributeType=="XML")
386
422
      this.target.setAttribute(attributeName, value);
387
423
    else
388
424
      this.target.setAttribute(attributeName, value);
403
439
      else if (this.repeatDur && this.repeatDur!="indefinite" && (now-this.startTime)>=toMillis(this.repeatDur))
404
440
        return this.finish();
405
441
      else {
406
 
        this.start();
 
442
        this.start(now);
407
443
        for(var i=0; i<this.repeatIterations.length ;i++) {
408
444
          if (this.repeatIterations[i]==this.iteration)
409
445
            this.repeatListeners[i].call();
430
466
      window.setTimeout(call, offset);
431
467
      return;
432
468
    }
 
469
    if (offset && offset<0) {
 
470
      var now = new Date();
 
471
      now.setTime(now.getTime()+offset);
 
472
      if (now<this.startTime)
 
473
        return;
 
474
    }
 
475
 
433
476
    var fill = this.fill;
434
477
    var kept = true;
435
478
    if (fill=="freeze") {
561
604
    this.isInterpolable = function(from, to) { return true; };
562
605
    this.interpolate = function(from, to, percent) {
563
606
      var path = "";
564
 
      var listFrom = from.normalizedPathSegList;
565
 
      var listTo = to.normalizedPathSegList;
 
607
      var listFrom = from.myNormalizedPathSegList;
 
608
      var listTo = to.myNormalizedPathSegList;
566
609
      var segFrom;
567
610
      var segTo;
568
611
      for (var i=0; i<listFrom.numberOfItems && i<listTo.numberOfItems ;i++) {
670
713
  this.max = anim.getAttribute("max");
671
714
  if (this.max && this.max!="indefinite") {
672
715
    this.computedMax = toMillis(this.max);
673
 
    if (!this.computedDur || this.computedDur>this.computedMax)
 
716
    if (!isNaN(this.computedMax) && this.computedMax>0 && (!this.computedDur || this.computedDur>this.computedMax))
674
717
      this.computedDur = this.computedMax;
675
718
  }
676
719
  this.min = anim.getAttribute("min");
966
1009
function createPath(d) {
967
1010
  var path = document.createElementNS(svgns, "path");
968
1011
  path.setAttribute("d", d);
969
 
  if (!path.normalizedPathSegList) {
 
1012
  try { 
 
1013
    if (path.normalizedPathSegList)
 
1014
      path.myNormalizedPathSegList = path.normalizedPathSegList;
 
1015
  } catch(exc) {}
 
1016
  if(!path.myNormalizedPathSegList) {
970
1017
    // TODO : normalize the path
971
 
    path.normalizedPathSegList = path.pathSegList;
 
1018
    path.myNormalizedPathSegList = path.pathSegList;
972
1019
  }
973
1020
  return path;
974
1021
}
1185
1232
propDefaults["word-spacing"] = "normal";
1186
1233
propDefaults["writing-mode"] = "lr-tb";
1187
1234
 
 
1235
function funk(func, obj, arg) {
 
1236
  return function() {func.call(obj, arg);};
 
1237
}
1188
1238
 
1189
1239
/**
1190
1240
 * removes the leading and trailing spaces chars from the string