再帰っていいよね

組み合わせを出さないといけなくなって作るのめんどくさくなったからPGで出力。1〜4までの数字の組み合わせを出そうとしたとして、javascriptで単純に書こうとすると、

var combination = function() {
    for(var i=1 ; i<=4 ; i++) {
        for(var j=1 ; j<=4 ; j++) {
            // めんどくさいのでここまで
        }
    }
}

って言うのがすぐ思い浮かぶけど、これだと書くほうがめんどくさい。しかも数字の種類が4個だからまだいけるけどこれが100個とかなると死ぬことになる。なので再帰。

var length = 4;
var combination = function(start, comb) {
    if(typeof comb === 'undefined') comb = '';
    if(comb.length == length) {
        console.log(comb);
    } else {
        for(var i=start ; i<=length ; i++) {
            tempComb = comb + "" + i;
            combination(i, tempComb);
        }
    }
}

これなら100個になろうが1000個になろうが余裕。再帰素晴らしい。

DialogをカスタマイズするならDialogを継承した独自Viewを作成したほうが捗る

AlertDialogをカスタムする方法は巷に溢れてるけど、カスタマイズするのが非常にめんどくさかったのでDialogを継承して独自Viewとして作成したら捗ったのでメモ

サンプル

ソース

public class WarningDialog extends Dialog {

	private TextView txtWarning;
	private RelativeLayout rltWarning;
	private View.OnClickListener listener;
	private String warningText;
	
	public WarningDialog(Context context) {
		super(context, android.R.style.Theme_Translucent_NoTitleBar);
	}

	@Override
	protected void onCreate(Bundle bundle) {
		super.onCreate(bundle);
		setContentView(R.layout.warning);
		
		txtWarning = (TextView)findViewById(R.id.txtWarning);
		txtWarning.setText(this.warningText);
		
		rltWarning = (RelativeLayout)findViewById(R.id.rltWarning);
		rltWarning.setOnClickListener(this.listener);
	}
	
	public void setWarningText(String warningText) {
		this.warningText = warningText;
	}
	
	public void setCallbackListener(View.OnClickListener listener) {
		this.listener = listener;
	}
}

xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rltWarning"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center|center"
    android:layout_margin="20dp"
    android:clickable="true"
    android:background="@drawable/warning_bg" >

    <ImageView
        android:id="@+id/imgWarning"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:scaleType="centerCrop"
        android:src="@drawable/warning_icon" />

    <TextView
        android:id="@+id/txtWarning"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imgWarning"
        android:layout_margin="30dp"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

使い方

	final WarningDialog dialog = new WarningDialog(getApplicationContext());
	dialog.setWarningText(getString(R.string.waring));
	dialog.setCallbackListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			dialog.dismiss();
		}
	});
	dialog.show();

解説

このサンプルは独自デザインのWarningを出しているサンプル。表示されているDialogをタップすることでDialogが消える。

onCreateのsetContentViewで独自デザインのxmlを渡すことでDialogを作成する。後は入れたい値とかちょっとしか変更しないものとかをsetter作って渡してあげて、onCreate時に設定された値を表示して上がれば問題なく動く。.show()のタイミングでonCreateが走るようなので、setterでそのままViewに値を設定してあげようとするとぬるぽで落ちるからちょっと注意が必要。後、android:layout_gravity=”center|center”を設定しないと中央に来ないのでちゃんと設定してあげましょう。

感想

これならAlertDialogのBackgroundの黒が気に食わないとか、Titleの場所が気に食わないとかボタンをもっと増やしたいとか色々細かいところまで触りたおせる。標準部品で作るならAlertDialogとかAndroidが標準で提供しているものを使ったほうがいいけど、凝ったデザインとか作る場合はこっちのほうが捗るぞ。なにかこれじゃだめだろとかツッコミがあればよろしくどうぞ。

jQueryのajaxを使って動的にjsファイルを読み込む

読み込みファイルとか増えるとファイルが多くなって見づらくなるからなんか方法ないかなーと思って調べるとscriptタグを無理やり差し込んで読み込む奴がよくヒットする。そんな力技じゃなくて普通にjQuery使えばいいんじゃね?っと思って書いてみた。

// 渡されたPathに存在するScriptを全部読み込んでCallbackを実行する
var ajaxLoadScript = function(paths, callback) {

  var loadCount = 0;

  $.each(paths, function(index) {
    $.ajax({
      type: "GET",
      url: this,
      dataType: "script",
      success: function(msg){
        loadCount++;
        if(loadCount === paths.length) {
          callback(true);
        }
      },
      error: function(msg){
        callback(false);
      }
    });
  });
}

// 使用例
$(document).ready(function() {

  // ここで読み込むやつを記載しておく
  var scriptArray = [
    './js/a.js',
    './js/b.js',
    './js/c.js',
    './js/d.js',
    './js/e.js',
  ];

  // 動的読み込み。aStringとかはa.jsとかに定義してある
  ajaxLoadScript(scriptArray, function(result) {
    if(result) {
      console.log(aString);
      console.log(bString);
      console.log(cString);
      console.log(dString);
      console.log(eString);
    }
  });
});

外部のファイルだとクロスサイトスクリプティングで弾かれるからできないけど、同一ドメインだったらScriptタグに書いたりしないでこんな感じで書けばスマートに書けるんじゃないかと。まぁ、同一ドメインにあるファイルたちだったら圧縮するべきだろっていう話はあるんだけど、ファイル分けたほうが複数人で作業する場合は捗ることも多いし、テスト環境で試すときとかなら簡単にこんなのを書けばいいんじゃないかな。

他になにかいい案があれば教えてください。