ラベル jQuery の投稿を表示しています。 すべての投稿を表示
ラベル jQuery の投稿を表示しています。 すべての投稿を表示

2011年2月26日土曜日

jQuery 1.5.1 リリースが嬉しい

jQuery: » jQuery 1.5.1 Released

出ましたね!待ちに待った1.5.1。近々jQuery Mobile alpha 4もくるみたいですね!

1.5.1になってIE9での不具合が解消されたおかげで、とうとう機能するようになりました。

ぐっと来た.cc
http://guttokita.cc

1.5.1にするまではひどいもんですよ。ロードした時点でjQueryさんが起こるもんだから、画面真っ黒。まだまだjQuery Mobileが本気じゃないみたいなので、Webkitバリのレンダリングにはならないけど、これでクマさんも使ってくれるようになることでしょう。ね!

http://razordo.it

も、同じ問題を抱えてたので、こっちは1.4.4を使ってたんですが、試してみたところ、大丈夫そうだったのでそれぞれ1.5.1にバージョンアップです!

嬉しさあまってThinkpad x201sも買っちゃいました。てへ。情報くれた@wakakoo サンクス!

2011年2月24日木曜日

マニフェスト Tips

RADWIMPSじゃなくてHTML5のキャッシュ。

やっとmanifestファイルを使ったキャッシュを組み込めました。

Offline resources in Firefox - MDC Doc Center
Safari Client-Side Storage and Offline Applications Programming Guide: HTML 5 Offline Application Cache

前回のエントリでjQuery Mobileを使ったぐっと来た.ccの話をしましたが、その時はmanifestが簡単に組み込めなくて断念してたんですが、移動中だとやっぱり遅さが気になるんです。

どうすれば簡単にmanifestを使ったキャッシュを使えるのか、ASP.NET MVCのアプリケーションに組み込めるのか、悩ましいところでしたが、なんとかかんとかキャッシュできました。

ローカルストレージを使ったりした、送信データのキューイングはまだ実装してないので、常時オンラインである必要があるのでOffline Applicationではないんですけどね。

gu

↑これ。

アプリの作り方として、ヘッダ部が認証状態に合わせて変化する+コンテンツ部も同じく認証状態によって内容が変化するので、Ajaxでそれぞれの部分を取得するようにメインページの実装を変更しました。こうすることで、メインページ(manifestを指定しているHTML)がキャッシュされてても、認証により変化する部分は都度リクエストがとんでキャッシュされずに済むようになります。ここまでは結構普通なんですけど、ここからjQuery Mobileに合わせた実装が必要になります。

と、いうのも動的にDOMを生成したとしても、それだけではjQuery Mobileのスタイルが適用されないから、です。はてさて困ったものです。いろいろ試して見つけたのが $.mobile.page() という関数。これを呼ぶことで対象のエレメントに対して強制的にjQuery Mobileのレンダリングを適用させることが出来ました。

JQM FAQ

javascript - jQuery Mobile - Dynamically creating form elements - Stack Overflow

素晴らしいですね。

ただ、素直にAjaxで取得したPartial htmlに対してpage()適用したりしちゃうと、ChromeでjQueryのコンフリクトエラーが発生!だめか~と思ったけど$(document).page()とすればあっさり解決。

今回の実装だと2つのPartialを取得するので、それぞれのリクエストの完了を待ち合わせが必要。リクエストのたびにレンダリングすればいいんだけどカッコ悪いじゃないっすか。そんな時にjQuery 1.5で追加された便利な関数があることを思い出した。

$.when(…).then(…);

jQuery.ajax() – jQuery API

新しく実装されたDeferred Object。jqXHR素敵すぎ。whenに同期したいDeferred Objectを並べて($.get()の戻り値とか)おくと、すべてが完了した時点でthenに渡したfunctionが実行される優れもの。

あとUnobtrusive validationをクライアントサイドでの動的フォームに適用するには $.validator.unobtrusive.parse(document); を呼び出しておくことも注意事項ですね。

Brad Wilson: Unobtrusive Client Validation in ASP.NET MVC 3

他にも面白そうなTipsがあったらエントリします~。

2011年2月19日土曜日

ドッグイアとjQuery Mobile

コンピュータ業界は進むのが早いっていう話じゃなくて、本を読んで気になるページに折り目をつける話です。

専門書でも漫画でも小説でも本なら何でも折り目をつけてしまう癖があります。最悪なのは借りた本に折り目をつけてしまうところ。マジすいません。読んだ本で気に入ったフレーズや大事なことだと思った部分を簡単に残しておきたいと思って、ブログに書いたりもするけど、なるべくその瞬間に書き残しておければより記憶に残るっていいなーと思ったわけです。ブクログとかいろいろ便利なサイトが世の中にはありますが、もっともっと特化してしまってもいいと思いませんか!手軽にささっと、となるとモバイルデバイスが利用対象になりましょう。と、いうか自分にとって使いやすいのは何かを考えたらiPhoneだなっていう。

iPhoneといえば最近何かと話題のjQuery Mobile。面白いですよね。まだまだコレだという作り方を見つけることが出来てないのですが。ASP.NET MVCとの相性も悪くない感じです。

そこで本やDVDを見てぐっと来た部分を簡単につぶやいて記録に残せるものを作ってみました。

IMG_0142 IMG_0143 IMG_0144

ぐっと来た.cc

jQuery MobileなのでiPhone/Android等スマートフォン専用です。PCでもそれっぽく動作しますが、まともなのはChromeだけ。Firefoxでも3.6系だと見た目だけはそれっぽいけど、動作(アニメーション)はしょぼしょぼです。HTML5+CSS3だからといってIE9はまるで対象外。パッチを当てても全然ダメだった。

gu1 gu2

左からChrome、Firefox、IE9。背景を黒ししてるのでひどいもんですよ。

使い方は簡単です。最初にサイトにアクセスすると「みんなのぐっと来た」が表示されます。

gu3 gu4

赤い枠の部分をクリックすると、Amazonの商品詳細ページへ。緑の枠の部分をクリックするとつぶやきの全文が表示されます。

右上の「Sign in」をクリックするとTwitterアカウントを使ってログイン。最近お気に入りのOAuthです。http://razordo.it も同じです。

ログインするとHome(検索と最近つぶやいた商品リスト)とPeople(みんなのぐっと来た)を切り替えるタブが出てくるので、初めてつぶやく商品は検索して探しましょう。んで、つぶやく!そしたらTwitterにつぶやき内容とAmazonへのリンクが一緒にポストされます。

That's it!

それだけの機能なんですが、ASP.NET MVC3+Razor+EF CodeFirst+jQuery Mobile+ExpressWeb(宣伝?)です。HTML5とはいえ別に新しいエレメント使ってなくてdata-*属性を指定するくらいなのお手軽実装です。

jQuery Mobileの特徴的な部分はすべてのページは最初に表示されるHTMLに従属する、的なところです。ページ遷移は基本的にAjaxでHTMLを先取りしておいたものを自ページ内にDIVエレメント(data-role="page")として展開して、それを表示するためにアニメーションするというものです。表示されてるのはui-page-activeクラスが指定されてる部分になります。

gu5

なのでページやドキュメントのロード時というのは基本的に最初のページロードの時になりますね。しかも、ページ自体をDIVエレメントで1ページ内に収めるし、キャッシュのためにエレメントは毎回削除されるわけじゃないので、ID属性が同じエレメントが多数発生して$(“#id”)がたくさんいるじゃないか、みたいな状況が出来上がります。

その辺はclassでのセレクタでアクティブなpageからの相対参照で書くようにとコツが必要になるので、慣れが必要でしょう。おや~?と思う動きをするときはだいたいこの辺の設計が関与してます。jQuery MobileっていうのをjQuery UIみたいにとらえると痛い目見るぜハニー。

全く別のフレームワークとして、ちゃんと認識しておくことが必要です。作り方が変わってくるからね。もちろん専用のイベントも用意されてるので、ページのロードじに何か処理をするとかは普通にかけます。コレ以外にもタッチ前提のスマートフォンだからkeydownなんかも発生しなくてびっくりした。そりゃそうなんだけど。

jQuery Mobile Docs – Events

あとはcache manifestがちょっと難しい。manifestを指定してるHTML自体が必ずキャッシュされるという理屈になかなか気がつかなかったです。この辺もうまいこと調整していけば晴れてスマートフォンでも最適なモバイルアプリが出来上がるわけですね。涙ぐましい。

なにはともあれ、それっぽく動くようになったので使ってみてね!あと、Amazonへのリンクは設定で自分アソシエイトIDを登録しておくとそれを使うようになってるので、ID持ってる人は登録しておくとチャリンチャリンと聞こえるかもね!

2010年7月11日日曜日

GridViewも使ってます

MVCだけじゃないよ。WebFormも使ってるよ。最近GridViewで表示結果が1件だけだったら最初から選択状態にしたいな、なんて思ったわけですが、そんなときってSelectedIndexに行番号セットすれば済むよね。

  <asp:GridView runat="server" ID="gridView" 
    DataSourceID="dataSource" AutoGenerateColumns="false" 
SelectedRowStyle-CssClass="selectedRow" ShowHeader="false" DataKeyNames="Name"> <Columns> <asp:CommandField ShowSelectButton="true" /> <asp:BoundField DataField="Name" /> <asp:BoundField DataField="AkumaNoMi" /> </Columns> </asp:GridView> <asp:ObjectDataSource runat="server" ID="dataSource"
TypeName="WebApplication1.People" SelectMethod="Select">
</asp:ObjectDataSource> <asp:Button runat="server" ID="button" Text="ぼたーん" /> <h2 runat="server" id="subject"></h2>

こんなページでしょうか。

gridview1

コードビハインドはこうですよね。

  public class Person
  {
    public string Name { get; set; }
    public string AkumaNoMi { get; set; }
  }

  public class People
  {
    private static List<Person> _people = new List<Person>
               {
                 new Person {Name = "ルフィー", AkumaNoMi = "ゴムゴム"},
                 new Person {Name = "ニューゲート", AkumaNoMi = "グラグラ"},
               };

    public IEnumerable<Person> Select()
    {
      return _people;
    }
  }

  public partial class _Default : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      gridView.SelectedIndexChanged += (s, ev) => 
subject.InnerText = gridView.SelectedIndex + "行目"; } }

ObjectDataSourceを使ってるのはデータバインドの処理とか実際にはコード書かないっていう前提だからです。この状態で、選択ボタンを押すとちゃんと「n行目」って選択した行が表示されましょう。そうでしょう。

gridview2

これって普通なんだけど、GridViewのSelectedIndexにセットするようPage_Loadに書いてみても「n行目」とは表示されませぬ。されませぬ。

    protected void Page_Load(object sender, EventArgs e)
    {
      gridView.SelectedIndexChanged += (s, ev) => 
subject.InnerText = gridView.SelectedIndex + "行目"; if(!IsPostBack) { gridView.SelectedIndex = 1; } }

gridview3


↑ちゃんとニューゲート選択されてるけど「1行目」とは表示されない。なぜでしょうか。SelectedIndexプロパティに値をセットしても、GridViewがSelectedIndexChanging/SelectedIndexChangedイベントをRaiseしてくれないからですね。これをRaiseしてあげればいいんだけどそんなことしてくれないと思うので、そんな時にはGridViewにあるprotectedなOnSelectedIndexChanging/OnSelectedIndexChangedを呼べばいいでしょう。GetMethodで取り出せばprotectedだとしても知ったこっちゃないしね。

 

    private void GridViewSelectedIndex(GridView grid, int index)
    {
      grid.SelectedIndex = index;
      var selectedIndexChanged = typeof(GridView).
GetMethod("OnSelectedIndexChanged",
BindingFlags.NonPublic |
BindingFlags.Instance); if (selectedIndexChanged != null) { selectedIndexChanged.Invoke(grid,
new object[] { new EventArgs() }); } }

これをPage_Loadの”gridView.SelectedIndex = 1;”の部分で呼び出してあげるように書き換えちゃえば、ほら出来た!

gridview4

うぬ。悪くない。でも、これと同じことをクライアントサイドで選択ボタンを押したことにすることでも、実現できますね。例えばこう。

  <script type="text/javascript">
    <% if(!IsPostBack){ %>
    $(function () { 
      __doPostBack("<%=gridView.ClientID.Replace("_","$") %>","Select$1");
    });
    <%} %>
  </script>
  

固定でニューゲートを選択させてます。Select$1の部分。これはちょっと気持ち悪いかも。悪くないとは言いがたい。UpdatePanelに入れておけばそれなりな感じでいいかもしれないけど、普通に1回PostBackされるから悩ましい。

サーバーサイドとクライアントサイドのどちらをチョイスしてもいいかなと思うけど、どうでしょうね。いきなりGridViewの話をしているのはフリで、ここからが本題です。

AjaxControlToolkit(ACT)をがんばって使ってます。WebFormでの簡単Ajax導入に関してACTはとてもいい選択肢ではありますね。お金払わなくていいし、クライアントサイドの知識も要らないし。でも気に入らない部分も多くてウキャ~!ってなる。ACTとはいえ、レンダリングされてしまえばただのHTMLとJavaScriptなわけじゃないですか。気に入らなければ書き換えちゃえばいい。どこを書き換えるかがポイントだと思いますが、今回Accordionを書き換えてみました。ボス、ごめんね!

先程のGridViewのサンプルの続きに書き足していきます。

まずはASPXに以下を追加。これでAccordionが使えます(なんつーかツールボックスからのドラッグアンドドロップのやり方を知ってるともっとラクにかけるんだろうけど、そんなやり方はわすれたので普通に手で書いてます)。

  <asp:ToolkitScriptManager runat="server"></asp:ToolkitScriptManager>
  <asp:Accordion runat="server" ID="accordion"
       HeaderCssClass="acd_header" HeaderSelectedCssClass="acd_selected" 
ContentCssClass="acd_content"> <Panes> <asp:AccordionPane runat="server" ID="pane1"> <Header>pane 1</Header> <Content>パネルのコンテンツ その1 <p>The Ajax Control Toolkit contains a rich set of controls that you can use to build highly responsive and interactive Ajax-enabled Web applications. The Ajax Control Toolkit contains more than 40 controls, including the AutoComplete, CollapsiblePanel, ColorPicker, MaskedEdit, Calendar, Accordion, and Watermark controls. Using the Ajax Control Toolkit, you can build Ajax-enabled ASP.NET Web Forms applications by dragging-and-dropping Toolkit controls from the Visual Studio Toolbox onto a Web Forms page.</p> </Content> </asp:AccordionPane> <asp:AccordionPane runat="server" ID="pane2"> <Header>pane 2</Header> <Content>パネルのコンテンツ その2 <p>The Ajax Control Toolkit contains a rich set of controls that you can use to build highly responsive and interactive Ajax-enabled Web applications. The Ajax Control Toolkit contains more than 40 controls, including the AutoComplete, CollapsiblePanel, ColorPicker, MaskedEdit, Calendar, Accordion, and Watermark controls. Using the Ajax Control Toolkit, you can build Ajax-enabled ASP.NET Web Forms applications by dragging-and-dropping Toolkit controls from the Visual Studio Toolbox onto a Web Forms page.</p> </Content> </asp:AccordionPane> <asp:AccordionPane runat="server" ID="pane3"> <Header>pane 3</Header> <Content>パネルのコンテンツ その3 <p>The Ajax Control Toolkit contains a rich set of controls that you can use to build highly responsive and interactive Ajax-enabled Web applications. The Ajax Control Toolkit contains more than 40 controls, including the AutoComplete, CollapsiblePanel, ColorPicker, MaskedEdit, Calendar, Accordion, and Watermark controls. Using the Ajax Control Toolkit, you can build Ajax-enabled ASP.NET Web Forms applications by dragging-and-dropping Toolkit controls from the Visual Studio Toolbox onto a Web Forms page.</p> </Content> </asp:AccordionPane> <asp:AccordionPane runat="server" ID="pane4"> <Header>pane 4</Header> <Content>パネルのコンテンツ その4 <p>The Ajax Control Toolkit contains a rich set of controls that you can use to build highly responsive and interactive Ajax-enabled Web applications. The Ajax Control Toolkit contains more than 40 controls, including the AutoComplete, CollapsiblePanel, ColorPicker, MaskedEdit, Calendar, Accordion, and Watermark controls. Using the Ajax Control Toolkit, you can build Ajax-enabled ASP.NET Web Forms applications by dragging-and-dropping Toolkit controls from the Visual Studio Toolbox onto a Web Forms page.</p> </Content> </asp:AccordionPane> <asp:AccordionPane runat="server" ID="pane5"> <Header>pane 5</Header> <Content>パネルのコンテンツ その5 <p>The Ajax Control Toolkit contains a rich set of controls that you can use to build highly responsive and interactive Ajax-enabled Web applications. The Ajax Control Toolkit contains more than 40 controls, including the AutoComplete, CollapsiblePanel, ColorPicker, MaskedEdit, Calendar, Accordion, and Watermark controls. Using the Ajax Control Toolkit, you can build Ajax-enabled ASP.NET Web Forms applications by dragging-and-dropping Toolkit controls from the Visual Studio Toolbox onto a Web Forms page.</p> </Content> </asp:AccordionPane> </Panes> </asp:Accordion>

acd1

恐ろしいほど簡単。もちろん、サーバーサイドで動的にPaneを追加するような使い方も多いでしょう。そうすると、Paneが10個や20個にナッチャウことも。そうなるとインターフェースとしてちょっと問題あり。そんなに追加しなきゃAccordionっていいのにとつくづく思う。でも、かなり開発が進んでしまうと、おいそれとインターフェースを変更するのはしんどい作業になります。変更箇所多すぎるし。そんなこんなで、クライアントサイドで何とかしてしまいます。

acd2acd3

完成形は↑これです。何をしてるのかというと、AccordionのHeaderをSelect(DropDown)にして、選択したら該当するPaneの中身を表示するという動きです。ヒマがあったら動かしてみてね。

まずは、AccordionがレンダリングするHTMLを確認。

<div>
  <input type=”hidden” value=”選択してるPaneのIndex”/>
  <div class=”header class name”>header 1</div>
  <div class=”content class name”>content 1</div>
  <div class=”header class name”>header 2</div>
  <div class=”content class name”>content 2</div>
</div>

こんな構造ですね。ヘッダとコンテンツが、連続してるdiv要素をクラス名で判別というのがちょっと気に入らないですが、今回そこはどうでもいいです。最初にこういう構造でレンダリングされるというのがわかりさえすればいいです。

続いて、どういうスクリプトが動いてるのかを確認してみると、ページ内では↓これだけですね。

<script type="text/javascript"> 
//<![CDATA[
(function() {var fn = function() {
$get("ctl00_MainContent_ToolkitScriptManager1_HiddenField").value = '';
Sys.Application.remove_init(fn);};Sys.Application.add_init(fn);})();


Sys.Application.add_init(function() { $create(Sys.Extended.UI.AccordionBehavior,
{"ClientStateFieldID":"ctl00_MainContent_accordion_AccordionExtender_ClientState",
"HeaderCssClass":"acd_header",
"HeaderSelectedCssClass":
"acd_selected","id":"ctl00_MainContent_accordion_AccordionExtender"},
null, null, $get("ctl00_MainContent_accordion")); }); //]]> </script>

Sys.Application.add_initのタイミングでAccordionBehaviorオブジェクト(クラスのような作りかな?)を渡してますね。そもそもSystem.Extendedが何者なのかしらないですけど、ソースが公開されてるので確認してみたところ、各種Behaviorオブジェクトのprototype.initializeでいろいろ初期化処理を書いてました。

ということは、そこを壊せば、Accordionの初期化処理は走らなくなるということなので、add_initで追加したものが実行される前に、AccodionBehavior.prototype.initializeを壊してみました。runat="server"なform要素の閉じタグ直前に以下のコードを書き足します。

  <script type="text/javascript">
    if (Sys.Extended !== undefined && 
Sys.Extended.UI.AccordionBehavior !== undefined) { Sys.Extended.UI.AccordionBehavior.prototype.initialize = function () { }; } </script>

やりすぎな感じもしますが、まぁいいでしょう。

続いてドロップダウンを表示する枠と、Paneの中身を表示する枠を用意します。Accordionタグの上にでもおいておきます。

  <div id="dropdown"></div>
  <div id="viewer"></div>

最後に、Accordionそのものが表示されてしまわないように、Accordionを非表示するためのCSSを定義します。Visibleを指定しちゃうとホントになくなっちゃうからCSSだけで消しちゃうのがいいです。

  <asp:Accordion runat="server" ID="accordion"
       CssClass="accordion_hack" HeaderCssClass="acd_header" HeaderSelectedCssClass="acd_selected" 
       ContentCssClass="acd_content">

太字のところで、クラス名指定して、そのクラスはdisplay:none;だけを適用してます。

あとはJavaScriptでDropDownを生成するのと選択肢を変えたときに表示を切り替えるようなコードをゴリゴリ書けば完成。

<script type="text/javascript">
  $(function () {
    var hack = function () {
      var accordion = $(".accordion_hack:first");
      var viewer = $("#viewer");

      var dropdown = $("<select />");
      var currentId = accordion.find(".acd_selected")
.next()
.attr("id"); var prevId = currentId; accordion.find(".acd_content").each(function (idx, e) { $(dropdown).append( $("<option />").text($(e).prev().text()) .val($(e).attr("id"))); }); $(dropdown).appendTo("#dropdown"); $(dropdown).change(function (e) { prevId = currentId; currentId = $(this).val(); viewer.fadeOut("fast",function () { if (currentId != prevId) { $("#" + prevId).appendTo(accordion); } $("#" + currentId).show().appendTo(viewer); }).fadeIn("fast"); // accordion.find("input[type='hidden']:first")
.val($(this).find("[value=" + currentId + "]").index()); }); $(dropdown).val(currentId).trigger("change"); }; hack(); }); </script>

わざわざhack変数にいれてるのは、特に意味ないです。テスト目的なので気にしないでね!長々とMVCとは関係ないことを書きましたが、要はJavaScriptとHTML、DOM操作、CSSを理解してると、ASP.NETもいろいろカスタムなレンダリングを気軽に実装できるよっていう話なのと、ACTをハックすることでちょっと勝てた気になれたので、調子にのってエントリしてみました。

今回の一式もダウンロード出来るようにしておきます。興味があればどうぞ。

だた、注意点があります。VS2010でASP.NET 4をターゲットにして作ってるのに、ACTは4.0じゃなくて3.5向けのものを使ってます。理由はACT4のAccordionPaneがMasterPageを使ってる時に、id属性を正しく吐き出してくれないからです。3.5だと問題ないので、4.0でなんかおかしくなったんじゃないかな。気をつけてね。

2009年2月23日月曜日

なにを~!タイムリー過ぎるぜ!

You Still Can’t Create a jQuery Plugin? – NETTUTS

まだ、作ったことないっていうかjQuery自体まだ使ったことないってばよ。fnに入れればいいんでしょ?

そのくらいしか、知識がないので、ビデオでお勉強。
シンプルなプラグインだけど、まずはシンプルな物を理解しないとね!

(function($){

})(jQuery);

っていうのは基本みたい。jQuery本体を引数に渡して$でショートカット。

ちょっと、不思議に思ったのがthisの扱い。
Enumerable(っていうのかな)なリストに対して、プラグインを実行すると、プラグイン内でのthisがこのリストを指す。プラグイン内でそのリストをeachで回したときのthisはDOMエレメント(だよね?)。だからeach内では$(this)でjQueryでかぶせて色々便利になるようにしないといけない。

hoverに渡すfunctionがmouseenterとmouseoutの両方なのが素敵な感じがする。
ビデオ中ではmouseoutの時に$(‘tooltip’).hide()って書いてるけど、これじゃ、無限に同じIDのtooltipが出来ちゃうからダメじゃん!と思ってたけど、デモで使ってるコード(ブログエントリの最後のコードも)ではちゃんとremove()になってる。前もそうだったけど、ここで取り上げるビデオな何かしら引っかけがあるよね。

最後に、チェインするためにreturn thisでエレメントのリストをそのまま返すあたりも、jQuery流なのかな。これしないと、"."で区切って続けていろいろ出来ないもんね。

この例だと、fnに単一のfunction(内部では無名関数使ってるけど)を入れてるだけの、シンプルな物だけどもっと大きなプラグインを作る時にはどうするか気になる。けど、そこはすでに公開されてる他のプラグインをいくらでも参照すればいいから、さぁ、作ってみよう!って言うときにはそれほど問題にならないよね、きっと。