ラベル javascript の投稿を表示しています。 すべての投稿を表示
ラベル javascript の投稿を表示しています。 すべての投稿を表示

2012年7月27日金曜日

show_errorsの表示をちょっと変えてHTML5風に

題名はかなり大げさなこと書いてますが、jQueryのプラグインを久しぶりに作ってみようと思っていま勉強中のFuelPHPと合わせて適当にいじってみました。

※下に書いてあることは別にプラグインを作らなくてもCSSだけでどうにでもなります・・・ただプラグインを作ってみたかっただけです。


HTML5を使って input に required 属性を付けると

こんなかんじで格好いいです。
でもこれは HTML5 を使ってるんで validation したあとのエラーメッセージとか至って普通に表示されます。(Email アドレスの記述が間違っている場合のエラー)


これを HTML5 風に変えてみよう・・・
(いろいろめんどくさくなってきたんで途中でやめましたが・・・)

簡単にやったこと

  • Formクラスを使って input を生成
  • Validationクラスをちょっとだけ修正
  • ConfigのValidationにopen_errorを追加
  • jQueryプラグイン作って埋め込む

まず、input の生成。これは普通。(required属性はつけません)
<?php echo Form::input('name', '名前'); ?>

次に、fuel/core/classes/validation.php と fuel/core/classes/validation.error.php を修正します。

fuel/core/classes/validation.php 行560
// $output .= $options['open_error'].$e->get_message().$options['close_error'];
$output .= $e->_replace_tags($options['open_error']).$e->get_message().$options['close_error'];

open_error のタグをエラーメッセージと同じように置換するようにメソッドを呼び出します。が、_replace_tagsは protected なんで public に変更しました。

fuel/core/classes/validation/error.php 行113
// protected function _replace_tags($msg)
public function _replace_tags($msg)

これでOK。
つぎに、fuel/app/config/config.php の validation に open_error を以下のように追加。
'validation' = array(
    'open_error' => '<li class="error_:field">',
);

上の :field の部分は validation や input で指定している id になります。

これであとはjQueryのプラグインを埋め込んで実装するだけです。
jquery.validation.js を作って中身は以下
(function($){
    function Validation() {
        this._defaults = {
            form_identifier: 'form_',
            error_identifier: 'error_',
        };
        this._target = null;
        
        this.errors = {};
    }
    
    $.extend(Validation.prototype, {
        _attach: function(element) {
            this._target = element;
            this._target.css('display', 'none');
            
            this._errors = this._get_errors();
            for (i = 0; i < this._errors.length; i++) {
                this._create_message(this._errors[i]);
            }
        },
        _get_errors: function() {
            errors = [];
            
            $("li", this._target).each(function(idx, val) {
                error = {};
                error['id'] = $(val).attr('id')
                                .replace($.validation._get('error_identifier'), '');
                error['text'] = $(val).text();
                
                errors.push(error);
            });
            
            return errors;
        },
        _create_message: function(error) {
            e = $('<div>')
                    .addClass('validation_message')
                    .text(error.text)
                    .css('display', 'none');
            
            t = $('#'+this._get('form_identifier')+error.id);
            t.after(e);
            
            e.css({
                'display': 'inline',
                'position': 'absolute',
                'top': t.position().top + (t.outerHeight() - e.outerHeight()),
                'left': t.position().left + t.outerWidth() + 10,
            });
        },
        _get: function(key) {
            return this._defaults[key];
        },
    });
    
    $.fn.validation = function(options) {
        $.extend($.validation._defaults, options);
        $.validation._attach(this);
        return this;
    }
    
    $.validation= new Validation();
    window.VALIDATION = $;
    
})(jQuery);

コメントも何もないですがshow_errors()で表示している内容をとってきてそれぞれのinputの横に出してるだけです。(汚いソースですみません)

使うときはこんなかんじ。
<div class="error">
    <?php echo $validation->show_errors(); ?>
</div>

<?php echo Asset::js('jquery-1.7.2.min.js') ?>
<?php echo Asset::js('jquery.validation.js') ?>
<script type="text/javascript">
    $(document).ready(function() {
        $('div.error').validation();
    });
<script>


こんなかんじで表示されます。


最初にも言った通り、べつにプラグインの必要はないです。
それぞれの項目の場所で
<?php echo $valication->error('name'); ?>

とかしてこれにスタイルをつければ同じことできます・・・



2012年6月26日火曜日

Node.js+expressをとりあえず試してみた

朝からインストールをしたNode.jsですがいろいろ見ていてもしょうがないので
とりあえず試しに動かしてみました。

Node.js恒例?のチャットアプリ。

Socket.IOを使うのかなって思ってましたがexpressでできそうなのでまずそれをインストールします。
$ npm install express

次にexpressには最低限必要となるファイル等があるみたいです。
それらを生成する必要がありますが自動的に生成してくれるコマンドがあります。
$ node node_modules/express/bin/express chatsample

こうすることでchatsampleというディレクトリが生成され、実行環境が整います。
さらにもうひとつ。expressに依存するモジュールもついでにインストールします。
$ cd chatsample
$ npm install

これでOK。

とりあえず動かしましょう。http://127.0.0.1:3000/
$ node app.js

こんな画面がでればOK。
中身を見てみるとjadeというNode用?のテンプレートエンジンを使って表示されているのがわかります。
とりあえずややこしいのでここでは使いませんが。。。

これからチャットアプリを作成していくわけですが、初心者なんでほとんどサンプルのままです。。。

app.js
var express = require('express')
  , routes = require('./routes')
  , http = require('http');

var app = express();

app.configure(function(){
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
    app.use(express.errorHandler());
});

// メッセージを管理するオブジェクト
var messageStore = {
    _messages: [],
    _listeners: [],

    // メッセージを追加
    addMessage: function(entry) {
        this._messages.push(entry);
        if (this._messages.length > 20) {
            this._messages = this._messages.slice(1);
        }

        for (var key in this._listeners) {
            this._listeners[key]();
            delete this._listeners[key];
        }
    },

    // メッセージを受け取ったある通知するコールバックを登録
    listenOnce: function(listener) {
        this._listeners.push(listener);
    },

    // メッセージを取得
    getMessages: function() {
        return this._messages;
    }
};

app.get("/", routes.index);

// メッセージの読み込みを受け付ける
app.get("/message", function(req, res) {
    res.header("content-type", "text/javascript");

    if (req.url == "/message") {
        // すぐにメッセージを返す
        res.end(JSON.stringify(messageStore.getMessages()));
    } else {
        // 新しいメッセージがくるまで待つ
        messageStore.listenOnce(function() {
            res.end(JSON.stringify(messageStore.getMessages()));
        });
    }
});

// メッセージの書き込みを受け付ける
app.post("/message", function(req, res) {
    var entry = {
        name: req.body.name,
        message: req.body.message,
    };

    messageStore.addMessage(entry);

    res.status = 202;
    res.send("message received");
});

http.createServer(app).listen(app.get('port'), function(){
    console.log("Express server listening on port " + app.get('port'));
});

次に画面です。public/chat.html
<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="/stylesheets/style.css">
    <title>Chat with Node.js</title>
</head>

<body>
<h1>Chat with Node.js</h1>

<form id="form" action="">
    <input type="text" name="name" id="name" size="10">
    <input type="text" name="message" id="message" size="60">
    <input type="submit" value="send" id="send">
</form>

<hr>
<div id="chat"></div>

<script type="text/javascript" src="/javascripts/client.js"></script>

</body>

</html>

最後にクライアント側のJS。public/javascripts/client.js
var connect = window.addEventListener
                ? function(element, type, callback) { // IE以外
                    element.addEventListener(type, callback, false);
                }
                : function(element, type, callback) { // IE
                    element.attachEvent("on" + type, function() {
                        return callback(window.event);
                    });
                };

var createXHR = XMLHttpRequest
                ? function() {
                    return new XMLHttpRequest();
                }
                : function() {
                    return new ActiveXObject("MSXML2.XMLHTTP.6.0");
                }

// ページが読み込まれたら呼び出される
connect(window, "load", function() {
    var nameInput = document.getElementById('name'),
        messageInput = document.getElementById('message'),
        sendMessage = function() {
            var data = "name=" + encodeURIComponent(nameInput.value)
                        + "&message=" + encodeURIComponent(messageInput.value),
                    xhr = createXHR();

            xhr.open("POST", "message", false);
            xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
            xhr.send(data);
        };

    var f = document.getElementById('form');

    connect(f, "submit", function(event) {
        sendMessage();
        messageInput.value = "";
        if (event.preventDefault) {
            event.preventDefault();
        }

        return false;
    });

    loop(true);
});

// メッセージを受け取るループ処理
function loop(isFirst) {
    var xhr = createXHR(),
        query = isFirst ? "" : ("?" + new Date().getTime());

    xhr.open("GET", "message" + query, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                render(eval(xhr.responseText));
            }

            loop(false);
        }
    };
    xhr.send();
}

// 受け取ったメッセージを表示する
function render(log) {
    var chat = document.getElementById('chat');

    chat.innerHTML = " ";
    log.reverse();

    for (var key in log) {
        var entry = log[key],
            div = document.createElement('div'),
            message = document.createTextNode(entry['name'] + ": " + entry['message']);

        div.appendChild(message);
        chat.appendChild(div);
    }
}

ほぼはじめてさわったので説明が難しいですがこれで動作します。
複数のブウラザからhttp://127.0.0.1:3000/chat.htmlにアクセスして見てください。

従来のWebアプリケーションと違い画面のリロードとか定期的にサーバへアクセスするなど余計なものがないはわかります。
がなかなか動きを把握するのにて手間取りました。

jQueryとかSocket.IOとかを使えばもっとシンプルに書けそうな気もするんですがとりあえずはこんなかんじで。



Macにnode.jsをインストール

前にさわったようなさわってないようなnode.js。
http://nodejs.org/

WebSocketを試してみたくて手軽に試せそうでインストールしてみました。
インストール手順をメモ程度に。。。

$ curl -O http://nodejs.org/dist/node-latest.tar.gz
$ tar zxvf node-latest.tar.gz
$ cd node-v0.8.0
$ ./configure
$ make
$ sudo make install
$ node -v
v0.8.0

インストールはこれでOK。

とりあえずお決まりのHelloWorldを実行してみます。
適当なディレクトリにファイルを作成します。

HelloWorld.js
var http = require('http');

var server = http.createServer(
 function(request, response) {
  response.writeHead(200, {'content-type': 'text/plain'});
  response.end('Hello World!');
 }
).listen(8124);

console.log('Server running at http://127.0.0.1:8124/')

これができたらターミナルでnode.jsを動かします。
$ node HelloWorld.js
Server running at http://127.0.0.1:8124

ブラウザを起動してhttp://127.0.0.1:8124にアクセスしてHelloWorldが表示されればOK。

簡単です。

ついでにnpm(node package manager)もインストールしておきました。
私の環境(Mac OS Lion)では権限を切り替えてからしか正常にインストールできませんでした。
$ sudo -s
# curl https://npmjs.org/install.sh | sh
# exit
$ npm -v
1.1.32

これでOK。
もうひとつついでにnpmの動作確認もかねてsocket.ioもインストール
$ npm install socket.io

これで一通りの準備はできたと思います。
また時間があるときにいろいろ作っていきたいと思います。


2011年8月22日月曜日

javascriptで0埋め

PHPで言うところのsprintf、VBで言うところのFormatやToStringみたいなことをjavascriptで。

いい記事がありましたのでそこを参考にしました。

PCソフト備忘録 JavaScriptで数値をゼロパディングする方法

slice関数を使って簡単に0埋めができます。
slice関数は先頭の引数に負の数字を指定すると後ろから数えてくれるのでそれを利用しています。
また、似たようなsubstring関数がありますがsubstringでは負の数字を指定しても0番目として認識してしまいます。

2011年7月8日金曜日

jQueryを使ったスライドとHTML5でのスライド

最近はHTML5が流行ってますが簡単な画面なスライドをjQuery版とHTML5版を作ってみました。
(作ったと言っても大したこと作ってませんが)
jQueryとHTML5でそれほどソースを変えているわけではありませんが、HTML5(というよりCSS3)でエフェクトをかけるのは何かと便利です。


【jQueryでスライド】


【HTML5でスライド】

2011年6月30日木曜日

javascriptでtrim

javascriptにはtrim関数がないので自前で実装する。
str.replace(/(^\s+)|(\s+$)/g, "");

他にもいかにも関数っぽくするなら
String.prototype.trim = function() {
    return this.replace(/(^\s+)|(\s+$)/g, "");
}

function func(str) {
    return str.trim();
}

jQueryを使える環境なら
$.trim(val);