画像ファイルのレビュー & Ajax送信


SenchaTouchの既存フォーム送信機能がうまくいかないため、別の方法で対応した。


## 専用コンポーネント実装
```javascript
// 写真用コンポーネント
Ext.define('MomBaby.view.common.CapturePicture', {
    extend: 'Ext.Component',
    xtype: 'capturepicture',

    config: {
        captured: false,
        cls: 'picture-capture-area',
        html: [
            '<div class="picture-capture">',
                '<div class="icon"><i class="icon-camera"></i> 写真選択</div>',
                '<img class="image-tns" />',
                '<input type="file" accept="image/*;capture=camera" />', //Step 1
            '</div>',
        ].join('')
    },

    initialize: function() {
        this.callParent(arguments);

        this.file = this.element.down('input[type=file]');
        this.img = this.element.down('img');
        this.inputImg = new Image();
        this.isChange = false;

        this.file.on('change', this.setPicture, this); //Step 2

        //FIX for webkit
        this.createObjectURL = (window.webkitURL && window.webkitURL.createObjectURL) ? function(file) {
            return window.webkitURL.createObjectURL(file);
        } : (window.URL && window.URL.createObjectURL) ? function(file) {
            return window.URL.createObjectURL(file);
        } : undefined;
    },

    setPicture: function(event) {
        this.isChange = true;
        var files = event.target.files;
        if (files.length === 1) {
            var file = files[0];
            if ( file.size == 0 ){
                // アラート
                Ext.Msg.alert('アラート', '選択したファイルがアップロードできません。');
                return;
            }

            // 画像表示
            var src = this.createObjectURL(file);
            this.img.setStyle('display', 'block');
            this.img.set({
                src: src //Step 4
            });
            this.inputImg.src = src;
            this.setCaptured(true);
        }
    },

    setPictureWithUrl: function(url){
        this.img.setStyle('display', 'block');
        this.img.set({
            src: url
        });
        this.inputImg.src = url;
        this.setCaptured(true);
    },

    reset: function() {
        this.img.setStyle('display', 'none');
        this.img.set({
            src: ''
        });
        this.inputImg.src = '';
        this.isChange = false;
        this.setCaptured(false);
    },

    getImageDataUrl: function() { //Step 6
        var imgCanvas = document.createElement("canvas"),
            imgContext = imgCanvas.getContext("2d");

        if (this.getCaptured()) {
            var num = this.inputImg.width / 320;
            this.inputImg.width = 320;
            this.inputImg.height = this.inputImg.height / num;

            // Make sure canvas is as big as the picture
            imgCanvas.width = this.inputImg.width;
            imgCanvas.height = this.inputImg.height;

            // Draw image into canvas element
            imgContext.drawImage(this.inputImg, 0, 0, this.inputImg.width, this.inputImg.height);

            // Return the image as a data URL
            var url = imgCanvas.toDataURL("image/png");
            imgCanvas = null;
            imgContext = null;
            return url;
        }
    }
});
```


## スタイル
```css
/* 写真選択 */
.picture-capture-area {
    background: #fff;
    padding: 20px 0;
    border-bottom: 1px solid #f0f0f0;
}
.picture-capture {
    background-image: -webkit-linear-gradient(top, #d11966 0%, #a2134f 3%, #750d38 100%);
    border-radius: 5px;
    border:1px solid #750d38;
    border-width:1px;
    overflow: hidden;
    margin: 0px auto;
    width: 100px;
    height: 100px;
    position: relative;
}
.picture-capture input {
    border: 0;
    position: absolute;
    cursor: pointer;
    top: -2px;
    right: -2px;
    filter: alpha(opacity=0);
    opacity: 0;
    font-size: 1000px;
}
.picture-capture img {
    position: absolute;
    border-radius: 5px;
    width: 100%;
    height: 100%;
    display:none;
    background: #fff;
}
.picture-capture .icon {
    position: absolute;
    width: 100%;
    height: 100%;
    color:#fff;
    text-align: center;
    font-size: 16px;
}
.picture-capture .icon i { display:block; font-size: 50px; color:#fff; height: 61px; }
.picture-capture .icon-camera {}
.picture-capture .icon-camera:before {
    font-style: normal;
    text-align: center;
    font-family: 'Pictos';
    content: "v";
}
```


## データをAjaxで送信する

下記のコードで画像データを取得し、送信する

```javascript
// formコンポーネントから取得する
var capture = form.down('capturepicture');
var data = capture.getImageDataUrl();

// Ajax送信
Ext.Ajax.request({
    url: 'xxx',
    method: 'POST',
    params: { image: data },
    success: function(response, opts){
    },
    failure: function(response, opts) {
    },
    scope: this
});
```


## 実装済みアプリ
* [MomBaby - 妊娠中のママと子育てのママに役立つアプリ](http://www.itmarlin.com/page-mom-baby.html) : [各種設定]-[親情報画面]など