07 | 2010/08 |  09

  1. 無料サーバー

User forum-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

CSSやJavascript自習の苦闘史を綴っていきたい。恐縮ですがJavascriptを有効にしてご覧ください。
2005年12月から社会問題も掲載!


スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

jquery.js を使ってインラインコンテンツサイズを計測する

jquery.js における要素サイズ計測

HTML 要素には、一般には特定の CSS スタイルシートが適用されていますし、各要素には style 属性が設定されている場合もあれば、されていない場合もあります。style 属性が設定されている場合であっても、要素サイズに係る CSS スタイル属性の、一部又は全部が指定されていない場合もあります。

このような状況に対して、jquery.js では CSS style について統一的な対応が図られており、例えば要素サイズを計測する場合、jQuery(・・・).width、jQuery(・・・).innerWidth、jQuery(・・・).outerWidth、jQuery(・・・).outerWidth(true) 各メソッドを使って、内容辺幅、パッディング辺幅、ボーダー辺幅及びマージン辺幅を取得出来ます。(jQuery(・・・).width メソッドだけは設定も可能)。そして同様なメソッドが高さについても存在しています。

そして、これらの要素サイズ計測メソッドは、全て 2 つのクラスメソッド( jQuery.css と jQuery.curCSS )を使用します。jQuery(・・・).css メソッドはサイズの設定/取得が可能で、jQuery(・・・).css メソッドから必要に応じて jQuery(・・・).curCSS メソッドが呼び出されます。

さて、これらの 2 つのクラスメソッドは、特別な指定をしない限り、スタイル属性が設定されていればその値を使用し、設定されていない場合には、算出スタイル値(computed style value。IE で言うところのカレントスタイル値)を計測します。jQuery(element).css(propertyName) メソッドはそのように作動します。(勿論、style 属性による指定を無視して、算出スタイル値を計測することも可能ですが、ここでの論議の焦点からずれるので、このことについては触れません。)

以上についてはこちらのエントリイで詳述しました。

では、jquery.js を使って、ブロックボックスサイズではなく、そのコンテンツサイズ、特にインラインコンテンツサイズを知るにはどうすればよいのでしょうか?( ※ コンテンツがブロック要素の場合には上述のメソッドで容易に取得可能 )

例えば、ul 要素内に複数の li 要素があるとします。問題を簡単にするために li 要素はデフォルトのブロック要素であると仮定します。このとき、各 li 要素のコンテンツは文字列だけの場合もあれば、画像や動画の場合もあります。それらの混合である場合もあるでしょう。そしてそれぞれのコンテンツの幅や高さは一般にコンテンツ毎に異なります。

このようなケースにおいて、インラインコンテンツの幅と高さを、jquery.js を使ってどのように取得すれば良いのでしょうか? ブロック要素ではなくその中のインラインコンテンツサイズを jquery.js を使って取得すること、これがこのエントリイのテーマです。なお、その際にはブラウザの表示内容や状態を、見た目では一切変えることなく計測することが前提となります。

▲ToTop

表示/非表示描画と可視/隠蔽描画

CSS 属性には要素の描画に関して、非常に似通っているが異なる内容の属性があります。それは display 属性と visibility 属性です。

前者は直訳すれば表示属性であり後者は可視属性と呼べるでしょう。以下この訳語を使います。

表示属性はよく知られている block、none、inline の他に、list-item、marker、compact、run-in、table、inline-table、table-caption 等々、多数の値が定義されています。他方可視属性は、visible、hidden、collapse の 3 つの値しか定義されていません。

さて、jquery.js を活用し、これらの 2 つの属性を組み合わせることで、出来るだけ効率的にインラインコンテンツのサイズを計測する方法について、以下に例示を示しつつ一般化してみます。

▲ToTop

jQuery(・・・).width()/height() メソッドで測る

このエントリイ上部にある「目次」を利用して、ol や li などのブロック要素とその中に配置されている文字列インラインコンテンツのサイズ計測を行いました。その結果は以下の通りです。

// ol ブロック要素の測定
 1: $("#contents").css({display:"block",visibility:"visible"}).width() //604
 2: $("#contents").css({display:"block",visibility:"hidden"}).width() //604
 3: $("#contents").css({display:"none",visibility:"visible"}).width() //354
 4: $("#contents").css({display:"none",visibility:"hidden"}).width() //354
// li ブロック要素の測定
 5: $("#contents>li:first").css({display:"block"}).width() //604
 6: $("#contents>li:first").css({display:"none"}).width() //241
 7: $("#contents>li:eq(1)").css({display:"none"}).width() //247
 8: $("#contents>li:last").css({display:"none"}).width() //354
// インラインコンテンツそのものの測定
// 9から11 は $("#contents>li").css({display:"block"}) となっている状態での
// 計測値である。もし  $("#contents>li").css({display:"none"}) であれば
// 9から11 は全てゼロとなる。
 9: $("#contents>li:first").children().eq(0).width() //241
10: $("#contents>li:eq(1)").children().eq(0).width() //247
11: $("#contents>li:last").children().eq(0).width() //354

// インラインコンテンツそのものの測定その2
12: $("#contents>li:eq(1)").children().eq(0).css({display:"inline"}).width() //247
13: $("#contents>li:eq(3)").children().eq(0).css({display:"block"}).width() //604

// ol ブロック要素の高さ測定
14: $("#contents").css({display:"block"}).height() //54
15: $("#contents").css({display:"none"}).height() //54

// li ブロック要素の高さ測定
16: $("#contents>li:first").css({display:"block"}).height() //18
17: $("#contents>li:first").css({display:"none"}).height() //18
// li ブロック内のインラインコンテンツの高さ測定
18: $("#contents>li:first").children().eq(0).height() //18

以上から以下のように多くのことが分かります。

  1. 或るブロック要素の display を none として当該要素に対して jQuery(・・・).width メソッドを適用すると、その子孫要素である inline 要素の幅を計測することが出来る。子要素だけではなく孫要素であるインライン要素に対してもこの方法で計測できることに注目したい。

    このことは 8. や 11. との比較で分かるように、3. で得られた値が目次文字列の中の最大幅の文字列幅となっていることから結論づけられる。

    また、5.~8. の li ブロックの計測結果でも判然としている。

    但し、この方法は対象要素が表示されている場合にはそのままでは使えない。display:"none" と指定することによって要素を非表示にしてしまうからである。その場合には、インラインコンテンツそのものを計測する 9.~11. の方法を採用すればよい。

  2. 1. と 2. 及び 3. と 4. との比較でも分かるように、サイズ計測に visibility 属性は影響を与えない。よって5. 以降では visibility 属性は考慮外とした。
  3. 9.~11. ではインライン要素そのものを対象として計測したが、このように直接測ることも可能である。しかしこの方法は記述が長くなるので計測対象が表示されている場合以外には、決して推奨できないだろう。
  4. 12. では敢えて inline 属性を与えて取得してみたがそれは 10.の結果と変わらなかった。つまり 12. の方法は意味がない。
  5. 14. ~ 18. で分かるように高さの取得については、display 値が block であろうが、none であろうが結果が変わらない。しかも複数行の場合もチェックしてみたが、やはりインラインコンテンツ高さは同じ値となった。つまり、高さに関しては display 値に無関係にインライン高さサイズが取得できた。

それにしてもどうしてこのように動くのか?、それを解明する必要があります。

ルールを知っておかないと jQuery(・・・).width()/height() メソッドを自在に運用することは出来ないからです。

次のエントリイでこの「ルール」について触れてみたいと思います。

スポンサーサイト

複数の jQuery プラグインで共有するオブジェクトを無名関数内に定義する

複数の jQuery プラグインを管理するために必要となる共通関数

マウスカーソル位置、要素位置、要素サイズ、window サイズ、スクロール値などの値は、jQuery プラグインを作成する上で、あれこれの複数のプラグインに共通して必要となる基本的な情報であり、どのプラグインからも使用できるように定義することが求められる。

こうして複数のプラグインから共通して利用できるオブジェクトを作成した。

概要は以下の通り。

  1. 各プラグインから共通して使用する jQuery クラスオブジェクト F を、任意の 1 以上のプラグインコードが記されたファイル内の無名関数内に配置する。
  2. プラグインファイルが 2 つ以上に分割されていても利用できるようにする。
  3. F のプロパティには HTML 要素や winodw の位置、大きさ、スクロール値を算出する関数を登録する。
  4. また、window resize、window scroll 及び mousemove イベントの各ハンドラーも F のプロパティに登録する。
  5. イベントハンドラーを除く上記の諸関数による取得値を、各プラグインコード内の変数や、HTML 要素を参照するオブジェクト( jQuery インスタンスオブジェクトを含む )に登録できるように、諸関数の引数を工夫する。
  6. F オブジェクトには getPos、getSize、getScroll、eF、winSize、winscrollPos、mousePos の 8 つのプロパティを設け、各プロパティ値を全て関数か、関数の実行返値とする。
  7. getPos、getSize、getScroll の 3 つの関数は、eF 関数オブジェクトから、あるいは各プラグインコード内に設けられた DOM Reaady 関数内から直接び出され、これらに返値を返す。
  8. 複数のプラグインから利用することを想定しているイベントハンドラーは、試行錯誤の結果、各プラグインコード内の変数や、HTML 要素を参照するオブジェクトに登録するのではなく、直接 $.F オブジェクトのプロパティ値として登録することにした。
  9. 言わずもがなのことであるが、mousemove イベントは DOM が Ready された状態でマウスカーソルが移動することによって発生する。そのため例えば DOM が Ready される前に、マウスカーソルを当該ブラウザとは別のアプリケーションに移動した場合には $.F.mousePos オブジェクトが誕生する前に、それを利用するコードが進行する場合もある。このような場合に対処するために、$.F.mousePos = {X:"0px",Y:"0px"};の一行を挿入した。

その jQuery クラスオブジェクトについて

オブジェクト名は単純明快に F とし、次のように定義した。因みに jquery.js による jQuery クラスオブジェクトには F プロパティは存在しない。

  $.F ={
    // 要素の位置計測
    getPos : function(elem){
      if (!$(elem)||!$(elem).offset()) return false;
      var off = $(elem).offset(),
      	  pos = $(elem).position();
      return {
        left : off.left, // 絶対座標横方向値
        top : off.top, // 絶対座標縦方向値
        posLeft : pos.left, // offsetParent座標横方向値
        posTop : pos.top // offsetParent座標横方向値
      }
    },
    // 要素の大きさ計測
    getSize : function(elem){
      if (!$(elem)||!$(elem).width()) return false;
      if (elem===window){
        return { //内容辺サイズ、border 辺サイズ
          cW:$(elem).width(), cH:$(elem).height(),
          oW:$(elem).outerWidth(), oH:$(elem).outerHeight()
        }
      } else {
        return { //内容辺サイズ、padding 辺サイズ、border 辺サイズ及び margin 返サイズ
          cW:$(elem).width(), cH:$(elem).height(),
          iW:$(elem).innerWidth(), iH:$(elem).innerHeight(),
          oW:$(elem).outerWidth(), oH:$(elem).outerHeight(),
          oMW:$(elem).outerWidth(true), oMH:$(elem).outerHeight(true)
        }
      }
    },
    // スクロール値取得
    getScroll : function(elem){
      if (!$(elem)) return false;
      return {L:$(elem).scrollLeft(), T:$(elem).scrollTop()}
    },
    // ノードに位置、サイズ及びスクロールの各プロパティを設定する。
    eF : function(elem){
      if (!$(elem)) return false;
      elem.pos = $.data(elem,"pos") || $.data(elem,"pos",$.F.getPos(elem));
      elem.size = $.data(elem,"size") || $.data(elem,"size",$.F.getSize(elem));
      elem.scroll =$.data(elem,"scroll") || $.data(elem,"scroll",$.F.getScroll(elem));
    }
  }
  // $.F オブジェクトにwindowサイズとスクロール値及び
  // resize event ハンドラー, scroll event ハンドラーを登録する。
  $(function(){
      $.F.winSize = $.F.getSize(window); // 現在値の取得
      $.F.winScrollPos = $.F.getScroll(window); // 現在値の取得
      $.F.mousePos = {X:"0px",Y:"0px"}; // 初期値設定
      //resize,scroll イベントハンドラー
      $(window).resize(function(){$.F.winSize = $.F.getSize(window)})
        .scroll(function(){$.F.scrollPos = $.F.getScroll(window)});
      // body 上での mousemove イベントハンドラー。マウス位置取得
      $(document.body).mousemove(function(e){
        $.F.mousePos={X:e.pageX, Y:e.pageY};
      });
    }
  })

▲ToTop

各プラグインから共用する F オブジェクトの説明

$.F.eF メソッドにより任意の HTML 要素の位置、大きさおよびスクロール値を取得する。また、$.F オブジェクトの winSize 及び winScrollPos プロパティに、頁オープン時の window の大きさとスクロール値を取得し、かつ、これらの値は window resize 及び window scroll イベントに対応させた。更に $.F.mousePos プロパティに、mousemove イベントによるマウスカーソル位置を取得した。

なお、$.F オブジェクト定義時(つまり頁を開いた時)にマウスカーソルが当該 window 内にない場合もあるので、mousePos プロパティは初期値として {top:0,left:0} を設定した。そうしないとマウスカーソルが window 外にある場合には、$.F オブジェクト定義時に mousePos プロパティが未定義になってしまうからである。

eF メソッドにより取得された値は、対象となった HTML 要素オブジェクトの pos、size 及び scroll プロパティ値に格納される。このことを jQuery インスタンスで表現すれば、jQuery における対象要素表現 strings を expr として、jQuery(expr)[0].pos、jQuery(expr)[0].size、jQuery(expr)[0].scroll である。

DOM Ready 関数内で取得された window サイズ、スクロール値あるいはマウスカーソル絶対座標値は、$.F オブジェクトの winSize、winScrollPos あるいは mousePos プロパティに格納される。

F オブジェクトや複数のプラグインを内包する無名関数の構成

■ 1 以上のプラグインコードを含む 1 つの任意のプラグインファイル内の冒頭で、
  $.F オブジェクトを登録する。
(function($){
  // 複数のプラグインから利用する F オブジェクトを定義する
  $.F={……}; 
  $(function(){
    $.F.winSize = $.F.getSize(window);
    ・・・
    ・・・
    $(document.body).mousemove(function(e){
      $.F.mousePos={X:e.pageX, Y:e.pageY};
    });
  });
  $.fn.pluginA = function(){ // プラグイン A
    // eF 関数を jQuery インスタンスの i 番目の要素を引数にして起動。これにより、
    // 当該要素の絶対位置とオブセットペアレント内の位置が当該要素の pos プロパティに、
    // 当該要素の大きさが当該要素の size プロパティに、
    // 当該要素のスクロール値が当該要素の scroll プロパティに、それぞれ設定される。
    $.F.eF(this[i]);
    ・・・・・・・
  };
  $.fn.pluginB = function(){ // プラグイン B
    $.F.eF(this[i]);
	・・・・・・・
  };
  ・・・・・・・
})(jQuery)

■ 別のプラグインファイル内からの $.F オブジェクトの利用
(function($){
  $.fn.pluginC = function(){ // プラグイン C
    // eF 関数を jQuery インスタンスの i 番目の要素を引数にして起動。これにより、
    // 当該要素の絶対位置とオブセットペアレント内の位置が当該要素の pos プロパティに、
    // 当該要素の大きさが当該要素の size プロパティに、
    // 当該要素のスクロール値が当該要素の scroll プロパティに、それぞれ設定される。
    $.F.eF(this[i]);
    ・・・・・・・
  };
  $.fn.pluginD = function(){ // プラグイン D
    $.F.eF(this[i]);
	・・・・・・・
  };
  ・・・・・・・
})(jQuery)

 90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。

 多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。

 StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。

 クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。

 起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。

 ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。

 無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。

 画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。

 複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。

 Animation Gifファイルを作れる無料ソフト。

 キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。

 画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)

 名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。

 ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。

 AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。

 IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。

 利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。

 WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。

 自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。

 DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。