<commit_before>var Credits = (function (Transition, window, calcScreenConst, changeCoords, changePath, Repository) {
    "use strict";

    function Credits(stage, tapController, messages) {
        this.stage = stage;
        this.tapController = tapController;
        this.messages = messages;

        this.resizeRepoDrawables = new Repository();
        this.resizeRepoTouchables = new Repository();
        this.resizeRepoPaths = new Repository();
    }

    Credits.prototype.resize = function (width, heigth) {
        this.screenWidth = width;
        this.screenHeight = heigth;

        this.resizeRepoDrawables.call();
        this.resizeRepoTouchables.call();
        this.resizeRepoPaths.call();
    };

    Credits.prototype.show = function (nextScene, previousScenesDrawables, screenWidth, screenHeight) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;

        var self = this;

        function fadeOut(drawables, callback) {
            drawables.forEach(function (drawable) {
                var path = self.stage.getPath(drawable.x, drawable.y, drawable.x - self.screenWidth, drawable.y, 60,
                    Transition.EASE_IN_OUT_QUAD);
                self.resizeRepoTouchables.add(drawable, function () {
                    changePath(path, drawable.x, drawable.y, drawable.x - self.screenWidth, drawable.y);
                });
                self.stage.move(drawable, path, function () {
                    self.resizeRepoTouchables.remove(drawable);
                    if (callback)
                        callback();
                });
            });
        }

        function fadeIn(drawables, callback) {
            drawables.forEach(function (drawable) {
                var path = self.stage.getPath(drawable.x, drawable.y, drawable.x + self.screenWidth, drawable.y, 60,
                    Transition.EASE_IN_OUT_QUAD);
                self.resizeRepoTouchables.add(drawable, function () {
                    changePath(path, drawable.x, drawable.y, drawable.x + self.screenWidth, drawable.y);
                });
                self.stage.move(drawable, path, function () {
                    self.resizeRepoTouchables.remove(drawable);
                    if (callback)
                        callback();
                });
            });
        }

        var back, fb, twitter, letsplayIO;

        function drawCreditsScreen() {
            back = self.stage.drawFresh(calcScreenConst(self.screenWidth, 10) + self.screenWidth, calcScreenConst(self.screenHeight, 25, 2), 'back');
            self.resizeRepoDrawables.add(back, function () {
                if (self.drawablesAtNewPosition)
                    changeCoords(back, calcScreenConst(self.screenWidth, 10),
                        calcScreenConst(self.screenHeight, 25, 2));
                else
                    changeCoords(back, calcScreenConst(self.screenWidth, 10) + self.screenWidth,
                        calcScreenConst(self.screenHeight, 25, 2));
            });

            var KEN_PIXEL_BLOCKS = 'KenPixelBlocks';
            var LIGHT_GREY = '#c4c4c4';

            var game_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4), 3,
                self.messages.get('credits', 'game'), 45, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(game_txt);
            self.resizeRepoDrawables.add(game_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(game_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4));
                } else {
                    changeCoords(game_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4));
                }
            });

            var a_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) - game_txt.txt.size, 3,
                self.messages.get('credits', 'a'), 25, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(a_txt);
            self.resizeRepoDrawables.add(a_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(a_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) - game_txt.txt.size);
                } else {
                    changeCoords(a_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) - game_txt.txt.size);
                }
            });

            var by_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) + game_txt.txt.size,
                3, self.messages.get('credits', 'by'), 25, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(by_txt);
            self.resizeRepoDrawables.add(by_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(by_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) + game_txt.txt.size)
                } else {
                    changeCoords(by_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) + game_txt.txt.size)
                }
            });

            letsplayIO = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 2), 'credits-logo');
            self.resizeRepoDrawables.add(letsplayIO, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(letsplayIO, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 2));
                } else {
                    changeCoords(letsplayIO, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 2));
                }
            });

            fb = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                    calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3), 'credits-facebook');
            self.resizeRepoDrawables.add(fb, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(fb, calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4),
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3));
                } else {
                    changeCoords(fb, calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3))
                }
            });

            twitter = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                    calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3), 'credits-twitter');
            self.resizeRepoDrawables.add(twitter, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(twitter, calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4),
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3));
                } else {
                    changeCoords(twitter, calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3))
                }
            });

            var graphics_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) * 3, 3,
                self.messages.get('credits', 'graphics'), 20, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(graphics_txt);
            self.resizeRepoDrawables.add(graphics_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(graphics_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) * 3);
                } else {
                    changeCoords(graphics_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) * 3);
                }
            });

            var kenney = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + self.screenWidth, graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height, 6, 5),
                'kenney');
            self.resizeRepoDrawables.add(kenney, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(kenney, calcScreenConst(self.screenWidth, 2), graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height));
                } else {
                    changeCoords(kenney, calcScreenConst(self.screenWidth, 2) + self.screenWidth, graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height));
                }
            });

            return [back, a_txt, game_txt, by_txt, letsplayIO, fb, twitter, graphics_txt, kenney];
        }

        function registerTapListener() {
            var twitterTouchable = {
                id: 'twitter_letsplayIO_tap',
                x: twitter.getCornerX() - self.screenWidth,
                y: twitter.getCornerY(),
                width: twitter.getWidth(),
                height: twitter.getHeight()
            };
            self.resizeRepoTouchables.add(twitterTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    twitterTouchable.x = twitter.getCornerX();
                } else {
                    twitterTouchable.x = twitter.getCornerX() - self.screenWidth;
                }
                twitterTouchable.y = twitter.getCornerY();
                twitterTouchable.width = twitter.getWidth();
                twitterTouchable.height = twitter.getHeight();
            });
            self.tapController.add(twitterTouchable, function () {
                window.open('https://twitter.com/letsplayIO', '_blank');
            });

            var fbTouchable = {
                id: 'fb_letsplayIO_tap',
                x: fb.getCornerX() - self.screenWidth,
                y: fb.getCornerY(),
                width: fb.getWidth(),
                height: fb.getHeight()
            };
            self.resizeRepoTouchables.add(fbTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    fbTouchable.x = fb.getCornerX();
                } else {
                    fbTouchable.x = fb.getCornerX() - self.screenWidth;
                }
                fbTouchable.y = fb.getCornerY();
                fbTouchable.width = fb.getWidth();
                fbTouchable.height = fb.getHeight();
            });
            self.tapController.add(fbTouchable, function () {
                window.open('https://www.facebook.com/letsplayIO', '_blank');
            });

            var letsplayIOSiteTouchable = {
                id: 'letsplayIO_site_tap',
                x: letsplayIO.getCornerX() - self.screenWidth,
                y: letsplayIO.getCornerY(),
                width: letsplayIO.getWidth(),
                height: letsplayIO.getHeight()
            };
            self.resizeRepoTouchables.add(letsplayIOSiteTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    letsplayIOSiteTouchable.x = letsplayIO.getCornerX();
                } else {
                    letsplayIOSiteTouchable.x = letsplayIO.getCornerX() - self.screenWidth;
                }
                letsplayIOSiteTouchable.y = letsplayIO.getCornerY();
                letsplayIOSiteTouchable.width = letsplayIO.getWidth();
                letsplayIOSiteTouchable.height = letsplayIO.getHeight();
            });
            self.tapController.add(letsplayIOSiteTouchable, function () {
                window.open('http://letsplay.io/', '_blank');
            });
            return [twitterTouchable, fbTouchable, letsplayIOSiteTouchable];
        }

        function unRegisterTapListener(touchables) {
            touchables.forEach(self.tapController.remove.bind(self.tapController));
        }

        fadeOut(previousScenesDrawables);
        var creditsDrawables = drawCreditsScreen();
        var touchables = registerTapListener();
        self.drawablesAtNewPosition = false;
        fadeOut(creditsDrawables, function () {
            self.drawablesAtNewPosition = true;
        });

        var backTouchable = {
            id: 'back_tap',
            x: 0,
            y: 0,
            width: calcScreenConst(self.screenWidth, 4),
            height: calcScreenConst(self.screenHeight, 4)
        };
        self.tapController.add(backTouchable, endScene);
        touchables.push(backTouchable);

        function endScene() {
            back.img = self.stage.getSubImage('back-active');
            unRegisterTapListener(touchables);
            fadeIn(creditsDrawables);
            function removeDrawables() {
                creditsDrawables.forEach(self.stage.remove.bind(self.stage));
            }

            var firstCallback = true;
            fadeIn(previousScenesDrawables, function () {
                if (firstCallback) {
                    firstCallback = false;
                    self.next(nextScene);
                    removeDrawables();
                }
            });
        }

    };

    Credits.prototype.next = function (nextScene) {
        nextScene();
    };

    return Credits;
})(Transition, window, calcScreenConst, changeCoords, changePath, Repository);<commit_msg>sanity stuff with credits resizing scene<commit_after>var Credits = (function (Transition, window, calcScreenConst, changeCoords, changePath, Repository) {
    "use strict";

    function Credits(stage, tapController, messages) {
        this.stage = stage;
        this.tapController = tapController;
        this.messages = messages;
    }

    Credits.prototype.resize = function (width, heigth) {
        this.screenWidth = width;
        this.screenHeight = heigth;

        if (this.resizeRepoDrawables)
            this.resizeRepoDrawables.call();
        if (this.resizeRepoTouchables)
            this.resizeRepoTouchables.call();
        if (this.resizeRepoPaths)
            this.resizeRepoPaths.call();
    };

    Credits.prototype.show = function (nextScene, previousScenesDrawables, screenWidth, screenHeight) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;

        this.resizeRepoDrawables = new Repository();
        this.resizeRepoTouchables = new Repository();
        this.resizeRepoPaths = new Repository();

        var self = this;

        function fadeOut(drawables, callback) {
            drawables.forEach(function (drawable) {
                var path = self.stage.getPath(drawable.x, drawable.y, drawable.x - self.screenWidth, drawable.y, 60,
                    Transition.EASE_IN_OUT_QUAD);
                self.resizeRepoTouchables.add(drawable, function () {
                    changePath(path, drawable.x, drawable.y, drawable.x - self.screenWidth, drawable.y);
                });
                self.stage.move(drawable, path, function () {
                    self.resizeRepoTouchables.remove(drawable);
                    if (callback)
                        callback();
                });
            });
        }

        function fadeIn(drawables, callback) {
            drawables.forEach(function (drawable) {
                var path = self.stage.getPath(drawable.x, drawable.y, drawable.x + self.screenWidth, drawable.y, 60,
                    Transition.EASE_IN_OUT_QUAD);
                self.resizeRepoTouchables.add(drawable, function () {
                    changePath(path, drawable.x, drawable.y, drawable.x + self.screenWidth, drawable.y);
                });
                self.stage.move(drawable, path, function () {
                    self.resizeRepoTouchables.remove(drawable);
                    if (callback)
                        callback();
                });
            });
        }

        var back, fb, twitter, letsplayIO;

        function drawCreditsScreen() {
            back = self.stage.drawFresh(calcScreenConst(self.screenWidth, 10) + self.screenWidth, calcScreenConst(self.screenHeight, 25, 2), 'back');
            self.resizeRepoDrawables.add(back, function () {
                if (self.drawablesAtNewPosition)
                    changeCoords(back, calcScreenConst(self.screenWidth, 10),
                        calcScreenConst(self.screenHeight, 25, 2));
                else
                    changeCoords(back, calcScreenConst(self.screenWidth, 10) + self.screenWidth,
                        calcScreenConst(self.screenHeight, 25, 2));
            });

            var KEN_PIXEL_BLOCKS = 'KenPixelBlocks';
            var LIGHT_GREY = '#c4c4c4';

            var game_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4), 3,
                self.messages.get('credits', 'game'), 45, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(game_txt);
            self.resizeRepoDrawables.add(game_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(game_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4));
                } else {
                    changeCoords(game_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4));
                }
            });

            var a_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) - game_txt.txt.size, 3,
                self.messages.get('credits', 'a'), 25, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(a_txt);
            self.resizeRepoDrawables.add(a_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(a_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) - game_txt.txt.size);
                } else {
                    changeCoords(a_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) - game_txt.txt.size);
                }
            });

            var by_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) + game_txt.txt.size,
                3, self.messages.get('credits', 'by'), 25, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(by_txt);
            self.resizeRepoDrawables.add(by_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(by_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) + game_txt.txt.size)
                } else {
                    changeCoords(by_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) + game_txt.txt.size)
                }
            });

            letsplayIO = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 2), 'credits-logo');
            self.resizeRepoDrawables.add(letsplayIO, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(letsplayIO, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 2));
                } else {
                    changeCoords(letsplayIO, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 2));
                }
            });

            fb = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                    calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3), 'credits-facebook');
            self.resizeRepoDrawables.add(fb, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(fb, calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4),
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3));
                } else {
                    changeCoords(fb, calcScreenConst(self.screenWidth, 2) - calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3))
                }
            });

            twitter = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                    calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3), 'credits-twitter');
            self.resizeRepoDrawables.add(twitter, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(twitter, calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4),
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3));
                } else {
                    changeCoords(twitter, calcScreenConst(self.screenWidth, 2) + calcScreenConst(self.stage.getSubImage('credits-facebook').width, 5, 4) + self.screenWidth,
                            calcScreenConst(self.screenHeight, 2) + calcScreenConst(letsplayIO.img.height, 2, 3))
                }
            });

            var graphics_txt = self.stage.getDrawableText(calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) * 3, 3,
                self.messages.get('credits', 'graphics'), 20, KEN_PIXEL_BLOCKS, LIGHT_GREY);
            self.stage.draw(graphics_txt);
            self.resizeRepoDrawables.add(graphics_txt, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(graphics_txt, calcScreenConst(self.screenWidth, 2), calcScreenConst(self.screenHeight, 4) * 3);
                } else {
                    changeCoords(graphics_txt, calcScreenConst(self.screenWidth, 2) + self.screenWidth, calcScreenConst(self.screenHeight, 4) * 3);
                }
            });

            var kenney = self.stage.drawFresh(calcScreenConst(self.screenWidth, 2) + self.screenWidth, graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height, 6, 5),
                'kenney');
            self.resizeRepoDrawables.add(kenney, function () {
                if (self.drawablesAtNewPosition) {
                    changeCoords(kenney, calcScreenConst(self.screenWidth, 2), graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height));
                } else {
                    changeCoords(kenney, calcScreenConst(self.screenWidth, 2) + self.screenWidth, graphics_txt.y + calcScreenConst(self.stage.getSubImage('kenney').height));
                }
            });

            return [back, a_txt, game_txt, by_txt, letsplayIO, fb, twitter, graphics_txt, kenney];
        }

        function registerTapListener() {
            var twitterTouchable = {
                id: 'twitter_letsplayIO_tap',
                x: twitter.getCornerX() - self.screenWidth,
                y: twitter.getCornerY(),
                width: twitter.getWidth(),
                height: twitter.getHeight()
            };
            self.resizeRepoTouchables.add(twitterTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    twitterTouchable.x = twitter.getCornerX();
                } else {
                    twitterTouchable.x = twitter.getCornerX() - self.screenWidth;
                }
                twitterTouchable.y = twitter.getCornerY();
                twitterTouchable.width = twitter.getWidth();
                twitterTouchable.height = twitter.getHeight();
            });
            self.tapController.add(twitterTouchable, function () {
                window.open('https://twitter.com/letsplayIO', '_blank');
            });

            var fbTouchable = {
                id: 'fb_letsplayIO_tap',
                x: fb.getCornerX() - self.screenWidth,
                y: fb.getCornerY(),
                width: fb.getWidth(),
                height: fb.getHeight()
            };
            self.resizeRepoTouchables.add(fbTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    fbTouchable.x = fb.getCornerX();
                } else {
                    fbTouchable.x = fb.getCornerX() - self.screenWidth;
                }
                fbTouchable.y = fb.getCornerY();
                fbTouchable.width = fb.getWidth();
                fbTouchable.height = fb.getHeight();
            });
            self.tapController.add(fbTouchable, function () {
                window.open('https://www.facebook.com/letsplayIO', '_blank');
            });

            var letsplayIOSiteTouchable = {
                id: 'letsplayIO_site_tap',
                x: letsplayIO.getCornerX() - self.screenWidth,
                y: letsplayIO.getCornerY(),
                width: letsplayIO.getWidth(),
                height: letsplayIO.getHeight()
            };
            self.resizeRepoTouchables.add(letsplayIOSiteTouchable, function () {
                if (self.drawablesAtNewPosition) {
                    letsplayIOSiteTouchable.x = letsplayIO.getCornerX();
                } else {
                    letsplayIOSiteTouchable.x = letsplayIO.getCornerX() - self.screenWidth;
                }
                letsplayIOSiteTouchable.y = letsplayIO.getCornerY();
                letsplayIOSiteTouchable.width = letsplayIO.getWidth();
                letsplayIOSiteTouchable.height = letsplayIO.getHeight();
            });
            self.tapController.add(letsplayIOSiteTouchable, function () {
                window.open('http://letsplay.io/', '_blank');
            });
            return [twitterTouchable, fbTouchable, letsplayIOSiteTouchable];
        }

        function unRegisterTapListener(touchables) {
            touchables.forEach(self.tapController.remove.bind(self.tapController));
        }

        fadeOut(previousScenesDrawables);
        var creditsDrawables = drawCreditsScreen();
        var touchables = registerTapListener();
        self.drawablesAtNewPosition = false;
        fadeOut(creditsDrawables, function () {
            self.drawablesAtNewPosition = true;
        });

        var backTouchable = {
            id: 'back_tap',
            x: 0,
            y: 0,
            width: calcScreenConst(self.screenWidth, 4),
            height: calcScreenConst(self.screenHeight, 4)
        };
        self.tapController.add(backTouchable, endScene);
        touchables.push(backTouchable);

        function endScene() {
            back.img = self.stage.getSubImage('back-active');
            unRegisterTapListener(touchables);
            fadeIn(creditsDrawables);
            function removeDrawables() {
                creditsDrawables.forEach(self.stage.remove.bind(self.stage));
            }

            var firstCallback = true;
            fadeIn(previousScenesDrawables, function () {
                if (firstCallback) {
                    firstCallback = false;
                    removeDrawables();
                    self.next(nextScene);
                }
            });
        }

    };

    Credits.prototype.next = function (nextScene) {
        delete this.resizeRepoDrawables;
        delete this.resizeRepoTouchables;
        delete this.resizeRepoPaths;

        nextScene();
    };

    return Credits;
})(Transition, window, calcScreenConst, changeCoords, changePath, Repository);<|endoftext|>


<commit_before>var BaseView, Handlebars, modelUtils, templateFinder, _;

templateFinder = require('./templateFinder');
Handlebars = require('handlebars');
_ = require('underscore');

// Lazy-required.
BaseView = null;
modelUtils = null;

var oldEach = Handlebars.helpers.each;

module.exports = {
  view: function(viewName, block) {
    var ViewClass, html, options, view;

    BaseView = BaseView || require('./base/view');
    modelUtils = modelUtils || require('./modelUtils');
    viewName = modelUtils.underscorize(viewName);
    options = block.hash || {};

    // Pass through a reference to the app.
    if (this._app) {
      options.app = this._app;
    }

    // Pass through a reference to the parent view.
    if (this._view) {
      options.parentView = this._view;
    }

    // get the Backbone.View based on viewName
    ViewClass = BaseView.getView(viewName);
    view = new ViewClass(options);

    // create the outerHTML using className, tagName
    html = view.getHtml();
    return new Handlebars.SafeString(html);
  },

  partial: function(templateName, block) {
    var data, html, options, template;

    template = templateFinder.getTemplate(templateName);
    options = block.hash || {};
    data = _.isEmpty(options) ? this : options.context ? options.context : options;
    data = _.clone(data);
    data._app = data._app || this._app;
    html = template(data);
    return new Handlebars.SafeString(html);
  },

  json: function(object) {
    return new Handlebars.SafeString(JSON.stringify(object) || 'null');
  },

  /**
   * Extend `each` to pass through important context. By default, `each` calls
   * `options.fn` without a calling context.
   */
  each: function(context, options) {
    var callingContext = getOptionsFromContext(this);
    // Make sure `this._app`, `this._view`, etc are available.
    options.fn = options.fn.bind(callingContext);
    // Call the original helper with new context.
    return oldEach.call(this, context, options);
  }
};

/**
 * Grab important underscored properties from the current context.
 * These properties come from BaseView::decorateTemplateData().
 */
function getOptionsFromContext(obj) {
  var options, keys, value;

  keys = [
    '_app',
    '_view',
    '_model',
    '_collection'
  ];

  options = keys.reduce(function(memo, key) {
    value = obj[key];
    if (value) {
      memo[key] = value;
    }
    return memo;
  }, {});

  return options;
}<commit_msg>Better way to pass through metatdata from 'each' to 'view' Handlebars helpers<commit_after>var BaseView, Handlebars, modelUtils, templateFinder, _;

templateFinder = require('./templateFinder');
Handlebars = require('handlebars');
_ = require('underscore');

// Lazy-required.
BaseView = null;
modelUtils = null;

var oldEach = Handlebars.helpers.each;

module.exports = {
  view: function(viewName, block) {
    var ViewClass, html, options, view, data;

    BaseView = BaseView || require('./base/view');
    modelUtils = modelUtils || require('./modelUtils');
    viewName = modelUtils.underscorize(viewName);
    options = block.hash || {};
    data = block.data || {};

    // Pass through a reference to the app.
    var app = this._app || data._app;
    if (app) {
      options.app = app;
    }

    // Pass through a reference to the parent view.
    parentView = this._view || data._view
    if (parentView) {
      options.parentView = parentView;
    }

    // get the Backbone.View based on viewName
    ViewClass = BaseView.getView(viewName);
    view = new ViewClass(options);

    // create the outerHTML using className, tagName
    html = view.getHtml();
    return new Handlebars.SafeString(html);
  },

  partial: function(templateName, block) {
    var data, html, options, template;

    template = templateFinder.getTemplate(templateName);
    options = block.hash || {};
    data = _.isEmpty(options) ? this : options.context ? options.context : options;
    data = _.clone(data);
    data._app = data._app || this._app;
    html = template(data);
    return new Handlebars.SafeString(html);
  },

  json: function(object) {
    return new Handlebars.SafeString(JSON.stringify(object) || 'null');
  },

  /**
   * Extend `each` to pass through important context.
   */
  each: function(context, options) {
    options.data = Handlebars.createFrame(options.data || {});

    // Make sure `this._app`, `this._view`, etc are available.
    _.extend(options.data, getOptionsFromContext(this));

    // Call the original helper with new context.
    return oldEach.call(this, context, options);
  }
};

/**
 * Grab important underscored properties from the current context.
 * These properties come from BaseView::decorateTemplateData().
 */
function getOptionsFromContext(obj) {
  var options, keys, value;

  keys = [
    '_app',
    '_view',
    '_model',
    '_collection'
  ];

  options = keys.reduce(function(memo, key) {
    value = obj[key];
    if (value) {
      memo[key] = value;
    }
    return memo;
  }, {});

  return options;
}<|endoftext|>


<commit_before>var csv_migrations_select2 = csv_migrations_select2 || {};

(function ($) {
    /**
     * Select2 Logic.
     */
    function Select2()
    {
        //
    }

    /**
     * Setup method.
     *
     * @return {undefined}
     */
    Select2.prototype.setup = function (options) {
        this.min_length = options.hasOwnProperty('min_length') ? options.min_length : 1;
        this.timeout = options.hasOwnProperty('timeout') ? options.timeout : 300;
        this.api_token = options.hasOwnProperty('token') ? options.token : null;
        this.limit = options.hasOwnProperty('limit') ? options.limit : 10;
        this.id = options.hasOwnProperty('id') ? options.id : null;
        this.magicValue = {id: '%%me%%', name: '<< me >>'};

        var that = this;
        // loop through select2 inputs
        $(this.id).each(function () {
            that.init(this);
        });

        // Observe document for added select2(s)
        dom_observer.added(document, function (nodes) {
            $(nodes).each(function () {
                $(this).find(that.id).each(function () {
                    that.init(this);
                });
            });
        });
    };

    /**
     * Initialize method.
     *
     * @return {undefined}
     */
    Select2.prototype.init = function (element) {
        var that = this;
        var value = $(element).val();

        // set select2 option label, if is empty and the option value is set
        if (value && !$(element).text()) {
            value = Array === value.constructor ? value : [value];
            value.forEach(function (val) {
                that._setDisplayValue(val, element);
            });
        }

        // enable select2 functionality
        this._enable(element);
    };

    /**
     * Method that enables select2 functionality on specified input.
     *
     * @param {string} input select2 input
     * @return {undefined}
     * {@link plugin: https://select2.github.io}
     */
    Select2.prototype._enable = function (input) {
        var that = this;
        var placeholder = $(input).attr('title');
        // enable select2
        $(input).select2({
            theme: 'bootstrap',
            width: '100%',
            placeholder: placeholder,
            allowClear: true,
            minimumInputLength: that.min_length,
            escapeMarkup: function (text) {
                return text;
            },
            ajax: {
                url: $(input).data('url'),
                dataType: 'json',
                contentType: 'application/json',
                accepts: {
                    json: 'application/json'
                },
                delay: that.timeout,
                method: 'get',
                headers: {
                    'Authorization': 'Bearer ' + that.api_token
                },
                data: function (params) {
                    return {
                        query: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, params) {
                    var result = [];
                    $.each(data.data, function (k, v) {
                        result.push({
                            id: k,
                            name: v
                        });
                    });
                    params.page = params.page || 1;

                    if ($(input).data('magic-value')) {
                        result.unshift(that.magicValue);
                    }

                    return {
                        results: result,
                        pagination: {
                            more: (params.page * 10) < data.pagination.count
                        }
                    };
                },
                cache: true
            },
            templateResult: function (data) {
                if (data.loading) {
                    // don't show any text if minimum input legth is 0
                    if (0 === that.min_length) {
                        return;
                    }

                    return data.text;
                }

                return data.name;
            },
            templateSelection: function (data) {
                return data.name || data.text;
            }
        });
    };

    /**
     * Set and set select2 field label value, based on table's display field.
     *
     * @param {string} id Record id
     * @param {object} input Select2 input
     * @return {undefined}
     */
    Select2.prototype._setDisplayValue = function (id, input) {
        $(input).data('magic-value') && id === this.magicValue.id ?
            this._magicDisplayValue(id, input) :
            this._ajaxDisplayValue(id, input);
    };

    Select2.prototype._magicDisplayValue = function (id, input) {
        $(input).find('option[value="' + id + '"]').remove();

        var option = $('<option selected="selected">' + this.magicValue.name + '</option>').val(id);

        $(input).append(option).trigger('change');
        $(input).trigger('change');
    };

    Select2.prototype._ajaxDisplayValue = function (id, input) {
        var that = this;
        var url = $(input).data('url').replace('/lookup', '/view/' + id);
        $.ajax({
            url: url,
            type: 'get',
            data: { format: 'pretty' },
            dataType: 'json',
            contentType: 'application/json',
            headers: {
                'Authorization': 'Bearer ' + that.api_token
            },
            success: function (data) {
                if (!data.success) {
                    return;
                }
                var label = data.data[$(input).data('display-field')];
                $(input).find('option[value="' + id + '"]').remove();
                var option = $('<option selected="selected">' + label + '</option>').val(id);
                $(input).append(option).trigger('change');
                // set select2 display value
                $(input).trigger('change');
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
    };

    csv_migrations_select2 = new Select2();

})(jQuery);
<commit_msg>Fix for broken select2 search in bootstrap modals (task #7445)<commit_after>var csv_migrations_select2 = csv_migrations_select2 || {};

(function ($) {
    /**
     * Select2 Logic.
     */
    function Select2()
    {
        //
    }

    /**
     * Setup method.
     *
     * @return {undefined}
     */
    Select2.prototype.setup = function (options) {
        this.min_length = options.hasOwnProperty('min_length') ? options.min_length : 1;
        this.timeout = options.hasOwnProperty('timeout') ? options.timeout : 300;
        this.api_token = options.hasOwnProperty('token') ? options.token : null;
        this.limit = options.hasOwnProperty('limit') ? options.limit : 10;
        this.id = options.hasOwnProperty('id') ? options.id : null;
        this.magicValue = {id: '%%me%%', name: '<< me >>'};

        var that = this;
        // loop through select2 inputs
        $(this.id).each(function () {
            that.init(this);
        });

        // Observe document for added select2(s)
        dom_observer.added(document, function (nodes) {
            $(nodes).each(function () {
                $(this).find(that.id).each(function () {
                    that.init(this);
                });
            });
        });
    };

    /**
     * Initialize method.
     *
     * @return {undefined}
     */
    Select2.prototype.init = function (element) {
        var that = this;
        var value = $(element).val();

        // set select2 option label, if is empty and the option value is set
        if (value && !$(element).text()) {
            value = Array === value.constructor ? value : [value];
            value.forEach(function (val) {
                that._setDisplayValue(val, element);
            });
        }

        // enable select2 functionality
        this._enable(element);
    };

    /**
     * Method that enables select2 functionality on specified input.
     *
     * @param {string} input select2 input
     * @return {undefined}
     * {@link plugin: https://select2.github.io}
     */
    Select2.prototype._enable = function (input) {
        var that = this;
        var placeholder = $(input).attr('title');
        // enable select2
        $(input).select2({
            theme: 'bootstrap',
            width: '100%',
            placeholder: placeholder,
            allowClear: true,
            minimumInputLength: that.min_length,
            escapeMarkup: function (text) {
                return text;
            },
            ajax: {
                url: $(input).data('url'),
                dataType: 'json',
                contentType: 'application/json',
                accepts: {
                    json: 'application/json'
                },
                delay: that.timeout,
                method: 'get',
                headers: {
                    'Authorization': 'Bearer ' + that.api_token
                },
                data: function (params) {
                    return {
                        query: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, params) {
                    var result = [];
                    $.each(data.data, function (k, v) {
                        result.push({
                            id: k,
                            name: v
                        });
                    });
                    params.page = params.page || 1;

                    if ($(input).data('magic-value')) {
                        result.unshift(that.magicValue);
                    }

                    return {
                        results: result,
                        pagination: {
                            more: (params.page * 10) < data.pagination.count
                        }
                    };
                },
                cache: true
            },
            templateResult: function (data) {
                if (data.loading) {
                    // don't show any text if minimum input legth is 0
                    if (0 === that.min_length) {
                        return;
                    }

                    return data.text;
                }

                return data.name;
            },
            templateSelection: function (data) {
                return data.name || data.text;
            }
        });

        // fix for select2 search not working within bootstrap modals
        // @link https://github.com/select2/select2/issues/1436#issuecomment-21028474
        $.fn.modal.Constructor.prototype.enforceFocus = function () {};
    };

    /**
     * Set and set select2 field label value, based on table's display field.
     *
     * @param {string} id Record id
     * @param {object} input Select2 input
     * @return {undefined}
     */
    Select2.prototype._setDisplayValue = function (id, input) {
        $(input).data('magic-value') && id === this.magicValue.id ?
            this._magicDisplayValue(id, input) :
            this._ajaxDisplayValue(id, input);
    };

    Select2.prototype._magicDisplayValue = function (id, input) {
        $(input).find('option[value="' + id + '"]').remove();

        var option = $('<option selected="selected">' + this.magicValue.name + '</option>').val(id);

        $(input).append(option).trigger('change');
        $(input).trigger('change');
    };

    Select2.prototype._ajaxDisplayValue = function (id, input) {
        var that = this;
        var url = $(input).data('url').replace('/lookup', '/view/' + id);
        $.ajax({
            url: url,
            type: 'get',
            data: { format: 'pretty' },
            dataType: 'json',
            contentType: 'application/json',
            headers: {
                'Authorization': 'Bearer ' + that.api_token
            },
            success: function (data) {
                if (!data.success) {
                    return;
                }
                var label = data.data[$(input).data('display-field')];
                $(input).find('option[value="' + id + '"]').remove();
                var option = $('<option selected="selected">' + label + '</option>').val(id);
                $(input).append(option).trigger('change');
                // set select2 display value
                $(input).trigger('change');
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
    };

    csv_migrations_select2 = new Select2();

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).

const ansiHTML = require('ansi-html');
const Entities = require('html-entities').AllHtmlEntities;

const entities = new Entities();

const colors = {
  reset: ['transparent', 'transparent'],
  black: '181818',
  red: 'E36049',
  green: 'B3CB74',
  yellow: 'FFD080',
  blue: '7CAFC2',
  magenta: '7FACCA',
  cyan: 'C3C2EF',
  lightgrey: 'EBE7E3',
  darkgrey: '6D7891'
};
ansiHTML.setColors(colors);

function createOverlayIframe(onIframeLoad) {
  const iframe = document.createElement('iframe');
  iframe.id = 'webpack-dev-server-client-overlay';
  iframe.src = 'about:blank';
  iframe.style.position = 'fixed';
  iframe.style.left = 0;
  iframe.style.top = 0;
  iframe.style.right = 0;
  iframe.style.bottom = 0;
  iframe.style.width = '100vw';
  iframe.style.height = '100vh';
  iframe.style.border = 'none';
  iframe.style.zIndex = 9999999999;
  iframe.onload = onIframeLoad;
  return iframe;
}

function addOverlayDivTo(iframe) {
  const div = iframe.contentDocument.createElement('div');
  div.id = 'webpack-dev-server-client-overlay-div';
  div.style.position = 'fixed';
  div.style.boxSizing = 'border-box';
  div.style.left = 0;
  div.style.top = 0;
  div.style.right = 0;
  div.style.bottom = 0;
  div.style.width = '100vw';
  div.style.height = '100vh';
  div.style.backgroundColor = 'black';
  div.style.color = '#E8E8E8';
  div.style.fontFamily = 'Menlo, Consolas, monospace';
  div.style.fontSize = 'large';
  div.style.padding = '2rem';
  div.style.lineHeight = '1.2';
  div.style.whiteSpace = 'pre-wrap';
  div.style.overflow = 'auto';
  iframe.contentDocument.body.appendChild(div);
  return div;
}

let overlayIframe = null;
let overlayDiv = null;
let lastOnOverlayDivReady = null;

function ensureOverlayDivExists(onOverlayDivReady) {
  if (overlayDiv) {
    // Everything is ready, call the callback right away.
    onOverlayDivReady(overlayDiv);
    return;
  }

  // Creating an iframe may be asynchronous so we'll schedule the callback.
  // In case of multiple calls, last callback wins.
  lastOnOverlayDivReady = onOverlayDivReady;

  if (overlayIframe) {
    // We're already creating it.
    return;
  }

  // Create iframe and, when it is ready, a div inside it.
  overlayIframe = createOverlayIframe(function cb() {
    overlayDiv = addOverlayDivTo(overlayIframe);
    // Now we can talk!
    lastOnOverlayDivReady(overlayDiv);
  });

  // Zalgo alert: onIframeLoad() will be called either synchronously
  // or asynchronously depending on the browser.
  // We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
  document.body.appendChild(overlayIframe);
}

function showMessageOverlay(message) {
  ensureOverlayDivExists(function cb(div) {
    // Make it look similar to our terminal.
    div.innerHTML = 'Failed to compile.

' +
                    ansiHTML(entities.encode(message));
  });
}

function destroyErrorOverlay() {
  if (!overlayDiv) {
    // It is not there in the first place.
    return;
  }

  // Clean up and reset internal state.
  document.body.removeChild(overlayIframe);
  overlayDiv = null;
  overlayIframe = null;
  lastOnOverlayDivReady = null;
}

// Successful compilation.
exports.clear = function handleSuccess() {
  destroyErrorOverlay();
};

// Compilation with errors (e.g. syntax error or missing modules).
exports.showMessage = function handleMessage(messages) {
  showMessageOverlay(messages[0]);
};
<commit_msg>Made error overlay translucent. (#1097)<commit_after>'use strict';

// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).

const ansiHTML = require('ansi-html');
const Entities = require('html-entities').AllHtmlEntities;

const entities = new Entities();

const colors = {
  reset: ['transparent', 'transparent'],
  black: '181818',
  red: 'E36049',
  green: 'B3CB74',
  yellow: 'FFD080',
  blue: '7CAFC2',
  magenta: '7FACCA',
  cyan: 'C3C2EF',
  lightgrey: 'EBE7E3',
  darkgrey: '6D7891'
};
ansiHTML.setColors(colors);

function createOverlayIframe(onIframeLoad) {
  const iframe = document.createElement('iframe');
  iframe.id = 'webpack-dev-server-client-overlay';
  iframe.src = 'about:blank';
  iframe.style.position = 'fixed';
  iframe.style.left = 0;
  iframe.style.top = 0;
  iframe.style.right = 0;
  iframe.style.bottom = 0;
  iframe.style.width = '100vw';
  iframe.style.height = '100vh';
  iframe.style.border = 'none';
  iframe.style.zIndex = 9999999999;
  iframe.onload = onIframeLoad;
  return iframe;
}

function addOverlayDivTo(iframe) {
  const div = iframe.contentDocument.createElement('div');
  div.id = 'webpack-dev-server-client-overlay-div';
  div.style.position = 'fixed';
  div.style.boxSizing = 'border-box';
  div.style.left = 0;
  div.style.top = 0;
  div.style.right = 0;
  div.style.bottom = 0;
  div.style.width = '100vw';
  div.style.height = '100vh';
  div.style.backgroundColor = 'rgba(0, 0, 0, 0.85)';
  div.style.color = '#E8E8E8';
  div.style.fontFamily = 'Menlo, Consolas, monospace';
  div.style.fontSize = 'large';
  div.style.padding = '2rem';
  div.style.lineHeight = '1.2';
  div.style.whiteSpace = 'pre-wrap';
  div.style.overflow = 'auto';
  iframe.contentDocument.body.appendChild(div);
  return div;
}

let overlayIframe = null;
let overlayDiv = null;
let lastOnOverlayDivReady = null;

function ensureOverlayDivExists(onOverlayDivReady) {
  if (overlayDiv) {
    // Everything is ready, call the callback right away.
    onOverlayDivReady(overlayDiv);
    return;
  }

  // Creating an iframe may be asynchronous so we'll schedule the callback.
  // In case of multiple calls, last callback wins.
  lastOnOverlayDivReady = onOverlayDivReady;

  if (overlayIframe) {
    // We're already creating it.
    return;
  }

  // Create iframe and, when it is ready, a div inside it.
  overlayIframe = createOverlayIframe(function cb() {
    overlayDiv = addOverlayDivTo(overlayIframe);
    // Now we can talk!
    lastOnOverlayDivReady(overlayDiv);
  });

  // Zalgo alert: onIframeLoad() will be called either synchronously
  // or asynchronously depending on the browser.
  // We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
  document.body.appendChild(overlayIframe);
}

function showMessageOverlay(message) {
  ensureOverlayDivExists(function cb(div) {
    // Make it look similar to our terminal.
    div.innerHTML = 'Failed to compile.

' +
                    ansiHTML(entities.encode(message));
  });
}

function destroyErrorOverlay() {
  if (!overlayDiv) {
    // It is not there in the first place.
    return;
  }

  // Clean up and reset internal state.
  document.body.removeChild(overlayIframe);
  overlayDiv = null;
  overlayIframe = null;
  lastOnOverlayDivReady = null;
}

// Successful compilation.
exports.clear = function handleSuccess() {
  destroyErrorOverlay();
};

// Compilation with errors (e.g. syntax error or missing modules).
exports.showMessage = function handleMessage(messages) {
  showMessageOverlay(messages[0]);
};
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
sap.ui.define(['sap/ui/Device', "sap/base/Log", "sap/ui/thirdparty/jquery"], function(Device, Log, jQuery) {
	"use strict";

	/**
	 * Provide methods for sap.ui.core.routing.Route in async mode
	 * @private
	 * @experimental
	 * @since 1.33
	 */
	return {

		/**
		 * @private
		 */
		_routeMatched : function(oArguments, oSequencePromise, oNestingChild) {

			var oRouter = this._oRouter,
				oTarget,
				oConfig,
				oEventData,
				oView = null,
				oTargetControl = null,
				bInitial,
				oTargetData,
				oCurrentPromise,
				that = this;

			oRouter._matchedRoute = this;

			if (!oSequencePromise || oSequencePromise === true) {
				bInitial = true;
				oSequencePromise = Promise.resolve();
			}

			// Recursively fire matched event and display views of this routes parents
			if (this._oParent) {
				oSequencePromise = this._oParent._routeMatched(oArguments, oSequencePromise);
			} else if (this._oNestingParent) {
				// pass child for setting the flag in event parameter of parent
				this._oNestingParent._routeMatched(oArguments, oSequencePromise, this);
			}

			oConfig = jQuery.extend({}, oRouter._oConfig, this._oConfig);

			// make a copy of arguments and forward route config to target
			oTargetData = jQuery.extend({}, oArguments);
			oTargetData.routeConfig = oConfig;

			oEventData = {
				name: oConfig.name,
				arguments: oArguments,
				config : oConfig
			};

			if (oNestingChild) {
				// setting the event parameter of nesting child
				oEventData.nestedRoute = oNestingChild;
			}

			// fire the beforeMatched and beforeRouteMathced events
			this.fireBeforeMatched(oEventData);
			oRouter.fireBeforeRouteMatched(oEventData);

			// Route is defined without target in the config - use the internally created target to place the view
			if (this._oTarget) {
				oTarget = this._oTarget;
				// update the targets config so defaults are taken into account - since targets cannot be added in runtime they don't merge configs like routes do
				oTarget._updateOptions(this._convertToTargetOptions(oConfig));

				oSequencePromise = oTarget._place(oSequencePromise);

				// this is for sap.m.routing.Router to chain the promise to the navigation promise in TargetHandler
				if (this._oRouter._oTargetHandler && this._oRouter._oTargetHandler._chainNavigation) {
					oCurrentPromise = oSequencePromise;
					oSequencePromise = this._oRouter._oTargetHandler._chainNavigation(function() {
						return oCurrentPromise;
					});
				}
			} else /* let targets do the placement + the events */ if (Device.browser.msie || Device.browser.edge) {
				oCurrentPromise = oSequencePromise;

				// when Promise polyfill is used for IE or Edge, the synchronous DOM or CSS change, e.g. showing a busy indicator, doesn't get
				// a slot for being executed. Therefore a explicit 0 timeout is added for allowing the DOM or CSS change to be executed before
				// the view is loaded.
				oSequencePromise = new Promise(function(resolve, reject) {
					setTimeout(function() {
						var oDisplayPromise = oRouter._oTargets._display(that._oConfig.target, oTargetData, that._oConfig.titleTarget, oCurrentPromise);
						oDisplayPromise.then(resolve, reject);
					}, 0);
				});
			} else {
				if (!this._oConfig.afterCreateHook) {
					this._oConfig.afterCreateHook = function(oTargetObject) {
						if (oTargetObject.isA("sap.ui.core.UIComponent")) {
							var oRouter = oTargetObject.getRouter();
							if (oRouter) {
								that.attachEvent("switched", function() {
									// stop the router in nested component when the Route which loads it is navigated away
									oRouter.stop();
								});
							}
						}
					};
				}
				oSequencePromise = oRouter._oTargets._display(this._oConfig.target, oTargetData, this._oConfig.titleTarget, oSequencePromise, this._oConfig.afterCreateHook);
			}

			return oSequencePromise.then(function(oResult) {
				oResult = oResult || {};

				oView = oResult.view;
				oTargetControl = oResult.control;

				// Extend the event data with view and targetControl
				oEventData.view = oView;
				oEventData.targetControl = oTargetControl;

				if (oConfig.callback) {
					//Targets don't pass TargetControl and view since there might be multiple
					oConfig.callback(this, oArguments, oConfig, oTargetControl, oView);
				}

				this.fireEvent("matched", oEventData);
				oRouter.fireRouteMatched(oEventData);
				// skip this event in the recursion
				if (bInitial) {
					Log.info("The route named '" + oConfig.name + "' did match with its pattern", this);
					this.fireEvent("patternMatched", oEventData);
					oRouter.fireRoutePatternMatched(oEventData);
				}

				return oResult;
			}.bind(this));
		}
	};
});
<commit_msg>[INTERNAL] routing.Route: make the afterCreate hook available for IE/Edge<commit_after>/*!
 * ${copyright}
 */
sap.ui.define(['sap/ui/Device', "sap/base/Log", "sap/ui/thirdparty/jquery"], function(Device, Log, jQuery) {
	"use strict";

	/**
	 * Provide methods for sap.ui.core.routing.Route in async mode
	 * @private
	 * @experimental
	 * @since 1.33
	 */
	return {

		/**
		 * @private
		 */
		_routeMatched : function(oArguments, oSequencePromise, oNestingChild) {

			var oRouter = this._oRouter,
				oTarget,
				oConfig,
				oEventData,
				oView = null,
				oTargetControl = null,
				bInitial,
				oTargetData,
				oCurrentPromise,
				that = this;

			oRouter._matchedRoute = this;

			if (!oSequencePromise || oSequencePromise === true) {
				bInitial = true;
				oSequencePromise = Promise.resolve();
			}

			// Recursively fire matched event and display views of this routes parents
			if (this._oParent) {
				oSequencePromise = this._oParent._routeMatched(oArguments, oSequencePromise);
			} else if (this._oNestingParent) {
				// pass child for setting the flag in event parameter of parent
				this._oNestingParent._routeMatched(oArguments, oSequencePromise, this);
			}

			oConfig = jQuery.extend({}, oRouter._oConfig, this._oConfig);

			// make a copy of arguments and forward route config to target
			oTargetData = jQuery.extend({}, oArguments);
			oTargetData.routeConfig = oConfig;

			oEventData = {
				name: oConfig.name,
				arguments: oArguments,
				config : oConfig
			};

			if (oNestingChild) {
				// setting the event parameter of nesting child
				oEventData.nestedRoute = oNestingChild;
			}

			// fire the beforeMatched and beforeRouteMathced events
			this.fireBeforeMatched(oEventData);
			oRouter.fireBeforeRouteMatched(oEventData);

			// Route is defined without target in the config - use the internally created target to place the view
			if (this._oTarget) {
				oTarget = this._oTarget;
				// update the targets config so defaults are taken into account - since targets cannot be added in runtime they don't merge configs like routes do
				oTarget._updateOptions(this._convertToTargetOptions(oConfig));

				oSequencePromise = oTarget._place(oSequencePromise);

				// this is for sap.m.routing.Router to chain the promise to the navigation promise in TargetHandler
				if (this._oRouter._oTargetHandler && this._oRouter._oTargetHandler._chainNavigation) {
					oCurrentPromise = oSequencePromise;
					oSequencePromise = this._oRouter._oTargetHandler._chainNavigation(function() {
						return oCurrentPromise;
					});
				}
			} else { // let targets do the placement + the events
				if (!this._oConfig.afterCreateHook) {
					this._oConfig.afterCreateHook = function(oTargetObject) {
						if (oTargetObject.isA("sap.ui.core.UIComponent")) {
							var oRouter = oTargetObject.getRouter();
							if (oRouter) {
								that.attachEvent("switched", function() {
									// stop the router in nested component when the Route which loads it is navigated away
									oRouter.stop();
								});
							}
						}
					};
				}

				if (Device.browser.msie || Device.browser.edge) {
					oCurrentPromise = oSequencePromise;

					// when Promise polyfill is used for IE or Edge, the synchronous DOM or CSS change, e.g. showing a busy indicator, doesn't get
					// a slot for being executed. Therefore a explicit 0 timeout is added for allowing the DOM or CSS change to be executed before
					// the view is loaded.
					oSequencePromise = new Promise(function(resolve, reject) {
						setTimeout(function() {
							var oDisplayPromise = oRouter._oTargets._display(that._oConfig.target, oTargetData, that._oConfig.titleTarget, oCurrentPromise, that._oConfig.afterCreateHook);
							oDisplayPromise.then(resolve, reject);
						}, 0);
					});
				} else {
					oSequencePromise = oRouter._oTargets._display(this._oConfig.target, oTargetData, this._oConfig.titleTarget, oSequencePromise, this._oConfig.afterCreateHook);
				}
			}

			return oSequencePromise.then(function(oResult) {
				oResult = oResult || {};

				oView = oResult.view;
				oTargetControl = oResult.control;

				// Extend the event data with view and targetControl
				oEventData.view = oView;
				oEventData.targetControl = oTargetControl;

				if (oConfig.callback) {
					//Targets don't pass TargetControl and view since there might be multiple
					oConfig.callback(this, oArguments, oConfig, oTargetControl, oView);
				}

				this.fireEvent("matched", oEventData);
				oRouter.fireRouteMatched(oEventData);
				// skip this event in the recursion
				if (bInitial) {
					Log.info("The route named '" + oConfig.name + "' did match with its pattern", this);
					this.fireEvent("patternMatched", oEventData);
					oRouter.fireRoutePatternMatched(oEventData);
				}

				return oResult;
			}.bind(this));
		}
	};
});
<|endoftext|>


<commit_before>#! /usr/bin/env node

'use strict'

const generators = require('./generators')
const meow = require('meow')
const path = require('path')
const version = require('../package').version

console.log(`  👋   hello (v${version})`)
console.log('')

const cli = meow(`
Usage
  $ hello <name>
  $ hello new <name>
  $ hello new <app|controller|model|view|migration|scaffold|user> <name>
  $ hello migrate <up|down>

Options
  --empty, -e  Generate the controller/model/migration without any contents

Examples
  $ hello blog
  $ hello new scaffold BlogPosts
  $ hello migrate
`)

// If no arguments are passed, show help
if (cli.input.length === 0) {
  cli.showHelp(0)
}

run(cli.input[0], cli.input[1], cli.input[2], cli.flags)

/**
 * Handle the cli input
 *
 * @param {String} action - The action to perform (new, generate)
 * @param {String} command - The command to pass to the generator or migrator
 * @param {String} name - The name of the item to create, if any
 * @param {Object} flags - The flags/options passed to the command line
 */
function run (action, command, name, flags) {
  switch (action) {
    case 'new':
    case 'generate':
    case 'g':
      generate(command, name, flags)
      break
    case 'migrate':
      migrate(command || 'up')
      break
    case 'up':
      migrate('up')
      break
    case 'down':
    case 'rollback':
      migrate('down')
      break
    default:
      run('new', action, command, flags)
  }
}

/**
 * Run a given generator
 *
 * @param {String} generatorName - The name of the generator to run
 * @param {String} name - The name of the generated item
 * @param {Object} flags - The flags passed to the generator
 */
function generate (generatorName, name, flags) {
  let generator

  switch (generatorName) {
    case 'app':
      generator = new generators.App(name)
      break
    case 'controller':
      generator = new generators.Controller(name, flags)
      break
    case 'model':
      generator = new generators.Model(name, flags)
      break
    case 'view':
      console.log(`generating view ${name} ...`)
      console.log('NotImplemented. View generation not yet available')
      break
    case 'migration':
      generator = new generators.Migration(name, flags)
      break
    case 'scaffold':
      console.log(`generating scaffold ${name} ...`)
      console.log('NotImplemented. Scaffold generation not yet available')
      break
    case 'user':
      console.log(`generating user ${name} ...`)
      console.log('NotImplemented. User generation not yet available')
      break
    default:
      if (!name) {
        return generate('app', generatorName)
      }
  }

  if (!generator) {
    return cli.showHelp(0)
  }

  return generator.run()
}

/**
 * Run the migrations in a given direction.
 *
 * @param {String} direction - The direcation to run, can be 'up' or 'down'
 */
function migrate (direction) {
  let config = require(path.join(process.cwd(), '.', 'config'))
  let db = require(path.join(process.cwd(), '.', 'db'))

  if (direction === 'up') {
    return db.migrate.latest(config.db)
  } else if (direction === 'down') {
    return db.migrate.rollback(config.db)
  }

  return cli.showHelp(0)
}
<commit_msg>Fix CLI migration runner<commit_after>#! /usr/bin/env node

'use strict'

const generators = require('./generators')
const meow = require('meow')
const path = require('path')
const version = require('../package').version

console.log(`  👋   hello (v${version})`)
console.log('')

const cli = meow(`
Usage
  $ hello <name>
  $ hello new <name>
  $ hello new <app|controller|model|view|migration|scaffold|user> <name>
  $ hello migrate <up|down>

Options
  --empty, -e  Generate the controller/model/migration without any contents

Examples
  $ hello blog
  $ hello new scaffold BlogPosts
  $ hello migrate
`)

// If no arguments are passed, show help
if (cli.input.length === 0) {
  cli.showHelp(0)
}

run(cli.input[0], cli.input[1], cli.input[2], cli.flags)

/**
 * Handle the cli input
 *
 * @param {String} action - The action to perform (new, generate)
 * @param {String} command - The command to pass to the generator or migrator
 * @param {String} name - The name of the item to create, if any
 * @param {Object} flags - The flags/options passed to the command line
 */
function run (action, command, name, flags) {
  switch (action) {
    case 'new':
    case 'generate':
    case 'g':
      generate(command, name, flags)
      break
    case 'migrate':
      migrate(command || 'up')
      break
    case 'up':
      migrate('up')
      break
    case 'down':
    case 'rollback':
      migrate('down')
      break
    default:
      run('new', action, command, flags)
  }
}

/**
 * Run a given generator
 *
 * @param {String} generatorName - The name of the generator to run
 * @param {String} name - The name of the generated item
 * @param {Object} flags - The flags passed to the generator
 */
function generate (generatorName, name, flags) {
  let generator

  switch (generatorName) {
    case 'app':
      generator = new generators.App(name)
      break
    case 'controller':
      generator = new generators.Controller(name, flags)
      break
    case 'model':
      generator = new generators.Model(name, flags)
      break
    case 'view':
      console.log(`generating view ${name} ...`)
      console.log('NotImplemented. View generation not yet available')
      break
    case 'migration':
      generator = new generators.Migration(name, flags)
      break
    case 'scaffold':
      console.log(`generating scaffold ${name} ...`)
      console.log('NotImplemented. Scaffold generation not yet available')
      break
    case 'user':
      console.log(`generating user ${name} ...`)
      console.log('NotImplemented. User generation not yet available')
      break
    default:
      if (!name) {
        return generate('app', generatorName)
      }
  }

  if (!generator) {
    return cli.showHelp(0)
  }

  return generator.run()
}

/**
 * Run the migrations in a given direction.
 *
 * @param {String} direction - The direcation to run, can be 'up' or 'down'
 */
function migrate (direction) {
  let config = require(path.join(process.cwd(), '.', 'config'))
  let db = require(path.join(process.cwd(), '.', 'db'))

  if (direction === 'up') {
    return db.knex.migrate.latest(config.db)
  } else if (direction === 'down') {
    return db.knex.migrate.rollback(config.db)
  }

  return cli.showHelp(0)
}
<|endoftext|>


<commit_before>var CoreView = require('backbone/core-view');
var template = require('./embed-banner.tpl');
var checkAndBuildOpts = require('builder/helpers/required-opts');

const SIGN_UP_URL = 'https://carto.com/signup';
const REMOVE_BANNER_URL = 'https://carto.com/help';

var EmbedBannerView = CoreView.extend({

  className: 'CDB-Embed-banner--inner',

  initialize: function (options) {
    // checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this.template = template;

    this._baseUrl = window.baseUrl + '/builder/' + window.vizJSON.id + '/embed';

    this._startNowUrl = SIGN_UP_URL +
    '?utm_source=' + window.location.href +
    '&utm_medium=referral' +
    '&utm_campaing=Free_Public_Map_Banner';
    this._removeBannerUrl = REMOVE_BANNER_URL;
  },

  render: function () {
    this.$el.html(this.template({
      startNowUrl: this.startNowUrl,
      removeBannerUrl: this._removeBannerUrl
    }));
    return this;
  }
});

module.exports = EmbedBannerView;
<commit_msg>Remove non used var<commit_after>var CoreView = require('backbone/core-view');
var template = require('./embed-banner.tpl');

const SIGN_UP_URL = 'https://carto.com/signup';
const REMOVE_BANNER_URL = 'https://carto.com/help';

var EmbedBannerView = CoreView.extend({

  className: 'CDB-Embed-banner--inner',

  initialize: function (options) {
    // checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this.template = template;

    this._baseUrl = window.baseUrl + '/builder/' + window.vizJSON.id + '/embed';

    this._startNowUrl = SIGN_UP_URL +
    '?utm_source=' + window.location.href +
    '&utm_medium=referral' +
    '&utm_campaing=Free_Public_Map_Banner';
    this._removeBannerUrl = REMOVE_BANNER_URL;
  },

  render: function () {
    this.$el.html(this.template({
      startNowUrl: this.startNowUrl,
      removeBannerUrl: this._removeBannerUrl
    }));
    return this;
  }
});

module.exports = EmbedBannerView;
<|endoftext|>


<commit_before>export default Ember.Component.extend({
  tagName: 'li',
  classNames: ['tree-node'],
  classNameBindings: ['focused'],

  dragging: false,

  getBaselineRatio: function() {
    var container = document.createElement('div');
    var small = document.createElement('span');
    var large = document.createElement('span');

    container.style.visibility = "hidden";
    small.style.fontSize = "0px";
    large.style.fontSize = "1800px";

    small.innerHTML = "X";
    large.innerHTML = "X";

    container.appendChild(small);
    container.appendChild(large);

    document.body.appendChild(container);
    var smalldims = small.getBoundingClientRect();
    var largedims = large.getBoundingClientRect();
    var baselineposition = smalldims.top - largedims.top;
    var height = largedims.height;
    document.body.removeChild(container);

    return 1 - (baselineposition / height);
  },

  dragproxy: function() {
    var svgnamespace = 'http://www.w3.org/2000/svg';
    var name = this.get('node.value.name');
    var splits = name.split(/([\.\_\-]{1})/);
    splits = splits.map(function(item) { return '<tspan style="text-anchor: middle;">' + item + "</tspan>"; });

    var dragproxy = document.createElementNS(svgnamespace, "svg");
    dragproxy.setAttribute("version", "1.1");
    dragproxy.setAttribute('class', 'dragproxy');

    var circle = document.createElementNS(svgnamespace, 'circle');
    circle.setAttribute('fill', 'green');

    var text = document.createElementNS(svgnamespace, 'text');
    text.innerHTML = splits.join('');

    // Much easier than instantiating them individually. :)
    var tspans = [].slice.call(text.getElementsByTagName('tspan'));

    dragproxy.appendChild(circle);
    dragproxy.appendChild(text);

    document.body.appendChild(dragproxy);

    /* Now that it's real, let's do some calculations on it to lay it out correctly. */
    var absoluteminheight = tspans[0].getBoundingClientRect().height;
    var absolutemaxheight = absoluteminheight * tspans.length;

    var absolutemaxwidth = text.getBoundingClientRect().width;
    var absoluteminwidth = tspans.reduce(function(previousmin, elem) {
      return Math.min(previousmin, elem.getBoundingClientRect().width);
    }, absolutemaxwidth);

    var baselineshift = this.getBaselineRatio() * absoluteminheight;

    var radius, numrows;
    if (tspans.length === 1) {
      // Account for the fact that the tspan is rectangular, not linear.
      var a = absolutemaxwidth / 2;
      var b = absolutemaxheight / 2;
      radius = Math.sqrt(a*a+b*b);
      numrows = 1;
    } else {
      // FIXME: Make this actually search through the space.
      // FIXME: Account for the fact that the tspan is rectangular, not linear.
      var searchrange = {
        min: Math.min(absoluteminwidth, absoluteminheight),
        max: Math.max(absolutemaxwidth, absolutemaxheight)
      }

      var a = absolutemaxwidth / 2;
      var b = absolutemaxheight / 2;
      radius = Math.sqrt(a*a+b*b);
      numrows = 1;
    }

    // Vertically centering the tspans in the circle means knowing how tall they are.
    var topspace = ((radius * 2) - (numrows * absoluteminheight))/2;

    circle.setAttribute('cx', radius);
    circle.setAttribute('cy', radius);
    circle.setAttribute('r', radius);
    text.setAttribute('x', 0);
    text.setAttribute('y', topspace + absoluteminheight - baselineshift);

    tspans.forEach(function(tspan, index) {
      tspan.setAttribute('x', radius);
      if (index) {
        tspan.setAttribute('dy', absoluteminheight);
      }
    });

    document.body.removeChild(dragproxy);

    dragproxy.setAttribute('width', (radius*2)+'px');
    dragproxy.setAttribute('height', (radius*2)+'px')
    return dragproxy;
  }.property(),

  // node: undefined,
  // currentNode: undefined,

  focused: function() {
    return this.get('currentNode') == this.get('node');
  }.property('currentNode'),

  actions: {
    focus: function(node) {
      this.sendAction('focus', node);
    }
  },

  mouseDown: function(e) {
    if (e.target !== this.$('> .target')[0]) { return; }

    e.preventDefault();

    var dragproxy = this.get('dragproxy');

    document.body.appendChild(dragproxy);
    var dims = dragproxy.getBoundingClientRect();

    var mouseMoveHandler = function(e) {
      e.preventDefault();

      this.set('dragging', true);
      document.body.classList.add('dragging');

      var x = e.pageX - (dims.width/2) + 'px';
      var y = e.pageY - (dims.height/2) + 'px'

      dragproxy.style.webkitTransform = "translate("+x+", "+y+")";
      dragproxy.style.transform = "translate("+x+", "+y+")";
    }.bind(this);

    var mouseUpHandler = function(e) {
      e.preventDefault();
      document.body.removeEventListener('mousemove', mouseMoveHandler);
      document.body.removeEventListener('mouseup', mouseUpHandler);
      document.body.classList.remove('dragging');

      // Clean up
      document.body.removeChild(dragproxy);
      dragproxy.style.webkitTransform = '';
      dragproxy.style.transform = '';

      this.set('dragging', false);
    }.bind(this);

    document.body.addEventListener('mousemove', mouseMoveHandler);
    document.body.addEventListener('mouseup', mouseUpHandler);
  }
});
<commit_msg>Set and enforce a minimum radius.<commit_after>export default Ember.Component.extend({
  tagName: 'li',
  classNames: ['tree-node'],
  classNameBindings: ['focused'],

  dragging: false,

  getBaselineRatio: function() {
    var container = document.createElement('div');
    var small = document.createElement('span');
    var large = document.createElement('span');

    container.style.visibility = "hidden";
    small.style.fontSize = "0px";
    large.style.fontSize = "1800px";

    small.innerHTML = "X";
    large.innerHTML = "X";

    container.appendChild(small);
    container.appendChild(large);

    document.body.appendChild(container);
    var smalldims = small.getBoundingClientRect();
    var largedims = large.getBoundingClientRect();
    var baselineposition = smalldims.top - largedims.top;
    var height = largedims.height;
    document.body.removeChild(container);

    return 1 - (baselineposition / height);
  },

  dragproxy: function() {
    var minradius = 40;
    var radiuspadding = 5;

    var svgnamespace = 'http://www.w3.org/2000/svg';
    var name = this.get('node.value.name');
    var splits = name.split(/([\.\_\-]{1})/);
    splits = splits.map(function(item) { return '<tspan style="text-anchor: middle;">' + item + "</tspan>"; });

    var dragproxy = document.createElementNS(svgnamespace, "svg");
    dragproxy.setAttribute("version", "1.1");
    dragproxy.setAttribute('class', 'dragproxy');

    var circle = document.createElementNS(svgnamespace, 'circle');
    circle.setAttribute('fill', 'green');

    var text = document.createElementNS(svgnamespace, 'text');
    text.innerHTML = splits.join('');

    // Much easier than instantiating them individually. :)
    var tspans = [].slice.call(text.getElementsByTagName('tspan'));

    dragproxy.appendChild(circle);
    dragproxy.appendChild(text);

    document.body.appendChild(dragproxy);

    /* Now that it's real, let's do some calculations on it to lay it out correctly. */
    var absoluteminheight = tspans[0].getBoundingClientRect().height;
    var absolutemaxheight = absoluteminheight * tspans.length;

    var absolutemaxwidth = text.getBoundingClientRect().width;
    var absoluteminwidth = tspans.reduce(function(previousmin, elem) {
      return Math.min(previousmin, elem.getBoundingClientRect().width);
    }, absolutemaxwidth);

    var baselineshift = this.getBaselineRatio() * absoluteminheight;

    var radius, numrows;
    if (tspans.length === 1) {
      // Account for the fact that the tspan is rectangular, not linear.
      var a = absolutemaxwidth / 2;
      var b = absolutemaxheight / 2;
      radius = Math.sqrt(a*a+b*b);
      numrows = 1;
    } else {
      // FIXME: Make this actually search through the space.
      // FIXME: Account for the fact that the tspan is rectangular, not linear.
      var searchrange = {
        min: Math.min(absoluteminwidth, absoluteminheight),
        max: Math.max(absolutemaxwidth, absolutemaxheight)
      }

      var a = absolutemaxwidth / 2;
      var b = absolutemaxheight / 2;
      radius = Math.sqrt(a*a+b*b);
      numrows = 1;
    }

    if (radius + radiuspadding > minradius) {
      // Add the padding at the right scale.
      radius += radiuspadding * radius / minradius;
    } else {
      // Enforce the minimum radius.
      radius = minradius;
    }

    // Vertically centering the tspans in the circle means knowing how tall they are.
    var topspace = ((radius * 2) - (numrows * absoluteminheight))/2;

    circle.setAttribute('cx', radius);
    circle.setAttribute('cy', radius);
    circle.setAttribute('r', radius);
    text.setAttribute('x', 0);
    text.setAttribute('y', topspace + absoluteminheight - baselineshift);

    tspans.forEach(function(tspan, index) {
      tspan.setAttribute('x', radius);
      if (index) {
        tspan.setAttribute('dy', absoluteminheight);
      }
    });

    document.body.removeChild(dragproxy);

    dragproxy.setAttribute('width', (radius*2)+'px');
    dragproxy.setAttribute('height', (radius*2)+'px')
    return dragproxy;
  }.property(),

  // node: undefined,
  // currentNode: undefined,

  focused: function() {
    return this.get('currentNode') == this.get('node');
  }.property('currentNode'),

  actions: {
    focus: function(node) {
      this.sendAction('focus', node);
    }
  },

  mouseDown: function(e) {
    if (e.target !== this.$('> .target')[0]) { return; }

    e.preventDefault();

    var dragproxy = this.get('dragproxy');

    document.body.appendChild(dragproxy);
    var dims = dragproxy.getBoundingClientRect();

    var mouseMoveHandler = function(e) {
      e.preventDefault();

      this.set('dragging', true);
      document.body.classList.add('dragging');

      var x = e.pageX - (dims.width/2) + 'px';
      var y = e.pageY - (dims.height/2) + 'px'

      dragproxy.style.webkitTransform = "translate("+x+", "+y+")";
      dragproxy.style.transform = "translate("+x+", "+y+")";
    }.bind(this);

    var mouseUpHandler = function(e) {
      e.preventDefault();
      document.body.removeEventListener('mousemove', mouseMoveHandler);
      document.body.removeEventListener('mouseup', mouseUpHandler);
      document.body.classList.remove('dragging');

      // Clean up
      document.body.removeChild(dragproxy);
      dragproxy.style.webkitTransform = '';
      dragproxy.style.transform = '';

      this.set('dragging', false);
    }.bind(this);

    document.body.addEventListener('mousemove', mouseMoveHandler);
    document.body.addEventListener('mouseup', mouseUpHandler);
  }
});
<|endoftext|>


<commit_before>import React from 'react'
import {Loading, GenericForm, Modal, Tip, Selector, Error} from 'app/components'
import rpc from 'app/rpc'
import Flash from 'app/flash'
import i18n from 'app/utils/i18n'
import cache from 'app/utils/cache'
import plugin from 'app/utils/plugin'
import Widget from 'app/containers/project/board/widget'

class SetupWidget extends React.Component{
  constructor(props){
    super(props)
    this.state= {
      config: {},
      delayed_config: {},
      delayed_config_timer: undefined,
    }
  }
  handleAddWidget(){
    return this.props.onAddWidget(this.state.config)
  }
  setConfig(config){
    let delayed_config_timer = this.state.delayed_config_timer
    if (delayed_config_timer)
      clearTimeout(delayed_config_timer)
    delayed_config_timer = setTimeout(
      () => this.setState({delayed_config: config, delayed_config_timer: undefined}),
      200 )

    this.setState({config, delayed_config_timer})
  }
  render(){
    const props = this.props
    const widget=props.widget

    let layout={x:0, y:0, h: 2, w: 2, minW: 1, minH: 1, width: 2, height: 2}

    console.log(widget)
    return (

                <Widget
                  key={widget.uuid}
                  widget={widget.id}
                  config={this.state.delayed_config}
                  uuid={widget.uuid}
                  project={this.props.project}
                  layout={layout}
                  />

{widget.name}

{widget.description}

            <GenericForm fields={widget.params} updateForm={(config) => this.setConfig(config)}/>

              <button type="button" className="ui basic button" onClick={this.props.cancelSetup}>
                {i18n("Back")}
              </button>
              { props.saveButtons ? (
                  props.saveButtons.map( sb => (
                    <button type="button" className={`ui button ${sb.className}`}
                        onClick={() => this.handleAddWidget().then( (data) => sb.onClick && sb.onClick(data) )}
                        >
                      {sb.label}
                    </button>
                  ))
              ) : (
                <button type="button" className="ui button teal" onClick={this.handleAddWidget.bind(this)}>
                  {i18n("Add widget")}
                </button>
              )}

    )
  }
}

function get_widget_market_catalog(){
  return Promise.all([
      plugin.start_call_stop(
            "serverboards.optional.update/catalog",
            "component_filter",
            {type: "widget"}
          )
      , cache.plugins()
    ]).then( (cp) => {
      const catalog = cp[0]
      const plugin_list = cp[1]
      // console.log("Got catalog %o // %o", catalog, plugin_list)
      return catalog.filter( c => !plugin_list[c.plugin] )
    })
}

class SelectWidget extends React.Component{
  constructor(props){
    super(props)

    this.state = {
      tab: 1
    }
  }
  handleInstallWidget(w){
    this.setState({tab:3})
    plugin.install(w.giturl).then(() => {
      const widget = {...w, type: w.id} // I need the component id in the type field.
      this.props.onSelectWidget(widget)
    }).catch((e) => {
      console.error(e)
      this.setState({tab:2})
      Flash.error(i18n("Error installing *{plugin}*. Please try again or check logs.", {plugin:w.name}))
    })
  }
  render(){
    const {state, props} = this
    const {tab} = state

    return (

            <input
              type="text"
              onChange={(ev) => {
                this.setState({filter:ev.target.value.toLocaleLowerCase().split(' ')})
              }}
              placeholder={i18n("Filter...")}
              />

            <i className={`icon cloud`}/>
            {i18n("Add a widget to this dashboard")}

            {i18n("Select the widget you want to add to the dashboard. If you can not find what you are looking for, check the marketplace.")}

          <a className={`item ${tab==1 ? "active" : ""}`} onClick={() => this.setState({tab:1})}>
            {i18n("Available services")}

          <a className={`item ${tab==2 ? "active" : ""}`} onClick={() => this.setState({tab:2})}>
            {i18n("Marketplace")}

        {tab == 1 ? (
          <Selector
            key="installed"
            get_items={cache.widget_catalog}
            onSelect={props.onSelectWidget}
            current={(props.widget || {}).id}
            show_filter={false}
            filter={state.filter}
            skip_label={props.skip_label}
            onSkip={props.onSkip}
            prev_label={props.prev_label}
            prevStep={props.prevStep}
          />
        ) : (tab==2) ? (
          <Selector
            key="marketplace"
            get_items={get_widget_market_catalog}
            onSelect={this.handleInstallWidget.bind(this)}
            current={(props.widget || {}).id}
            show_filter={false}
            filter={state.filter}
            skip_label={props.skip_label}
            onSkip={props.onSkip}
            prev_label={props.prev_label}
            prevStep={props.prevStep}
          />
        ) : (
          <Loading>
            {i18n("Installing plugin")}
          </Loading>
        ) }

    )
  }
}

class AddWidget extends React.Component{
  constructor(props){
    super(props)

    this.state = {
      step: 0
    }
  }
  handleSelectWidget(widget){
    if (!this.props.saveButtons && (!widget.params || widget.params.length==0)){
      // no more config
      this.props.addWidget( widget.id, this.props.dashboard_uuid, {} )
    }
    else
      this.setState({widget, step: 1})
  }
  handleAddWidget(config){
    return this.props.addWidget( this.state.widget.id, this.props.dashboard_uuid, config )
  }
  render(){
    let section=null
    switch(this.state.step){
      case 0:
        section = (

              <Tip
                className="ui round pane white background with padding"
                top_img={require("imgs/024-illustration-addaddons.svg")}
                title={i18n("Add widgets to your dashboards.")}
                middle_img={require("imgs/019-illustration-tips.svg")}
                subtitle={i18n("Dashboards allow to have a fast graphic view of your system.")}
                description={i18n(`Select a widget type from your left to be able to configure it.`)}
                  />

              <SelectWidget
                onSelectWidget={this.handleSelectWidget.bind(this)}
                widget={this.state.widget}
                {...this.props}
                />

        )
        break;
      case 1:
        section = (
          <SetupWidget
            widget={this.state.widget}
            cancelSetup={() => this.setState({step: 0})}
            onAddWidget={this.handleAddWidget.bind(this)}
            {...this.props}
            />
        )
        break;
      default:
        section = (
          <Error>
            {i18n("Unknown section")}
          </Error>
        )
        break;
    }

    return section
  }
}

export default AddWidget
<commit_msg>Fixed recomended size of widgets at widget add<commit_after>import React from 'react'
import {Loading, GenericForm, Modal, Tip, Selector, Error} from 'app/components'
import rpc from 'app/rpc'
import Flash from 'app/flash'
import i18n from 'app/utils/i18n'
import cache from 'app/utils/cache'
import plugin from 'app/utils/plugin'
import Widget from 'app/containers/project/board/widget'

class SetupWidget extends React.Component{
  constructor(props){
    super(props)
    this.state= {
      config: {},
      delayed_config: {},
      delayed_config_timer: undefined,
    }
  }
  handleAddWidget(){
    return this.props.onAddWidget(this.state.config)
  }
  setConfig(config){
    let delayed_config_timer = this.state.delayed_config_timer
    if (delayed_config_timer)
      clearTimeout(delayed_config_timer)
    delayed_config_timer = setTimeout(
      () => this.setState({delayed_config: config, delayed_config_timer: undefined}),
      200 )

    this.setState({config, delayed_config_timer})
  }
  render(){
    const props = this.props
    const widget=props.widget

    let layout={x:0, y:0, h: 2, w: 2, minW: 1, minH: 1, width: 2, height: 2}
    if (widget.hints)
      layout = {...layout, ...widget.hints}
    const width = Math.max(Math.min(layout.w, layout.maxW), layout.minW)*283
    let height = Math.max(Math.min(layout.h, layout.maxH), layout.minH)
    height = (height*135)+(height-1)*28

    return (

                <Widget
                  key={widget.uuid}
                  widget={widget.id}
                  config={this.state.delayed_config}
                  uuid={widget.uuid}
                  project={this.props.project}
                  layout={layout}
                  />

{widget.name}

{widget.description}

            <GenericForm fields={widget.params} updateForm={(config) => this.setConfig(config)}/>

              <button type="button" className="ui basic button" onClick={this.props.cancelSetup}>
                {i18n("Back")}
              </button>
              { props.saveButtons ? (
                  props.saveButtons.map( sb => (
                    <button type="button" className={`ui button ${sb.className}`}
                        onClick={() => this.handleAddWidget().then( (data) => sb.onClick && sb.onClick(data) )}
                        >
                      {sb.label}
                    </button>
                  ))
              ) : (
                <button type="button" className="ui button teal" onClick={this.handleAddWidget.bind(this)}>
                  {i18n("Add widget")}
                </button>
              )}

    )
  }
}

function get_widget_market_catalog(){
  return Promise.all([
      plugin.start_call_stop(
            "serverboards.optional.update/catalog",
            "component_filter",
            {type: "widget"}
          )
      , cache.plugins()
    ]).then( (cp) => {
      const catalog = cp[0]
      const plugin_list = cp[1]
      // console.log("Got catalog %o // %o", catalog, plugin_list)
      return catalog.filter( c => !plugin_list[c.plugin] )
    })
}

class SelectWidget extends React.Component{
  constructor(props){
    super(props)

    this.state = {
      tab: 1
    }
  }
  handleInstallWidget(w){
    this.setState({tab:3})
    plugin.install(w.giturl).then(() => {
      const widget = {...w, type: w.id} // I need the component id in the type field.
      this.props.onSelectWidget(widget)
    }).catch((e) => {
      console.error(e)
      this.setState({tab:2})
      Flash.error(i18n("Error installing *{plugin}*. Please try again or check logs.", {plugin:w.name}))
    })
  }
  render(){
    const {state, props} = this
    const {tab} = state

    return (

            <input
              type="text"
              onChange={(ev) => {
                this.setState({filter:ev.target.value.toLocaleLowerCase().split(' ')})
              }}
              placeholder={i18n("Filter...")}
              />

            <i className={`icon cloud`}/>
            {i18n("Add a widget to this dashboard")}

            {i18n("Select the widget you want to add to the dashboard. If you can not find what you are looking for, check the marketplace.")}

          <a className={`item ${tab==1 ? "active" : ""}`} onClick={() => this.setState({tab:1})}>
            {i18n("Available services")}

          <a className={`item ${tab==2 ? "active" : ""}`} onClick={() => this.setState({tab:2})}>
            {i18n("Marketplace")}

        {tab == 1 ? (
          <Selector
            key="installed"
            get_items={cache.widget_catalog}
            onSelect={props.onSelectWidget}
            current={(props.widget || {}).id}
            show_filter={false}
            filter={state.filter}
            skip_label={props.skip_label}
            onSkip={props.onSkip}
            prev_label={props.prev_label}
            prevStep={props.prevStep}
          />
        ) : (tab==2) ? (
          <Selector
            key="marketplace"
            get_items={get_widget_market_catalog}
            onSelect={this.handleInstallWidget.bind(this)}
            current={(props.widget || {}).id}
            show_filter={false}
            filter={state.filter}
            skip_label={props.skip_label}
            onSkip={props.onSkip}
            prev_label={props.prev_label}
            prevStep={props.prevStep}
          />
        ) : (
          <Loading>
            {i18n("Installing plugin")}
          </Loading>
        ) }

    )
  }
}

class AddWidget extends React.Component{
  constructor(props){
    super(props)

    this.state = {
      step: 0
    }
  }
  handleSelectWidget(widget){
    if (!this.props.saveButtons && (!widget.params || widget.params.length==0)){
      // no more config
      this.props.addWidget( widget.id, this.props.dashboard_uuid, {} )
    }
    else
      this.setState({widget, step: 1})
  }
  handleAddWidget(config){
    return this.props.addWidget( this.state.widget.id, this.props.dashboard_uuid, config )
  }
  render(){
    let section=null
    switch(this.state.step){
      case 0:
        section = (

              <Tip
                className="ui round pane white background with padding"
                top_img={require("imgs/024-illustration-addaddons.svg")}
                title={i18n("Add widgets to your dashboards.")}
                middle_img={require("imgs/019-illustration-tips.svg")}
                subtitle={i18n("Dashboards allow to have a fast graphic view of your system.")}
                description={i18n(`Select a widget type from your left to be able to configure it.`)}
                  />

              <SelectWidget
                onSelectWidget={this.handleSelectWidget.bind(this)}
                widget={this.state.widget}
                {...this.props}
                />

        )
        break;
      case 1:
        section = (
          <SetupWidget
            widget={this.state.widget}
            cancelSetup={() => this.setState({step: 0})}
            onAddWidget={this.handleAddWidget.bind(this)}
            {...this.props}
            />
        )
        break;
      default:
        section = (
          <Error>
            {i18n("Unknown section")}
          </Error>
        )
        break;
    }

    return section
  }
}

export default AddWidget
<|endoftext|>