<commit_before>Ext.namespace('Vps.Component');
Vps.Component.Pages = Ext.extend(Ext.Panel, {
    initComponent : function()
    {
        this.actions = {};
        this.componentConfigs = {};

        this.pageButtonMenu = new Ext.menu.Menu({
            items    : [
                '-',
                this.getAction('properties'),
                this.getAction('add'),
                this.getAction('delete'),
                this.getAction('visible'),
                this.getAction('makeHome'),
                this.getAction('preview')
            ]
        });
        this.pageButton = new Ext.Toolbar.Button({
            cls     : 'x-btn-text-icon bmenu',
            text    : trlVps('Page'),
            menu    : this.pageButtonMenu,
            icon    : '/assets/silkicons/page.png',
            disabled: true
        });

        this.treePanel = new Vps.Auto.TreePanel({
            controllerUrl: '/admin/component/pages',
            title       : trlVps('Seitenbaum'),
            region      : 'west',
            split       : true,
            width       : 300,
            collapsible : true,
            minSize     : 200,
            maxSize     : 600,
            autoScroll: true,
            tbar: []
        });

        var tbar = this.treePanel.getTopToolbar();
        tbar.add(this.pageButton);

        tbar.add('-');
        tbar.add(trlVps('Search: '));

        var filter = new Vps.Auto.Filter.Text({name: 'text', 'paramName': 'query'});
        filter.on('filter', function(f, params) {
            this.applyBaseParams(params);
            this.reload();
        }, this.treePanel);
        filter.getToolbarItem().each(function(i) {
            tbar.add(i);
        });

        tbar.add('->');
        tbar.add(this.treePanel.getAction('reload'));

        this.treePanel.onMoved = function (response) {
            this.tree.getRootNode().reload();
        };

        this.contentTabPanel = new Ext.TabPanel({
            region      : 'center'
        });
        this.contentTabPanel.on('render', function() {
            this.contentTabPanel.strip.setHeight(24);
        }, this);

        this.layout = 'border';
        this.items = [this.treePanel, this.contentTabPanel];

        Vps.Component.Pages.superclass.initComponent.call(this);

        this.treePanel.on('loaded', this.onTreePanelLoaded, this);
        this.setupEditform();

        this.editActions = {};
    },
    setupEditform : function ()
    {
       this.editDialog = new Vps.Auto.Form.Window({
            width: 400,
            height: 400,
            controllerUrl: ' '
        });
        this.editDialog.on('datachange', function(test) {
            this.treePanel.tree.root.reload();
        }, this);
    },

    onTreePanelLoaded : function(tree)
    {
        tree.loader.on('load', function(tree, node, response) {
            var result = Ext.decode(response.responseText);
            Ext.applyIf(this.componentConfigs, result.componentConfigs);
        }, this);

        this.contextMenu = new Ext.menu.Menu({
             items: [
                '-',
                this.getAction('properties'),
                this.getAction('add'),
                this.getAction('delete'),
                this.getAction('visible'),
                this.getAction('makeHome'),
                this.getAction('preview')
            ]
        });

        tree.on('click', this.treeSelectionchange, this);
        tree.on('contextmenu', function (node) {
            node.select();
            this.treeSelectionchange(node);
            this.contextMenu.show(node.ui.getAnchor());
        }, this);

        tree.on('dblclick', function (o, e) {
            var action;
            for (var i in this.editActions) {
                if (!this.editActions[i].isHidden()) {
                    action = this.editActions[i];
                }
            }
            if (action) {
                action.execute(action.initialConfig);
            }
        }, this);

    },

    treeSelectionchange : function (node) {
        if (!node) return;
        var data = node.attributes;

        this.editDialog.getAutoForm().editControllerUrl = data.editControllerUrl;
        this.editDialog.getAutoForm().addControllerUrl = data.addControllerUrl;

        if (data.disabled) {
            this.pageButton.disable();
        } else {
            this.pageButton.enable();
        }

        for (var action in data.actions) {
        	if (data.actions[action]) {
                this.getAction(action).enable();
        	} else {
                this.getAction(action).disable();
        	}
        }

        for (var i in this.editActions) {
            this.editActions[i].hide();
        }
        data.editComponents.each(function(editComponent) {
            var actionKey = editComponent.componentClass+'-'+editComponent.type;
            if (!this.editActions[actionKey]) {
                this.editActions[actionKey] = new Ext.Action({
                    text    : this.componentConfigs[actionKey].title,
                    handler : function (o, e) {
                        var node = this.treePanel.tree.getSelectionModel().getSelectedNode();
                        node.attributes.editComponents.each(function(editComponent) {
                            if (editComponent.componentClass+'-'+editComponent.type == o.actionKey) {
                                this.loadComponent({
                                    id: editComponent.componentId,
                                    componentClass: editComponent.componentClass,
                                    type: editComponent.type,
                                    text: node.text,
                                    icon: node.attributes.bIcon,
                                    editComponents: node.attributes.editComponents,
                                    pageId: node.attributes.id
                                });
                                return false;
                            }
                        }, this);
                    },
                    icon    : this.componentConfigs[actionKey].icon,
                    cls     : 'x-btn-text-icon',
                    scope   : this,
                    disabled : data.disabled,
                    actionKey: actionKey
                });
                this.contextMenu.insert(0, new Ext.menu.Item(this.editActions[actionKey]));
                this.pageButtonMenu.insert(0, new Ext.menu.Item(this.editActions[actionKey]));
            }
            this.editActions[actionKey].show();
        }, this);
    },

    loadComponent: function(data)
    {
        var panel = this.contentTabPanel.getItem('page'+data.pageId);
        if (!panel) {
            panel = this.createComponentPanel(data);
            this.contentTabPanel.add(panel);
        }
        this.contentTabPanel.setActiveTab(panel);

        panel.applyBaseParams({
            id: data.id
        });
        panel.mainComponentText = data.text;
        panel.mainComponentIcon = data.icon;
        panel.load({
            componentClass: data.componentClass,
            type: data.type,
            editComponents: data.editComponents
        });
    },

    createComponentPanel: function(data)
    {
        var panel = new Vps.Component.ComponentPanel({
            id          : 'page'+data.pageId,
            title       : data.text,
            closable    : true,
            autoLoad    : false,
            componentConfigs : this.componentConfigs
        });
        return panel;
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];

        if (type == 'properties') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Page properties'),
                handler : function () {
                    var form = this.editDialog.getAutoForm();
                    form.controllerUrl = form.editControllerUrl;
                    if (form.formPanel) {
                        form.remove(form.formPanel, true);
                        this.editDialog.getAutoForm().formPanel = null;
                    }
                    var node = this.treePanel.tree.selModel.selNode;
                    this.editDialog.getAutoForm().setBaseParams({
                        componentId: node.attributes.editControllerComponentId
                    });
                    this.editDialog.showEdit(node.id);
                },
                icon    : '/assets/silkicons/page_gear.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'add') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Add new child page'),
                handler : function () {
            		var form = this.editDialog.getAutoForm();
                    form.controllerUrl = form.addControllerUrl;
	                if (form.formPanel) {
	                    form.remove(form.formPanel, true);
	                    this.editDialog.getAutoForm().formPanel = null;
	                }
                    var node = this.treePanel.tree.selModel.selNode;
                    this.editDialog.getAutoForm().setBaseParams({
                        componentId: node.attributes.editControllerComponentId,
                        parent_id: node.id
                    });
                    this.editDialog.showAdd();
                },
                icon    : '/assets/silkicons/page_add.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'delete') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Delete page'),
                handler : function() {
                    this.treePanel.onDelete();
                },
                icon    : '/assets/silkicons/page_delete.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'visible') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Show / hide page'),
                handler : function() {
                    this.treePanel.onVisible();
                },
                icon    : '/assets/fx_invisible/silkicons/page.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'makeHome') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Use as homepage'),
                handler : function (o, e) {
                    Ext.Msg.show({
                        title: trlVps('Use as homepage'),
                        msg: trlVps('Attention! You are about to set the selected page as the homepage of your website. This may affect the entire website. Do you wish to proceed?'),
                        buttons: Ext.Msg.YESNO,
                        icon: Ext.MessageBox.WARNING,
                        fn: function(btn, text) {
                            if (btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/admin/component/pages/json-make-home',
                                    success: function(r) {
                                        response = Ext.decode(r.responseText);
                                        var oldhome = this.treePanel.tree.getNodeById(response.oldhome);
                                        oldhome.attributes.visible = response.oldhomeVisible;
                                        this.treePanel.setVisible(oldhome);
                                        oldhome.ui.iconNode.style.backgroundImage = 'url(/assets/silkicons/page.png)';
                                        var home = this.treePanel.tree.getNodeById(response.home);
                                        home.ui.iconNode.style.backgroundImage = 'url(/assets/silkicons/application_home.png)';
                                    },
                                    params: {id: this.treePanel.tree.getSelectionModel().getSelectedNode().id },
                                    scope: this
                                });
                            }
                        },
                        scope: this
                    });
                },
                icon    : '/assets/silkicons/application_home.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'expand') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Expand here'),
                handler : function () { this.treePanel.tree.getSelectionModel().getSelectedNode().expand(true); },
                icon    : '/assets/silkicons/bullet_add.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'collapse') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Collapse here'),
                handler : function () { this.treePanel.tree.getSelectionModel().getSelectedNode().collapse(true); },
                icon    : '/assets/silkicons/bullet_delete.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'preview') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Open preview'),
                handler : function () {
                    window.open('/admin/component/pages/open-preview?page_id='+
                                this.treePanel.getSelectedId());
                },
                icon    : '/assets/silkicons/page_white_magnify.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else {
            throw 'unknown action-type: ' + type;
        }
        return this.actions[type];
    }

});

Ext.reg('vps.component.pages', Vps.Component.Pages);
<commit_msg>disabled nicht nur beim erstenmal erstellen der action beruecksichtigen<commit_after>Ext.namespace('Vps.Component');
Vps.Component.Pages = Ext.extend(Ext.Panel, {
    initComponent : function()
    {
        this.actions = {};
        this.componentConfigs = {};

        this.pageButtonMenu = new Ext.menu.Menu({
            items    : [
                '-',
                this.getAction('properties'),
                this.getAction('add'),
                this.getAction('delete'),
                this.getAction('visible'),
                this.getAction('makeHome'),
                this.getAction('preview')
            ]
        });
        this.pageButton = new Ext.Toolbar.Button({
            cls     : 'x-btn-text-icon bmenu',
            text    : trlVps('Page'),
            menu    : this.pageButtonMenu,
            icon    : '/assets/silkicons/page.png',
            disabled: true
        });

        this.treePanel = new Vps.Auto.TreePanel({
            controllerUrl: '/admin/component/pages',
            title       : trlVps('Seitenbaum'),
            region      : 'west',
            split       : true,
            width       : 300,
            collapsible : true,
            minSize     : 200,
            maxSize     : 600,
            autoScroll: true,
            tbar: []
        });

        var tbar = this.treePanel.getTopToolbar();
        tbar.add(this.pageButton);

        tbar.add('-');
        tbar.add(trlVps('Search: '));

        var filter = new Vps.Auto.Filter.Text({name: 'text', 'paramName': 'query'});
        filter.on('filter', function(f, params) {
            this.applyBaseParams(params);
            this.reload();
        }, this.treePanel);
        filter.getToolbarItem().each(function(i) {
            tbar.add(i);
        });

        tbar.add('->');
        tbar.add(this.treePanel.getAction('reload'));

        this.treePanel.onMoved = function (response) {
            this.tree.getRootNode().reload();
        };

        this.contentTabPanel = new Ext.TabPanel({
            region      : 'center'
        });
        this.contentTabPanel.on('render', function() {
            this.contentTabPanel.strip.setHeight(24);
        }, this);

        this.layout = 'border';
        this.items = [this.treePanel, this.contentTabPanel];

        Vps.Component.Pages.superclass.initComponent.call(this);

        this.treePanel.on('loaded', this.onTreePanelLoaded, this);
        this.setupEditform();

        this.editActions = {};
    },
    setupEditform : function ()
    {
       this.editDialog = new Vps.Auto.Form.Window({
            width: 400,
            height: 400,
            controllerUrl: ' '
        });
        this.editDialog.on('datachange', function(test) {
            this.treePanel.tree.root.reload();
        }, this);
    },

    onTreePanelLoaded : function(tree)
    {
        tree.loader.on('load', function(tree, node, response) {
            var result = Ext.decode(response.responseText);
            Ext.applyIf(this.componentConfigs, result.componentConfigs);
        }, this);

        this.contextMenu = new Ext.menu.Menu({
             items: [
                '-',
                this.getAction('properties'),
                this.getAction('add'),
                this.getAction('delete'),
                this.getAction('visible'),
                this.getAction('makeHome'),
                this.getAction('preview')
            ]
        });

        tree.on('click', this.treeSelectionchange, this);
        tree.on('contextmenu', function (node) {
            node.select();
            this.treeSelectionchange(node);
            this.contextMenu.show(node.ui.getAnchor());
        }, this);

        tree.on('dblclick', function (o, e) {
            var action;
            for (var i in this.editActions) {
                if (!this.editActions[i].isHidden()) {
                    action = this.editActions[i];
                }
            }
            if (action) {
                action.execute(action.initialConfig);
            }
        }, this);

    },

    treeSelectionchange : function (node) {
        if (!node) return;
        var data = node.attributes;

        this.editDialog.getAutoForm().editControllerUrl = data.editControllerUrl;
        this.editDialog.getAutoForm().addControllerUrl = data.addControllerUrl;

        if (data.disabled) {
            this.pageButton.disable();
        } else {
            this.pageButton.enable();
        }

        for (var action in data.actions) {
        	if (data.actions[action]) {
                this.getAction(action).enable();
        	} else {
                this.getAction(action).disable();
        	}
        }

        for (var i in this.editActions) {
            this.editActions[i].hide();
        }
        data.editComponents.each(function(editComponent) {
            var actionKey = editComponent.componentClass+'-'+editComponent.type;
            if (!this.editActions[actionKey]) {
                this.editActions[actionKey] = new Ext.Action({
                    text    : this.componentConfigs[actionKey].title,
                    handler : function (o, e) {
                        var node = this.treePanel.tree.getSelectionModel().getSelectedNode();
                        node.attributes.editComponents.each(function(editComponent) {
                            if (editComponent.componentClass+'-'+editComponent.type == o.actionKey) {
                                this.loadComponent({
                                    id: editComponent.componentId,
                                    componentClass: editComponent.componentClass,
                                    type: editComponent.type,
                                    text: node.text,
                                    icon: node.attributes.bIcon,
                                    editComponents: node.attributes.editComponents,
                                    pageId: node.attributes.id
                                });
                                return false;
                            }
                        }, this);
                    },
                    icon    : this.componentConfigs[actionKey].icon,
                    cls     : 'x-btn-text-icon',
                    scope   : this,
                    actionKey: actionKey
                });
                this.contextMenu.insert(0, new Ext.menu.Item(this.editActions[actionKey]));
                this.pageButtonMenu.insert(0, new Ext.menu.Item(this.editActions[actionKey]));
            }
            this.editActions[actionKey].setDisabled(data.disabled);
            this.editActions[actionKey].show();
        }, this);
    },

    loadComponent: function(data)
    {
        var panel = this.contentTabPanel.getItem('page'+data.pageId);
        if (!panel) {
            panel = this.createComponentPanel(data);
            this.contentTabPanel.add(panel);
        }
        this.contentTabPanel.setActiveTab(panel);

        panel.applyBaseParams({
            id: data.id
        });
        panel.mainComponentText = data.text;
        panel.mainComponentIcon = data.icon;
        panel.load({
            componentClass: data.componentClass,
            type: data.type,
            editComponents: data.editComponents
        });
    },

    createComponentPanel: function(data)
    {
        var panel = new Vps.Component.ComponentPanel({
            id          : 'page'+data.pageId,
            title       : data.text,
            closable    : true,
            autoLoad    : false,
            componentConfigs : this.componentConfigs
        });
        return panel;
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];

        if (type == 'properties') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Page properties'),
                handler : function () {
                    var form = this.editDialog.getAutoForm();
                    form.controllerUrl = form.editControllerUrl;
                    if (form.formPanel) {
                        form.remove(form.formPanel, true);
                        this.editDialog.getAutoForm().formPanel = null;
                    }
                    var node = this.treePanel.tree.selModel.selNode;
                    this.editDialog.getAutoForm().setBaseParams({
                        componentId: node.attributes.editControllerComponentId
                    });
                    this.editDialog.showEdit(node.id);
                },
                icon    : '/assets/silkicons/page_gear.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'add') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Add new child page'),
                handler : function () {
            		var form = this.editDialog.getAutoForm();
                    form.controllerUrl = form.addControllerUrl;
	                if (form.formPanel) {
	                    form.remove(form.formPanel, true);
	                    this.editDialog.getAutoForm().formPanel = null;
	                }
                    var node = this.treePanel.tree.selModel.selNode;
                    this.editDialog.getAutoForm().setBaseParams({
                        componentId: node.attributes.editControllerComponentId,
                        parent_id: node.id
                    });
                    this.editDialog.showAdd();
                },
                icon    : '/assets/silkicons/page_add.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'delete') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Delete page'),
                handler : function() {
                    this.treePanel.onDelete();
                },
                icon    : '/assets/silkicons/page_delete.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'visible') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Show / hide page'),
                handler : function() {
                    this.treePanel.onVisible();
                },
                icon    : '/assets/fx_invisible/silkicons/page.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'makeHome') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Use as homepage'),
                handler : function (o, e) {
                    Ext.Msg.show({
                        title: trlVps('Use as homepage'),
                        msg: trlVps('Attention! You are about to set the selected page as the homepage of your website. This may affect the entire website. Do you wish to proceed?'),
                        buttons: Ext.Msg.YESNO,
                        icon: Ext.MessageBox.WARNING,
                        fn: function(btn, text) {
                            if (btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/admin/component/pages/json-make-home',
                                    success: function(r) {
                                        response = Ext.decode(r.responseText);
                                        var oldhome = this.treePanel.tree.getNodeById(response.oldhome);
                                        oldhome.attributes.visible = response.oldhomeVisible;
                                        this.treePanel.setVisible(oldhome);
                                        oldhome.ui.iconNode.style.backgroundImage = 'url(/assets/silkicons/page.png)';
                                        var home = this.treePanel.tree.getNodeById(response.home);
                                        home.ui.iconNode.style.backgroundImage = 'url(/assets/silkicons/application_home.png)';
                                    },
                                    params: {id: this.treePanel.tree.getSelectionModel().getSelectedNode().id },
                                    scope: this
                                });
                            }
                        },
                        scope: this
                    });
                },
                icon    : '/assets/silkicons/application_home.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'expand') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Expand here'),
                handler : function () { this.treePanel.tree.getSelectionModel().getSelectedNode().expand(true); },
                icon    : '/assets/silkicons/bullet_add.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'collapse') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Collapse here'),
                handler : function () { this.treePanel.tree.getSelectionModel().getSelectedNode().collapse(true); },
                icon    : '/assets/silkicons/bullet_delete.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else if (type == 'preview') {
            this.actions[type] = new Ext.Action({
                text    : trlVps('Open preview'),
                handler : function () {
                    window.open('/admin/component/pages/open-preview?page_id='+
                                this.treePanel.getSelectedId());
                },
                icon    : '/assets/silkicons/page_white_magnify.png',
                cls     : 'x-btn-text-icon',
                scope   : this
            });
        } else {
            throw 'unknown action-type: ' + type;
        }
        return this.actions[type];
    }

});

Ext.reg('vps.component.pages', Vps.Component.Pages);
<|endoftext|>


<commit_before>const AgeCounters = require("../../lib/components/agecounters");

describe("AgeCounters", function() {
    describe("constructor", function() {
        it("Can construct some counter periods by default", function() {
            const ageCounter = new AgeCounters();
            expect(ageCounter.counterPeriods).toEqual(["1h", "1d", "7d", "all"]);
            expect(ageCounter.counters.size).toEqual(4);
            const mapIter = ageCounter.counters.keys();
            expect(mapIter.next().value).toEqual(3600);
            expect(mapIter.next().value).toEqual(3600 * 24);
            expect(mapIter.next().value).toEqual(3600 * 24 * 7);
            expect(mapIter.next().value).toEqual("all");
        });

        it("Can construct given counter periods", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d", "3w"]);
            expect(ageCounter.counterPeriods).toEqual(["1h", "2d", "5d", "3w", "all"]);
            expect(ageCounter.counters.size).toEqual(5);
            const mapIter = ageCounter.counters.keys();
            expect(mapIter.next().value).toEqual(3600);
            expect(mapIter.next().value).toEqual(3600 * 24 * 2);
            expect(mapIter.next().value).toEqual(3600 * 24 * 5);
            expect(mapIter.next().value).toEqual(3600 * 24 * 7 * 3);
            expect(mapIter.next().value).toEqual("all");
        });
    });

    describe("bump", function () {
        it("Bumping a small age should go in all slots", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(1200);
            expect(ageCounter.counters.get(3600)).toEqual(1);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(1);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(1);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });

        it("Bumping a middling age should only go in some", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(3600 * 24 * 2);
            expect(ageCounter.counters.get(3600)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(1);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });

        it("Bumping a large age should only go in 'all'", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(1200000);
            expect(ageCounter.counters.get(3600)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(0);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });
    })
    describe("setGauge", function () {
        it("Should appropriately report gauge contents", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            for (let i = 0; i < 5;i++){
                ageCounter.bump(1200);
            }

            for (let i = 0; i < 3;i++){
                ageCounter.bump(3600 * 24);
            }

            for (let i = 0; i < 7;i++){
                ageCounter.bump(3600 * 24 * 7);
            }
            const gaugeContents = [];
            const mockGauge = {
                set: (labels, count) => {
                    gaugeContents.push({labels, count});
                }
            };
            ageCounter.setGauge(mockGauge, {aLabel: 42});
            expect(gaugeContents[0]).toEqual({
                labels: {
                    age: "1h",
                    aLabel: 42,
                },
                count: 5
            });
            expect(gaugeContents[1]).toEqual({
                labels: {
                    age: "2d",
                    aLabel: 42,
                },
                count: 8
            });
            expect(gaugeContents[2]).toEqual({
                labels: {
                    age: "5d",
                    aLabel: 42,
                },
                count: 8
            });
            expect(gaugeContents[3]).toEqual({
                labels: {
                    age: "all",
                    aLabel: 42,
                },
                count: 15
            });
        });
    });

});
<commit_msg>More testing around passed in values<commit_after>const AgeCounters = require("../../lib/components/agecounters");

describe("AgeCounters", function() {
    describe("constructor", function() {
        it("Can construct some counter periods by default", function() {
            const ageCounter = new AgeCounters();
            expect(ageCounter.counterPeriods).toEqual(["1h", "1d", "7d", "all"]);
            expect(ageCounter.counters.size).toEqual(4);
            const mapIter = ageCounter.counters.keys();
            expect(mapIter.next().value).toEqual(3600);
            expect(mapIter.next().value).toEqual(3600 * 24);
            expect(mapIter.next().value).toEqual(3600 * 24 * 7);
            expect(mapIter.next().value).toEqual("all");
        });

        it("Can construct given counter periods", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d", "3w"]);
            expect(ageCounter.counterPeriods).toEqual(["1h", "2d", "5d", "3w", "all"]);
            expect(ageCounter.counters.size).toEqual(5);
            const mapIter = ageCounter.counters.keys();
            expect(mapIter.next().value).toEqual(3600);
            expect(mapIter.next().value).toEqual(3600 * 24 * 2);
            expect(mapIter.next().value).toEqual(3600 * 24 * 5);
            expect(mapIter.next().value).toEqual(3600 * 24 * 7 * 3);
            expect(mapIter.next().value).toEqual("all");
        });

        it("Can construct with an empty array", function() {
            const ageCounter = new AgeCounters([]);
            expect(ageCounter.counterPeriods).toEqual(["all"]);
            expect(ageCounter.counters.size).toEqual(1);
        });

        it("Cannot construct with invalid period strings", function() {
            expect(() => {new AgeCounters(["cats", "dogs"]);}).toThrow();
            expect(() => {new AgeCounters(["5"]);}).toThrow();
            expect(() => {new AgeCounters(["h"]);}).toThrow();
            expect(() => {new AgeCounters(["1x"]);}).toThrow();
        });
        it("Cannot construct with negative integers", function() {
            expect(() => {new AgeCounters(["-1h"]);}).toThrow();
        });

        it("Cannot construct counter with null", function() {
            expect(() => {new AgeCounters([null]);}).toThrow();
            expect(() => {new AgeCounters([undefined]);}).toThrow();
        });
    });

    describe("bump", function () {
        it("Bumping a small age should go in all slots", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(1200);
            expect(ageCounter.counters.get(3600)).toEqual(1);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(1);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(1);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });

        it("Bumping a middling age should only go in some", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(3600 * 24 * 2);
            expect(ageCounter.counters.get(3600)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(1);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });

        it("Bumping a large age should only go in 'all'", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            ageCounter.bump(1200000);
            expect(ageCounter.counters.get(3600)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 2)).toEqual(0);
            expect(ageCounter.counters.get(3600 * 24 * 5)).toEqual(0);
            expect(ageCounter.counters.get("all")).toEqual(1);
        });
    })
    describe("setGauge", function () {
        it("Should appropriately report gauge contents", function() {
            const ageCounter = new AgeCounters(["1h", "2d", "5d"]);
            for (let i = 0; i < 5;i++){
                ageCounter.bump(1200);
            }

            for (let i = 0; i < 3;i++){
                ageCounter.bump(3600 * 24);
            }

            for (let i = 0; i < 7;i++){
                ageCounter.bump(3600 * 24 * 7);
            }
            const gaugeContents = [];
            const mockGauge = {
                set: (labels, count) => {
                    gaugeContents.push({labels, count});
                }
            };
            ageCounter.setGauge(mockGauge, {aLabel: 42});
            expect(gaugeContents[0]).toEqual({
                labels: {
                    age: "1h",
                    aLabel: 42,
                },
                count: 5
            });
            expect(gaugeContents[1]).toEqual({
                labels: {
                    age: "2d",
                    aLabel: 42,
                },
                count: 8
            });
            expect(gaugeContents[2]).toEqual({
                labels: {
                    age: "5d",
                    aLabel: 42,
                },
                count: 8
            });
            expect(gaugeContents[3]).toEqual({
                labels: {
                    age: "all",
                    aLabel: 42,
                },
                count: 15
            });
        });
    });

});
<|endoftext|>


<commit_before>function saveOptions() {
	let cahcePeriodInput = document.getElementById('cache-period').value;
	let cahcePeriod = Math.max(0, Math.min(60 * 24, cahcePeriodInput));

	let options = {
		autorun: {
			updated: document.getElementById('autorun-updated').checked,
			activated: document.getElementById('autorun-activated').checked
		},
		cache: { period: cahcePeriod },
		popup: {
			newtab: document.getElementById('popup-newtab').checked,
			newtabInBg: document.getElementById('popup-newtab-bg').checked
		}
	};
	updateOptions(options)
		.then(notifySuccess)
		.then(reloadBackgroundPage)
		.catch(notifyFailure);
}

function notifySuccess() {
	let status = document.getElementById('status');
	status.classList.add('success');
	status.textContent = 'Saved!';
	setTimeout(() => status.textContent = '', 750);
}

function notifyFailure() {
	let status = document.getElementById('status');
	status.classList.add('failure');
	status.textContent = 'Error saving options';
}

function restoreOptions() {
	let query = {
		autorun: {
			updated: true,
			activated: true
		},
		cache: { period: DEFAULT_CACHE_PERIOD_MINS },
		popup: {
			newtab: true,
			newtabInBg: true
		}
	};
	getOptions(query).then(options => {
		document.getElementById('autorun-updated').checked = options.autorun.updated;
		document.getElementById('autorun-activated').checked = options.autorun.activated;
		document.getElementById('cache-period').value = options.cache.period;
	});
}

document.addEventListener('DOMContentLoaded', restoreOptions);
document.getElementById('save').addEventListener('click', saveOptions);
<commit_msg>set popup options<commit_after>function saveOptions() {
	let cahcePeriodInput = document.getElementById('cache-period').value;
	let cahcePeriod = Math.max(0, Math.min(60 * 24, cahcePeriodInput));

	let options = {
		autorun: {
			updated: document.getElementById('autorun-updated').checked,
			activated: document.getElementById('autorun-activated').checked
		},
		cache: { period: cahcePeriod },
		popup: {
			newtab: document.getElementById('popup-newtab').checked,
			newtabInBg: document.getElementById('popup-newtab-bg').checked
		}
	};
	updateOptions(options)
		.then(notifySuccess)
		.then(reloadBackgroundPage)
		.catch(notifyFailure);
}

function notifySuccess() {
	let status = document.getElementById('status');
	status.classList.add('success');
	status.textContent = 'Saved!';
	setTimeout(() => status.textContent = '', 750);
}

function notifyFailure() {
	let status = document.getElementById('status');
	status.classList.add('failure');
	status.textContent = 'Error saving options';
}

function restoreOptions() {
	let query = {
		autorun: {
			updated: true,
			activated: true
		},
		cache: { period: DEFAULT_CACHE_PERIOD_MINS },
		popup: {
			newtab: true,
			newtabInBg: true
		}
	};
	getOptions(query).then(options => {
		document.getElementById('autorun-updated').checked = options.autorun.updated;
		document.getElementById('autorun-activated').checked = options.autorun.activated;
		document.getElementById('cache-period').value = options.cache.period;
		document.getElementById('popup-newtab').checked = options.popup.newtab;
		document.getElementById('popup-newtab-bg').checked = options.popup.newtabInBg;
	});
}

document.addEventListener('DOMContentLoaded', restoreOptions);
document.getElementById('save').addEventListener('click', saveOptions);
<|endoftext|>


<commit_before>import math.geom.Vec2D as Vec2D;

import ui.View as View;
import ui.ImageView as ImageView;
import ui.TextView as TextView;
import ui.ScoreView as ScoreView;
import animate;

import ..ViewPool;

exports = Class(ImageView, function (supr) {
	var invert = function(direction) {
		var ret,
			pos = {
				left: 'right',
				right: 'left'
			};

		if (direction !== '') {
			ret = pos[direction];
		}
		return ret;
	};

	this.init = function (opts) {
		opts.width = opts.tileSettings.tileWidth;
		opts.height = opts.tileSettings.tileHeight;

		supr(this, 'init', [opts]);

		this._adventureMapView = opts.adventureMapView;
		this._superview = opts.superview;
		this._ongoing = false;

		this._itemView = null;

		this._tileX = 0;
		this._tileY = 0;

		this._editMode = opts.editMode;

		/*this._doodadView = new ImageView({
			superview: this
		});*/
		this._itemView = new ImageView({
			superview: this,
			zIndex: 1
		});

		this._idText = null;
		this._characterSettings = null;
		this._addItemEmitter = true;
		this._locSet = false;

		this._itemCtors = opts.nodeSettings.itemCtors;
		this._hideViews = {};

		this._tileSettings = opts.tileSettings;
		/*this._doodads = opts.tileSettings.doodads;*/
		this._nodes = opts.nodeSettings.nodes;

		this.canHandleEvents(false);
	};

	this.update = function (grid, tileX, tileY) {
		this._tileX = tileX;
		this._tileY = tileY;

		var tile = grid[tileY][tileX];
		if (tile && tile.node) {
			var node = this._nodes[tile.node - 1];
			var style = this._itemView.style;
			var x = this.style.width * tile.x;
			var y = this.style.height * tile.y;
			if(!this._locSet)
			{
				this.initial = [this.style.x, this.style.y];
				style.x = x - node.width * 0.5;
				style.y = y - node.height * 0.5;
				this.style.x = this.style.x + style.x;
				this.style.y = this.style.y + style.y;
				style.x = 0;
				style.y = 0;
				style.width = node.width;
				style.height = node.height;
				this._locSet = true;
			}

			style.visible = true;
			this._itemView.setImage(node.image);

			this._hideViews = {};
			var itemViews = tile.itemViews;
			if (!itemViews) {
				itemViews = {};
				tile.itemViews = itemViews;
			}

			var hideViews = this._hideViews;
			for (var tag in itemViews) {
				var itemView = itemViews[tag];
				if (itemView.style.visible) {
					hideViews[tag] = itemView;
				}
			}

			for (var tag in tile.tags) {
				if (this._itemCtors[tag]) {
					var itemView = this._adventureMapView._playerView;
					if (!itemView) {
						itemView = new this._itemCtors[tag]({
							superview: this._superview,
							adventureMapView: this._adventureMapView,
							zIndex: 999999999,
							tag: tag,
							tile: tile
						});
						this._adventureMapView._playerView = itemView;
					}
					else {
						itemView.updateOpts({
							tile: tile
						});
						itemView.removeAllListeners('InputSelect');
					}
					itemView.on('InputSelect', bind(this, 'onSelectTag', tag, tile, itemView));

					if (!('centerTag' in this._tileSettings) || this._tileSettings.centerTag) {
						itemView.style.x = this.style.x + (this.style.width * 0.15);
						itemView.style.y = this.style.y - (itemView.style.height * 0.3 + this.style.height);
					} else {
						itemView.style.x = this.style.x + (this.style.width * 0.15);
						itemView.style.y = this.style.y - (itemView.style.height * 0.3 + this.style.height);
					}
					itemView.update && itemView.update(tile);

					hideViews[tag] = null;
				}
			}

			for (var tag in hideViews) {
				if (hideViews[tag]) {
					hideViews[tag].style.visible = false;
				}
			}

			if (tile.id && node.characterSettings && !tile.tags.locked) {
				if (this._idText) {
					this._idText.style.width = node.width;
					this._idText.style.height = node.characterSettings.height || node.height;
					this._idText.setText(tile.id);
					if (node.characterSettings !== this._characterSettings) {
						this._idText.setCharacterData(node.characterSettings.data);
						this._characterSettings = node.characterSettings.data;
					}
				} else {
					this._idText = new ScoreView({
						superview: this._itemView,
						width: node.width,
						height: node.characterSettings.height || node.height,
						text: tile.id,
						blockEvents: true,
						characterData: node.characterSettings.data
					});
					this._idText._container.style.x = -10;
					this._idText._container.style.y = (node.height - node.characterSettings.height) * 0.5-30;
				}
				this._idText.style.width = node.width;
				this._idText.style.height = node.characterSettings.height || node.height;
				this._idText.style.x = node.characterSettings.x || 0;
				this._idText.style.y = node.characterSettings.y || 0;
				if (node.characterSettings !== this._characterSettings) {
					this._idText.setCharacterData(node.characterSettings.data);
					this._characterSettings = node.characterSettings.data;
				}
			}

			if (this._addItemEmitter) {
				this._addItemEmitter = false;
				this._itemView.on('InputSelect', bind(this, 'onSelectNode', tile));
			}
		} else {
			this._itemView.style.visible = false;
		}

		/*if (tile && tile.doodad) {
			var doodad = this._doodads[tile.doodad - 1];
			if (doodad) {
				var style = this._doodadView.style;

				this._doodadView.setImage(doodad.image);
				style.x = tile.doodadX * this._tileSettings.tileWidth - doodad.width * 0.5;
				style.y = tile.doodadY * this._tileSettings.tileHeight - doodad.height * 0.5;
				style.width = doodad.width;
				style.height = doodad.height;
				style.visible = true;
			} else {
				this._doodadView.style.visible = false;
			}
		} else {
			this._doodadView.style.visible = false;
		}*/

		var friendsView = this._friendsView;
		if (tile && tile.friends.views) {
			var friends = tile.friends,
				views = friends.views,
				tileSettings = this._tileSettings,
				position = friends.position || invert(tile.position) || 'right',
				left = (position === 'left'),
				right = (position === 'right'),
				top = (position === 'top'),
				bottom = (position === 'bottom'),
				deltaX = (left ? -1 : (right ? 1 : 0)),
				deltaY = (top ? -1 : (bottom ? 1 : 0)),
				// with and height of the container
				friendsWidth =  (left || right ? friends.width : friends.height),
				friendsHeight = (left || right ? friends.height : friends.width),
				// position of the container if it is after the milestone icon
				// if position is right, then x position should come after the node, on left it should be 0, before the node
				// otherwise (top and bottom) it should take x value from tile settings.
				friendsRight = (right && isNaN(parseFloat(friends.x)) && node ? node.width : (left ? 0 : tileSettings.friendsX)),
				// if position is bottom, then y position should come after the node, on top it should be 0, before the node
				// otherwise (left and right) it should take y value from tile settings.
				friendsBottom = (bottom && isNaN(parseFloat(friends.y)) && node ? node.height : (top ? 0 : tileSettings.friendsY)),
				// position of the container if it is before the milestone icon
				friendsLeft = (left ? friendsWidth : 0),
				friendsTop = (top ? friendsHeight : 0),
				// x and y value for inner views
				x = (deltaX === -1 ? friendsWidth - tileSettings.friendWidth : 0),
				y = (deltaY === -1 ? friendsHeight - tileSettings.friendHeight : 0),
				padding = 25,
				len = views.length,
				view, i;

			if (!friendsView) {
				friendsView = this._friendsView = new View({
					superview: this._superview
				});
				friendsView.on('InputSelect', bind(this, 'onSelectFriends', views, deltaX, deltaY));
			}

			i = len;
			while (i > 0) {
				friendsView.addSubview(views[--i]);
			}

			i = len;
			while (i > 0) {
				view = views[--i];
				view.updateOpts({
					x: x,
					y: y,
					zIndex: i
				});
				x += (padding * deltaX);
				y += (padding * deltaY);
			}

			friendsView.updateOpts({
				x: this.style.x + friends.x * tileSettings.tileWidth - friendsLeft + friendsRight,
				y: this.style.y + friends.y * tileSettings.tileHeight - friendsTop + friendsBottom,
				r: friends.r,
				anchorX: (top || bottom ? friendsWidth / 2 : (left ? friendsWidth : 0)),
				anchorY: (left || right ? friendsHeight / 2 : (top ? friendsHeight : 0)),
				width: friendsWidth,
				height: friendsHeight,
				visible: true
			});
		} else if (friendsView) {
			friendsView.hide();
		}

		this.style.visible = tile.node;
	};

	this.onSelectTag = function (tag, tile, itemView) {
		this._adventureMapView.emit('ClickTag', tag, tile, itemView);
	};

	this.onSelectNode = function (tile) {
		this._adventureMapView.emit('ClickNode', tile);
	};

	this.onSelectFriends = function (views, deltaX, deltaY) {
		if(this._ongoing) {
			return;
		}

		var sub = this._friendsView.getSubviews(),
			len = sub.length,
			i = len,
			tileSettings = this._tileSettings,
			valueX, valueY, view, x, y;

		this._ongoing = true;

		while (i > 0) {
			valueX = tileSettings.friendWidth * deltaX * (len - i);
			valueY = tileSettings.friendHeight * deltaY * (len - i);
			view = views[--i];
			x = view.style.x;
			y = view.style.y;

			animate(view, 'friends')
				.then({x: x + valueX, y: y + valueY})
				.then({}, 1000)
				.then({x: x, y: y})
				.then(bind(this, function() {
					this._ongoing = false;
				}));
		}
	};

	this.refreshLoc = function() {
		this.style.x = this.initial[0];
		this.style.y = this.initial[1];
		this._locSet = false;
	};

	this.onRelease = function () {
		this._addItemEmitter = true;
		this._itemView.removeAllListeners('InputSelect');
	}
});
<commit_msg>reset location of node on viewpool release<commit_after>import math.geom.Vec2D as Vec2D;

import ui.View as View;
import ui.ImageView as ImageView;
import ui.TextView as TextView;
import ui.ScoreView as ScoreView;
import animate;

import ..ViewPool;

exports = Class(ImageView, function (supr) {
	var invert = function(direction) {
		var ret,
			pos = {
				left: 'right',
				right: 'left'
			};

		if (direction !== '') {
			ret = pos[direction];
		}
		return ret;
	};

	this.init = function (opts) {
		opts.width = opts.tileSettings.tileWidth;
		opts.height = opts.tileSettings.tileHeight;

		supr(this, 'init', [opts]);

		this._adventureMapView = opts.adventureMapView;
		this._superview = opts.superview;
		this._ongoing = false;

		this._itemView = null;

		this._tileX = 0;
		this._tileY = 0;

		this._editMode = opts.editMode;

		/*this._doodadView = new ImageView({
			superview: this
		});*/
		this._itemView = new ImageView({
			superview: this,
			zIndex: 1
		});

		this._idText = null;
		this._characterSettings = null;
		this._addItemEmitter = true;
		this._locSet = false;

		this._itemCtors = opts.nodeSettings.itemCtors;
		this._hideViews = {};

		this._tileSettings = opts.tileSettings;
		/*this._doodads = opts.tileSettings.doodads;*/
		this._nodes = opts.nodeSettings.nodes;

		this.canHandleEvents(false);
	};

	this.update = function (grid, tileX, tileY) {
		this._tileX = tileX;
		this._tileY = tileY;

		var tile = grid[tileY][tileX];
		if (tile && tile.node) {
			var node = this._nodes[tile.node - 1];
			var style = this._itemView.style;
			var x = this.style.width * tile.x;
			var y = this.style.height * tile.y;
			if(!this._locSet)
			{
				this.initial = [this.style.x, this.style.y];
				style.x = x - node.width * 0.5;
				style.y = y - node.height * 0.5;
				this.style.x = this.style.x + style.x;
				this.style.y = this.style.y + style.y;
				style.x = 0;
				style.y = 0;
				style.width = node.width;
				style.height = node.height;
				this._locSet = true;
			}

			style.visible = true;
			this._itemView.setImage(node.image);

			this._hideViews = {};
			var itemViews = tile.itemViews;
			if (!itemViews) {
				itemViews = {};
				tile.itemViews = itemViews;
			}

			var hideViews = this._hideViews;
			for (var tag in itemViews) {
				var itemView = itemViews[tag];
				if (itemView.style.visible) {
					hideViews[tag] = itemView;
				}
			}

			for (var tag in tile.tags) {
				if (this._itemCtors[tag]) {
					var itemView = this._adventureMapView._playerView;
					if (!itemView) {
						itemView = new this._itemCtors[tag]({
							superview: this._superview,
							adventureMapView: this._adventureMapView,
							zIndex: 999999999,
							tag: tag,
							tile: tile
						});
						this._adventureMapView._playerView = itemView;
					}
					else {
						itemView.updateOpts({
							tile: tile
						});
						itemView.removeAllListeners('InputSelect');
					}
					itemView.on('InputSelect', bind(this, 'onSelectTag', tag, tile, itemView));

					if (!('centerTag' in this._tileSettings) || this._tileSettings.centerTag) {
						itemView.style.x = this.style.x + (this.style.width * 0.15);
						itemView.style.y = this.style.y - (itemView.style.height * 0.3 + this.style.height);
					} else {
						itemView.style.x = this.style.x + (this.style.width * 0.15);
						itemView.style.y = this.style.y - (itemView.style.height * 0.3 + this.style.height);
					}
					itemView.update && itemView.update(tile);

					hideViews[tag] = null;
				}
			}

			for (var tag in hideViews) {
				if (hideViews[tag]) {
					hideViews[tag].style.visible = false;
				}
			}

			if (tile.id && node.characterSettings && !tile.tags.locked) {
				if (this._idText) {
					this._idText.style.width = node.width;
					this._idText.style.height = node.characterSettings.height || node.height;
					this._idText.setText(tile.id);
					if (node.characterSettings !== this._characterSettings) {
						this._idText.setCharacterData(node.characterSettings.data);
						this._characterSettings = node.characterSettings.data;
					}
				} else {
					this._idText = new ScoreView({
						superview: this._itemView,
						width: node.width,
						height: node.characterSettings.height || node.height,
						text: tile.id,
						blockEvents: true,
						characterData: node.characterSettings.data
					});
					this._idText._container.style.x = -10;
					this._idText._container.style.y = (node.height - node.characterSettings.height) * 0.5-30;
				}
				this._idText.style.width = node.width;
				this._idText.style.height = node.characterSettings.height || node.height;
				this._idText.style.x = node.characterSettings.x || 0;
				this._idText.style.y = node.characterSettings.y || 0;
				if (node.characterSettings !== this._characterSettings) {
					this._idText.setCharacterData(node.characterSettings.data);
					this._characterSettings = node.characterSettings.data;
				}
			}

			if (this._addItemEmitter) {
				this._addItemEmitter = false;
				this._itemView.on('InputSelect', bind(this, 'onSelectNode', tile));
			}
		} else {
			this._itemView.style.visible = false;
		}

		/*if (tile && tile.doodad) {
			var doodad = this._doodads[tile.doodad - 1];
			if (doodad) {
				var style = this._doodadView.style;

				this._doodadView.setImage(doodad.image);
				style.x = tile.doodadX * this._tileSettings.tileWidth - doodad.width * 0.5;
				style.y = tile.doodadY * this._tileSettings.tileHeight - doodad.height * 0.5;
				style.width = doodad.width;
				style.height = doodad.height;
				style.visible = true;
			} else {
				this._doodadView.style.visible = false;
			}
		} else {
			this._doodadView.style.visible = false;
		}*/

		var friendsView = this._friendsView;
		if (tile && tile.friends.views) {
			var friends = tile.friends,
				views = friends.views,
				tileSettings = this._tileSettings,
				position = friends.position || invert(tile.position) || 'right',
				left = (position === 'left'),
				right = (position === 'right'),
				top = (position === 'top'),
				bottom = (position === 'bottom'),
				deltaX = (left ? -1 : (right ? 1 : 0)),
				deltaY = (top ? -1 : (bottom ? 1 : 0)),
				// with and height of the container
				friendsWidth =  (left || right ? friends.width : friends.height),
				friendsHeight = (left || right ? friends.height : friends.width),
				// position of the container if it is after the milestone icon
				// if position is right, then x position should come after the node, on left it should be 0, before the node
				// otherwise (top and bottom) it should take x value from tile settings.
				friendsRight = (right && isNaN(parseFloat(friends.x)) && node ? node.width : (left ? 0 : tileSettings.friendsX)),
				// if position is bottom, then y position should come after the node, on top it should be 0, before the node
				// otherwise (left and right) it should take y value from tile settings.
				friendsBottom = (bottom && isNaN(parseFloat(friends.y)) && node ? node.height : (top ? 0 : tileSettings.friendsY)),
				// position of the container if it is before the milestone icon
				friendsLeft = (left ? friendsWidth : 0),
				friendsTop = (top ? friendsHeight : 0),
				// x and y value for inner views
				x = (deltaX === -1 ? friendsWidth - tileSettings.friendWidth : 0),
				y = (deltaY === -1 ? friendsHeight - tileSettings.friendHeight : 0),
				padding = 25,
				len = views.length,
				view, i;

			if (!friendsView) {
				friendsView = this._friendsView = new View({
					superview: this._superview
				});
				friendsView.on('InputSelect', bind(this, 'onSelectFriends', views, deltaX, deltaY));
			}

			i = len;
			while (i > 0) {
				friendsView.addSubview(views[--i]);
			}

			i = len;
			while (i > 0) {
				view = views[--i];
				view.updateOpts({
					x: x,
					y: y,
					zIndex: i
				});
				x += (padding * deltaX);
				y += (padding * deltaY);
			}

			friendsView.updateOpts({
				x: this.style.x + friends.x * tileSettings.tileWidth - friendsLeft + friendsRight,
				y: this.style.y + friends.y * tileSettings.tileHeight - friendsTop + friendsBottom,
				r: friends.r,
				anchorX: (top || bottom ? friendsWidth / 2 : (left ? friendsWidth : 0)),
				anchorY: (left || right ? friendsHeight / 2 : (top ? friendsHeight : 0)),
				width: friendsWidth,
				height: friendsHeight,
				visible: true
			});
		} else if (friendsView) {
			friendsView.hide();
		}

		this.style.visible = tile.node;
	};

	this.onSelectTag = function (tag, tile, itemView) {
		this._adventureMapView.emit('ClickTag', tag, tile, itemView);
	};

	this.onSelectNode = function (tile) {
		this._adventureMapView.emit('ClickNode', tile);
	};

	this.onSelectFriends = function (views, deltaX, deltaY) {
		if(this._ongoing) {
			return;
		}

		var sub = this._friendsView.getSubviews(),
			len = sub.length,
			i = len,
			tileSettings = this._tileSettings,
			valueX, valueY, view, x, y;

		this._ongoing = true;

		while (i > 0) {
			valueX = tileSettings.friendWidth * deltaX * (len - i);
			valueY = tileSettings.friendHeight * deltaY * (len - i);
			view = views[--i];
			x = view.style.x;
			y = view.style.y;

			animate(view, 'friends')
				.then({x: x + valueX, y: y + valueY})
				.then({}, 1000)
				.then({x: x, y: y})
				.then(bind(this, function() {
					this._ongoing = false;
				}));
		}
	};

	this.refreshLoc = function() {
		this.style.x = this.initial[0];
		this.style.y = this.initial[1];
		this._locSet = false;
	};

	this.onRelease = function () {
		this._addItemEmitter = true;
		this.refreshLoc();
		this._itemView.removeAllListeners('InputSelect');
	}
});
<|endoftext|>


<commit_before>import math.geom.Vec2D as Vec2D;

import ui.View as View;
import ui.ImageView as ImageView;
import ui.TextView as TextView;

exports = Class(ImageView, function (supr) {
	this.init = function (opts) {
		supr(this, 'init', [opts]);

		this._path = opts.tileSettings.directory;
	};

	this.update = function (grid, tileX, tileY) {
		this._tileX = tileX;
		this._tileY = tileY;

		this.setImage(this._path + '/' + tileY + '_' + tileX + '.png');
	};

	this.onInputSelect = function () {
		this._superview.emit('Select', this._tileX, this._tileY);
	};
});
<commit_msg>Changes to support location based spritesheets<commit_after>import math.geom.Vec2D as Vec2D;

import ui.View as View;
import ui.ImageView as ImageView;
import ui.TextView as TextView;

exports = Class(ImageView, function (supr) {
	this.init = function (opts) {
		supr(this, 'init', [opts]);

		this._path = opts.tileSettings.directory;
	};

	this.update = function (grid, tileX, tileY) {
		this._tileX = tileX;
		this._tileY = tileY;

		if (typeof(this._path) === 'string') {
			this.setImage(this._path + '/' + tileY + '_' + tileX + '.png');
		} else {
			this.setImage(this._path(tileX, tileY));
		}
	};

	this.onInputSelect = function () {
		this._superview.emit('Select', this._tileX, this._tileY);
	};
});
<|endoftext|>


<commit_before>/*
 *
 * https://github.com/seiyugi/debuguy
 *
 * Copyright (c) 2014 seiyugi
 * Licensed under the MPL license.
 */

'use strict';

var fs = require('fs');
var regex = /^(\s*)\/\*\sdebuguy\:\stag\((.+)\)\s*\*\//;
var outputLine = '$1console.log(\'debuguy,\' + (new Date()).getTime() + \',\' + $2);';

var endsWith = function _endsWith(src, suffix) {
    return src.indexOf(suffix, src.length - suffix.length) !== -1;
};

var debuguy = {
  parse: function(dir, out) {
    fs.readdir(dir, function (err, list) {
      if (err) {
        console.log(err);
        return;
      }

      dir = endsWith(dir, '/') ? dir : dir + '/';

      out = out || dir;

      fs.exists(out, function (exists) {
        if (!exists) {
          // change it to async mkdir later
          fs.mkdirSync(out);
        }
      });

      list.filter(function(item) {
        fs.readFile(dir+item, function (err, data) {

          if (err) {
            console.log(err);
            console.log(data);
            return;
          }

          var txt = data.toString();
          var lines = txt.split('\n');
          var outputLines = [];

          lines.forEach(function (line) {
            // console.log(line);
            line = line.replace(regex, outputLine);
            outputLines.push(line);
          });

          fs.writeFile(out + item, outputLines.join('\n'), function(err) {
            if (err) {
              console.log(err);
            } else {
              console.log("The file was saved!");
            }
          });

          });

        });
    });

  }
};

module.exports = debuguy;
<commit_msg>Revise js source parsing.<commit_after>/*
 *
 * https://github.com/seiyugi/debuguy
 *
 * Copyright (c) 2014 seiyugi
 * Licensed under the MPL license.
 */

'use strict';

var fs = require('fs');
var regex = /^(\s*)\/\*\sdebuguy\:\stag\((.+)\)\s*\*\/\n/gm;
var outputLine = '$1console.log(\'debuguy,\' + (new Date()).getTime() + \',\' + $2);';

var endsWith = function _endsWith(src, suffix) {
  return src.indexOf(suffix, src.length - suffix.length) !== -1;
};

var debuguy = {
  parse: function(dir, out) {
    fs.readdir(dir, function(err, list) {
      if (err) {
        console.log(err);
        return;
      }

      dir = endsWith(dir, '/') ? dir : dir + '/';

      out = out || dir;

      fs.exists(out, function(exists) {
        if (!exists) {
          // change it to async mkdir later
          fs.mkdirSync(out);
        }
      });

      list.forEach(function(item) {
        // if the item is a directory
        if (fs.lstatSync(dir + item).isDirectory()) {
          return;
        }

        fs.readFile(dir + item, function(err, data) {

          if (err) {
            console.log(err);
            console.log(data);
            return;
          }

          var txt = data.toString();

          // if no match in the file
          if (!txt.match(regex)) {
            return;
          }

          fs.writeFile(out + item, txt.replace(regex, outputLine), function(err) {
            if (err) {
              console.log(err);
            } else {
              console.log(out + item + ' was saved!');
            }
          });

        });

      });
    });

  }
};

module.exports = debuguy;
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';
import { humanReadableTimeStamp } from '../utillities'

class BlockUser extends React.Component {

  render() {
    return (
      <Link to={`conversation/${this.props.id}`} className="c-block-user" key={ this.props.id } onClick={ () => this.props.onClick() }>

          { this.renderBlockUserData() }

{ this.props.name }

{ this.renderBlockUserText() }

      </Link>
    );
  }

  renderBlockUserData() {
    let data = [];

    if (this.props.unreadMessagesCount) {
      data.push(
{this.props.unreadMessagesCount} new messages
);
    }

    if (this.props.lastMessage) {
      data.push(
{ humanReadableTimeStamp(this.props.lastMessageAt) }
);
    }

    else if (this.props.lastSeenAt) {
      data.push(
last seen: { humanReadableTimeStamp(this.props.lastSeenAt) }
);
    }

    return data;
  }

  renderBlockUserText() {
    let text;

    if (this.props.lastMessage) {
      text = this.props.lastMessage;
    }

    else if (this.props.description) {
      text = this.props.description;
    }

    return text;
  }
}

BlockUser.propTypes = {
  id: React.PropTypes.number,
  name: React.PropTypes.string,
  description: React.PropTypes.string,
  lastMessage: React.PropTypes.string,
  imageSource: React.PropTypes.string,
  lastSeenDate: React.PropTypes.string,
  lastMessageDate: React.PropTypes.string,
  unreadMessagesLength: React.PropTypes.number,
};

BlockUser.defaultProps = {
  onClick: () => {},
};

export default BlockUser;
<commit_msg>Added isActive and onClick to component props specification.<commit_after>import React from 'react';
import { Link } from 'react-router';
import { humanReadableTimeStamp } from '../utillities'

class BlockUser extends React.Component {

  render() {
    return (
      <Link to={`conversation/${this.props.id}`} className="c-block-user" key={ this.props.id } onClick={ () => this.props.onClick() }>

          { this.renderBlockUserData() }

{ this.props.name }

{ this.renderBlockUserText() }

      </Link>
    );
  }

  renderBlockUserData() {
    let data = [];

    if (this.props.unreadMessagesCount) {
      data.push(
{this.props.unreadMessagesCount} new messages
);
    }

    if (this.props.lastMessage) {
      data.push(
{ humanReadableTimeStamp(this.props.lastMessageAt) }
);
    }

    else if (this.props.lastSeenAt) {
      data.push(
last seen: { humanReadableTimeStamp(this.props.lastSeenAt) }
);
    }

    return data;
  }

  renderBlockUserText() {
    let text;

    if (this.props.lastMessage) {
      text = this.props.lastMessage;
    }

    else if (this.props.description) {
      text = this.props.description;
    }

    return text;
  }
}

BlockUser.propTypes = {
  id: React.PropTypes.number,
  name: React.PropTypes.string,
  description: React.PropTypes.string,
  lastMessage: React.PropTypes.string,
  imageSource: React.PropTypes.string,
  lastSeenDate: React.PropTypes.string,
  lastMessageDate: React.PropTypes.string,
  unreadMessagesLength: React.PropTypes.number,
  isActive: React.PropTypes.bool,
  onClick: React.PropTypes.func,
};

BlockUser.defaultProps = {
  isActive: false,
  onClick: () => {},
};

export default BlockUser;
<|endoftext|>


<commit_before>//..............................................................................
//
//  This file is part of the Doxyrest toolkit.
//
//  Doxyrest is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/doxyrest/license.txt
//
//..............................................................................

(function () {

var g_oldTarget = $([]);

function getTargetFromSpan(span) {
	var parent = span.parent();

	// ascend to the top-level

	while (parent.is("span"))
	{
		span = parent;
		parent = parent.parent();
	}

	// check the direct parent of the top-level

	if (parent.is("pre"))
		return parent;

	// nope, skip all sibling spans

	var next = span.next();
	while (next.is("span"))
		next = next.next();

	if (next.is("pre, :header"))
		return next;

	return null;
}

function updateTarget() {
	var target = $(":target");

	// sphinx uses spans to inject multiple ids

	if (target.is("span")) {
		element = getTargetFromSpan(target);
		if (element)
			target = element;
	}

	g_oldTarget.removeClass("target-highlight");
	target.addClass("target-highlight");
	g_oldTarget = target;
}

$(document).ready(updateTarget);
$(window).on('hashchange', updateTarget);

} ());

//..............................................................................
<commit_msg>[sphinx] updated the target highlighting logic<commit_after>//..............................................................................
//
//  This file is part of the Doxyrest toolkit.
//
//  Doxyrest is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/doxyrest/license.txt
//
//..............................................................................

(function () {

var g_oldTarget = $([]);
var g_suitableTargetClass = "pre, h2, h3, h4, h5, h6"; // don't highlight

function adjustTarget(target) {
	if (target.is("div"))
		target = target.children(":first");

	if (target.is(g_suitableTargetClass))
		return target;

	if (!target.is("span"))
		return $([]);

	// ascend to the top-level

	var parent = target.parent();
	while (parent.is("span"))
	{
		target = parent;
		parent = parent.parent();
	}

	// check the direct parent of the top-level

	if (parent.is("pre"))
		return parent;

	// nope, skip all sibling spans

	target = target.next();
	while (target.is("span"))
		target = target.next();

	if (target.is(g_suitableTargetClass))
		return target;

	return $([]); // no target to highlight
}

function updateTarget() {
	var target = adjustTarget($(":target"));
	g_oldTarget.removeClass("target-highlight");
	target.addClass("target-highlight");
	g_oldTarget = target;
}

$(document).ready(updateTarget);
$(window).on('hashchange', updateTarget);

} ());

//..............................................................................
<|endoftext|>


<commit_before>var _ = require('underscore');
var Model = require('../core/model');
var Template = require('../core/template');
var Annotation = require('../geo/ui/annotation');
var Search = require('../geo/ui/search/search');
var Text = require('../geo/ui/text');
var TilesLoader = require('../geo/ui/tiles-loader');
var Zoom = require('../geo/ui/zoom/zoom-view');
var FullScreen = require('../ui/common/fullscreen/fullscreen-view');
var AttributionView = require('../geo/ui/attribution/attribution-view');
var LogoView = require('../geo/ui/logo-view');
var log = require('cdb.log');

/**
 * defines the container for an overlay.
 * It places the overlay
 */
var OverlaysFactory = {

  _types: {},

  // register a type to be created
  register: function (type, creatorFn) {
    OverlaysFactory._types[type] = creatorFn;
  },

  // create a type given the data
  // raise an exception if the type does not exist
  create: function (type, data, deps) {
    deps = deps || {};
    if (!deps.visView) throw new Error('visView is required');
    if (!deps.map) throw new Error('map is required');
    var visView = deps.visView;
    var map = deps.map;

    var t = OverlaysFactory._types[type];

    if (!t) {
      log.error("OverlaysFactory: '" + type + "' does not exist");
      return;
    }

    data.options = typeof data.options === 'string' ? JSON.parse(data.options) : data.options;
    data.options = data.options || {};
    var widget = t(data, visView, map);

    if (widget) {
      widget.type = type;
      return widget;
    }

    return false;
  }
};

OverlaysFactory.register('logo', function (data, visView, map) {
  var overlay = new LogoView();
  return overlay.render();
});

OverlaysFactory.register('attribution', function (data, visView, map) {
  var overlay = new AttributionView({
    map: map
  });

  return overlay.render();
});

OverlaysFactory.register('text', function (data, visView, map) {
  var options = data.options;

  var template = Template.compile(
    data.template || [
      '
',
      '
{{{ text }}}
',
      '
'
    ].join('\n'),
    data.templateType || 'mustache'
  );

  var widget = new Text({
    model: new Model(options),
    template: template,
    className: 'cartodb-overlay overlay-text ' + options.device
  });

  return widget.render();
});

OverlaysFactory.register('annotation', function (data, visView, map) {
  var options = data.options;

  var template = Template.compile(
    data.template || [
      '
',
      '
{{{ text }}}
',
      '

',
      '
'
    ].join('\n'),
    data.templateType || 'mustache'
  );

  var widget = new Annotation({
    className: 'cartodb-overlay overlay-annotation ' + options.device,
    template: template,
    mapView: visView.mapView,
    device: options.device,
    text: options.extra.rendered_text,
    minZoom: options.style['min-zoom'],
    maxZoom: options.style['max-zoom'],
    latlng: options.extra.latlng,
    style: options.style
  });

  return widget.render();
});

// map zoom control
OverlaysFactory.register('zoom', function (data, visView, map) {
  var opts = {
    model: map
  };

  var zoom = new Zoom(opts);
  return zoom.render();
});

// Tiles loader
OverlaysFactory.register('loader', function (data) {
  var tilesLoader = new TilesLoader();
  return tilesLoader.render();
});

// layer_selector
OverlaysFactory.register('layer_selector', function (data, visView, map) {

});

// fullscreen
OverlaysFactory.register('fullscreen', function (data, visView, map) {
  var options = _.extend(data, {
    doc: visView.$el.find('> div').get(0),
    allowWheelOnFullscreen: false,
    mapView: visView.mapView
  });

  if (data.template) {
    options.template = Template.compile(
      data.template,
      data.templateType || 'mustache'
    );
  }

  var fullscreen = new FullScreen(options);
  return fullscreen.render();
});

// share content
OverlaysFactory.register('share', function (data, visView, map) {});

// search content
OverlaysFactory.register('search', function (data, visView, map) {
  var opts = _.extend(data, {
    mapView: visView.mapView,
    model: map
  });

  if (data.template) {
    opts.template = Template.compile(data.template, data.templateType || 'mustache');
  }
  var search = new Search(opts);
  return search.render();
});

OverlaysFactory.register('custom', function (data, visView, map) {
  var customOverlayView = data;
  return customOverlayView.render();
});

module.exports = OverlaysFactory;

<commit_msg>log.error -> log.log<commit_after>var _ = require('underscore');
var Model = require('../core/model');
var Template = require('../core/template');
var Annotation = require('../geo/ui/annotation');
var Search = require('../geo/ui/search/search');
var Text = require('../geo/ui/text');
var TilesLoader = require('../geo/ui/tiles-loader');
var Zoom = require('../geo/ui/zoom/zoom-view');
var FullScreen = require('../ui/common/fullscreen/fullscreen-view');
var AttributionView = require('../geo/ui/attribution/attribution-view');
var LogoView = require('../geo/ui/logo-view');
var log = require('cdb.log');

/**
 * defines the container for an overlay.
 * It places the overlay
 */
var OverlaysFactory = {

  _types: {},

  // register a type to be created
  register: function (type, creatorFn) {
    OverlaysFactory._types[type] = creatorFn;
  },

  // create a type given the data
  // raise an exception if the type does not exist
  create: function (type, data, deps) {
    deps = deps || {};
    if (!deps.visView) throw new Error('visView is required');
    if (!deps.map) throw new Error('map is required');
    var visView = deps.visView;
    var map = deps.map;

    var t = OverlaysFactory._types[type];

    if (!t) {
      log.log("Overlays of type '" + type + "' are not supported anymore");
      return;
    }

    data.options = typeof data.options === 'string' ? JSON.parse(data.options) : data.options;
    data.options = data.options || {};
    var widget = t(data, visView, map);

    if (widget) {
      widget.type = type;
      return widget;
    }

    return false;
  }
};

OverlaysFactory.register('logo', function (data, visView, map) {
  var overlay = new LogoView();
  return overlay.render();
});

OverlaysFactory.register('attribution', function (data, visView, map) {
  var overlay = new AttributionView({
    map: map
  });

  return overlay.render();
});

OverlaysFactory.register('text', function (data, visView, map) {
  var options = data.options;

  var template = Template.compile(
    data.template || [
      '
',
      '
{{{ text }}}
',
      '
'
    ].join('\n'),
    data.templateType || 'mustache'
  );

  var widget = new Text({
    model: new Model(options),
    template: template,
    className: 'cartodb-overlay overlay-text ' + options.device
  });

  return widget.render();
});

OverlaysFactory.register('annotation', function (data, visView, map) {
  var options = data.options;

  var template = Template.compile(
    data.template || [
      '
',
      '
{{{ text }}}
',
      '

',
      '
'
    ].join('\n'),
    data.templateType || 'mustache'
  );

  var widget = new Annotation({
    className: 'cartodb-overlay overlay-annotation ' + options.device,
    template: template,
    mapView: visView.mapView,
    device: options.device,
    text: options.extra.rendered_text,
    minZoom: options.style['min-zoom'],
    maxZoom: options.style['max-zoom'],
    latlng: options.extra.latlng,
    style: options.style
  });

  return widget.render();
});

// map zoom control
OverlaysFactory.register('zoom', function (data, visView, map) {
  var opts = {
    model: map
  };

  var zoom = new Zoom(opts);
  return zoom.render();
});

// Tiles loader
OverlaysFactory.register('loader', function (data) {
  var tilesLoader = new TilesLoader();
  return tilesLoader.render();
});

// layer_selector
OverlaysFactory.register('layer_selector', function (data, visView, map) {

});

// fullscreen
OverlaysFactory.register('fullscreen', function (data, visView, map) {
  var options = _.extend(data, {
    doc: visView.$el.find('> div').get(0),
    allowWheelOnFullscreen: false,
    mapView: visView.mapView
  });

  if (data.template) {
    options.template = Template.compile(
      data.template,
      data.templateType || 'mustache'
    );
  }

  var fullscreen = new FullScreen(options);
  return fullscreen.render();
});

// share content
OverlaysFactory.register('share', function (data, visView, map) {});

// search content
OverlaysFactory.register('search', function (data, visView, map) {
  var opts = _.extend(data, {
    mapView: visView.mapView,
    model: map
  });

  if (data.template) {
    opts.template = Template.compile(data.template, data.templateType || 'mustache');
  }
  var search = new Search(opts);
  return search.render();
});

OverlaysFactory.register('custom', function (data, visView, map) {
  var customOverlayView = data;
  return customOverlayView.render();
});

module.exports = OverlaysFactory;

<|endoftext|>


<commit_before>/* Copyright 2007 by Oliver Steele.  All rights reserved. */

var gHostPrefix = 'http://styleandshare.com';
var gStaticHostPrefix = 'http://images.styleandshare.com';

if (LzBrowser.getLoadURL().indexOf(':8080') >= 0 || LzBrowser.getLoadURL().indexOf('zardoz.dev') >= 0) {
    gHost = 'zardoz.dev';
    gHostPrefix = 'http://' + gHost;
    gStaticHostPrefix = gHostPrefix;
} else if (LzBrowser.getLoadURL().indexOf('staging.styleandshare.com') >= 0) {
    gHostPrefix = 'http://staging.styleandshare.com';
}

LzLoadQueue.maxOpen = 10000;
//LzLoadQueue.__LZmonitorState = true;

function setTimeout(fn, ms) {
    var obj = {run:fn};
    LzTimer.addTimer(new LzDelegate(obj, 'run'), ms);
    return obj;
}

function clearTimeout(obj) {
    obj.run = function(){};
}

Function.prototype.delay = function(ms) {
    setTimeout(this, arguments.length ? ms : 10);
}

/*
 * Image processing
 */

var Image = {};

Image.removeBackground = function(bitmap) {
    var l = 30;
    var w = bitmap.width - 1;
    var h = bitmap.height - 1;
    for (var x = 0; x < w+l; x += l) {
        x = Math.min(w, x);
        for (var y = 0; y < h+l; y += l) {
            y = Math.min(h, y);
            if (bitmap.getPixel(x, y) == 0xffffff)
                bitmap.floodFill(x, y, 0);
        }
    }
}

LzView.prototype.removeBitmapBackground = function() {
    var mc = this.getMCRef();
    var bitmap = this.bitmap = new flash.display.BitmapData(mc._width, mc._height, true, 0x80FFFFFF);
    bitmap.draw(mc);
    Image.removeBackground(bitmap);
    mc.attachBitmap(bitmap, mc.getNextHighestDepth(), 'always', true);
}

function animateRect(sourceView, targetView) {
    return;
    function getGlobalBounds(view) {
        function get(aname) {
            return view.getAttributeRelative(aname, canvas);
        }
        return {x: get('x'), y: get('y'), width: get('width'), height: get('height')};
    }
    var sourceRect = getGlobalBounds(sourceView);
    var targetRect = getGlobalBounds(targetView);
    var view = new ZoomRect(canvas, sourceRect);
    targetRect.vanish = 1;
    view.animators(targetRect, 500);
}

/*
 * Misc.
 */

var Template = {};

Template.expand = function(text, table) {
    var spans = [];
    for (var i = 0; i < text.length; ) {
        var i0 = text.indexOf('#{', i);
        if (i0 < 0) break;
        var i1 = text.indexOf('}', i0);
        if (i1 < 0) break;
        i0 > i && spans.push(text.slice(i, i0));
        var key = text.slice(i0+2, i1);
        spans.push(table[key]);
        i = i1+1;
    }
    text.length > 0 && spans.push(text.slice(i));
    return spans.join('');
}

Number.prototype.toCardinal = function(max) {
    var cardinals = arguments.callee.cardinals = arguments.callee['cardinals'] || ['no', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
    return this <= (max || Infinity) && cardinals[this] || String(this);
}

String.prototype.toCapitalized = function() {
    return this.slice(0, 1).toUpperCase() + this.slice(1);
}

var Size = function(width, height) {
    this.width = width;
    this.height = height;
}

Size.prototype.maxSizeTo = function(maxWidth, maxHeight) {
    arguments.length < 1 && (maxHeight = maxWidth);
    var width = Math.min(this.width, maxWidth);
    var height = Math.min(this.height, maxHeight);
    var ratio = this.width / this.height;
    if (width / height > ratio)
        width = height * ratio;
    else
        height = width / ratio;
    return new Size(width, height);
}

// requires that start tags are of the form '<a ' (the tagname is
// a space, not another form of whitespace), and that end tags are
// exactly ''.  Doesn't deal with nested links.
String.prototype.colorizeLinks = function() {
    return (this
            .replace('<a ', '<a ')
            .replace('', ''));
}

LzBrowser.makeHTMLCallback = function(fname, arg) {
    return ['asfunction:_root.', fname, ',', arg].join('');
}

/*
 * Dragger
 */

Dragger = {}

Dragger.start = function(view) {
    var state = Dragger.state = {
        view: view,
        start: {x: canvas.getMouse('x'), y: canvas.getMouse('y')},
        last: {x: canvas.getMouse('x'), y: canvas.getMouse('y')},
        resizing: false
    };
    if (view['resizeHandle'] && view.resizeHandle.containsMouse()) {
        state.resizing = true;
        state.ratio = view.width / view.height;
        state.startSize = {width: view.width, height: view.height};
    }
}

Dragger.stop = function() {}

Dragger.handleMouseMove = function(view, x, y) {
    var state = Dragger.state;
    var dx = x - state.last.x;
    var dy = y - state.last.y;
    if (dx == 0 && dy == 0) return;
    if (view != state.view) return;
    if (state.resizing) {
        var width = w = Math.max(40, state.startSize.width + canvas.getMouse('x') - state.start.x);
        var height = h = Math.max(40, state.startSize.height + canvas.getMouse('y') - state.start.y);
        var ratio = width / height;
        if (ratio < state.ratio)
            width = height * state.ratio;
        else
            height = width / state.ratio;
        //info(w, h, ratio, width, height, width/height, state.ratio)
        view.setWidth(width);
        view.setHeight(height);
    } else {
        view.setX(view.x + dx);
        view.setY(view.y + dy);
    }
    state.last = {x: x, y: y};
}

/*
 * AJAX
 */

// AJAX w/ JSON
function ajax(url, onsuccess, onerror) {
    if (url.indexOf('http') < 0) url = gHostPrefix + url;
    var responseHolder = [];
    Debug.write('XHR', url);
    var req = new XMLHttpRequest();
    req.onreadystatechange = handleReadyStateChange;
    req.open("GET", url, true);
    req.send(null);
    if (typeof onsuccess == 'undefined') onsuccess = null;
    if (typeof onerror == 'undefined') onerror = null;
    function handleReadyStateChange(request) {
        if (request.readyState == 4) {
            if (request.status == 200) {
                var result = ajax.lastResult = JSON.parse(request.responseText);
                responseHolder.push(result);
                if (typeof result == 'string') {
                    error(result);
                    return;
                }
                onsuccess && onsuccess(result);
            } else {
                onerror ? onerror(result) : Debug.error(request);
            }
        }
    }
}

// JQuery compatability
function $() {}

$.get = function(url, params, options) {
    $.post(url, params, options);
}

// actually does GET
$.post = function(url, params, options) {
    if (url.indexOf('http') < 0) url = gHostPrefix + url;
    var query = Hash.toQueryString(params);
    if (query.length) {
        if (url.indexOf('?') < 0) url += '?';
        url += query;
    }
    var onsuccess = options = options || {};
    if (typeof options == 'function')
        options = {};
    else
        onsuccess = options['onsuccess'];
    ajax(url, onsuccess, options['onerror']);
}

/*
 * JS Bridge
 */

var FlashBridge = function() {
    this.callbacks = {};
    this.nextId = 0;
//     flash.external.ExternalInterface.addCallback("info", null, function(){
//         info.apply(null, arguments);
//     });
    if (typeof flash == 'undefined') return;
    flash.external.ExternalInterface.addCallback("handleCallback",
                                                 this, this.handleCallback);
    this.register('info', function() {info.apply(null,  arguments)});
}

FlashBridge.prototype.register = function(name, fn) {
    flash.external.ExternalInterface.addCallback(name, null, fn);
}

FlashBridge.prototype.call = function(fn) {
    var args = [];
    for (var i = 1; i < arguments.length; i++)
        args.push(arguments[i]);
    var callback = null;
    var callbackId = 0;
    if (callback) {
        callbackId = ++this.nextId;
        this.callbacks[id] = callback;
    }
    var expr = ['FlashBridge.handle("', fn, '",', JSON.stringify(args), ')'].join('');
    info(expr);
    LzBrowser.loadJS(expr);
}

FlashBridge.prototype.handleCallback = function(callbackId, result) {
    var handler = this.callbacks[callbackId];
    delete this.callbacks[callbackId];
    handler && handler(result)
}

FlashBridge = new FlashBridge();
<commit_msg>add getBitmapString<commit_after>/* Copyright 2007 by Oliver Steele.  All rights reserved. */

var gHostPrefix = 'http://styleandshare.com';
var gStaticHostPrefix = 'http://images.styleandshare.com';

if (LzBrowser.getLoadURL().indexOf(':8080') >= 0 || LzBrowser.getLoadURL().indexOf('zardoz.dev') >= 0) {
    gHost = 'zardoz.dev';
    gHostPrefix = 'http://' + gHost;
    gStaticHostPrefix = gHostPrefix;
} else if (LzBrowser.getLoadURL().indexOf('staging.styleandshare.com') >= 0) {
    gHostPrefix = 'http://staging.styleandshare.com';
}

LzLoadQueue.maxOpen = 10000;
//LzLoadQueue.__LZmonitorState = true;

function setTimeout(fn, ms) {
    var obj = {run:fn};
    LzTimer.addTimer(new LzDelegate(obj, 'run'), ms);
    return obj;
}

function clearTimeout(obj) {
    obj.run = function(){};
}

Function.prototype.delay = function(ms) {
    setTimeout(this, arguments.length ? ms : 10);
}

/*
 * Image processing
 */

var Image = {};

Image.removeBackground = function(bitmap) {
    var l = 30;
    var w = bitmap.width - 1;
    var h = bitmap.height - 1;
    for (var x = 0; x < w+l; x += l) {
        x = Math.min(w, x);
        for (var y = 0; y < h+l; y += l) {
            y = Math.min(h, y);
            if (bitmap.getPixel(x, y) == 0xffffff)
                bitmap.floodFill(x, y, 0);
        }
    }
}

LzView.prototype.removeBitmapBackground = function() {
    var mc = this.getMCRef();
    var bitmap = this.bitmap = new flash.display.BitmapData(mc._width, mc._height, true, 0x80FFFFFF);
    bitmap.draw(mc);
    Image.removeBackground(bitmap);
    mc.attachBitmap(bitmap, mc.getNextHighestDepth(), 'always', true);
}

// Gallery.galleries.MINE.pages[0].view.image.getBitmapString().length
LzView.prototype.getBitmapString = function() {
    var mc = this.getMCRef();
    var bitmap = this.bitmap = new flash.display.BitmapData(mc._width, mc._height, true, 0x80FFFFFF);
    bitmap.draw(mc);
    var s = new Array(2*bitmap.width*bitmap.height);
    info(s, s.length);
    var last = null, repeat, uniques = [];
    for (var y = 0, i = 0; y < bitmap.height; y++)
        for (var x = 0; x < bitmap.width; x++) {
            var color = bitmap.getPixel32(x, y);
            if (color == last) {
                ++repeat;
            } else if (last == null) {
                last = color;
                repeat = 1;
            } else {
                var hi = (color >> 16) & 0xffff, lo = color & 0xffff;
                s[i++] = (hi).toString(16);
                s[i++] = (lo).toString(16);
            }
        }
    s.length = i;
    return s.join('');
}

function animateRect(sourceView, targetView) {
    return;
    function getGlobalBounds(view) {
        function get(aname) {
            return view.getAttributeRelative(aname, canvas);
        }
        return {x: get('x'), y: get('y'), width: get('width'), height: get('height')};
    }
    var sourceRect = getGlobalBounds(sourceView);
    var targetRect = getGlobalBounds(targetView);
    var view = new ZoomRect(canvas, sourceRect);
    targetRect.vanish = 1;
    view.animators(targetRect, 500);
}

/*
 * Misc.
 */

var Template = {};

Template.expand = function(text, table) {
    var spans = [];
    for (var i = 0; i < text.length; ) {
        var i0 = text.indexOf('#{', i);
        if (i0 < 0) break;
        var i1 = text.indexOf('}', i0);
        if (i1 < 0) break;
        i0 > i && spans.push(text.slice(i, i0));
        var key = text.slice(i0+2, i1);
        spans.push(table[key]);
        i = i1+1;
    }
    text.length > 0 && spans.push(text.slice(i));
    return spans.join('');
}

Number.prototype.toCardinal = function(max) {
    var cardinals = arguments.callee.cardinals = arguments.callee['cardinals'] || ['no', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
    return this <= (max || Infinity) && cardinals[this] || String(this);
}

String.prototype.toCapitalized = function() {
    return this.slice(0, 1).toUpperCase() + this.slice(1);
}

var Size = function(width, height) {
    this.width = width;
    this.height = height;
}

Size.prototype.maxSizeTo = function(maxWidth, maxHeight) {
    arguments.length < 1 && (maxHeight = maxWidth);
    var width = Math.min(this.width, maxWidth);
    var height = Math.min(this.height, maxHeight);
    var ratio = this.width / this.height;
    if (width / height > ratio)
        width = height * ratio;
    else
        height = width / ratio;
    return new Size(width, height);
}

// requires that start tags are of the form '<a ' (the tagname is
// a space, not another form of whitespace), and that end tags are
// exactly ''.  Doesn't deal with nested links.
String.prototype.colorizeLinks = function() {
    return (this
            .replace('<a ', '<a ')
            .replace('', ''));
}

LzBrowser.makeHTMLCallback = function(fname, arg) {
    return ['asfunction:_root.', fname, ',', arg].join('');
}

/*
 * Dragger
 */

Dragger = {}

Dragger.start = function(view) {
    var state = Dragger.state = {
        view: view,
        start: {x: canvas.getMouse('x'), y: canvas.getMouse('y')},
        last: {x: canvas.getMouse('x'), y: canvas.getMouse('y')},
        resizing: false
    };
    if (view['resizeHandle'] && view.resizeHandle.containsMouse()) {
        state.resizing = true;
        state.ratio = view.width / view.height;
        state.startSize = {width: view.width, height: view.height};
    }
}

Dragger.stop = function() {}

Dragger.handleMouseMove = function(view, x, y) {
    var state = Dragger.state;
    var dx = x - state.last.x;
    var dy = y - state.last.y;
    if (dx == 0 && dy == 0) return;
    if (view != state.view) return;
    if (state.resizing) {
        var width = w = Math.max(40, state.startSize.width + canvas.getMouse('x') - state.start.x);
        var height = h = Math.max(40, state.startSize.height + canvas.getMouse('y') - state.start.y);
        var ratio = width / height;
        if (ratio < state.ratio)
            width = height * state.ratio;
        else
            height = width / state.ratio;
        //info(w, h, ratio, width, height, width/height, state.ratio)
        view.setWidth(width);
        view.setHeight(height);
    } else {
        view.setX(view.x + dx);
        view.setY(view.y + dy);
    }
    state.last = {x: x, y: y};
}

/*
 * AJAX
 */

// AJAX w/ JSON
function ajax(url, onsuccess, onerror) {
    if (url.indexOf('http') < 0) url = gHostPrefix + url;
    var responseHolder = [];
    Debug.write('XHR', url);
    var req = new XMLHttpRequest();
    req.onreadystatechange = handleReadyStateChange;
    req.open("GET", url, true);
    req.send(null);
    if (typeof onsuccess == 'undefined') onsuccess = null;
    if (typeof onerror == 'undefined') onerror = null;
    function handleReadyStateChange(request) {
        if (request.readyState == 4) {
            if (request.status == 200) {
                var result = ajax.lastResult = JSON.parse(request.responseText);
                responseHolder.push(result);
                if (typeof result == 'string') {
                    error(result);
                    return;
                }
                onsuccess && onsuccess(result);
            } else {
                onerror ? onerror(result) : Debug.error(request);
            }
        }
    }
}

// JQuery compatability
function $() {}

$.get = function(url, params, options) {
    $.post(url, params, options);
}

// actually does GET
$.post = function(url, params, options) {
    if (url.indexOf('http') < 0) url = gHostPrefix + url;
    var query = Hash.toQueryString(params);
    if (query.length) {
        if (url.indexOf('?') < 0) url += '?';
        url += query;
    }
    var onsuccess = options = options || {};
    if (typeof options == 'function')
        options = {};
    else
        onsuccess = options['onsuccess'];
    ajax(url, onsuccess, options['onerror']);
}

/*
 * JS Bridge
 */

var FlashBridge = function() {
    this.callbacks = {};
    this.nextId = 0;
//     flash.external.ExternalInterface.addCallback("info", null, function(){
//         info.apply(null, arguments);
//     });
    if (typeof flash == 'undefined') return;
    flash.external.ExternalInterface.addCallback("handleCallback",
                                                 this, this.handleCallback);
    this.register('info', function() {info.apply(null,  arguments)});
}

FlashBridge.prototype.register = function(name, fn) {
    flash.external.ExternalInterface.addCallback(name, null, fn);
}

FlashBridge.prototype.call = function(fn) {
    var args = [];
    for (var i = 1; i < arguments.length; i++)
        args.push(arguments[i]);
    var callback = null;
    var callbackId = 0;
    if (callback) {
        callbackId = ++this.nextId;
        this.callbacks[id] = callback;
    }
    var expr = ['FlashBridge.handle("', fn, '",', JSON.stringify(args), ')'].join('');
    info(expr);
    LzBrowser.loadJS(expr);
}

FlashBridge.prototype.handleCallback = function(callbackId, result) {
    var handler = this.callbacks[callbackId];
    delete this.callbacks[callbackId];
    handler && handler(result)
}

FlashBridge = new FlashBridge();
<|endoftext|>