2015年1月12日月曜日

インスタント検索

Google検索で、文字入力するたびに勝手に検索する機能について、
ちょっと調べたのでメモ。

実装自体は非常に単純で、JavaScriptでkeyupイベントを取得してajaxで検索処理を実行して
結果を表示するだけ、サーバサイドはPHPでもJavaでも好きなものを使って良いです。

ただし、何も考えずこのまま実装すると文字を入力するたびに検索処理が走ってしまい
非常に重たいページになってしまう。
そのため、以下のような工夫が必要になる。
・前回のキー入力から一定時間経っている場合のみ検索結果を取得
・カーソルキーやタブキーに反応しないよう、前回の入力内容と比較して同じなら処理中止

こういった注意点を突き詰めていかないと、使いづらくて重いだけのものになってしまい、
誰も使いたくないものができあがるんだろうなーと思った。

2014年5月16日金曜日

WYSIWYGエディタで画像アップロード

WYSIWYGエディタで画像アップロードできるようにしたい!!!

■CKEditor
CKEditorに画像アップロード機能を追加する設定メモ。
KCFinderと連携させる場合、phpでgdを有効化しておく必要がある。

手順などの参考リンク
CKEditorに画像アップロード機能を追加する
CKFinder からKCFinderに乗り換え
CKEditorとKCFinderの最新版がうまく動かないと聞いたので検証

ただし、そのままだとサーバのアップロードディレクトリを直接触るようなイメージになる。
そのため、以下のような懸念がある
・アップロードされた画像がそのまま残る
・他人のアップロード画像を使用したり編集できる
・削除された場合は表示できる画像がなくなる

KCFinderを使わず、画像アップロード機能を自作する場合に参考にできそうなブログ
CKEditor でオリジナルの画像ブラウザを作る的な

■TinyMCE
TinyMCEというエディタ。
解説しているブログを見る感じだと、やりたいことに近いのはこれかも。
CKEditor同様、プラグインで機能拡張するタイプみたい。

TinyMCE エディタ上で画像をアップロードしながら貼り付けられる jbimages プラグインを使ってみた


■その他
プラグインなどを使用せず、アップロード機能を別に作って
エディタ内に挿入する方法だとこんなのがある。
CLEditorとの連携になっているけど、他のエディタとでも連携できるように思う。

CLEditor + jQuery.upload Sample

jQuery.uploadの公式サイトがリンク切れているぽい。
こっちからはダウンロードできる。

jQuery.upload

2014年5月15日木曜日

Strutsの脆弱性

Apache Strutsの脆弱性について調べてみた。
こちらのブログの方が非常に丁寧にまとめていたので、
ポイントを抜粋する形でメモ。

Strutsの脆弱性CVE-2014-0094について改めてまとめてみた
Struts: ClassLoader の操作を許してしまう脆弱性 (CVE-2014-0094, CVE-2014-0112, CVE-2014-0113) について

今回の脆弱性は、外部からJavaのクラスローダーの操作を許してしまう脆弱性です。
(クラスローダーを操作して何が出来るかはStrutsが動作するアプリケーションサーバーに依存します。)

IPAでは次の影響を受ける可能性を報告しています。
・Webアプリケーションの動作権限内で情報の窃取や特定ファイルの操作が出来る
・Webアプリケーションを一時的に使用不可に出来る
・攻撃者が操作したファイルに Java コードが含まれている場合、任意のコードが実行される

対象の主なバージョン
■Struts1
全てのバージョンではないが、サポート終了のため修正版リリースは現在行われていない。
(ただし修正版、または回避策の提供をする可能性についてApache Software Foundationよりアナウンスが出ています。)

■Struts2
2.3.16.1以前全て。
2.3.16.2(2014年4月25日リリース)へアップデートすることで修正されるようです。
ただし、別のこのバージョンも新たな脆弱性が発見されたため、
2014年5月3日に2.3.16.3がリリースされているので、どうせならこっちへアップデートするべき。

とりあえずまとめは以上。
Strutsの現状について、以下のブログで詳しく紹介されていますが、
まだまだ脆弱性がでそうです。



OpenSSLの脆弱性

OpenSSLに脆弱性が発見されたという話をちょっと前に聞いたけど、
具体的にどういう脆弱性なのかがわかりづらかったのでメモ。

OpenSSLの機能の中で、今回脆弱性が発見されたのが
OpenSSL1.0.1から追加されたheartBeat機能という機能。
これは、SSLで通信している相手が稼働状態かを確認するための機能で、
具体的な動作としては、以下の通り。

1.64KBのデータを送信(クライアント⇒サーバ)
2.受信したデータをメモリにコピー(サーバ)
3.メモリ上にコピーした64KBのデータを送信(サーバ⇒クライアント)
4.データが受信可否で稼働状態を確認(クライアント)

脆弱性があるポイントは、1で送信するデータサイズを詐称することができるというところ。
この脆弱性のため、1KBのデータであっても64KBのデータとして送信することで、
サーバはメモリ上に1KBのデータしかコピーしていないのに、64KBのデータを返してしまう。
つまり、メモリ上に存在する意図しない63KB分のデータをクライアントに送信してしまうことになる。

意図しないデータの中には、ユーザの個人情報などが含まれている可能性があるため、
上記の攻撃を繰り返すことでこれらのデータが盗まれてしまうことになる。

この脆弱性が存在するのはOpenSSL1.0.1~1.0.1f と1.0.2-beta~1.0.2-beta1で、
OpenSSL1.0.1g では修正されている、1.0.2系はbeta版ということで放置されてるぽい。
もし該当のバージョンを使用しているならば、早めにバージョンアップするべき。
(ちなみに、1.0.1gの公開は、2014年4月7日)

バージョンアップが難しい場合、「-DOPENSSL_NO_HEARTBEATS」オプションを有効にし、
OpenSSLをリコンパイルすることでも対応可能らしいので、こちらを考慮するのもあり。

SSLを使用するJPドメインWebサイトの4割以上に今回の脆弱性が該当するらしいので、
影響範囲が恐ろしいほど広いのも、騒がれた原因みたい。

今回の問題はハートブリード(Heartbleed)と名前がつけられ、ロゴが作成され、
Wikipediaで専用ページまで作成されているので、一度確認しておいたほうがいい。

ハートブリード(Wikipedia)


2014年4月2日水曜日

デスクトップ整理バッチ

デスクトップがすぐに作業ファイルでいっぱいになるので、
整理用バッチを作ってみた。



@echo off
setlocal

rem ---------------------------------------------------------------------------
rem バッチ名:デスクトップ整理バッチ
rem 機能説明:バックアップ先に今日の日付でフォルダを作成し、
rem           デスクトップのファイル・フォルダを全て移動する。
rem ---------------------------------------------------------------------------

set YYYYMMDD=%DATE:/=%
set BACKUP_DIR=%USERPROFILE%\Documents\デスクトップバックアップ\%YYYYMMDD%
set BAT_NAME=デスクトップ整理.bat

mkdir %BACKUP_DIR%

for /F %%a in ('dir %USERPROFILE%\Desktop /B') do (
if NOT %BAT_NAME% == %%a (
echo "%%a"
  move "%USERPROFILE%\Desktop\%%a" %BACKUP_DIR%
)
)
for /F "skip=2 delims=" %%a in ('dir %USERPROFILE%\Desktop /B') do (
if NOT %BAT_NAME% == %%a (
echo "%%a"
  move "%USERPROFILE%\Desktop\%%a" %BACKUP_DIR%
)
)
pause
endlocal

Linuxのcron登録方法

#crontab -l
cronの設定内容を表示する。

#crontab -e
cronの登録エディタを開く。

cronの設定方法は以下の通り。

設定項目は左から「分」「時」「日」「月」「曜日」となっている。
* * * * * [実行コマンド]

設定可能な数値
分 0-59  時 0-23  日 1-31  月 1-12  曜日 0-7 (0または7は日曜日)

実行時間指定方法
リスト   0,10,20,30  分フィールド指定した場合は0,10,20,30分に実行します。
範囲  1-5         月フィールドで指定した場合、1,2,3,4,5月に処理を実行します。
共存  1,6,9-11     時間フィールドで指定した場合、1時、6時、9時、10時、11時に処理を実行します。
間隔  */10       分フィールドで指定した場合、10分間隔で処理を実行します。
          「/」の後ろに指定した値の間隔で処理を実行します。

Tomcatのスレッドダンプの解析方法

TomcatのCPU負荷が高い場合などに、一定の間隔で5回くらい出力したスレッドダンプを
「侍」というソフトで解析することで、処理中のソースを特定することができます。

Linuxでのスレッドダンプは、以下のコマンドで catalina.out に出力されます。
kill -3 [TomcatのPID]

※TomcatのJavaのオプションに「-Xrs」を付加すると、スレッドダンプを取得するための
 シグナルを受け付けなくなり解析できないので注意が必要です。

Google Maps API をとりあえず使う

Google Maps APIのサンプルを作ったのでメモ。
とりあえず動くものにしてある。
おもしろそうな機能があれば更新する予定。
文字コードはUTF-8にすること。

■GoogleMapsAPIサンプル.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps API サンプル</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=places&sensor=false&language=ja"></script>
<script type="text/javascript" src="js/map.js"></script>
</head>
<body>
<p>Google Maps APIを使ったサンプルです。</p>
X座標:<input type="text" id="locationX" value="35.709984" />&nbsp;
Y座標:<input type="text" id="locationY" value="139.810703" />&nbsp;
<input type="button" onClick="mapCreate(map_canvas, latlng, locationX, locationY);" value="地図表示" />&nbsp;
<input type="button" onClick="mapUpdate(locationX.value, locationY.value);" value="地図更新" /><br />
住所:<input type="text" id="address" />&nbsp;
<input type="button" onClick="setLatlngZip(address.value, locationX, locationY);" value="座標取得" /><br />
キーワード:<input type="text" id="keyword" />&nbsp;
<input type="button" onClick="setLatlngKeyword(keyword.value, locationX, locationY);" value="座標取得" /><br />
<div id="map_canvas" style="width:500px; height:300px"></div>
<p id="latlng"></p>
</body>
</html>


■js/maps.js
var map=null;
var marker=null;
var latlngLabel=null;
var locationXText=null;
var locationYText=null;

// マップの作成
function mapCreate(canvasObject, latlngLabelObject, positionX, positionY) {
// 座標を設定
var latlng = new google.maps.LatLng(positionX.value, positionY.value);
locationXText = positionX;
locationYText = positionY;
// マップオブジェクトのオプションを設定
var opts = {
zoom: 15,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// マップを作成し、対象のオブジェクトへ描画
map = new google.maps.Map(canvasObject, opts);
// マーカーを作成
markerCreate();
// 情報ウインドウを作成
infoWindowCreate();
// 地図のドラッグイベントに各座標を表示
latlngLabel = latlngLabelObject;
google.maps.event.addListener(map, 'drag', dispLatLng);
return;
}

// マップの座標更新
function mapUpdate(positionX, positionY) {
if(map != null) {
var latlng = new google.maps.LatLng(positionX, positionY);
// マップの座標更新
map.setCenter(latlng);

// マーカーの再作成
markerCreate();

// 情報ウインドウの再作成
markerCreate();
}
return;
}

// ドラッグ時に座標を表示
function dispLatLng(latlngObject){
var latlng = map.getCenter();
var str = "[中心座標]=[" + latlng.lat() + ", " + latlng.lng() + "]<br />";

var latlngBounds = map.getBounds();
var swLatlng = latlngBounds.getSouthWest();
str = str + "[南西端座標]=[" + swLatlng.lat() + ", " + swLatlng.lng() + "]<br />";

var neLatlng = latlngBounds.getNorthEast();
str = str + "[北東端座標]=[" + neLatlng.lat() + ", " + neLatlng.lng() + "]";
locationXText.value = latlng.lat();
locationYText.value = latlng.lng();

latlngLabel.innerHTML = str;
return;
}

// マーカーを作成
function markerCreate() {
var latlng = map.getCenter();
if(marker != null) {
marker.setMap(null);
}
marker = new google.maps.Marker({
position: latlng,
map: map,
clickable : true
});
}

// 情報ウインドウを作成
function infoWindowCreate() {
var latlng = map.getCenter();
var iwopts = {
content: 'Hello',
position: latlng
};

var infowindow = new google.maps.InfoWindow(iwopts);
    infowindow.open(map);

}

// 住所から座標を取得
function setLatlngZip(address,locationX, locationY) {
//ジオコードオブジェクト
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
address: address,
region: 'jp'
},
function(results, status){
if(status==google.maps.GeocoderStatus.OK){
//処理
locationX.value = results[0].geometry.location.lat();
locationY.value = results[0].geometry.location.lng();
}
});
}

// キーワードから座標を取得
function setLatlngKeyword(keyword,locationX, locationY) {
// 位置情報オブジェクト
var service = new google.maps.places.PlacesService(map);
service.textSearch({
location: map.center,
radius: '500',
query: keyword
},
function(results, status){
if(status==google.maps.places.PlacesServiceStatus.OK){
//処理
locationX.value = results[0].geometry.location.lat();
locationY.value = results[0].geometry.location.lng();
}
});
}

2013年9月8日日曜日

jQuery入門

Webシステムの開発で欠かせないのがJavaScript。
さらに発展した使い方をしたいときはjQueryを使うことが多いなーと感じる。
半分フレームワークだし、あまり好きではないけど便利なものは使わないともったいない。
ということでjQueryの入門。
※これも随時更新の予定

jQuery日本語リファレンス

jQuery事始め・コピペに頼らず、基礎知識を理解して実際に動かしてみる

2013年9月3日火曜日

PHPの基本

PHPを本格的にはじめそうなので、入門サイトのリンクをはっておく。
※随時追加予定

PHP入門

別のPHP入門

PHP 5.3.x から PHP 5.4.x への移行


2013年9月2日月曜日

PostgreSQLのチューニング情報

VACUUM FULL(データベースの最適化)をしても性能が向上しない現象が発生した。
原因は、統計精度が小さすぎることで、統計情報が荒くなって性能が低下するという現象が起きていた。

PostgreSQLのバージョン8.1で、postgresql.confのdefault_statistics_target(統計精度)がデフォルトで10になっていた。(8.4以降はデフォルトが100)
10では大きなテーブルでは統計情報が荒くなる。

対策は、統計精度を拡張することだが、default_statistics_targetを単純に増やしてしまうと
VACUUMの処理時間が長くなる。
よって、性能が低下しているSQLで参照しているテーブル、カラムを個別に拡張することが効果的だと思われる。
設定方法は以下の通り。
 ALTER TABLE テーブル名 ALTER COLUMN カラム名 SET STATISTICS 200;

上記設定が適用されるのはVACUUM実行時。
早くなるのは、統計精度を拡張したカラムを条件としたSELECTのみ。
統計精度が関係ないカラムのSELECTやINSERTには何の影響もない

履歴テーブルから各IDの最新レコードを取得する方法(PostgreSQL)

PostgreSQL8.4 以降に限るが、分析関数を使用すると以下のように取得することができる。
   OVER (PARTITION BY ...) : 区間に分割
   OVER (ORDER BY ...) : 区間ごとに並び替え

select * from (
 select *,
        row_number() over(partition by code order by kaiteiymd desc) as rowNo
 from history
) list
where rowNo = 1

Firefox・ThunderBirdの移行方法


======================================
Firefoxのデータ移行手順
======================================
※実行前に移行元・先のFirefoxを停止しておくこと

1.以下のプロファイル情報を移行元からコピーする
 WinXPの場合
  C:\Documents and Settings\ユーザー名\Application Data(隠しフォルダ)\Mozilla\Firefox\Profiles\任意の英数字.default
 
 Win7の場合
  C\Users\ユーザー名\Appdata(隠しフォルダ)\Roaming\Mozilla\Firefox\Profiles\任意の英数字.default

2.移行先の同様のフォルダ(~\Firefox\Profiles)に設置する
3.移行先の「任意の英数字.default」をコピーしておき、持ってきたファイルの名称を同じに変える

======================================
ThunderBirdのデータ移行手順
======================================
※実行前に移行元・先のThunderBirdを停止しておくこと

1.以下のプロファイル情報を移行元からコピーする
 WinXPの場合
  C:\C:\Documents and Settings\ユーザー名\Application Data(隠しフォルダ)\Thunderbird\Profiles\任意の英数字.default
 
 Win7の場合
  C:\Users\ユーザー名\Appdata(隠しフォルダ)\Roaming\Thunderbird\Profiles\任意の英数字.default

2.移行先の同様のフォルダ(~\Thunderbird\Profiles)に設置する
3.移行先の「任意の英数字.default」をコピーしておき、持ってきたファイルの名称を同じに変える

Windows7でクイックランチャ・送る

Windows7でXPみたいにクイックランチャを使用する方法。
右クリック→「送る」 に追加する方法も一緒に記載する。


【クイックランチャ表示】
C:\Users\ユーザー名\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch
上記を新規ツールバーで追加する。
追加したツールバーを右クリックし、「ボタン名の表示」・「タイトルの表示」のチェックを外す。

【「送る」の追加先】
C:\Users\ユーザー名\AppData\Roaming\Microsoft\Windows\SendTo

Excel VBAのあれこれ

久しぶりにExcelでVBAを組んでみると、いろいろ忘れすぎててびっくりしたのでメモっておく。


'' ======================================
'' 既存のシートをコピーして新規ブックで保存
'' ======================================

Dim objNewBook As Workbook

' 新規ブックを作成
Set objNewBook = Workbooks.Add

' 既存のワークシートを新規ブックへコピー
Worksheets("テンプレ").Copy Before:= objNewBook.Worksheets("新規シート名")

' 新規ブックを保存
objNewBook.SaveAs "C:\テンプレから作成.xls"

objNewBook.close
Set objNewBook = Nothing



'' ======================================
'' ファイル選択ダイアログ
'' ======================================
Dim strFileFilter As String     ' 選択ダイアログのファイルフィルター
Dim strPath As String           ' 選択されているファイルのパス

' 選択できる拡張子はCSVと全てのファイル
strFileFilter = "CSVファイル(*.csv),*.csv" & _
                "Excelファイル(*.xls),*.xls" & _
                ",すべてのファイル(*.*),*.*"

' ダイアログの初期ディレクトリにカレントディレクトリをセット
ChDir (CurDir)

' ファイル選択ダイアログを開く
strPath = Application.GetOpenFilename(strFileFilter)

If strPath = "False" Then
    MgsBox "キャンセルされました。"
Else
    MgsBox "選択したファイルのパス:" & strPath   
End If


'' ======================================
'' フォルダ選択ダイアログ
'' ======================================
 Dim objFolderDlg As Office.FileDialog   ' ダイアログオブジェクト

'  ダイアログオブジェクトの取得
Set objFolderDlg = Application.FileDialog(msoFileDialogFolderPicker)

' ダイアログの初期値をセット
objFolderDlg.InitialFileName = "C:\temp"

If objFolderDlg.Show() = True Then
    MgsBox "キャンセルされました。"
Else
    MgsBox "選択したフォルダのパス:" & objFolderDlg.SelectedItems(1) 
End If

'' ======================================
'' 数値チェック関数
'' ======================================
Private Function IsNumber(ByVal p_strValue As String) As Boolean
    Dim bolResult As Boolean
    Dim i As Integer
   
    bolResult = True

    If Len(p_strValue) = 0 Then
        bolResult = False
    Else
        For i = 1 To Len(p_strValue)
            If Not Mid(p_strValue, i, 1) Like "[0-9]" Then
                bolResult = False
                Exit For
            End If
        Next
    End If

    IsNumber = bolResult
End Function

'' ======================================
'' 画面の自動更新、自動計算の停止・再開
'' ======================================
' 画面の更新停止
Application.ScreenUpdating = False

' 自動計算停止
Application.Calculation = xlManual

' 自動計算実行
Calculate

' 自動計算再開
Application.Calculation = xlAutomatic

' 画面の更新再開
Application.ScreenUpdating = True

2012年9月12日水曜日

HTMLのtableタグは時代遅れ

HTML5を勉強しなければと、ずっと思ってましたが・・・。
それ以前に、table タグについては随分昔から使わないというのが主流になっているそうですね。
かなり遅れましたが、本日思い知りました。

とりあえず役立つサイトリンク
dl、dt、ddの使い方サンプル
定義リスト(dl、dt、dd)について
tableタグを使わないでレイアウトする方法

あとはその理由についてのリンク
その1
その2

新規でやるならば、これまでの安易な方法ばかりをとらない!!
これが大事だと痛感しました。

2011年12月16日金曜日

UTF-8のBOMを削除する

AccessでUTF-8のファイルをインポートしようとしたとき、
ビューで先頭に「・ソ」と表示された謎の文字がついていて、正しくインポートできなかった。
どうもこれはBOMらしい。
バイナリエディタで削除はできるけど、自動で削除する方法を2つほど見つけたのでメモ。

コードを書く前に参照設定で「Microsoft ActiveX Data Objects ~」を有効にすること。
BOMは先頭3バイトに着いてくる。
ならば4バイト目から先を出力しなおせばいいんだという手法。
ただし、ファイルが大きすぎるとメモリに入りきらないためエラー落ちする。
280MBまではちゃんと動いた、660MBではだめでした。

==================================================================
Dim readStream As ADODB.Stream
Dim writeStream As ADODB.Stream
Dim readFile As String
Dim writeFile As String

readFile = "C:\BOM付きファイル.txt"
writeFile = "C:\BOM無しファイル.txt"

' 4バイト目から読み込む
Set readStream = CreateObject("ADODB.Stream")
readStream.Open
readStream.Type = adTypeBinary
readStream.LoadFromFile (readFile)
readStream.Position = 3

' 出力ファイルをオープン
Set writeStream = CreateObject("ADODB.Stream")
writeStream.Open
writeStream.Type = adTypeBinary
' 読み込んだデータをそのままファイルに出力する(4バイト目以降を出力)
writeStream.Write (readStream.Read(adReadAll))
writeStream.SaveToFile writeFile, adSaveCreateOverWrite

' ファイルをクローズ
writeStream.Close
Set writeStream = Nothing
readStream.Close
Set readStream = Nothing
==================================================================

これはよくわからないが、たしかに削除できる。
ただし、Unicodeで保存されてしまう。
そのうち理解できたら役に立つかも。
 
cmd /u /c type BOMありUnicodeファイル > BOMなしUnicodeファイル 

2011年12月14日水曜日

バッチ作成時によく使うもの

■ファイル名にくっつける日時の取得
DBバックアップなどをバッチで自動化する場合、必ず実行ログを出力する。
そんなとき、大概ファイル名の後ろに日時をつけろって言われる。
簡単にできるけど毎回忘れて毎回調べてるので、覚えてる間にメモっておく。

echo %DATE:~0,4%%DATE:~5,2%%DATE:~8,2%
echo %TIME:~0,2%%TIME:~3,2%%TIME:~6,2%%TIME:~9,2%
 実行結果:
20111214
23150102

現在日時は 2011/12/14 23:15:01.02 でした。

■テンプレート
バッチを一から作るときのテンプレート。
setlocal、endlocal をよく忘れてしまうのでメモ。

@echo off
rem =================================================
rem 機能の説明
rem =================================================
setlocal

endlocal

■コマンド一覧
これがあればバッチ作成には困らないというサイトのリンク。
コマンドプロンプトを使ってみよう!
DOSコマンド一覧

子画面から親画面に値をセットする(JavaScript)

コードマスタなどの値をポップアップ画面で検索してセットということを
今まで携わったWebシステムではよくやっていた。
JavaScriptだけでサンプルが作れたのでメモ。
window.open で子画面を開き、window.opener で親画面にセットする流れ。
ついでに close して子画面も閉じる。

======================================================================

parent.html(親画面)
<html>
<head>
<title></title>
<script type="text/javascript">
    function windowOpen(controlName) {
        window.open("child.html?controlid=" + controlName,"new");
    }
</script>
</head>
<body>
子画面から選択した値を入れる
<input type="button" value="open" onclick="windowOpen('txtParent');">
<input type="text" id="txtParent">
</body>
</html>

======================================================================

======================================================================

child.html(子画面)
<html>
<head>
<title></title>
<script type="text/JavaScript">
    function setParentValue(){
        var controlId = getQuerystring("controlid");
        window.opener.document.getElementById(controlId).value = document.getElementById("txtValue").value;
        self.close();
    }
   
    function getQuerystring(key) { 
        var keyName = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regex = new RegExp("[\\?&]" + keyName + "=([^&#]*)");
          
        var qs = regex.exec(window.location.href);
        if(qs == null) {
            return ""; 
        } else {
            return qs[1];
        }
    }
</script>
</head>
<body>
<input type="text" id="txtValue">
<input type="button" value="親画面に反映" onclick="setParentValue();">
</body>
</html>
======================================================================

Getで親画面のセット先のコントロールIDを渡すようにしているけど、
PHPとか.Net使うならセッションで管理するのがいいと思う。
上の例だとクエリストリングの取得サンプルも書けた。

JavaScriptでのクエリストリングの取り方

2011年12月13日火曜日

SVNコミット時にいろいろする方法

前にやってたSVNコミット時にメールを飛ばす方法を書いてる人がいたのでメモ。

Windows上のSubversionでコミット時にメールを送信する方法

さらに、コミット後に自動でチェックアウトする方法があるらしい。
SVNはリソース管理のみで、そんなことできるとは思わなかった。

SubversionにコミットしたらWEBサーバの内容も更新する方法
複数Webサイトの動作環境、しかもSVNコミット後即動作確認

コミット時にスクリプトを実行させ、自動でアップデートを掛けるらしい。
Javaなどコンパイルが必要なものはさらに仕掛けを作りこめばいけるんだろうか・・・
少なくともPHPやPerlなどは、コミット即動作確認は難しくなさそう。
ただし、コミットする度に上書きされてしまうため、前のバージョンの動作確認をするために
前のバージョンのソースをコミットするといったことが起きそう。
最新バージョンが最新じゃないって混乱しそうだ。