2017年1月24日 星期二

(js)Promise不能捕捉到的錯誤

//var Promise = require('../lib/promise');


var p1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, "one");
});
var p2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, "two");
});
var p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, "three");
});
var p4 = new Promise((resolve, reject) => {
    setTimeout(function() {
        resolve("four");
    }, 4000);
});

var p5 = new Promise((resolve, reject) => {
    setTimeout(function() {
        reject("p5 reject");
    }, 5000);
});

var p6 = new Promise((resolve, reject) => {
    setTimeout(resolve, 4000, "six");
});

/*
 * Promise.all([p1, p2, p3, p4]).then(values => { console.log(values); }, reason => {
 * console.log(reason) });
 */

Promise.all([p1, p2, p3, p4, p6]).then(values => {
    console.log(values);
}).catch(reason => {
    console.log(reason)
});

2017年1月19日 星期四

(js)readDataOnly

/**
 * 只做表層複製
 * 
 * 只能確定{}[]的表層資料不能改變,不能刪除
 */
function readDataOnly(source) {

    var toString = Object.prototype.toString;
    var clone;
    var type = _getType(source);

    if (/array/gi.test(type) || _isPlainObject(source)) {
        // source is [], {}
        clone = _copyProperty(source);
    } else if (/map/gi.test(type)) {
        // source is Map
        clone = _copyMap(source);
    } else {
        clone = source;
    }
    return clone;
};
/**
 * copy([], {})
 */
function _copyProperty(source) {
    debugger;

    if (!isObject(source)) {
        return source;
    } else {
        var copy;
        var prototype = Object.getPrototypeOf(source);
        /* ---------------------------------- */
        if (typeof prototype != 'undefined') {
            copy = Object.create(prototype);
        } else {
            copy = Object.create(null);
        }
        /* ---------------------------------- */
        copyProperty(copy, source);

        return copy;
    }
    /* =========================================== */
    /**
     * 是否是Object
     */
    function isObject(value) {
        debugger;

        var result = (value === Object(value));
        return result;
    };
    /* =========================================== */

    function copyProperty(copy, source) {
        var propertys = Object.getOwnPropertyNames(source);

        console.dir(propertys);

        propertys.forEach(function(property) {
            var desc = Object.getOwnPropertyDescriptor(source, property);

            // 禁止表層資料被修改新增刪除
            desc.writable = false;
            desc.configurable = false;

            Object.defineProperty(copy, property, desc);
        });
    };
};
/**
 * copy map
 */
function _copyMap(source) {
    var cloneMap = new Map();

    source.forEach(function(v, k) {
        cloneMap.set(k, v);
    });

    return cloneMap;
};
/* ====================================================================== */
/**
 * 確定型別
 */
function _getType(obj) {
    var type = toString.call(obj) || '';
    type = type.replace(/(^\s?\[object\s?)|(\]\s?$)/gi, '').toLowerCase();
    return type;
};
/* ====================================================================== */
/**
 * 是否是{}
 */
function _isPlainObject(obj) {
    if (!obj || _getType(obj) !== "object") {
        return false;
    }

    var constructorName = '';
    try {
        constructorName = obj.constructor.toString();
    } catch (error) {}

    // 'Object() {[native code]}'
    if (!/function\s*Object\(\s*\)\s*\{\s*\[native\s*code\]\s*\}\s*$/gi.test(constructorName)) {
        return false;
    }
    return true;
};

2017年1月17日 星期二

(php)sscanf

sscanf($newTimeStr, "%d-%d-%d", $y, $m, $d);

(js)$.getJSON()

var jqxhr = $.getJSON( "example.json", {
        tags: "mount rainier",
        tagmode: "any",
        format: "json"
  }) .done(function() {
        console.log( "success" );
 }) .fail(function() {
        console.log( "error" );
 }) .always(function() {
        console.log( "complete" );
 });

2017年1月15日 星期日

(js)物間經過 JSON.stringfy()的結果

var x = {
            a: 0,
            b: '0',
            c: '',
            d: undefined,
            e: null
        };

JSON.stringify(x) => {"a":0,"b":"0","c":"","e":null}
----------------------------------------------------------------------------
a  =>  0 , type =  number
b  =>  0 , type =  string
c  =>   , type =  string
e  =>  null , type =  object

(js)表單數值

<form id="form_1">
            <input type="text" name="a1">
            <input type="text" name="a2" value="5">
            <select name="a3">
                    <option value=""></option>
                    <option value="0">0</option>
                    <option value="1">1</option>
             </select>
            <input type="submit" value="go">
</form>
-----------------------------------------------------------------------
name =  a1 value =   , type =  string 
name =  a2 value =  5 , type =  string
name =  a3 value =   , type =  string

2017年1月11日 星期三

HAPPY DAYS



Pratt And Mcclain 


Happy Days

Sunday, Monday, happy days.
Tuesday, Wednesday, happy days.
Thursday, Friday, happy days.
Saturday, what a day, rockin' all week for you.


These days are...
Won't you be mine? (oh, happy days)
These days are...
Oh, please be mine. (oh, happy days)


Hello sunshine, goodbye rain.
She's wearing my school ring on her chain.
She's my steady, I'm her man.
I'm gonna love her all I can.


Gonna cruise her around the town,
Show everybody what I found.
Rock and roll with all my friends,
Hopin' the music never ends.


Sunday, Monday, happy days.
Tuesday, Wednesday, happy days.
Thursday, Friday, happy days.
Saturday, what a day, rockin' all week for you.


Goodbye gray sky, hello blue,
'Cause nothing can hold me when I hold you.
Feels so right, can't be wrong,
A-rockin' and rollin' all week long.


Hello sunshine, goodbye rain.
She's wearing my school ring on her chain.
She's my steady, I'm her man.
Now I'm gonna love her all I can.


These happy days are yours and mine.
Won't you be mine? (oh, happy days)
These happy days are yours and mine.
Oh, please be mine. (oh, happy days)
These happy days are yours and mine.
Won't you be mine? (oh, happy days)
These happy days are yours and mine.
Oh, please be mine. (oh, happy days)



transcribed by Sean Wang

(php)CodeIgnite_路由規則

$route['test/([a-zA-Z]+)/\\1'] = 'test_2/classTest';

url(test/a/a) => 'test_2/classTest';


$route['test/\w+/\w+/(.*)'] = 'test_2/classTest/$1';  ($1區塊為收到的參數)
$route['test/\w+/\w+/(:any)'] = 'test_2/classTest/$1'; ($1區塊為收到的參數)

2017年1月6日 星期五

(js)JSONP的流程


////////////////////////////////////////////////////////////////////////////////
/**
 *
 *
 * 使用方式 JSONP.send(options);
 *
 *
 * <options 主要對外參數>
 *
 * timeout(int) => 設定過時
 * url(string, not null) => 要連往後端的網址
 * data(string, {}) => 要送出的參數
 * jsonp(string) => url參數(request('callBack') = function_name)
 * jsonpCallBack(string) => 手動設定callBack 函式的名稱(尚無此功能,主要是自動給予)
 *
 * error(function) => 若執行錯誤要執行的
 * beforeSend(function) => 在整個執行前要執行的函式
 * complete(function) => success完,數據都讀完處理完要做的事
 * success(function) => 執行成功要執行的函式
 *
 */
////////////////////////////////////////////////////////////////////////////////


function $JSONP_(option) {
    'use strict';
    // debugger;

    var self = this;

    // 物件的建構函式
    this.fn = this.constructor;

    /* --------------------------------------------- */
    this.haveCall = false; // 是否在傳輸階段
    this.haveLoad = false; // script是否正在load
    /* --------------------------------------------- */
    this.errorMsg_array = [];

    // head-tag
    this.headTag;
    /* --------------------------------------------- */

    /**
     * timeout: 設定過時
     * url: 要連往後端的網址
     * data: 要送出的參數(string|{})
     * jsonp: url參數(傳遞給後端的key => 此 key 內容主要的功能在告訴回呼函式的名稱)
     * jsonpCallBack: 手動設定callBack 函式的名稱(尚無此功能,主要是自動給予)
     *
     * async: 網頁運作是否要等 script loading完
     * defer:是否要等整網頁都 load完才執行
     *
     * error: 若執行錯誤要執行的函式
     * beforeSend: 在整個執行前要執行的函式
     * complete:
     * success: 執行成功要執行的函式
     */
    this.options = {
        timeout: 6000,
        url: '',
        data: null,
        async: true,
        defer: false,
        jsonp: 'callBack', // (request('callBack') = function_name)
        error: null,
        beforeSend: null,
        complete: null,
        success: null
    };

    /* -------------------------------------------- */
    this.id;
    this.fun_name = ''; // (callBack)的名稱
    this.script_id = '';
    /* -------------------------------------------- */

    this.src = ''; // 要引入 json 數據的 script.src
    this.arg = ''; // 要引入 json 數據的網址參數

    /* ====================================================================== */

    /**
     * 初始化(建構式)
     */
    this.__construct = function() {
        'use strict';
        // debugger;
        if (!(this.headTag = this.fn.prototype.headTag)) {
            this.headTag = this.fn.prototype.headTag = document.querySelector('head');
        }

        // 登錄所有 option
        this.setOption(option);
        /* ---------------------------------------------- */

        // 創建所需要的(id)
        this.id = this.fn.prototype.guid++;

        this.script_id = '$JSONP_' + this.id;

        // (callBack)的名稱
        this.fun_name = 'fun_' + this.id;
        /* ---------------------------------------------- */
        // 處理要傳送的參數(this.arg)
        this.setData();

        this.setArg();
        /* ---------------------------------------------- */
        // (script)的網址
        this.src = this.options.url + '?' + this.arg;;
    };
    /* ====================================================================== */

    this.__construct();
}
/* ========================================================================== */
/**
 * 共有參數
 */
(function() {
    this.headTag;
    this.guid = 1; // 編碼

}).call($JSONP_.prototype);


////////////////////////////////////////////////////////////////////////////////
/**
 * prototype
 *
 */

(function() {
    /**
     * start here
     */
    this.main = function() {
        var self = this;

        if (typeof this.options.beforeSend == 'function') {
            this.options.beforeSend();
        };
        /* ---------------------------------------------------- */

        // 檢查(options)
        this.checkOptions();

        // 創建臨時需要的(callBack)
        this.createCallBackFun();

        // 定時檢查
        setTimeout(timeOut.bind(this), this.options.timeout);

        // 創建要引入資料的(script)
        this.createJSONDataScript();
    };
    /* ===================================================================== */
    /**
     * 當傳輸過時
     *
     */
    function timeOut() {
        debugger;

        if (!this.haveCall) {
            // 時間到了,(callBack)卻未執行過

            var scriptDom = document.getElementById(this.script_id);;

            /* ---------------------------------- */
            // 錯誤訊息
            this.errorMsg_array.push('timeout');

            if (scriptDom) {
                this.errorMsg_array.push(scriptDom.textContent);
            }
            /* ---------------------------------- */
            // reset

            if (this.haveLoad) {
                this.reset_1();
            } else {
                // (script)還在(load)中
                this.reset_2();
            }

            /* ---------------------------------- */
            // 發出錯誤
            this.error();
        }
    };
}).call($JSONP_.prototype);
/* ========================================================================== */
(function() {
    /**
     * 創建要被(script)呼叫的(callBack)
     *
     * @return {[type]} [description]
     */
    this.createCallBackFun = function() {
        // debugger;

        var self = this;

        this.fn[this.fun_name] = callBack;

        /* ---------------------------------- */
        /**
         * 被呼叫的地方
         *
         */
        function callBack(data) {
            alert('callBack');
            debugger;
            // 已執行(callBack)
            self.haveCall = true;

            var success = self.options.success;
            self.options.success = undefined;

            if (typeof success == 'function') {
                success(data);
            }
        };
    };
    /* ====================================================================== */
    // 創建要引入 json 數據的 script
    this.createJSONDataScript = function() {
        debugger;

        var self = this;

        var script = document.createElement('script');

        script.setAttribute('src', this.src);
        script.setAttribute('id', this.script_id);
        /* ----------------------------------------- */
        /**
         * (script)的同步設定
         *
         * (defer)比(async)優先
         *
         * defer => 在網頁(load)完才執行
         * async => 異步處理
         *
         */

        if (this.options.defer) {
            this.options.async = false;
            script.defer = true;
        } else if (this.options.async) {
            script.async = true;
        }

        /* ----------------------------------------- */
        script.onerror = function(e) {
            self.haveLoad = true; // 已嘗試建立過(script)

            self.errorMsg_array.push('script 無法建立');
            self.error();
        };

        /* ----------------------------------------- */
        /**
         * 最後步驟
         *
         * (script)已經(load)完,要執行的命令也執行完
         */
        script.onload = function(e) {
            self.haveLoad = true; // 已嘗試建立過(script)

            var complete = self.options.complete;
            self.options.complete = undefined;

            (typeof complete == 'function') && (complete());
            /* ---------------------------------- */

            if (self.haveCall == true) {
                // callBack已執行過,script已讀完
                self.reset_1();
            }
        };

        /* ----------------------------------------- */

        // debugger;

        this.headTag.appendChild(script);
    };

    /* ====================================================================== */

    /**
     * 立即移除<script>標籤
     *
     * 立即移除(callBack)在(jsonp)中的紀錄
     */
    this.reset_1 = function() {

        var self = this;

        // 移除(callback)
        if (this.fn[this.fun_name] != null) {
            delete self.fn[this.fun_name];
        }
        /* ---------------------------------------- */
        // 移除(script)
        var scriptNode = document.getElementById(this.script_id);
        (scriptNode) && (this.headTag.removeChild(scriptNode));
    };
    /**
     * 移除(script)標籤
     *
     * 延時移除(callback)
     */
    this.reset_2 = function() {

        var self = this;

        // 移除(callback)
        if (this.fn[this.fun_name] != null) {
            // 正常執行的話(this.fn[this.fun_name])應該已經刪除了
            setTimeout(function() {
                // body
                delete self.fn[this.fun_name];
            }, 100000);
        }
        /* ---------------------------------------- */
        // 移除(script)
        var scriptNode = document.getElementById(this.script_id);
        (scriptNode) && (this.headTag.removeChild(scriptNode));
    };



    /* ====================================================================== */
    /**
     * 發出錯誤
     */
    this.error = function() {
        var error = this.options.error;
        this.options.error = undefined;

        if (typeof error == 'function') {
            var error_msg = this.errorMsg_array.join(', ');
            error(error_msg);
        }
    };

}).call($JSONP_.prototype);

/* ========================================================================== */
/**
 * prototype
 */
(function() {

    /**
     * 處理傳送的參數,轉換 data格式
     */
    this.setData = function() {
        // debugger;

        if (this.options.data == null) {
            this.options.data = {};
        } else if (typeof this.options.data == 'string') {
            // 將文字參數轉為物件
            var arg_array = this.options.data.split('&');

            this.options.data = {};

            for (var i in arg_array) {
                var tmp_array = arg_array[i].split('=');

                var key = tmp_array[0] || '';
                var value = tmp_array[1] || '';

                this.options.data[key] = value;
            }
        }
        /* ------------------------------------------------------- */
        // 處理(callBack)
        var date = new Date();

        // 預設是(callBack)
        var jsonpName = this.options.jsonp;

        // 告訴後端要呼叫那個(callBack)
        this.options.data[jsonpName] = '$JSONP_.' + this.fun_name;
        this.options.data.timeStamp = date.getTime(); // 防止網頁快取
    };
    /* ====================================================================== */
    /**
     * 設定網址參數
     */
    this.setArg = function() {
        var tmpArray = [];
        for (var j in this.options.data) {
            var str = j + '=' + this.options.data[j];
            tmpArray.push(str);
        }

        this.arg = tmpArray.join('&');
    };

    /* ====================================================================== */
    /**
     * 處理選項
     */
    this.setOption = function(option) {
        // debugger;

        var optionType = Object.prototype.toString.call(option);

        if (!/object\]\s*$/gi.test(optionType)) {
            throw new TypeError('input option must be {}');
        }

        for (var key in option) {
            if (this.options.hasOwnProperty(key)) {
                this.options[key] = option[key];
            }
        }

    };

}).call($JSONP_.prototype);
////////////////////////////////////////////////////////////////////////////////
(function() {
    this.___check = function() {};
    /* ======================================================================== */
    /**
     * 輸入檢查
     */
    this.checkOptions = function() {
        // debugger;
        var errorMsg_array = [];
        var toString_fun = Object.prototype.toString;

        if (!this.headTag || this.headTag.tagName.toLowerCase() !== 'head') {
            errorMsg_array.push('no catch head tag');
        }

        if (typeof this.arg !== 'string') {
            errorMsg_array.push('網址參數格式有問題');
        }
        // options.data
        if (this.options.data != null) {
            var type = toString_fun.call(this.options.data);
            if (typeof this.options.data !== 'string' &&
                !/object\]\s*$/gi.test(type)) {
                errorMsg_array.push('data參數格式有問題');
            }
        }
        // options.url
        if (typeof this.options.url !== 'string' || this.options.url.length == 0) {
            errorMsg_array.push('網址格式有問題');
        }

        // options.timeout
        if (typeof this.options.timeout != 'number') {
            errorMsg_array.push('timeout must be number');
        }

        // options.error
        if (this.options.error && (typeof this.options.error !== 'function')) {
            errorMsg_array.push('error must be function');
        }

        // options.beforeSend
        if (this.options.beforeSend && (typeof this.options.beforeSend !== 'function')) {
            errorMsg_array.push('beforeSend must be function');
        }

        // options.complete
        if (this.options.complete && (typeof this.options.complete !== 'function')) {
            errorMsg_array.push('complete must be function');
        }

        // options.success
        if (this.options.success && (typeof this.options.success !== 'function')) {
            errorMsg_array.push('success must be function');
        }

        // this.src
        if (typeof this.src != 'string' || this.src.length == 0) {
            errorMsg_array.push('script no set link');
        }

        if (errorMsg_array.length > 0) {
            throw new Error(errorMsg_array.join(" | "));
        }
    };
    /* ====================================================================== */
}).call($JSONP_.prototype);

////////////////////////////////////////////////////////////////////////////////
/**
 * 類別方法
 */
(function() {
    var self = this;

    /* ====================================================================== */
    // (API)start here
    this.send = function(options) {
        // debugger;

        var jsonp = new $JSONP_(options);

        jsonp.main();

        return jsonp;
    };
    /* ====================================================================== */


}).call($JSONP_);

2017年1月5日 星期四

2016年12月29日 星期四

(css)transition-problem

<!DOCTYPE html>
<html lang="en">

<head>
    <title></title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        #div_1 {
            width: 100px;
            height: 100px;
            transition-property: top;
            transition-duration: 1s;
            position: absolute;
            top: 50px;
            background-color: red;
        }
     
        .noAnimate {
            transition: none;
        }
    </style>
    <script>
        function domRedraw_1(dom) {
            // 藉著寬度改變

            var css = getComputedStyle(dom, null);
            var oldStyle = dom.style.cssText;
            /* ------------------------ */
            /**
             * 改變寬度
             * 
             * 寬度+1
             * 
             * 再改回來
             */

            var width = css.width.replace(/\D/g, '');
            width = Number(width);
            width++;
            dom.style.width = width + 'px';
            /* ------------------------ */
            // 回復
            dom.style.cssText = oldStyle;
        };

        function domRedraw_2(dom) {
            // 藉著(offsetHeight)
            dom.offsetHeight;
        };
    </script>
    <script>
        function test_1() {
            var div = document.querySelector('#div_1');
            var style = div.style;

            style.removeProperty('display');

            // important
            domRedraw_1(div);

            style.top = '200px';
        }
    </script>
</head>

<body>
    <button onclick="test_1();">Click!</button>
    <div id="div_1" style="display: none">
        target
    </div>
</body>

</html>