<commit_before>/*
 * Copyright (c) 2013, Yahoo! Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jslint browser: true, nomen: true, plusplus: true */
/*global YUI */

YUI.add('mojito-debug-addon', function (Y, NAME) {
    'use strict';

    var NOOP = function () {},
        isBrowser = typeof window === 'object';

    function DebugAddon(command, adapter, ac) {
        var self = this,
            root = isBrowser ? window.top : adapter.req,
            debugParam;

        // Ensure debugger is a singleton per request.
        if (!root.globals) {
            root.globals = {};
        }
        if (!root.globals[NAME]) {
            root.globals[NAME] = self;
        } else {
            return root.globals[NAME];
        }

        self.ac = ac;
        self.mode = ac.params.params.url.hasOwnProperty('debug') ? '' :
                    ac.params.params.url.hasOwnProperty('debug.hide') ? 'hide' :
                        ac.params.params.url.hasOwnProperty('debug.json') ? 'json' : null;
        self.timing = {
            client: {},
            server: {}
        };

        // Do nothing if the debug parameter is not present.
        if (self.mode === null) {
            return;
        }

        if (!isBrowser) {
            if (!command.instance.config.hooks) {
                return;
            }

            self.hooks = {};

            // Get config, make sure the help hook appears first.
            self.config = {
                hooks: {
                    help: command.instance.config.hooks.help
                }
            };
            Y.mix(self.config, command.instance.config, false, null, 0, true);

            // Add configuration hooks into 'all' alias.
            Y.Object.each(self.config.hooks, function (hookConfig, hook) {
                self._initHookConfig(hook);
                if (self.config.aliases.all.indexOf(hook) === -1) {
                    self.config.aliases.all.push(hook);
                }
            });

            // Determine all the active hooks specified in the debug parameter.
            // If no hook specified, use 'all' by default.
            debugParam = ac.params.url('debug' + (self.mode ? '.' + self.mode : '')) || 'all';
            self.urlHooks = debugParam.split(/\s*,\s*/);
            Y.Array.each(self.urlHooks, function (hook) {
                if (!hook) {
                    return;
                }

                if (hook === 'all') {
                    self.allHooksEnabled = true;
                } else if (self.config.aliases.all.indexOf(hook) === -1) {
                    self.config.aliases.all.push(hook);
                }

                Y.Array.each(self.config.aliases[hook] || [hook], function (hook) {
                    self._initHook(hook);
                });
            });
        }

        self.enabled = true;

        self.on = self._on;
        self.once = self._once;
        self.log = self._log;
        self.setContent = self._setContent;
        self.appendContent = self._appendContent;
        self.error = self._error;
        self.clear = self._clear;
        self.get = self._get;
    }

    DebugAddon.prototype = {
        namespace: 'debug',

        on: NOOP,

        log: NOOP,

        setContent: NOOP,

        appendContent: NOOP,

        get: NOOP,

        render: NOOP,

        _on: function (type, callback, once) {
            var parts = type.split(':'),
                hook = parts[0],
                event = parts[1],
                errorMessage = 'Error in a callback passed to ac.debug.on',
                originalCallback = callback;

            if (!event && !this.hooks[hook]) {
                if (this.allHooksEnabled) {
                    this.config.aliases.all.push(hook);
                    this._initHook(hook);
                } else {
                    return;
                }
            }

            // Wrap the callback with a try-catch in order to report any errors
            // occurring after calling callback.
            callback = function () {
                try {
                    originalCallback.apply(this, arguments);
                } catch (e) {
                    if (this.hooks[hook]) {
                        this.error(hook, {
                            message: errorMessage,
                            exception: e
                        }, 'error');
                    } else {
                        Y.log(errorMessage + '(' + type + ')', NAME);
                    }
                }
            }.bind(this);

            if (event) {
                return Y[once ? 'once' : 'on'](hook + ':' + event, callback);
            }

            this.hooks[hook]._modified = true;

            callback(this.hooks[hook].debugData, this.hooks[hook]);
        },

        _once: function (type, callback) {
            return this.on(type, callback, true);
        },

        _log: function (line, options) {
            var hook = 'log';
            this.on(hook, function (debugData) {
                if (Y.Lang.isObject(line) && Y.Lang.isObject(options)) {
                    line = {
                        json: line,
                        options: options
                    };
                } else if (Y.Lang.isString(line) && Y.Lang.isString(options)) {
                    line = '' + line + '';
                }
                debugData._append.push(line);
                this.render(hook);
            }.bind(this));

        },

        _setContent: function (hook, content) {
            this.on(hook, function (debugData) {
                debugData._content = content;
                this.render(hook);
            }.bind(this));
        },

        _appendContent: function (hook, content) {
            this.on(hook, function (debugData) {
                debugData._append.push(content);
                this.render(hook);
            }.bind(this));
        },

        _error: function (hook, error, type, name) {
            this.on(hook, function (debugData) {
                var message = error,
                    exception,
                    exceptionMessage,
                    stack,
                    colon;

                if (Y.Lang.isObject(error)) {
                    if (error.exception) {
                        message = error.message;
                        exception = error.exception;
                    } else {
                        message = '';
                        exception = error;
                    }
                    exceptionMessage = exception.message || '';
                    stack = exception.stack || '';
                    colon = (message && exceptionMessage) ? ': ' : '';

                    Y.log(message + colon + exceptionMessage + '\n' + stack, 'error', name || NAME);
                    exceptionMessage = '' + exceptionMessage + '';

                    message = (message + colon + exceptionMessage);
                } else {
                    Y.log(error, 'error', name || NAME);
                }

                debugData._errors.push('
' + (message || type || 'erorr') + '
');
                this.render(hook);
            }.bind(this));
        },

        _clear: function (hookName, whitelist) {
            var hook = this.hooks[hookName],
                debugData = hook && hook.debugData;
            if (hook) {
                hook.debugData = {
                    _errors: debugData._errors,
                    _append: debugData._append,
                    _content: debugData._content
                };

                if (whitelist) {
                    Y.mix(hook.debugData, debugData, false, whitelist);
                }
            }
        },

        _get: function (hook) {
            return this.hooks[hook];
        },

        _render: function (hooks, done) {
            var self = this,
                ac = self.ac,
                hooksToRender = {},
                numHooksToRender = 0,
                mergedMeta = {};

            if (typeof hooks === 'function') {
                done = hooks;
                hooks = null;
            }

            if (hooks) {
                hooks = typeof hooks === 'string' ? [hooks] : hooks;
                // Mark hooks that were specifically specified as modified to make sure they are rendered.
                Y.Array.each(hooks, function (hook) {
                    self.hooks[hook]._modified = true;
                });
            } else {
                hooks = Y.Object.keys(self.hooks);
            }

            Y.Array.each(hooks, function (hookName) {
                var hook = self.hooks[hookName],
                    prepareToRender;
                if (!hook || !hook._modified) {
                    return;
                }

                prepareToRender = function () {
                    hook._modified = false;

                    if (hook.debugData._errors.length > 0) {
                        // Do not attempt to render this hook if it has errors,
                        // otherwise the rendering may result in more errors,
                        // resulting in an infinite loop.
                        hook._rendered = true;
                    } else if (hook.binder && hook.binder.render) {
                        // The hook has a binder with a render function,
                        // which is used to render this hook.
                        hook.binder.render(hook.node, hook.debugData);
                        hook._rendered = true;
                    } else if (hook.config && (hook.config.base || hook.config.type)) {
                        // Render this hook if it's config specifies a base or a type.
                        numHooksToRender++;
                        // It's important to clone the config instead of using it directly,
                        // because it should not be modified; otherwise there can be interference,
                        // and the added params will be sent to the client.
                        hooksToRender[hookName] = Y.clone(hook.config);
                        hooksToRender[hookName].params = hook.params || {};
                        hooksToRender[hookName].params.body = (hook.params && hook.params.body) || {};
                        hooksToRender[hookName].params.body.debugData = hook.debugData;
                        hooksToRender[hookName].params.body.hook = hookName;
                    } else {
                        // This is a simple hook that will rendered according to _content/_append in debugData.
                        hook._rendered = true;
                    }
                };

                // Fire the event hook:render, any subscribers
                Y.publish(hookName + ':render', {
                    emitFacade: true,
                    defaultFn : prepareToRender
                });
                Y.fire(hookName + ':render', {
                    hook: hook,
                    debugData: hook.debugData
                });
            });

            if (Y.Object.isEmpty(hooksToRender)) {
                return done && done(Y.mix(self.hooks, self.hooks, true, hooks), mergedMeta);
            }

            Y.Object.each(hooksToRender, function (hook, hookName) {
                var command = {
                        instance: hook,
                        action: hook.action || 'index',
                        context: ac.context,
                        params: hook.params
                    },
                    adapter = new Y.mojito.debug.OutputHandler(hookName + '-hook', function (err, data, meta) {
                        var hook = self.hooks[hookName];

                        if (err) {
                            self.error(hookName, 'Rendering failed on ' + (isBrowser ? 'client' : 'server') + '-side: ' + err, 'error');
                        } else {
                            mergedMeta = Y.mojito.util.metaMerge(mergedMeta, meta);

                            hook.debugData._content = data;
                            hook._viewId = meta.view.id;
                        }

                        hook._rendered = true;

                        if (--numHooksToRender === 0) {
                            return done && done(Y.mix(self.hooks, self.hooks, true, hooks), mergedMeta);
                        }
                    }, self.MojitoClient);

                Y.mix(adapter, ac._adapter);

                ac._dispatch(command, adapter);
            });
        },

        _initHook: function (hook) {
            var self = this;
            if (self.hooks[hook]) {
                return;
            }
            // Make sure the config includes all hooks mentioned in the debug param.
            self.config.hooks[hook] = self.config.hooks[hook] || {};

            self.hooks[hook] = {
                _modified: true,
                _rendered: false,
                config: self.config.hooks[hook],
                debugData: {
                    _errors: [],
                    _content: null,
                    _append: []
                }
            };

            self._initHookConfig(hook);
        },

        _initHookConfig: function (hook) {
            // Make sure each hook has a title and description.
            if (!this.config.hooks[hook].title) {
                this.config.hooks[hook].title = hook.substring(0, 1).toUpperCase() + hook.substring(1);
            }
            if (!this.config.hooks[hook].description) {
                this.config.hooks[hook].description = this.config.hooks[hook].title + '.';
            }
        }/*,

        _decycleHooks: function (hooks) {
            var self = this,
                decycledHooks = {},
                JSON_DEPTH_LIMIT = 7;
            Y.Object.each(hooks, function (hook, hookName) {
                decycledHooks[hookName] = Y.mojito.debug.Utils.decycle(hook);
                return;
                // TODO: revisit converting the json into an object that references itself.
                try {
                    JSON.stringify(hook);
                    // we know it has no cycles so just copy the object while stringifing functions, no depth limit.
                    serializedHooks[hookName] = Y.mojito.debug.Utils.transformObject(hook, 0, true, true, true);
                } catch (e) {
                    self.error(hookName, 'Unable to serialize debugData: "' + e.message
                        + '". debugData has been decycled and limited to a depth of ' + (JSON_DEPTH_LIMIT - 1) + '.', 'warning');
                    serializedHooks[hookName] = Y.mojito.debug.Utils.removeCycles(hook, JSON_DEPTH_LIMIT);
                }
            });

            return decycledHooks;
        },

        _retrocycleHooks: function (hooks) {
            Y.Object.each(hooks)
        }*/
    };

    Y.namespace('mojito.addons.ac').debug = DebugAddon;

    if (isBrowser) {
        if (window.top.DEBUGGER) {
            Y.Debug = window.top.DEBUGGER;
        } else {
            Y.Debug = {};
            Y.mix(Y.Debug, DebugAddon.prototype);
        }
    }
}, '0.0.1', {
    requires: [
        'event-custom',
        'mojito-composite-addon',
        'mojito-params-addon',
        'mojito-debug-output-handler',
        'mojito-util'
    ]
});
<commit_msg>Escaping any html when loging errors on the client side, logging exception stack after a rendering exception.<commit_after>/*
 * Copyright (c) 2013, Yahoo! Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jslint browser: true, nomen: true, plusplus: true */
/*global YUI */

YUI.add('mojito-debug-addon', function (Y, NAME) {
    'use strict';

    var NOOP = function () {},
        isBrowser = typeof window === 'object';

    function DebugAddon(command, adapter, ac) {
        var self = this,
            root = isBrowser ? window.top : adapter.req,
            debugParam;

        // Ensure debugger is a singleton per request.
        if (!root.globals) {
            root.globals = {};
        }
        if (!root.globals[NAME]) {
            root.globals[NAME] = self;
        } else {
            return root.globals[NAME];
        }

        self.ac = ac;
        self.mode = ac.params.params.url.hasOwnProperty('debug') ? '' :
                    ac.params.params.url.hasOwnProperty('debug.hide') ? 'hide' :
                        ac.params.params.url.hasOwnProperty('debug.json') ? 'json' : null;
        self.timing = {
            client: {},
            server: {}
        };

        // Do nothing if the debug parameter is not present.
        if (self.mode === null) {
            return;
        }

        if (!isBrowser) {
            if (!command.instance.config.hooks) {
                return;
            }

            self.hooks = {};

            // Get config, make sure the help hook appears first.
            self.config = {
                hooks: {
                    help: command.instance.config.hooks.help
                }
            };
            Y.mix(self.config, command.instance.config, false, null, 0, true);

            // Add configuration hooks into 'all' alias.
            Y.Object.each(self.config.hooks, function (hookConfig, hook) {
                self._initHookConfig(hook);
                if (self.config.aliases.all.indexOf(hook) === -1) {
                    self.config.aliases.all.push(hook);
                }
            });

            // Determine all the active hooks specified in the debug parameter.
            // If no hook specified, use 'all' by default.
            debugParam = ac.params.url('debug' + (self.mode ? '.' + self.mode : '')) || 'all';
            self.urlHooks = debugParam.split(/\s*,\s*/);
            Y.Array.each(self.urlHooks, function (hook) {
                if (!hook) {
                    return;
                }

                if (hook === 'all') {
                    self.allHooksEnabled = true;
                } else if (self.config.aliases.all.indexOf(hook) === -1) {
                    self.config.aliases.all.push(hook);
                }

                Y.Array.each(self.config.aliases[hook] || [hook], function (hook) {
                    self._initHook(hook);
                });
            });
        }

        self.enabled = true;

        self.on = self._on;
        self.once = self._once;
        self.log = self._log;
        self.setContent = self._setContent;
        self.appendContent = self._appendContent;
        self.error = self._error;
        self.clear = self._clear;
        self.get = self._get;
    }

    DebugAddon.prototype = {
        namespace: 'debug',

        on: NOOP,

        log: NOOP,

        setContent: NOOP,

        appendContent: NOOP,

        get: NOOP,

        render: NOOP,

        _on: function (type, callback, once) {
            var parts = type.split(':'),
                hook = parts[0],
                event = parts[1],
                errorMessage = 'Error in a callback passed to ac.debug.on',
                originalCallback = callback;

            if (!event && !this.hooks[hook]) {
                if (this.allHooksEnabled) {
                    this.config.aliases.all.push(hook);
                    this._initHook(hook);
                } else {
                    return;
                }
            }

            // Wrap the callback with a try-catch in order to report any errors
            // occurring after calling callback.
            callback = function () {
                try {
                    originalCallback.apply(this, arguments);
                } catch (e) {
                    if (this.hooks[hook]) {
                        this.error(hook, {
                            message: errorMessage,
                            exception: e
                        }, 'error');
                    } else {
                        Y.log(errorMessage + '(' + type + ')', NAME);
                    }
                }
            }.bind(this);

            if (event) {
                return Y[once ? 'once' : 'on'](hook + ':' + event, callback);
            }

            this.hooks[hook]._modified = true;

            callback(this.hooks[hook].debugData, this.hooks[hook]);
        },

        _once: function (type, callback) {
            return this.on(type, callback, true);
        },

        _log: function (line, options) {
            var hook = 'log';
            this.on(hook, function (debugData) {
                if (Y.Lang.isObject(line) && Y.Lang.isObject(options)) {
                    line = {
                        json: line,
                        options: options
                    };
                } else if (Y.Lang.isString(line) && Y.Lang.isString(options)) {
                    line = '' + line + '';
                }
                debugData._append.push(line);
                this.render(hook);
            }.bind(this));

        },

        _setContent: function (hook, content) {
            this.on(hook, function (debugData) {
                debugData._content = content;
                this.render(hook);
            }.bind(this));
        },

        _appendContent: function (hook, content) {
            this.on(hook, function (debugData) {
                debugData._append.push(content);
                this.render(hook);
            }.bind(this));
        },

        _error: function (hook, error, type, name) {
            this.on(hook, function (debugData) {
                var message = error,
                    exception,
                    exceptionMessage,
                    stack,
                    colon,
                    escapeHTML = function (html) {
                        return html.replace(/[&<>]/gm, function (tag) {
                            switch (tag) {
                            case '<':
                                return '<';
                            case '>':
                                return '>';
                            case '&':
                                return '&';
                            default:
                                return tag;
                            }
                        });
                    };

                if (Y.Lang.isObject(error)) {
                    if (error.exception) {
                        message = error.message;
                        exception = error.exception;
                    } else {
                        message = '';
                        exception = error;
                    }
                    exceptionMessage = exception.message || '';
                    stack = exception.stack || '';
                    colon = (message && exceptionMessage) ? ': ' : '';

                    Y.log(message + colon + exceptionMessage + '\n' + stack, 'error', name || NAME);
                    exceptionMessage = '' + escapeHTML(exceptionMessage) + '';

                    message = (escapeHTML(message) + colon + exceptionMessage);
                } else {
                    Y.log(error, 'error', name || NAME);
                    message = escapeHTML(message);
                }

                debugData._errors.push('
' + (message || type || 'erorr') + '
');
                this.render(hook);
            }.bind(this));
        },

        _clear: function (hookName, whitelist) {
            var hook = this.hooks[hookName],
                debugData = hook && hook.debugData;
            if (hook) {
                hook.debugData = {
                    _errors: debugData._errors,
                    _append: debugData._append,
                    _content: debugData._content
                };

                if (whitelist) {
                    Y.mix(hook.debugData, debugData, false, whitelist);
                }
            }
        },

        _get: function (hook) {
            return this.hooks[hook];
        },

        _render: function (hooks, done) {
            var self = this,
                ac = self.ac,
                hooksToRender = {},
                numHooksToRender = 0,
                mergedMeta = {};

            if (typeof hooks === 'function') {
                done = hooks;
                hooks = null;
            }

            if (hooks) {
                hooks = typeof hooks === 'string' ? [hooks] : hooks;
                // Mark hooks that were specifically specified as modified to make sure they are rendered.
                Y.Array.each(hooks, function (hook) {
                    self.hooks[hook]._modified = true;
                });
            } else {
                hooks = Y.Object.keys(self.hooks);
            }

            Y.Array.each(hooks, function (hookName) {
                var hook = self.hooks[hookName],
                    prepareToRender;
                if (!hook || !hook._modified) {
                    return;
                }

                prepareToRender = function () {
                    hook._modified = false;

                    if (hook.debugData._errors.length > 0) {
                        // Do not attempt to render this hook if it has errors,
                        // otherwise the rendering may result in more errors,
                        // resulting in an infinite loop.
                        hook._rendered = true;
                    } else if (hook.binder && hook.binder.render) {
                        // The hook has a binder with a render function,
                        // which is used to render this hook.
                        hook.binder.render(hook.node, hook.debugData);
                        hook._rendered = true;
                    } else if (hook.config && (hook.config.base || hook.config.type)) {
                        // Render this hook if it's config specifies a base or a type.
                        numHooksToRender++;
                        // It's important to clone the config instead of using it directly,
                        // because it should not be modified; otherwise there can be interference,
                        // and the added params will be sent to the client.
                        hooksToRender[hookName] = Y.clone(hook.config);
                        hooksToRender[hookName].params = hook.params || {};
                        hooksToRender[hookName].params.body = (hook.params && hook.params.body) || {};
                        hooksToRender[hookName].params.body.debugData = hook.debugData;
                        hooksToRender[hookName].params.body.hook = hookName;
                    } else {
                        // This is a simple hook that will rendered according to _content/_append in debugData.
                        hook._rendered = true;
                    }
                };

                // Fire the event hook:render, any subscribers
                Y.publish(hookName + ':render', {
                    emitFacade: true,
                    defaultFn : prepareToRender
                });
                Y.fire(hookName + ':render', {
                    hook: hook,
                    debugData: hook.debugData
                });
            });

            if (Y.Object.isEmpty(hooksToRender)) {
                return done && done(Y.mix(self.hooks, self.hooks, true, hooks), mergedMeta);
            }

            Y.Object.each(hooksToRender, function (hook, hookName) {
                var command = {
                        instance: hook,
                        action: hook.action || 'index',
                        context: ac.context,
                        params: hook.params
                    },
                    adapter = new Y.mojito.debug.OutputHandler(hookName + '-hook', function (err, data, meta) {
                        var hook = self.hooks[hookName];

                        if (err) {
                            self.error(hookName, {
                                message: 'Rendering failed on ' + (isBrowser ? 'client' : 'server') + '-side',
                                exception: err
                            }, 'error');
                        } else {
                            mergedMeta = Y.mojito.util.metaMerge(mergedMeta, meta);

                            hook.debugData._content = data;
                            hook._viewId = meta.view.id;
                        }

                        hook._rendered = true;

                        if (--numHooksToRender === 0) {
                            return done && done(Y.mix(self.hooks, self.hooks, true, hooks), mergedMeta);
                        }
                    }, self.MojitoClient);

                Y.mix(adapter, ac._adapter);

                ac._dispatch(command, adapter);
            });
        },

        _initHook: function (hook) {
            var self = this;
            if (self.hooks[hook]) {
                return;
            }
            // Make sure the config includes all hooks mentioned in the debug param.
            self.config.hooks[hook] = self.config.hooks[hook] || {};

            self.hooks[hook] = {
                _modified: true,
                _rendered: false,
                config: self.config.hooks[hook],
                debugData: {
                    _errors: [],
                    _content: null,
                    _append: []
                }
            };

            self._initHookConfig(hook);
        },

        _initHookConfig: function (hook) {
            // Make sure each hook has a title and description.
            if (!this.config.hooks[hook].title) {
                this.config.hooks[hook].title = hook.substring(0, 1).toUpperCase() + hook.substring(1);
            }
            if (!this.config.hooks[hook].description) {
                this.config.hooks[hook].description = this.config.hooks[hook].title + '.';
            }
        }
    };

    Y.namespace('mojito.addons.ac').debug = DebugAddon;

    if (isBrowser) {
        if (window.top.DEBUGGER) {
            Y.Debug = window.top.DEBUGGER;
        } else {
            Y.Debug = {};
            Y.mix(Y.Debug, DebugAddon.prototype);
        }
    }
}, '0.0.1', {
    requires: [
        'event-custom',
        'mojito-composite-addon',
        'mojito-params-addon',
        'mojito-debug-output-handler',
        'mojito-util'
    ]
});
<|endoftext|>


<commit_before>yimport { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { click, currentURL, visit } from '@ember/test-helpers';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import axeConfig from '../axe-config';
import setupMirage from '../helpers/setup-mirage';
import { percySnapshot } from 'ember-percy';

module('Acceptance | crates page', function(hooks) {
    setupApplicationTest(hooks);
    setupMirage(hooks);

    test('is accessible', async function(assert) {
        assert.expect(0);

        this.server.loadFixtures();

        await visit('/');
        percySnapshot(assert);

        await a11yAudit(axeConfig);
    });

    test('/crates is accessible', async function(assert) {
        assert.expect(0);

        this.server.loadFixtures();

        await visit('/crates');
        percySnapshot(assert);

        await a11yAudit(axeConfig);
    });

    test('visiting the crates page from the front page', async function(assert) {
        this.server.loadFixtures();

        await visit('/');
        await click('[data-test-all-crates-link]');

        assert.equal(currentURL(), '/crates');
        assert.equal(document.title, 'Crates - crates.io: Rust Package Registry');
    });

    test('visiting the crates page directly', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        await click('[data-test-all-crates-link]');

        assert.equal(currentURL(), '/crates');
        assert.equal(document.title, 'Crates - crates.io: Rust Package Registry');
    });

    test('listing crates', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');

        assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('1-10');
        assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19');
    });

    test('navigating to next page of crates', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        await click('[data-test-pagination-next]');

        assert.equal(currentURL(), '/crates?page=2');
        assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('11-19');
        assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19');
    });

    test('crates default sort is alphabetical', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');

        assert.dom('[data-test-crates-sort] [data-test-current-order]').hasText('Alphabetical');
    });

    test('downloads appears for each crate on crate list', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 497');
    });

    test('recent downloads appears for each crate on crate list', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        assert.dom('[data-test-crate-row="0"] [data-test-recent-downloads]').hasText('Recent: 497');
    });
});
<commit_msg>crates-test: Remove a stray 'y'<commit_after>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { click, currentURL, visit } from '@ember/test-helpers';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import axeConfig from '../axe-config';
import setupMirage from '../helpers/setup-mirage';
import { percySnapshot } from 'ember-percy';

module('Acceptance | crates page', function(hooks) {
    setupApplicationTest(hooks);
    setupMirage(hooks);

    test('is accessible', async function(assert) {
        assert.expect(0);

        this.server.loadFixtures();

        await visit('/');
        percySnapshot(assert);

        await a11yAudit(axeConfig);
    });

    test('/crates is accessible', async function(assert) {
        assert.expect(0);

        this.server.loadFixtures();

        await visit('/crates');
        percySnapshot(assert);

        await a11yAudit(axeConfig);
    });

    test('visiting the crates page from the front page', async function(assert) {
        this.server.loadFixtures();

        await visit('/');
        await click('[data-test-all-crates-link]');

        assert.equal(currentURL(), '/crates');
        assert.equal(document.title, 'Crates - crates.io: Rust Package Registry');
    });

    test('visiting the crates page directly', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        await click('[data-test-all-crates-link]');

        assert.equal(currentURL(), '/crates');
        assert.equal(document.title, 'Crates - crates.io: Rust Package Registry');
    });

    test('listing crates', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');

        assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('1-10');
        assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19');
    });

    test('navigating to next page of crates', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        await click('[data-test-pagination-next]');

        assert.equal(currentURL(), '/crates?page=2');
        assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('11-19');
        assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19');
    });

    test('crates default sort is alphabetical', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');

        assert.dom('[data-test-crates-sort] [data-test-current-order]').hasText('Alphabetical');
    });

    test('downloads appears for each crate on crate list', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 497');
    });

    test('recent downloads appears for each crate on crate list', async function(assert) {
        this.server.loadFixtures();

        await visit('/crates');
        assert.dom('[data-test-crate-row="0"] [data-test-recent-downloads]').hasText('Recent: 497');
    });
});
<|endoftext|>


<commit_before>/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
 */
;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
<commit_msg>cleanup<commit_after><|endoftext|>


<commit_before>goog.provide('gmf.AbstractController');

goog.require('gmf');
/** @suppress {extraRequire} */
goog.require('gmf.QueryManager');
/** @suppress {extraRequire} */
goog.require('gmf.Themes');
/** @suppress {extraRequire} */
goog.require('gmf.layertreeDirective');
/** @suppress {extraRequire} */
goog.require('gmf.mapDirective');
/** @suppress {extraRequire} */
goog.require('gmf.searchDirective');
/** @suppress {extraRequire} */
goog.require('gmf.themeselectorDirective');
goog.require('ngeo.FeatureOverlayMgr');
goog.require('ngeo.GetBrowserLanguage');
goog.require('ngeo.StateManager');
goog.require('ngeo.ToolActivate');
goog.require('ngeo.ToolActivateMgr');

/**
 * Application abstract controller.
 *
 * This file includes `goog.require` for base components/directives used
 * by the HTML page and the controller to provide the configuration.
 *
 * @param {gmfx.Config} config A part of the application config.
 * @param {angular.Scope} $scope Scope.
 * @param {angular.$injector} $injector Main injector.
 * @constructor
 * @ngInject
 * @export
 */
gmf.AbstractController = function(config, $scope, $injector) {

  goog.asserts.assertInstanceof(this.map, ol.Map);

  /**
   * A reference to the current theme
   * @type {Object}
   * @export
   */
  this.theme;

  /**
   * Themes service
   * @type {gmf.Themes}
   */
  var gmfThemes = $injector.get('gmfThemes');
  gmfThemes.loadThemes();

  /**
   * @type {Array.<gmfx.SearchDirectiveDatasource>}
   * @export
   */
  this.searchDatasources = [{
    labelKey: 'label',
    groupValues: /** @type {Array.<string>} **/ ($injector.get('gmfSearchGroups')),
    groupActions: /** @type {Array.<string>} **/ ($injector.get('gmfSearchActions')),
    projection: 'EPSG:' + (config.srid || 21781),
    url: /** @type {string} **/ ($injector.get('fulltextsearchUrl'))
  }];

  /**
   * @type {boolean}
   * @export
   */
  this.leftNavVisible = false;

  /**
   * @type {boolean}
   * @export
   */
  this.rightNavVisible = false;

  /**
   * The active state of the ngeo query directive.
   * @type {boolean}
   * @export
   */
  this.queryActive = true;

  // Not used in this file but the QueryManager must be injected to be watched.
  $injector.get('gmfQueryManager');

  /**
   * The active state of the directive responsible of point measurements.
   * @type {boolean}
   * @export
   */
  this.measurePointActive = false;

  /**
   * The active state of the directive responsible of length measurements.
   * @type {boolean}
   * @export
   */
  this.measureLengthActive = false;

  /**
   * @type {ngeo.GetBrowserLanguage}
   */
  this.getBrowserLanguage = $injector.get('ngeoGetBrowserLanguage');

  /**
   * @type {ngeo.StateManager}
   */
  this.stateManager = $injector.get('ngeoStateManager');

  /**
   * @type {angular.Scope}
   */
  this.$scope = $scope;

  /**
   * Default language
   * @type {string}
   */
  this.defaultLang = $injector.get('defaultLang');

  /**
   * Languages URL
   * @type {Object.<string, string>}
   */
  this.langUrls = $injector.get('langUrls');

  /**
   * The gettext catalog
   * @type {angularGettext.Catalog}
   */
  this.gettextCatalog = $injector.get('gettextCatalog');

  this.initLanguage();

  /**
   * The ngeo feature overlay manager service
   * @type {ngeo.FeatureOverlayMgr}
   */
  var ngeoFeatureOverlayMgr = $injector.get('ngeoFeatureOverlayMgr');
  ngeoFeatureOverlayMgr.init(this.map);

  /**
   * The ngeo ToolActivate manager service.
   * @type {ngeo.ToolActivateMgr}
   */
  var ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr');

  var queryToolActivate = new ngeo.ToolActivate(this, 'queryActive');
  ngeoToolActivateMgr.registerTool('mapTools', queryToolActivate, true);

  var measurePointActivate = new ngeo.ToolActivate(this, 'measurePointActive');
  ngeoToolActivateMgr.registerTool('mapTools', measurePointActivate, false);

  var measureLengthActivate = new ngeo.ToolActivate(
      this, 'measureLengthActive');
  ngeoToolActivateMgr.registerTool('mapTools', measureLengthActivate, false);

};

/**
 * @param {string} lang Language code.
 * @export
 */
gmf.AbstractController.prototype.switchLanguage = function(lang) {
  goog.asserts.assert(lang in this.langUrls);
  this.gettextCatalog.setCurrentLanguage(lang);
  this.gettextCatalog.loadRemote(this.langUrls[lang]);
  this['lang'] = lang;
};

/**
 */
gmf.AbstractController.prototype.initLanguage = function() {
  this.$scope.$watch(function() {
    return this['lang'];
  }.bind(this), function(newValue) {
    this.stateManager.updateState({
      'lang': newValue
    });
  }.bind(this));

  var browserLanguage = /** @type {string|undefined} */
      (this.getBrowserLanguage(goog.object.getKeys(this.langUrls)));
  var urlLanguage = /** @type {string|undefined} */
      (this.stateManager.getInitialValue('lang'));

  if (urlLanguage !== undefined &&
      goog.object.containsKey(this.langUrls, urlLanguage)) {
    this.switchLanguage(urlLanguage);
    return;
  } else if (browserLanguage !== undefined &&
      goog.object.containsKey(this.langUrls, browserLanguage)) {
    this.switchLanguage(browserLanguage);
    return;
  } else {
    // if there is no information about language preference,
    // fallback to default language

    this.switchLanguage(this.defaultLang);
    return;
  }
};

gmf.module.controller('AbstractController', gmf.AbstractController);
<commit_msg>Use 'Object.keys' instead of 'goog.object.getKeys'<commit_after>goog.provide('gmf.AbstractController');

goog.require('gmf');
/** @suppress {extraRequire} */
goog.require('gmf.QueryManager');
/** @suppress {extraRequire} */
goog.require('gmf.Themes');
/** @suppress {extraRequire} */
goog.require('gmf.layertreeDirective');
/** @suppress {extraRequire} */
goog.require('gmf.mapDirective');
/** @suppress {extraRequire} */
goog.require('gmf.searchDirective');
/** @suppress {extraRequire} */
goog.require('gmf.themeselectorDirective');
goog.require('ngeo.FeatureOverlayMgr');
goog.require('ngeo.GetBrowserLanguage');
goog.require('ngeo.StateManager');
goog.require('ngeo.ToolActivate');
goog.require('ngeo.ToolActivateMgr');

/**
 * Application abstract controller.
 *
 * This file includes `goog.require` for base components/directives used
 * by the HTML page and the controller to provide the configuration.
 *
 * @param {gmfx.Config} config A part of the application config.
 * @param {angular.Scope} $scope Scope.
 * @param {angular.$injector} $injector Main injector.
 * @constructor
 * @ngInject
 * @export
 */
gmf.AbstractController = function(config, $scope, $injector) {

  goog.asserts.assertInstanceof(this.map, ol.Map);

  /**
   * A reference to the current theme
   * @type {Object}
   * @export
   */
  this.theme;

  /**
   * Themes service
   * @type {gmf.Themes}
   */
  var gmfThemes = $injector.get('gmfThemes');
  gmfThemes.loadThemes();

  /**
   * @type {Array.<gmfx.SearchDirectiveDatasource>}
   * @export
   */
  this.searchDatasources = [{
    labelKey: 'label',
    groupValues: /** @type {Array.<string>} **/ ($injector.get('gmfSearchGroups')),
    groupActions: /** @type {Array.<string>} **/ ($injector.get('gmfSearchActions')),
    projection: 'EPSG:' + (config.srid || 21781),
    url: /** @type {string} **/ ($injector.get('fulltextsearchUrl'))
  }];

  /**
   * @type {boolean}
   * @export
   */
  this.leftNavVisible = false;

  /**
   * @type {boolean}
   * @export
   */
  this.rightNavVisible = false;

  /**
   * The active state of the ngeo query directive.
   * @type {boolean}
   * @export
   */
  this.queryActive = true;

  // Not used in this file but the QueryManager must be injected to be watched.
  $injector.get('gmfQueryManager');

  /**
   * The active state of the directive responsible of point measurements.
   * @type {boolean}
   * @export
   */
  this.measurePointActive = false;

  /**
   * The active state of the directive responsible of length measurements.
   * @type {boolean}
   * @export
   */
  this.measureLengthActive = false;

  /**
   * @type {ngeo.GetBrowserLanguage}
   */
  this.getBrowserLanguage = $injector.get('ngeoGetBrowserLanguage');

  /**
   * @type {ngeo.StateManager}
   */
  this.stateManager = $injector.get('ngeoStateManager');

  /**
   * @type {angular.Scope}
   */
  this.$scope = $scope;

  /**
   * Default language
   * @type {string}
   */
  this.defaultLang = $injector.get('defaultLang');

  /**
   * Languages URL
   * @type {!Object.<string, string>}
   */
  this.langUrls = $injector.get('langUrls');

  /**
   * The gettext catalog
   * @type {angularGettext.Catalog}
   */
  this.gettextCatalog = $injector.get('gettextCatalog');

  this.initLanguage();

  /**
   * The ngeo feature overlay manager service
   * @type {ngeo.FeatureOverlayMgr}
   */
  var ngeoFeatureOverlayMgr = $injector.get('ngeoFeatureOverlayMgr');
  ngeoFeatureOverlayMgr.init(this.map);

  /**
   * The ngeo ToolActivate manager service.
   * @type {ngeo.ToolActivateMgr}
   */
  var ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr');

  var queryToolActivate = new ngeo.ToolActivate(this, 'queryActive');
  ngeoToolActivateMgr.registerTool('mapTools', queryToolActivate, true);

  var measurePointActivate = new ngeo.ToolActivate(this, 'measurePointActive');
  ngeoToolActivateMgr.registerTool('mapTools', measurePointActivate, false);

  var measureLengthActivate = new ngeo.ToolActivate(
      this, 'measureLengthActive');
  ngeoToolActivateMgr.registerTool('mapTools', measureLengthActivate, false);

};

/**
 * @param {string} lang Language code.
 * @export
 */
gmf.AbstractController.prototype.switchLanguage = function(lang) {
  goog.asserts.assert(lang in this.langUrls);
  this.gettextCatalog.setCurrentLanguage(lang);
  this.gettextCatalog.loadRemote(this.langUrls[lang]);
  this['lang'] = lang;
};

/**
 */
gmf.AbstractController.prototype.initLanguage = function() {
  this.$scope.$watch(function() {
    return this['lang'];
  }.bind(this), function(newValue) {
    this.stateManager.updateState({
      'lang': newValue
    });
  }.bind(this));

  var browserLanguage = /** @type {string|undefined} */
      (this.getBrowserLanguage(Object.keys(this.langUrls)));
  var urlLanguage = /** @type {string|undefined} */
      (this.stateManager.getInitialValue('lang'));

  if (urlLanguage !== undefined &&
      goog.object.containsKey(this.langUrls, urlLanguage)) {
    this.switchLanguage(urlLanguage);
    return;
  } else if (browserLanguage !== undefined &&
      goog.object.containsKey(this.langUrls, browserLanguage)) {
    this.switchLanguage(browserLanguage);
    return;
  } else {
    // if there is no information about language preference,
    // fallback to default language

    this.switchLanguage(this.defaultLang);
    return;
  }
};

gmf.module.controller('AbstractController', gmf.AbstractController);
<|endoftext|>


<commit_before>// http://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_250,h_250,c_fit/sample.jpg
const defaultState = 'f_auto,q_auto,fl_lossy';

export default (url, { maxWidth, maxHeight, width, height, cropX, cropY, quality, blur } = {}, crop) => {
  if (!url) return url;
  if (crop) {
    width = crop[0];
    height = crop[1];
    cropX = crop[2];
    cropY = crop[3];
  }
  if (url.indexOf('http://res.cloudinary.com/') === 0) {
    url = url.split('ttp://res.cloudinary.com/').join('ttps://res.cloudinary.com/');
  }
  if (url.indexOf('https://res.cloudinary.com/') !== 0) return url;
  let part = defaultState;
  if (cropX !== undefined && cropY !== undefined) {
    part = `x_${cropX},y_${cropY},w_${width},h_${height},c_crop/${part}`;
  } else if (width && height) {
    part += `w_${width},h_${height},c_fit/${part}`;
  }

  if (maxWidth && maxHeight) {
    part += `,w_${maxWidth},h_${maxHeight},c_fit`;
  }
  if (quality) {
    part += `,q_${quality}`;
  }
  if (blur) {
    part += `,e_blur:${blur}`;
  }
  if (part === defaultState) {
    part += ',q_75';
  }

  return url.replace('/upload/', `/upload/${part}/`);
};
<commit_msg>Wloudinary url bugfix<commit_after>// http://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_250,h_250,c_fit/sample.jpg
const defaultState = 'f_auto,q_auto,fl_lossy';

export default (url, { maxWidth, maxHeight, width, height, cropX, cropY, quality, blur } = {}, crop) => {
  if (!url) return url;
  if (crop) {
    width = crop[0];
    height = crop[1];
    cropX = crop[2];
    cropY = crop[3];
  }
  if (url.indexOf('http://res.cloudinary.com/') === 0) {
    url = url.split('ttp://res.cloudinary.com/').join('ttps://res.cloudinary.com/');
  }
  if (url.indexOf('https://res.cloudinary.com/') !== 0) return url;
  let part = defaultState;
  if (cropX !== undefined && cropY !== undefined) {
    part = `x_${cropX},y_${cropY},w_${width},h_${height},c_crop/${part}`;
  } else if (width && height) {
    part = `w_${width},h_${height},c_fit/${part}`;
  }

  if (maxWidth && maxHeight) {
    part += `,w_${maxWidth},h_${maxHeight},c_fit`;
  }
  if (quality) {
    part += `,q_${quality}`;
  }
  if (blur) {
    part += `,e_blur:${blur}`;
  }
  if (part === defaultState) {
    part += ',q_75';
  }

  return url.replace('/upload/', `/upload/${part}/`);
};
<|endoftext|>


<commit_before>$(document).ready(function () {
	// get real height of all elements inside div#content
	function getRealHeight() {
		var realHeight = 0;
		$("#content").children().each(function(){
			realHeight = realHeight + $(this).outerHeight(true);
		});
		return realHeight;
	}
	$('#content').css('min-height', getRealHeight());

	var bodyshortcut = false;
	function ensure_bodyshortcut() {
		if ( bodyshortcut == true )
			return;
		var bsc = $('

');
		bsc.insertAfter($('div.body h1:first'));
		bodyshortcut = true;
	};

	// if it's an API page, show the module name.
	var pagename = location.pathname.split('/');
	var is_api = false;
	pagename = pagename[pagename.length - 1];
	if (pagename.search('api-') == 0) {
		pagename = pagename.substr(4, pagename.length - 9);

		ensure_bodyshortcut();
		var modulename = $('
Module: ' + pagename + '
')
		modulename.appendTo($('div.bodyshortcut'));
		is_api = true;
	}

	// insert breaker only for the first data/class/function found.
	var apibreaker = false;
	$('div.body dl[class]').each(function (i1, elem) {
		// these are first level class: attribute and method are inside class.
		if (!$(elem).hasClass('data') &&
			!$(elem).hasClass('class') &&
			!$(elem).hasClass('exception') &&
			!$(elem).hasClass('function'))
			return;
		// dont accept dl inside dl
		if ($(elem).parents().filter('dl').length > 0)
			return;

		$(elem).addClass('api-level');

		if ( apibreaker == true )
			return;
		$('

')
			.attr('id', 'api')
			.html(
				$('
API ' +
				  'Hide Description ⇑' +
				  '
')
				)
			.insertBefore(elem);
		apibreaker = true;
	});

	$('div.body dl[class] dt').hover(
		function() { $(this).addClass('hover'); },
		function() { $(this).removeClass('hover'); }
	);

	if ( apibreaker == true ) {
		ensure_bodyshortcut();
		var apilink = $('
Jump to API ⇓
');
		apilink.insertBefore($('div.bodyshortcut'));
	}

	/**
	$('#api-toggle-all').click(function() {
		if ($(this).hasClass('showed')) {
			$('div.body dl.api-level > dd').slideUp();
			$(this).removeClass('showed');
			$(this).html('Expand All ⇓');
			$.cookie('kivy.toggleall', 'true');
		} else {
			$('div.body dl.api-level > dd').slideDown();
			$(this).addClass('showed');
			$(this).html('Collapse All ⇑');
			$.cookie('kivy.toggleall', 'false');
		}
	});
	**/

	$('#api-toggle-desc').click(function() {
		if ($(this).hasClass('showed')) {
			$('div.body dl.api-level > dd p').hide();
			$('div.body dl.api-level > dd pre').hide();
			$('div.body dl.api-level > dd blockquote').hide();
			$('div.body dl.api-level > dd ul').hide();
			$(this).removeClass('showed');
			$(this).html('Show Descriptions ⇓');
			$('#content').css('min-height',getRealHeight());
			$.cookie('kivy.toggledesc', 'true');
		} else {
			$('div.body dl.api-level > dd p').show();
			$('div.body dl.api-level > dd pre').show();
			$('div.body dl.api-level > dd blockquote').show();
			$('div.body dl.api-level > dd ul').show();
			$(this).addClass('showed');
			$(this).html('Hide Descriptions ⇑');
			$('#content').css('min-height',getRealHeight());
			$.cookie('kivy.toggledesc', 'false');
		}
	});

	$('div.body dl.api-level dt').click(function() {
		$(this).next().children().toggle();
	});

	if ( $.cookie('kivy.toggledesc') == 'true' ) {
		$('div.body dl.api-level > dd > dl > dd').hide();
		$('#api-toggle-desc').removeClass('showed');
		$('#api-toggle-desc').html('Show Descriptions ⇓');
	}

	if ( $.cookie('kivy.toggleall') == 'true' ) {
		$('div.body dl.api-level > dd').hide();
		$('#api-toggle').removeClass('showed');
		$('#api-toggle').html('Expand All ⇓');
	}

	//----------------------------------------------------------------------------
	// Reduce the TOC page
	//----------------------------------------------------------------------------

	var ul = $('div.sphinxsidebarwrapper h3:eq(1) + ul > li > ul');
	$('div.sphinxsidebarwrapper h3:eq(1) + ul').detach();
	ul.insertAfter($('div.sphinxsidebarwrapper h3:eq(1)'));
	$("div.sphinxsidebarwrapper ul").each(function() {
		if ($(this).children().length < 1)
			$(this).remove()
	});

	//----------------------------------------------------------------------------
	// Menu navigation
	//----------------------------------------------------------------------------
	$('div.sphinxsidebarwrapper > ul > li > a').each(function(index, item) {
		$(item)
			.attr('href', '#')
			.addClass('mainlevel');
		if ( !is_api ) {
			$(item)
				.bind('mousedown', function() {
				$('div.sphinxsidebar ul li ul').filter(function (index, child) {
					if (child != $(item).parent().children('ul').get(0)) return child;
				}).slideUp();
				$(item).parent().children('ul').slideToggle();
			});
		}
	})

	$('div.sphinxsidebarwrapper li.current').parent().show();

	if ( !is_api ) {
		$('div.sphinxsidebarwrapper ul li').each(function(index, item) {
			if ($(item).children('ul').length > 0) {
				$(item).children('a').addClass('togglable');
			}
		});
	}

	// FIXME
	$('div.sphinxsidebar a[href$="api-kivy.html"]').parent().parent().addClass('api-index');
	$('div.sphinxsidebar a[href$="api-kivy.utils.html"]').parent().parent().addClass('api-index');
	$('li.current.toctree-l2').slice(0, -1).removeClass('current');

	$('ul.api-index a').each(function(index, item) {
		var url = $(item).attr('href').slice(0, -5);
		if (url == '') {
			$(item).attr('href', location.pathname);
			url = location.pathname.slice(0, -5);
		}
		url = url.substr(url.search('api-') + 4);
		$(item).empty().append(url);
	});

	// Hide API section if we are not in the API.
	// or hide all the others sections if we are in the API
	if ( is_api ) {
		$('div.sphinxsidebarwrapper > ul > li > ul').filter(
				function(index, item) {
					if (! $(item).hasClass('api-index'))
						return item;
				}).parent().hide();
		$('.nav-api').addClass('current');
	} else {
		$('div.sphinxsidebarwrapper > ul > li > ul').filter(
				function(index, item) {
					if ($(item).hasClass('api-index'))
						return item;
				}).parent().hide();
		$('.nav-guides').addClass('current');
	}

	if ( is_api ) {
		var divscroll = $('div.sphinxsidebarwrapper');
		var divscrollwidth = divscroll.width();
		var divapi = $('.api-index');
		var initial_offset = divscroll.offset();
		var jwindow = $(window);

		function update_api() {
			var ywindow = jwindow.scrollTop();
			var ypadding = 20;
			var ydiff = ywindow - initial_offset.top;
			var height = jwindow.height();
			if ( ydiff + ypadding > 0) {
				divscroll.css('position', 'fixed').css('top', ypadding);
				height -= ypadding * 2;
			} else {
				divscroll.css('position', 'static').css('top', -ydiff);
				height += ydiff - ypadding;
			}
			divscroll.height(height).width(divscrollwidth);
			divapi.height(divapi.offsetParent().height() - divapi.position().top)
		}

		$(window).scroll(update_api).bind('resize', update_api);

		update_api();

		$('.toc').hide();

		// Resolve API version
		function read_version(item, default_version) {
			if ( item === undefined )
				return default_version;
			var version = item.find('p').text();
			if ( version == "" )
				return default_version;
			item.detach();
			version = version.replace('New in version ', '');
			if ( version.substr(-1) == '.' )
				version = version.substr(0, version.length - 1);
			return version;
		}

		//function read_version(item, version) { return version; }

		// get module version
		var module_version = read_version($('div.body > div.section > div.versionadded'), '1.0.0');
		var html_version = 'Added in ' + module_version + '';
		$('div.bodyshortcut').append(html_version);

		// resolve class version, default to module if nothing has been found
		$('div.section > dl[class]').each(function (i1, el_class) {
			var rel_class = $(el_class);
			var class_version = read_version(
				rel_class.find('> dd > div.versionadded'), module_version);

			var html_version = 'Added in ' + class_version + '';
			rel_class.find('> dt').append(html_version);

			// resolve method / attr version
			rel_class.find('> dd > dl[class]').each(function (i2, el_methattr) {
				var rel_methattr = $(el_methattr);
				var methattr_version = read_version(
					rel_methattr.find('> dd > div.versionadded'), class_version);
				var html_version = 'Added in ' + methattr_version + '';
				rel_methattr.find('> dt').append(html_version);
			});
		});

	} else {
		var divscroll = $('div.sphinxsidebar');
		var initial_offset = divscroll.offset();
		var jwindow = $(window);
		var b = divscroll.position().top + divscroll.height();

		function update_sidebar() {
			var ywindow = jwindow.scrollTop();
			var ymintop = initial_offset.top;
			var a = ywindow + jwindow.height();
			if ( ywindow <= b ) {
				divscroll.css('position', 'relative').css('top', 0);
			}
		}

		$(window).scroll(update_sidebar).bind('resize', update_sidebar);
		update_sidebar();

		if ($('.toc > ul > li> ul').length < 1)
			$('.toc').hide();

		var section_title = $('li.toctree-l1.current > a').text();
		$('div.body h1:eq(0)').prepend(section_title + ' » ');
	}

});
<commit_msg>Removed update_sidebar. references #5586<commit_after>$(document).ready(function () {
	// get real height of all elements inside div#content
	function getRealHeight() {
		var realHeight = 0;
		$("#content").children().each(function(){
			realHeight = realHeight + $(this).outerHeight(true);
		});
		return realHeight;
	}
	$('#content').css('min-height', getRealHeight());

	var bodyshortcut = false;
	function ensure_bodyshortcut() {
		if ( bodyshortcut == true )
			return;
		var bsc = $('

');
		bsc.insertAfter($('div.body h1:first'));
		bodyshortcut = true;
	};

	// if it's an API page, show the module name.
	var pagename = location.pathname.split('/');
	var is_api = false;
	pagename = pagename[pagename.length - 1];
	if (pagename.search('api-') == 0) {
		pagename = pagename.substr(4, pagename.length - 9);

		ensure_bodyshortcut();
		var modulename = $('
Module: ' + pagename + '
')
		modulename.appendTo($('div.bodyshortcut'));
		is_api = true;
	}

	// insert breaker only for the first data/class/function found.
	var apibreaker = false;
	$('div.body dl[class]').each(function (i1, elem) {
		// these are first level class: attribute and method are inside class.
		if (!$(elem).hasClass('data') &&
			!$(elem).hasClass('class') &&
			!$(elem).hasClass('exception') &&
			!$(elem).hasClass('function'))
			return;
		// dont accept dl inside dl
		if ($(elem).parents().filter('dl').length > 0)
			return;

		$(elem).addClass('api-level');

		if ( apibreaker == true )
			return;
		$('

')
			.attr('id', 'api')
			.html(
				$('
API ' +
				  'Hide Description ⇑' +
				  '
')
				)
			.insertBefore(elem);
		apibreaker = true;
	});

	$('div.body dl[class] dt').hover(
		function() { $(this).addClass('hover'); },
		function() { $(this).removeClass('hover'); }
	);

	if ( apibreaker == true ) {
		ensure_bodyshortcut();
		var apilink = $('
Jump to API ⇓
');
		apilink.insertBefore($('div.bodyshortcut'));
	}

	/**
	$('#api-toggle-all').click(function() {
		if ($(this).hasClass('showed')) {
			$('div.body dl.api-level > dd').slideUp();
			$(this).removeClass('showed');
			$(this).html('Expand All ⇓');
			$.cookie('kivy.toggleall', 'true');
		} else {
			$('div.body dl.api-level > dd').slideDown();
			$(this).addClass('showed');
			$(this).html('Collapse All ⇑');
			$.cookie('kivy.toggleall', 'false');
		}
	});
	**/

	$('#api-toggle-desc').click(function() {
		if ($(this).hasClass('showed')) {
			$('div.body dl.api-level > dd p').hide();
			$('div.body dl.api-level > dd pre').hide();
			$('div.body dl.api-level > dd blockquote').hide();
			$('div.body dl.api-level > dd ul').hide();
			$(this).removeClass('showed');
			$(this).html('Show Descriptions ⇓');
			$('#content').css('min-height',getRealHeight());
			$.cookie('kivy.toggledesc', 'true');
		} else {
			$('div.body dl.api-level > dd p').show();
			$('div.body dl.api-level > dd pre').show();
			$('div.body dl.api-level > dd blockquote').show();
			$('div.body dl.api-level > dd ul').show();
			$(this).addClass('showed');
			$(this).html('Hide Descriptions ⇑');
			$('#content').css('min-height',getRealHeight());
			$.cookie('kivy.toggledesc', 'false');
		}
	});

	$('div.body dl.api-level dt').click(function() {
		$(this).next().children().toggle();
	});

	if ( $.cookie('kivy.toggledesc') == 'true' ) {
		$('div.body dl.api-level > dd > dl > dd').hide();
		$('#api-toggle-desc').removeClass('showed');
		$('#api-toggle-desc').html('Show Descriptions ⇓');
	}

	if ( $.cookie('kivy.toggleall') == 'true' ) {
		$('div.body dl.api-level > dd').hide();
		$('#api-toggle').removeClass('showed');
		$('#api-toggle').html('Expand All ⇓');
	}

	//----------------------------------------------------------------------------
	// Reduce the TOC page
	//----------------------------------------------------------------------------

	var ul = $('div.sphinxsidebarwrapper h3:eq(1) + ul > li > ul');
	$('div.sphinxsidebarwrapper h3:eq(1) + ul').detach();
	ul.insertAfter($('div.sphinxsidebarwrapper h3:eq(1)'));
	$("div.sphinxsidebarwrapper ul").each(function() {
		if ($(this).children().length < 1)
			$(this).remove()
	});

	//----------------------------------------------------------------------------
	// Menu navigation
	//----------------------------------------------------------------------------
	$('div.sphinxsidebarwrapper > ul > li > a').each(function(index, item) {
		$(item)
			.attr('href', '#')
			.addClass('mainlevel');
		if ( !is_api ) {
			$(item)
				.bind('mousedown', function() {
				$('div.sphinxsidebar ul li ul').filter(function (index, child) {
					if (child != $(item).parent().children('ul').get(0)) return child;
				}).slideUp();
				$(item).parent().children('ul').slideToggle();
			});
		}
	})

	$('div.sphinxsidebarwrapper li.current').parent().show();

	if ( !is_api ) {
		$('div.sphinxsidebarwrapper ul li').each(function(index, item) {
			if ($(item).children('ul').length > 0) {
				$(item).children('a').addClass('togglable');
			}
		});
	}

	// FIXME
	$('div.sphinxsidebar a[href$="api-kivy.html"]').parent().parent().addClass('api-index');
	$('div.sphinxsidebar a[href$="api-kivy.utils.html"]').parent().parent().addClass('api-index');
	$('li.current.toctree-l2').slice(0, -1).removeClass('current');

	$('ul.api-index a').each(function(index, item) {
		var url = $(item).attr('href').slice(0, -5);
		if (url == '') {
			$(item).attr('href', location.pathname);
			url = location.pathname.slice(0, -5);
		}
		url = url.substr(url.search('api-') + 4);
		$(item).empty().append(url);
	});

	// Hide API section if we are not in the API.
	// or hide all the others sections if we are in the API
	if ( is_api ) {
		$('div.sphinxsidebarwrapper > ul > li > ul').filter(
				function(index, item) {
					if (! $(item).hasClass('api-index'))
						return item;
				}).parent().hide();
		$('.nav-api').addClass('current');
	} else {
		$('div.sphinxsidebarwrapper > ul > li > ul').filter(
				function(index, item) {
					if ($(item).hasClass('api-index'))
						return item;
				}).parent().hide();
		$('.nav-guides').addClass('current');
	}

	if ( is_api ) {
		var divscroll = $('div.sphinxsidebarwrapper');
		var divscrollwidth = divscroll.width();
		var divapi = $('.api-index');
		var initial_offset = divscroll.offset();
		var jwindow = $(window);

		function update_api() {
			var ywindow = jwindow.scrollTop();
			var ypadding = 20;
			var ydiff = ywindow - initial_offset.top;
			var height = jwindow.height();
			if ( ydiff + ypadding > 0) {
				divscroll.css('position', 'fixed').css('top', ypadding);
				height -= ypadding * 2;
			} else {
				divscroll.css('position', 'static').css('top', -ydiff);
				height += ydiff - ypadding;
			}
			divscroll.height(height).width(divscrollwidth);
			divapi.height(divapi.offsetParent().height() - divapi.position().top)
		}

		$(window).scroll(update_api).bind('resize', update_api);

		update_api();

		$('.toc').hide();

		// Resolve API version
		function read_version(item, default_version) {
			if ( item === undefined )
				return default_version;
			var version = item.find('p').text();
			if ( version == "" )
				return default_version;
			item.detach();
			version = version.replace('New in version ', '');
			if ( version.substr(-1) == '.' )
				version = version.substr(0, version.length - 1);
			return version;
		}

		//function read_version(item, version) { return version; }

		// get module version
		var module_version = read_version($('div.body > div.section > div.versionadded'), '1.0.0');
		var html_version = 'Added in ' + module_version + '';
		$('div.bodyshortcut').append(html_version);

		// resolve class version, default to module if nothing has been found
		$('div.section > dl[class]').each(function (i1, el_class) {
			var rel_class = $(el_class);
			var class_version = read_version(
				rel_class.find('> dd > div.versionadded'), module_version);

			var html_version = 'Added in ' + class_version + '';
			rel_class.find('> dt').append(html_version);

			// resolve method / attr version
			rel_class.find('> dd > dl[class]').each(function (i2, el_methattr) {
				var rel_methattr = $(el_methattr);
				var methattr_version = read_version(
					rel_methattr.find('> dd > div.versionadded'), class_version);
				var html_version = 'Added in ' + methattr_version + '';
				rel_methattr.find('> dt').append(html_version);
			});
		});

	} else {

		if ($('.toc > ul > li> ul').length < 1)
			$('.toc').hide();

		var section_title = $('li.toctree-l1.current > a').text();
		$('div.body h1:eq(0)').prepend(section_title + ' » ');
	}

});
<|endoftext|>


<commit_before>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
var MemberInfoController = require("../../../../src/controllers/molecules/MemberInfo");

module.exports = React.createClass({
    displayName: 'MemberInfo',
    mixins: [MemberInfoController],

    componentDidMount: function() {
        var self = this;

        var memberInfo = this.getDOMNode();
        var memberListScroll = document.getElementsByClassName("mx_MemberList_border")[0];
        if (memberListScroll) {
            memberInfo.style.top = (memberInfo.parentElement.offsetTop - memberListScroll.scrollTop) + "px";
        }
    },

    getDuration: function(time) {
        if (!time) return;
        var t = parseInt(time / 1000);
        var s = t % 60;
        var m = parseInt(t / 60) % 60;
        var h = parseInt(t / (60 * 60)) % 24;
        var d = parseInt(t / (60 * 60 * 24));
        if (t < 60) {
            if (t < 0) {
                return "0s";
            }
            return s + "s";
        }
        if (t < 60 * 60) {
            return m + "m";
        }
        if (t < 24 * 60 * 60) {
            return h + "h";
        }
        return d + "d ";
    },

    render: function() {
        var power;
        if (this.props.member) {
            var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png";
            power = ;
        }
        var activeAgo = "unknown";
        if (this.state.active >= 0) {
            activeAgo = this.getDuration(this.state.active);
        }
        var kickButton, banButton, muteButton, giveModButton;
        if (this.state.can.kick) {
            kickButton =

                Kick

;
        }
        if (this.state.can.ban) {
            banButton =

                Ban

;
        }
        if (this.state.can.mute) {
            var muteLabel = this.state.muted ? "Unmute" : "Mute";
            muteButton =

                {muteLabel}

;
        }
        if (this.state.can.modifyLevel) {
            var giveOpLabel = this.state.isTargetMod ? "Revoke Mod" : "Make Mod";
            giveModButton =

                {giveOpLabel}

        }

        var opLabel;
        if (this.state.isTargetMod) {
            var level = this.props.member.powerLevelNorm + "%";
            opLabel =
Moderator ({level})

        }
        return (

{this.props.member.userId}

                {opLabel}

Presence: {this.state.presence}

Last active: {activeAgo}

Start chat

                {muteButton}
                {kickButton}
                {banButton}
                {giveModButton}

        );
    }
});
<commit_msg>remove spurious dead code<commit_after>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
var MemberInfoController = require("../../../../src/controllers/molecules/MemberInfo");

module.exports = React.createClass({
    displayName: 'MemberInfo',
    mixins: [MemberInfoController],

    componentDidMount: function() {
        var self = this;

        var memberInfo = this.getDOMNode();
        var memberListScroll = document.getElementsByClassName("mx_MemberList_border")[0];
        if (memberListScroll) {
            memberInfo.style.top = (memberInfo.parentElement.offsetTop - memberListScroll.scrollTop) + "px";
        }
    },

    getDuration: function(time) {
        if (!time) return;
        var t = parseInt(time / 1000);
        var s = t % 60;
        var m = parseInt(t / 60) % 60;
        var h = parseInt(t / (60 * 60)) % 24;
        var d = parseInt(t / (60 * 60 * 24));
        if (t < 60) {
            if (t < 0) {
                return "0s";
            }
            return s + "s";
        }
        if (t < 60 * 60) {
            return m + "m";
        }
        if (t < 24 * 60 * 60) {
            return h + "h";
        }
        return d + "d ";
    },

    render: function() {
        var activeAgo = "unknown";
        if (this.state.active >= 0) {
            activeAgo = this.getDuration(this.state.active);
        }
        var kickButton, banButton, muteButton, giveModButton;
        if (this.state.can.kick) {
            kickButton =

                Kick

;
        }
        if (this.state.can.ban) {
            banButton =

                Ban

;
        }
        if (this.state.can.mute) {
            var muteLabel = this.state.muted ? "Unmute" : "Mute";
            muteButton =

                {muteLabel}

;
        }
        if (this.state.can.modifyLevel) {
            var giveOpLabel = this.state.isTargetMod ? "Revoke Mod" : "Make Mod";
            giveModButton =

                {giveOpLabel}

        }

        var opLabel;
        if (this.state.isTargetMod) {
            var level = this.props.member.powerLevelNorm + "%";
            opLabel =
Moderator ({level})

        }
        return (

{this.props.member.userId}

                {opLabel}

Presence: {this.state.presence}

Last active: {activeAgo}

Start chat

                {muteButton}
                {kickButton}
                {banButton}
                {giveModButton}

        );
    }
});
<|endoftext|>


<commit_before>Ext.onReady(function(){
        var mainStore = Ext.create('Ext.data.Store', {
                    storeId: 'tutorials',
                    fields:[ 'S.No','Title', 'Link'],
                    data: [
                        { no:'1', name: 'What is Ext.JS?', link: 'http://kyrierose.github.io'}
                    ]
            });

                Ext.create('Ext.grid.Panel', {
                    title: 'Extjs Tutorials',
                    store: mainStore,
                    columns: [
                        { text: 'S.No', dataIndex: 'no' },
                        { text: 'Name', dataIndex: 'name', width:200 },
                        { text: 'Link', dataIndex: 'link' , width: 200},
                    ],
                    style: 'margin:0 auto;',
                    height: 700,
                    width: "100%",
                    renderTo: Ext.getBody()
                });
});
<commit_msg>Update app.js<commit_after>Ext.onReady(function(){
        var mainStore = Ext.create('Ext.data.Store', {
                    storeId: 'tutorials',
                    fields:[ 'S.No','Title', 'Link'],
                    data: [
                        { no:'1', name: 'What is Ext.JS?', link: 'http://kyrierose.github.io'}
                    ]
            });

                Ext.create('Ext.grid.Panel', {
                    title: 'Extjs Tutorials',
                    store: mainStore,
                    columns: [
                        { text: 'S.No', dataIndex: 'no' },
                        { text: 'Name', dataIndex: 'name', width:200 },
                        { text: 'Link', dataIndex: 'link' , width: 200},
                    ],
                    style: 'margin:0 auto;',
                    height: 700,
                    align: center,
                    width: "70%",
                    renderTo: Ext.getBody()
                });
});
<|endoftext|>