ExtJS EditorGridPanel でランタイムエラーが発生する問題の回避策 - IE 使用時
ExtJS 2.2.1 の EditorGridPanel を IE6, 7 上で使用している場合、以下のような操作でランタイムエラーが発生する。(ただし、環境や設定によってはランタイムエラーが表示されない可能性あり)
- 編集中の任意のセルから同じ行の Grid に全体が表示されていない別のセルをクリック
ランタイムエラー発生サンプル
<html> <head> <link rel="stylesheet" type="text/css" href="../ext-2.2.1/resources/css/ext-all.css" /> <script type="text/javascript" src="../ext-2.2.1/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext-2.2.1/ext-all.js"></script> <script type="text/javascript"> Ext.BLANK_IMAGE_URL = "../ext-2.2.1/resources/images/default/s.gif"; Ext.onReady(function() { var store = new Ext.data.SimpleStore({ fields: [ {name: 'title'}, {name: 'point', type: 'float'} ] }); store.loadData([ ['test1', 1000.10], ['a', 50.1] ]); //グリッドの定義 var grid = new Ext.grid.EditorGridPanel({ columns: [ {header: 'Title', dataIndex: 'title', width: 270, editor: new Ext.form.TextField()}, {header: 'Point', dataIndex: 'point', width: 100, editor: new Ext.form.TextField()} ], store: store, width: 300, height: 100, stripeRows: true }); grid.render('grid-sample'); }); </script> </head> <body> <h1>EditorGridPanel RuntimeError Sample for IE</h1> <div id="grid-sample"></div> </body> </html>
上記ファイルを IE7 等で表示し、Title 列のセルを編集した状態で、右隣の Point 列をクリックするとランタイムエラーが発生。
ランタイムエラーの発生原因
ランタイムエラーの発生原因は getBoundingClientRect メソッドの実行にある。
問題となる操作を実施すると、ExtJS のライブラリ内で getBoundingClientRect を呼び出し、ランタイムエラーが発生する。(IE の場合のみ)
なお、getBoundingClientRect は Firefox 3 でも導入されているが、Firefox では全く問題無い模様。
回避策
この問題を回避するには、getBoundingClientRect の呼び出しを try-catch するだけでよい。
ただし、ExtJS のソースに手を加えるのは望ましい方法では無いため、今回は getBoundingClientRect をラッパーメソッドで置き換える方法を取る事にした。
なお、問題が発生する際の getBoundingClientRect の実行対象は Ext.getDom() で取得していたため、Ext.getDom() で取得したものだけに getBoundingClientRect の置き換えを行うようにしてみた。
<html> <head> <link rel="stylesheet" type="text/css" href="../ext-2.2.1/resources/css/ext-all.css" /> <script type="text/javascript" src="../ext-2.2.1/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext-2.2.1/ext-all.js"></script> <script type="text/javascript"> Ext.BLANK_IMAGE_URL = "../ext-2.2.1/resources/images/default/s.gif"; Ext.onReady(function() { if (Ext.getDom && !Ext.original_getDom) { Ext.original_getDom = Ext.getDom; Ext.getDom = function(el) { var d = Ext.original_getDom(el); if (d && d.getBoundingClientRect && !d.original_getBoundingClientRect) { //オリジナルの getBoundingClientRect を退避 d.original_getBoundingClientRect = d.getBoundingClientRect; //getBoundingClientRect をラッパーメソッドで置換 d.getBoundingClientRect = function() { var result = {top: 0, left: 0, bottom: 0, right: 0}; try { //オリジナルの getBoundingClientRect を実行し //ランタイムエラーを try-catch する result = d.original_getBoundingClientRect(); } catch(e) { } return result; }; } return d; }; } ・・・ grid.render('grid-sample'); }); </script> </head> <body> <h1>EditorGridPanel RuntimeError Sample for IE</h1> <div id="grid-sample"></div> </body> </html>