<commit_before>
/**
 * Walrus Framework
 * File maintained by: Nicolas Beauvais (E-Wok)
 * Created: 07:51 21/01/14.
 */

var Walrus = {};

(function (Walrus) {

    'use strict';

    Walrus.catchLinks = function (event) {

        var elem,
            attributes,
            attribute,
            treeExplorer;

        elem = event.srcElement;
        treeExplorer = 1;

        for (treeExplorer; treeExplorer > 0; treeExplorer -= 1) {//fake faster while

            //handle body, html, document
            if (elem === null) { break; }

            //if we found a link
            if (elem.localName === 'a') {

                attributes = elem.attributes;

                for (attribute in attributes) {
                    if (attributes.hasOwnProperty(attribute)) {

                        attribute = attributes[attribute];
                        if (attribute.localName === 'href') {
                            if (Walrus.isntExternal(attribute.value)) {
                                Walrus.ajaxNavigation(event, attribute.value);
                                break;
                            } else { return; }

                        }
                        return;
                    }
                }

            } else {
                elem = elem.parentNode;
                treeExplorer += 1;
            }
        }

        event.preventDefault();
    };

    Walrus.isntExternal = function (url) {
        var local = location.href.replace(/^((https?:)?\/\/)?(www\.)?(\.)?/gi, '').split('/')[0];
        url = url.replace(/^((https?:)?\/\/)?(www\.)?(\.)?/gi, '').split('/')[0];
        return local === (url === '' ? local : url);
    };

    Walrus.ajaxNavigation = function (event, url) {
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.send();

        request.onload = function () {
            var resp,
                node,
                container,
                allChilds,
                i;

            document.getElementById('container').innerHTML = '';

            resp = this.response;
            node = document.createElement('div');
            node.innerHTML = resp;

            document.title = node.getElementsByTagName('title')[0].innerText;
            window.history.pushState({"html": resp.innerHTML, "pageTitle": document.title}, '', document.URL += url);

            allChilds = node.childNodes;
            i = allChilds.length - 1;

            for (i; i > 0; i -= 1) {
                if (allChilds[i].id && allChilds[i].id === "container") { container = allChilds[i]; }
            }

            document.getElementById('container').innerHTML = container.innerHTML;
            event.preventDefault();
        };
    };

    //Event Listener
    document.onclick = Walrus.catchLinks;

})(Walrus);<commit_msg>Walrus.js: fix JSLint error<commit_after>
/**
 * Walrus Framework
 * File maintained by: Nicolas Beauvais (E-Wok)
 * Created: 07:51 21/01/14.
 */

var Walrus = {};

(function (Walrus) {

    'use strict';

    Walrus.catchLinks = function (event) {

        var elem,
            attributes,
            attribute,
            treeExplorer;

        elem = event.srcElement;
        treeExplorer = 1;

        for (treeExplorer; treeExplorer > 0; treeExplorer -= 1) {//fake faster while

            //handle body, html, document
            if (elem === null) { break; }

            //if we found a link
            if (elem.localName === 'a') {

                attributes = elem.attributes;

                for (attribute in attributes) {
                    if (attributes.hasOwnProperty(attribute)) {

                        attribute = attributes[attribute];
                        if (attribute.localName === 'href') {
                            if (Walrus.isntExternal(attribute.value)) {
                                Walrus.ajaxNavigation(event, attribute.value);
                                break;
                            } else { return; }

                        }
                        return;
                    }
                }

            } else {
                elem = elem.parentNode;
                treeExplorer += 1;
            }
        }

        event.preventDefault();
    };

    Walrus.isntExternal = function (url) {
        var local = location.href.replace(/^((https?:)?\/\/)?(www\.)?(\.)?/gi, '').split('/')[0];
        url = url.replace(/^((https?:)?\/\/)?(www\.)?(\.)?/gi, '').split('/')[0];
        return local === (url === '' ? local : url);
    };

    Walrus.ajaxNavigation = function (event, url) {
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.send();

        request.onload = function () {
            var resp,
                node,
                container,
                allChilds,
                i;

            document.getElementById('container').innerHTML = '';

            resp = this.response;
            node = document.createElement('div');
            node.innerHTML = resp;

            document.title = node.getElementsByTagName('title')[0].innerText;
            window.history.pushState({"html": resp.innerHTML, "pageTitle": document.title}, '', url);

            allChilds = node.childNodes;
            i = allChilds.length - 1;

            for (i; i > 0; i -= 1) {
                if (allChilds[i].id && allChilds[i].id === "container") { container = allChilds[i]; }
            }

            document.getElementById('container').innerHTML = container.innerHTML;
            event.preventDefault();
        };
    };

    //Event Listener
    document.onclick = Walrus.catchLinks;

}(Walrus));<|endoftext|>


<commit_before>//  cordova-plugin-document-viewer
//
//  Created by Felix Schauerte 25.09.2014
//
//  Copyright 2015 sitewaerts GmbH. All rights reserved.
//  MIT Licensed

/*  configuration   */

var JS_HANDLE = "SitewaertsDocumentViewer";
var CDV_HANDLE = "SitewaertsDocumentViewer";

var CDV_HANDLE_ACTIONS = {

    GET_SUPPORT_INFO: "getSupportInfo",

    CAN_VIEW: "canViewDocument",

    VIEW_DOCUMENT: "viewDocument",

    INSTALL_VIEWER_APP: "install"
};

var exec = require('cordova/exec');

/*  private functions (not accessible via plugin API) */

function getOptions(provided)
{
    var options = provided || {};

    if (!options.documentView)
        options.documentView = {};
    if (!options.documentView.closeLabel)
        options.documentView.closeLabel = "Done";

    if (!options.navigationView)
        options.navigationView = {};
    if (!options.navigationView.closeLabel)
        options.navigationView.closeLabel = "Back";

    if (!options.email)
        options.email = {};
    if (!options.email.enabled)
        options.email.enabled = false;

    if (!options.print)
        options.print = {};
    if (!options.print.enabled)
        options.print.enabled = false;

    if (!options.openWith)
        options.openWith = {};
    if (!options.openWith.enabled)
        options.openWith.enabled = false;

    if (!options.bookmarks)
        options.bookmarks = {};
    if (!options.bookmarks.enabled)
        options.bookmarks.enabled = false;

    if (!options.search)
        options.search = {};
    if (!options.search.enabled)
        options.search.enabled = false;

    if (!options.android)
        options.android = {};
    if (!options.android.viewerAppPackage)
        options.android.viewerAppPackage = 'de.sitewaerts.cleverdox.viewer';
    if (!options.android.viewerAppActivity)
        options.android.viewerAppActivity = 'DocumentViewerActivity';

    return options;
}

function installApp(options, onSuccess, onError)
{
    var errorPrefix = "Error in " + JS_HANDLE + ".installApp(): ";
    try
    {
        options = getOptions(options);
        exec(
                onSuccess,
                function (err)
                {
                    window.console.log(errorPrefix + JSON.stringify(err));
                    if (onError)
                        onError(err);
                },
                CDV_HANDLE,
                CDV_HANDLE_ACTIONS.INSTALL_VIEWER_APP,
                [
                    {options: options}
                ]
        );
    }
    catch (e)
    {
        window.console.log(errorPrefix + JSON.stringify(e));
        if (onError)
            onError(e);
    }
}

/*  public API of the plugin    */

var SitewaertsDocumentViewer = {

    getSupportInfo: function (onSuccess, onError)
    {
        var errorPrefix = "Error in " + JS_HANDLE + ".getSupportInfo(): ";
        try
        {
            exec(
                    function (result)
                    {
                        if (onSuccess)
                        {
                            window.console.log("support info is "
                                    + JSON.stringify(result));
                            onSuccess(result);
                        }
                    },
                    function (err)
                    {
                        window.console.log(errorPrefix,  err);
                        if (onError)
                        {
                            onError(err);
                        }
                    },
                    CDV_HANDLE,
                    CDV_HANDLE_ACTIONS.GET_SUPPORT_INFO,
                    []
            );
        }
        catch (e)
        {
            window.console.log(errorPrefix + JSON.stringify(e));
            if (onError)
            {
                onError(e);
            }
        }

    },

    canViewDocument: function (url, contentType, options, onPossible, onMissingApp, onImpossible, onError)
    {
        var errorPrefix = "Error in " + JS_HANDLE + ".canViewDocument(): ";
        try
        {
            options = getOptions(options);

            exec(
                    function (result)
                    {
                        var status = result ? result.status : null;

                        if (status == 1)
                        {
                            if (onPossible)
                                onPossible();
                        }
                        else if (result.missingAppId != null)
                        {
                            if (onMissingApp)
                            {
                                var appId = result.missingAppId;
                                onMissingApp(appId,
                                        function (onSuccess, onError)
                                        {
                                            installApp(
                                                    options, onSuccess, onError
                                            );
                                        });
                            }
                        }
                        else
                        {
                            if (onImpossible)
                                onImpossible();
                        }
                    },
                    function (err)
                    {
                        window.console.log(errorPrefix, err);
                        if (onError)
                            onError(err);
                    },
                    CDV_HANDLE,
                    CDV_HANDLE_ACTIONS.CAN_VIEW,
                    [
                        {url: url, contentType: contentType, options: options}
                    ]
            );
        }
        catch (e)
        {
            window.console.log(errorPrefix, e);
            if (onError)
                onError(e);
        }
    },

    viewDocument: function (url, contentType, options, onShow, onClose, onMissingApp, onError)
    {
        var me = this;
        var errorPrefix = "Error in " + JS_HANDLE + ".viewDocument(): ";
        try
        {
            options = getOptions(options);

            if (!options.title)
                options.title = url.split('/').pop(); // strip file name from url

            this.canViewDocument(
                    url,
                    contentType,
                    options,
                    function ()
                    {
                        exec(
                                function (result)
                                {
                                    var status = result ? result.status : null;

                                    if (status == 1)
                                    {
                                        if (onShow)
                                            onShow();
                                    }
                                    else if (status == 0)
                                    {
                                        if (onClose)
                                            onClose();
                                    }
                                    else
                                    {
                                        var errorMsg =
                                                "unknown state '" + status
                                                        + "'";
                                        window.console.log(
                                                errorPrefix + errorMsg);
                                    }
                                },
                                function (err)
                                {
                                    window.console.log(errorPrefix, err);
                                    if (onError)
                                        onError(err);
                                },
                                CDV_HANDLE,
                                CDV_HANDLE_ACTIONS.VIEW_DOCUMENT,
                                [
                                    {url: url, contentType: contentType, options: options}
                                ]
                        );
                    },
                    function (appId, installer)
                    {
                        if (onMissingApp)
                            onMissingApp(appId, installer);
                        else
                            installer(function ()
                            {
                                window.console.log("App successfully installed");
                            }, onError);
                    },
                    function ()
                    {
                        var errorMsg = "No viewer for " + contentType;
                        window.console.log(errorPrefix + errorMsg);
                        if (onError)
                            onError(errorMsg);
                    },
                    onError
            );

        }
        catch (e)
        {
            window.console.log(errorPrefix, e);
            if (onError)
                onError(e);
        }
    }
};

module.exports = SitewaertsDocumentViewer;

<commit_msg>better error message<commit_after>//  cordova-plugin-document-viewer
//
//  Created by Felix Schauerte 25.09.2014
//
//  Copyright 2015 sitewaerts GmbH. All rights reserved.
//  MIT Licensed

/*  configuration   */

var JS_HANDLE = "SitewaertsDocumentViewer";
var CDV_HANDLE = "SitewaertsDocumentViewer";

var CDV_HANDLE_ACTIONS = {

    GET_SUPPORT_INFO: "getSupportInfo",

    CAN_VIEW: "canViewDocument",

    VIEW_DOCUMENT: "viewDocument",

    INSTALL_VIEWER_APP: "install"
};

var exec = require('cordova/exec');

/*  private functions (not accessible via plugin API) */

function getOptions(provided)
{
    var options = provided || {};

    if (!options.documentView)
        options.documentView = {};
    if (!options.documentView.closeLabel)
        options.documentView.closeLabel = "Done";

    if (!options.navigationView)
        options.navigationView = {};
    if (!options.navigationView.closeLabel)
        options.navigationView.closeLabel = "Back";

    if (!options.email)
        options.email = {};
    if (!options.email.enabled)
        options.email.enabled = false;

    if (!options.print)
        options.print = {};
    if (!options.print.enabled)
        options.print.enabled = false;

    if (!options.openWith)
        options.openWith = {};
    if (!options.openWith.enabled)
        options.openWith.enabled = false;

    if (!options.bookmarks)
        options.bookmarks = {};
    if (!options.bookmarks.enabled)
        options.bookmarks.enabled = false;

    if (!options.search)
        options.search = {};
    if (!options.search.enabled)
        options.search.enabled = false;

    if (!options.android)
        options.android = {};
    if (!options.android.viewerAppPackage)
        options.android.viewerAppPackage = 'de.sitewaerts.cleverdox.viewer';
    if (!options.android.viewerAppActivity)
        options.android.viewerAppActivity = 'DocumentViewerActivity';

    return options;
}

function installApp(options, onSuccess, onError)
{
    var errorPrefix = "Error in " + JS_HANDLE + ".installApp(): ";
    try
    {
        options = getOptions(options);
        exec(
                onSuccess,
                function (err)
                {
                    window.console.log(errorPrefix + JSON.stringify(err));
                    if (onError)
                        onError(err);
                },
                CDV_HANDLE,
                CDV_HANDLE_ACTIONS.INSTALL_VIEWER_APP,
                [
                    {options: options}
                ]
        );
    }
    catch (e)
    {
        window.console.log(errorPrefix + JSON.stringify(e));
        if (onError)
            onError(e);
    }
}

/*  public API of the plugin    */

var SitewaertsDocumentViewer = {

    getSupportInfo: function (onSuccess, onError)
    {
        var errorPrefix = "Error in " + JS_HANDLE + ".getSupportInfo(): ";
        try
        {
            exec(
                    function (result)
                    {
                        if (onSuccess)
                        {
                            window.console.log("support info is "
                                    + JSON.stringify(result));
                            onSuccess(result);
                        }
                    },
                    function (err)
                    {
                        window.console.log(errorPrefix,  err);
                        if (onError)
                        {
                            onError(err);
                        }
                    },
                    CDV_HANDLE,
                    CDV_HANDLE_ACTIONS.GET_SUPPORT_INFO,
                    []
            );
        }
        catch (e)
        {
            window.console.log(errorPrefix + JSON.stringify(e));
            if (onError)
            {
                onError(e);
            }
        }

    },

    canViewDocument: function (url, contentType, options, onPossible, onMissingApp, onImpossible, onError)
    {
        var errorPrefix = "Error in " + JS_HANDLE + ".canViewDocument(): ";
        try
        {
            options = getOptions(options);

            exec(
                    function (result)
                    {
                        var status = result ? result.status : null;

                        if (status == 1)
                        {
                            if (onPossible)
                                onPossible();
                        }
                        else if (result.missingAppId != null)
                        {
                            if (onMissingApp)
                            {
                                var appId = result.missingAppId;
                                onMissingApp(appId,
                                        function (onSuccess, onError)
                                        {
                                            installApp(
                                                    options, onSuccess, onError
                                            );
                                        });
                            }
                        }
                        else
                        {
                            if (onImpossible)
                                onImpossible();
                        }
                    },
                    function (err)
                    {
                        window.console.log(errorPrefix, err);
                        if (onError)
                            onError(err);
                    },
                    CDV_HANDLE,
                    CDV_HANDLE_ACTIONS.CAN_VIEW,
                    [
                        {url: url, contentType: contentType, options: options}
                    ]
            );
        }
        catch (e)
        {
            window.console.log(errorPrefix, e);
            if (onError)
                onError(e);
        }
    },

    viewDocument: function (url, contentType, options, onShow, onClose, onMissingApp, onError)
    {
        var me = this;
        var errorPrefix = "Error in " + JS_HANDLE + ".viewDocument(): ";
        try
        {
            options = getOptions(options);

            if (!options.title)
                options.title = url.split('/').pop(); // strip file name from url

            this.canViewDocument(
                    url,
                    contentType,
                    options,
                    function ()
                    {
                        exec(
                                function (result)
                                {
                                    var status = result ? result.status : null;

                                    if (status == 1)
                                    {
                                        if (onShow)
                                            onShow();
                                    }
                                    else if (status == 0)
                                    {
                                        if (onClose)
                                            onClose();
                                    }
                                    else
                                    {
                                        var errorMsg =
                                                "unknown state '" + status
                                                        + "'";
                                        window.console.log(
                                                errorPrefix + errorMsg);
                                    }
                                },
                                function (err)
                                {
                                    window.console.log(errorPrefix, err);
                                    if (onError)
                                        onError(err);
                                },
                                CDV_HANDLE,
                                CDV_HANDLE_ACTIONS.VIEW_DOCUMENT,
                                [
                                    {url: url, contentType: contentType, options: options}
                                ]
                        );
                    },
                    function (appId, installer)
                    {
                        if (onMissingApp)
                            onMissingApp(appId, installer);
                        else
                            installer(function ()
                            {
                                window.console.log("App successfully installed");
                            }, onError);
                    },
                    function ()
                    {
                        var errorMsg = "invalid file url '" + url + "' or no viewer for mime type '" + contentType + "'";
                        window.console.log(errorPrefix + errorMsg);
                        if (onError)
                            onError(errorMsg);
                    },
                    onError
            );

        }
        catch (e)
        {
            window.console.log(errorPrefix, e);
            if (onError)
                onError(e);
        }
    }
};

module.exports = SitewaertsDocumentViewer;

<|endoftext|>


<commit_before>"use strict";
var SFX;

/**
 * Renderer of simple SFX on the map.
 */
SFX = function () {
    var canvas, map, canvasWidth, canvasHeight, tileWidth, tileHeight, context,
            canvasTileWidth, canvasTileHeight, depthFactor, canvasCenterX,
            canvasCenterY, buildingsIndex, displayLightSFX,
            displayBuildableTiles, displayTileOverlay, enableBuildOverlay,
            displayNavigableTiles, navigationIndex, enableNavigationIndex,
            inaccessibleColor, accessibleColor;

    depthFactor = Settings.sfx3DLightFactor;
    accessibleColor = Settings.sfxAccessibleTileColor;
    inaccessibleColor = Settings.sfxInaccessibleTileColor;
    enableBuildOverlay = false;
    enableNavigationIndex = false;

    /**
     * Sets the output canvas for rendering.
     *
     * @param {HTMLCavansElement} newCanvas New output canvas for rendering.
     */
    this.setCanvas = function (newCanvas) {
        canvas = newCanvas;
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        context = canvas.getContext('2d');
        context.strokeStyle = Settings.sfx3DLightColor;
        context.lineCap = 'round';
        canvasCenterX = canvasWidth / 2;
        canvasCenterY = canvasHeight / 2;
    };

    /**
     * Sets the current map of which SFX should be renderer.
     *
     * @param {Map} newMap The map for rendering. The method also accepts raw
     *        map data.
     */
    this.setMap = function (newMap) {
        if (!canvas) {
            throw new Error("cannot set map for SFX before canvas!");
        }
        map = newMap.getMap();
        tileWidth = TilesDefinition.getType(0).imageData.width - 1;
        tileHeight = TilesDefinition.getType(0).imageData.height / 2 - 1;
        canvasTileWidth = Math.ceil(canvasWidth / tileWidth);
        canvasTileHeight = Math.ceil(canvasHeight / tileHeight);
        buildingsIndex = newMap.getBuildingsIndex();
        navigationIndex = newMap.getNavigationIndex();
    };

    /**
     * Set whether or not the SFX renderer should display an overlay over the
     * buildings to signal that those tiles cannot be used for placing other
     * buildings.
     *
     * @param {Boolean} displayBuildableOverlay When set to true, the SFX
     *        renderer will display an overlay over the buildings.
     */
    this.setDisplayBuildableOverlay = function (displayBuildableOverlay) {
        enableBuildOverlay = displayBuildableOverlay;
    };

    this.setDisplayNavigationIndex = function (displayNavigationIndex) {
        enableNavigationIndex = displayNavigationIndex;
    };

    /**
     * Displays the SFX of the map on the chosen offset on the provided
     * canvas.
     *
     * @param {Number} x X offset for rendering.
     * @param {Number} y Y offset for rendering.
     */
    this.display = function (x, y) {
        context.globalAlpha = 0.3;
        displayLightSFX(x, y);
        enableBuildOverlay && displayBuildableTiles(x, y);
        enableNavigationIndex && displayNavigableTiles(x, y);
        context.globalAlpha = 1;
    };

    displayLightSFX = function (x, y) {
        var mapOffsetX, mapOffsetY, i, j, offsetX, offsetY, shiftX, endX, endY,
                mapRow, mapTile;
        y -= tileHeight;
        x -= tileWidth / 2;
        mapOffsetX = Math.floor(x / tileWidth);
        mapOffsetY = Math.floor(y / tileHeight);
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = map[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                if (!mapTile || !mapTile.lightSfx) {
                   continue;
                }
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                endX = offsetX + (offsetX - canvasCenterX) / depthFactor;
                endY = offsetY + (offsetY - canvasCenterY) / depthFactor;
                context.lineWidth = mapTile.lightSfx;
                context.beginPath();
                context.moveTo(offsetX, offsetY);
                context.lineTo(endX, endY);
                context.stroke();
            }
        }
    };

    displayBuildableTiles = function (x, y) {
        var mapOffsetX, mapOffsetY, i, j, mapRow, offsetY, shiftX, mapTile,
                offsetX;
        context.fillStyle = Settings.sfxBuildLayerColor;
        mapOffsetX = Math.floor(x / tileWidth) - 1;
        mapOffsetY = Math.floor(y / tileHeight) - 1;
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = buildingsIndex[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                if (!mapTile) {
                    continue;
                }
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                displayTileOverlay(offsetX, offsetY);
            }
        }
    };

    displayTileOverlay = function (x, y) {
        context.beginPath();
        context.moveTo(x + (tileWidth / 2), y);
        context.lineTo(x + tileWidth, y + tileHeight);
        context.lineTo(x + (tileWidth / 2), y + (tileHeight * 2));
        context.lineTo(x, y + tileHeight);
        context.fill();
    };

    displayNavigableTiles = function (x, y) {
        var mapOffsetX, mapOffsetY, i, j, mapRow, offsetY, shiftX, mapTile,
                offsetX;
        mapOffsetX = Math.floor(x / tileWidth) - 1;
        mapOffsetY = Math.floor(y / tileHeight) - 1;
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = navigationIndex[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                context.fillStyle = mapTile ? accessibleColor :
                        inaccessibleColor;
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                displayTileOverlay(offsetX, offsetY);
            }
        }
    };
};
<commit_msg>updated documentation and code conventions<commit_after>"use strict";
var SFX;

/**
 * Renderer of simple SFX on the map.
 */
SFX = function () {
    var canvas, map, canvasWidth, canvasHeight, tileWidth, tileHeight, context,
            canvasTileWidth, canvasTileHeight, depthFactor, canvasCenterX,
            canvasCenterY, buildingsIndex, displayLightSFX,
            displayBuildableTiles, enableBuildOverlay, navigationIndex,
            enableNavigationIndex, inaccessibleColor, accessibleColor;

    depthFactor = Settings.sfx3DLightFactor;
    accessibleColor = Settings.sfxAccessibleTileColor;
    inaccessibleColor = Settings.sfxInaccessibleTileColor;
    enableBuildOverlay = false;
    enableNavigationIndex = false;

    /**
     * Sets the output canvas for rendering.
     *
     * @param {HTMLCavansElement} newCanvas New output canvas for rendering.
     */
    this.setCanvas = function (newCanvas) {
        canvas = newCanvas;
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        context = canvas.getContext('2d');
        context.strokeStyle = Settings.sfx3DLightColor;
        context.lineCap = 'round';
        canvasCenterX = canvasWidth / 2;
        canvasCenterY = canvasHeight / 2;
    };

    /**
     * Sets the current map of which SFX should be renderer.
     *
     * @param {Map} newMap The map for rendering. The method also accepts raw
     *        map data.
     */
    this.setMap = function (newMap) {
        if (!canvas) {
            throw new Error("cannot set map for SFX before canvas!");
        }
        map = newMap.getMap();
        tileWidth = TilesDefinition.getType(0).imageData.width - 1;
        tileHeight = TilesDefinition.getType(0).imageData.height / 2 - 1;
        canvasTileWidth = Math.ceil(canvasWidth / tileWidth);
        canvasTileHeight = Math.ceil(canvasHeight / tileHeight);
        buildingsIndex = newMap.getBuildingsIndex();
        navigationIndex = newMap.getNavigationIndex();
    };

    /**
     * Set whether or not the SFX renderer should display an overlay over the
     * buildings to signal that those tiles cannot be used for placing other
     * buildings.
     *
     * @param {Boolean} displayBuildableOverlay When set to true, the SFX
     *        renderer will display an overlay over the buildings.
     */
    this.setDisplayBuildableOverlay = function (displayBuildableOverlay) {
        enableBuildOverlay = displayBuildableOverlay;
    };

    /**
     * Enables or disables the rendering of the navigation index over the UI.
     * The navigation index will show which tiles can be navigated by units
     * (are not occupied by another unit or a building).
     *
     * @param {Boolean} displayNavigationIndex true if the
     *        navigation display should be visible.
     */
    this.setDisplayNavigationIndex = function (displayNavigationIndex) {
        enableNavigationIndex = displayNavigationIndex;
    };

    /**
     * Displays the SFX of the map on the chosen offset on the provided
     * canvas.
     *
     * @param {Number} x X offset for rendering.
     * @param {Number} y Y offset for rendering.
     */
    this.display = function (x, y) {
        context.globalAlpha = 0.3;
        displayLightSFX(x, y);
        enableBuildOverlay && displayBuildableTiles(x, y);
        enableNavigationIndex && displayNavigableTiles(x, y);
        context.globalAlpha = 1;
    };

    /**
     * Displays a 3D-like light beams emmanating from the map's surface.
     *
     * @param {Number} x  The horizonat offset of the camera from the map's top
     *        left corner in pixels.
     * @param {Number} y The vertical offset of the camera from the map's top
     *        left corner in pixels.
     */
    function displayLightSFX(x, y) {
        var mapOffsetX, mapOffsetY, i, j, offsetX, offsetY, shiftX, endX, endY,
                mapRow, mapTile;
        y -= tileHeight;
        x -= tileWidth / 2;
        mapOffsetX = Math.floor(x / tileWidth);
        mapOffsetY = Math.floor(y / tileHeight);
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = map[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                if (!mapTile || !mapTile.lightSfx) {
                   continue;
                }
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                endX = offsetX + (offsetX - canvasCenterX) / depthFactor;
                endY = offsetY + (offsetY - canvasCenterY) / depthFactor;
                context.lineWidth = mapTile.lightSfx;
                context.beginPath();
                context.moveTo(offsetX, offsetY);
                context.lineTo(endX, endY);
                context.stroke();
            }
        }
    }

    /**
     * Displays the overlay showing which tiles are occupied by buildings and
     * which are still free for building construction.
     *
     * @param {Number} x  The horizonat offset of the camera from the map's top
     *        left corner in pixels.
     * @param {Number} y The vertical offset of the camera from the map's top
     *        left corner in pixels.
     */
    function displayBuildableTiles(x, y) {
        var mapOffsetX, mapOffsetY, i, j, mapRow, offsetY, shiftX, mapTile,
                offsetX;
        context.fillStyle = Settings.sfxBuildLayerColor;
        mapOffsetX = Math.floor(x / tileWidth) - 1;
        mapOffsetY = Math.floor(y / tileHeight) - 1;
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = buildingsIndex[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                if (!mapTile) {
                    continue;
                }
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                displayTileOverlay(offsetX, offsetY);
            }
        }
    }

    /**
     * Displays an overlay over a single map tile at the specified coordinates.
     * The tile will be overlayed using a polygon filled with the current fill
     * style.
     *
     * @param {Number} x The horizontal offset of the tile's position from the
     *        map's top left cornenr.
     * @param {type} y The vertical offset of the tile's position from the
     *        map's top left corner.
     */
    function displayTileOverlay(x, y) {
        context.beginPath();
        context.moveTo(x + (tileWidth / 2), y);
        context.lineTo(x + tileWidth, y + tileHeight);
        context.lineTo(x + (tileWidth / 2), y + (tileHeight * 2));
        context.lineTo(x, y + tileHeight);
        context.fill();
    }

    /**
     * Displays the overlay showing which tiles are navigable by units
     * (accessible for unit movement).
     *
     * @param {Number} x The horizonat offset of the camera from the map's top
     *        left corner in pixels.
     * @param {Number} y The vertical offset of the camera from the map's top
     *        left corner in pixels.
     */
    function displayNavigableTiles(x, y) {
        var mapOffsetX, mapOffsetY, i, j, mapRow, offsetY, shiftX, mapTile,
                offsetX;
        mapOffsetX = Math.floor(x / tileWidth) - 1;
        mapOffsetY = Math.floor(y / tileHeight) - 1;
        for (j = canvasTileHeight + 2; j--;) {
            mapRow = navigationIndex[j + mapOffsetY];
            if (!mapRow) {
                continue;
            }
            offsetY = (j + mapOffsetY) * tileHeight - y;
            shiftX = ((mapOffsetY + j) % 2) * tileWidth / 2;
            for (i = canvasTileWidth + 2; i--;) {
                mapTile = mapRow[i + mapOffsetX];
                context.fillStyle = mapTile ? accessibleColor :
                        inaccessibleColor;
                offsetX = (i + mapOffsetX) * tileWidth + shiftX - x;
                displayTileOverlay(offsetX, offsetY);
            }
        }
    }
};
<|endoftext|>


<commit_before>(function (define) {
define(function (require) {
	"use strict";

	var mapTokenList, replaceClasses, functional;

	mapTokenList = require('./mapTokenList');
	replaceClasses = require('./replaceClasses');
	functional = require('../../lib/functional');

	return function(map, options) {
		return functional.compose(
			mapTokenList(map, options),
			replaceClasses(options)
		);
	}

});
}(
	typeof define == 'function' && define.amd
		? define
		: function (factory) { module.exports = factory(require); }
));<commit_msg>updated mapClasses updated mapClasses to support more flavors of options and reuse options.map as options.group if the group isn't specified. needs tests!<commit_after>(function (define) {
define(function (require) {
"use strict";

	var mapTokenList, replaceClasses;

	mapTokenList = require('./mapTokenList');
	replaceClasses = require('./replaceClasses');

	return function (options) {
		var mapper, replacer;

		if (!options.group) options.group = mapToGroup(options.map);

		mapper = mapTokenList(options.map, options);
		replacer = replaceClasses(options);

		return options.node
			? function (val) { return replacer(mapper(val)); }
			: function (node, val) { return replacer(node, mapper(val)); };
	};

	function mapToGroup (map) {
		return Object.keys(map).reduce(function (group, p) {
			var str = '' + map[p];
			if (str) group.push(str);
			return group;
		}, []);
	}

});
}(
	typeof define == 'function' && define.amd
		? define
		: function (factory) { module.exports = factory(require); }
));<|endoftext|>


<commit_before>"use strict";
function DontYouFillItCanvasGui(game, canvasID) {
	var PlayPauseButton = {
		draw: function() {
			ctx.fillStyle = 'white';
			ctx.fillRect(canvas.width - Math.floor(SCALE / 6 * 0.9),
			             Math.floor(SCALE / 6 * 0.1),
			             Math.floor(SCALE / 6 * 0.3),
			             Math.floor(SCALE / 6 * 0.8));
			ctx.fillRect(canvas.width - Math.floor(SCALE / 6 * 0.4),
			             Math.floor(SCALE / 6 * 0.1),
			             Math.floor(SCALE / 6 * 0.3),
			             Math.floor(SCALE / 6 * 0.8));
		},
		handleClick: function(x, y) {
			var xm = canvas.width - SCALE / 6,
			    xM = canvas.width,
			    ym = 0,
			    yM = SCALE / 6;

			if((x > xm) && (x <= xM) && (y > ym) && (y <= yM)) {
				if(game.state == game.RUNNING()) {
					game.pause();
					setScreenVisible(pauseScreen, 1);
				}

				return true;
			}

			return false;
		}
	};

	function drawCannon() {
		var r = Math.round(CANNON_BASE_WIDTH / 2);

		ctx.fillStyle = 'white';
		ctx.beginPath();
		ctx.moveTo(Math.round(SCALE / 2) - r,
		           Math.round(BOTTOM_BORDER + SCALE / 6));
		ctx.lineTo(Math.round(SCALE / 2) - r,
		           Math.round(BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT));
		ctx.arc(
		    Math.round(SCALE / 2),
		    Math.round(BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT),
		    r,
		    Math.PI,
		    0);
		ctx.lineTo(Math.round(SCALE / 2) + r,
		           Math.round(BOTTOM_BORDER + SCALE / 6));
		ctx.closePath();
		ctx.fill();

		ctx.lineWidth = CANNON_WIDTH;
		ctx.lineCap = 'butt';
		ctx.beginPath();
		ctx.moveTo(SCALE / 2,
		           BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT);
		ctx.lineTo(SCALE / 2 + Math.cos(game.cannon.getAngle()) * CANNON_LENGTH,
		           BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT - Math.sin(game.cannon.getAngle()) * CANNON_LENGTH);
		ctx.closePath();
		ctx.stroke();
	};

	function drawBall(ball) {
		var x = LEFT_BORDER + ball.nx * SCALE,
		    y = BOTTOM_BORDER - ball.ny * SCALE,
		    r = ball.nr * SCALE;

		ctx.fillStyle = 'white';
		ctx.lineWidth = 1;
		ctx.beginPath();
		ctx.arc(x, y, r, 0, Math.PI*2, false);

		if(ball.counter == 1) {
			ctx.moveTo(x - r * 0.2, y - r * 0.7);
			ctx.lineTo(x - r * 0.2, y + r * 0.7);
			ctx.lineTo(x + r * 0.2, y + r * 0.7);
			ctx.lineTo(x + r * 0.2, y - r * 0.7);
		} else if(ball.counter == 2) {
			ctx.moveTo(x - r * 0.5, y - r * 0.7);
			ctx.lineTo(x - r * 0.5, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.3);
			ctx.lineTo(x - r * 0.1, y + r * 0.3);
			ctx.lineTo(x - r * 0.1, y + r * 0.15);
			ctx.lineTo(x + r * 0.5, y + r * 0.15);
			ctx.lineTo(x + r * 0.5, y - r * 0.7);
		} else if(ball.counter == 3) {
			ctx.moveTo(x - r * 0.5, y - r * 0.7);
			ctx.lineTo(x - r * 0.5, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y + r * 0.15);
			ctx.lineTo(x + r * 0.1, y + r * 0.15);
			ctx.lineTo(x + r * 0.1, y + r * 0.3);
			ctx.lineTo(x - r * 0.5, y + r * 0.3);
			ctx.lineTo(x - r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y - r * 0.7);
		}
		ctx.closePath();
		ctx.fill();
	}

	function drawGame() {
		// Always add 0.5 to coordinates of lines of width 1
		// https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example
		ctx.strokeStyle = 'white';
		ctx.lineWidth = '1';
		ctx.beginPath();
		ctx.moveTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
		ctx.lineTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(TOP_BORDER) + 0.5);
		ctx.lineTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(TOP_BORDER) + 0.5);
		ctx.lineTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
		if(!ctx.setLineDash)
			ctx.closePath();
		ctx.stroke();

		// Android stock browser does not support setLineDash
		// (at least on version <= 4.1.2)
		if(ctx.setLineDash) {
			ctx.beginPath();
			ctx.setLineDash([5, 5]);
			ctx.moveTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
			ctx.lineTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
			ctx.stroke();
			ctx.setLineDash([]);
		}

		drawCannon(game.cannon);

		for(var i = 0; i < game.staticBalls.length; ++i)
			drawBall(game.staticBalls[i]);

		if(game.currentBall)
			drawBall(game.currentBall);

		PlayPauseButton.draw();

		ctx.textAlign = 'left';
		ctx.textBaseline = 'bottom';
		ctx.font = Math.floor(SCALE / 12) + 'px Arial';
		ctx.fillText('Highscore', LEFT_BORDER, TOP_BORDER - Math.floor(SCALE / 12) + Math.floor(SCALE / 120));
		ctx.fillText('Score', LEFT_BORDER, TOP_BORDER);

		var scoreOffset = ctx.measureText('Highscore ').width;
		ctx.fillText(game.highscore, LEFT_BORDER + scoreOffset, TOP_BORDER - Math.floor(SCALE / 12) + Math.floor(SCALE / 120));
		ctx.fillText(game.score, LEFT_BORDER + scoreOffset, TOP_BORDER);
	}

	function draw() {
		// clearRect doesn't work on android stock browser, fillRect is used instead
		// ctx.clearRect(0, 0, canvas.width, canvas.height);
		ctx.fillStyle = 'black';
		ctx.fillRect(0, 0, canvas.width, canvas.height);

		if(that.state == that.GAME) {
			drawGame();
		}
	}

	function step(time) {
		that.observable.notifyObservers('beginStep');

		if(game.state == game.RUNNING())
			game.update(time);

		draw();

		that.observable.notifyObservers('endStep');

		if(game.state == game.RUNNING()) {
			window.requestAnimationFrame(step);
		} else if(game.state == game.GAMEOVER()) {
			document.getElementById('gameoverScreenScoreMessage').style.display = (game.newHighscore ? 'none' : 'inline');
			document.getElementById('gameoverScreenHighscoreMessage').style.display = (game.newHighscore ? 'inline' : 'none');
			document.getElementById('gameoverScreenScore').innerHTML = game.score;
			setScreenVisible(gameoverScreen, 1);
		}
	}

	function handleTouch(evt) {
		evt.preventDefault();
		handleTouchOrClick(evt.touches[0].clientX, evt.touches[0].clientY);
	}

	function handleClick(evt) {
		evt.preventDefault();
		handleTouchOrClick(evt.clientX, evt.clientY);
	}

	function handleTouchOrClick(evx, evy) {
		if(Date.now() - lastClickDate < 500)
			return;

		lastClickDate = Date.now();

		var rect = canvas.getBoundingClientRect();
		var x = evx - rect.left,
		    y = evy - rect.top;

		if(PlayPauseButton.handleClick(x, y))
			return;

		if((game.currentBall == null) && (game.state == game.RUNNING())) {
			game.fire();
			return;
		}
	}

	function handleVisibilityChange() {
		if(document.hidden) {
			game.pause();
			setScreenVisible(pauseScreen, 1);
		}
	}

	function resizeCanvas() {
		computeGameDimensions();

		canvas.width = Math.floor(GAME_WIDTH);
		canvas.height = Math.floor(GAME_HEIGHT);
		canvas.style.left = Math.floor(H_OFFSET) + "px";
		canvas.style.top = Math.floor(V_OFFSET) + "px";

		// Redraw event when the game is not running
		if(game.state != game.RUNNING())
			window.requestAnimationFrame(step);
	}

	function computeGameDimensions() {
		var w = container.clientWidth, h = container.clientHeight;

		if(w / h < 3/4) {
			GAME_WIDTH = w;
			GAME_HEIGHT = 4/3 * GAME_WIDTH;
		} else {
			GAME_HEIGHT = h;
			GAME_WIDTH = 3/4 * GAME_HEIGHT;
		}

		SCALE              = GAME_WIDTH;
		V_OFFSET           = (h - GAME_HEIGHT) / 2;
		H_OFFSET           = (w - GAME_WIDTH) / 2;
		TOP_BORDER         = SCALE / 6;
		BOTTOM_BORDER      = TOP_BORDER + SCALE;
		LEFT_BORDER        = 0;
		RIGHT_BORDER       = LEFT_BORDER + SCALE;
		CANNON_BASE_WIDTH  = SCALE / 10;
		CANNON_BASE_HEIGHT = SCALE / 15;
		CANNON_LENGTH      = SCALE / 15;
		CANNON_WIDTH       = SCALE / 18;
	}

	function setScreenVisible(screen, zindex) {
		screen.style.zIndex = (zindex >= 0 ? zindex : -1);
		screen.scrollTop = 0;
		// Prevent flickering
		screen.style.display = (zindex >= 0 ? 'block' : 'none');
	}

	this.MENU = 1;
	this.GAME = 2;

	this.state = this.MENU;

	this.game = game;
	this.observable = new Observable();

	var      canvas = document.getElementById(canvasID),
	      container = canvas.parentNode,
	    startScreen = document.getElementById('startScreen'),
	    pauseScreen = document.getElementById('pauseScreen'),
	 gameoverScreen = document.getElementById('gameoverScreen'),
	  licenseScreen = document.getElementById('licenseScreen');

	document.getElementById('startScreenPlayButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.resume();
		that.state = that.GAME;
		window.requestAnimationFrame(step);
		setScreenVisible(startScreen, -1);
	});

	document.getElementById('pauseScreenContinueButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.resume();
		window.requestAnimationFrame(step);
		setScreenVisible(pauseScreen, -1);
	});

	document.getElementById('gameoverScreenPlayAgainButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.reset();
		window.requestAnimationFrame(step);
		setScreenVisible(gameoverScreen, -1);
	});

	document.getElementById('startScreenLicenseButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		setScreenVisible(licenseScreen, 2);
	});

	document.getElementById('licenseScreenBackButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		setScreenVisible(licenseScreen, -1);
	});

	var ctx = canvas.getContext('2d');

	var SCALE, GAME_WIDTH, GAME_HEIGHT, V_OFFSET, H_OFFSET,
	    BOTTOM_BORDER, TOP_BORDER, LEFT_BORDER, RIGHT_BORDER,
	    CANNON_BASE_WIDTH, CANNON_BASE_HEIGHT, CANNON_LENGTH, CANNON_WIDTH;

	var lastClickDate = 0;

	var that = this; // Allow to access this from the closure.

	window.addEventListener('resize', resizeCanvas, false);
	[canvas, container].forEach(function(e) {
		e.addEventListener('mousedown', handleClick, false);
		e.addEventListener('touchstart', handleTouch, false);
	});

	document.addEventListener('visibilitychange', handleVisibilityChange, false);

	resizeCanvas();

	window.requestAnimationFrame(step);
}

DontYouFillItCanvasGui.prototype.addObserver = function(o) {
	this.observable.addObserver(o);
};

DontYouFillItCanvasGui.prototype.removeObserver = function(o) {
	this.observable.removeObserver(o);
};

DontYouFillItCanvasGui.prototype.notifyObservers = function() {
	this.observable.notifyObservers();
};
<commit_msg>Prevent pause menu from appearing when visibility changes on the start menu<commit_after>"use strict";
function DontYouFillItCanvasGui(game, canvasID) {
	var PlayPauseButton = {
		draw: function() {
			ctx.fillStyle = 'white';
			ctx.fillRect(canvas.width - Math.floor(SCALE / 6 * 0.9),
			             Math.floor(SCALE / 6 * 0.1),
			             Math.floor(SCALE / 6 * 0.3),
			             Math.floor(SCALE / 6 * 0.8));
			ctx.fillRect(canvas.width - Math.floor(SCALE / 6 * 0.4),
			             Math.floor(SCALE / 6 * 0.1),
			             Math.floor(SCALE / 6 * 0.3),
			             Math.floor(SCALE / 6 * 0.8));
		},
		handleClick: function(x, y) {
			var xm = canvas.width - SCALE / 6,
			    xM = canvas.width,
			    ym = 0,
			    yM = SCALE / 6;

			if((x > xm) && (x <= xM) && (y > ym) && (y <= yM)) {
				if(game.state == game.RUNNING()) {
					game.pause();
					setScreenVisible(pauseScreen, 1);
				}

				return true;
			}

			return false;
		}
	};

	function drawCannon() {
		var r = Math.round(CANNON_BASE_WIDTH / 2);

		ctx.fillStyle = 'white';
		ctx.beginPath();
		ctx.moveTo(Math.round(SCALE / 2) - r,
		           Math.round(BOTTOM_BORDER + SCALE / 6));
		ctx.lineTo(Math.round(SCALE / 2) - r,
		           Math.round(BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT));
		ctx.arc(
		    Math.round(SCALE / 2),
		    Math.round(BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT),
		    r,
		    Math.PI,
		    0);
		ctx.lineTo(Math.round(SCALE / 2) + r,
		           Math.round(BOTTOM_BORDER + SCALE / 6));
		ctx.closePath();
		ctx.fill();

		ctx.lineWidth = CANNON_WIDTH;
		ctx.lineCap = 'butt';
		ctx.beginPath();
		ctx.moveTo(SCALE / 2,
		           BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT);
		ctx.lineTo(SCALE / 2 + Math.cos(game.cannon.getAngle()) * CANNON_LENGTH,
		           BOTTOM_BORDER + SCALE / 6 - CANNON_BASE_HEIGHT - Math.sin(game.cannon.getAngle()) * CANNON_LENGTH);
		ctx.closePath();
		ctx.stroke();
	};

	function drawBall(ball) {
		var x = LEFT_BORDER + ball.nx * SCALE,
		    y = BOTTOM_BORDER - ball.ny * SCALE,
		    r = ball.nr * SCALE;

		ctx.fillStyle = 'white';
		ctx.lineWidth = 1;
		ctx.beginPath();
		ctx.arc(x, y, r, 0, Math.PI*2, false);

		if(ball.counter == 1) {
			ctx.moveTo(x - r * 0.2, y - r * 0.7);
			ctx.lineTo(x - r * 0.2, y + r * 0.7);
			ctx.lineTo(x + r * 0.2, y + r * 0.7);
			ctx.lineTo(x + r * 0.2, y - r * 0.7);
		} else if(ball.counter == 2) {
			ctx.moveTo(x - r * 0.5, y - r * 0.7);
			ctx.lineTo(x - r * 0.5, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.3);
			ctx.lineTo(x - r * 0.1, y + r * 0.3);
			ctx.lineTo(x - r * 0.1, y + r * 0.15);
			ctx.lineTo(x + r * 0.5, y + r * 0.15);
			ctx.lineTo(x + r * 0.5, y - r * 0.7);
		} else if(ball.counter == 3) {
			ctx.moveTo(x - r * 0.5, y - r * 0.7);
			ctx.lineTo(x - r * 0.5, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.3);
			ctx.lineTo(x + r * 0.1, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y - r * 0.15);
			ctx.lineTo(x - r * 0.5, y + r * 0.15);
			ctx.lineTo(x + r * 0.1, y + r * 0.15);
			ctx.lineTo(x + r * 0.1, y + r * 0.3);
			ctx.lineTo(x - r * 0.5, y + r * 0.3);
			ctx.lineTo(x - r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y + r * 0.7);
			ctx.lineTo(x + r * 0.5, y - r * 0.7);
		}
		ctx.closePath();
		ctx.fill();
	}

	function drawGame() {
		// Always add 0.5 to coordinates of lines of width 1
		// https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example
		ctx.strokeStyle = 'white';
		ctx.lineWidth = '1';
		ctx.beginPath();
		ctx.moveTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
		ctx.lineTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(TOP_BORDER) + 0.5);
		ctx.lineTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(TOP_BORDER) + 0.5);
		ctx.lineTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
		if(!ctx.setLineDash)
			ctx.closePath();
		ctx.stroke();

		// Android stock browser does not support setLineDash
		// (at least on version <= 4.1.2)
		if(ctx.setLineDash) {
			ctx.beginPath();
			ctx.setLineDash([5, 5]);
			ctx.moveTo(Math.floor(RIGHT_BORDER) - 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
			ctx.lineTo(Math.floor(LEFT_BORDER) + 0.5, Math.floor(BOTTOM_BORDER) + 0.5);
			ctx.stroke();
			ctx.setLineDash([]);
		}

		drawCannon(game.cannon);

		for(var i = 0; i < game.staticBalls.length; ++i)
			drawBall(game.staticBalls[i]);

		if(game.currentBall)
			drawBall(game.currentBall);

		PlayPauseButton.draw();

		ctx.textAlign = 'left';
		ctx.textBaseline = 'bottom';
		ctx.font = Math.floor(SCALE / 12) + 'px Arial';
		ctx.fillText('Highscore', LEFT_BORDER, TOP_BORDER - Math.floor(SCALE / 12) + Math.floor(SCALE / 120));
		ctx.fillText('Score', LEFT_BORDER, TOP_BORDER);

		var scoreOffset = ctx.measureText('Highscore ').width;
		ctx.fillText(game.highscore, LEFT_BORDER + scoreOffset, TOP_BORDER - Math.floor(SCALE / 12) + Math.floor(SCALE / 120));
		ctx.fillText(game.score, LEFT_BORDER + scoreOffset, TOP_BORDER);
	}

	function draw() {
		// clearRect doesn't work on android stock browser, fillRect is used instead
		// ctx.clearRect(0, 0, canvas.width, canvas.height);
		ctx.fillStyle = 'black';
		ctx.fillRect(0, 0, canvas.width, canvas.height);

		if(that.state == that.GAME) {
			drawGame();
		}
	}

	function step(time) {
		that.observable.notifyObservers('beginStep');

		if(game.state == game.RUNNING())
			game.update(time);

		draw();

		that.observable.notifyObservers('endStep');

		if(game.state == game.RUNNING()) {
			window.requestAnimationFrame(step);
		} else if(game.state == game.GAMEOVER()) {
			document.getElementById('gameoverScreenScoreMessage').style.display = (game.newHighscore ? 'none' : 'inline');
			document.getElementById('gameoverScreenHighscoreMessage').style.display = (game.newHighscore ? 'inline' : 'none');
			document.getElementById('gameoverScreenScore').innerHTML = game.score;
			setScreenVisible(gameoverScreen, 1);
		}
	}

	function pauseGame() {
		if(game.state == game.RUNNING()) {
			game.pause();
			setScreenVisible(pauseScreen, 1);
		}
	}

	function handleTouch(evt) {
		evt.preventDefault();
		handleTouchOrClick(evt.touches[0].clientX, evt.touches[0].clientY);
	}

	function handleClick(evt) {
		evt.preventDefault();
		handleTouchOrClick(evt.clientX, evt.clientY);
	}

	function handleTouchOrClick(evx, evy) {
		if(Date.now() - lastClickDate < 500)
			return;

		lastClickDate = Date.now();

		var rect = canvas.getBoundingClientRect();
		var x = evx - rect.left,
		    y = evy - rect.top;

		if(PlayPauseButton.handleClick(x, y))
			return;

		if((game.currentBall == null) && (game.state == game.RUNNING())) {
			game.fire();
			return;
		}
	}

	function handleVisibilityChange() {
		if(document.hidden) {
			pauseGame();
		}
	}

	function resizeCanvas() {
		computeGameDimensions();

		canvas.width = Math.floor(GAME_WIDTH);
		canvas.height = Math.floor(GAME_HEIGHT);
		canvas.style.left = Math.floor(H_OFFSET) + "px";
		canvas.style.top = Math.floor(V_OFFSET) + "px";

		// Redraw event when the game is not running
		if(game.state != game.RUNNING())
			window.requestAnimationFrame(step);
	}

	function computeGameDimensions() {
		var w = container.clientWidth, h = container.clientHeight;

		if(w / h < 3/4) {
			GAME_WIDTH = w;
			GAME_HEIGHT = 4/3 * GAME_WIDTH;
		} else {
			GAME_HEIGHT = h;
			GAME_WIDTH = 3/4 * GAME_HEIGHT;
		}

		SCALE              = GAME_WIDTH;
		V_OFFSET           = (h - GAME_HEIGHT) / 2;
		H_OFFSET           = (w - GAME_WIDTH) / 2;
		TOP_BORDER         = SCALE / 6;
		BOTTOM_BORDER      = TOP_BORDER + SCALE;
		LEFT_BORDER        = 0;
		RIGHT_BORDER       = LEFT_BORDER + SCALE;
		CANNON_BASE_WIDTH  = SCALE / 10;
		CANNON_BASE_HEIGHT = SCALE / 15;
		CANNON_LENGTH      = SCALE / 15;
		CANNON_WIDTH       = SCALE / 18;
	}

	function setScreenVisible(screen, zindex) {
		screen.style.zIndex = (zindex >= 0 ? zindex : -1);
		screen.scrollTop = 0;
		// Prevent flickering
		screen.style.display = (zindex >= 0 ? 'block' : 'none');
	}

	this.MENU = 1;
	this.GAME = 2;

	this.state = this.MENU;

	this.game = game;
	this.observable = new Observable();

	var      canvas = document.getElementById(canvasID),
	      container = canvas.parentNode,
	    startScreen = document.getElementById('startScreen'),
	    pauseScreen = document.getElementById('pauseScreen'),
	 gameoverScreen = document.getElementById('gameoverScreen'),
	  licenseScreen = document.getElementById('licenseScreen');

	document.getElementById('startScreenPlayButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.resume();
		that.state = that.GAME;
		window.requestAnimationFrame(step);
		setScreenVisible(startScreen, -1);
	});

	document.getElementById('pauseScreenContinueButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.resume();
		window.requestAnimationFrame(step);
		setScreenVisible(pauseScreen, -1);
	});

	document.getElementById('gameoverScreenPlayAgainButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		game.reset();
		window.requestAnimationFrame(step);
		setScreenVisible(gameoverScreen, -1);
	});

	document.getElementById('startScreenLicenseButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		setScreenVisible(licenseScreen, 2);
	});

	document.getElementById('licenseScreenBackButton').addEventListener('click', function(evt) {
		evt.preventDefault();
		setScreenVisible(licenseScreen, -1);
	});

	var ctx = canvas.getContext('2d');

	var SCALE, GAME_WIDTH, GAME_HEIGHT, V_OFFSET, H_OFFSET,
	    BOTTOM_BORDER, TOP_BORDER, LEFT_BORDER, RIGHT_BORDER,
	    CANNON_BASE_WIDTH, CANNON_BASE_HEIGHT, CANNON_LENGTH, CANNON_WIDTH;

	var lastClickDate = 0;

	var that = this; // Allow to access this from the closure.

	window.addEventListener('resize', resizeCanvas, false);
	[canvas, container].forEach(function(e) {
		e.addEventListener('mousedown', handleClick, false);
		e.addEventListener('touchstart', handleTouch, false);
	});

	document.addEventListener('visibilitychange', handleVisibilityChange, false);

	resizeCanvas();

	window.requestAnimationFrame(step);
}

DontYouFillItCanvasGui.prototype.addObserver = function(o) {
	this.observable.addObserver(o);
};

DontYouFillItCanvasGui.prototype.removeObserver = function(o) {
	this.observable.removeObserver(o);
};

DontYouFillItCanvasGui.prototype.notifyObservers = function() {
	this.observable.notifyObservers();
};
<|endoftext|>


<commit_before>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;
      $scope.primaryColorRgb =
          $mdColors.getThemeColor($rootScope.portal.theme.name + '-primary');

      $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
      };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<commit_msg>fix: Change scope of theme variable<commit_after>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;
      $scope.primaryColorRgb =
          $mdColors.getThemeColor($sessionStorage.portal.theme.name + '-primary');

      $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
      };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<|endoftext|>


<commit_before>goog.require('ol.Map');
goog.require('ol.Overlay');
goog.require('ol.OverlayPositioning');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.GeoJSON');
goog.require('ol.source.TileJSON');
goog.require('ol.style.Icon');
goog.require('ol.style.Style');

var raster = new ol.layer.Tile({
  source: new ol.source.TileJSON({
    url: 'http://api.tiles.mapbox.com/v3/mapbox.geography-class.jsonp'
  })
});

var styleArray = [new ol.style.Style({
  image: new ol.style.Icon({
    src: 'data/icon.png'
  })
})];

var vector = new ol.layer.Vector({
  source: new ol.source.GeoJSON(/** @type {olx.source.GeoJSONOptions} */ ({
    object: {
      'type': 'FeatureCollection',
      'features': [{
        'type': 'Feature',
        'properties': {
          'name': 'Null Island',
          'population': 4000,
          'rainfall': 500
        },
        'geometry': {
          'type': 'Point',
          'coordinates': [0, 0]
        }
      }]
    }
  })),
  styleFunction: function(feature, resolution) {
    return styleArray;
  }
});

var map = new ol.Map({
  layers: [raster, vector],
  renderer: ol.RendererHint.CANVAS,
  target: document.getElementById('map'),
  view: new ol.View2D({
    center: [0, 0],
    zoom: 3
  })
});

var element = document.getElementById('popup');

var popup = new ol.Overlay({
  element: element,
  positioning: ol.OverlayPositioning.BOTTOM_CENTER,
  stopEvent: false
});
map.addOverlay(popup);

// display popup on click
map.on('singleclick', function(evt) {
  var feature = map.forEachFeatureAtPixel(evt.getPixel(),
      function(feature, layer) {
        return feature;
      });
  if (feature) {
    var geometry = feature.getGeometry();
    var coord = geometry.getCoordinates();
    popup.setPosition(coord);
    $(element).popover({
      'placement': 'top',
      'html': true,
      'content': feature.get('name')
    });
    $(element).popover('show');
  } else {
    $(element).popover('destroy');
  }
});

// change mouse cursor when over marker
$(map.getViewport()).on('mousemove', function(e) {
  var pixel = map.getEventPixel(e.originalEvent);
  var hit = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
    return true;
  });
  if (hit) {
    map.getTarget().style.cursor = 'pointer';
  } else {
    map.getTarget().style.cursor = '';
  }
});
<commit_msg>Use anchorXUnits and anchorYUnits in icon example<commit_after>goog.require('ol.Map');
goog.require('ol.Overlay');
goog.require('ol.OverlayPositioning');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.GeoJSON');
goog.require('ol.source.TileJSON');
goog.require('ol.style.Icon');
goog.require('ol.style.Style');

var raster = new ol.layer.Tile({
  source: new ol.source.TileJSON({
    url: 'http://api.tiles.mapbox.com/v3/mapbox.geography-class.jsonp'
  })
});

var styleArray = [new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0.5, 46],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    src: 'data/icon.png'
  })
})];

var vector = new ol.layer.Vector({
  source: new ol.source.GeoJSON(/** @type {olx.source.GeoJSONOptions} */ ({
    object: {
      'type': 'FeatureCollection',
      'features': [{
        'type': 'Feature',
        'properties': {
          'name': 'Null Island',
          'population': 4000,
          'rainfall': 500
        },
        'geometry': {
          'type': 'Point',
          'coordinates': [0, 0]
        }
      }]
    }
  })),
  styleFunction: function(feature, resolution) {
    return styleArray;
  }
});

var map = new ol.Map({
  layers: [raster, vector],
  renderer: ol.RendererHint.CANVAS,
  target: document.getElementById('map'),
  view: new ol.View2D({
    center: [0, 0],
    zoom: 3
  })
});

var element = document.getElementById('popup');

var popup = new ol.Overlay({
  element: element,
  positioning: ol.OverlayPositioning.BOTTOM_CENTER,
  stopEvent: false
});
map.addOverlay(popup);

// display popup on click
map.on('singleclick', function(evt) {
  var feature = map.forEachFeatureAtPixel(evt.getPixel(),
      function(feature, layer) {
        return feature;
      });
  if (feature) {
    var geometry = feature.getGeometry();
    var coord = geometry.getCoordinates();
    popup.setPosition(coord);
    $(element).popover({
      'placement': 'top',
      'html': true,
      'content': feature.get('name')
    });
    $(element).popover('show');
  } else {
    $(element).popover('destroy');
  }
});

// change mouse cursor when over marker
$(map.getViewport()).on('mousemove', function(e) {
  var pixel = map.getEventPixel(e.originalEvent);
  var hit = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
    return true;
  });
  if (hit) {
    map.getTarget().style.cursor = 'pointer';
  } else {
    map.getTarget().style.cursor = '';
  }
});
<|endoftext|>