function option(args, elements, promiseHandler, action) {
    var key = args[0],
        queue = action.indexOf(".") >= 0 ? action.replace(/^.*\./, "") : undefined,
        queueName = queue === "false" ? false : validateQueue(queue, true);
    var animations = void 0,
        value = args[1];
    if (!key) {
        console.warn("VelocityJS: Cannot access a non-existant key!");
        return null;
    }
    // If we're chaining the return value from Velocity then we are only
    // interested in the values related to that call
    if (isVelocityResult(elements) && elements.velocity.animations) {
        animations = elements.velocity.animations;
    } else {
        animations = [];
        for (var activeCall = State.first; activeCall; activeCall = activeCall._next) {
            if (elements.indexOf(activeCall.element) >= 0 && getValue(activeCall.queue, activeCall.options.queue) === queueName) {
                animations.push(activeCall);
            }
        }
        // If we're dealing with multiple elements that are pointing at a
        // single running animation, then instead treat them as a single
        // animation.
        if (elements.length > 1 && animations.length > 1) {
            var i = 1,
                options = animations[0].options;
            while (i < animations.length) {
                if (animations[i++].options !== options) {
                    options = null;
                    break;
                }
            }
            // TODO: this needs to check that they're actually a sync:true animation to merge the results, otherwise the individual values may be different
            if (options) {
                animations = [animations[0]];
            }
        }
    }
    // GET
    if (value === undefined) {
        var result = [],
            flag = animationFlags[key];
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;

        try {
            for (var _iterator = animations[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                var animation = _step.value;

                if (flag === undefined) {
                    // A normal key to get.
                    result.push(getValue(animation[key], animation.options[key]));
                } else {
                    // A flag that we're checking against.
                    result.push((animation._flags & flag) === 0); // tslint:disable-line:no-bitwise
                }
            }
        } catch (err) {
            _didIteratorError = true;
            _iteratorError = err;
        } finally {
            try {
                if (!_iteratorNormalCompletion && _iterator.return) {
                    _iterator.return();
                }
            } finally {
                if (_didIteratorError) {
                    throw _iteratorError;
                }
            }
        }

        if (elements.length === 1 && animations.length === 1) {
            // If only a single animation is found and we're only targetting a
            // single element, then return the value directly
            return result[0];
        }
        return result;
    }
    // SET
    var isPercentComplete = void 0;
    switch (key) {
        case "cache":
            value = validateCache(value);
            break;
        case "begin":
            value = validateBegin(value);
            break;
        case "complete":
            value = validateComplete(value);
            break;
        case "delay":
            value = validateDelay(value);
            break;
        case "duration":
            value = validateDuration(value);
            break;
        case "fpsLimit":
            value = validateFpsLimit(value);
            break;
        case "loop":
            value = validateLoop(value);
            break;
        case "percentComplete":
            isPercentComplete = true;
            value = parseFloat(value);
            break;
        case "repeat":
        case "repeatAgain":
            value = validateRepeat(value);
            break;
        default:
            if (key[0] !== "_") {
                var num = parseFloat(value);
                if (value === String(num)) {
                    value = num;
                }
                break;
            }
        // deliberate fallthrough
        case "queue":
        case "promise":
        case "promiseRejectEmpty":
        case "easing":
        case "started":
            console.warn("VelocityJS: Trying to set a read-only key:", key);
            return;
    }
    if (value === undefined || value !== value) {
        console.warn("VelocityJS: Trying to set an invalid value:" + key + "=" + value + " (" + args[1] + ")");
        return null;
    }
    var _iteratorNormalCompletion2 = true;
    var _didIteratorError2 = false;
    var _iteratorError2 = undefined;

    try {
        for (var _iterator2 = animations[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var _animation = _step2.value;

            if (isPercentComplete) {
                _animation.timeStart = lastTick - getValue(_animation.duration, _animation.options.duration, defaults$1.duration) * value;
            } else {
                _animation[key] = value;
            }
        }
    } catch (err) {
        _didIteratorError2 = true;
        _iteratorError2 = err;
    } finally {
        try {
            if (!_iteratorNormalCompletion2 && _iterator2.return) {
                _iterator2.return();
            }
        } finally {
            if (_didIteratorError2) {
                throw _iteratorError2;
            }
        }
    }

    if (promiseHandler) {
        if (isVelocityResult(elements) && elements.velocity.animations && elements.then) {
            elements.then(promiseHandler._resolver);
        } else {
            promiseHandler._resolver(elements);
        }
    }
}
Get or set an option or running AnimationCall data value. If there is no
value passed then it will get, otherwise we will set.

NOTE: When using "get" this will not touch the Promise as it is never
returned to the user.