DIR : /home/kozerus/public_html/jkwii/js/jsdoit/jsdoit18/index.js

/home/kozerus/public_html/jkwii/js/jsdoit/jsdoit18

// forked from beryujp's "ぺたぺた貼るToDoリスト" http://jsdo.it/beryujp/ptodo
// forked from edo_m18's "Simple ToDo管理アプリ with HTML5" http://jsdo.it/edo_m18/stodo
/**
 * 自分の画像を背景に、使い方それぞれなToDo管理アプリ
 * @author beryujp
 */
(function(win, doc, $, exports) {

    var ToDoApp = {
        STORAGE    : window.localStorage,
        DBNAME     : 'todo',
        FILEDBNAME : 'todobg',
        INDEX      : 0,
        CONTAINER  : 'taskPane',
        CURRENT    : null,
        ADDFLG     : false,

        /**
         * 初期化
         * 初期化はINDEXの取得、設定
         */
        initialize: function() {
            this.INDEX = this.getIndex() || 0;
            
            // 背景画像が保存済みでなければデフォルト画像を設定
            if(!this.STORAGE[this.FILEDBNAME]) {
                this.STORAGE[this.FILEDBNAME] = JSON.stringify({dataSchema: 'http://jsrun.it/assets/j/9/O/O/j9OO9.jpg'});
            }
            this.setBackground(JSON.parse(this.STORAGE[this.FILEDBNAME]));
        },
    
        /**
         * ToDoをリストに追加する
         *
         * @param {String} txt ToDoに設定するテキスト.
         * @param {Number} id ToDoのユニークID
         * @param {Number} x 表示場所(X座標)
         * @param {Number} y 表示場所(Y座標)
         */
        addToDo: function(txt, id, x, y){
            var data;

            /**
             * 渡されたIDのデータを取得
             * もしデータがあればそれを更新する
             */
            data = this.getData(id);

            //各プロパティの正規化
            data || (data = {});
            data.groupID || (data.groupID = 0);
            data.complete || (data.complete = 0);

            data.txt = txt;
            data.tid = id;
            data.x = x;
            data.y = y;

            //設定した情報を保存
            this.setData(data, id);
            this.update();
            this.ADDFLG = false;
        },

        /**
         * ToDoを完了状態にする
         *
         * @param {Number} id 完了にする対象のToDo ID
         */
        completeToDo: function(id) {

            var data = this.getData(id);

            //コンプリートフラグを1(=完了)に
            data.complete = 1;

            //フラグを更新してデータを保存
            this.setData(data, id);
            this.update();
        },

        /**
         * ToDoを削除する
         *
         * @param {Number} id 削除するToDoのID
         */
        removeToDo: function(id) {

            var data,
                i = 0, l;

            if (!confirm('このToDoを削除しますか?')) {
                return false;
            }

            //いったん全データを取得
            data = this.getData();

            //該当するデータを検索
            for (l = data.length; i < l; i++) {
                if (data[i].tid == id) {
                    data.splice(i,1);
                    break;
                }
            }

            //更新したデータリストを保存
            this.setData(data);
            this.update();
        },

        /**
         * ToDoを変更
         * 
         * @param {Number} id 変更するToDoのID
         */
        changeToDo: function(id, x, y) {
            var txt = $('input.todoTxt', '#todo' + id).val();
            this.addToDo(txt, id, x, y);
        },

        /**
         * ToDoの追加フォームを生成する
         */
        createToDoForm: function(e) {
	    
            var id;

            if (this.isID(this.CURRENT) || this.ADDFLG) {
                return;
            }

            this.ADDFLG = true;
	    
	    /*
            if ($('#noToDo').length === 1) {
                $('#noToDo').remove();
            }
	    */

            id = this.getIndex();
            id = !isNaN(id) ? id : 0;

            $('#taskPane').append([
                '<a id="todo' + id + '" class="todoItem" style="top:' + e.offsetY + 'px; left:' + e.offsetX + 'px;">',
                    '<input type="text" class="todoTxt" value="" placeholder="ToDoアイテム" onclick="event.stopPropagation();"/> ',
                    '<input type="button" value="save" onclick="ToDoApp.changeToDo(' + id + ', ' + e.offsetX + ', ' + e.offsetY + '); event.stopPropagation();" /> ',
                    '<input type="button" value="x" onclick="ToDoApp.cancel(); event.stopPropagation();" />',
                '</a>'].join(''));
            $('input.todoTxt:visible').keyup(function(event) {
            	ToDoApp.keyupHandler(event, id);
            }).focus();
        },
        
        /**
         * ToDoアイテムのKeyupイベントハンドラ
         */
        keyupHandler: function(event, id) {
        	if(event.keyCode == 13) { // enter
				ToDoApp.changeToDo(id, 
					$('#todo'+id).css('left').substr(0, $('#todo'+id).css('left').length - 2), 
					$('#todo'+id).css('top').substr(0, $('#todo'+id).css('top').length - 2));
			} else if(event.keyCode == 27) { // escape
				ToDoApp.cancel();
			}
        },

        /**
         * ToDoの更新フォームを生成する
         */
        replaceToDoForm: function(item,evt) {
            var id, data;

            /**
             * クリックされた対象がinput要素か、
             * すでに完了しているものの場合はなにもしない
             */
            if (evt.target.nodeName.toLowerCase() === 'input') {
                return;
            }
            if (evt.currentTarget.className.indexOf('complete') !== -1) {
                return;
            }

            if (!this.isID(this.CURRENT)) {
                id = parseInt($(item).attr('data-id'),10);
                data = this.getData(id);

                if (!isNaN(id) && data) {
                    $(item)
                    .after([
                        '<a id="todo' + id + '" class="todoItem" style="top:' + data.y + 'px; left:' + data.x + 'px;">',
                            '<input type="text" class="todoTxt" value="' + data.txt + '" onclick="event.stopPropagation();"/> ',
                            '<input type="button" value="save" onclick="ToDoApp.changeToDo(' + id + ', ' + data.x + ', ' + data.y + '); event.stopPropagation();" /> ',
                            '<input type="button" value="x" onclick="ToDoApp.cancel(); event.stopPropagation();" />',
                        '</a>'].join(''))
                    .remove();
                    $('#todo' + id + ' input.todoTxt:visible').keyup(function(event) {
		            	ToDoApp.keyupHandler(event, id);
		            }).focus();
                }
            }
            evt.stopPropagation();
        },

        /**
         * 現在のindex数を取得する
         */
        getIndex: function() {

            var o = this.getData();
	    if(!o) {
		return null;
	    }
	    
	    // 最大値を求める
	    var max = 0;
	    for(var l = o.length - 1; l >= 0; l--) {
		if(parseInt(o[l].tid) > max) {
		    max = parseInt(o[l].tid);
		}
	    }
            return ++max;
        },

        /**
         * ToDoデータをlocalStorageから取得する
         *
         * @param {Number} id 取得したいToDoのID
         * @returns {Object} 取得したToDoデータリスト
         */
        getData: function(id) {

            var db = this.STORAGE[this.DBNAME],
                json,
                i = 0, l;
 
            //データが存在していなければ初期化を実行する
            (db) || this.clear();

            //JSONデータをチェック。データが存在しなければ正規化
            json = JSON.parse(this.STORAGE[this.DBNAME]);
            (json) || (json = {});
            (json.data) || (json.data = []);

			// X座標、Y座標初期化
			for(i = json.data.length; i >= 0; i-- ) {
				if(json.data && json.data[i] && json.data[i].x == undefined) {
					json.data[i].x = 10;
					json.data[i].y = 30 * i;
				}
			}
			i = 0;

            //IDが指定されていなかったらデータすべてを返す
            if (!this.isID(id)) {
                return json.data;
            }

            //指定されたIDのデータを返す
            for (l = json.data.length; i < l; i++ ) {
                if (json.data[i].tid == id) {
                    return json.data[i];
                }
            }

            //該当IDが存在しなければnullを返す
            return null;
        },

        /**
         * @param {Object} data
         * @param {Number} id
         */
        setData: function(data, id) {

            var d,
                i = 0, l;

            if (!this.isID(id)) {
                this.STORAGE[this.DBNAME] = JSON.stringify({data: data});
            }
            else {
                d = this.getData();
                update: {
                    for (l = d.length; i < l; i++) {
                        if (d[i].tid == id) {
                            d[i] = data;
                            break update;
                        }
                    }

                    d[d.length] = data;
                }

                this.STORAGE[this.DBNAME] = JSON.stringify({data:d});
            }
        },


        /**
         * idが数値かどうかを判定
         */
        isID: function(id) {

            return typeof id === 'number';
        },


        /**
         * ToDoリストをアップデートする
         *
         * @param {Number} id アップデート対象のToDo ID
         */
        update: function(id) {

            var data,
                groups = {}, index = 1, gid,
                i = 0, l,
                compFlg, element, ele,
                that = this;

            if (this.isID(id)) {
                data = this.getData(id);
            }
            else {
                data = this.getData();

                //いったん全ToDoデータを画面から削除
                $('#' + this.CONTAINER).html('');

                //ToDoがひとつも登録されていなければそれを表示
                if (!data || !data[0]) {
                    $('#todo').append('<p id="noToDo">ToDoが登録されていません。</p>');
                    return false;
                }


                //完了状態を元にソート(完了したものがリストの下に移動するように)
                /*
                data = data.sort(function(a, b) {
                    return a.complete - b.complete;
                });
                */

                for (l = data.length; i < l; i++) {
                    gid = 'g' + data[i].groupID;

/*
                    if (!groups[gid]) {
                        groups[gid] = $('<div class="groupBox" />');
                        groups[gid].attr('data-gid', data[i].groupID);
                        groups[gid].append('<p class="ttlGroup">ToDo List</p>');
                    }

                    $('#' + this.CONTAINER).append(groups['g' + data[i].groupID]);
*/
                    //完了状態をチェック
                    compFlg = data[i].complete ? ' complete' : '';

                    element = [
                        '<a id="todo{{id}}" class="{{class}}" data-id="{{id}}" style="top:{{posY}}px;left:{{posX}}px;">',
                            '<span class="todoTxtItem">{{todotext}}</span>',
                            '<div class="todoCtrl">',
                                '<input type="button" value="done" onclick="ToDoApp.completeToDo({{id}}); event.stopPropagation();" class="btnComp" /> ',
                                '<input type="button" value="x" onclick="ToDoApp.removeToDo({{id}}); event.stopPropagation();" class="btnDel" />',
                            '</div>',
                            '<div class="todoCtrl2">',
                                '<input type="button" value="resume"  onclick="ToDoApp.resume({{id}}); event.stopPropagation();" class="btnResume" />',
                                '<input type="button" value="x" onclick="ToDoApp.removeToDo({{id}}); event.stopPropagation();" class="btnDel" />',
                            '</div>',
                        '</div>'
                    ].join('');
                        
                    //要素のテンプレートからそれぞれToDoのデータで置き換え
                    element = element.replace(/{{id}}/ig, data[i].tid);
                    element = element.replace(/{{class}}/ig, 'todoItem' + compFlg);
                    element = element.replace(/{{todotext}}/ig, data[i].txt);
                    element = element.replace(/{{posY}}/ig, data[i].y);
                    element = element.replace(/{{posX}}/ig, data[i].x);

                    //生成したToDoアイテムをリストに追加
                    //ele = groups['g' + data[i].groupID].append(element);
                    ele = $('#' + this.CONTAINER).append(element);
                }

                /**
                 * 生成したToDoアイテムにクリックと
                 * hoverイベントを設定
                 */
                $('.todoItem')
                    .click(function(e) {
                        that.replaceToDoForm(this, e);
                        e.stopPropagation();
                    })
                    .hover(function() {

                        that.status('クリックで編集できます。');
                    },
                    function() {
                        that.statusClear();
                    
                    }).draggable({
                        stop: function(event, ui) {
                            that.addToDo($('#todo' + ui.helper[0].dataset['id'] + ' .todoTxtItem').html(),
					   parseInt(ui.helper[0].dataset['id']), ui.position.left, ui.position.top);
                            event.stopPropagation();
                        }
                    });
            }
        },
        
        /**
         * 完了状態にしたToDoを再開する(完了状態を解除する)
         *
         * @param {Number} id 完了状態をオフにするToDoのID
         */
        resume: function(id) {

            var data = this.getData(id);

            //完了状態をオフに
            data.complete = 0;

            //完了状態を更新してアップデート
            this.setData(data, id);
            this.update();
        },

        /**
         * 更新・追加フォームの状態をキャンセルする
         */
        cancel: function() {

            this.update();
            this.ADDFLG = false;
        },

        /**
         * データベース(localStorage)とリストを初期化(クリア)する
         */
        clear: function() {

            this.STORAGE[this.DBNAME] = JSON.stringify({data:[]});
            this.INDEX = 0;

            //画面に表示しているリストを削除
            $('#' + this.CONTAINER).html('');
        },

        /**
         * 全ToDoを削除する
         */
        clearAction: function() {

            if (this.isID(this.CURRENT)) {
                return;
            }

            if (confirm('ToDoをクリアします。この処理は取り消せません。本当に実行しますか?')) {
                this.clear();
                this.update();
            }
        },
        
        /**
         * ステータスバーにメッセージを表示
         *
         * @param {String} mes 表示するメッセージ
         */
        status: function(mes) {
            $('#status').html(mes);
        },
        statusClear: function() {
            $('#status').html('');
        },

	/**
         * 背景画像がドロップされた時の動作
         */
        onFileDrop: function(event) {
	    // ドロップされたファイルのfilesプロパティを参照
	    var files = event.dataTransfer.files;
	    var reader = new FileReader();
	    var disp = document.getElementById("disp");
	    
	    // FileReaderにイベントを登録
	    reader.onload = this.onLoadComplete;
	    
	    // ブラウザ上でファイルを展開する挙動を抑止
	    event.preventDefault();
	    
	    // 読み込み開始
	    reader.readAsDataURL(files[0]);
	    
	    /*
	    disp.innerHTML = "";
	    for (var i = 0; i < files.length; i++) {
		var f = files[i];
		// ファイル名とサイズを表示
		disp.innerHTML += "ファイル名 :" + f.name + "ファイルの型:" + f.type + "ファイルサイズ:" + f.size / 1000 + " KB " + "<br />";
	    }
	    */
	},
	
	/**
         * HTML5のドラッグ操作のお決まりごと
         * 参考:http://cpplover.blogspot.jp/2009/09/quirksblog-html5.html
         */
	onFileDragOver: function(event) {
	    // ブラウザ上でファイルを展開する挙動を抑止
	    event.preventDefault();
	},
	
        /**
         * ファイルロード完了ハンドラ
         */
	onLoadComplete: function(event) {
            window.ToDoApp.STORAGE[window.ToDoApp.FILEDBNAME] = JSON.stringify({dataSchema: event.target.result});
            window.ToDoApp.setBackground({dataSchema: event.target.result});
	},
        
        /**
         * localStorage内の画像を背景に設定
         */
        setBackground: function(json) {
            if(json.dataSchema) {
                $('#taskPane').css('background', 'url("' + json.dataSchema + '")');
            }
        },

        /**
         * localStorage内の画像を初期画像に戻す
         */
        resetBackground: function() {
	    delete window.ToDoApp.STORAGE[window.ToDoApp.FILEDBNAME];
            window.ToDoApp.initialize();
        }
    };
    //アプリの初期化を実行
    ToDoApp.initialize();

    /* ----------------------------------------------------------------------------------
       EXPORT
       グローバルからアクセスできるように変数をエクスポート
    ------------------------------------------------------------------------------------- */
    exports.ToDoApp = ToDoApp;

}(window, document, jQuery, window));

//ページ読み込み後に、アプリを実行する
$(function() { ToDoApp.update(); });
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer