※ パクレゼルヴではWeb開発エンジニアを大募集中!詳細はこちら

Archive

Author Archive

IEでimg要素でlabelが効かない  

2010/8/30 月曜日 15:21:42

ラジオボタンとかチェックボックスを使うときって、

の中にがあった場合、普通に考えれば画像をクリックしたらラジオボタンやチェックボックスも選択した状態になるはずですが、
IEは切り替わりません。ありえない。
ちょっと調べたら色々出てくるんですが、多分簡単なのはこれかな。

<script type="text/javascript">
window.onload=function(){
	var lab = document.getElementsByTagName('label');
	for(var i=0;i<lab.length;i++){
		var labimg = lab[i].getElementsByTagName('img');
		for(var j=0;j<labimg.length;j++){
			labimg[j].formCtrlId = lab[i].htmlFor;
			labimg[j].onclick = function(){
				document.getElementById(this.formCtrlId).click();
			};
		}
	}
}
</script>

HTML側

<input type="radio" name="lab" id="a"><label for="a"><img src=""></label>
<input type="radio" name="lab" id="b"><label for="b"><img src=""></label>
<input type="radio" name="lab" id="c"><label for="c"><img src=""></label>
<input type="radio" name="lab" id="d"><label for="d"><img src=""></label>

ページ内の[label]を取得して、各画像クリック時にラジオボタンをチェックさせるようにしてます。
しかしこれだとページ内の全ての[label]タグを取得してしまいます。
てことでちょっとだけ改良。
例えば、a~cまでの[label]を取得したい場合は・・・・

<script type="text/javascript">
window.onload=function(){
	var obj = document.getElementById('in');
	var lab = obj.getElementsByTagName('label');
	for(var i=0;i<lab.length;i++){
		var labimg = lab[i].getElementsByTagName('img');
		for(var j=0;j<labimg.length;j++){
			labimg[j].formCtrlId = lab[i].htmlFor;
			labimg[j].onclick = function(){
				document.getElementById(this.formCtrlId).click();
			};
		}
	}
}
</script>

HTML側

<div id = "in">
	<input type="radio" name="lab" id="a"><label for="a"><img src=""></label>
	<input type="radio" name="lab" id="b"><label for="b"><img src=""></label>
	<input type="radio" name="lab" id="c"><label for="c"><img src=""></label>
</div>
<input type="radio" name="lab" id="d"><label for="d"><img src=""></label>

こんな感じでinの中の[label]だけを取得させればいいんじゃないでしょうかっ!

つっしー HTMLとか

urldecodeについて  

2010/8/3 火曜日 15:57:47

お久しぶりです。つっしーです。
またちょっと空いてしまいました・・・・
なんだかんだで入社して4カ月。早いですね。

今回はurldecodeについて。

urldecode  (string $str);

urldecodeは、URL エンコードされた文字列をデコードしたり、
与えられたあらゆる文字列をデコードする関数です。

例えば、ユーザ情報を入力してもらう画面で、当然メールアドレスを入力してもらうことになるのですが、
確認ページへ移動し、確認画面で入力された情報を出す時に、入力された情報を

$data= trim(urldecode('入力された情報');

とこんな感じでデコードしてトリムしてあげてたわけです。

と、ここで話は変わってGmailについてですが、Gmailのアドレスに’+~’と付け加えれる裏技があります。
例えば、abcdefghijk@gmail.comというアカウントを

abcdefghijk+07261@gmail.com

といった感じで入力すると、ちゃんとabcdefghijk@gmail.comにメールが帰ってくるのです。

これを利用することで、メールアカウントひとつでたくさん登録が出来るので、登録処理などのデバックが楽に。

話は戻って、上記のように入力された情報をデコードしてトリムする場合、Gmailの裏技が使えないのです。

原因はurldecodeでした。
urldecodeはあらゆる文字列をデコードするんですが、なんとこいつ、プラス記号 (’+') は、スペース文字にデコードしてしまうのです。

そこで、rawurldecode()関数の登場です。
この関数は、「文字列の中にパーセント記号 (%) に続いて 2 つの 16 進数があるような表現形式を、文字定数に置き換えて返します。」
という感じの関数です。
何を言ってるんだお前は、と思いますが要はこんな感じです

echo rawurldecode('foo%20bar%40baz');
// foo bar@baz

てな感じ。このrawurldecodeはプラス記号 (’+') をデコードしないんで、今回のメールアドレスのデコードに関してはもってこいの関数です。

しかし注意。
文字列に%が入っていて、その後に続いて16進数のような表記をしちゃうと置き換えられちゃうんで、rawurldecodeする前にバリデートしましょう。

つっしー PHP, 未分類

HTMLの事とか  

2010/7/5 月曜日 14:33:29

先月はWebデザインを主にしていました。
プログラムを全く触っていないわけじゃないですよ・・・?
まぁともかく!HTMLとかCSSとか、後PHPですこし気付いた事でも。
自分メモ的な感じで。

array_shift()とarray_pop()

array_shift()
array_pop()
てのがあるんですが。この関数、例えばarray_shift()だったら

$data = array('青','赤','黄','白','緑','紫','金','銀');
$data1 = array_shift($data);
echo $data1;
foreach($data1 as $val){
    echo $val;
}

ってやれば

//$data1
青
//$data
赤黄白緑紫金銀

となる。配列の先頭の要素を抜き出す。
array_pop()は最後の要素を抜き出す。
元の配列が変わってしまうという点に注意さえすれば、便利な関数なんですが、
元の配列が変わってしまった事で起きた出来事が。

配列に都道府県毎の料金を入れて、最大値と最低値、都道府県毎の料金を表示させるって事をやってたんですが、
料金の最大値と最低値が表示されない!なんで!
と思って調べたら、array_shift()とarray_pop()を使っていたためでした。
料金の配列を降順でソートして、array_shift()で先頭(最大値)を、array_pop()で最後(最低値)を
抜いていたのです。

そこで、reset()、end()の登場。

reset()は内部ポインタを最初の要素まで戻し、その値を返す。
end()はその逆。

array_shift()とarray_pop()と似たような動きをする関数です。
array_shift()等とは違って、元の配列が変わらない。
処理速度はというと・・・そんなに変わらないそうです;;(若干reset()のほうが早いようですが)

しかし、max()、min()でやったら?って気がするかも・・・

因みにこのreset()関数、同じソースで、同じ配列を複数回使う場合などに使えます。というか使います。

$array = array('1', '2', '3', '4');

next($array);
echo current($array) ; // "2"

//ポインタをリセットして再度実行
reset($array);
echo current($array) ; // "1"

こんな感じかな?

以降はhtml関係のお話
メイリオについて
>メイリオとは、和文ゴシック体フォントの一つで、Vista以降のマイクロソフト製OSに標準で搭載されてる。
まぁXPとか2003とかで使ってたMS UI Gothicに代わるフォントなんですけど、今回これに苦しめられました。

font-family:"メイリオ",Meiryo,"Hiragino Kaku Gothic Pro","ヒラギノ角ゴ Pro W3","MS P Gothic","MS Pゴシック",Verdana,Arial,sans-serif;

てな感じで指定してるんですけど、OSがVistaと7だとデザインが崩れるんですよね。

なぜかというと、メイリオは全角文字がすべて固定幅のフォントであり、行間も従来フォントに比べて広いから。
なのでゴシックなどを想定して作ってるとデザインが崩れる。

font-familyでメイリオはずして、ゴシックを先頭にするとかで解決。
line-heightで行間を短くするのでもOKかな?
僕は今回line-heightで行間短くして対処しました。ゴシックだとなんか字が汚いんですよね・・・

つっしー HTMLとか, PHP, Tips

fgetcsvがphp5で文字化けする  

2010/5/31 月曜日 20:45:08

仕事でCSVを使うことがあったんですけど、その時に悩んだことを書こうと思います。

fgetcsv()という便利な関数があるんですが、php5で使うと文字化けするんですよ。
なぜ文字化けが起きるのかと言うと、
「fgetcsvはマルチバイト文字の2バイト目に’\'があると、直後のダブルクォーテーションをエスケープするという、少なくともエクセルの仕様にはない独自解釈をする。」
らしい。
訳わかんない事言ってるなーと思いますが、要はShift-JIS形式のCSVをfgetcsv()関数でと文字化けするみたいです。

いろいろと調べた結果、
「PHP 5.0 の fgetcsv() はロケールの設定に依存します。」
とのことなので、

setlocale('LC_ALL', ja_JP.EUC_JP);

でロケールを設定してあげれば直ら・・・・ない。
ぱっと見た感じ直ってるように見えるんですけど、機種依存文字が化けてしまう。

それじゃあCSVをまずUTF-8とかに変換しちゃえば解決するんですけど、実はfgetcsvぽく動いて、しかもバグがない
関数があったので、それを使うことに。

function fgetcsv_reg (&$file, $length = null, $d = ',', $e = '"') {
	$d = preg_quote($d);
	$e = preg_quote($e);
	$_line = "";
	$eof = FALSE;
	while (!$eof && !feof($file)) {
		$_line .= (empty($length) ? fgets($file) : fgets($file, $length));
		$itemcnt = preg_match_all('/'.$e.'/', $_line, $dummy);
		if ($itemcnt % 2 == 0) $eof = true;
	}
	$_csv_line = preg_replace('/(?:\r\n|[\r\n])?$/', $d, trim($_line));
	$_csv_pattern = '/('.$e.'[^'.$e.']*(?:'.$e.$e.'[^'.$e.']*)*'.$e.'|[^'.$d.']*)'.$d.'/';
	preg_match_all($_csv_pattern, $_csv_line, $_csv_matches);
	$_csv_data = $_csv_matches[1];
	for($_csv_i=0;$_csv_i<count ($_csv_data);$_csv_i++){
		$_csv_data[$_csv_i]=preg_replace('/^'.$e.'(.*)'.$e.'$/s','$1',$_csv_data[$_csv_i]);
		$_csv_data[$_csv_i]=str_replace("'","\\'",$_csv_data[$_csv_i]);
		$_csv_data[$_csv_i]=str_replace($e.$e, $e, $_csv_data[$_csv_i]);
	}
	return empty($_line) ? false : $_csv_data;
}

この関数で、CSVを正規表現で切ってます。
使うときはこういう感じで

$new_data = array();
$header = array('name','zip','addr','tel','fax','manage','security','url');

$filename = 'CSVファイルパス';
$file = fopen($filename, "r");

while (($data = fgetcsv_reg($file)) !== false) {
	$_enc_to=mb_internal_encoding();
	$_enc_from=mb_detect_order();
	mb_convert_variables($_enc_to,$_enc_from,$data);
	$num = count($data);
	for ($c=0; $c < $num; $c++) {
		$new_data[$header[$c]] = $data[$c];
	}
	foreach($new_data as $key => $val){
		echo $key." : ".$val."<br />";
	}
}

こういう風に使えば、fgetcsv()関数とほぼ同じ動作をし、さらに文字化けもおきません。

こういうオリジナルの関数を自分でも作れるようになりたいですね。。

つっしー PHP, 未分類

うごくひと2。(初投稿)  

2010/4/30 金曜日 18:09:36

はじめまして!今年から新卒で入社したつっしーです。
のびーにょさんの後輩になります。
早く業務に慣れて活躍できるようになるのが目標ですが、会社のプログラムは、学生時代に僕が触ってきたプログラムと比べて、とても複雑・・・早く慣れたいなぁ。

今、「うごくひと2」という携帯アクセス解析ツールについて調べています。
うごくひと2は、通常版を使う場合、解析対象ページに

<img src="**********?u=********&amp;guid=ON&amp;ut=*&amp;h=********" alt="携帯アクセス解析" height="1" width="1" />

このコードを追加するだけなのですが、今回は上級版を使おうと思います。
まず、通常版コードのURLとパラメータを正規表現を使って抽出し、serialize関数を使ってシリアル化します。

//url抽出
$tag_regex = '/<img \s[^/>]*?src\s*=["\'](([^\"]*)[^>]*)[/]/i';
preg_match($tag_regex,$_POST['bic_analytics'], $matches);
//urlのみ取得
$url_regex = '/http[^\?]*/';
preg_match($url_regex,$matches[2],$matcheurl);

$param_bic = array();
$param_bic[url] = $matcheurl[0];
//URLを分解して配列で返す
$strtest = parse_url($matches[2]);
//パラメータ取得
foreach($strtest as $key => $var){
	if($key == 'query'){
		$keyword = explode('&amp;', $var);
		foreach($keyword as $vval){
			$bic = explode('=',$vval);
			if($bic[0] != 'guid'){
				$param_bic[$bic[0]] = $bic[1];
			}
		}
	}
}
$bic_analytics = serialize($param_bic);

正規表現で通常版コードの中の必要な部分を抽出してシリアル化してます。
URLのパラメータ抽出も正規表現で抽出しようかと思いましたが、parse_url関数を使ったほうがいいよ、という助言をいただいたので使っています、実際そのほうが簡単でした。

$param_bicの中はこうなってます。

Array
(
[url] => ************
[u] => *******
[ut] => *
[h] => ******
)

これをserializeするとこうなります。

a:4:{s:3:"url";s:1:"************";s:1:"u";s:1:"*******";s:*:"ut";
s:1:"*";s:1:"h";s:1:******";}

これをunserializeしたら元に戻ります。
この各要素を、上級版コードのURLに入れていきます

$ret = $_POST['bic_analytics'];
//unserializeして元の配列に戻す。
$arrBic = unserialize($ret);

//配列の要素をURLに入れる。
$UH2url  = $arrBic['url'].'?u='.$arrBic['u'].'&amp;h='.$arrBic['h'].'&amp;ut='.$arrBic['ut'].'&amp;guid=ON&amp;qM=';
$UH2url .= urlencode(isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:'').'|Az|'.(int)($_SERVER['SERVER_PORT']);
$UH2url .= '|'.urlencode($_SERVER['HTTP_HOST']).'|'.urlencode($_SERVER['REQUEST_URI']);
$UH2url .= '|H|&amp;ch=UTF-8&amp;sb='.urlencode('[page title]');
print '<img src="'.$UH2url.'" alt="携帯アクセス解析" width="1" height="1" border="0" />';

こんな感じで上級版コードを作ります。

まだまだ未熟ですが、今後もよろしくお願いします。

つっしー PHP