Example #1
0
    // Functions


    /**
     * Prepare hostEditor for an InlineTimingFunctionEditor at pos if possible.
     * Return editor context if so; otherwise null.
     *
     * @param {Editor} hostEditor
     * @param {{line:Number, ch:Number}} pos
     * @return {timingFunction:{?string}, reason:{?string}, start:{?TextMarker}, end:{?TextMarker}}
     */
    function prepareEditorForProvider(hostEditor, pos) {
        var cursorLine, sel, startPos, endPos, startBookmark, endBookmark, currentMatch,
            cm = hostEditor._codeMirror;

        sel = hostEditor.getSelection();
        if (sel.start.line !== sel.end.line) {
            return {timingFunction: null, reason: null};
        }
        
        cursorLine = hostEditor.document.getLine(pos.line);
        
        // code runs several matches complicated patterns, multiple times, so
        // first do a quick, simple check to see make sure we may have a match
        if (!cursorLine.match(/cubic-bezier|linear|ease|step/)) {
            return {timingFunction: null, reason: null};
        }

        currentMatch = TimingFunctionUtils.timingFunctionMatch(cursorLine, false);
        if (!currentMatch) {
            return {timingFunction: null, reason: Strings.ERROR_TIMINGQUICKEDIT_INVALIDSYNTAX};
        }
        
        // check for subsequent matches, and use first match after pos
        var lineOffset = 0,
            matchLength = ((currentMatch.originalString && currentMatch.originalString.length) || currentMatch[0].length);
        while (pos.ch > (currentMatch.index + matchLength + lineOffset)) {
            var restOfLine = cursorLine.substring(currentMatch.index + matchLength + lineOffset),
                newMatch = TimingFunctionUtils.timingFunctionMatch(restOfLine, false);

            if (newMatch) {
                lineOffset += (currentMatch.index + matchLength);
                currentMatch = $.extend(true, [], newMatch);
            } else {
                break;
            }
        }

        currentMatch.lineOffset = lineOffset;

        startPos = {line: pos.line, ch: lineOffset + currentMatch.index};
        endPos   = {line: pos.line, ch: lineOffset + currentMatch.index + matchLength};
        
        startBookmark = cm.setBookmark(startPos);
        endBookmark   = cm.setBookmark(endPos);
        
        // Adjust selection to the match so that the inline editor won't
        // get dismissed while we're updating the timing function.
        hostEditor.setSelection(startPos, endPos);
        
        return {
            timingFunction: currentMatch,
            start: startBookmark,
            end: endBookmark
        };
    }
Example #2
0
 /**
  * Expects an invalid steps() function to be corrected the right way, with the right match
  * and originalString given a string to match and an expectation of the output match.
  * @param {string} str The string to match
  * @param {Array} expectedArray The array that should equal the output match.
  */
 function testInvalidBezier(str, expectedArray) {
     var match = TimingFunctionUtils.timingFunctionMatch(str, false);
     runs(function () {
         expectArraysToBeEqual(match, expectedArray);
         expect(match.originalString).toEqual(str);
     });
 }
Example #3
0
 runs(function () {
     makeTimingFuncUI("steps(5, start)");
     var matchUpdate = TimingFunctionUtils.timingFunctionMatch("steps(6, end)", true);
     timingFuncEditor.handleExternalUpdate(matchUpdate);
     expect(timingFuncEditor._stepParams.count).toEqual(6);
     expect(timingFuncEditor._stepParams.timing).toEqual("end");
 });
    InlineTimingFunctionEditor.prototype.getCurrentRange = function () {
        var start, end;
        
        start = this._startBookmark.find();
        if (!start) {
            return null;
        }
        
        end = this._endBookmark.find();
        if (!end) {
            end = { line: start.line };
        }
        
        // Even if we think we have a good end bookmark, we want to run the
        // regexp match to see if there's a valid match that extends past the bookmark.
        // This can happen if the user deletes the end of the existing timingFunction and then
        // types some more.
        // FUTURE: when we migrate to CodeMirror v3, we might be able to use markText()
        // instead of two bookmarks to track the range. (In our current old version of
        // CodeMirror v2, markText() isn't robust enough for this case.)
        var line = this.hostEditor.document.getLine(start.line),
            matches = TimingFunctionUtils.timingFunctionMatch(line.substr(start.ch), true),
            originalLength;

        // No longer have a match
        if (!matches) {
            return null;
        }
        
        originalLength = ((matches.originalString && matches.originalString.length) || matches[0].length);
        // Note that end.ch is exclusive, so we don't need to add 1 before comparing to
        // the matched length here.
        if (end.ch === undefined || (end.ch - start.ch) !== originalLength) {
            end.ch = start.ch + originalLength;
            this._endBookmark.clear();
            this._endBookmark = this.hostEditor._codeMirror.setBookmark(end);
        }
        
        if (end.ch === undefined) {
            // We were unable to resync the end bookmark.
            return null;
        } else {
            return {
                start: start,
                end:   end,
                match: matches,
                originalLength: originalLength
            };
        }
    };
Example #5
0
            /**
             * Creates a hidden BezierCurveEditor and appends it to the body. Note that this is a
             * standalone BezierCurveEditor, not inside an InlineTimingFunctionEditor.
             * @param {string} initialTimingFunction The timingFunction that should be initially set
             *     in the BezierCurveEditor.
             * @param {?function} callback An optional callback to be passed as the BezierCurveEditor's
             *     callback. If none is supplied, a dummy function is passed.
             */
            function makeTimingFuncUI(initialTimingFunction, callback) {
                var parent = $(window.document.body),
                    match = TimingFunctionUtils.timingFunctionMatch(initialTimingFunction, true),
                    cb = callback || function () { };

                if (match.isBezier) {
                    timingFuncEditor = new BezierCurveEditor(parent, match, cb);
                } else if (match.isStep) {
                    timingFuncEditor = new StepEditor(parent, match, cb);
                }

                // Hide it
                timingFuncEditor.getRootElement().css("display", "none");
            }
    InlineTimingFunctionEditor.prototype._handleTimingFunctionChange = function (timingFunctionString) {
        var timingFunctionMatch = TimingFunctionUtils.timingFunctionMatch(timingFunctionString, true);
        if (timingFunctionMatch !== this._timingFunction) {
            var range = this.getCurrentRange();
            if (!range) {
                return;
            }

            // Don't push the change back into the host editor if it came from the host editor.
            if (!this._isHostChange) {
                // Replace old timingFunction in code with the editor's timing function, and select it
                this._isOwnChange = true;
                this.hostEditor.document.replaceRange(timingFunctionString, range.start, range.end, this._origin);
                this._isOwnChange = false;
                this.hostEditor.setSelection(range.start, {
                    line: range.start.line,
                    ch: range.start.ch + timingFunctionString.length
                });
            }
            
            this._timingFunction = timingFunctionMatch;
        }
    };
Example #7
0
 it("should not match steps function with no parens", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps", false);
     expect(match).toBeFalsy();
 });
Example #8
0
 it("should match step-end function in declaration in strict mode", function () {
     match = TimingFunctionUtils.timingFunctionMatch("transition-timing-function: step-end;", false);
     expect(match.length).toEqual(1);
     expect(match[0]).toEqual("step-end");
     expect(match.originalString).toBeFalsy();
 });
Example #9
0
 it("should match step-end function value in lax mode", function () {
     match = TimingFunctionUtils.timingFunctionMatch("step-end", true);
     expect(match.length).toEqual(1);
     expect(match[0]).toEqual("step-end");
     expect(match.originalString).toBeFalsy();
 });
Example #10
0
 it("should not match cubic-bezier function with invalid whitespace", function () {
     match = TimingFunctionUtils.timingFunctionMatch("cubic-bezier (0, 0, 1, 1)", false);
     expect(match).toBeFalsy();
 });
Example #11
0
 it("should match steps function with extra optional whitespace with 2 params", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps( 8 , start )", false);
     expectArraysToBeEqual(match, ["steps( 8 , start )", "8", "start"]);
     expect(match.originalString).toBeFalsy();
 });
Example #12
0
 it("should not match unknown timing function", function () {
     match = TimingFunctionUtils.timingFunctionMatch("step", false);
     expect(match).toBeFalsy();
 });
Example #13
0
 runs(function () {
     makeTimingFuncUI("cubic-bezier(.1, .3, .5, .7)");
     var matchUpdate = TimingFunctionUtils.timingFunctionMatch("cubic-bezier(.2, .4, .6, .8)", true);
     timingFuncEditor.handleExternalUpdate(matchUpdate);
     expectArraysToBeEqual(timingFuncEditor._cubicBezierCoords, [".2", ".4", ".6", ".8"]);
 });
Example #14
0
 it("should match steps function in full line of longhand css", function () {
     match = TimingFunctionUtils.timingFunctionMatch("    transition-timing-function: steps(5, start);", false);
     expectArraysToBeEqual(match, ["steps(5, start)", "5", "start"]);
     expect(match.originalString).toBeFalsy();
 });
Example #15
0
 it("should match bezier curve function with extra optional whitespace", function () {
     match = TimingFunctionUtils.timingFunctionMatch("cubic-bezier( .1 , .2 , .3 , .4 )", false);
     expectArraysToBeEqual(match, ["cubic-bezier( .1 , .2 , .3 , .4 )", ".1", ".2", ".3", ".4"]);
     expect(match.originalString).toBeFalsy();
 });
Example #16
0
 it("should match steps function with second parameter of end", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps(12, end)", false);
     expectArraysToBeEqual(match, ["steps(12, end)", "12", "end"]);
     expect(match.originalString).toBeFalsy();
 });
Example #17
0
 it("should match steps function with only 1 parameter", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps(8)", false);
     expectArraysToBeEqual(match, ["steps(8)", "8", undefined]);
     expect(match.originalString).toBeFalsy();
 });
Example #18
0
 it("should match steps function in lax mode", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps(3, start)", true);
     expect(match).toBeTruthy();
     expectArraysToBeEqual(match, ["steps(3, start)", "3", "start"]);
     expect(match.originalString).toBeFalsy();
 });
Example #19
0
 it("should not match linear when not a timing function", function () {
     match = TimingFunctionUtils.timingFunctionMatch("background: linear-gradient(to bottom, blue, white);", false);
     expect(match).toBeFalsy();
 });
Example #20
0
 it("should not match cubic-bezier function with UPPER-CASE", function () {
     match = TimingFunctionUtils.timingFunctionMatch("CUBIC-BEZIER(0, 0, 1, 1)", false);
     expect(match).toBeFalsy();
 });
Example #21
0
 it("should not match steps function with invalid whitespace", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps (1, end)", false);
     expect(match).toBeFalsy();
 });
Example #22
0
 it("should match bezier curve function with leading zeros", function () {
     match = TimingFunctionUtils.timingFunctionMatch("cubic-bezier(0.1, 0.2, 0.3, 0.4)", false);
     expectArraysToBeEqual(match, ["cubic-bezier(0.1, 0.2, 0.3, 0.4)", "0.1", "0.2", "0.3", "0.4"]);
     expect(match.originalString).toBeFalsy();
 });
Example #23
0
 it("should not match steps function with UPPER-CASE", function () {
     match = TimingFunctionUtils.timingFunctionMatch("STEPS(12)", false);
     expect(match).toBeFalsy();
 });
Example #24
0
 it("should match steps function with no optional whitespace with 2 params", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps(3,end)", false);
     expectArraysToBeEqual(match, ["steps(3,end)", "3", "end"]);
     expect(match.originalString).toBeFalsy();
 });
Example #25
0
 it("should match bezier curve function in full line of shorthand css", function () {
     match = TimingFunctionUtils.timingFunctionMatch("    transition: top 100ms cubic-bezier(.37, .28, .83, .94) 0;", false);
     expectArraysToBeEqual(match, ["cubic-bezier(.37, .28, .83, .94)", ".37", ".28", ".83", ".94"]);
     expect(match.originalString).toBeFalsy();
 });
Example #26
0
 it("should match steps function with extra optional whitespace with 1 param", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps( 7 )", false);
     expectArraysToBeEqual(match, ["steps( 7 )", "7", undefined]);
     expect(match.originalString).toBeFalsy();
 });
Example #27
0
 it("should match steps function in full line of shorthand css", function () {
     match = TimingFunctionUtils.timingFunctionMatch("    transition: top 100ms steps(10) 0;", false);
     expectArraysToBeEqual(match, ["steps(10)", "10", undefined]);
     expect(match.originalString).toBeFalsy();
 });
Example #28
0
 it("should match ease-in-out animation function in declaration in strict mode", function () {
     match = TimingFunctionUtils.timingFunctionMatch("animation-timing-function: ease-in-out;", false);
     expect(match.length).toEqual(1);
     expect(match[0]).toEqual("ease-in-out");
     expect(match.originalString).toBeFalsy();
 });
Example #29
0
 it("should match bezier curve function in lax mode", function () {
     match = TimingFunctionUtils.timingFunctionMatch("cubic-bezier(.1, .2, .3, .4)", true);
     expect(match).toBeTruthy();
     expectArraysToBeEqual(match, ["cubic-bezier(.1, .2, .3, .4)", ".1", ".2", ".3", ".4"]);
     expect(match.originalString).toBeFalsy();
 });
Example #30
0
 it("should match steps function with leading zeros", function () {
     match = TimingFunctionUtils.timingFunctionMatch("steps(04, end)", false);
     expectArraysToBeEqual(match, ["steps(04, end)", "04", "end"]);
     expect(match.originalString).toBeFalsy();
 });