ID Reference Emulation for Navigator 4

Netscape Navigator 4.x での、(A 要素の name 参照でなく) ID 参照によるハイパーリンクの実現を試みる。 XHTML1.1 とかで使える、かも。

Table of Contents

基本原理

ここでは、 position 指定をした要素であれば、 N4 でも id によって要素を Layer オブジェクトとして認識可能である点を利用して、この実現を試みる。

目標1

こんな感じで動作させるような関数を作ればよいだろう。

  if(location.hash){  // 現在の URI が部分識別子を持っていたら
    scrollToLayer( location.hash.substring(1) );
                      // ロケーションから取得した部分識別子を元に
                      // その名前を ID に持つ Layer までスクロール
  }

このような scrollToLayer() を作れば解決できる。

目標2

同一ページ内でのリンクについては上のコードの呼出しが難しい。上で想定した scrollToLayer が作れるとしたら、それをリンクのクリックで呼出したい。

  var links = document.links;
  for ( var i=0; i<links.length; i++ ){
    if(links[i].hash && links[i].pathname==location.pathname){
      links[i].onclick = scrollToLayer;
    }
  }

function scrollToLayer (o)

では、部分識別子のオブジェクトを取得してその位置までページをスクロールさせる Function を作成する。引数は部分識別子を表す文字列、またはイベントオブジェクト。

  function scrollToLayer (o){
    var id = (typeof o == 'object')?
                  o.target.hash.substring(1) : String(o);
    if (document.layers[id]){
      location.hash=id;
      window.scrollTo(0, document.layers[id].pageY);
      return false;
    }
  }

function layerEnum (layers)

上で参照している document.layers は、実際には、 Layer オブジェクトが階層化されているため文書中の全 Layer オブジェクトを認識することが出来ない。なので、別途オブジェクトを作成し Layer を単階層にまとめなおし、上の関数ではそのオブジェクトを参照するようにする。

  var lays = function layerEnum (layers, lays) {
    for(var i=0; i<layers.length; i++){
      lays[layers[i].id] = layers[i];
      layerEnum(layers[i].document.layers, lays);
    }
    return lays;
  } (document.layers, new Object);

JavaScript StyleSheet

勿論、 position 指定するのを忘れてはいけない。ここでは、折角なので(笑) JSS を使ってみた。 JSS にしたのは Netscape 4 以外にこのスタイルを読ませる必要が無いこと、同時に上記の JavaScript も書けてしまうことからである。

  with(document.tags){
    h1.position =
    h2.position =
    h3.position =
    h4.position =
    h5.position =
    h6.position = 'relative';
  }

これで全ての見出し要素 (h1-h6) が、 Layer として認識可能になる。

サンプル

では、実行してみよう。というか、このページ自体にすでに上記のコードが埋め込んであったりする。後は実際に NN4 でこのページにアクセスして、リンクを追ってみるだけだ。勿論このページのソースも見て A 要素の name 属性を使ってないことも確認して欲しい。 目次へ

実際のコード:

with(document.tags){
  h1.position =
  h2.position =
  h3.position =
  h4.position =
  h5.position =
  h6.position = 'relative';
}
window.onload = function () {

  function scrollToLayer (o){
    var id = (typeof o == 'object')?
                  o.target.hash.substring(1) : String(o);
    if (lays[id]){
      location.hash=id;
      window.scrollTo(0, lays[id].pageY);
      return false;
    }
  }

  var lays = function layerEnum (layers, lays) {
    for(var i=0; i<layers.length; i++){
      lays[layers[i].id] = layers[i];
      layerEnum(layers[i].document.layers, lays);
    }
    return lays;
  } (document.layers, new Object);

  var links = document.links;
  if(location.hash){ scrollToLayer(location.hash.substring(1)); }
  for ( var i=0; i<links.length; i++ ){
    if(links[i].hash && links[i].pathname==location.pathname){
      links[i].onclick = scrollToLayer;
    }
  }

}

のうんばぐ他

かなりうまくいっているように見えるが、やはり問題は山積み。この他にもいっぱい問題を抱えていることだろうと思う。

Issued: / Revised: / All rights reserved. © 2002-2017 TAKI