とりあえず書きなぐる

とりあえず、マイノリティーなプログラムを極力説明せずに書きなぐります

TypeScriptでjQueryプラグインとか

かなりポンコツjQuery Mobile
特にPopupは結構致命傷で、例えばInputを配置してAndroidで表示すると日本語入力できません
キーボードに負けます
公式のデモでもそうなので、現状どうしようもないのでしょう

そこで別途オーバーラップな子ウィンドウをでっちあげます
JavaScriptを使用しなくてはいけないのですが、生のJavaScriptは書きたくありません
無理です、スペルミスで勝手に変数が生えてくるようなものは気が狂います、古VBのバリアント思い出します
そこでTypeScript
型付き、Class付き、Namespace付きのJavaScript擬きです
最終的には自動生成されたJavaScriptが実行されるのですが、VisualStudioを使用している限りは変換等を気にする必要はありません
発行まで全自動です

VisualStudioは2013なのでTypeScript1.8.2とかなり古いですが十分です
別途型定義ファイル(*.d.ts)が必要ですがNuGetでサクッと取れます
ソースファイルの先頭に

/// <reference path="../scripts/typings/jquery/jquery.d.ts" />
/// <reference path="../scripts/typings/jquerymobile/jquerymobile.d.ts" />

と書くと使えるようになります
外部モジュールとか使えるようですが面倒なのでこれでいいです

VisualStudioでプロジェクトのプロパティに「TypeScrptビルド」があるので「暗黙的な'any'型を許可」をオフしなと台無しです
ECMAScriptのバージョンは5で
設定が出ない場合はtsファイルを追加してVisualStudio再起動

脱線してTypeScriptでprototypeとjQueryプラグインを書いてみます
/Srcにcm.tsとhome.tsを作成します
homeはhtmlに合わせただけでなんでもよいです
cmは共通モジュールです

/Src/cm.ts

interface String {
    toInt(): number;
    toFloat(): number;
}
String.prototype.toInt = function () {
    let n = parseInt(this, 0);
    if (!n || isNaN(n)) {
        n = 0;
    }
    return n;
};
String.prototype.toFloat = function () {
    let n = parseFloat(this);
    if (!n || isNaN(n)) {
        n = 0;
    }
    return n;
};
interface Number {
    toComma(): string;
    toFillZero(width: number): string;
}
Number.prototype.toComma = function () {
    return String(this).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
};
Number.prototype.toFillZero = function (width: number) {
    let v = String(this);
    width -= v.length;
    if (width > 0) {
        return Array(width + 1).join("0") + v;
    } else {
        return v;
    }
};

StringとNumberを拡張します
interface を用意して実行という流れになります
インテリセンスも効いてくれます

続けてJQueryプラグイン

interface JQuery {
    checked(): boolean;
    checked(value: boolean): JQuery;
    disabled(): boolean;
    disabled(value: boolean): JQuery;
    uiDisabled(): boolean;
    uiDisabled(value: boolean): JQuery;
    resetDisplay(): JQuery;
    readOnly(): boolean;
    readOnly(value: boolean): JQuery;
    uiBtnActive(): boolean;
    uiBtnActive(value: boolean): JQuery;
    uiBtnUnderline(): boolean;
    uiBtnUnderline(value: boolean): JQuery;
    vclick(): JQuery;
    isVisible(): boolean;
}

namespace JQuery {
    "use strict";
    let $: JQueryStatic = <JQueryStatic>jQuery;

    $.fn.disabled = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            if ($(this).is(":disabled")) {
                return true;
            } else {
                return false;
            }
        } else {
            if (value === true) {
                $(this).attr("disabled", "disabled");
            } else {
                $(this).removeAttr("disabled");
            }
            return this;
        }
    };
    $.fn.uiDisabled = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            return $(this).hasClass("ui-disabled");
        } else {
            if (value === true) {
                $(this).addClass("ui-disabled");
            } else {
                $(this).removeClass("ui-disabled");
            }
            return this;
        }
    };
    $.fn.readOnly = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            if ($(this).is(":readonly")) {
                return true;
            } else {
                return false;
            }
        } else {
            if (value === true) {
                $(this).attr("readonly", "readonly");
            } else {
                $(this).removeAttr("readonly");
            }
            return this;
        }
    };
    $.fn.checked = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            if ($(this).is(":checked")) {
                return true;
            } else {
                return false;
            }
        } else {
            if (value === true) {
                $(this).attr("checked", "checked");
            } else {
                $(this).removeAttr("checked");
            }
            return this;
        }
    };
    $.fn.resetDisplay = function () {
        $(this).css("display", "");
        return this;
    };
    $.fn.uiBtnActive = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            return $(this).hasClass("ui-btn-active");
        } else {
            if (value === true) {
                $(this).addClass("ui-btn-active");
            } else {
                $(this).removeClass("ui-btn-active");
            }
            return this;
        }
    };
    $.fn.uiBtnUnderline = function (value?: boolean): JQuery | boolean {
        if (typeof value === "undefined") {
            return $(this).hasClass("ui-btn-underline");
        } else {
            if (value) {
                $(this).addClass("ui-btn-underline");
            } else {
                $(this).removeClass("ui-btn-underline");
            }
            return this;
        }
    };
    $.fn.vclick = function (): JQuery {
        $(this).trigger("vclick");
        return this;
    };
    $.fn.isVisible = function (): boolean {
        if ($(this).is(":visible")) {
            return true;
        } else {
            return false;
        }
    };
}

こちらも流れは同じです