Jquery ITかあさん

ITかあさん

jQuery色々なformパーツの選択を解除する

jQuery色々なformパーツの選択を解除する


本年もよろしくお願いします!
一発目はformパーツで

何やらエラーが発生した時に、選択を解除するjQuery

こちらをお送りします。

Checkbox・radio

チェックボックスなどはremoveAttrで、cheched属性を削除すれはよいですね。

$(’#mainform input’).removeAttr("checked");

select

selectタグは、何かしら選択されているとして、デフォルトの値を選択させた状態にすればよいわけですね。
ただfalseなどやってもダメなわけです。

this.selectedIndex  = '';//デフォルトのselectタグの値を入れる

こうすることで、formで何かしらエラーが発生したときに『選択を解除する』ことが出来るわけですね。

jQueryでリンク先が外部ドメインだったらを別タブで開く


jQueryを使って別タブで外部リンクを開くJavascript。
自分のドメインを指定して、それ以外のURLの記述があれば別タブで外部リンクを開くというものです。

もう一つポイントで、もしもaタグにtarget属性が含まれている外部ドメインなら、タブが二重で開いてしまう問題があるので、
もしtarget属性が含まれていたら先に属性をremoveしてあげる必要があります。

	$(document).ready(function() {
		$('a').removeAttr('target');
		$("a[href^=http://]").not($("a[href^=http://www.kaasan.info]")).click(function() {
		window.open($(this).attr("href"));
		return false;
	});
});

Javascriptで特定のパラメータを取得するjQueryプラグインjquery.url.js

Javascriptで特定のパラメータを取得するjQueryプラグインjquery.url.js

JavascriptでURL中の特定のパラメータgetしたいことがあったのでメモ。
通常Javascriptないし、jQueryでパラメータを取得しようとすると、

var n=document.location.search.substring(1,window.location.search.length);

として、&や?の記号をパースして、連想配列にいれて取得しますが、『このパラメータの値だけよこせやっ!』という時はちょっと面倒。
そんな時に大変お役に立ちましたのが

このプラグイン、パラメータ以外にもディレクトリや、ディレクトリの階層など、自URLの様々な情報を返してくれますが、今回は特定のパラメータを取得しました。

$(function(){
var url = $.url('http://www.kaasan.info?name=hoge');
url.param('name');	//値のほしいパラメータを指定するだけ
});

何かと便利に使えそうですね

Javascriptスクレイピング!jquery.xdomainajax.js

これぞJavascriptスクレイピング!jquery.xdomainajax.js

主催している勉強会でも何度もPHPでのスクレイピングネタを取り上げていいます。

スクレイピングってなんぞや?PHPでのスクレイピング

Javascriptでもスクレイピング出来ないものか

PHPでのスクレイピングでもそうなのですがスクレイピングする際はHTMLのタグやIDなどのセレクタを利用して取得します。
でもこの考えがいかにもJavascriptっぽいので、だったらJavascriptでもいけるのではないかと調べていたら素敵なjQueryプラグインを発見しました。

クロスドメインの制約突破!jquery.xdomainajax.js

jquery.xdomainajax.js

Javascriptの場合ネックになるのがクロスドメイン間の突破です。クロスドメインとは、例えばこのサイトはwww.kaasan.infoというドメインですが、このサイトを閲覧しながら
違うドメインの他サイトにアクセスするということです。
自ドメイン間の通信であればload関数を利用すれば情報を引っ張ることが出来ますが、ドメインの違う外部サイトではload関数は使うことが出来ないので、そこでクロスドメインの制約を突破できるjquery.xdomainajax.jsを使うのです。

jquery.xdomainajax.jsの特徴

このプラグインのおもしろいところ、特徴を解説します。

  • HTMLのセレクタで要素を指定できる
  • 属性値での取得は直接は無理っぽい
  • 自ドメインの情報取得は無理 あくまでクロスドメイン間
  • ローカルでも取得可能
  • メタ情報の取得は無理。あくまでbody内のどこか
  • クロスドメインのbody情報全て一度取得し、指定要素をfindする

自ドメインの取得は出来ません。
おもしろいなと思ったのが、ローカルでもネットに繋がっている環境であれば取得するこが出来ること。

jquery.xdomainajax.jsの使い方

jquery.xdomainajax.jsの詳しい使い方を解説しているサイトが全然なかったので、ITかあさんなりに考えてみました。

基本的な使い方

まずは基本的な使い方から。
jQueryのプラグインですからjQueryと一緒に使います。



基本フォーマット

$(function() {
   $( ).ajax{
     url : ”http://www.example.com/test.html",//取得したいURLを指定
      type : "GET",
        success : function(data){
           // dataは取得したデータ
           // htmlをスクレイピングしたりできます。
     }
   )}
});

コンソールを使って取得情報確認

例えば、YahooのトップページをJavascriptスクレイピングしてみます。
Firebugを使って、取得した情報を確認してみます。

//Javascript変数定義
var content ="";
$(document).ready(function(){
$.ajax({
    url: 'http://www.yahoo.co.jp/',// http://から始まるURLを指定
    type: 'GET',
    success: function(res) {
	
		content = $(res.responseText);//○○.responseTextで取得
		
		console.log(content);
		
}
	
});

});

xdomain.jsでの取得結果
これではイマイチ分かりませんね。テキスト形式に直してみたいと思います。

content = $(res.responseText).text();//○○.responseTextで取得

xdomain.jsでの取得結果
実行結果の通り、指定したURLの情報を全て取得していることが分かります。

指定したidの中の情報を取得

では取得URLを別の物の変更して、
実際にセレクタを指定して、『欲しい部分のここだけ!』スクレイピングしたいなら、こういう書き方になります。ただfind(‘セレクタ’)を書くだけ

//Javascript変数定義
var content ="";

$(document).ready(function(){

$.ajax({
    url: 'http://font-master.info/',// http://から始まるURLを指定
    type: 'GET',
    success: function(res) {
	
		content = $(res.responseText).find('.grid_8').text();//クラス名やID、タグをfindの中に指定
		
		console.log(content);
		
}
	
});

});

属性値の取得

属性値の取得なら、さきほどのfind以下をこのように書くだけ。attrで属性の取得をするだけですね。

content = $(res.responseText).find('h1 img').attr('src');//クラス名やID、タグをfindの中に指定

n番目の要素を取得

もし指定した要素が複数見つかっても、勝手に配列化はされず、変数に対して上書きがかかるだけなので、eachで配列化をし、
配列化した変数からn版目の要素を取得する、というように指定すればよいようです。
例では指定URLの全てのliを取得し、最初のliを参照する方法です。

//Javascript変数定義
var content = new Array();

$(document).ready(function(){

$.ajax({
    url: 'http://font-master.info/',// http://から始まるURLを指定
    type: 'GET',
    success: function(res) {
	
	content = $(res.responseText).find('li').each(function(){//liの数だけeachでループ

	content.push($(this));//取得したliをpushで配列データ追加する
	
});
		
	console.log(content[0]);//これでやっと最初のliの取得が完了
		
}
	
});

});

まとめ

個人的にはやはりPHPでのスクレイピングが好きですが、場合によっては非常にJavascriptスクレイピングは使えるかもしれません。
必ずしも取得したい情報がIDでユニークとは限らないので、○○番目のpタグのテキストが欲しい!と言う場合はユニークの親を見つけて、
一度全てのpを取得して、配列かしてから、その配列の中の○番目の結果を取得する!という周りくどいやり方をせねばいけないようです。

相対パスを絶対パスに変換するJavascript

相対パスを絶対パスに変換するJavascript

非常に簡単、シンプルな相対パスを絶対パスに変換する小技

function absolutePath(path){
var e = document.createElement('span');
e.innerHTML = '<a href="' + path + '" />';
return e.firstChild.href;
}

使う時は

absolutePath('contents/text.html');

とします。

実行結果

http://www.kaasan.info/contents/text.html

と、なるのです。

解説

このJavascriptで生成されるHTMLのイメージはこんなカンジ。

<span><a href="http://www.kaasan.info/contents/text.html">contents/text.html</a></span>

指定文字列をspanタグで囲い

document.createElement('span');

さらにaタグで囲う

e.innerHTML = '<a href="' + path + '" />';

spanで囲われた最初の子要素のhref属性の中身は何ですか?とたずねているわけですね。

return e.firstChild.href;

spanが気に入らなければ何のタグでもいいわけですね。
私も調べて知って、分かればなんてことないんですが 今後もけっこう便利に使えそうです。

Facebookでお馴染みのコメント機能の『あれ』を作ってみた

Facebookでお馴染みのあれをjQueryで作ってみた

前々から気になっていたのですが、FacebookのコメントなどにURLを入力すると、そのURL先の情報が画像付で表示される『あれ』、いいですよね!
Facebookのコメント機能のサンプル
こんな風に、コメント中にURLがあると、そのURLの中身を画像付で表示できます。
こんなURL先の画像を引っ張って来れるようなJavascript(jQuery)で書いてみました。

Facebookのコメント機能のあれ サンプル

何はともあれ、下記URLをチェックしてください。

キャプチャー画像

テキストエリアにURLを記入してOKを押すと、しばらくすると指定したURLの画像の1枚目が出てきます。クリックすると次々とそのURL中に存在する画像が登場します。
FacebookのコメントのURL指定で画像が出て来るあれ

今回使ったもの

今回、外部ドメインにアクセスして、その情報を引っ張るjquery.xdomainajax.jsを使いました。

クロスドメインの制約を簡単に突破できるjquery.xdomainajax.jsが有効でした。

idやタグなどのHTMLのセレクタを指定すると、欲しい箇所をスクレイピングできる優れものです。
Javascriptで手軽にスクレイピングを実装したいなら断然このjquery.xdomainajax.jsでしょう!

出来なかったこと

jquery.xdomainajax.jsというプラグインは、bodyの中身しか引っ張ってくれないため、タイトルタグやディスクリプションを抜くことが出来ませんでした。これは残念です。

というか、ディスクリプションなどメタ情報を抜くならPHPのget_meta_tagsを利用したほうが早いですし、今回のケースなら画像を抜くまでに留めておいたほうが無難かなと。

補足

割とさっき気がついたのですが、画像のsrcがhttp:// から始まっているケースでないと取得できないようです。画像が相対パスとか拾えないみたい・・これは近日中に修正してアップしたいと思います

補足2 相対パスも取得できるように修正

function absolutePath(path){
var e = document.createElement('span');
e.innerHTML = '<a href="' + path + '" />';
return e.firstChild.href;
}

これで相対パスを絶対パスに書き換えることが出来ます。
ただし、このままだと、自ホストの絶対パスになってしまい、これを入力したURLのホスト名にさらに文字列置き換えをする処理を追加

imgArray.push(img_path.replace(location.host,url.split('/')[2]));//自ドメインから入力されたURLのホストに変換

これで、私の試した限り画像のURLが相対パスだろうが、絶対パスだろうが取得できるようになりました。

Facebookのコメント機能のあれ ソース

ソースコードをこちらに置いておきます。サンプルからソースを引っ張ってもよいです。
変更などはご自由にどうぞ。

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
  <script type="text/javascript" src="js/jquery.xdomainajax.js"></script>
  <script type="text/javascript">
//相対パスを絶対パスに変換するJavascript
  function absolutePath(path){
  var e = document.createElement('span');
  e.innerHTML = '<a href="' + path + '" />';
  return e.firstChild.href;
  }
//Javascript変数定義
  var html ="";
  var imgArray = new Array();
  var cnt = 0;
  var imgLength = "";
  var url = "";
  var img_path= "";
$(document).ready(function(){
  
  $("#target").click(function () {
url = $('#text').attr('value');
 
$.ajax({
  url: url,// http://から始まるURLを指定
  type: 'GET',
  success: function(res) {
  
  imgArray=[];
  imgLength = $(res.responseText).find('img').length;//URL中の全ての画像が何個かカウント
  $(res.responseText).find('img').each(function(){//画像の数だけeachでループ
img_path = absolutePath($(this).attr('src'));//画像のパス取得
  
  imgArray.push(img_path.replace(location.host,url.split('/')[2]));//自ドメインから入力されたURLのホストに変換
});
console.log(imgArray);
  console.log(imgLength);
console.log(url.split('/')[2]);
 
  html = "<div><img src='" + imgArray[0] + "'></div>";
  $("#header").html(html);
$("#header").click(function () {
  cnt++;
if(cnt >= imgLength){
  cnt = 0; 
  }
html = "<div><img src='" + imgArray[0+cnt] + "'></div>";
  $("#header").html(html);
});
 
  }
  
  });
} );
});
  </script>
  </head>
<body>
<input type="text" id="text" /><input type="submit" value="OK" id="target" />
<div id="header">
</div>

Javascriptのエラー回避にはtry-catch構文がいいカンジ

Javascriptのエラー回避にはtry-catch構文がいいカンジ

Javascriptのエラーに悩まされるのはjQueryプラグインを利用した時や、最近多いのがHTML5によるWEBアプリを作ったときに 当然古いブラウザでは非対応なわけでして、でも古いブラウザは単純に利用出来ないだけにしたい!エラーが発動するのだけは避けたい!

エラーが出ないようにする という記事も書いたのですが エラーが発動する箇所がわかっているならtry-catch構文が非常にいいカンジです!

try{
//エラー出るかもしれないけど実行したい処理
var nativeJSON = localStorage.setItem('memo',nativeJSON);
}catch(e){
//エラーが出たときの処理
alert('ローカルストレージ対応のブラウザをご利用下さい');
}finally{
//必ず実行される処理
}

if文よりも手軽に使えていいカンジです!

LocalStorageとCookieによるWEBアプリ TODOメモを作った

LocalStorageとCookieによるWEBアプリ TODOメモ

HTML5 LocalStorageといえば、Cookieのように文字列を保存したり、画像も保存出来たり何かと便利で、さらにCookieに比べて制約が少なく、容量も多いと10MBも保存出来て大変便利なのですが、対応ブラウザはいるかIE8~となっていたり、IEだとデフォルトの設定ではLocalStorageはOffになっていたりとユーザー側の設定 に依存します。

もしもLocalStorage保存可能ならLocalStorage,もしLocalStorageが使えない環境ならCookieに保存するマルチWEBメモ帳アプリが作れないかな、と思ってチャレンジしました。うまくいけばLocalStorageの利用の幅を広げられると思ったからです。

が、結論から言って失敗しました。たまには失敗例も紹介するのも悪くないかなと。

LocalStorageによるTODOメモ

$(function(){  
  var object = {};
  //object.modified = "2012/05/23 Wed";
  object.items = new Array();
  var data = {};
  var date = new Date();
  var object = localStorage.getItem('memo') ? JSON.parse(localStorage.getItem('memo')) : { items: []};
  object.modified = date.getFullYear()  + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
  
  var getStrage = function () {
  data.title = $('#title').attr('value');
  object.items.push(data);
  nativeJSON = JSON.stringify(object);
var nativeJSON = localStorage.setItem('memo',nativeJSON); 

location.href=""
}
 
$("#submit").live('click', getStrage);
  
  $("#main_box").append(function(){
var nativeJSON = localStorage.getItem('memo'); 
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 
// オブジェクトからデータ取得
  var html = ""; 
for(var idx=0; idx < object.items.length; idx++) {
  html = html + "<tr><td class='w230'>" + object.items[idx].title + "</td><td><span class='disp'>削除</span></td></tr>";
  }
  //ローカルストレージの件数取得
  $("#num .txt01").text(object.items.length);
$("#main_box").append(html);
});
 
var disp = function disp(){

// 「OK」時の処理開始 + 確認ダイアログの表示
  if(window.confirm('削除してよろしいですか?')){

var nativeJSON = localStorage.getItem('memo'); 
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 

var object = localStorage.getItem('memo') ? JSON.parse(localStorage.getItem('memo')) : { items: []};
//更新日時
  var date = new Date();
  object.modified = date.getFullYear()  + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
//何番目??
  var index = $(".disp").index(this);
//クリックされた配列データをspliceで削除
  object.items.splice(index,1);
var count = object.items.length;
//削除したら、ふたたびnativeJSONの変数に代入
  nativeJSON = JSON.stringify(object);
//対象を削除した状態で再びローカルストレージを保存
  localStorage.setItem('memo', nativeJSON); 
//保存したら再びストレージを呼び出し
  var nativeJSON = localStorage.getItem('memo');
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 
 
// オブジェクトからデータ取得
  var html = ""; 
// オブジェクトからデータ取得
  for(var idx=0; idx < object.items.length; idx++) {
  html = html + "<tr><td>" + object.items[idx].title + "</td><td><span class='disp'>削除</span></td></tr>";
  }
console.log(html);
$("#main_box").html(html);
}
}
  $(".disp").live('click', disp);
  });

CookieによるTODOメモ

Cookieの保存についてはjquery.cookie.jsを利用しています。

$(function(){
  
  var object = {};
  object.items = new Array();
  var data = {};
  
  
  var date = new Date();
  var object = $.cookie("memo") ? JSON.parse($.cookie("memo")) : { items: []};
  
  var getStrage = function () {
  data.title = $('#title').attr('value');
  object.items.push(data);
  nativeJSON = JSON.stringify(object);
$.cookie("memo",nativeJSON,{ expires: 7, path: '/', domain: "kaasan.info"});

location.href="index2.html"
}

$("#submit").live('click', getStrage);
  
  $("#main_box").append(function(){
var nativeJSON = $.cookie("memo"); 
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 
// オブジェクトからデータ取得
  var html = "";
for(var idx=0; idx < object.items.length; idx++) {
  html = html + "<tr><td>" + object.items[idx].title + "</td><td><span class='disp'>削除</span></td></tr>";
  }
$("#main_box").append(html);
});
 
var disp = function disp(){

// 「OK」時の処理開始 + 確認ダイアログの表示
  if(window.confirm('削除してよろしいですか?')){

var nativeJSON = $.cookie("memo"); 
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 
// Cookieによる保存
var object = $.cookie("memo") ? JSON.parse($.cookie("memo")) : { items: []};
//更新日時
  var date = new Date();
  object.modified = date.getFullYear()  + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
//何番目??
  var index = $(".disp").index(this);
//クリックされた配列データをspliceで削除
  object.items.splice(index,1);
var count = object.items.length;
//削除したら、ふたたびnativeJSONの変数に代入
  nativeJSON = JSON.stringify(object);
//対象を削除した状態で再びローカルストレージを保存
  $.cookie("memo",nativeJSON,{ expires: 7, path: '/', domain: "kaasan.info"});
//保存したら再びストレージを呼び出し
  var nativeJSON = $.cookie("memo");
// JSONデータ→JavaScriptオブジェクトに変換
  var object = JSON.parse(nativeJSON); 
 
// オブジェクトからデータ取得
  var html = ""; 
// オブジェクトからデータ取得
  for(var idx=0; idx < object.items.length; idx++) {
  html = html + "<tr><td>" + object.items[idx].title + "</td><td><span class='disp'>削除</span></td></tr>";
  }
console.log(html);
$("#main_box").html(html);
}
}
  $(".disp").live('click', disp);
  
  });

どうでしょうか?
基本的にはどちらもJSONデータをLocalStorage、あるいはCookieに保存しているだけなので、保存と呼び出しがやや異なったり、Cookieは保存先のURLや保存期間を指定しているだけの違いでそれぞれのやり方の違いで悩まされることは少ないと思います。

//Cookieによる保存
$.cookie("memo",nativeJSON,{ expires: 7, path: ‘/’, domain: "kaasan.info"});
//localStorageによる保存
localStorage.setItem(‘memo’,nativeJSON);

LocalStorage対応か、非対応か

以前こんな記事を書いたことがあるのですが これはあまりよくありませんね。
TRY-Catch構文を使うのがよいようです。

localStorageと書いただけでIE7以下がエラーになってしまいます。IE8以上でもインターネットオプションにDOMストレージを保存する、にチェックが入っていないとうまく保存できません。

そこでTRY-Catch構文でエラーが予測される点をこのようにしました。まるでif文のようですね。

try{
//localStorageが使えるとき
var nativeJSON = localStorage.setItem('memo',nativeJSON); 
}catch(e){
//localStorageが使えないとき
var nativeJSON = $.cookie("memo",nativeJSON,{ expires: 7, path: '/', domain: "kaasan.info"});
}

これを利用して書いたのが以下のサンプル。Firefoxや、LocalStorage対応ブラウザでは無事に保存されます。

う~ん、IE7などでは これでいけると思ったのに、うまくいきませんね。
Firefoxで色々LocalStorageを切ってテストしてみたかったのですが、Cookieと一緒になっているようで Localstrageが使えないとCookieも使うことが出来ないようです。
疑問がまだ残るものの、一旦終了。

もし解決できたらこの件についてはまた触れたいと思います。

でも、色々やって思ったのがPCサイトはLocalStorageではやらないで、Cookieでやるのが無難だと思いました。
Cookieは128キロバイト、データ数20までですが、JSONデータにしてしまえば128キロバイト上限まで使うことも可能で、文字に置き換えるとそれなりにたくさんのデータを保存することが可能です。

パソコンリテラシの低い人にインターネットオプションを変更してもらうのは気がひけますし、だったらCookie使ったほうが万人が使えると思います。

まだまだスマホサイトしかLocalStorageは難しいのかな

Javascriptでissetとin_array

Javascriptでissetとin_array

日ごろPHPに慣れていると、不慣れなJavascriptでも似たような関数を探します。
issetとは変数がちゃんと定義されているか、in_arrayは配列中に指定された値がsetされているかを判定し、True、Falseを結果に応じて返してくれるものですがJavascriptにはそんなPHPではあたりまえにやっていたことがプロパティとして用意されていません。

そこで今回はissetとin_arrayをJavascript式でやってみたいと思います。

Javascriptでisset

変数がセットされているかどうかを判定するプロパティは用意されていませんが、仮に変数を定義していなくて、それでも変数を出力しようとすればundifinedが返ってくるので

//typeofの後に変数
if (typeof obj == 'undefined') {
alert('お前はすでにundefinedだっ!');
}else{
alert('お前の変数は定義されている');
}

typeofとは、変数がどういう内容が入っているか、数値型なのか、文字列型なのか、undefinedなのかを調べるプロパティです。

Javascriptでin_array

私もこちらは解説できるほど詳しくありませんが、海外のコードでこちらが出回っておりましたし、これで動作の確認も出来ました。なお、prototypeとprototype.jsとは何のかかわりもありません。

Array.prototype.in_array = function(val) {
	for(var i = 0, l = this.length; i < l; i++) {
		if(this[i] == val) {
			return true;
		}
	}
	return false;
}
var v_array = [ 5, 10, 15, 20, 25];
//数字の12はv_arrayの中に含まれない
if(!v_array.in_array(12)){
alert('お前はさらにundefinedだっ!');
}

jQueryで色々なフォーム入力値をリアルタイム取得する

jQueryで色々なフォーム入力値をリアルタイム取得する

jQueryでフォームの入力地をリアルタイムで取得する方法を紹介します。
フォームのvalue値をリアルタイムで取得したい場合、必ずしも
フォームのパーツからフォーカスが外れた時やクリック時とは限りません。フォームの入力値が変更されたことを取得していきます。

jQueryのchangeイベントがかなり便利

今日まで知らなかったのですが、フォームのvalue値が変更されたことを知るにはchangeイベントがかなり便利なようです。

プルダウンが変更されたら

フォームのプルダウンが変更されたらvalue値がリアルタイムに変更されます。

ソースコード
$("#select1 select").change(function () {
var str = "";
str = $(this).val();
$("#select1 div").text(str);
}).change();
実行例

テキストエリアのテキストが変更されたら

先ほどのchangeイベントを使ってテキストエリアでも同じようにvalue値がリアルタイムに変更されるかテストしてみます。

ソースコード
$("#textarea1 textarea").change(function () {
var str = "";
str = $(this).val();
$("#textarea1 div").text(str);
}).change();
実行例

これは間違いではないのですがイマイチリアルタイムにvalue値を取得しているとは言いがたいです。(テキストエリアからフォーカスが外れたら実行されます)
そもそもchangeとはフォーカスが外れたら処理が実行されるので、フォームの入力値をリアルタイムに判定しているわけではありません。

リアルタイムにテキストエリアのvalue値を取得する

今回はこちらを参考にさせて頂きました。
つまり、先に入力したほうと、後から入力した方それぞれのvalueを比べているわけですね。

ソースコード

$("#textarea2 textarea").each(function(){
$(this).bind(‘keyup’, hoge(this));
});
function hoge(elm){
var v, old = elm.value;
return function(){
if(old != (v=elm.value)){
old = v;
str = $(this).val();
$("#textarea2 div").text(str);
}
}
}

実行例