5

問題空間:

JQUERY Ajaxを使用してHTMLにインラインで埋め込むSVGマップがあります。次に、Java スクリプトを使用して svg オブジェクト内の多くの要素に対処し、属性を変更して、データ シリーズに基づいてイベント リスナーを追加します。データとマップはインタラクティブです。ユーザーは、多くの順列で状態を変更できます。

JQUERY UI 1.10.3タブも使用しています

多数のカテゴリがあります。したがって、プレゼンテーションによっては、同じタブに svg マップの複数のコピーが存在し、同じ svg マップを持つ多くの異なるタブが存在する可能性があります。

svg ドキュメントの各コピーには、同じ要素 ID があります。私が経験している問題は、要素 ID が HTML DOM で互いに競合していることです。そのため、アドレス指定可能な唯一の要素は、HTML ドキュメントで最初に出現する svg オブジェクトの要素です。

私の質問は:

svg オブジェクトのインスタンスごとに要素 ID を一意にする必要がありますか? または、HTML DOM の svg オブジェクトにスコープとコンテキストを設定する方法はありますか?

例:

含まれている各 div には、svg ドキュメントを挿入して SVG ドキュメントを取得するために使用する一意の ID があります。

    <div id="svgMap_div_1" class="cIG" style="height: 500px; width: 750px"></div>

ajax から受信した svg ドキュメントをロードするために使用されるコード (mimeType = "image/svg+xml"):

    document.getElementById('svgMap_div_1').appendChild(svgXMLObject.documentElement)

svg ドキュメントを取得するために使用されるコード。svgDoc の宣言は、実装されている関数に対してローカルであり、一意です。

    var svgDoc = document.getElementById('svgMap_div_1').ownerDocument;

個々の要素を更新するために使用されるコード。同一の svg オブジェクト (子要素の ID が同じ) が同じ HTML DOM にある場合、この JavaScript は、個別の div から取得された場合でも、HTML DOM で最初に発生する svg オブジェクトを常にアドレス指定します。 svgMap_div_2'.

    var svgElem = svgDoc.getElementById('elemID');
    svgElem.setAttribute("fill", '#0000FF');

問題の根本は、ownerDocument を使用して svgDoc を取得していることにあると思います。スコープとコンテキストを持つ個別のオブジェクトを作成するのではなく、DOM がコンテキストになるように DOM 全体に到達します。IDE のコード リファレンスを参照してください。

HTMLDocument Node.ownerDocument

    Property ownerDocument http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html 
    See Also:
    Document
    Since:
    Standard ECMA-262 3rd. Edition
    Level 2 Document Object Model Core Definition.
    @type
    Document

必要に応じて、すべての ID を一意にする実用的なアルゴリズムを開発できますが、より良い方法を見つけたいと思っています。他のメソッドとプロパティを試して、機能する svg ドキュメント オブジェクトを取得しましたが、どれも機能しません。

以下は、両方の svg オブジェクトが同じページの異なる div にある場合に何が起こるかを示す実際の例です。4 つの組み合わせはすべて、最初の四角形の色を変更します。2 番目のオブジェクトの四角形の ID を「box-b」に変更し、それに応じてアドレス指定すると (「bbox_div」、「box-b」)、両方の四角形が互いに独立して操作されます。

<script type='text/javascript'>
function colorBox(divID, svgElem, colorHex) {
    /* DOM  This is the original solution that did not work !!!*/
    //    var svgDoc = document.getElementById(divID).ownerDocument.
    //    var svgBox = svgDoc.getElementById(svgElem);
    //    svgBox.setAttribute("fill", colorHex);

    /* querySelector */
    //    document.querySelector("#"+divID + " ."+svgElem).setAttribute("fill", colorHex);

    /* jquery div */
    //    var svgBox = $('#'+divID+' svg').find('#'+svgElem);
    //    svgBox.css("fill", colorHex);    

    /* jquery class */
    $('#'+divID+' svg').find('.'+svgElem).css("fill", colorHex);
}
</script>
<div style="height: 100px; width: 100px">
    <a href="#" onclick="colorBox('abox_div', 'box-a', '#FF0000');return false;">Box A Red</a><br>
    <a href="#" onclick="colorBox('abox_div', 'box-a', '#0000FF');return false;">Box A Blue</a><br>
    <a href="#" onclick="colorBox('bbox_div', 'box-a', '#FF0000');return false;">Box B Red</a><br>
    <a href="#" onclick="colorBox('bbox_div', 'box-a', '#0000FF');return false;">Box B Blue</a><br -->
</div>
<div id="abox_div" style="height: 100px; width: 100px">
    <svg xmlns="http://www.w3.org/2000/svg"
         width="0.990919in"
         height="0.597218in" 
         viewBox="0 0 71.3461 42.9997">

    <style type="text/css">
    <![CDATA[
        .allboxes {fill:#00FF00}
    ]]>
    </style>

    <g class="box-a allboxes" transform="translate(0.24,-0.24)"  fill="#e8eef7">
        <rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box A</title></rect>
    </g>
   </svg>
</div>
<div id="bbox_div" style="height: 100px; width: 100px">
   <svg xmlns="http://www.w3.org/2000/svg"
        width="0.990919in"
        height="0.597218in" 
        viewBox="0 0 71.3461 42.9997">
    <g class="box-a allboxes" transform="translate(0.24,-0.24)"  fill="#e8eef7">
        <rect x="0" y="0.48" width="70.8661" height="42.5197" ><title>Box B</title></rect>
    </g>
   </svg>
</div>
4

2 に答える 2

3

ID が重複している場合、厳密に言えば無効な HTML だと思います。IDまたはdata-属性の代わりにクラスを使用して、要素を識別する他のメカニズムを使用することをお勧めします。.getElemntById()次に、次のいずれかに移動できます.querySelector()JS Bin を試してください):

<html>
<head>
<title></title>
</head>
<body>
  <div id="div1">
    <svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px">
      <rect class="rect1" width="50px" height="50px"/>
    </svg>
  </div>
  <div id="div2">
    <svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px">
      <rect class="rect1" width="50px" height="50px"/>
    </svg>
  </div>
  <script type="text/javascript">
    document.querySelector("#div1 .rect1").setAttribute("fill","red");
    document.querySelector("#div2 .rect1").setAttribute("fill","green");
  </script>
</body>
</html>

または.getElementsByClassName()JS Bin を試してください):

<html>
  <head>
    <title></title>
  </head>
  <body>
    <div id="div1">
      <svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px">
        <rect class="rect1" width="50px" height="50px"/>
      </svg>
    </div>
    <div id="div2">
      <svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px">
        <rect class="rect1" width="50px" height="50px"/>
      </svg>
    </div>
    <script type="text/javascript">
      document.getElementById("div1").getElementsByClassName("rect1")[0].setAttribute("fill","red");
      document.getElementById("div2").getElementsByClassName("rect1")[0].setAttribute("fill","green");
    </script>
  </body>
</html>

ID.querySelector()属性をそのままにしておくと、次のように機能する可能性があります。

document.querySelector("#div1 [id=rect1]")

data-しかし、潜在的な ID の落とし穴を回避するため、属性を使用することをお勧めします。

于 2013-09-06T05:59:43.670 に答える
2

すでに jQuery を使用しているため、ID の重複を気にしない jQuery のセレクターを使用できます。

function colorBox(divID, svgElem, colorHex) {
  var svgBox = $('#'+divID+' svg').find('#'+svgElem);
  svgBox.css("fill", colorHex);
}

デモはこちら: http://jsfiddle.net/w9KA3/1/

于 2013-09-06T06:10:42.527 に答える