<commit_before>//ranking is mostly arbitrary
var Groupsranking = [' ', 'T', 'L', 'F', 'ß', 'α', 'P', 'Θ', 'Σ', 'C', ];
var Groups = {

        'C': {
                id: "champion",
                name: "Champion",
                rank: 9
        },
        'Σ': {
                id: "elite",
                name: "Elite",
                rank: 8
        },
        'Θ': {
                id: "rg",
                name: "Royal Guard",
                rank: 7
        },
        'P': {
                id: "professor",
                name: "Professor",
                rank: 6
        },
        'α': {
        	id: "ace",
        	name: "Ace",
        	rank: 5
        },
        'ß': {
                id: "brain",
                name: "Frontier Brain",
                rank: 4
        },
        'F': {
                id: "frontier",
                name: "Frontier",
                rank: 3
        },
        'L': {
                id: "gleader",
                name: "Gym Leader",
                rank: 2
        },
        'T': {
                id: "trainer",
                name: "Gym Trainer",
                rank: 1
        },
        ' ': {
                rank: 0
        }
}

exports.commands = {
        leaguedeauth: 'leaguepromote',
        roomtrainer: 'leaguepromote',
        roomgleader: 'leaguepromote',
        roomfrontier: 'leaguepromote',
        roombrain: 'leaguepromote',
        roomace: 'leaguepromote',
        roomprofessor: 'leaguepromote',
        roomrg: 'leaguepromote',
        roomelite: 'leaguepromote',
        roomchampion: 'leaguepromote',
        leaguedemote: 'leagueauth',
        leaguepromote: function (target, room, user, connection, cmd) {
                if (!room.auth) {
                        this.sendReply("/leagueauth - This room isn't designed for per-room moderation");
                        return this.sendReply("Before setting league staff, you need to set it up with /roomfounder");
                }
                if (!target) return this.parse('/leagueauth [user] - Giver a user a rank in a league. Use /leagueauthhelp for more help.');
                if (!this.can('roommod', null, room)) return false;

                target = this.splitTarget(target, true);
                var targetUser = this.targetUser;
                var userid = toId(this.targetUsername);
                var name = targetUser ? targetUser.name : this.targetUsername;

                if (!userid) return this.parse('/leagueauthhelp');
                if (!targetUser && (!room.auth || !room.auth[userid])) {
                        return this.sendReply("User '" + name + "' is offline and unauthed, and so can't be promoted.");
                }

                var currentGroup = ((room.leagueauth&& room.leagueauth[userid]) || ' ')[0];
                var nextGroup = target;
                if (target === 'leaguedeauth') nextGroup = Groupsranking[0];

                if (cmd==='roomtrainer') {
                        nextGroup = Groupsranking[1];
                } else if (cmd==='roomgleader') {
                        nextGroup = Groupsranking[2];
                } else if (cmd==='roomfrontier') {
                        nextGroup = Groupsranking[3];
                } else if (cmd==='roombrain') {
                        nextGroup = Groupsranking[4];
                } else if (cmd==='roomace') {
                        nextGroup = Groupsranking[5];
                } else if (cmd==='roomprofessor') {
                        nextGroup = Groupsranking[6];
                } else if (cmd==='roomrg') {
                        nextGroup = Groupsranking[7];
                } else if (cmd==='roomelite') {
                        nextGroup = Groupsranking[8];
                } else if (cmd==='roomchampion') {
                        nextGroup = Groupsranking[9];
                } else if (cmd==='leaguedeauth') {
                        nextGroup = Groupsranking[0];
                }

                if (!nextGroup) {
			return this.sendReply("Please specify a group such as /roomgldeader or /roomtrainer");
		}

		if (!Groups[nextGroup]) {
                        return this.sendReply("Group '" + nextGroup + "' does not exist.");
                }

                var groupName = Groups[nextGroup].name || "regular user";
                if (currentGroup === nextGroup) {
                        return this.sendReply("User '" + name + "' is already a " + groupName + " in this room.");
                }

                if (nextGroup === ' ') {
                        delete room.leagueauth[userid];
                } else {
                        room.leagueauth[userid] = nextGroup;
                }

                if (Groups[nextGroup].rank < Groups[currentGroup].rank) {
                        this.privateModCommand("(" + name + " was changed to " + groupName + " by " + user.name + ".)");
                        if (targetUser && Rooms.rooms[room.id].users[targetUser.userid]) targetUser.popup("You were changed to " + groupName + " by " + user.name + ".");
                } else {
                        this.addModCommand("" + name + " was changed to " + groupName + " by " + user.name + ".");
                }

                if (targetUser) targetUser.updateIdentity(room.id);
                if (room.chatRoomData) Rooms.global.writeChatRoomData();
        },
	leagueauth: function (target, room, user, connection) {
		var targetRoom = room;
		if (target) targetRoom = Rooms.search(target);
		if (!targetRoom || (targetRoom !== room && targetRoom.modjoin && !user.can('bypassall'))) return this.sendReply("The room '" + target + "' does not exist.");
		if (!targetRoom.auth) return this.sendReply("/roomauth - The room '" + (targetRoom.title ? targetRoom.title : target) + "' isn't designed for per-room moderation and therefore has no auth list.");

		var rankLists = {};
		for (var u in targetRoom.leagueauth) {
			if (!rankLists[targetRoom.leagueauth[u]]) rankLists[targetRoom.leagueauth[u]] = [];
			rankLists[targetRoom.leagueauth[u]].push(u);
		}

		var buffer = [];
		Object.keys(rankLists).sort(function (a, b) {
			return (Groups[b] || {rank:0}).rank - (Groups[a] || {rank:0}).rank;
		}).forEach(function (r) {
			buffer.push((Groups[r] ? Groups[r] .name + "s (" + r + ")" : r) + ":\n" + rankLists[r].sort().join(", "));
		});

		if (!buffer.length) {
			connection.popup("The room '" + targetRoom.title + "' has no league auth.");
			return;
		}
		if (targetRoom !== room) buffer.unshift("" + targetRoom.title + " room auth:");
		connection.popup(buffer.join("\n\n"));
	},
}
<commit_msg>Update leagueauth.js<commit_after>//ranking is mostly arbitrary
var Groupsranking = [' ', 'τ', '£', 'ϝ', 'ß', 'α', 'ϸ', 'Θ', 'Σ', '©', ];
var Groups = {

        '©': {
                id: "champion",
                name: "Champion",
                rank: 9
        },
        'Σ': {
                id: "elite",
                name: "Elite",
                rank: 8
        },
        'Θ': {
                id: "rg",
                name: "Royal Guard",
                rank: 7
        },
        'ϸ': {
                id: "professor",
                name: "Professor",
                rank: 6
        },
        'α': {
        	id: "ace",
        	name: "Ace",
        	rank: 5
        },
        'ß': {
                id: "brain",
                name: "Frontier Brain",
                rank: 4
        },
        'ϝ': {
                id: "frontier",
                name: "Frontier",
                rank: 3
        },
        '£': {
                id: "gleader",
                name: "Gym Leader",
                rank: 2
        },
        'τ': {
                id: "trainer",
                name: "Gym Trainer",
                rank: 1
        },
        ' ': {
                rank: 0
        }
}

exports.commands = {
        leaguedeauth: 'leaguepromote',
        roomtrainer: 'leaguepromote',
        roomgleader: 'leaguepromote',
        roomfrontier: 'leaguepromote',
        roombrain: 'leaguepromote',
        roomace: 'leaguepromote',
        roomprofessor: 'leaguepromote',
        roomrg: 'leaguepromote',
        roomelite: 'leaguepromote',
        roomchampion: 'leaguepromote',
        leaguedemote: 'leagueauth',
        leaguepromote: function (target, room, user, connection, cmd) {
                if (!room.auth) {
                        this.sendReply("/leagueauth - This room isn't designed for per-room moderation");
                        return this.sendReply("Before setting league staff, you need to set it up with /roomfounder");
                }
                if (!target) return this.parse('/leagueauth [user] - Giver a user a rank in a league. Use /leagueauthhelp for more help.');
                if (!this.can('roommod', null, room)) return false;

                target = this.splitTarget(target, true);
                var targetUser = this.targetUser;
                var userid = toId(this.targetUsername);
                var name = targetUser ? targetUser.name : this.targetUsername;

                if (!userid) return this.parse('/leagueauthhelp');
                if (!targetUser && (!room.auth || !room.auth[userid])) {
                        return this.sendReply("User '" + name + "' is offline and unauthed, and so can't be promoted.");
                }

                var currentGroup = ((room.leagueauth&& room.leagueauth[userid]) || ' ')[0];
                var nextGroup = target;
                if (target === 'leaguedeauth') nextGroup = Groupsranking[0];

                if (cmd==='roomtrainer') {
                        nextGroup = Groupsranking[1];
                } else if (cmd==='roomgleader') {
                        nextGroup = Groupsranking[2];
                } else if (cmd==='roomfrontier') {
                        nextGroup = Groupsranking[3];
                } else if (cmd==='roombrain') {
                        nextGroup = Groupsranking[4];
                } else if (cmd==='roomace') {
                        nextGroup = Groupsranking[5];
                } else if (cmd==='roomprofessor') {
                        nextGroup = Groupsranking[6];
                } else if (cmd==='roomrg') {
                        nextGroup = Groupsranking[7];
                } else if (cmd==='roomelite') {
                        nextGroup = Groupsranking[8];
                } else if (cmd==='roomchampion') {
                        nextGroup = Groupsranking[9];
                } else if (cmd==='leaguedeauth') {
                        nextGroup = Groupsranking[0];
                }

                if (!nextGroup) {
			return this.sendReply("Please specify a group such as /roomgldeader or /roomtrainer");
		}

		if (!Groups[nextGroup]) {
                        return this.sendReply("Group '" + nextGroup + "' does not exist.");
                }

                var groupName = Groups[nextGroup].name || "regular user";
                if (currentGroup === nextGroup) {
                        return this.sendReply("User '" + name + "' is already a " + groupName + " in this room.");
                }

                if (nextGroup === ' ') {
                        delete room.leagueauth[userid];
                } else {
                        room.leagueauth[userid] = nextGroup;
                }

                if (Groups[nextGroup].rank < Groups[currentGroup].rank) {
                        this.privateModCommand("(" + name + " was changed to " + groupName + " by " + user.name + ".)");
                        if (targetUser && Rooms.rooms[room.id].users[targetUser.userid]) targetUser.popup("You were changed to " + groupName + " by " + user.name + ".");
                } else {
                        this.addModCommand("" + name + " was changed to " + groupName + " by " + user.name + ".");
                }

                if (targetUser) targetUser.updateIdentity(room.id);
                if (room.chatRoomData) Rooms.global.writeChatRoomData();
        },
	leagueauth: function (target, room, user, connection) {
		var targetRoom = room;
		if (target) targetRoom = Rooms.search(target);
		if (!targetRoom || (targetRoom !== room && targetRoom.modjoin && !user.can('bypassall'))) return this.sendReply("The room '" + target + "' does not exist.");
		if (!targetRoom.auth) return this.sendReply("/roomauth - The room '" + (targetRoom.title ? targetRoom.title : target) + "' isn't designed for per-room moderation and therefore has no auth list.");

		var rankLists = {};
		for (var u in targetRoom.leagueauth) {
			if (!rankLists[targetRoom.leagueauth[u]]) rankLists[targetRoom.leagueauth[u]] = [];
			rankLists[targetRoom.leagueauth[u]].push(u);
		}

		var buffer = [];
		Object.keys(rankLists).sort(function (a, b) {
			return (Groups[b] || {rank:0}).rank - (Groups[a] || {rank:0}).rank;
		}).forEach(function (r) {
			buffer.push((Groups[r] ? Groups[r] .name + "s (" + r + ")" : r) + ":\n" + rankLists[r].sort().join(", "));
		});

		if (!buffer.length) {
			connection.popup("The room '" + targetRoom.title + "' has no league auth.");
			return;
		}
		if (targetRoom !== room) buffer.unshift("" + targetRoom.title + " room auth:");
		connection.popup(buffer.join("\n\n"));
	},
}
<|endoftext|>


<commit_before>(function($) {
    $.isScrollToFixed = function(el) {
        return $(el).data('ScrollToFixed') !== undefined;
    };

    $.ScrollToFixed = function(el, options) {
        // To avoid scope issues, use 'base' instead of 'this' to reference this
        // class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element.
        base.$el = $(el);
        base.el = el;

        // Add a reverse reference to the DOM object.
        base.$el.data('ScrollToFixed', base);

        // A flag so we know if the scroll has been reset.
        var isReset = false;

        // The element that was given to us to fix if scrolled above the top of
        // the page.
        var target = base.$el;

        var position;
        var originalPosition;

        var originalOffset;

        // The offset top of the element when resetScroll was called. This is
        // used to determine if we have scrolled past the top of the element.
        var offsetTop = 0;

        // The offset left of the element when resetScroll was called. This is
        // used to move the element left or right relative to the horizontal
        // scroll.
        var offsetLeft = 0;
        var originalOffsetLeft = -1;

        // This last offset used to move the element horizontally. This is used
        // to determine if we need to move the element because we would not want
        // to do that for no reason.
        var lastOffsetLeft = -1;

        // This is the element used to fill the void left by the target element
        // when it goes fixed; otherwise, everything below it moves up the page.
        var spacer = null;

        var spacerClass;

        var className;

        // Capture the original offsets for the target element. This needs to be
        // called whenever the page size changes or when the page is first
        // scrolled. For some reason, calling this before the page is first
        // scrolled causes the element to become fixed too late.
        function resetScroll() {
            // Set the element to it original positioning.
            target.trigger('preUnfixed.ScrollToFixed');
            setUnfixed();
            target.trigger('unfixed.ScrollToFixed');

            // Reset the last offset used to determine if the page has moved
            // horizontally.
            lastOffsetLeft = -1;

            // Capture the offset top of the target element.
            offsetTop = target.offset().top;

            // Capture the offset left of the target element.
            offsetLeft = target.offset().left;

            // If the offsets option is on, alter the left offset.
            if (base.options.offsets) {
                offsetLeft += (target.offset().left - target.position().left);
            }

            if (originalOffsetLeft == -1) {
                originalOffsetLeft = offsetLeft;
            }

            position = target.css('position');

            // Set that this has been called at least once.
            isReset = true;

            if (base.options.bottom != -1) {
                target.trigger('preFixed.ScrollToFixed');
                setFixed();
                target.trigger('fixed.ScrollToFixed');
            }
        }

        function getLimit() {
            var limit = base.options.limit;
            if (!limit) return 0;

            if (typeof(limit) === 'function') {
                return limit.apply(target);
            }
            return limit;
        }

        // Returns whether the target element is fixed or not.
        function isFixed() {
            return position === 'fixed';
        }

        // Returns whether the target element is absolute or not.
        function isAbsolute() {
            return position === 'absolute';
        }

        function isUnfixed() {
            return !(isFixed() || isAbsolute());
        }

        // Sets the target element to fixed. Also, sets the spacer to fill the
        // void left by the target element.
        function setFixed() {
            // Only fix the target element and the spacer if we need to.
            if (!isFixed()) {
                // Set the spacer to fill the height and width of the target
                // element, then display it.
                spacer.css({
                    'display' : target.css('display'),
                    'width' : target.outerWidth(true),
                    'height' : target.outerHeight(true),
                    'float' : target.css('float')
                });

                // Set the target element to fixed and set its width so it does
                // not fill the rest of the page horizontally. Also, set its top
                // to the margin top specified in the options.
                target.css({
                    'position' : 'fixed',
                    'top' : base.options.bottom == -1?getMarginTop():'',
                    'bottom' : base.options.bottom == -1?'':base.options.bottom,
                    'margin-left' : '0px'
                });
                if (!base.options.dontSetWidth) {
                  target.css("width", target.width());
                }

                target.addClass('scroll-to-fixed-fixed');

                if (base.options.className) {
                    target.addClass(base.options.className);
                }

                position = 'fixed';
            }
        }

        function setAbsolute() {

            var top = getLimit();
            var left = offsetLeft;

            if (base.options.removeOffsets) {
                left = 0;
                top = top - offsetTop;
            }

            target.css({
                'position' : 'absolute',
                'top' : top,
                'left' : left,
                'margin-left' : '0px',
                'bottom' : ''
            });
            if (!base.options.dontSetWidth) {
              target.css("width", target.width());
            }

            position = 'absolute';
        }

        // Sets the target element back to unfixed. Also, hides the spacer.
        function setUnfixed() {
            // Only unfix the target element and the spacer if we need to.
            if (!isUnfixed()) {
                lastOffsetLeft = -1;

                // Hide the spacer now that the target element will fill the
                // space.
                spacer.css('display', 'none');

                // Remove the style attributes that were added to the target.
                // This will reverse the target back to the its original style.
                target.css({
                    'width' : '',
                    'position' : originalPosition,
                    'left' : '',
                    'top' : originalOffset.top,
                    'margin-left' : ''
                });

                target.removeClass('scroll-to-fixed-fixed');

                if (base.options.className) {
                    target.removeClass(base.options.className);
                }

                position = null;
            }
        }

        // Moves the target element left or right relative to the horizontal
        // scroll position.
        function setLeft(x) {
            // Only if the scroll is not what it was last time we did this.
            if (x != lastOffsetLeft) {
                // Move the target element horizontally relative to its original
                // horizontal position.
                target.css('left', offsetLeft - x);

                // Hold the last horizontal position set.
                lastOffsetLeft = x;
            }
        }

        function getMarginTop() {
            var marginTop = base.options.marginTop;
            if (!marginTop) return 0;

            if (typeof(marginTop) === 'function') {
                return marginTop.apply(target);
            }
            return marginTop;
        }

        // Checks to see if we need to do something based on new scroll position
        // of the page.
        function checkScroll() {
            if (!$.isScrollToFixed(target)) return;
            var wasReset = isReset;

            // If resetScroll has not yet been called, call it. This only
            // happens once.
            if (!isReset) {
                resetScroll();
            }

            // Grab the current horizontal scroll position.
            var x = $(window).scrollLeft();

            // Grab the current vertical scroll position.
            var y = $(window).scrollTop();

            // Get the limit, if there is one.
            var limit = getLimit();

            // If the vertical scroll position, plus the optional margin, would
            // put the target element at the specified limit, set the target
            // element to absolute.
            if (base.options.minWidth && $(window).width() < base.options.minWidth) {
                if (!isUnfixed() || !wasReset) {
                    postPosition();
                    target.trigger('preUnfixed.ScrollToFixed');
                    setUnfixed();
                    target.trigger('unfixed.ScrollToFixed');
                }
            } else if (base.options.bottom == -1) {
                // If the vertical scroll position, plus the optional margin, would
                // put the target element at the specified limit, set the target
                // element to absolute.
                if (limit > 0 && y >= limit - getMarginTop()) {
                    if (!isAbsolute() || !wasReset) {
                        postPosition();
                        target.trigger('preAbsolute.ScrollToFixed');
                        setAbsolute();
                        target.trigger('unfixed.ScrollToFixed');
                    }
                // If the vertical scroll position, plus the optional margin, would
                // put the target element above the top of the page, set the target
                // element to fixed.
                } else if (y >= offsetTop - getMarginTop()) {
                    if (!isFixed() || !wasReset) {
                        postPosition();
                        target.trigger('preFixed.ScrollToFixed');

                        // Set the target element to fixed.
                        setFixed();

                        // Reset the last offset left because we just went fixed.
                        lastOffsetLeft = -1;

                        target.trigger('fixed.ScrollToFixed');
                    }
                    // If the page has been scrolled horizontally as well, move the
                    // target element accordingly.
                    setLeft(x);
                } else {
                    // Set the target element to unfixed, placing it where it was
                    // before.
                    if (!isUnfixed() || !wasReset) {
                        postPosition();
                        target.trigger('preUnfixed.ScrollToFixed');
                        setUnfixed();
                        target.trigger('unfixed.ScrollToFixed');
                    }
                }
            } else {
                if (limit > 0) {
                    if (y + $(window).height() - target.outerHeight(true) >= limit - (getMarginTop() || -getBottom())) {
                        if (isFixed()) {
                            postPosition();
                            target.trigger('preUnfixed.ScrollToFixed');

                            if (originalPosition === 'absolute') {
                                setAbsolute();
                            } else {
                                setUnfixed();
                            }

                            target.trigger('unfixed.ScrollToFixed');
                        }
                    } else {
                        if (!isFixed()) {
                            postPosition();
                            target.trigger('preFixed.ScrollToFixed');
                            setFixed();
                        }
                        setLeft(x);
                        target.trigger('fixed.ScrollToFixed');
                    }
                } else {
                    setLeft(x);
                }
            }
        }

        function getBottom() {
            if (!base.options.bottom) return 0;
            return base.options.bottom;
        }

        function postPosition() {
            var position = target.css('position');

            if (position == 'absolute') {
                target.trigger('postAbsolute.ScrollToFixed');
            } else if (position == 'fixed') {
                target.trigger('postFixed.ScrollToFixed');
            } else {
                target.trigger('postUnfixed.ScrollToFixed');
            }
        }

        var windowResize = function(event) {
            // Check if the element is visible before updating it's position, which
            // improves behavior with responsive designs where this element is hidden.
            if(target.is(':visible')) {
                isReset = false;
                checkScroll();
			}
        }

        var windowScroll = function(event) {
            checkScroll();
        }

        // From: http://kangax.github.com/cft/#IS_POSITION_FIXED_SUPPORTED
        var isPositionFixedSupported = function() {
            var container = document.body;

            if (document.createElement && container && container.appendChild && container.removeChild) {
                var el = document.createElement('div');

                if (!el.getBoundingClientRect) return null;

                el.innerHTML = 'x';
                el.style.cssText = 'position:fixed;top:100px;';
                container.appendChild(el);

                var originalHeight = container.style.height,
                originalScrollTop = container.scrollTop;

                container.style.height = '3000px';
                container.scrollTop = 500;

                var elementTop = el.getBoundingClientRect().top;
                container.style.height = originalHeight;

                var isSupported = (elementTop === 100);
                container.removeChild(el);
                container.scrollTop = originalScrollTop;

                return isSupported;
            }

            return null;
        }

        var preventDefault = function(e) {
            e = e || window.event;
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.returnValue = false;
        }

        // Initializes this plugin. Captures the options passed in, turns this
        // off for devices that do not support fixed position, adds the spacer,
        // and binds to the window scroll and resize events.
        base.init = function() {
            // Capture the options for this plugin.
            base.options = $
                    .extend({}, $.ScrollToFixed.defaultOptions, options);

            // Turn off this functionality for devices that do not support it.
            // if (!(base.options && base.options.dontCheckForPositionFixedSupport)) {
            //     var fixedSupported = isPositionFixedSupported();
            //     if (!fixedSupported) return;
            // }

            // Put the target element on top of everything that could be below
            // it. This reduces flicker when the target element is transitioning
            // to fixed.
            base.$el.css('z-index', base.options.zIndex);

            // Create a spacer element to fill the void left by the target
            // element when it goes fixed.
            spacer = $('<div />');

            position = target.css('position');
            originalPosition = target.css('position');

            originalOffset = $.extend({}, target.offset());

            // Place the spacer right after the target element.
            if (isUnfixed()) base.$el.after(spacer);

            // Reset the target element offsets when the window is resized, then
            // check to see if we need to fix or unfix the target element.
            $(window).bind('resize.ScrollToFixed', windowResize);

            // When the window scrolls, check to see if we need to fix or unfix
            // the target element.
            $(window).bind('scroll.ScrollToFixed', windowScroll);

            if (base.options.preFixed) {
                target.bind('preFixed.ScrollToFixed', base.options.preFixed);
            }
            if (base.options.postFixed) {
                target.bind('postFixed.ScrollToFixed', base.options.postFixed);
            }
            if (base.options.preUnfixed) {
                target.bind('preUnfixed.ScrollToFixed', base.options.preUnfixed);
            }
            if (base.options.postUnfixed) {
                target.bind('postUnfixed.ScrollToFixed', base.options.postUnfixed);
            }
            if (base.options.preAbsolute) {
                target.bind('preAbsolute.ScrollToFixed', base.options.preAbsolute);
            }
            if (base.options.postAbsolute) {
                target.bind('postAbsolute.ScrollToFixed', base.options.postAbsolute);
            }
            if (base.options.fixed) {
                target.bind('fixed.ScrollToFixed', base.options.fixed);
            }
            if (base.options.unfixed) {
                target.bind('unfixed.ScrollToFixed', base.options.unfixed);
            }

            if (base.options.spacerClass) {
                spacer.addClass(base.options.spacerClass);
            }

            target.bind('resize.ScrollToFixed', function() {
                spacer.height(target.height());
            });

            target.bind('scroll.ScrollToFixed', function() {
                target.trigger('preUnfixed.ScrollToFixed');
                setUnfixed();
                target.trigger('unfixed.ScrollToFixed');
                checkScroll();
            });

            target.bind('detach.ScrollToFixed', function(ev) {
                preventDefault(ev);

                target.trigger('preUnfixed.ScrollToFixed');
                setUnfixed();
                target.trigger('unfixed.ScrollToFixed');

                $(window).unbind('resize.ScrollToFixed', windowResize);
                $(window).unbind('scroll.ScrollToFixed', windowScroll);

                target.unbind('.ScrollToFixed');
                base.$el.removeData('ScrollToFixed');
            });

            // Reset everything.
            windowResize();
        };

        // Initialize the plugin.
        base.init();
    };

    // Sets the option defaults.
    $.ScrollToFixed.defaultOptions = {
        marginTop : 0,
        limit : 0,
        bottom : -1,
        zIndex : 1000
    };

    // Returns enhanced elements that will fix to the top of the page when the
    // page is scrolled.
    $.fn.scrollToFixed = function(options) {
        return this.each(function() {
            (new $.ScrollToFixed(this, options));
        });
    };
})(jQuery);
<commit_msg>trying to fix previous errors<commit_after>(function($) {
    $.isScrollToFixed = function(el) {
        return $(el).data('ScrollToFixed') !== undefined;
    };

    $.ScrollToFixed = function(el, options) {
        // To avoid scope issues, use 'base' instead of 'this' to reference this
        // class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element.
        base.$el = $(el);
        base.el = el;

        // Add a reverse reference to the DOM object.
        base.$el.data('ScrollToFixed', base);

        // A flag so we know if the scroll has been reset.
        var isReset = false;

        // The element that was given to us to fix if scrolled above the top of
        // the page.
        var target = base.$el;

        var position;
        var originalPosition;

        var originalOffset;

        // The offset top of the element when resetScroll was called. This is
        // used to determine if we have scrolled past the top of the element.
        var offsetTop = 0;

        // The offset left of the element when resetScroll was called. This is
        // used to move the element left or right relative to the horizontal
        // scroll.
        var offsetLeft = 0;
        var originalOffsetLeft = -1;

        // This last offset used to move the element horizontally. This is used
        // to determine if we need to move the element because we would not want
        // to do that for no reason.
        var lastOffsetLeft = -1;

        // This is the element used to fill the void left by the target element
        // when it goes fixed; otherwise, everything below it moves up the page.
        var spacer = null;

        var spacerClass;

        var className;

        // Capture the original offsets for the target element. This needs to be
        // called whenever the page size changes or when the page is first
        // scrolled. For some reason, calling this before the page is first
        // scrolled causes the element to become fixed too late.
        function resetScroll() {
            // Set the element to it original positioning.
            target.trigger('preUnfixed.ScrollToFixed');
            setUnfixed();
            target.trigger('unfixed.ScrollToFixed');

            // Reset the last offset used to determine if the page has moved
            // horizontally.
            lastOffsetLeft = -1;

            // Capture the offset top of the target element.
            offsetTop = target.offset().top;

            // Capture the offset left of the target element.
            offsetLeft = target.offset().left;

            // If the offsets option is on, alter the left offset.
            if (base.options.offsets) {
                offsetLeft += (target.offset().left - target.position().left);
            }

            if (originalOffsetLeft == -1) {
                originalOffsetLeft = offsetLeft;
            }

            position = target.css('position');

            // Set that this has been called at least once.
            isReset = true;

            if (base.options.bottom != -1) {
                target.trigger('preFixed.ScrollToFixed');
                setFixed();
                target.trigger('fixed.ScrollToFixed');
            }
        }

        function getLimit() {
            var limit = base.options.limit;
            if (!limit) return 0;

            if (typeof(limit) === 'function') {
                return limit.apply(target);
            }
            return limit;
        }

        // Returns whether the target element is fixed or not.
        function isFixed() {
            return position === 'fixed';
        }

        // Returns whether the target element is absolute or not.
        function isAbsolute() {
            return position === 'absolute';
        }

        function isUnfixed() {
            return !(isFixed() || isAbsolute());
        }

        // Sets the target element to fixed. Also, sets the spacer to fill the
        // void left by the target element.
        function setFixed() {
            // Only fix the target element and the spacer if we need to.
            if (!isFixed()) {
                // Set the spacer to fill the height and width of the target
                // element, then display it.
                spacer.css({
                    'display' : target.css('display'),
                    'width' : target.outerWidth(true),
                    'height' : target.outerHeight(true),
                    'float' : target.css('float')
                });

                // Set the target element to fixed and set its width so it does
                // not fill the rest of the page horizontally. Also, set its top
                // to the margin top specified in the options.
                target.css({
                    'position' : 'fixed',
                    'top' : base.options.bottom == -1?getMarginTop():'',
                    'bottom' : base.options.bottom == -1?'':base.options.bottom,
                    'margin-left' : '0px'
                });
                if (!base.options.dontSetWidth||base.options.dontSetWidth==null) {
                  target.css("width", target.width());
                }

                target.addClass('scroll-to-fixed-fixed');

                if (base.options.className) {
                    target.addClass(base.options.className);
                }

                position = 'fixed';
            }
        }

        function setAbsolute() {

            var top = getLimit();
            var left = offsetLeft;

            if (base.options.removeOffsets) {
                left = 0;
                top = top - offsetTop;
            }

            target.css({
                'position' : 'absolute',
                'top' : top,
                'left' : left,
                'margin-left' : '0px',
                'bottom' : ''
            });
            if (!base.options.dontSetWidth||base.options.dontSetWidth==null) {
              target.css("width", target.width());
            }

            position = 'absolute';
        }

        // Sets the target element back to unfixed. Also, hides the spacer.
        function setUnfixed() {
            // Only unfix the target element and the spacer if we need to.
            if (!isUnfixed()) {
                lastOffsetLeft = -1;

                // Hide the spacer now that the target element will fill the
                // space.
                spacer.css('display', 'none');

                // Remove the style attributes that were added to the target.
                // This will reverse the target back to the its original style.
                target.css({
                    'width' : '',
                    'position' : originalPosition,
                    'left' : '',
                    'top' : originalOffset.top,
                    'margin-left' : ''
                });

                target.removeClass('scroll-to-fixed-fixed');

                if (base.options.className) {
                    target.removeClass(base.options.className);
                }

                position = null;
            }
        }

        // Moves the target element left or right relative to the horizontal
        // scroll position.
        function setLeft(x) {
            // Only if the scroll is not what it was last time we did this.
            if (x != lastOffsetLeft) {
                // Move the target element horizontally relative to its original
                // horizontal position.
                target.css('left', offsetLeft - x);

                // Hold the last horizontal position set.
                lastOffsetLeft = x;
            }
        }

        function getMarginTop() {
            var marginTop = base.options.marginTop;
            if (!marginTop) return 0;

            if (typeof(marginTop) === 'function') {
                return marginTop.apply(target);
            }
            return marginTop;
        }

        // Checks to see if we need to do something based on new scroll position
        // of the page.
        function checkScroll() {
            if (!$.isScrollToFixed(target)) return;
            var wasReset = isReset;

            // If resetScroll has not yet been called, call it. This only
            // happens once.
            if (!isReset) {
                resetScroll();
            }

            // Grab the current horizontal scroll position.
            var x = $(window).scrollLeft();

            // Grab the current vertical scroll position.
            var y = $(window).scrollTop();

            // Get the limit, if there is one.
            var limit = getLimit();

            // If the vertical scroll position, plus the optional margin, would
            // put the target element at the specified limit, set the target
            // element to absolute.
            if (base.options.minWidth && $(window).width() < base.options.minWidth) {
                if (!isUnfixed() || !wasReset) {
                    postPosition();
                    target.trigger('preUnfixed.ScrollToFixed');
                    setUnfixed();
                    target.trigger('unfixed.ScrollToFixed');
                }
            } else if (base.options.bottom == -1) {
                // If the vertical scroll position, plus the optional margin, would
                // put the target element at the specified limit, set the target
                // element to absolute.
                if (limit > 0 && y >= limit - getMarginTop()) {
                    if (!isAbsolute() || !wasReset) {
                        postPosition();
                        target.trigger('preAbsolute.ScrollToFixed');
                        setAbsolute();
                        target.trigger('unfixed.ScrollToFixed');
                    }
                // If the vertical scroll position, plus the optional margin, would
                // put the target element above the top of the page, set the target
                // element to fixed.
                } else if (y >= offsetTop - getMarginTop()) {
                    if (!isFixed() || !wasReset) {
                        postPosition();
                        target.trigger('preFixed.ScrollToFixed');

                        // Set the target element to fixed.
                        setFixed();

                        // Reset the last offset left because we just went fixed.
                        lastOffsetLeft = -1;

                        target.trigger('fixed.ScrollToFixed');
                    }
                    // If the page has been scrolled horizontally as well, move the
                    // target element accordingly.
                    setLeft(x);
                } else {
                    // Set the target element to unfixed, placing it where it was
                    // before.
                    if (!isUnfixed() || !wasReset) {
                        postPosition();
                        target.trigger('preUnfixed.ScrollToFixed');
                        setUnfixed();
                        target.trigger('unfixed.ScrollToFixed');
                    }
                }
            } else {
                if (limit > 0) {
                    if (y + $(window).height() - target.outerHeight(true) >= limit - (getMarginTop() || -getBottom())) {
                        if (isFixed()) {
                            postPosition();
                            target.trigger('preUnfixed.ScrollToFixed');

                            if (originalPosition === 'absolute') {
                                setAbsolute();
                            } else {
                                setUnfixed();
                            }

                            target.trigger('unfixed.ScrollToFixed');
                        }
                    } else {
                        if (!isFixed()) {
                            postPosition();
                            target.trigger('preFixed.ScrollToFixed');
                            setFixed();
                        }
                        setLeft(x);
                        target.trigger('fixed.ScrollToFixed');
                    }
                } else {
                    setLeft(x);
                }
            }
        }

        function getBottom() {
            if (!base.options.bottom) return 0;
            return base.options.bottom;
        }

        function postPosition() {
            var position = target.css('position');

            if (position == 'absolute') {
                target.trigger('postAbsolute.ScrollToFixed');
            } else if (position == 'fixed') {
                target.trigger('postFixed.ScrollToFixed');
            } else {
                target.trigger('postUnfixed.ScrollToFixed');
            }
        }

        var windowResize = function(event) {
            // Check if the element is visible before updating it's position, which
            // improves behavior with responsive designs where this element is hidden.
            if(target.is(':visible')) {
                isReset = false;
                checkScroll();
			}
        }

        var windowScroll = function(event) {
            checkScroll();
        }

        // From: http://kangax.github.com/cft/#IS_POSITION_FIXED_SUPPORTED
        var isPositionFixedSupported = function() {
            var container = document.body;

            if (document.createElement && container && container.appendChild && container.removeChild) {
                var el = document.createElement('div');

                if (!el.getBoundingClientRect) return null;

                el.innerHTML = 'x';
                el.style.cssText = 'position:fixed;top:100px;';
                container.appendChild(el);

                var originalHeight = container.style.height,
                originalScrollTop = container.scrollTop;

                container.style.height = '3000px';
                container.scrollTop = 500;

                var elementTop = el.getBoundingClientRect().top;
                container.style.height = originalHeight;

                var isSupported = (elementTop === 100);
                container.removeChild(el);
                container.scrollTop = originalScrollTop;

                return isSupported;
            }

            return null;
        }

        var preventDefault = function(e) {
            e = e || window.event;
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.returnValue = false;
        }

        // Initializes this plugin. Captures the options passed in, turns this
        // off for devices that do not support fixed position, adds the spacer,
        // and binds to the window scroll and resize events.
        base.init = function() {
            // Capture the options for this plugin.
            base.options = $
                    .extend({}, $.ScrollToFixed.defaultOptions, options);

            // Turn off this functionality for devices that do not support it.
            // if (!(base.options && base.options.dontCheckForPositionFixedSupport)) {
            //     var fixedSupported = isPositionFixedSupported();
            //     if (!fixedSupported) return;
            // }

            // Put the target element on top of everything that could be below
            // it. This reduces flicker when the target element is transitioning
            // to fixed.
            base.$el.css('z-index', base.options.zIndex);

            // Create a spacer element to fill the void left by the target
            // element when it goes fixed.
            spacer = $('<div />');

            position = target.css('position');
            originalPosition = target.css('position');

            originalOffset = $.extend({}, target.offset());

            // Place the spacer right after the target element.
            if (isUnfixed()) base.$el.after(spacer);

            // Reset the target element offsets when the window is resized, then
            // check to see if we need to fix or unfix the target element.
            $(window).bind('resize.ScrollToFixed', windowResize);

            // When the window scrolls, check to see if we need to fix or unfix
            // the target element.
            $(window).bind('scroll.ScrollToFixed', windowScroll);

            if (base.options.preFixed) {
                target.bind('preFixed.ScrollToFixed', base.options.preFixed);
            }
            if (base.options.postFixed) {
                target.bind('postFixed.ScrollToFixed', base.options.postFixed);
            }
            if (base.options.preUnfixed) {
                target.bind('preUnfixed.ScrollToFixed', base.options.preUnfixed);
            }
            if (base.options.postUnfixed) {
                target.bind('postUnfixed.ScrollToFixed', base.options.postUnfixed);
            }
            if (base.options.preAbsolute) {
                target.bind('preAbsolute.ScrollToFixed', base.options.preAbsolute);
            }
            if (base.options.postAbsolute) {
                target.bind('postAbsolute.ScrollToFixed', base.options.postAbsolute);
            }
            if (base.options.fixed) {
                target.bind('fixed.ScrollToFixed', base.options.fixed);
            }
            if (base.options.unfixed) {
                target.bind('unfixed.ScrollToFixed', base.options.unfixed);
            }

            if (base.options.spacerClass) {
                spacer.addClass(base.options.spacerClass);
            }

            target.bind('resize.ScrollToFixed', function() {
                spacer.height(target.height());
            });

            target.bind('scroll.ScrollToFixed', function() {
                target.trigger('preUnfixed.ScrollToFixed');
                setUnfixed();
                target.trigger('unfixed.ScrollToFixed');
                checkScroll();
            });

            target.bind('detach.ScrollToFixed', function(ev) {
                preventDefault(ev);

                target.trigger('preUnfixed.ScrollToFixed');
                setUnfixed();
                target.trigger('unfixed.ScrollToFixed');

                $(window).unbind('resize.ScrollToFixed', windowResize);
                $(window).unbind('scroll.ScrollToFixed', windowScroll);

                target.unbind('.ScrollToFixed');
                base.$el.removeData('ScrollToFixed');
            });

            // Reset everything.
            windowResize();
        };

        // Initialize the plugin.
        base.init();
    };

    // Sets the option defaults.
    $.ScrollToFixed.defaultOptions = {
        marginTop : 0,
        limit : 0,
        bottom : -1,
        zIndex : 1000
    };

    // Returns enhanced elements that will fix to the top of the page when the
    // page is scrolled.
    $.fn.scrollToFixed = function(options) {
        return this.each(function() {
            (new $.ScrollToFixed(this, options));
        });
    };
})(jQuery);
<|endoftext|>


<commit_before>const $ = require('jquery');
const anime = require('animejs');
const Stage = require('./stage');

class Game {
	constructor(configs) {
		this.configs = configs;
		this.$stage = $('.stage');
		this.stageIndex = 0;
		this.stagePrototype = this.$stage.clone();
		this.currentStage = null;

		const $stageNames = this.configs.map((config, index) => {
			const $stageName = $('<li/>', {
				'class': 'stage-name',
				text: config.statement,
			});

			$stageName.click(() => {
				this.startStage(index);
			});

			return $stageName;
		});

		$('ol.stage-list').append($stageNames);

		$(window).resize(() => this.currentStage.updateStyles());
		$('.menu-screen button.start').click(() => {
			this.startStage(0);
		});

		$('.menu-screen button.select').click(() => {
			$('ol.stage-list').toggleClass('active');
		});

		$('.menu-screen button.credit').click(() => {
			$('ul.credit-body').toggleClass('active');
		});
	}

	startStage(index) {
		this.currentStage = new Stage(this, this.configs[index]);
		this.stageIndex = index;
		$('.screens').addClass('gaming');
	}

	answer() {
		if (this.configs.length <= this.stageIndex){
			// 全てのステージを終了
			alert('wei wei wei');
		} else {
			this.exitStage();

			// 何らかの処理

			this.startStage(this.stageIndex + 1)
		}
	}

	exitStage() {
		// TODO: Should graceful shutdown of this.currentStage be necessary?
		this.$stage.remove();
		this.$stage = this.stagePrototype.clone();
		this.$stage.appendTo('.game-screen');

		$('.screens').removeClass('gaming');
		this.currentStage = null;
	}
}

module.exports = Game;
<commit_msg>Ensure currentStage exists for resize trigger<commit_after>const $ = require('jquery');
const anime = require('animejs');
const Stage = require('./stage');

class Game {
	constructor(configs) {
		this.configs = configs;
		this.$stage = $('.stage');
		this.stageIndex = 0;
		this.stagePrototype = this.$stage.clone();
		this.currentStage = null;

		const $stageNames = this.configs.map((config, index) => {
			const $stageName = $('<li/>', {
				'class': 'stage-name',
				text: config.statement,
			});

			$stageName.click(() => {
				this.startStage(index);
			});

			return $stageName;
		});

		$('ol.stage-list').append($stageNames);

		$(window).resize(() => this.currentStage && this.currentStage.updateStyles());
		$('.menu-screen button.start').click(() => {
			this.startStage(0);
		});

		$('.menu-screen button.select').click(() => {
			$('ol.stage-list').toggleClass('active');
		});

		$('.menu-screen button.credit').click(() => {
			$('ul.credit-body').toggleClass('active');
		});
	}

	startStage(index) {
		this.currentStage = new Stage(this, this.configs[index]);
		this.stageIndex = index;
		$('.screens').addClass('gaming');
	}

	answer() {
		if (this.configs.length <= this.stageIndex){
			// 全てのステージを終了
			alert('wei wei wei');
		} else {
			this.exitStage();

			// 何らかの処理

			this.startStage(this.stageIndex + 1)
		}
	}

	exitStage() {
		// TODO: Should graceful shutdown of this.currentStage be necessary?
		this.$stage.remove();
		this.$stage = this.stagePrototype.clone();
		this.$stage.appendTo('.game-screen');

		$('.screens').removeClass('gaming');
		this.currentStage = null;
	}
}

module.exports = Game;
<|endoftext|>


<commit_before>'use strict';

const ROOM_NAME = "Shadow Ban Room";
let room = Rooms.get(toId(ROOM_NAME));
if (!room) {
	Rooms.global.addChatRoom(ROOM_NAME);
	room = Rooms.get(toId(ROOM_NAME));

	room.isPrivate = true;
	room.staffRoom = true;
	room.staffAutojoin = true;
	room.addedUsers = {};

	if (room.chatRoomData) {
		room.chatRoomData.isPrivate = true;
		room.chatRoomData.staffRoom = true;
		room.chatRoomData.staffAutojoin = true;
		room.chatRoomData.addedUsers = room.addedUsers;

		Rooms.global.writeChatRoomData();
	}
}
if (Object.size(room.addedUsers) > 0) {
	setImmediate(function () {
		room.add("||Loaded user list: " + Object.keys(room.addedUsers).sort().join(", "));
		room.update();
	});
}
exports.room = room;

function getAllAlts(user) {
	let targets = {};
	if (typeof user === 'string') {
		targets[toId(user)] = 1;
	} else {
		user.getAlts().concat(user.name).forEach(function (altName) {
			let alt = Users.get(altName);
			if (!alt.named) return;

			targets[toId(alt)] = 1;
			Object.keys(alt.prevNames).forEach(function (name) {
				targets[toId(name)] = 1;
			});
		});
	}
	return targets;
}

function intersectAndExclude(a, b) {
	let intersection = [];
	let exclusionA = [];
	let exclusionB = [];

	let ai = 0;
	let bi = 0;
	while (ai < a.length && bi < b.length) {
		let difference = a[ai].localeCompare(b[bi]);
		if (difference < 0) {
			exclusionA.push(a[ai]);
			++ai;
		} else if (difference > 0) {
			exclusionB.push(b[bi]);
			++bi;
		} else {
			intersection.push(a[ai]);
			++ai;
			++bi;
		}
	}

	Array.prototype.push.apply(exclusionA, a.slice(ai));
	Array.prototype.push.apply(exclusionB, b.slice(bi));
	return {intersection: intersection, exclusionA: exclusionA, exclusionB: exclusionB};
}

let checkBannedCache = {};
exports.checkBanned = function (user) {
	let userId = toId(user);
	if (userId in checkBannedCache) return checkBannedCache[userId];
	//console.log("Shadow ban cache miss:", userId);

	let targets = Object.keys(getAllAlts(user)).sort();
	let bannedUsers = Object.keys(room.addedUsers).sort();

	let matches = intersectAndExclude(targets, bannedUsers);
	let isBanned = matches.intersection.length !== 0;
	for (let t = 0; t < targets.length; ++t) {
		if (isBanned) room.addedUsers[targets[t]] = 1;
		checkBannedCache[targets[t]] = isBanned;
	}
	if (!isBanned) return false;

	if (matches.exclusionA.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Alts of " + matches.intersection[0] + " automatically added: " + matches.exclusionA.join(", "));
	}

	return true;
};

let addUser = exports.addUser = function (user) {
	let targets = getAllAlts(user);
	for (let u in targets) {
		if (room.addedUsers[u]) {
			delete targets[u];
		} else {
			room.addedUsers[u] = 1;
		}
		checkBannedCache[u] = true;
	}
	targets = Object.keys(targets).sort();

	if (targets.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Added users: " + targets.join(", "));
		room.update();
	}

	return targets;
};
let removeUser = exports.removeUser = function (user) {
	let targets = getAllAlts(user);
	for (let u in targets) {
		if (!room.addedUsers[u]) {
			delete targets[u];
		} else {
			delete room.addedUsers[u];
		}
		checkBannedCache[u] = false;
	}
	targets = Object.keys(targets).sort();

	if (targets.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Removed users: " + targets.join(", "));
		room.update();
	}

	return targets;
};

exports.addMessage = function (user, tag, message) {
	room.add('|c|' + user.getIdentity() + '|__(' + tag + ')__ ' + message);
	room.update();
};
exports.addEmoticonMessage = function (user, message) {
	room.add(message);
	room.update();
};

exports.commands = {
	spam: 'shadowban',
	sban: 'shadowban',
	shadowban: function (target, room, user) {
		if (!target) return this.sendReply("/shadowban OR /sban [username], [secondary command], [reason] - Sends all the user's messages to the shadow ban room.");

		let params = this.splitTarget(target).split(',');
		let action = params[0].trim().toLowerCase();
		let reason = params.slice(1).join(',').trim();
		if (!(action in CommandParser.commands)) {
			action = 'mute';
			reason = params.join(',').trim();
		}

		if (!this.targetUser) return this.sendReply("User '" + this.targetUsername + "' not found.");
		if (!this.can('lock', this.targetUser)) return;

		let targets = addUser(this.targetUser);
		if (targets.length === 0) {
			return this.sendReply('||' + this.targetUsername + " is already shadow banned or isn't named.");
		}
		this.privateModCommand("(" + user.name + " has shadow banned: " + targets.join(", ") + (reason ? " (" + reason + ")" : "") + ")");

		//return this.parse('/' + action + ' ' + toId(this.targetUser) + ',' + reason);
	},

	unspam: 'unshadowban',
	unsban: 'unshadowban',
	unshadowban: function (target, room, user) {
		if (!target) return this.sendReply("/unshadowban OR /unsban [username] - Undoes /shadowban (except the secondary command).");
		this.splitTarget(target);

		if (!this.can('lock')) return;

		let targets = removeUser(this.targetUser || this.targetUsername);
		if (targets.length === 0) {
			return this.sendReply('||' + this.targetUsername + " is not shadow banned.");
		}
		this.privateModCommand("(" + user.name + " has shadow unbanned: " + targets.join(", ") + ")");
	},

	sbanlist: function (target, room, user) {
		if (!target && !this.can('lock')) return this.sendReply("The command '/sbanlist' was unrecognized.  To send a message starting with '/sbanlist', type '//sbanlist'.");
		if ((user.locked || room.isMuted(user)) && !user.can('bypassall')) return this.sendReply("You cannot do this while unable to talk.");
		if (!this.can('lock')) return false;

		Users.get(toId(user.name)).send('|popup| Here is a list of sbanned users: \n' + JSON.stringify(Rooms('shadowbanroom').chatRoomData, null, 2));
	},
};

Users.ShadowBan = exports;
<commit_msg>Refactor the sbanlist command There was no reason the list should of actually been displayed literally as an object...<commit_after>'use strict';

const ROOM_NAME = "Shadow Ban Room";
let room = Rooms.get(toId(ROOM_NAME));
if (!room) {
	Rooms.global.addChatRoom(ROOM_NAME);
	room = Rooms.get(toId(ROOM_NAME));

	room.isPrivate = true;
	room.staffRoom = true;
	room.staffAutojoin = true;
	room.addedUsers = {};

	if (room.chatRoomData) {
		room.chatRoomData.isPrivate = true;
		room.chatRoomData.staffRoom = true;
		room.chatRoomData.staffAutojoin = true;
		room.chatRoomData.addedUsers = room.addedUsers;

		Rooms.global.writeChatRoomData();
	}
}
if (Object.size(room.addedUsers) > 0) {
	setImmediate(function () {
		room.add("||Loaded user list: " + Object.keys(room.addedUsers).sort().join(", "));
		room.update();
	});
}
exports.room = room;

function getAllAlts(user) {
	let targets = {};
	if (typeof user === 'string') {
		targets[toId(user)] = 1;
	} else {
		user.getAlts().concat(user.name).forEach(function (altName) {
			let alt = Users.get(altName);
			if (!alt.named) return;

			targets[toId(alt)] = 1;
			Object.keys(alt.prevNames).forEach(function (name) {
				targets[toId(name)] = 1;
			});
		});
	}
	return targets;
}

function intersectAndExclude(a, b) {
	let intersection = [];
	let exclusionA = [];
	let exclusionB = [];

	let ai = 0;
	let bi = 0;
	while (ai < a.length && bi < b.length) {
		let difference = a[ai].localeCompare(b[bi]);
		if (difference < 0) {
			exclusionA.push(a[ai]);
			++ai;
		} else if (difference > 0) {
			exclusionB.push(b[bi]);
			++bi;
		} else {
			intersection.push(a[ai]);
			++ai;
			++bi;
		}
	}

	Array.prototype.push.apply(exclusionA, a.slice(ai));
	Array.prototype.push.apply(exclusionB, b.slice(bi));
	return {intersection: intersection, exclusionA: exclusionA, exclusionB: exclusionB};
}

let checkBannedCache = {};
exports.checkBanned = function (user) {
	let userId = toId(user);
	if (userId in checkBannedCache) return checkBannedCache[userId];
	//console.log("Shadow ban cache miss:", userId);

	let targets = Object.keys(getAllAlts(user)).sort();
	let bannedUsers = Object.keys(room.addedUsers).sort();

	let matches = intersectAndExclude(targets, bannedUsers);
	let isBanned = matches.intersection.length !== 0;
	for (let t = 0; t < targets.length; ++t) {
		if (isBanned) room.addedUsers[targets[t]] = 1;
		checkBannedCache[targets[t]] = isBanned;
	}
	if (!isBanned) return false;

	if (matches.exclusionA.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Alts of " + matches.intersection[0] + " automatically added: " + matches.exclusionA.join(", "));
	}

	return true;
};

let addUser = exports.addUser = function (user) {
	let targets = getAllAlts(user);
	for (let u in targets) {
		if (room.addedUsers[u]) {
			delete targets[u];
		} else {
			room.addedUsers[u] = 1;
		}
		checkBannedCache[u] = true;
	}
	targets = Object.keys(targets).sort();

	if (targets.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Added users: " + targets.join(", "));
		room.update();
	}

	return targets;
};
let removeUser = exports.removeUser = function (user) {
	let targets = getAllAlts(user);
	for (let u in targets) {
		if (!room.addedUsers[u]) {
			delete targets[u];
		} else {
			delete room.addedUsers[u];
		}
		checkBannedCache[u] = false;
	}
	targets = Object.keys(targets).sort();

	if (targets.length > 0) {
		Rooms.global.writeChatRoomData();
		room.add("||Removed users: " + targets.join(", "));
		room.update();
	}

	return targets;
};

exports.addMessage = function (user, tag, message) {
	room.add('|c|' + user.getIdentity() + '|__(' + tag + ')__ ' + message);
	room.update();
};
exports.addEmoticonMessage = function (user, message) {
	room.add(message);
	room.update();
};

exports.commands = {
	spam: 'shadowban',
	sban: 'shadowban',
	shadowban: function (target, room, user) {
		if (!target) return this.sendReply("/shadowban OR /sban [username], [secondary command], [reason] - Sends all the user's messages to the shadow ban room.");

		let params = this.splitTarget(target).split(',');
		let action = params[0].trim().toLowerCase();
		let reason = params.slice(1).join(',').trim();
		if (!(action in CommandParser.commands)) {
			action = 'mute';
			reason = params.join(',').trim();
		}

		if (!this.targetUser) return this.sendReply("User '" + this.targetUsername + "' not found.");
		if (!this.can('lock', this.targetUser)) return;

		let targets = addUser(this.targetUser);
		if (targets.length === 0) {
			return this.sendReply('||' + this.targetUsername + " is already shadow banned or isn't named.");
		}
		this.privateModCommand("(" + user.name + " has shadow banned: " + targets.join(", ") + (reason ? " (" + reason + ")" : "") + ")");

		//return this.parse('/' + action + ' ' + toId(this.targetUser) + ',' + reason);
	},

	unspam: 'unshadowban',
	unsban: 'unshadowban',
	unshadowban: function (target, room, user) {
		if (!target) return this.sendReply("/unshadowban OR /unsban [username] - Undoes /shadowban (except the secondary command).");
		this.splitTarget(target);

		if (!this.can('lock')) return;

		let targets = removeUser(this.targetUser || this.targetUsername);
		if (targets.length === 0) {
			return this.sendReply('||' + this.targetUsername + " is not shadow banned.");
		}
		this.privateModCommand("(" + user.name + " has shadow unbanned: " + targets.join(", ") + ")");
	},

	sbanlist: function (target, room, user) {
		if (!this.can('lock')) return false;
		if ((user.locked || room.isMuted(user)) && !user.can('bypassall')) return this.sendReply("You cannot do this while unable to talk.");
		let keys = Object.keys(Rooms('shadowbanroom').addedUsers);
		if (keys.length < 1) return this.errorReply("There are currently no shadow banned users at this time.");

		Users.get(toId(user.name)).send('|popup||wide| Here is a list of sbanned users: \n' + keys.join(', '));
	},
};

Users.ShadowBan = exports;
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  var traceurCommand = './node_modules/traceur/traceur-build --modules=inline ';

  return {
    dist: {
      command: [
        'rm -rf dist',
        traceurCommand + '--out dist/skate.js --module src/skate.js'
      ].join(' && ')
    },
    installBower: {
      command: './node_modules/.bin/bower install'
    },
    installTraceur: {
      command: [
        'cd ./node_modules/traceur',
        'make clean',
        'make'
      ].join(' && ')
    },
    test: {
      command: [
        'rm -rf .tmp',
        traceurCommand + '--out .tmp/run-unit-tests.js --module test/unit.js'
      ].join(' && ')
    }
  };
};
<commit_msg>Attempting to get around the fact that you 'make clean' fails on Travis CI for Traceur.<commit_after>module.exports = function (grunt) {
  var traceurCommand = './node_modules/traceur/traceur-build --modules=inline ';

  return {
    dist: {
      command: [
        'rm -rf dist',
        traceurCommand + '--out dist/skate.js --module src/skate.js'
      ].join(' && ')
    },
    installBower: {
      command: './node_modules/.bin/bower install'
    },
    installTraceur: {
      command: [
        'cd ./node_modules/traceur',
        'npm install',
        'make'
      ].join(' && ')
    },
    test: {
      command: [
        'rm -rf .tmp',
        traceurCommand + '--out .tmp/run-unit-tests.js --module test/unit.js'
      ].join(' && ')
    }
  };
};
<|endoftext|>


<commit_before>/*
Flot plugin for adding panning and zooming capabilities to a plot.

The default behaviour is double click and scrollwheel up/down to zoom
in, drag to pan. The plugin defines plot.zoom({ center }),
plot.zoomOut() and plot.pan(offset) so you easily can add custom
controls. It also fires a "plotpan" and "plotzoom" event when
something happens, useful for synchronizing plots.

Example usage:

  plot = $.plot(...);

  // zoom default amount in on the pixel (100, 200)
  plot.zoom({ center: { left: 10, top: 20 } });

  // zoom out again
  plot.zoomOut();

  // pan 100 pixels to the left and 20 down
  plot.pan({ left: -100, top: 20 })

Options:

  zoom: {
    interactive: false
    trigger: "dblclick" // or "click" for single click
    amount: 1.5         // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
  }

  pan: {
    interactive: false
  }

  xaxis, yaxis, x2axis, y2axis: {
    zoomRange: null  // or [number, number] (min range, max range)
    panRange: null   // or [number, number] (min, max)
  }

"interactive" enables the built-in drag/click behaviour. "amount" is
the amount to zoom the viewport relative to the current range, so 1 is
100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out).

"zoomRange" is the interval in which zooming can happen, e.g. with
zoomRange: [1, 100] the zoom will never scale the axis so that the
difference between min and max is smaller than 1 or larger than 100.
You can set either of them to null to ignore.

"panRange" confines the panning to stay within a range, e.g. with
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
other. Either can be null.
*/

// First two dependencies, jquery.event.drag.js and
// jquery.mousewheel.js, we put them inline here to save people the
// effort of downloading them.

/*
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
*/
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);

/* jquery.mousewheel.min.js
 * Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * Version: 3.0.2
 *
 * Requires: 1.2.2+
 */
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);

(function ($) {
    var options = {
        xaxis: {
            zoomRange: null, // or [number, number] (min range, max range)
            panRange: null // or [number, number] (min, max)
        },
        zoom: {
            interactive: false,
            trigger: "dblclick", // or "click" for single click
            amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
        },
        pan: {
            interactive: false
        }
    };

    function init(plot) {
        var prevPoint = null;

        function bindEvents(plot, eventHolder) {
            var o = plot.getOptions();
            if (o.zoom.interactive) {
                function clickHandler(e) {
                    prevPoint = plot.offset();
                    prevPoint.left = e.pageX - prevPoint.left;
                    prevPoint.top = e.pageY - prevPoint.top;
                    plot.zoom({ center: prevPoint });
                }

                eventHolder[o.zoom.trigger](clickHandler);

                eventHolder.mousewheel(function (e, delta) {
                    if (delta > 0)
                        clickHandler(e);
                    else
                        plot.zoomOut();
                });
            }
            if (o.pan.interactive) {
                var prevCursor = 'default', pageX = 0, pageY = 0;

                eventHolder.bind("dragstart", { distance: 10 }, function (e) {
                    if (e.which != 1)  // only accept left-click
                        return false;
                    eventHolderCursor = eventHolder.css('cursor');
                    eventHolder.css('cursor', 'move');
                    pageX = e.pageX;
                    pageY = e.pageY;
                });
                eventHolder.bind("drag", function (e) {
                    // unused at the moment, but we need it here to
                    // trigger the dragstart/dragend events
                });
                eventHolder.bind("dragend", function (e) {
                    eventHolder.css('cursor', prevCursor);
                    plot.pan({ left: pageX - e.pageX,
                               top: pageY - e.pageY });
                });
            }
        }

        plot.zoomOut = function () {
            plot.zoom({ amount: 1 / plot.getOptions().zoom.amount });
            prevPoint = null;
        }

        plot.zoom = function (args) {
            var axes = plot.getAxes(),
                options = plot.getOptions(),
                c = args.center ? args.center : prevPoint,
                amount = args.amount ? args.amount : options.zoom.amount,
                w = plot.width(), h = plot.height();

            if (!c)
                c = { left: w / 2, top: h / 2 };

            var xf = c.left / w,
                x1 = c.left - xf * w / amount,
                x2 = c.left + (1 - xf) * w / amount,
                yf = c.top / h,
                y1 = c.top - yf * h / amount,
                y2 = c.top + (1 - yf) * h / amount;

            function scaleAxis(min, max, name) {
                var axis = axes[name],
                    axisOptions = options[name];

                if (!axis.used)
                    return;

                min = axis.c2p(min);
                max = axis.c2p(max);
                if (max < min) { // make sure min < max
                    var tmp = min
                    min = max;
                    max = tmp;
                }

                var range = max - min, zr = axisOptions.zoomRange;
                if (zr &&
                    ((zr[0] != null && range < zr[0]) ||
                     (zr[1] != null && range > zr[1])))
                    return;

                axisOptions.min = min;
                axisOptions.max = max;
            }

            scaleAxis(x1, x2, 'xaxis');
            scaleAxis(x1, x2, 'x2axis');
            scaleAxis(y1, y2, 'yaxis');
            scaleAxis(y1, y2, 'y2axis');

            plot.setupGrid();
            plot.draw();

            if (!args.preventEvent)
                plot.getPlaceholder().trigger("plotzoom", [ plot ]);
        }

        plot.pan = function (args) {
            var l = +args.left, t = +args.top,
                axes = plot.getAxes(), options = plot.getOptions();

            if (isNaN(l))
                l = 0;
            if (isNaN(t))
                t = 0;

            function panAxis(delta, name) {
                var axis = axes[name],
                    axisOptions = options[name],
                    min, max;

                if (!axis.used)
                    return;

                min = axis.c2p(axis.p2c(axis.min) + delta),
                max = axis.c2p(axis.p2c(axis.max) + delta);

                var pr = axisOptions.panRange;
                if (pr) {
                    // check whether we hit the wall
                    if (pr[0] != null && pr[0] > min) {
                        delta = pr[0] - min;
                        min += delta;
                        max += delta;
                    }

                    if (pr[1] != null && pr[1] < max) {
                        delta = pr[1] - max;
                        min += delta;
                        max += delta;
                    }
                }

                axisOptions.min = min;
                axisOptions.max = max;
            }

            panAxis(l, 'xaxis');
            panAxis(l, 'x2axis');
            panAxis(t, 'yaxis');
            panAxis(t, 'y2axis');

            plot.setupGrid();
            plot.draw();

            if (!args.preventEvent)
                plot.getPlaceholder().trigger("plotpan", [ plot ]);
        }

        plot.hooks.bindEvents.push(bindEvents);
    }

    $.plot.plugins.push({
        init: init,
        options: options,
        name: 'navigate',
        version: '1.0'
    });
})(jQuery);
<commit_msg>Base zoom out on current mouse position rather than a one-level undo<commit_after>/*
Flot plugin for adding panning and zooming capabilities to a plot.

The default behaviour is double click and scrollwheel up/down to zoom
in, drag to pan. The plugin defines plot.zoom({ center }),
plot.zoomOut() and plot.pan(offset) so you easily can add custom
controls. It also fires a "plotpan" and "plotzoom" event when
something happens, useful for synchronizing plots.

Example usage:

  plot = $.plot(...);

  // zoom default amount in on the pixel (100, 200)
  plot.zoom({ center: { left: 10, top: 20 } });

  // zoom out again
  plot.zoomOut({ center: { left: 10, top: 20 } });

  // pan 100 pixels to the left and 20 down
  plot.pan({ left: -100, top: 20 })

Options:

  zoom: {
    interactive: false
    trigger: "dblclick" // or "click" for single click
    amount: 1.5         // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
  }

  pan: {
    interactive: false
  }

  xaxis, yaxis, x2axis, y2axis: {
    zoomRange: null  // or [number, number] (min range, max range)
    panRange: null   // or [number, number] (min, max)
  }

"interactive" enables the built-in drag/click behaviour. "amount" is
the amount to zoom the viewport relative to the current range, so 1 is
100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out).

"zoomRange" is the interval in which zooming can happen, e.g. with
zoomRange: [1, 100] the zoom will never scale the axis so that the
difference between min and max is smaller than 1 or larger than 100.
You can set either of them to null to ignore.

"panRange" confines the panning to stay within a range, e.g. with
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
other. Either can be null.
*/

// First two dependencies, jquery.event.drag.js and
// jquery.mousewheel.js, we put them inline here to save people the
// effort of downloading them.

/*
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
*/
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);

/* jquery.mousewheel.min.js
 * Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * Version: 3.0.2
 *
 * Requires: 1.2.2+
 */
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);

(function ($) {
    var options = {
        xaxis: {
            zoomRange: null, // or [number, number] (min range, max range)
            panRange: null // or [number, number] (min, max)
        },
        zoom: {
            interactive: false,
            trigger: "dblclick", // or "click" for single click
            amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
        },
        pan: {
            interactive: false
        }
    };

    function init(plot) {
        function bindEvents(plot, eventHolder) {
            var o = plot.getOptions();
            if (o.zoom.interactive) {
                function clickHandler(e, zoomOut) {
                    var c = plot.offset();
                    c.left = e.pageX - c.left;
                    c.top = e.pageY - c.top;
                    if (zoomOut)
                        plot.zoomOut({ center: c });
                    else
                        plot.zoom({ center: c });
                }

                eventHolder[o.zoom.trigger](clickHandler);

                eventHolder.mousewheel(function (e, delta) {
                    clickHandler(e, delta < 0);
                });
            }
            if (o.pan.interactive) {
                var prevCursor = 'default', pageX = 0, pageY = 0;

                eventHolder.bind("dragstart", { distance: 10 }, function (e) {
                    if (e.which != 1)  // only accept left-click
                        return false;
                    eventHolderCursor = eventHolder.css('cursor');
                    eventHolder.css('cursor', 'move');
                    pageX = e.pageX;
                    pageY = e.pageY;
                });
                eventHolder.bind("drag", function (e) {
                    // unused at the moment, but we need it here to
                    // trigger the dragstart/dragend events
                });
                eventHolder.bind("dragend", function (e) {
                    eventHolder.css('cursor', prevCursor);
                    plot.pan({ left: pageX - e.pageX,
                               top: pageY - e.pageY });
                });
            }
        }

        plot.zoomOut = function (args) {
            if (!args.amount)
                args.amount = plot.getOptions().zoom.amount

            args.amount = 1 / args.amount;
            plot.zoom(args);
        }

        plot.zoom = function (args) {
            var axes = plot.getAxes(),
                options = plot.getOptions(),
                c = args.center,
                amount = args.amount ? args.amount : options.zoom.amount,
                w = plot.width(), h = plot.height();

            if (!c)
                c = { left: w / 2, top: h / 2 };

            var xf = c.left / w,
                x1 = c.left - xf * w / amount,
                x2 = c.left + (1 - xf) * w / amount,
                yf = c.top / h,
                y1 = c.top - yf * h / amount,
                y2 = c.top + (1 - yf) * h / amount;

            function scaleAxis(min, max, name) {
                var axis = axes[name],
                    axisOptions = options[name];

                if (!axis.used)
                    return;

                min = axis.c2p(min);
                max = axis.c2p(max);
                if (max < min) { // make sure min < max
                    var tmp = min
                    min = max;
                    max = tmp;
                }

                var range = max - min, zr = axisOptions.zoomRange;
                if (zr &&
                    ((zr[0] != null && range < zr[0]) ||
                     (zr[1] != null && range > zr[1])))
                    return;

                axisOptions.min = min;
                axisOptions.max = max;
            }

            scaleAxis(x1, x2, 'xaxis');
            scaleAxis(x1, x2, 'x2axis');
            scaleAxis(y1, y2, 'yaxis');
            scaleAxis(y1, y2, 'y2axis');

            plot.setupGrid();
            plot.draw();

            if (!args.preventEvent)
                plot.getPlaceholder().trigger("plotzoom", [ plot ]);
        }

        plot.pan = function (args) {
            var l = +args.left, t = +args.top,
                axes = plot.getAxes(), options = plot.getOptions();

            if (isNaN(l))
                l = 0;
            if (isNaN(t))
                t = 0;

            function panAxis(delta, name) {
                var axis = axes[name],
                    axisOptions = options[name],
                    min, max;

                if (!axis.used)
                    return;

                min = axis.c2p(axis.p2c(axis.min) + delta),
                max = axis.c2p(axis.p2c(axis.max) + delta);

                var pr = axisOptions.panRange;
                if (pr) {
                    // check whether we hit the wall
                    if (pr[0] != null && pr[0] > min) {
                        delta = pr[0] - min;
                        min += delta;
                        max += delta;
                    }

                    if (pr[1] != null && pr[1] < max) {
                        delta = pr[1] - max;
                        min += delta;
                        max += delta;
                    }
                }

                axisOptions.min = min;
                axisOptions.max = max;
            }

            panAxis(l, 'xaxis');
            panAxis(l, 'x2axis');
            panAxis(t, 'yaxis');
            panAxis(t, 'y2axis');

            plot.setupGrid();
            plot.draw();

            if (!args.preventEvent)
                plot.getPlaceholder().trigger("plotpan", [ plot ]);
        }

        plot.hooks.bindEvents.push(bindEvents);
    }

    $.plot.plugins.push({
        init: init,
        options: options,
        name: 'navigate',
        version: '1.1'
    });
})(jQuery);
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  return {
    dist: {
      files: ['src/*.js'],
      tasks: ['shell:dist', 'uglify:dist']
    },
    test: {
      files: ['src/*.js', 'test/{*,**.js}'],
      tasks: ['shell:test']
    }
  };
};
<commit_msg>Fix watch task patterns.<commit_after>module.exports = function (grunt) {
  var src = 'src/{*,**/*}.{js,less}';
  var test = 'test/{*,**/*}.{js,less}';

  return {
    dist: {
      files: [src],
      tasks: ['less:dist', 'shell:dist', 'uglify:dist']
    },
    test: {
      files: [src, test],
      tasks: ['shell:test']
    }
  };
};
<|endoftext|>


<commit_before>(function ($) {

var dotTag = "$1",
    spaceTag = " ",
    rDotClass = /(^|\s)kick\-dots\-out__dot(\s|$)/,
    insertSpace;

function wrapDots(el) {
  insertSpace = false
  _wrapDots(el)
}
function _wrapDots(el) {
  var node = el.firstChild, t, len, tmp, next, newChild;
  do {
    switch (node.nodeType) {

      // tag node
      case 1:
        if (!rDotClass.test(node.className)) {
          _wrapDots(node, true)
        }
        break;

      // text node
      case 3:
        if (node.nodeValue.length) {
          t = node.nodeValue
          if (insertSpace) {
            t = spaceTag + t
          }

          len = t.length
          t = t.replace(/([\.\,\?\!\;\:]+)\s*$/, dotTag)

          // If text was changed at last operation then (i.e. text node ends with dot)
          // at the begining of next text node insert "magic space"
          insertSpace = (len != t.length)

          t = t.replace(/([\.\,\?\!\;\:])\s/g, dotTag + spaceTag)

          tmp = document.createElement("i")
          tmp.innerHTML = t
          while (tmp.firstChild) {
            newChild = el.insertBefore(tmp.firstChild, node)
          }
          el.removeChild(node)
          node = newChild
        }
        break;
    }
  }
  while (node = node.nextSibling)
}

$.fn.kickDotsOut = function () {
  return this.each(function () {
    wrapDots(this);
    var spaces = $(".kick-dots-out__s", this), fs;

    $(".kick-dots-out__dot", this).each(function (i) {
      fs = parseFloat($(this).css("font-size"))
      $(spaces[i]).css("word-spacing", ($(this).width()/fs) + "em")
    })
  })
}

$(function () {
  $(".kick-dots-out").kickDotsOut()
})

})(jQuery);
<commit_msg>refactoring<commit_after>(function ($) {

var dotTag = "$1",
    spaceTag = " ",
    rDotClass = /(?:^|\s)kick\-dots\-out__dot(?:\s|$)/,
    insertSpace;

function wrapDots(el) {
  insertSpace = false
  _wrapDots(el)
}
function _wrapDots(el) {
  var node = el.firstChild, t, len, tmp, next, newChild;
  do {
    switch (node.nodeType) {

      // tag node
      case 1:
        if (!rDotClass.test(node.className)) {
          _wrapDots(node, true)
        }
        break;

      // text node
      case 3:
        if (node.nodeValue.length) {
          t = node.nodeValue
          if (insertSpace) {
            t = spaceTag + t
          }

          len = t.length
          t = t.replace(/([\.\,\?\!\;\:]+)\s*$/, dotTag)

          // If text was changed at last operation then (i.e. text node ends with dot)
          // at the begining of next text node insert "magic space"
          insertSpace = (len != t.length)

          t = t.replace(/([\.\,\?\!\;\:])\s/g, dotTag + spaceTag)

          tmp = document.createElement("i")
          tmp.innerHTML = t
          while (tmp.firstChild) {
            newChild = el.insertBefore(tmp.firstChild, node)
          }
          el.removeChild(node)
          node = newChild
        }
        break;
    }
  }
  while (node = node.nextSibling)
}

$.fn.kickDotsOut = function () {
  return this.each(function () {
    wrapDots(this);
    var spaces = $(".kick-dots-out__s", this), fs;

    $(".kick-dots-out__dot", this).each(function (i) {
      fs = parseFloat($(this).css("font-size"))
      $(spaces[i]).css("word-spacing", ($(this).width()/fs) + "em")
    })
  })
}

$(function () {
  $(".kick-dots-out").kickDotsOut()
})

})(jQuery);
<|endoftext|>