h5y1m141 / connextion

Other
0 stars 0 forks source link

TableViewに配置した要素をクリックイベントで画面表示する #7

Open h5y1m141 opened 9 years ago

h5y1m141 commented 9 years ago

前置き

4 と #5 の連携ワザっぽい感じですが、TableViewに配置した要素に対して、クリックのイベントを割り当てることが出来ます。

クリックした箇所のインデックス(上から連番でふられてるID番号のようなものだとおもってください)を取得するサンプルコード

mainTable.addEventListener('click',function(e){
    alert(e.index);
});

一番先頭のインデックスは0 になり、実際にクリックするとこのようなアラートが表示されます。

shot-2015-01-02-6 08 02

クリックした箇所の要素が何か確認する

少しわかりづらいかもしれませんが、TableViewの上に、TableViewRowという要素が載っていて、そのTableViewRowの上にLabelを配置したUIになってます。

mainTable.addEventListener('click',function(e){
    alert(e.source);
});

上記サンプルを実行した場合に、クリックする箇所が、空白の所だとLabelではなくTableViewRowがクリックされたと検知されるので、以下のようにobject TiUITableViewRowという表示がされます

shot-2015-01-02-6 07 58

クリックした箇所がLabelの場合にはその文字が取得できます

mainTable.addEventListener('click',function(e){
    alert(e.source.text);
});

上記サンプルを実行した場合に、クリックする箇所がLabelの場所ならばこのように文字が表示されます

shot-2015-01-02-6 14 52

課題

shot-2015-01-02-6 27 48

TableViewRow要素がクリックされた時のキャプチャ

shot-2015-01-02-6 27 53

kozasaryosuke commented 9 years ago

見事につまづいてます。

mainTable.addEventListener('click',function(e) {
    if (e.source.getApiName() === 'Ti.Ui.Label') {
        alert(e.source.text);
    } else {
        // テキスト以外をクリックしたときの処理
    }
});

こんな感じでいけるかと思っていましたが、Javascriptの特性を理解しきれていないせいか、 うまく動作しません。 すみませんが、もう少しヒントをいただけないでしょうか。。

h5y1m141 commented 9 years ago

@kozasaryosuke さん、 見た感じの処理の流れは全く問題ないのですが、ちょっとしたタイプミスされてますね(^_^;)

いくつかヒントになることをお教えしておきますね

Ti.API.infoの利用方法サンプルコード

mainTable.addEventListener('click',function(e) {
    Ti.API.info("クリックされた要素:" + e.source);
    if (e.source.getApiName() === 'Ti.Ui.Label') {
       Ti.API.info(e.source.getApiName());
        Ti.API.info(e.source.text);
    } else {
        // テキスト以外をクリックしたときの処理
    }
});
h5y1m141 commented 9 years ago

GitHubのコメント欄は結構便利な機能があるので、それをお伝えしておけば良かったですね(^_^;)

shot-2015-01-04-7 53 05

詳しいことは解説ページにあるのですが、よく利用するものとして

あたりを覚えておくと便利かなと。この独特の書き方は、Markdownという記法に沿ったものでGitHubが一部独自の拡張をしてますが、Markdownは覚えておくと色々便利だったりします

kozasaryosuke commented 9 years ago
mainTable.addEventListener('click',function(e) {
    if (e.source.getApiName() === 'Ti.UI.Label') {
        alert(e.source.text);
    } else {
        var children = e.source.getChildren();
        for (var i=0;i<children.length;i++){
            var child = children[i];
        }
        alert(child.text);
    }
});

こんな感じでできました。合ってますかね?

h5y1m141 commented 9 years ago

@kozasaryosuke さん、それでOKです~

後は細かいところとして

変数を関数の先頭でまとめた場合のサンプル

mainTable.addEventListener('click',function(e) {
    // ここで利用する変数をまとめて宣言する
    var children, i , len, child;
    if (e.source.getApiName() === 'Ti.UI.Label') {
        alert(e.source.text);
    } else {
        children = e.source.getChildren();
        len = children.length;
        for (i = 0; i < len; i++ ) {
            child= children[i];
        }
        alert(child.text);
    }
});

おもいがけないバグの話

こちらのページのサンプルがとてもわかりやすいので一部抜粋しつつ捕捉します

例えば、Titanium で以下のようなコードを書いたとします

var a = 0;
(function() {
  Ti.API.info(a);  // (1)
  var a = 2;
  return a;
})();

(1)の所では、感覚的には0が出力される印象かと思いますが、実際にはundefinedが出力されます。実際私もこのコードを見てるとそういう印象を持ってしまいます(^_^;)

(function() {

})();

というコードはあまり見かけることがないと思うのですが、Titaniumでそれなりの規模のアプリ開発をすすめるとこういう書き方をするケースがどうしても出てきます。

話を戻して

(function() {
  Ti.API.info(a);  // (1)
  // 省略

})();

という場合に、(1)のaはこの関数内部で利用される別の変数として扱われるため、JavaScriptとしては、上記のコードは下記のコードと等価になってしまいます

var a = 0;
(function() {
  var a;
  console.log(a); // (1)
  a = 2;
  return a;
})();

(1)の aはその直前で変数宣言されてますが初期化されてないのでundefined になってしまいます

まぁこういうのは結構やりがちなミスなんですけどね

kozasaryosuke commented 9 years ago

重複がなければ先頭行ですべての変数を宣言してしまっても良いのでしょうか?

var sample, file, body, mainTable, win, i ,len ,row ,rows,textLabel;

7でいうとこの部分ですね。

たぶんアプリが複雑になるにつれて最初にすべて宣言するのはナンセンスになってくるので、 関数内の先頭行で宣言するのが実用的なのかなと勝手に解釈してますが、そんな感じですかね?

細かい解説ありがとうございます!

h5y1m141 commented 9 years ago

たぶんアプリが複雑になるにつれて最初にすべて宣言するのはナンセンスになってくるので、 関数内の先頭行で宣言するのが実用的なのかなと勝手に解釈してますが、そんな感じですかね?

う~ん、ちょっとニュアンスが違いますね(^_^;)

JavaScriptの場合には、関数単位で利用できる変数が決まってしまうのでこちらを見てもらうとイメージが掴めるかと思います。

7 のコードで言うと

var sample, file, body, mainTable, win, i ,len ,row ,rows,textLabel;  // (1)
      // 省略
mainTable.addEventListener('click',function(e) { 
    var children, i,len, child;                              // (2)
    if (e.source.getApiName() === 'Ti.UI.Label') {
      // 省略
    }
});

という感じで変数宣言をする形になるはずですが、

  1. こちらの変数はグローバル変数になるので、このスクリプトの中ではどこからも参照・変更ができる
  2. こちらの変数はmainTable.addEventListener('click',function(e) {以降の中でしか利用できない変数のため、この外の部分から参照できない。(そのため上記1.で宣言してる変数 iと、この内部で宣言してる変数iは同じ変数名ですが、プログラム的には別の変数として認識されます)

ということになります。

グローバル変数というのは、どこからも参照できたり、編集できるので一見すると便利なのですが、変数名が増えてくると人間が管理しきれなくなってきてしまい、結果バグが生まれやすくなってしまい、アプリの出来栄えにも影響してくるかなと思ってるので、今後一緒に働きたいと思うエンジニアさんのスキルの見極めする上での1つの目安になるかなと思ってます。

kozasaryosuke commented 9 years ago

最高にわかりやすい解説、ありがとうございます!理解しました!