変換後、外側の要素に、内側と同じclass属性を付けたい

はじめに

 バリデーションエラー時、inputタグに対してサーバ側でclass属性を追加することがあるかと思います。
 jQuery Mobile使用時、「type="text"」の場合は素直にclass属性によって見た目が変わるのですが、「type="search"」の場合は、期待通りに見た目が変わらなかったのでメモ。

環境

事象

素直に「type="search"」なinputタグのみにclass属性を適用すると、以下のように、コントロールの一部だけ見た目が変更されてしまいます。

期待通りに行かない理由

 type="search"の場合、jQuery Mobileによって、DOMにタグが追加されます。
 このため、素直にinputタグのみにclassを指定すると、追加されたタグにスタイルが適用されないのです。

 ・変換前

<input type="search" class="error"></input>

 ・変換後(divタグが外側に入って装飾が行われる。)

<div class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield ui-body-c">
    <input type="text" data-type="search" class="error ui-input-text ui-body-c">
(略)
</div>

対策

 外側のDIVタグにもバリデーションエラー用classを付ければ、コントロール全体の見た目を変更できます。
 ただし、外側のDIVタグは、サーバサイドでHTMLを生成した時点では、当然存在しません。よって、jQuery Mobileによる変換後、JavaScriptでバリデーションエラー用classを付けます。

 例えば、以下のような実装になります。
 (もう少し短く書けるとは思いますが、そこはおいておいてください)

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet"  href="js/jquery/jquery.mobile-1.2.0.css" />
    <script src="js/jquery/jquery.js"></script>
    <script src="js/jquery/jquery.mobile-1.2.0.js"></script>
    <style type="text/css">
        div.error  {
            background-color: red;
        }
    </style>
    <script type="text/javascript">
    $('#page').live('pagebeforeshow',function(event, ui){
        //jQuery Mobileによる変換後に付与されるclass属性を使用して、処理対象のタグを特定する。
        var searchElm = $("[data-type='search']");

        jQuery.each(searchElm, function() {
            //バリデーションエラーが発生した検索用フィールドのみ処理
            //(すなわち、class属性にerrorが付与されているフィールドのみ処理)
            if($(this).hasClass("error")){
                //親のdivタグを取得。
                //多分常に検索フィールド用の装飾用のDIVタグは存在するが、なかったら変な風に色が付いてしまうので、検索フィールド用の装飾用のdivタグのみを拾えるよう、classを指定しておく。
                var divElm = $(this).parent("div.ui-input-search");
                jQuery.each(divElm, function() {
                    //外側のdivタグにclass属性を追加する。
                    $(this).addClass("error");
                });
            }
        });
    });
    </script>
</head>
<body>
<div data-role="page" id="page" class="type-home">
    <div data-role="content">
        <input type="search" class="error"></input>
    </div>
</div>
</body>
</html>

さいごに

 最初、「type="search"」→「type="text"」の変換が行われることに気づかなかったため、上手く要素を選択できず、苦労しました。