OSDN Git Service

Modify the initialize method
[sie/sie.git] / org / w3c / dom / smil.js
index e8a8c5e..fd398ec 100644 (file)
@@ -34,8 +34,9 @@ base("$frame").mix ( {
   timelines: [],\r
 \r
   /*開始フレーム数の候補。アニメーションの開始条件となる\r
-   * 単位はフレーム数であって、秒数ではない*/\r
-  begin: 0,\r
+   * 単位はフレーム数であって、秒数ではない\r
+   * なお、初期値については、開始フレームが負の値を考慮しているため*/\r
+  begin: -Number.MAX_VALUE,\r
 \r
   /*活動継続時間 (Active Duration)のフレーム数。アニメーションの継続条件となる\r
    * 単位はフレーム数であって、秒数ではない*/\r
@@ -46,8 +47,8 @@ base("$frame").mix ( {
   \r
   /*アニメーションを開始させるメソッド*/\r
   startAnimation: function() {\r
-    /*__step関数は最後に書く*/\r
-    __step();\r
+    /*$getDocument.step関数は最後に書く*/\r
+    base("$getDocument").step();\r
   },\r
   \r
   /*アニメーションが停止した状態かどうか、停止しているならばtrue*/\r
@@ -57,13 +58,21 @@ base("$frame").mix ( {
   pauseAnimation: function() {\r
     this.isPaused = true;\r
   },\r
+  \r
+  /*後述のinitializeメソッドで使うオブジェクトリスト*/\r
+  objList: [],\r
+  \r
+  /*オブジェクトの初期化処理*/\r
+  initialize: function() {\r
+    var list = this.objList;\r
+    for (var i=0;i<list.length;++i) {\r
+      list[i].initialize();\r
+    }\r
+  },\r
 \r
   /*setFrame メソッド\r
    * フレーム数を数値num まで進めるか、戻す*/\r
   setFrame: function( /*number*/ num) {\r
-    if((num < this.begin) || (num >= (this.begin+this.activeTime))) {\r
-      return;\r
-    }\r
     this.currentFrame = num;\r
     var timelines = this.timelines;\r
     for (var i=0;i<timelines.length;++i) {\r
@@ -105,13 +114,20 @@ base("$frame").mix ( {
   }\r
 } ).mix( function($frame) {\r
   $frame.up("$list").mix( {\r
-    /*開始時刻リスト (後述のupdateStateメソッドで使う)*/\r
+    /*終了時刻(単位フレーム数)のキャッシュとして使う*/\r
+    end: 0,\r
+    \r
+    /*開始時刻から終了時刻までのフレーム数\r
+     * これがactiveTimeより短ければ、活動継続時間とみなす*/\r
+    beginEnd: Number.MAX_VALUE,\r
+    \r
+    /*開始時刻(単位フレーム数)リスト (後述のupdateStateメソッドで使う)*/\r
     beginList: { \r
       next: null,\r
       value: Number.MAX_VALUE\r
     },\r
     \r
-    /*終了時刻リスト (後述のupdateStateメソッドで使う)*/\r
+    /*終了時刻(単位フレーム数)リスト (後述のupdateStateメソッドで使う)*/\r
     endList: {\r
        next: null,\r
        value: Number.MAX_VALUE\r
@@ -132,12 +148,12 @@ base("$frame").mix ( {
     },\r
     \r
     /*引数に渡された時刻リストの中から、現在フレームf以下の、最大値を求めるメソッド\r
-     * -1を返したときはリストの中にf以下の値がないことを示す*/\r
+     * Number.MIN_VALUEの値を返したときはリストの中にf以下の値がないことを示す*/\r
     getMaxList: function (f, list) {\r
-      var maxTime = -1; /*時刻の最大値*/\r
+      var maxTime = -Number.MAX_VALUE; /*時刻の最大値*/\r
       while( list ) {\r
         var v = list.value;\r
-        /*f以下の開始リスト値のうち、最大値をstartTimeに代入*/\r
+        /*f以下の開始リスト値のうち、最大値をmaxTimeに代入*/\r
         if ( (v <= f)\r
              && (maxTime <= v) ) {\r
           maxTime = v;\r
@@ -165,6 +181,13 @@ base("$frame").mix ( {
     /*終了処理をした後の待機状態を示す定数*/\r
     POSTWAITING: 4,\r
     \r
+    /*初期化用メソッド*/\r
+    init: function() {\r
+      this.state = this.WAITING;\r
+      this.begin = 0;\r
+      return this;\r
+    },\r
+    \r
     /*引数で指定されたフレーム数に応じて、stateプロパティを更新するメソッド*/\r
     updateState: function( /*number*/ f) {\r
       if (f === void 0) {\r
@@ -179,44 +202,67 @@ base("$frame").mix ( {
           post = /*this.POSTWAITING*/ 4;\r
       /*beginListプロパティと、endListプロパティの中で、\r
        * 現在フレーム数 f より大きい数値は、更新できる条件と無関係なので、除外しておく\r
-       * ã\81¾ã\81\9f、f以下の値の中から、最大値を探して、\r
+       * ã\81 ã\81\8bã\82\89、f以下の値の中から、最大値を探して、\r
        * それをbeginプロパティの値cacheBeginと比較する*/\r
-      var startTime = this.getMaxList(f, this.beginList),\r
-          endTime = this.getMaxList(f, this.endList),\r
+      var startTime = this.getMaxList(f, this.beginList);\r
+      if (startTime === -Number.MAX_VALUE) {\r
+        (state > post) && (this.state = begin);\r
+        return this;\r
+      }\r
+      var endTime = this.getMaxList(f, this.endList),\r
+          isWait = (state === wait),\r
           cacheBegin = this.begin;\r
-      if ( (state === wait) || (state === post) ) {\r
+      if ( !startTime && isWait) {\r
+          /*開始時刻が0ならば、アニメーションを開始\r
+           * ただし、アニメが終了した後のPOSTWAITING状態の時には作動させない*/\r
+          this.begin = 0;\r
+          this.state = begin;\r
+      } else if ( isWait || (state === post) ) {\r
         if (startTime > cacheBegin) {\r
           this.state = begin;\r
           /*beginプロパティに開始時刻をキャッシュ用に保存*/\r
           this.begin = startTime;\r
-        } else if (!startTime) {\r
-          /*開始時刻が0ならば、アニメーションを開始*/\r
-          this.state = begin;\r
         }\r
       } else if (state === begin) {\r
         if (endTime >= cacheBegin) {\r
           /*終了時刻にもう到達したときは、直接BEGINNING状態からENDING状態へ移行*/\r
           this.state = end;\r
+          /*endTimeを終了時刻とみなす*/\r
+          (endTime > 0) && (this.end = endTime);\r
+          /*activeTimeプロパティは、begin属性とend属性が反映されていないため、\r
+           * beginEndプロパティに別に設定しておく*/\r
+          this.beginEnd = 0;\r
         } else {\r
           this.state = play;\r
         }\r
       } else if (state === play) {\r
-        if ( (endTime >= cacheBegin) || (startTime > cacheBegin) ) {\r
+        /*activeTimeプロパティを比較して、変数endTimeを書き換える*/\r
+        var act = cacheBegin + this.activeTime;\r
+        endTime = (endTime > act) ? act\r
+                                  : endTime;\r
+        if ( (f >= act) || (endTime >= cacheBegin) || (startTime > cacheBegin) ) {\r
           /*終了時刻に到達したか、再び開始イベントが発火されたとき*/\r
           this.state = end;\r
+          if (endTime > 0) {\r
+            /*endTimeを終了時刻とみなす*/\r
+            this.end = endTime;\r
+            /*activeTimeプロパティは、begin属性とend属性が反映されていないため、\r
+             * beginEndプロパティに別に設定しておく*/\r
+            this.beginEnd = endTime - cacheBegin;\r
+          }\r
         }\r
       } else if (state === end) {\r
-        if (endTime >= cacheBegin) {\r
-          this.state = post;\r
-        } else {\r
+        if (startTime > cacheBegin) {\r
           /*再生中に開始イベントが発火されて、終了状態となったとき*/\r
           this.state = begin;\r
           this.begin = startTime;\r
+        } else {\r
+          this.state = post;\r
         }\r
       } else {\r
         this.state = begin;\r
       }\r
-      cacheBegin = startTime = endTime = void 0;\r
+      cacheBegin = startTime = endTime = isWait = state = void 0;\r
       return this;\r
     },\r
     \r
@@ -255,7 +301,8 @@ base("$frame").mix ( {
         for (var i=0;i<list.length;++i) {\r
           list[i](this);\r
         }\r
-        /*開始時刻と終了時刻が一致した場合はstateはENDING状態*/\r
+        /*開始時刻と終了時刻が一致した場合はstateはENDING状態\r
+         * それ以外はPLAYING状態*/\r
         state = this.updateState(f).state;\r
       }\r
       if (state === /*this.ENDING*/ 3) {\r
@@ -370,11 +417,6 @@ base("$frame").mix ( {
           ele,\r
           /*endListのvalueプロパティには、活動継続フレーム数と開始フレーム数を足したものが入る*/\r
           endList = this.$list.addEndList(Number.MAX_VALUE);\r
-      if (this.$end) {\r
-        /*$endオブジェクトを継承していた場合、\r
-         *活動継続フレーム数関連のリストは無効とする*/\r
-        endList = { value: 0};\r
-      }\r
       if (str === "indefinite") {\r
         this.begin = Number.MAX_VALUE;\r
       } else if (plusminus > 0) {\r
@@ -408,8 +450,7 @@ base("$frame").mix ( {
             objList = this.$list.addList(Number.MAX_VALUE),\r
         /*イベントのリスナーとして使う*/\r
             listener = function(evt) {\r
-              objList.value = this.begin = eventOffset + this.$frame.currentFrame;\r
-              endList.value = this.$list.begin + this.activeTime;\r
+              objList.value = this.begin = eventOffset + base("$frame").currentFrame;\r
               this.isResolved = true;\r
             };\r
         this.eventOffset = eventOffset;\r
@@ -431,8 +472,6 @@ base("$frame").mix ( {
       } else {\r
         /*開始リストに登録しておく($endの場合は終了リストに登録)*/\r
         this.$list.addList(this.begin);\r
-        /*活動継続時間から算出される終了フレーム数は、終了リストに入れておく*/\r
-        endList.value = this.begin + this.activeTime;\r
       }\r
       s = event = str = plusminus = ele = void 0;\r
     },\r
@@ -464,7 +503,7 @@ base("$frame").mix ( {
       var s = ( this.$activate = this.$activate.up() );\r
       /*$endオブジェクトに付属している$listプロパティを更新したものと一致させておく*/\r
       s.end && (s.end.$list = this.$list);\r
-      this.activeTime = s.call() || Number.MAX_VALUE;\r
+      this.activeTime = this.$list.activeTime = s.call() || Number.MAX_VALUE;\r
       this.simpleDuration = s.simpleDur;\r
       return this;\r
     }\r
@@ -1031,6 +1070,73 @@ base("$calcMode").up("$attribute").mix( {
     }\r
     return s;\r
   },\r
+  \r
+  /*repeatイベントの発火時刻リスト\r
+   * setSmilEventメソッドを見よ*/\r
+  _repeatList: [],\r
+  \r
+  /*リピート回数を示すプロパティ\r
+   * setSmilEventメソッドを見よ*/\r
+  _repeatCount: 0,\r
+  \r
+  /*SMILイベント関連を発火させるためのメソッド\r
+   * もっぱら、$attributeオブジェクトのpush メソッドで使われる*/\r
+   setSmilEvent: function($list) {\r
+    $list.addEvent("begin", function($list) {\r
+        var target = this._ele,\r
+            detail = 0;\r
+        /*IE11のために、MouseEventsでSMILEventsの代用をする*/\r
+        var evt = target.ownerDocument.createEvent("MouseEvents");\r
+        evt.initMouseEvent("beginEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+        target.dispatchEvent(evt);\r
+        /*repeatイベントのために、_repeatListプロパティを初期化する*/\r
+        var list = this._repeatList = [],\r
+            active = $list.activeTime,\r
+            begin = $list.begin,\r
+            simpleDuration = this.timeline.simpleDuration;\r
+            if (simpleDuration && (simpleDuration !== active)\r
+                  && (active !== Number.MAX_VALUE) ) {\r
+              /*活動継続時間と単純持続時間が異なるとき、repeatイベントを設定*/\r
+              for (var m= simpleDuration, n=1;m < active ; m+=simpleDuration) {\r
+                list.push( {\r
+                  frame: begin + m,\r
+                  /*リピートの回数 (n >= 1)*/\r
+                  count: n\r
+                } );\r
+                ++n;\r
+              }\r
+            }\r
+    }.bind(this) );\r
+    \r
+    $list.addEvent("play", function($list) {\r
+      var target = this._ele,\r
+          detail = 0,\r
+          frame = $list.currentFrame,\r
+          list = this._repeatList;\r
+      if (!list.length) {\r
+        return;\r
+      }\r
+      for (var i=0;i<list.length;++i) {\r
+        if ( (this._repaetCount >= i+1)\r
+            || (list[i].frame >= frame) ) {\r
+          this._repeatCount = detail;\r
+          break;\r
+        } \r
+        detail = list[i].count;\r
+        var evt = target.ownerDocument.createEvent("MouseEvents");\r
+        evt.initMouseEvent("repeatEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+        target.dispatchEvent(evt);\r
+      }\r
+    }.bind(this) );\r
+    \r
+    $list.addEvent("end", function() {\r
+        var target = this._ele,\r
+            detail = 0;\r
+        var evt = target.ownerDocument.createEvent("MouseEvents");\r
+        evt.initMouseEvent("endEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+        target.dispatchEvent(evt);\r
+    }.bind(this) );\r
+   },\r
 \r
   /*引数で指定した要素 ele の属性を解析して、フレームに追加する*/\r
   push: function(/*Element Node*/ ele) {\r
@@ -1108,21 +1214,35 @@ base("$calcMode").up("$attribute").mix( {
                     max: this.getAttr("max", "indefinite")\r
                   } )\r
                 } ).updateList().parse();\r
-    $frame.addLine(frame.$list);\r
+    $frame.addLine(frame.$list.init());\r
+    \r
     /*beginElementメソッドを追加*/\r
-    function eleMethod (obj, eventName) {\r
-      return (obj.string !== "indefinite") ? function(){}\r
+    var objList = frame.$list.addList(Number.MAX_VALUE),\r
+        /*endListのvalueプロパティには、活動継続フレーム数と開始フレーム数を足したものが入る*/\r
+        endList = frame.$list.addEndList(Number.MAX_VALUE);\r
+    ele.beginElement = (frame.string !== "indefinite") ? function(){}\r
                         : function() {\r
+                            objList.value = frame.begin = base("$frame").currentFrame;\r
+                            frame.isResolved = true;\r
                             var evt = this.ownerDocument.createEvent("MouseEvents");\r
-                            evt.initMouseEvent(eventName + "Event" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
+                            evt.initMouseEvent("beginEvent" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
                             this.dispatchEvent(evt);\r
                           };\r
-    };\r
-    ele.beginElement = eleMethod(frame, "begin");\r
     /*endElementメソッドを追加*/\r
-    ele.endElement = eleMethod(frame.$activate.end || {}, "end");\r
+    var endFrame = frame.$activate.end || {};\r
+    ele.endElement = (endFrame.string !== "indefinite") ? function(){}\r
+                        : function() {\r
+                            if (frame.isResolved) {\r
+                              endFrame.isResolved = true;\r
+                              endList.value  = base("$frame").currentFrame;\r
+                              var evt = this.ownerDocument.createEvent("MouseEvents");\r
+                              evt.initMouseEvent("endEvent" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
+                              this.dispatchEvent(evt);\r
+                            }\r
+                          };\r
     /*setFrameメソッドを使ったときの、再帰スタックの使いすぎを防ぐため*/\r
     frame.timelines = [];\r
+    this.setSmilEvent(frame.$list);\r
     begin = ele = void 0;\r
     return frame;\r
   },\r
@@ -1281,6 +1401,34 @@ base("$calcMode").up("$attribute").mix( {
   /*to属性の値、文字列*/\r
   to: "",\r
   \r
+  \r
+  /*後述のinitializeメソッドで使う要素リスト\r
+   * getElementsByTagNameNSメソッドの返り値をArray化したことを想定*/\r
+  elementList: [],\r
+  \r
+  /*何番目からelementListを処理しているかの数値*/\r
+  numberOfElemList: 0,\r
+  \r
+  /*initialize メソッド\r
+   * 要素リストを初期化させる\r
+   * 初期化処理を分散させるために使う*/\r
+  initialize: function() {\r
+    var eles = this.elementList;\r
+    if (!eles || !eles.length) {\r
+      return;\r
+    }\r
+    var length = this.numberOfElemList+50;\r
+    for (var i=length-50; i<length; ++i) {\r
+      if (eles.length <= i) {\r
+        this.elementList = null;\r
+        return;\r
+      }\r
+      this.up().init(eles[i]);\r
+    }\r
+    this.numberOfElemList += 50;\r
+    eles = length = void 0;\r
+  },\r
+   \r
   /*initメソッドで使われるアニメーション関数*/\r
   _setFrame: function ($list) {\r
     this.setAttribute(this.to);\r
@@ -1350,7 +1498,7 @@ base("$calcMode").up("$attribute").mix( {
   },\r
   \r
   _setFrame: function($list) {\r
-    var currentTime = $list.currentFrame;\r
+    var currentFrame = $list.currentFrame;\r
     /*durationは単純継続時間\r
      *advanceは継続時間内での、進捗率\r
      *  仕様を参照 http://www.w3.org/TR/smil-animation/#AnimFuncValues\r
@@ -1362,29 +1510,37 @@ base("$calcMode").up("$attribute").mix( {
         /*単純継続時間が不定の場合、補間はせずに初期値が採用されるため、advanceは0となる\r
          * 仕様を参照 SMIL Animation 3.2.2. Animation function values のInterpolation and indefinite simple durations\r
          * http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues*/\r
-        advance = duration ? ( (currentTime - $list.begin) % duration ) / duration\r
+        advance = duration ? ( (currentFrame - $list.begin) % duration ) / duration\r
                     : 0;\r
     this.setAttribute(this.tocall(advance));\r
     line = duration = advance = void 0;\r
   },\r
   \r
-  /*_setEndFrameメソッドは、終了処理と凍結作業をするときに、falseを返す*/\r
+  /*凍結処理をするために、進捗率を最後まで進めて調整するメソッド\r
+   * 返り値は調整された進捗率\r
+   * もっぱら、_setEndFrameメソッドで使われる*/\r
+  getAdvanceEnd: function($list) {\r
+    var line = this.timeline,\r
+        duration = line.simpleDuration;\r
+    if (duration) {\r
+      var time = (line.activeTime > $list.beginEnd) ? $list.beginEnd\r
+                  : line.activeTime;\r
+      var advance = ( time % duration ) / duration;\r
+      /*例外が発生するため、進捗率が1を超えないように処理*/\r
+      advance = (advance > 1) ? 1 : advance;\r
+       /*活動継続時間と単純継続時間が一致すると、余りは0となるため以下の処理*/\r
+      advance = advance || 1;\r
+    } else {\r
+      advance = 0;\r
+    }\r
+    return advance;\r
+  },\r
+  \r
+  /*_setEndFrameメソッドは、終了処理と凍結作業をする*/\r
   _setEndFrame: function($list) {\r
-    var frame = $list.currentFrame;\r
     /*上書きされたメソッドを呼び出してアニメーションの凍結作業をする*/\r
     if (this.fill === "freeze") {\r
-      var line = this.timeline,\r
-          duration = line.simpleDuration;\r
-      if (duration) {\r
-        var advance = ( line.activeTime % duration ) / duration;\r
-        /*例外が発生するため、進捗率が1を超えないように処理*/\r
-        advance = (advance > 1) ? 1 : advance;\r
-         /*活動継続時間と単純継続時間が一致すると、余りは0となるため以下の処理*/\r
-        advance = advance || 1;\r
-      } else {\r
-        advance = 0;\r
-      }\r
-      this.setAttribute(this.tocall(advance));\r
+      this.setAttribute(this.tocall( this.getAdvanceEnd($list) ));\r
       line = duration = advance = void 0;\r
     } else {\r
       this.removeAttribute();\r
@@ -1726,7 +1882,8 @@ base("$calcMode").up("$attribute").mix( {
    /*後の_setFrameメソッドで使うダミー*/\r
    __setAttribute: function(){},\r
    \r
-   _setFrame: function(currentFrame) {\r
+   _setFrame: function($list) {\r
+    var currentFrame = $list.currentFrame;\r
      /*__transformListの中で、自分より後の項目に再生中のものがあれば、\r
       *アニメーションを再生させないで、後に続く項目に任せる*/\r
      var list = this.element.__transformList,\r
@@ -1745,32 +1902,34 @@ base("$calcMode").up("$attribute").mix( {
      this.setAttribute = isPostActive ? this.__setAttribute\r
                                     : this.$animateElement.setAttribute;\r
      /*上書きされたメソッドを呼び出す*/\r
-     this.$animateElement._setFrame.call(this, currentFrame);\r
+     this.$animateElement._setFrame.call(this, $list);\r
    },\r
    \r
-   _setEndFrame: function(currentFrame) {\r
+   _setEndFrame: function($list) {\r
      var list = this.element.__transformList;\r
-     if ((this.fill !== "remove") || !list) {\r
+     if (!list) {\r
        return;\r
      }\r
-     if (!this.isSum) {\r
-       /*凍結処理をしないで、かつ、元の状態に戻して、効果が出ないようにする*/\r
-       list[this.numberOfList]\r
-        && (list[this.numberOfList].isPlaying = false);\r
-        for (var i = 0;i<list.length;++i) {\r
-          var listi = list[i];\r
-          if (listi.isPlaying || !listi.isRemove) {\r
-            /*他のanimateTransform要素が活性化しているか、凍結処理が必要ならば、\r
-             * 属性の初期化はしない*/\r
-            return;\r
-          }\r
-        }\r
-       this.removeAttribute();\r
+     var item = list[this.numberOfList];\r
+     if (this.fill === "remove") {\r
+       if (!item) {\r
+         return;\r
+       } else if (!this.isSum) {\r
+         /*凍結処理をしないで、かつ、元の状態に戻して、効果が出ないようにする*/\r
+         item.isPlaying = false;\r
+       } else {\r
+         /*凍結処理をしないで、かつ、効果を出すが、変形させないようにする*/\r
+         item.value = "translate(0)";\r
+       }\r
      } else {\r
-       /*凍結処理をしないで、かつ、効果を出すが、変形させないようにする*/\r
-       list[this.numberOfList]\r
-        && (list[this.numberOfList].value = "translate(0)");\r
+       /*凍結処理をする\r
+        * 自前のtocallメソッドはvalueプロパティを書きかえてしまうため、\r
+        * 上書きメソッドを呼び出す*/\r
+       item.value = this.type+ "(" \r
+                                      +this.$animateElement.tocall.call( this, this.getAdvanceEnd($list) )+ ")";\r
      }\r
+     this.setAttribute( this.joinList(this.defaultValue || "") );\r
+     item = void 0;\r
    },\r
    \r
     /*setAddメソッドのオーバライド\r
@@ -1799,15 +1958,16 @@ base("$calcMode").up("$attribute").mix( {
      /*isPlayingプロパティはアニメーション再生終了後でもtrueとなるので注意*/\r
      parent.__transformList.push( {isPlaying: false,\r
                                    value: "translate(0)",\r
-                                   isSum: this.isSum,\r
-                                   isRemove: (this.fill === "remove")\r
+                                   isSum: this.isSum\r
                                   } );\r
    }\r
   } )\r
   .up("$motionElement")\r
   .mix( function() {\r
-    /*setRFrameメソッドを再定義*/\r
+    /*$animateTransformElementオブジェクトのでは、うまくいかないため、\r
+     * setRFrameとsetEndFrameメソッドを再定義*/\r
     this._setFrame = this.$animateElement._setFrame;\r
+    this._setEndFrame = this.$animateElement._setEndFrame;\r
   })\r
   .mix( {\r
     numberOfList: -1,\r
@@ -1873,7 +2033,7 @@ base("$calcMode").up("$attribute").mix( {
       }\r
     },\r
     \r
-    /*$animateElement.tocallメソッドを置き換えるためのメソッド\r
+    /*this.$animateElement.tocallメソッドを置き換えるためのメソッド\r
      * mpath要素が指定されたときか、path属性のときにのみ使われる*/\r
     _tocallForPath: function(advance) {\r
       var path = this.path,\r
@@ -1920,212 +2080,101 @@ base("$calcMode").up("$attribute").mix( {
     }\r
   } );\r
 \r
-/*$svgEventオブジェクトは、SVGEvent発火を監視するためのオブジェクト*/\r
-base("$frame").up("$svgEvent").mix( {\r
-  /*イベントのスケジュール記録*/\r
-  first: null,\r
-  \r
-  /*タイムラインの最後のキャッシュ*/\r
-  lastTimeLine: null,\r
-  \r
-  /*setTimeTable メソッドはスケジュールの記録をつけるためのメソッド*/\r
-  setTimeTable: function () {\r
-    var timelines = this.timelines;\r
-      for (var i=0, obj = null;i<timelines.length;++i) {\r
-        if (!timelines[i].target || !timelines[i].isResolved) {\r
-          /*一度スケジュールを作成して実行したり、未解決だったタイムラインは、処理しない*/\r
-          continue;\r
-        }\r
-        /*タイムラインから、beginEventとendEventを発火するスケジュールを作成*/\r
-        var timeline = timelines[i],\r
-            begin = timeline.begin,\r
-            target = timeline.target,\r
-            simpleDur = timeline.simpleDuration,\r
-            activeTime = timeline.activeTime;\r
-        var first = {\r
-              frame: begin,\r
-              eventType: "begin",\r
-              target: target,\r
-              next: {\r
-                frame: begin+activeTime,\r
-                eventType: "end",\r
-                target: target,\r
-                next: null\r
-              }\r
-            };\r
-        if (obj) {\r
-          obj.next.next = first;\r
-        } else if (!this.first) {\r
-          /*firstプロパティがすでにある場合、書き換えない*/\r
-          this.first = first;\r
-        } else {\r
-          /*firstプロパティがある場合、そのリストのリンクをたどっていって、\r
-           * 最後の尾を変数firstとつなげる*/\r
-          var fst = this.first;\r
-          while(fst.next) {\r
-            fst = fst.next;\r
-          }\r
-          fst.next = first;\r
-        }\r
-        obj = first;\r
-        if (simpleDur && (activeTime !== simpleDur)) {\r
-          /*活動継続時間と単純持続時間が異なるとき、repeatイベントを設定\r
-           * ただし、repeatイベントはendイベントが発生する前に起きるものと仮定*/\r
-          for (var a = first, m= begin + simpleDur, n=1;m < begin + activeTime; m+=simpleDur, ++n) {\r
-            a.next = {\r
-              frame: m,\r
-              eventType: "repeat",\r
-              target: target,\r
-              /*リピートの回数 (n >= 1)*/\r
-              count: n,\r
-              next: a.next\r
-            };\r
-            a = a.next;\r
-          }\r
-        }\r
-        /*一度、スケジュールを作っておいたタイムラインは次回から処理しないようにする*/\r
-        timeline.target = null;\r
-      }\r
-    timelines = obj = first = begin = target = simpleDur = activeTime = void 0;\r
-  },\r
-  \r
-  $frame: base("$frame"),\r
-  \r
-  setFrame: function (num) {\r
-    var timelines = this.timelines,\r
-        lastTimeLine = timelines[timelines.length-1],\r
-        s = this.$frame.setFrame(num);\r
-    /*キャッシュのlastTimeLineプロパティを使って、再びスケジュールの計算をさせないようにする*/\r
-    if (this.lastTimeLine !== lastTimeLine) {\r
-      this.lastTimeLine = lastTimeLine;\r
-      this.setTimeTable();\r
-    }\r
-    /*スケジュールに記録しておいたものを実行して、イベントを発火\r
-     * また、発火した場合は記録から取り除いて、次回から再び発火しないようにする*/\r
-    var obj = this.first,\r
-        cobj = obj,\r
-        floor = Math.floor;\r
-    while(obj) {\r
-      var frame = obj.frame,\r
-          target = obj.target\r
-          detail = 0;\r
-      if (frame <= num) {\r
-        /*IE11ではSVGEventsやDOMEventsを使うと問題が起きるため、MouseEventsで代用する*/\r
-        if (obj.eventType === "repeat") {\r
-          /*detailは何回リピートしたか*/\r
-          detail = obj.count;\r
-        }\r
-        /*ポインタの連結を変更することで、リストからobj を除去\r
-         * 一度除去したものはイベントを発生させない*/\r
-        cobj.next = obj.next;\r
-        if (this.first === obj) {\r
-          cobj = obj.next;\r
-          this.first = cobj;\r
-        } else {\r
-          cobj = obj;\r
-        }\r
-        var evt = target.ownerDocument.createEvent("MouseEvents");\r
-        evt.initMouseEvent(obj.eventType+"Event" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
-        target.dispatchEvent(evt);\r
-      } else {\r
-        /*next プロパティを書き換えるためのobj オブジェクトのキャッシュ*/\r
-        cobj = obj;\r
-      }\r
-      obj = obj.next;\r
-    }\r
-    obj = num = first = frame = target = cobj = detail = void 0;\r
-    return s;\r
-  }\r
-} );\r
+base("$getDocument").mix ( function() {\r
 \r
-function getDocument() \r
-{\r
-  var svg = document.getElementsByTagName("object"),\r
-      svgns = "http://www.w3.org/2000/svg";\r
-  if (svg) {\r
-    for (var i=0;i<svg.length;++i) {\r
-      getElement( svg[i].getSVGDocument() );\r
+  function getDocument() \r
+  {\r
+    var svg = document.getElementsByTagName("object"),\r
+        svgns = "http://www.w3.org/2000/svg";\r
+    if (svg) {\r
+      for (var i=0;i<svg.length;++i) {\r
+        getElement( svg[i].getSVGDocument() );\r
+      }\r
     }\r
+    /*SVG文書から呼び出されたときも処理する*/\r
+    getElement(document);\r
+    /*idはアニメの中止ハンドル*/\r
+    var id = __step(),\r
+        idstop = function() {\r
+          /*アニメーションを中止する関数*/\r
+          window.cancelAnimationFrame && cancelAnimationFrame(id);\r
+        };\r
+    base("$frame").on("pauseAnimation", idstop);\r
+    window.addEventListener("unload", idstop);\r
+    \r
+    /*文書からアニメーション関連要素を取り出して、オブジェクトを初期化*/\r
+    function getElement (svgDoc) {\r
+        var $set = base("$calcMode").$attribute.$setElement,\r
+            $animate = $set.$animateElement,\r
+            frame = base("$frame");\r
+        init($set, "set");\r
+        init($animate, "animate");\r
+        init($animate.up(), "animateColor");\r
+        init($animate.$animateTransformElement, "animateTransform");\r
+        init($animate.$animateTransformElement.$motionElement, "animateMotion");\r
+          /*リンクのハッシュ読み取りで、ハイパーリンクのイベント処理\r
+         * たとえば、a要素のxlink:href="#hoge"で、<animate id="hoge"のとき、\r
+         * animate要素がハイパーリンク作動と同時に動くようになる\r
+         * \r
+         * ただし、SMIL アニメーションの仕様では、\r
+         * animate要素の開始時刻まで、時を進める操作をするだけ*/\r
+         svgDoc.defaultView.addEventListener("hashchange", function() {\r
+             var hash = svgDoc.defaultView.location.hash.slice(1);\r
+             svgDoc.getElementById(hash).beginElement();\r
+           });\r
+        function init (obj, name) {\r
+          /*あとでframe.initializeメソッドで呼び出すために準備しておく*/\r
+          var elist = svgDoc.getElementsByTagNameNS(svgns, name);\r
+          obj.numberOfElemList = 0;\r
+          if (elist.length > 0) {\r
+            obj.elementList = elist;\r
+            frame.objList.push(obj);\r
+          }\r
+          elist = obj = void 0;\r
+        };\r
+    };\r
   }\r
-  /*SVG文書から呼び出されたときも処理する*/\r
-  getElement(document);\r
-  /*idはアニメの中止ハンドル*/\r
-  var id = __step(),\r
-      idstop = function() {\r
-        /*アニメーションを中止する関数*/\r
-        window.cancelAnimationRequest && cancelAnimationRequest(id);\r
-      };\r
-  base("$frame").on("pauseAnimation", idstop);\r
-  window.addEventListener("unload", idstop);\r
   \r
-  /*文書からアニメーション関連要素を取り出して、オブジェクトを初期化*/\r
-  function getElement (svgDoc) {\r
-      var $set = base("$calcMode").$attribute.$setElement,\r
-          $animate = $set.$animateElement;\r
-      init($set, "set");\r
-      init($animate, "animate");\r
-      init($animate, "animateColor");\r
-      init($animate.$animateTransformElement, "animateTransform");\r
-      init($animate.$animateTransformElement.$motionElement, "animateMotion");\r
-        /*リンクのハッシュ読み取りで、ハイパーリンクのイベント処理\r
-       * たとえば、a要素のxlink:href="#hoge"で、<animate id="hoge"のとき、\r
-       * animate要素がハイパーリンク作動と同時に動くようになる\r
-       * \r
-       * ただし、SMIL アニメーションの仕様では、\r
-       * animate要素の開始時刻まで、時を進める操作をするだけ*/\r
-       svgDoc.defaultView.addEventListener("hashchange", function() {\r
-           var hash = svgDoc.defaultView.location.hash.slice(1);\r
-           svgDoc.getElementById(hash).beginElement();\r
-         });\r
-\r
-      function init (obj, name) {\r
-        var eles = svgDoc.getElementsByTagNameNS(svgns, name)\r
-        for (var i=0;i<eles.length;++i) {\r
-          obj.up().init(eles.item(i));\r
-        }\r
-        eles = obj = void 0;\r
-      };\r
-  };\r
-}\r
+  window.addEventListener && window.addEventListener("load", getDocument);\r
 \r
-window.addEventListener && window.addEventListener("load", getDocument);\r
-\r
-function __step() {\r
-/*EdgeはhasFeatureメソッドでtrueを返す*/\r
-if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Animation", "1.1")\r
-    || window.navigator.userAgent.toLowerCase().indexOf("edge")) {\r
-  if (window.requestAnimationFrame && requestAnimationFrame) {\r
-    /*IE11などSMILアニメーションに対応していないブラウザ用*/\r
-    /*cancelはアニメーションの中止ハンドル*/\r
-    var cancel = {\r
-       handle: null\r
-      };\r
-    (function(frame) {\r
-      var $frame = base("$frame"),\r
-          $f = $frame.$svgEvent,\r
-          _cancel = cancel; /*cancelのエイリアス*/\r
-      _cancel.handle = requestAnimationFrame(step);\r
-      function step() {\r
-        if (!$frame.isPaused) {\r
-          frame++;\r
-          try {\r
-            $f.setFrame(frame);\r
-          } catch(e) {\r
-          }\r
+  this.step = __step;\r
+  function __step() {\r
+    /*EdgeはhasFeatureメソッドでtrueを返す*/\r
+    if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Animation", "1.1")\r
+        || (window.navigator.userAgent.toLowerCase().indexOf("edge") > 0)) {\r
+      if (window.requestAnimationFrame && requestAnimationFrame) {\r
+        /*IE11やEdgeなどSMILアニメーションに対応していないブラウザ用*/\r
+        /*cancelはアニメーションの中止ハンドル*/\r
+        var cancel = {\r
+           handle: null\r
+          };\r
+        (function(frame) {\r
+          var _cancel = cancel; /*cancelのエイリアス*/\r
+          var step = function () {\r
+            if (!this.isPaused) {\r
+              frame++;\r
+              try {\r
+                this.initialize();\r
+                this.setFrame(frame);\r
+              } catch(e) {\r
+              }\r
+              _cancel.handle = requestAnimationFrame(step);\r
+            }\r
+          }.bind(base("$frame"));\r
           _cancel.handle = requestAnimationFrame(step);\r
-        }\r
-      };\r
-    })(-1);\r
-    return cancel;\r
-  } else {\r
-    setInterval( (function(frame) {\r
-      var $f = base("$frame").$svgEvent;\r
-      return function () {\r
-        frame++;\r
-        $f.setFrame(frame);\r
-      };\r
-    })(-1), 1 );\r
+        })(-1);\r
+        return cancel;\r
+      } else {\r
+        setInterval( (function(frame) {\r
+          var $f = base("$frame");\r
+          return function () {\r
+            frame++;\r
+            $f.initialize();\r
+            $f.setFrame(frame);\r
+          };\r
+        })(-1), 1 );\r
+      }\r
+    }\r
   }\r
-}\r
-}\r
+} );\r
 //#endif // _SMIL_IDL_\r