adobe/brackets

View on GitHub
src/extensions/default/DebugCommands/ErrorNotification.js

Summary

Maintainability
A
55 mins
Test Coverage
/*
 * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var _               = brackets.getModule("thirdparty/lodash"),
        AnimationUtils  = brackets.getModule("utils/AnimationUtils"),
        ExtensionUtils  = brackets.getModule("utils/ExtensionUtils"),
        Strings         = brackets.getModule("strings");

    var $span      = null,
        errorCount = 0,
        _attached  = false,
        _windowOnError,
        _consoleError,
        _consoleClear;

    ExtensionUtils.loadStyleSheet(module, "styles.css");

    function showDeveloperTools() {
        try {
            brackets.app.showDeveloperTools();
        } catch (err) {
            console.error(err);
        }
    }

    function handleClick(event) {
        if (event.shiftKey) {
            window.console.clear();
        } else {
            showDeveloperTools();
        }
    }

    function refreshIndicator() {
        // never show 0 errors
        if (!_attached || errorCount === 0) {
            // hide notifier if it was attached previously
            // but errorCount was cleared or it was disabled
            if ($span) {
                $span.parent().hide();
            }
            return;
        }

        // update span if it was created before
        if ($span) {
            $span.text(errorCount).parent().show();
            return;
        }

        // create the span
        $span = $("<span>").text(errorCount);
        $("<div>")
            .attr("id", "error-counter")
            .attr("title", Strings.CMD_SHOW_DEV_TOOLS + "\u2026")
            .text(Strings.ERRORS + ": ")
            .append($span)
            .on("click", handleClick)
            .insertBefore("#status-bar .spinner");
    }

    var blink = _.debounce(function () {
        AnimationUtils.animateUsingClass($span.parent()[0], "flash", 1500);
    }, 100);

    function incErrorCount() {
        errorCount++;
        blink();
        refreshIndicator();
    }

    function clearErrorCount() {
        errorCount = 0;
        refreshIndicator();
    }

    function attachFunctions() {
        if (_attached) {
            return;
        }

        _attached      = true;
        _windowOnError = window.onerror;
        _consoleError  = window.console.error;
        _consoleClear  = window.console.clear;

        // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror
        window.onerror = function (errorMsg, url, lineNumber) {
            incErrorCount();
            if (_windowOnError) {
                return _windowOnError(errorMsg, url, lineNumber);
            }
            // return false means that we didn't handle this error and it should run the default handler
            return false;
        };

        window.console.error = function () {
            incErrorCount();
            return _consoleError.apply(window.console, arguments);
        };

        window.console.clear = function () {
            clearErrorCount();
            return _consoleClear.apply(window.console, arguments);
        };
    }

    function detachFunctions() {
        if (!_attached) {
            return;
        }

        _attached            = false;
        window.onerror       = _windowOnError;
        window.console.error = _consoleError;
        window.console.clear = _consoleClear;
    }

    function toggle(bool) {
        if (bool) {
            attachFunctions();
        } else {
            detachFunctions();
        }
        refreshIndicator();
    }

    // Public API
    exports.toggle = toggle;

});