アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

AJAX内でのリダイレクト処理の罠

こんばんは。笹亀です。

iPhoneの白をず〜〜っと待っているのですが、
今年末ということになってとても残念でなりません。
ここまで待ったので気長に待つことにします。

さて今日はAJAX内でのリダイレクト処理をした際に、
起こったことをご紹介させていただきます。

結論から言うと、
AJAX内でリダイレクトするときはセッションは使うな!」

まずは遷移として下記のように試しました。
AJAXSymfonyをfile_get_contentsで呼び出すスクリプトを指定します。


info.php
 ↓AJAXで呼び出し
get.php(外部のSymfonyで作成されたページの呼び出し)
 ↓file_get_contents関数で呼び出し
http://sasa.local/top/sessionTest
 ↓(Symfony内でリダイレクト
http://sasa.local/top/sessionTest1

※Symfonyのリダイレクト(redirect)を使用してセッションのデータを書き込んで値を引き継ぐことができるのかを試しました。


まずは表示する側のページを作成します。

-- info.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>symfony &ajax session Test</title>
<script language="JavaScript" type="text/javascript" src="/jquery.js"></script>


<!-- EXPAND SKIPED -->
<script type="text/javascript">
<!--
function ajax_test() {
  $.ajax( {
    type : "POST",
    url : "get.php",
    data : {param : "sasagame hiroshi"},
    success : function(txt) {
      $('#view_area').html(txt);
    },
    error : function() {
      alert('error');
    }
  });
}
// -->
</script>
</head>
<body>
symfonyとセッションのテスト中
<input type="button" name="test" onClick="ajax_test();return false;" value="テスト開始">

<div id="view_area">

</div>
</body>
</html>


次にAJAXの呼び出し側のPHPスクリプトを作成します。
-- get.php


<?php
  $html = file_get_contents('http://sasa.local/top/sessionTest?param=sasagame+hiroshi');
  echo $html;
?>

※ここではSymfonyで作成されたページを指定しております


get.phpで呼び出しているSymfony側の処理を実装します。



・・・省略
  public function executeSessionTest(sfWebRequest $request)
  {
    $param = $request->getParameter('param');
    $this->getUser()->setAttribute('session_test', $param);
    $this->redirect('top/sessionTest1');
  }

  public function executeSessionTest1(sfWebRequest $request)
  {
    $param = $request->getParameter('param');
    $session_data = $this->getUser()->getAttribute('session_test', '取得できない');
    echo 'session_test_data:' . $session_data . "";
    echo print_r($_SESSION, true);
    exit;
  }
・・・省略


上記のように実装完了後に実際に動かしてみます。


テスト開始ボタンをクリック・・

うあ、やっぱり取得できません。

普通にSymfony側を実行すれば、セッションデータの取得はおこなえます。


普通にAJAXで処理するときには、ご紹介させていただいたようなリダレクトして処理を遷移させて使うみたいなことはそうそうないことだとおもいます。
今回はイレギュラー的にどうしてもセッションを使ってリダイレクトすることになってしまいました。なぜだといろいろと試行したため時間を使いました。先入観で出来るだろうと思って使うと痛い目にあいますというか痛い目にあいました。

教訓としてはこんな遠まわしな使い方をするなということと先入観で使用するなでした^^;

皆さんもAJAX使うときには気をつけてくださいませ。

javascriptライブラリ「MooTools」を使ってみました。

はじめまして。
8月にアシアルに入社した橋本です。

今回はjavascripライブラリの一つである「MooTools」を使ってみました。
MooToolsは、軽量かつ高機能を謳っているライブラリで、オブジェクト指向に基づいて設計されています。知名度的にはいま一つかもしれませんが、優秀なjavascriptライブラリのようです。

現在、以下のサイトでMooToolsを30日でマスターするチュートリアルが連載されています。
30 Days of Mootools 1.2 Tutorials
今回はそのチュートリアルを参考に、MooToolsを使って遊んでみました。
チュートリアルは残念ながら(?)英語で書かれているのですが、JavaScript初心者でも理解できるように書かれているため、内容自体は大変わかりやすいものとなっています。

では、以下サンプルファイルです。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SmoothScroll Using MooTools 1.2 Example</title> 
<script type="text/javascript" src="js/mootools-1.2-core.js"></script>
<script type="text/javascript" src="js/mootools-1.2-more.js"></script>
<script type="text/javascript" src="js/mooSamples.js"></script>
<style type="text/css">
  #tween_element{
	height: 50px;
	width: 10px;
	background-color: #3399CC;
  }
  #morph_element2{
	width: 0px;
	height: 0px;
	background-color: #ffffff;
  }
</style>
</head> 
<body>
<h3 class="title">Fx.Tweenの使用例</h3>
<div class="contents">
  <div class="contetns_wrap">
	<div id="tween_element"></div>
	<button id="tween_reset">リセット</button>
	<button id="tween_long">伸びる</button>
	<button id="tween_short">縮む</button>
	<button id="tween_fade_out">フェードアウト</button>
	<button id="tween_fade_in">フェードイン</button>
  </div>
</div>
<h3 class="title">Fx.Morphの使用例</h3>
<div class="contents">
  <div class="contetns_wrap">
    <div id="morph_element"></div>
    <button id="morph_set">セット</button>
    <button id="morph_big">大きく</button>
    <button id="morph_small">小さく</button>
    <button id="morph_reset">リセット</button>
  </div>
</div>
<h3 class="title">組み合わせ例</h3>
<div class="contents">

  <div class="contetns_wrap">  
    <div id="morph_element2">
        <div id="text" style="color: #ffffff">
	  	optionで「link」を指定することで、
	    このようなアニメーション効果を生み出すことも出来ます。
	  </div>
    </div>
      <button id="start">スタート</button>
      <button id="reset">リセット</button>
  </div>
</div>
</body> 
</html>


javascriptファイル


//tween効果使用例
var tweenerLong  = function() {
	$('tween_element').tween('width', '200px');
}

var tweenerShort  = function() {
	$('tween_element').tween('width', '50px');
}
 
var tweenerReset  = function() {
	$('tween_element').tween('width', '10px');
}
 
var tweenFadeOut = function() {
	$('tween_element').fade('out');
}
 
var tweenFadeIn = function() {
	$('tween_element').fade('in');
}

//Morph効果使用例
var morphSet = function(){
	this.set({
		'width': 0,
		'height': 0,
		'background-color': '#ffffff'
	}).start({
		'width': 20,
		'height': 20,
		'background-color': '#000000'
	});
}

var morphBig = function(){
	this.start({
		'width': 50,
		'height': 50,
		'background-color': '#d3715c'
	});
}

var morphSmall = function(){
	this.start({
		'width': 30,
		'height': 30,
		'background-color': '#006544'
	});
}

var morphReset = function(){
	this.set({
		'width': 0,
		'height': 0,
		'background-color': '#ffffff'
	});
}

var morphReset = function(){
	this.set({
		'width': 0,
		'height': 0,
		'background-color': '#ffffff'
	});
}

//組み合わせ例
var morphChange = function(){
  this.set({
    'width': 0,
    'height': 0,
    'background-color': '#ffffff'
  }).start({
    'width': 10,
    'height': 10,
    'background-color': '#dddddd'
  }).start({
    'width': 300,
    'height': 10,
    'background-color': '#888888'
  }).start({
    'width': 400,
    'height': 120,
    'background-color': '#333333'
  });
}

var morphReset2 = function(){
  this.set({
    'width': 0,
    'height': 0,
    'background-color': '#ffffff' 
  });  
}

window.addEvent('domready', function() {
	//変数の定義

	//Fx.Morph
	var morphElement = $('morph_element');
	
	//組み合わせ例
	var morphElement2 = $('morph_element2');
	
	//Accordion
	var title = $$('.title');
	var contents = $$('.contents');
  	var accordObj = new Accordion(title,contents, {
    	fixedHeight: 150,
        onComplete: function(){
			$$('.contetns_wrap').fade('in');
		}
  	});

	//Morph
  	var morphObject = new Fx.Morph(morphElement, {
    	link: 'chain',
    	transition: 'back:out',
	});
	
	var morphObject2 = new Fx.Morph(morphElement2, {
    	link: 'chain',
    	transition: 'back:out',
		onComplete: function(){
				$('text').fade('in');
		}
	});
	//Tween使用例
	$('tween_reset').addEvent('click', tweenerReset);
	$('tween_long').addEvent('click', tweenerLong);
	$('tween_short').addEvent('click', tweenerShort);
	$('tween_fade_out').addEvent('click', tweenFadeOut);
	$('tween_fade_in').addEvent('click', tweenFadeIn);
		
	//Morph使用例
	$('morph_set').addEvent('click', morphSet.bind(morphObject));  
	$('morph_big').addEvent('click', morphBig.bind(morphObject));
	$('morph_small').addEvent('click', morphSmall.bind(morphObject));
	$('morph_reset').addEvent('click', morphReset.bind(morphObject));
	
	//組み合わせ例
	$('start').addEvent('click', morphChange.bind(morphObject2));
	$('reset').addEvent('click', morphReset2.bind(morphObject2));
});



HTMLファイルの中身ですが、各タイトルをクリックすると隠された内容が表示されるようになっています。
これはMooToolssの拡張モジュールの一つであるアコーディオンモジュールを使用したものです。
アコーディオンモジュールはMooToolsの公式サイトから「MooTools 1.2 More Builder」をダウンロードすることで使用することができます。
使用方法は簡単で、タイトルとして表示したい要素と、クリックした際に表示したい内容を引数として、
Accordionクラスのオブジェクトを作成するだけです。


window.addEvent('domready', function() {
//Accordion
    //引数として表示したい要素を渡す
	var title = $$('.title');
	var contents = $$('.contents');
	
	//Accordionクラスのオブジェクトを作成
  	var accordObj = new Accordion(title,contents);
});


1つめのサンプルでは、Tween効果の使用例を表示しています。


//tween効果使用例
var tweenerLong  = function() {
	$('tween_element').tween('width', '200px');
}

var tweenerShort  = function() {
	$('tween_element').tween('width', '50px');
}
 
var tweenerReset  = function() {
	$('tween_element').tween('width', '10px');
}
 
var tweenFadeOut = function() {
	$('tween_element').fade('out');
}
 
var tweenFadeIn = function() {
	$('tween_element').fade('in');
}

window.addEvent('domready', function() {
    //ボタンを押すと実行
	$('tween_reset').addEvent('click', tweenerReset);
	$('tween_long').addEvent('click', tweenerLong);
	$('tween_short').addEvent('click', tweenerShort);
	$('tween_fade_out').addEvent('click', tweenFadeOut);
	$('tween_fade_in').addEvent('click', tweenFadeIn);
});

今回は標準要素に対して、あらかじめ用意されたメソッド(tween,fade)を利用していますが、
取得した要素からFx.Tweenクラスのオブジェクトを作成して、Tween効果を独自に設定することも可能です。


2つ目のサンプルでは、Fx.Morphクラスのオブジェクトを作成し、取得した要素を拡大、縮小したり、
色を変えたりしています。


//Fx.Morph使用例
var morphSet = function(){
	this.set({
		'width': 0,
		'height': 0,
		'background-color': '#ffffff'
	}).start({
		'width': 20,
		'height': 20,
		'background-color': '#000000'
	});
}

var morphBig = function(){
	this.start({
		'width': 50,
		'height': 50,
		'background-color': '#d3715c'
	});
}

var morphSmall = function(){
	this.start({
		'width': 30,
		'height': 30,
		'background-color': '#006544'
	});
}

var morphReset = function(){
	this.set({
		'width': 0,
		'height': 0,
		'background-color': '#ffffff'
	});
}

window.addEvent('domready', function() {
	//Fx.Morphクラスのオブジェクトを作成
	var morphElement = $('morph_element');
  	var morphObject = new Fx.Morph(morphElement, {
    	link: 'chain',
    	transition: 'back:out',
	});
	//ボタンを押すと実行
	$('morph_set').addEvent('click', morphSet.bind(morphObject));  
	$('morph_big').addEvent('click', morphBig.bind(morphObject));
	$('morph_small').addEvent('click', morphSmall.bind(morphObject));
	$('morph_reset').addEvent('click', morphReset.bind(morphObject));
});

オブジェクトを作成する際にオプションを指定することで、アニメーションの動きに変化をつけることもできます。
詳しくは先ほど紹介したチュートリアルの11日目の記事の中程あたりを参照してください。
30 Days of Mootools 1.2 Tutorials - Day 11 - Using Fx.Morph, Fx Options and Fx Events

3つ目のサンプルでは。二つ目のサンプルで使用したFx.Morphモジュールの表示効果を組み合わせたアニメーション効果を表示しています。


//組み合わせ例
var morphChange = function(){
  this.set({
    'width': 0,
    'height': 0,
    'background-color': '#ffffff'
  }).start({
    'width': 10,
    'height': 10,
    'background-color': '#dddddd'
  }).start({
    'width': 300,
    'height': 10,
    'background-color': '#888888'
  }).start({
    'width': 400,
    'height': 120,
    'background-color': '#333333'
  });
}

var morphReset2 = function(){
  this.set({
    'width': 0,
    'height': 0,
    'background-color': '#ffffff' 
  });  
}

window.addEvent('domready', function() {
	var morphObject2 = new Fx.Morph(morphElement2, {
    	link: 'chain',
    	transition: 'back:out',
		onComplete: function(){
				$('text').fade('in');
		}
	});
	//ボタンを押すと実行
	$('start').addEvent('click', morphChange.bind(morphObject2));
	$('reset').addEvent('click', morphReset2.bind(morphObject2));
});


2つ目の例でも使用していたのですが、オブジェクトを生成する際のオプションとして、
「link: 'chain'」を指定することで、連続した動作を表現することが出来ます。

今回はいくつかの簡単な例を紹介しましたが、そのほかにも様々なモジュールがあります。
公式ページにもサンプルがいくつか載っているので参考にしてみてください。
MooTools - a compact javascript framework

また、冒頭に紹介したチュートリアルは現在21日目まで進んでおり、今月末までには30日目まで公開されるようです。こちらも参考にしてみてください。
30 Days of Mootools 1.2 Tutorials

今回は短い時間触っただけですが、javascript初心者かつAjax初心者の僕でもこんなに簡単にアニメーション効果を実現出来てしまいました。
素晴らしいですね。
そんなMooTools、皆さんも試してみてはいかがでしょうか。

簡単に別ドメインからAjax対応する方法

こんばんは、笹亀です。

最近は、もっぱらjavascriptsymfony漬けです。
普段よく使用するAjaxですが、Ajaxを実装する際の問題点について悩まされました。
「クロスドメイン」という問題です。
Ajaxのクロスドメイン対策について、難しいことやめんどくさいことが苦手な私は、簡単で手軽に実装する方法がないものかと調べました。
調べている中、私にぴったりな手軽にクロスドメインAjaxを実装する方法がありましたので紹介したいと思います。

Ajaxを使用する際に、しばしば別ドメインスクリプトを呼び出して使用したいことがあると思います。しかし、通常のAjaxで使用されるXMLHttpRequestなどはセキュリティ上の理由で使用しているページ以外のドメインに対してリクエストを送ることができません。使用しているページ以外のドメインではAjaxに限らず、使用しているページのJavascriptの属性などの変更や操作をすることもできません。

これから紹介するDOMを使用することでクロスドメインでも手軽にAjaxを実装できます。
以下にサンプルとして検索結果を表示するクロスドメイン対策したAjaxサンプルを記載します。

Ajax使用側サンプル(ttp://++++.++++.+++/index.html


<?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="text/html; charset=UTF-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>別ドメインのAJAX</title>
<script type="text/javascript">
<!--
  function search_start()
  {
    var result = document.getElementById('result');
    var out = document.createElement('script');
    var keyword = document.getElementById('search').value;
    
    if (keyword == "") {
      alert("検索するキーワードを入力してください。");
    } else {
      keyword = encodeURI(keyword);
      out.src='http://****.****.***/index.php?keyword=' + keyword;
      result.appendChild(out);
    }
  }
//-->
</script>
</head>
<body>
<p>「テスト」や「アシアル」と検索すると結果が表示されます。</p>
<form>
検索:<input type="text" id="search" name="search" value=""> <input type="button" name="submit" value="検索する" onClick="search_start()">
</form>
<div id="result">
ここに検索結果が表示されます。
</div>
</body>
</html>

上記javascript部分では、別ドメイン「****.****.***」へのindex.phpを呼び出すためのscriptタグを生成しています。
次に、呼び出し側では単純な検索を行なうようにしました。
配列内容から条件に一致するリストを返すPHPスクリプトです。

Ajax呼び出し側サンプル(ttp://****.****.***/index.php


<?php
$title = array();
$title[1] = 'アシアル';
$title[2] = 'テスト';
$title[3] = 'アシアル株式会社';
$title[4] = 'テストコード';
$title[5] = 'アシアルホームページ';

$keyword = $_GET["keyword"];
$result = array();
foreach ($title as $value) {
 if (mb_strpos($value,$keyword) !== false) {
    $result[] = $value;
  }
}

$str  = "検索条件:「{$keyword}」<hr>";
$str .= "検索結果:<br>";
foreach ((array)$result as $value) {
  $str .= "{$value}<br>";
}
header("Content-type: application/x-javascript");
print <<<END
var view = document.getElementById('result');
view.innerHTML = "{$str}";
END;
?>

PHP側では、PHPで検索処理を行ない結果をjavascriptとして出力しています。
出力する箇所は、Ajax使用側HTMLのdivタグを指定しています。



<div id="result">
ここに検索結果が表示されます。
</div>


実行イメージ


このように、クロスドメインでも手軽にAjaxを実装することができます。
DOMを利用することで、javascriptの制約もうまく回避して実装できます。
単純な方法だとは思うのですが、クロスドメイン対策のAjaxが手軽にできることことが何よりすばらしいと思いました。

今回は、以下のサイトを参考にさせて頂きました。ありがとうございました。
・JS:Ajax:動的に別ドメインスクリプト呼び出し
 http://www.res-system.com/item/536

最近、symfonyの携帯用のプラグインやヘルパーを作っていたりします。まだ作成中のため、タイミングがあったときにご紹介できたらと思います^^