2018年5月1日 星期二

jq.css 相關有用函示

(function () {
    let rcssNum = /^(?:([+-])=|)([+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))([a-z%]*)$/i;
    rcssNum = /^(?:([+-])=)?(\-{0,1}(?:\d+|\d+\.\d+))([a-z%]*)$/i;

    let rmsPrefix = /^-ms-/;
    let rdashAlpha = /-([a-z])/g;

    let rcustomProp = /^--/;

    let cssNumber = {
        animationIterationCount: true,
        columnCount: true,
        fillOpacity: true,
        flexGrow: true,
        flexShrink: true,
        fontWeight: true,
        lineHeight: true,
        opacity: true,
        order: true,
        orphans: true,
        widows: true,
        zIndex: true,
        zoom: true
    };
    //==========================================================================
    // Convert dashed to camelCase; used by the css and data modules
    // Support: IE <=9 - 11, Edge 12 - 13
    // Microsoft forgot to hump their vendor prefix (#9572)
    function camelCase(string) {

        // rmsPrefix = /^-ms-/
        // rdashAlpha = /-([a-z])/g
        return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase);
    }
    //==========================================================================

    // Return a property mapped along what jQuery.cssProps suggests or to
    // a vendor prefixed property.
    function finalPropName(name) {
        // jQuery.cssProps = {float: }
        var ret = jQuery.cssProps[name];
        if (!ret) {
            ret = jQuery.cssProps[name] = vendorPropName(name) || name;
        }
        return ret;
    }
    //==========================================================================

    // Return a css property mapped to a potentially vendor prefixed property
    // 針對不同瀏覽器的 prefixes
    function vendorPropName(name) {

        // Shortcut for names that are not vendor prefixed
        // emptyStyle
        if (name in emptyStyle) {
            return name;
        }

        // Check for vendor prefixed names
        var capName = name[0].toUpperCase() + name.slice(1),
                i = cssPrefixes.length;

        while (i--) {
            name = cssPrefixes[i] + capName;
            if (name in emptyStyle) {
                return name;
            }
        }
    }
    //==========================================================================

    function style(elem, name, value, extra) {
        debugger;

        // Don't set styles on text and comment nodes
        // nodeType:(3:text, 8:comment)
        if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) {
            return;
        }

        // Make sure that we're working with the right name
        var ret, type, hooks;
        var origName = jQuery.camelCase(name);

        // rcustomProp:/^--/
        var isCustomProp = rcustomProp.test(name);
        var style = elem.style;

        // Make sure that we're working with the right name. We don't
        // want to query the value if it is a CSS custom property
        // since they are user-defined.
        // 名稱的統一與修正
        if (!isCustomProp) {
            name = finalPropName(origName);
        }

        // Gets hook for the prefixed version, then unprefixed version
        hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];

        // Check if we're setting a value
        if (value !== undefined) {
            debugger;

            type = typeof value;

            // Convert "+=" or "-=" to relative numbers (#7345)
            if (type === "string" && (ret = rcssNum.exec(value)) && ret[1]) {
                // here
                value = adjustCSS(elem, name, ret);

                // Fixes bug #9237
                type = "number";
            }

            // Make sure that null and NaN values aren't set (#7116)
            if (value == null || value !== value) {
                return;
            }

            // If a number was passed in, add the unit (except for certain CSS properties)
            if (type === "number") {
                value += ret && ret[3] || (jQuery.cssNumber[origName] ? "" : "px");
            }

            // background-* props affect original clone's values
            if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0) {
                style[name] = "inherit";
            }

            // If a hook was provided, use that value, otherwise just set the specified value
            if (!hooks || !("set" in hooks) ||
                    (value = hooks.set(elem, value, extra)) !== undefined) {

                if (isCustomProp) {
                    style.setProperty(name, value);
                } else {
                    style[name] = value;
                }
            }

        } else {

            // If a hook was provided get the non-computed value from there
            if (hooks && "get" in hooks &&
                    (ret = hooks.get(elem, false, extra)) !== undefined) {

                return ret;
            }

            // Otherwise just get the value from the style object
            return style[name];
        }
    }

    //==========================================================================
    // elem: dom
    // prop: cssKey
    // valueParts(單位與數值)
    function adjustCSS(elem, prop, valueParts, tween) {
        debugger;

        var adjusted;
        var scale = 1;
        var maxIterations = 20;

        //----------------------------
        // 獲取現在的值
        var currentValue = tween ?
                function () {
                    return tween.cur();
                } :
                function () {
                    return jQuery.css(elem, prop, "");
                };
        var initial = currentValue();
        //----------------------------
        // 設定的單位
        let unit;

        if (valueParts && valueParts[3]) {
            unit = valueParts[3];
        } else {
            unit = (jQuery.cssNumber[prop] ? "" : "px");
        }
        //----------------------------
        // 預設單位
        // Starting value computation is required for potential unit mismatches
        var initialInUnit = (jQuery.cssNumber[prop] || unit !== "px" && +initial);

        if (initialInUnit) {
            initialInUnit = rcssNum.exec(jQuery.css(elem, prop));
        }

        //----------------------------
        // 若預設單位與設定單位不同
        // 必須進入轉換
        if (initialInUnit && initialInUnit[3] !== unit) {

            // Trust units reported by jQuery.css
            unit = unit || initialInUnit[3];

            // Make sure we update the tween properties later on
            valueParts = valueParts || [];

            // Iteratively approximate from a nonzero starting point
            initialInUnit = +initial || 1;

            do {

                // If previous iteration zeroed out, double until we get *something*.
                // Use string for doubling so we don't accidentally see scale as unchanged below
                scale = scale || ".5";

                // Adjust and apply
                initialInUnit = initialInUnit / scale;
                jQuery.style(elem, prop, initialInUnit + unit);

                // Update scale, tolerating zero or NaN from tween.cur()
                // Break the loop if scale is unchanged or perfect, or if we've just had enough.
            } while (
                    (function () {
                        debugger;
                        let c_value = currentValue();
                        let a = scale;

                        // initial(一開始的值)
                        // 用目標單位移動後,取比例值,供下次修正
                        let b = scale = (c_value / initial);

                        return (a !== b) && (scale !== 1) && --maxIterations;
                    })()
                    );
        }
        //----------------------------
        if (valueParts) {
            initialInUnit = +initialInUnit || +initial || 0;

            // Apply relative offset (+=/-=) if specified
            adjusted = valueParts[1] ?
                    initialInUnit + (valueParts[1] + 1) * valueParts[2] :
                    +valueParts[2];
            if (tween) {
                tween.unit = unit;
                tween.start = initialInUnit;
                tween.end = adjusted;
            }
        }
        return adjusted;
    }
    ;
})();