アーカイブ

Archive for 2012年2月

Android, iOSのアプリケーションをWebブラウザーで作成できる開発環境

デベロッパーサーミットに参加した時に、Monacaというサービスを紹介されました。

http://monaca.mobi/

これは、Webブラウザー上でAndroid、iOSアプリケーションを開発するための開発環境です。

Webブラウザーで動作する開発環境というと、CodeRunを思い浮かべますが、MonacaはPhoneGapを利用してAndoroidとiOSのアプリをWebブラウザー上で作成するための開発環境です。

通常AndroidであればEclipse+Java、iOSであればXCode+Objective-Cで開発を行いますが、WebブラウザーとHTML、Javascriptがかければ開発ができます。主に個人用途をターゲットにしているようですが、興味がある方は触ってみてはどうでしょう。

マーケットへの公開は別途それぞれの環境向けに開発者登録が必要なので注意です。

カテゴリー:メモ, モバイル タグ: ,

ASP.NETでjQueryをExtenderとして利用するライブラリJUICE

2012年2月29日 1件のコメント

Juice UI: Open source ASP.NET Web Forms components for jQuery UI widgetsより

ASP.NET Web FormでjQuery UIを簡単に組み込むためのライブラリJUICENugetで公開されています。ライセンスはGPL2とMITのデュアルライセンスなようです。

jQuery UIのプラグインはjQueryのwidgetとして公開されているので、たとえばASP.NET WebFormなんかでTextBoxにjQuery UIのDatepickerプラグインを関連付ける場合、初期化イベント時にこんなJavascriptを書きます。

<div>
    <asp:TextBox runat="server" ID="txtCalendar"></asp:TextBox>
    <script type="text/javascript">
    $(function () {
        $("#<%= txtCalendar.ClientID %>").datepicker();
     });
    </script>
</div>

まぁ、問題ないんですけれど、JUICEを導入するとこんな感じになります。

<asp:ScriptManager runat="server"></asp:ScriptManager>
<div>
    <asp:TextBox runat="server" ID="txtCalendar"></asp:TextBox>
    <juice:Datepicker runat="server" TargetControlID="txtCalendar"/>
</div>

TargetControlIDプロパティーに拡張したいコントロールのIDを指定します。

ASP.NET AJAX ControlToolkitのエクステンダーみたいですね。というかDatepickerが継承しているJuiceExtenderExtenderControlを継承しているのでエクステンダーそのものなんですけれどね。

インストールはNuGetで、いろいろ入ります。

PM> Install-Package JuiceUI
Attempting to resolve dependency 'jQuery (= 1.7.1)'.
Attempting to resolve dependency 'jQuery.UI.Combined (= 1.8.17)'.
Attempting to resolve dependency 'json2'.
Attempting to resolve dependency 'AmplifyJS'.
Successfully installed 'jQuery 1.7.1'.
Successfully installed 'jQuery.UI.Combined 1.8.17'.
Successfully installed 'json2 1.0.2'.
Successfully installed 'AmplifyJS 1.0.0'.
Successfully installed 'JuiceUI 0.9'.
Successfully added 'jQuery 1.7.1' to WebApplication2.
Successfully added 'jQuery.UI.Combined 1.8.17' to WebApplication2.
Successfully added 'json2 1.0.2' to WebApplication2.
Successfully added 'AmplifyJS 1.0.0' to WebApplication2.
Successfully added 'JuiceUI 0.9' to WebApplication2.

インストールが終了すると、Web.ConfigにJuiceライブラリのタグライブラリが登録されるので、あとはASPXのエディターで<juice:と打てばインテリセンスが出てきます。

image

現在用意されているエクステンダーは次の14個です。

まぁ、Javascriptをじかに利用したほうが自由に書けるので、使うシーンは限定されそうだけれどこういうものもあるということで。

Silverlight5の信頼されたアプリケーションのブラウザー実行

メモ、どうも日本語資料がなかなか無いんだけれど、八巻さんの資料に載ってた。

Silverlight 5でぶり返すWPF不要論(http://www.slideshare.net/Yamaki/silverlight-5wpf)16ページあたり

というか、MSDNに日本語の記述がない。。。消え行く技術には厳しいのか。

#この記事書くまで、このサイトのカテゴリに「メモ」がなかったことに気づいた。。。

カテゴリー:メモ, Silverlight タグ:

jQueryUIのautocompleteとASP.NETの連携

2012年2月17日 2件のコメント

ASP.NETでオートコンプリートを実装する場合、ASP.NET AJAX ControlToolkitのAutoCompleteExtenderを使うと、Javascriptを基本触らずに済ませられています。また、コンボボックスみたいなのを使う場合には同じくComboBoxコントロールを使えば嬉しいんですが、どうもMSDN Forumのログを見ると日本語環境では問題があるようです。

代替案としては、今の段階ではjQuery UIのautocompleteが最も有効そうです。とりあえずサンプルはjQuery UIのページに良い感じのものがあるのでこいつを参考にしましょう。

autocomplete:http://jqueryui.com/demos/autocomplete/

リモートのデータソース:http://jqueryui.com/demos/autocomplete/#remote

コンボボックス:http://jqueryui.com/demos/autocomplete/#combobox

 

ライブラリーの参照

Visual Studioでプログラムを作成している場合は、NuGetを使うと導入が簡単です。

パッケージコンソールで次の2つのパッケージを導入しましょう。

PM> Install-Package jQuery
PM> Install-Package jquery.UI.Core.All

または、CDNで参照してもいいでしょう。

http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.js
http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.17/jquery-ui.js
http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.17/themes/cupertino/jquery-ui.css

 

その1、テキストボックスにオートコンプリートを組み込む

autocompleteをテキストボックスに適用するには、ページのスタートアップ時に「$(“#コントロールのID”).ウィジェットのクラス」な感じで指定します。例えば、ASP:TEXTにjQueryのautocompleteを単純に適用するにはこんな感じにします。

<fieldset>
    <legend>ASP.NETのTextBoxをAutoCompleteにする。</legend>
    <asp:TextBox ID="TextBox1" runat="server" />
    <script type="text/javascript">
        $(function () {
            var dataSource = ["かるあ", "かるあくん", "かるい", "かるかん", "かるすぎる"];
            $("#<%= TextBox1.ClientID %>").autocomplete({ source: dataSource });
        });
    </script>
</fieldset>

 

実行するとこんな感じになります。

image

image

テキストボックスへ文字を入力すると、dataSourceに含まれる文字を前方一致で引っかけて候補が表示されます。

 

その2、値を入力した段階でサーバーのメソッドを呼び出して候補を確定する

入力候補が少ないなら、その1の方法でページのロード時にクライアントにまるごと落としてしまえばいいでしょう。しかし検索エンジンの入力候補のように候補が膨大で、予めページにダウンロード出来ない場合はテキストが入力された段階でサーバー側に候補の一覧を問い合わせます。

autocompleteのsourceプロパティーには、単なる配列だけではなく、候補検索時に実行するデリゲートを設定することができます。通常は別途Webサービスを作ってそいつを呼び出すように指定するんですが、ASP.NETには、ページクラスにJavascriptからアクセス可能なメソッドを定義できるので今回はそっちでやってみましょう。

ページにクライアントのJavascriptからアクセス可能なサーバーメソッドを定義する場合、Shared(C#ではstatic)なメソッドを用意して、WebMethodAttributeでマークします。

今回は、クライアント側からテキストボックスに入力されたテキスト(inputValue)を受け取り、候補の一覧をList(Of KeyValuePair(Of String, String))の形式でJavascriptに返してあげるメソッドGetAutocompleteDataを次のように定義します。

    <WebMethod()>
    Public Shared Function GetAutocompleteData(inputValue As String) _
        As List(Of KeyValuePair(Of String, String))

        Dim dataSource = GetDataSource()
        Dim result = dataSource.
                         Where(Function(pair) pair.Value.StartsWith(inputValue)).
                         ToList()
        Return result
    End Function

ASPX側では、sourceプロパティーに候補を要求された際に上のメソッドを呼び出し、JSONで値を受け取りたいのでこんなスクリプトを記述します。

<fieldset>
    <legend>ASP.NETのTextBoxをAutoCompleteにする。</legend>
    <asp:TextBox ID="TextBox2" runat="server" />
    <script type="text/javascript">
        $(function () {
            $("#<%= TextBox2.ClientID %>").autocomplete({
                source: function (request, response) {
                    $.ajax({
                        type: "POST",
                        dataType: "json",
                        contentType: "application/json; charset=utf-8",
                        url: "WebForm1.aspx/GetAutocompleteData",
                        data: "{inputValue: '" + request.term + "'}",
                        success: function (data) {
                            response($.map(data.d, function (item) {
                                return { value: item.Value }
                            }))
                        },
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            alert(textStatus);
                        }
                    });
                }
            });
        });
    </script>
</fieldset>

ASP.NETではSharedなメソッドをWebMethod属性でマークすると、ASPXの場合は [ページのURL]/[Webメソッド名] のURLをリクエストすると、直にメソッドを(規定ではPOSTで)呼び出すことができます。なので、$.ajaxでリクエストするURLはこうなります。

url: "WebForm1.aspx/GetAutocompleteData",

テキストボックスに入力されたテキストは、request.termプロパティーに格納されるので、ajaxオブジェクトのdataプロパティーにサーバー側の仮引数の名前(inputValue)の値として設定します。

data: "{inputValue: ‘" + request.term + "’}",

autocompleteはsouceとしてvalueプロパティーを持つクラスの配列を欲しがるので、受け取ったJSONをautocompleteが欲しがる形にマップします。

success: function (data) {

            response($.map(data.d, function (item) {

                return { value: item.Value }

            }))

        },

 

その3、コンボボックスを利用する

jQuery UIのサンプルページでは、autocompleteプラグインを拡張した、comboboxプラグインが公開されています。とりあえず、サンプルページからまるまるコピーしたこんなスクリプトを作り、外部Javascript(/scripts/combobox.js)として保存しておきます。

(function ($) {
    $.widget("ui.combobox", {
        _create: function () {
            var self = this,
                    select = this.element.hide(),
                    selected = select.children(":selected"),
                    value = selected.val() ? selected.text() : "";
            var input = this.input = $("<input>")
                    .insertAfter(select)
                    .val(value)
                    .autocomplete({
                        delay: 0,
                        minLength: 0,
                        source: function (request, response) {
                            var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
                            response(select.children("option").map(function () {
                                var text = $(this).text();
                                if (this.value && (!request.term || matcher.test(text)))
                                    return {
                                        label: text.replace(
                                            new RegExp(
                                                "(?![^&;]+;)(?!<[^<>]*)(" +
                                                $.ui.autocomplete.escapeRegex(request.term) +
                                                ")(?![^<>]*>)(?![^&;]+;)", "gi"
                                            ), "<strong>$1</strong>"),
                                        value: text,
                                        option: this
                                    };
                            }));
                        },
                        select: function (event, ui) {
                            ui.item.option.selected = true;
                            self._trigger("selected", event, {
                                item: ui.item.option
                            });
                        },
                        change: function (event, ui) {
                            if (!ui.item) {
                                var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
                                    valid = false;
                                select.children("option").each(function () {
                                    if ($(this).text().match(matcher)) {
                                        this.selected = valid = true;
                                        return false;
                                    }
                                });
                                if (!valid) {
                                    // remove invalid value, as it didn't match anything
                                    $(this).val("");
                                    select.val("");
                                    input.data("autocomplete").term = "";
                                    return false;
                                }
                            }
                        }
                    })
                    .addClass("ui-widget ui-widget-content ui-corner-left");

            input.data("autocomplete")._renderItem = function (ul, item) {
                return $("<li></li>")
                        .data("item.autocomplete", item)
                        .append("<a>" + item.label + "</a>")
                        .appendTo(ul);
            };

            this.button = $("<button type='button'>&nbsp;</button>")
                    .attr("tabIndex", -1)
                    .attr("title", "Show All Items")
                    .insertAfter(input)
                    .button({
                        icons: {
                            primary: "ui-icon-triangle-1-s"
                        },
                        text: false
                    })
                    .removeClass("ui-corner-all")
                    .addClass("ui-corner-right ui-button-icon")
                    .click(function () {
                        // close if already visible
                        if (input.autocomplete("widget").is(":visible")) {
                            input.autocomplete("close");
                            return;
                        }

                        // work around a bug (likely same cause as #5265)
                        $(this).blur();

                        // pass empty string as value to search for, displaying all results
                        input.autocomplete("search", "");
                        input.focus();
                    });
        },

        destroy: function () {
            this.input.remove();
            this.button.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);

使う側は、このスクリプトをリンクして、ASP:DROPDOWNLISTをui.comboboxプラグインに紐付けるだけです。

<fieldset>
    <legend>DropDownListにデータバインドしてComboBoxにする。</legend>
    <asp:DropDownList id="DropDownList1" runat="server" DataValueField="Key" DataTextField="Value" />
    <script type="text/javascript">
        $(function () {
            $("#<%= DropDownList1.ClientID %>").combobox(); 
        });
    </script>
</fieldset>

サンプルページ同様、微妙にスタイルの調整をします。

    <style>
	.ui-button { margin-left: -1px; }
	.ui-button-icon-only .ui-button-text { padding: 0.35em; } 
	.ui-autocomplete-input { margin: 0; padding: 0.48em 0 0.47em 0.45em; }        
    </style>

あとは、通常のASP.NETで扱うDROPDOWNLISTとして、データをバインドすることでドロップダウンリストが表示されます。

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            DropDownList1.DataSource = GetDataSource()
            DropDownList1.DataBind()
        End If
    End Sub

image

image

Oracle SQL Developer 3.1.07.42でオブジェクトの一覧が表示されないのが治った。

Windowsのドメインサーバーを変更したタイミングで、Oracle SQL Developer(3.0.04)でこんなエラーが表示されて、テーブルの一覧やViewの一覧などが表示されなくなってしまいました。Javaのランタイム有り・無しとか、32Bit版でインストールしてみたりとかやっても、全く変わらずだったので、すっかり諦めていました。

o.d.db.DBUtil(oracle.dbtools.db.DBUtil) 警告、未処理例外:クローズされた例外です。

image

 

同僚のN君から、SQL Developerの最新版が出たよーと教えてもらったので、早速ここからダウンロードしてインストールしてみたら、、、

image

おぉ、ちゃんと表示されている!!

カテゴリー:Oracle タグ: