@blog.justoneplanet.info

日々勉強

IEはradioボタンをappendChildしてもつかえない

IE6~7でラジオボタンをappendChildした場合、そのラジオボタンはクリックできない。ラジオボタンとして致命的なバグである。

■失敗例

以下のようにDOM要素を操作する。

var input = document.createElement('input');
var p     = document.createElement('p');
p.appendChild(input);

ちなみにjQueryを使うと以下のようになる。

var input = document.createElement('input');
var p     = document.createElement('p');
$(p).append(input);

■解決策

IEだけinnerHTMLを使う。

var input = document.createElement('input');
var p     = document.createElement('p');
if(!!(!window.opera && window.attachEvent)){
    p.innerHTML = '<input type="radio" name="id" />';
}
else{
    p.appendChild(input);
}

ちなみにjQueryを使うと以下のようになる。

var input = document.createElement('input');
var p     = document.createElement('p');
if($.browser.msie){
    $(p).append('<input type="radio" name="id" />');
}
else{
    $(p).append(input);
}

Shadowboxの設定

以下のようにHTML側で設定する。

<a href="#" id="shadowbox" rel="shadowbox;width=450;height=110;">open window</a>

script側でも以下のように設定した場合、上手く動作しないことがある。

Shadowbox.open({
    "content" : 'this is a shadow box',
    "player"  : "html",
    "width"   : 300,
    "height"  : 200,
    "options" : {
        "onFinish" : function(){
            alert('test');
        }
    }
});

onFinishが上手く動作しなかった。設定ミスに起因するが、見つけにくいミスでもある。

Javaの拡張forループ

以下のような記法は、java.lang.Iterableインターフェースを実装しているコレクションクラスに対して使用することができる。

import java.util.ArrayList;

public class HelloWorld
{
    public static void main(String[] args)
    {
        ArrayList<String> list = new ArrayList<String>();
        list.add("hoge");
        list.add("fuga");
        list.add("piyo");
        for(String value : list){
            System.out.println(value);
        }
    }
}
/*
hoge
fuga
piyo
*/

また、以下のように配列に対しても使用することができる。

import java.util.ArrayList;

public class HelloWorld
{
    public static void main(String[] args)
    {
        ArrayList<String> list = new ArrayList<String>();
        list.add("hoge");
        list.add("fuga");
        list.add("piyo");
        for(String value : list){
            System.out.println(value);
        }
        
        String[] ary = new String[3];
        ary[0] = "hoge";
        ary[1] = "fuga";
        ary[2] = "piyo";
        for(String value : ary){
            System.out.println(value);
        }
    }
}

Javaのコレクションフレームワーク

■java.util.ArrayList

定義時に要素数を指定する必要がなく、それによる要素追加に対する制約がない。

import java.util.ArrayList;

public class HelloWorld
{
    public static void main(String[] args)
    {
        ArrayList<String> list = new ArrayList<String>();
        list.add("hoge");
        list.add("fuga");
        list.add("piyo");
        list.remove(1);
        System.out.println(list);// [hoge, piyo]
    }
}

■java.util.HashSet

  • 順序は保持しない
  • 同一のオブジェクトは1つしか存在しない
import java.util.HashSet;

public class HelloWorld
{
    public static void main(String[] args)
    {
        HashSet<String> list = new HashSet<String>();
        list.add("dog");
        list.add("cat");
        list.add("rabbit");
        list.add("fox");
        list.add("cat");
        list.add("dog");
        list.remove("rabbit");
        System.out.println(list);// [cat, fox, dog]
    }
}

集合だよね。

■java.util.HashMap

連想配列ですな。

import java.util.HashMap;

public class HelloWorld
{
    public static void main(String[] args)
    {
        HashMap<String, String> hash = new HashMap<String, String>();
        hash.put("ID12345", "yamada");
        hash.put("ID12346", "tanaka");
        hash.put("ID12347", "suzuki");
        hash.put("ID12348", "ishimoto");
        hash.remove("ID12348");
        System.out.println(hash.get("ID12345"));// yamada
        System.out.println(hash);// {ID12346=tanaka, ID12345=yamada, ID12347=suzuki}
    }
}

Javaのジェネリックス

ジェネリックスとは、型を指定することなく、パラメータ化することにより型を定義できるようにすること。

■通常のクラスとクライアントコード

まずは、一般的なコードを見てみる。

クラス

public class Dog
{
    private String _name;
    public Dog(String name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

クライアントコード

上述の場合、以下のようにして使用することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog pochi = new Dog("pochi");
        System.out.println(pochi.cry());
    }
}

しかし、以下のようにして使用することはできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog pochi = new Dog(123);
        System.out.println(pochi.cry());
    }
}

クラス

以下のように、全てのクラスと互換性があるObjectとすることで使用することができるようになる。

public class Dog
{
    private Object _name;
    public Dog(Object name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

■ジェネリックスを用いたコード

インスタンス化する時に使用する型を指定する。

クラス

public class Dog<T>
{
    private T _name;
    public Dog(T name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

クライアントコード

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog<String> pochi = new Dog<String>("pochi");
        System.out.println(pochi.cry());
        Dog<Integer> shiro = new Dog<Integer>(123);
        System.out.println(shiro.cry());
    }
}

これはデータ構造などのクラスにおいて多用される。

■コレクション

List

List自体はインターフェースである。

ArrayList

可変長配列を表す。

ArrayList<String> ary = new ArrayList<String>();
ary.add("hoge");
ary.add("fuga");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

ちなみに以下のようにするとエラーになる。

ArrayList<String> ary = new ArrayList<String>();
ary.add("hoge");
ary.add(2, "fuga");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

Cとか本来の配列に可変長を持たせたものであり、JavaScriptやPHPの配列とは異なる。

LinkedList

連結リストを表す。

LinkedList<String> ary = new LinkedList<String>();
ary.add("hoge");
ary.add("fuga");
ary.add(1, "piyo");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

配列の途中への追加や削除がO(1)のコストでできるデータ構造。

Set

集合。要素の重複を許容しない。

HashSet

任意の順序で要素を保持する。

HashSet<String> hash = new HashSet<String>();
hash.add("hoge");
hash.add("hoge");
hash.add("hoge");
Log.e("hash", hash.toString());
// [hoge]
LinkedHashSet

HashSetとは異なり要素の順序を保持する。

Queue

PriorityQueue

優先順位つきキュー。探索とかでよく使う。

Map

HashMap

連想配列。但し格納順書は保持しない。

HashMap<String, Object> map = new HashMap<String, Object>();
HashMap<String, HashMap<String, String>> map = new HashMap<String, HashMap<String,String>>();
LinkedHashMap

HashMapと違って格納順序を保持する。

Firefox3.6で旧バージョン用のプラグインを動かす

URL欄に以下のように打ち込む。

about:config

右クリックで項目を追加する。「真偽値」を選択だ。項目名は以下の通りだ。

extensions.checkCompatibility.3.6

値は「偽」(=false)だ。

false

3.6にアップデートしたらlive http headersが動かなくなってしまったので対処。

JavaScriptで画像を縦横比を維持しつつ指定サイズに丸める

SVGやcanvasを使えば確かそのままトリミングもできた気がするが、別にそこまでしたくない用の関数。画像のオリジナルサイズを取得し計算する感じだ。面倒なのでjQueryを使う。

var frameWidth  = 700;
var frameHeight = 400;
$('li').css({
    "overflow" : "hidden"
});
$('div.resize img').each(function(){
    $(this).load(function(){
        var nWidth  = this.naturalWidth  || getNaturalSize(this).width;
        var nHeight = this.naturalHeight || getNaturalSize(this).height;
        if(nHeight < nWidth * (frameHeight / frameWidth)){
            this.width  = nWidth * frameHeight / nHeight;
            this.height = frameHeight;
            $(this).css({
                "width"  : nWidth * frameHeight / nHeight + 'px',
                "height" : frameHeight + 'px',
                "position" : "relative",
                "left" : -((nWidth * frameHeight / nHeight) - frameWidth) / 2 + 'px'
            });
        }
        else{
            this.width  = frameWidth;
            this.height = nHeight * frameWidth / nWidth;
            $(this).css({
                "width"  : frameWidth + 'px',
                "height" : nHeight * frameWidth / nWidth + 'px',
                "position" : "relative",
                "top" : -((nHeight * frameWidth / nWidth) - frameHeight) / 2 + 'px'
            });
        }
    });
});

以下の部分でブラウザ分岐をしている。IEとOpera以外はimgオブジェクトにオリジナルのサイズが格納されたプロパティ(naturalWidth、naturalHeight)を持つ。

var nWidth  = this.naturalWidth  || getNaturalSize(this).width;//ff : ie
var nHeight = this.naturalHeight || getNaturalSize(this).height;//ff : ie

getNaturalSize関数は以下のようになる。

var getNaturalSize = function(image){
    var w, h, key = "actual", run, mem;
    if(window.opera){
    }
    if (image[key] && image[key].src === image.src) {
        return image[key];
    }
    run = image.runtimeStyle;
    mem = {
        "w" : run.width,
        "h" : run.height
    }; // keep runtimeStyle
    run.width  = "auto"; // override
    run.height = "auto";
    w = image.width;
    h = image.height;
    run.width  = mem.w; // restore
    run.height = mem.h;
    image[key] = {
        "width"  : w,
        "height" : h,
        "src"    : image.src
    };
    return image[key]; // bond
};

ちなみにOperaには対応していない。

Javaのパッケージ

Javaにはクラスの上にパッケージという概念がある。Pythonのモジュールの概念やPHP5.3以降の名前空間といった概念と似ている。

■コード

/HelloWorld/src/info/justoneplanet/Animal.java

せっかくなので親クラスを定義。

package info.justoneplanet.blog;

public class Animal
{
    protected String name = "";
    public Animal(String name)
    {
        this.name = name;
    }
}

/HelloWorld/src/info/justoneplanet/Dog.java

Animalクラスを継承したDogクラスを定義。同パッケージ内ならばimport無しで、Animalクラスを使用できる。

package info.justoneplanet.blog;

public class Dog extends Animal
{
    public Dog(String name)
    {
        super(name);
    }
    public String cry()
    {
        return super.name + ", bow!";
    }
}

/HelloWorld/src/HelloWorld.java

クライアントコードですな。importを使用することで、他のパッケージからデフォルト・パッケージにインポートしている。

import info.justoneplanet.blog.Dog;

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog pochi = new Dog("pochi");
        System.out.println(pochi.cry());
    }
}
// pochi, bow!

ちなみに以下のようにimportを使用せず、完全修飾クラス名を使用して書くこともできる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        info.justoneplanet.blog.Dog pochi = new info.justoneplanet.blog.Dog("pochi");
        System.out.println(pochi.cry());
    }
}

但し、明らかに見づらいのでおすすめしない。

getterとsetterの定義

eclipseでは「ソース > getterおよびsetterの生成」をクリックしすると、自動的にこれらのメソッドが定義される。

package info.justoneplanet.blog;

public class Animal
{
    protected String name;
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public Animal(String name)
    {
        this.name = name;
    }
}