frog.raindrop.jp

.knowledge
::JavaScript / JScript / ECMAScript

Last Modified
February 01, 2010 11:20 PM

Search


もっと前のEntry


あわせて読みたいブログパーツ
RSS feed meter for http://frog.raindrop.jp/
counter

January 6, 2010

続、目次フレームを自動生成する

あと、目次フレームを自動生成するの toc.js の諸々を修正しました。主な修正点はオブジェクトメンバの実装をリテラル記法にして見やすくしたのと、自動生成される ID の番号の階層がおかしかった点を改善しました。

あと、汎用性を考慮して初期化ハンドラを自動で登録しないようにしたのでwindow.onload を待たずに処理を開始するを使ってもいいかも。

<script type="text/javascript" src="loadlistener.js"></script>
<script type="text/javascript" src="toc.js"></script>
<script type="text/javascript">//<![CDATA[
    LoadListener.onload = function () { toc.create(); };
//]]></script>

window.onload を待たずに処理を開始する

Web ページの読み込み時に処理をさせる場合、何の疑問も持たずに window.onload を使っていたんですが、このハンドラは DOM ツリーだけじゃなくて画像まで全部読込んでから実行されるらしいです。知らんかった…。

で、そうじゃなくて DOM ツリーが生成されたタイミングで処理を開始したいなーってことで、あちこちのサイトでそんな Tips が取り上げられてるんですが、よんでもいまひとつ理解できない…。

なので調べつつ、結局自分でスクリプトを書き直してみました。こちらのブログ記事がよくまとまっていて大変参考になりました。あと、元ネタにあたるこちらとかこちらとか…。

December 22, 2009

目次フレームを自動生成する

Javascript で HTML 文書中の h1 ~ h6 を抜き出して、目次を作成するスクリプトを作成しました。見出し要素に id が振られていなければ自動生成します。自動生成した場合にやたらと "-0" が付くのはご愛嬌…。


2010.01.06 10:40 追記
自動生成した id の階層がおかしかったのを修正したものはこちら

とりあえず、Google Chrome 3.0.195.38 と IE 8 で動作確認しました。あんまりきれいじゃないです。

さらに、CSS で目次部分を左側のフレームっぽく表示させるようにしています。なんちゃって擬似フレーム。これも動作確認環境は同じ。


2009.12.22 22:50 追記
Firefox 3.5 で確認したところ、目次が全部 "undefined" ってなっちゃってました。
Firefox は Element.innerText って使えないんでしたな… とりあえず、Element.textContent を優先的に使うように修正してみました。

サンプルの HTML / toc.js / toc.css

HTML 側では、toc.js と toc.css を読込むだけです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
    <head>
        <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8"/>
        <meta http-equiv="content-script-type" content="text/javascript"/>
        <meta http-equiv="content-style-type" content="text/css"/>
        <link href="toc.css" rel="stylesheet" type="text/css"/> 
        <script type="text/javascript" src="toc.js"></script>
        <!-- 省略… -->
    </head>
    <body>
        <h1>1章</h1>
        <h2>1章-1節</h2>
        <h3>1章-1節-1項</h3>
        <!-- 省略… -->
    </body>
</html>

自動生成する内容は、若干カスタマイズできます。toc.js を読込んだより下の行で以下のように書けば。

<script type="text/javascript">//<![CDATA[
toc.listtag = "ol";    // 番号つきリストに
toc.tocId = "tableOfContents";    // 目次部分の id を別の値に
toc.defaultIdPrefix = "section";    // 見出し要素の自動生成 id のプリフィックス
//]]>
</script>

November 27, 2009

address 要素を自動的にリンクする

body 要素の onload で下記関数をコールするようにして使用します。詳しい説明はまた。

function makeAddressLink ()
{
    var elements = document.getElementsByTagName ("address");
    for (var i = 0; i < elements.length; i ++)
    {
        var element = elements [i];
        var anchors = element.getElementsByTagName ("a");
        if (anchors == null || anchors.length == 0)
        {
            var first = element.firstChild;
            var anchor = document.createElement ("a");
            var text = document.createTextNode (first.nodeValue);
            anchor.setAttribute ("href", text.nodeValue);
            anchor.appendChild (text);
            element.replaceChild (anchor, first);
        }
    }
}

July 10, 2009

インストールされている .NET Framework のバージョンをチェックするスクリプト

.NET Frameworkのバージョンを確認する方法を参考に WSH スクリプトを書いた。

拡張子を .wsf で保存して実行してくださいねー。

<?xml version="1.0" encoding="Shift_JIS" standalone="yes" ?>
<package>
<job id="Registry">
<?job error="True" debug="True" ?>
<script language="JScript">
<![CDATA[
    var checker = new DotNetChecker ();
    var result = "";
    result += checker.FormatResult (checker.Check10 (), ".NET Framework 1.0");
    result += checker.FormatResult (checker.Check11 (), ".NET Framework 1.1");
    result += checker.FormatResult (checker.Check11JP (), "    Japanese Langage Pack");
    result += checker.FormatResult (checker.Check20 (), ".NET Framework 2.0");
    result += checker.FormatResult (checker.Check20JP (), "    Japanese Langage Pack");
    result += checker.FormatResult (checker.Check30 (), ".NET Framework 3.0");
    result += checker.FormatResult (checker.Check30JP (), "    Japanese Langage Pack");
    result += checker.FormatResult (checker.Check35 (), ".NET Framework 3.5");
    result += checker.FormatResult (checker.Check35JP (), "    Japanese Langage Pack");

    WScript.Echo (result);

    function DotNetChecker ()
    {
        this.reader = new RegReader ();

        this.Check10 = function ()
        {
            var install = this.reader.RegRead ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\Full\\v1.0.3705\\1041\\Microsoft .NET Framework Full v1.0.3705 (1041)\\Install");
            if (install == null || "" + install == "0")
                return null;

            var version = this.reader.RegRead ("HKLM\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{78705f0d-e8db-4b2d-8193-982bdda15ecd}\\Version");
            if (version == null)
                version = this.reader.RegRead ("HKLM\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}\\Version");
            if (version == null)
                return 0;

            var regex = /^1,0,3705,(\d+)$/;
            var m = regex.exec (version);
            var sp = 0;
            if (m != null && m.length > 1)
                sp = m [1] - 0;

            return sp;
        }

        this.Check11 = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322");
        }

        this.Check20 = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727");
        }

        this.Check30 = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.0");
        }

        this.Check35 = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5");
        }

        this.Check11JP = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322\\1041");
        }

        this.Check20JP = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727\\1041");
        }

        this.Check30JP = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.0\\1041");
        }

        this.Check35JP = function ()
        {
            return this.CheckKey ("HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5\\1041");
        }

        this.CheckKey = function (key)
        {
            var install = this.reader.RegRead (key + "\\Install");

            if (install == null || "" + install == "0")
                return null;

            var sp = this.reader.RegRead (key + "\\SP");
            if (sp == null)
                sp = 0;
            return sp;
        }

        this.FormatResult = function (value, label)
        {
            var result = label;

            switch (value)
            {
            case null:
                result += ": not installed.\n"; break;
            case 0:
                result += ": installed.\n"; break;
            default:
                result += ": SP" + value + " installed.\n"; break;
            }
            return result;
        }

    }

    function RegReader ()
    {
        this.shell = WScript.CreateObject ('WScript.Shell');

        this.RegRead = function (name)
        {
            var ret = null;
            try
            {
                ret = this.shell.RegRead (name);
            }
            catch (e)
            {
                //WScript.Echo (e.number + "\n" + e.description);
            }
            return ret;
        }

        return this;
}
]]>
</script>
</job>
</package>

November 29, 2007

圧縮フォルダを作成してコピーする WSH スクリプト

shell32.dll の Shell オブジェクトを使用してZIPフォルダを作る JScript です。これも1回使っただけでお蔵入りの予感。VC++ 版もあるけど・・・API直叩きの方がいい気がするので、それはとりあえず保留。
//
// makeZipFolder.js
//

// スクリプト ランタイム関連
var fileSystemObject = new ActiveXObject ('Scripting.FileSystemObject');
var wsShell = new ActiveXObject ('WScript.Shell');

// 固めるパス
var sourcePath = wsShell.SpecialFolders ('AppData');
sourcePath = fileSystemObject.BuildPath (sourcePath, "Test");

// デスクトップ
var desktopPath = wsShell.SpecialFolders ('Desktop');

// 作成する ZIP ファイルのパス
var zipPath = fileSystemobject.BuildPath (desktopPath, 'Test.zip');

// ZIP ファイルを作成する
var zipFile = fileSystemObject.CreateTextFile (zipPath, false);
zipFile.Write ("PK\5\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
zipFile.Close ();

// ZIP ファイルを圧縮フォルダとして取得
var shell = new ActiveXObject ('Shell.Application');
var zipFolder = shell.NameSpace (zipPath);

// コピー元
var sourceFolder = fileSystemObject.GetFolder (sourcePath);

for (var n = 0, var e = new Enumerator (sourceFolder.Files); ! e.atEnd (); e.moveNext ())
{
    // ファイルをコピー
    var sourceFolderItem = shell.Namespace (e.item ().ParentFolder.Path).ParseName (e.item ().Name);
    zipFolder.CopyHere (sourceFolderItem);
    n ++;
    
    // コピーが完全に完了するまで待機
    while (n == zipFolder.Items ().Count)
    {
        WScript.Sleep (100);
    }
}
WScript.echo ("完了しました。");

入力システムを列挙する WSH スクリプト

タイトルの通りです。「テキスト サービスと入力言語」コントロールパネルでいうと、
規定の言語
HKCU\Keyboard Layout\Preload\1
インストールされているサービス
HKCU\Keyboard Layout\Preload 以下の値のリスト
[追加] ボタンより追加可能な全IME
HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts 以下のサブキーのリスト
と言う具合に、レジストリに情報が格納されているのでこれらを取得します。お蔵入りスクリプトになってしまい、もったいないのでアップします。
//
// enumIme.js
//

// 定義済み HKEY
var HKEY_CLASSES_ROOT   = 0x80000000;
var HKEY_CURRENT_USER   = 0x80000001;
var HKEY_LOCAL_MACHINE  = 0x80000002;
var HKEY_USERS          = 0x80000003;
var HKEY_CURRENT_CONFIG = 0x80000005;
var HKEY_DYN_DATA       = 0x80000006;

// WMI の StdRegProv を使用する
var locator = new ActiveXObject ("WbemScripting.SWbemLocator");
var service = locator.ConnectServer (null, "root\\default");
var stdRegProv = service.Get ("StdRegProv");

// スクリプト ランタイム関連
var fileSystemObject = new ActiveXObject ('Scripting.FileSystemObject');
var wsShell = new ActiveXObject ('WScript.Shell');
var desktopPath = wsShell.SpecialFolders ('Desktop');

// ログファイル、Layout Text 等が SJIS では表示できない可能性があるため、ユニコードテキストで
var logFile = fileSystemObject.CreateTextFile (fileSystemObject.BuildPath (desktopPath, "imecheck.txt"), true, true);

// すべてのキーボードレイアウト
// HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts
var lmImeList = new SubKey (stdRegProv, HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control", "Keyboard Layouts");
lmImeList.getSubKeys ();

// 言語バーより選択可能なキーボードレイアウト
// HKCU\Keyboard Layout\Preload
var preload = new SubKey (stdRegProv, HKEY_CURRENT_USER, "Keyboard Layout", "Preload");

for (var item in preload.getRegValues ())
{
    logFile.Write (item);   // 値名は番号
    logFile.Write (":");
    
    // 値はキーボードレイアウトの番号
    logFile.WriteLine (preload.regValues [item].value);
    
    // キーボードレイアウトの番号より、情報を取り出す
    var keyObj = lmImeList.subKeys [preload.regValues [item].value.toUpperCase ()];
    if (keyObj == null) keyObj = lmImeList.subKeys [preload.regValues [item].value.toLowerCase ()];
    
    // 情報あり
    if (keyObj != null)
    {
        for (var item2 in keyObj.getRegValues ())
        {
            // 値名 "layout text" を探す
            if (-1 != item2.search (/layout text/i))
            {// 見つかった
                logFile.Write ("        ");
                logFile.Write (item2);
                logFile.Write ("(" + keyObj.regValues [item2].typeName + ")");
                logFile.Write ("\t:");
                logFile.WriteLine (keyObj.regValues [item2].value);
            }
        }
    }
}

logFile.WriteBlankLine ();

// Keyboard Layouts のリスト
logFile.WriteLine (lmImeList.path);
writeImeList (logFile, lmImeList, "");

// ファイルを閉じる
logFile.Close ();

// 終了
WScript.echo ("完了しました");

//
// キーボードレイアウトのリストを出力する
//
function writeImeList (file, keyObj, padding)
{
    var item;
    var pad = padding + "  ";

    for (item in keyObj.getSubKeys ())
    {
        file.WriteLine (pad + keyObj.subKeys[item].name);
        writeImeList (file, keyObj.subKeys[item], pad);
    }
    
    for (item in keyObj.getRegValues ())
    {
        file.Write (pad);
        file.Write (item);
        file.Write ("(" + keyObj.regValues[item].typeName + ")");
        file.Write ("\t:");
        file.WriteLine (keyObj.regValues[item].value);
    }
    file.WriteLine ();
}



// レジストリキーオブジェクトのコンストラクタ
function SubKey (regProv, hDefKey, parentSubKey, name)
{
    //
    // メンバの初期化
    //
    this.regProv = regProv;
    this.hDefKey = hDefKey;
    this.parentSubKey = parentSubKey;
    this.name = name;
    this.path = parentSubKey + "\\" + name;
    this.subKeys = null;
    this.regValues = null;
    
    //
    // メソッドの定義
    //
    
    // サブキーのコレクションを取得
    this.getSubKeys = function ()
    {
        if (!this.subKeys)
        {
            var method = this.regProv.Methods_.Item ("EnumKey");
            var inParameter = method.InParameters.SpawnInstance_ ();
            inParameter.hDefKey = this.hDefKey;
            inParameter.sSubKeyName = this.path;
            var outParameter = this.regProv.ExecMethod_ (method.Name, inParameter);
            this.subKeys = new Array ();
            if (outParameter.sNames != null)
            {
                var subKeys = outParameter.sNames.toArray ();
                for (var i = 0; i < subKeys.length; i ++)
                {
                    this.subKeys [subKeys [i]] = new SubKey (this.regProv, this.hDefKey, this.path, subKeys [i]);
                }
            }
        }
        return this.subKeys;
    }
    
    // キー内の値の取得
    this.getRegValues = function ()
    {
        if (!this.regValues)
        {
            var method = this.regProv.Methods_.Item ("EnumValues");
            var inParameter = method.InParameters.SpawnInstance_ ();
            inParameter.hDefKey = this.hDefKey;
            inParameter.sSubKeyName = this.path;
            var outParameter = this.regProv.ExecMethod_ (method.Name, inParameter);
            this.regValues = new Array ();
            if (outParameter.sNames != null)
            {
                var names = outParameter.sNames.toArray ();
                var types = outParameter.Types.toArray ();
                var typeNames = new Array (
                    ""                              ,    // 0
                    "REG_SZ"                        ,    // 1
                    "REG_EXPAND_SZ"                 ,    // 2
                    "REG_BINARY"                    ,    // 3
                    "REG_DWORD"                     ,    // 4
                    "REG_DWORD_BIG_ENDIAN"          ,    // 5
                    "REG_LINK"                      ,    // 6
                    "REG_MULTI_SZ"                  ,    // 7
                    "REG_RESOURCE_LIST"             ,    // 8
                    "REG_FULL_RESOURCE_DESCRIPTOR"  ,    // 9
                    "REG_RESOURCE_REQUIREMENTS_LIST",    // 10
                    "REG_QWORD"                    );    // 11
                var getTypeValues = new Array (
                    null,
                    getStringValue,
                    getExpandedStringValue,
                    getBinaryValue,
                    getDWORDValue,
                    getDWORDValue,
                    null,
                    getMultiStringValue,
                    null,
                    null,
                    null,
                    getQWORDValue);
                
                for (var i = 0; i < names.length; i ++)
                {
                    this.regValues [names [i]] = new Object ();
                    this.regValues [names [i]].name = names [i];
                    this.regValues [names [i]].type = types [i];
                    this.regValues [names [i]].typeName = typeNames [types [i]];
                    this.regValues [names [i]].value = "";
                    var fn = getTypeValues [types [i]];
                    if (fn)
                    {
                        this.regValues [names [i]].value = fn (this.regProv, this.hDefKey, this.path, names [i]);
                    }
                }
            }
        }
        return this.regValues;
    }
    return this;
}


// 文字列値取得
function getStringValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetStringValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    return outParameter.sValue;
}

// 展開済み文字列値取得
function getExpandedStringValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetExpandedStringValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    return outParameter.sValue;
}

// バイナリ値取得
function getBinaryValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetBinaryValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    var str = "";
    var ary = outParameter.uValue.toArray ();
    for (var i = 0; i < ary.length; i ++)
    {
        str += ary [i].toString (16) + ((i + 1) % 8)? " ": "\n";
    }
    return str;
}

// DWORD 値取得
function getDWORDValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetDWORDValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    return outParameter.uValue.toString (16);
}

// QWORD 値取得
function getQWORDValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetQWORDValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    return outParameter.uValue.toString (16);
}

// マルチ文字列値取得
function getMultiStringValue (regProv, hDefKey, sSubKeyName, sValueName)
{
    var method = regProv.Methods_.Item ("GetMultiStringValue");
    var inParameter = method.InParameters.SpawnInstance_ ();
    inParameter.hDefKey = hDefKey;
    inParameter.sSubKeyName = sSubKeyName;
    inParameter.sValueName = sValueName;
    var outParameter = regProv.ExecMethod_ (method.Name, inParameter);
    return outParameter.sValue.toArray ().toString ();
}

February 20, 2005

WSH よりクリップボードを使う

WSH よりクリップボードにアクセスすることはできない。しかし、調べてみたところ、Internet Explorer がクリップボードにアクセスするためのインターフェースを公開していることがわかった(常套手段?)。

そんなわけで、文字列をコピー & 取得する部分をクラス化した。

使い方はこんな感じで。

var clipboard = new Clipboard ();
var s = clipboard.getText ();
WScript.Echo (s);
clipboard.setText (s.replace (/my/gi, "Your"));

January 21, 2005

WSH でショートカットを作成する

WSH でショートカットを作成する方法です。どこにでも転がっているものと同じですが、自分のために。 コマンドラインコピーツール のインストーラとして作成したものです。

November 19, 2004

IE をぎょうさん起動したいとき

ASP のテストで、同時最大セッション数を超えるとエラー表示する、みたいな項目があったが、最大セッション数分手でブラウザを起動するのが面倒だった。セッション数だけ稼げれば別にブラウザは何でも良かったので、IE でいいやって WSH スクリプトを作成。

// NavMaxSess.js
var MAX_SESSION = 100;
for ( var i = 0; i < MAX_SESSION; i++ ) {
	var oIE = WScript.CreateObject( "InternetExplorer.Application" );
	oIE.Visible = true;
	oIE.Navigate2( "http://aspserver/target.asp" );
}

小品ですが、結構重宝してます。

October 5, 2004

連番の拡張子にリネームするJScript

拡張子が'tif'のファイルを連番の拡張子に変えるWSHのバッチプログラムです。 これ自体はあまり汎用性がないのですが、ちょこちょこっと変えれば使い道はあるでしょう。 できればこれのBATファイル解がほしいのですが・・・。

September 16, 2004

連番フォルダ作成JScript

連番フォルダ作成バッチの姉妹品。WSHさえ入っていれば動くので、拡張機能を使いまくったBATファイルより汎用的なのかも。

February 26, 2004

MSDEのデータをエクスポート・インポートするJScript

MSDEのデータを手軽にExport/ImportするWSHスクリプトです。'.js'拡張子をつけて保存し、ダブルクリックするかコンソールからCSCRIPT Export.jsなどとして実行します。わざわざ実行速度の遅いJScriptで作っている理由は、単に try{...} catch( e ) {...} でトランザクション処理がしたかったというだけのことです 笑。

MSDE用になっているのは接続文字列だけなので、その部分のみ変更すればOracleやJETなど、ADOで接続可能なDBであれば使用可能だと思います。(でもWSHが利用可能な環境でしか実行できません。)