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

/*jslint anon:true, sloppy:true, regexp: true, nomen:true*/
/*global YUI*/

YUI.add('mojito-route-maker', function(Y, NAME) {

    var doCallReplacement,
        copy;

    function wild(it) {
        // if {it}, then it is a wildcard
        if (it.indexOf('{') === 0) {
            // so return the true value without the {}
            return it.substring(1, it.length - 1);
        }
    }

    function resolveParams(route, params) {
        // console.log('============= resolving params for route ' +
        //     route.name);
        // console.log(params);
        // console.log('requires: ' + JSON.stringify(route.requires));
        var tester = [];

        // we don't need to do anything if this route requires no params
        if (Y.Object.size(route.requires) === 0) {
            return route;
        }

        Y.Object.each(params, function(pval, pname) {
            if (route.requires && route.requires[pname]) {
                tester.push(pname + '=' + pval);
            }
        });

        if (tester.length) {
            tester.sort();
            if (new RegExp(route.int_match).test(tester.join('&'))) {
                Y.Object.each(params, function(pval, pname) {
                    route.query[pname] = pval;
                });
                return route;
            }
        }
    }

    function buildRoute(name, route) {

        var i,
            verbObj,
            path,
            matches,
            build,
            segment,
            key;

        if (!route.name) {
            route.name = name;
        }
        if (!route.verbs) {
            route.verbs = ['GET'];
        }

        // Checking route.verbs is changed from an array to an object by the
        // building process, so routes that have already been computed are
        // not recomputed.

        if (route.verbs.length && route.path && route.call) {
            // FUTURE: [Issue 73] allow object params, not just string
            if (!route.params) {
                route.params = '';
            }
            if (!route.regex) {
                route.regex = {};
            }
            if (!route.query) {
                route.query = {};
            }

            /*
             * Here we convert the verb array to a map for easy use later on
             **/
            verbObj = {};
            for (i in route.verbs) {
                if (route.verbs.hasOwnProperty(i)) {
                    verbObj[route.verbs[i].toUpperCase()] = true;
                }
            }
            route.verbs = verbObj;

            path = route.path.split('/');

            /*
             * Here we build the matching regex for external URI's
             */
            for (segment in path) {
                if (path.hasOwnProperty(segment)) {
                    if (path[segment][0] === ':') {
                        key = path[segment].substr(1);
                        route.query[key] = '';
                        path[segment] = route.regex[key] ?
                                '(' + route.regex[key] + ')' :
                                '([^\/]+)';
                    }

                    if (path[segment][0] === '*') {
                        path[segment] = '(.*)';
                    }
                }
            }

            /*
             * Here we build the matching regex for internal URI's
             */
            route.requires = {};
            matches = route.path.match(/:([^\/]+)/g);
            for (i in matches) {
                if (matches.hasOwnProperty(i)) {
                    route.requires[matches[i].substr(1)] = '[^&]+';
                }
            }
            for (i in route.regex) {
                if (route.regex.hasOwnProperty(i)) {
                    route.requires[i] = route.regex[i];
                }
            }

            if (typeof route.params !== 'object') {
                route.params = Y.QueryString.parse(String(route.params));
            }

            build = [];
            for (i in route.requires) {
                if (route.requires.hasOwnProperty(i)) {
                    build.push(i + '=' + route.requires[i]);
                }
            }
            build.sort();

            /*
             * We are done so lets store the regex's for the route.
             */
            // TODO: [Issue 74] These Regexes are recreated on
            // every request because they need to be serialized and sent to the
            // client, need to figure out a way to prevent that
            route.ext_match = '^' + path.join('\/') + '$';
            route.int_match = '^' + build.join('&') + '$';
        }

        return route;
    }

    doCallReplacement = function(route, uri) {
        var uriParts = uri.substr(1).split('\/'),
            pathParts = route.path.substr(1).split('\/'),
            template = {},
            cnt = 0;

        pathParts.forEach(function(pathPart) {
            var key,
                val,
                regex;

            // process only those keyed by ':'
            if (pathPart.indexOf(':') === 0) {
                key = pathPart.substr(1);
                val = uriParts[cnt];
                template[key] = val;
                regex = new RegExp('{' + key + '}', 'g');
                if (regex.test(route.call)) {
                    route.call = route.call.replace(regex, template[key]);
                } else {
                    route.params[key] = val;
                }
            }
            cnt += 1;
        });
        return route;
    };

    copy = function(obj) {
        var temp = null, key = '';
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
        temp = new obj.constructor();
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                temp[key] = copy(obj[key]);
            }
        }
        return temp;
    };

    /*
     * The route maker for reverse URL lookup.
     * @class Maker
     * @namespace Y.mojito
     * @param {Object} routes key value store of all routes in the system
     */
    function Maker(routes) {
        var name;
        this._routes = {};
        // TODO: [Issue 75] Cache these computed routes so we
        // don't have to do this on each request.
        for (name in routes) {
            if (routes.hasOwnProperty(name)) {
                this._routes[name] = buildRoute(name, routes[name]);
            }
        }
    }

    Maker.prototype = {

        /*
         * Generates a URL from a route query
         * @method make
         * @param {String} query string to convert to a URL
         * @param {String} verb http method
         */
        make: function(query, verb) {
            // Y.log('make(' + query + ', ' + verb + ')', 'debug', NAME);

            var parts = query.split('?'),
                call = parts[0],
                params = {},
                route,
                uri;

            // TODO: don't assign to a parameter.
            verb = verb || 'GET';

            if (parts[1]) {
                params = Y.QueryString.parse(parts[1]);
            }
            route = this._matchToExternal(call, params, verb, this._routes);

            if (!route) {
                throw new Error(
                    "No route match found for '" + query + "' (" + verb + ')'
                );
            }

            uri = route.path;

            Y.Object.each(route.query, function(v, k) {
                uri = uri.replace(':' + k, v);
                delete params[k];
            });

            if (!Y.Object.isEmpty(params)) {
                uri += '?' + Y.QueryString.stringify(params);
            }

            return uri;
        },

        /**
         * Finds a route for a given method+URL
         * @method find
         * @param {string} url the URL to find a route for.
         * @param {string} verb the HTTP method.
         */
        find: function(uri, verb) {
            // logger.log('[UriRouter] find( ' + uri + ', ' + verb + ' )');

            var route,
                match,
                ret,
                i,
                id;

            // TODO: don't assign to parameter.
            verb = verb || 'GET';

            route = this._matchToInternal(uri, verb, this._routes);
            if (!route) {
                return null;
            }

            // logger.log('[UriRouter] found route: ' + JSON.stringify(route));

            match = copy(route);

            // Add the extracted URI params to the query obj
            ret = new RegExp(route.ext_match).exec(uri);
            i = 1;

            for (id in match.query) {
                if (match.query.hasOwnProperty(id)) {
                    match.query[id] = ret[i];
                    i += 1;
                }
            }

            // Add the fixed params to a query obj if they are not there
            for (i in match.params) {
                if (match.params.hasOwnProperty(i) && !match.query[i]) {
                    match.query[i] = match.params[i];
                }
            }

            return match;
        },

        /**
         * For optimization. Call this to get the computed routes that can be
         * passed to the constructor to avoid recomputing the routes.
         * @method getComputedRoutes
         * @return {object} computed routes.
         */
        getComputedRoutes: function() {
            return this._routes;
        },

        /**
         * Returns a matching route for the given URI
         * @method _matchToInternal
         * @param {string} uri The uri to find a route for.
         * @param {string} verb. The HTTP verb for the route.
         * @private
         */
        _matchToInternal: function(uri, verb, routes) {
            var name;

            // TODO: don't assign to a parameter.
            if (!verb) {
                verb = 'GET';
            }

            verb = verb.toUpperCase();

            // logger.log('[UriRouter] Start Matching ...');
            for (name in routes) {
                if (routes.hasOwnProperty(name)) {
                    // logger.log('[UriRouter] testing ' + name);

                    // TODO: [Issue 74] See comment elsewhere
                    // about regexes being created... we need to stash these
                    // objects somewhere instead of creating them on every
                    // request
                    if (new RegExp(routes[name].ext_match).test(uri) &&
                            routes[name].verbs &&
                            routes[name].verbs.hasOwnProperty(verb)) {

                        // TODO: [Issue 74] Prevent more Regex creations.
                        return doCallReplacement(routes[name], uri);
                    }
                    // logger.log('[UriRouter] ' + verb + ' ' + uri + ' ' +
                    //     routes[name].ext_match);
                }
            }
            return false;
        },

        /*
         * @method _matchToExternal
         * @private
         */
        _matchToExternal: function(call, params, verb, routes) {
            var match,
                callParts = call.split('.'),
                callId = callParts[0],
                callAction = callParts[1];

            Y.Object.some(routes, function(route) {
                var routeCall,
                    routeId,
                    routeAction,
                    wildId,
                    wildAction;

                // it might be an exact match
                if (call === route.call && route.verbs[verb]) {
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }

                // if we have a wild card try a match
                if ('*.*' === route.call && route.verbs[verb]) {
                    params.module = callId;
                    params.action = callAction;
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }

                routeCall = route.call.split('.');
                routeId = routeCall[0];
                routeAction = routeCall[1];

                wildId = wild(routeId);
                if (wildId) {
                    params[wildId] = callId;
                }
                wildAction = wild(routeAction);
                if (wildAction) {
                    params[wildAction] = callAction;
                }

                // if action is wild, or action matches
                if ((wildAction || (callAction === routeAction)) &&
                        // and if id is wild, or id matches
                        ((wildId || (callId === routeId))) &&
                        // and if the verb is correct
                        route.verbs[verb]) {

                    // then we can try a param match
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }
            });
            return match;
        }
    };

    Y.mojito.RouteMaker = Maker;

}, '0.1.0', {  requires: [
    'querystring',
    'mojito-util'
]});
<commit_msg>Added back requirements that I removed in debugging<commit_after>/*
 * Copyright (c) 2011-2012, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jslint anon:true, sloppy:true, regexp: true, nomen:true*/
/*global YUI*/

YUI.add('mojito-route-maker', function(Y, NAME) {

    var doCallReplacement,
        copy;

    function wild(it) {
        // if {it}, then it is a wildcard
        if (it.indexOf('{') === 0) {
            // so return the true value without the {}
            return it.substring(1, it.length - 1);
        }
    }

    function resolveParams(route, params) {
        // console.log('============= resolving params for route ' +
        //     route.name);
        // console.log(params);
        // console.log('requires: ' + JSON.stringify(route.requires));
        var tester = [];

        // we don't need to do anything if this route requires no params
        if (Y.Object.size(route.requires) === 0) {
            return route;
        }

        Y.Object.each(params, function(pval, pname) {
            if (route.requires && route.requires[pname]) {
                tester.push(pname + '=' + pval);
            }
        });

        if (tester.length) {
            tester.sort();
            if (new RegExp(route.int_match).test(tester.join('&'))) {
                Y.Object.each(params, function(pval, pname) {
                    route.query[pname] = pval;
                });
                return route;
            }
        }
    }

    function buildRoute(name, route) {

        var i,
            verbObj,
            path,
            matches,
            build,
            segment,
            key;

        if (!route.name) {
            route.name = name;
        }
        if (!route.verbs) {
            route.verbs = ['GET'];
        }

        // Checking route.verbs is changed from an array to an object by the
        // building process, so routes that have already been computed are
        // not recomputed.

        if (route.verbs.length && route.path && route.call) {
            // FUTURE: [Issue 73] allow object params, not just string
            if (!route.params) {
                route.params = '';
            }
            if (!route.regex) {
                route.regex = {};
            }
            if (!route.query) {
                route.query = {};
            }

            /*
             * Here we convert the verb array to a map for easy use later on
             **/
            verbObj = {};
            for (i in route.verbs) {
                if (route.verbs.hasOwnProperty(i)) {
                    verbObj[route.verbs[i].toUpperCase()] = true;
                }
            }
            route.verbs = verbObj;

            path = route.path.split('/');

            /*
             * Here we build the matching regex for external URI's
             */
            for (segment in path) {
                if (path.hasOwnProperty(segment)) {
                    if (path[segment][0] === ':') {
                        key = path[segment].substr(1);
                        route.query[key] = '';
                        path[segment] = route.regex[key] ?
                                '(' + route.regex[key] + ')' :
                                '([^\/]+)';
                    }

                    if (path[segment][0] === '*') {
                        path[segment] = '(.*)';
                    }
                }
            }

            /*
             * Here we build the matching regex for internal URI's
             */
            route.requires = {};
            matches = route.path.match(/:([^\/]+)/g);
            for (i in matches) {
                if (matches.hasOwnProperty(i)) {
                    route.requires[matches[i].substr(1)] = '[^&]+';
                }
            }
            for (i in route.regex) {
                if (route.regex.hasOwnProperty(i)) {
                    route.requires[i] = route.regex[i];
                }
            }

            if (typeof route.params !== 'object') {
                route.params = Y.QueryString.parse(String(route.params));
            }

            build = [];
            for (i in route.requires) {
                if (route.requires.hasOwnProperty(i)) {
                    build.push(i + '=' + route.requires[i]);
                }
            }
            build.sort();

            /*
             * We are done so lets store the regex's for the route.
             */
            // TODO: [Issue 74] These Regexes are recreated on
            // every request because they need to be serialized and sent to the
            // client, need to figure out a way to prevent that
            route.ext_match = '^' + path.join('\/') + '$';
            route.int_match = '^' + build.join('&') + '$';
        }

        return route;
    }

    doCallReplacement = function(route, uri) {
        var uriParts = uri.substr(1).split('\/'),
            pathParts = route.path.substr(1).split('\/'),
            template = {},
            cnt = 0;

        pathParts.forEach(function(pathPart) {
            var key,
                val,
                regex;

            // process only those keyed by ':'
            if (pathPart.indexOf(':') === 0) {
                key = pathPart.substr(1);
                val = uriParts[cnt];
                template[key] = val;
                regex = new RegExp('{' + key + '}', 'g');
                if (regex.test(route.call)) {
                    route.call = route.call.replace(regex, template[key]);
                } else {
                    route.params[key] = val;
                }
            }
            cnt += 1;
        });
        return route;
    };

    copy = function(obj) {
        var temp = null, key = '';
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
        temp = new obj.constructor();
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                temp[key] = copy(obj[key]);
            }
        }
        return temp;
    };

    /*
     * The route maker for reverse URL lookup.
     * @class Maker
     * @namespace Y.mojito
     * @param {Object} routes key value store of all routes in the system
     */
    function Maker(routes) {
        var name;
        this._routes = {};
        // TODO: [Issue 75] Cache these computed routes so we
        // don't have to do this on each request.
        for (name in routes) {
            if (routes.hasOwnProperty(name)) {
                this._routes[name] = buildRoute(name, routes[name]);
            }
        }
    }

    Maker.prototype = {

        /*
         * Generates a URL from a route query
         * @method make
         * @param {String} query string to convert to a URL
         * @param {String} verb http method
         */
        make: function(query, verb) {
            // Y.log('make(' + query + ', ' + verb + ')', 'debug', NAME);

            var parts = query.split('?'),
                call = parts[0],
                params = {},
                route,
                uri;

            // TODO: don't assign to a parameter.
            verb = verb || 'GET';

            if (parts[1]) {
                params = Y.QueryString.parse(parts[1]);
            }
            route = this._matchToExternal(call, params, verb, this._routes);

            if (!route) {
                throw new Error(
                    "No route match found for '" + query + "' (" + verb + ')'
                );
            }

            uri = route.path;

            Y.Object.each(route.query, function(v, k) {
                uri = uri.replace(':' + k, v);
                delete params[k];
            });

            if (!Y.Object.isEmpty(params)) {
                uri += '?' + Y.QueryString.stringify(params);
            }

            return uri;
        },

        /**
         * Finds a route for a given method+URL
         * @method find
         * @param {string} url the URL to find a route for.
         * @param {string} verb the HTTP method.
         */
        find: function(uri, verb) {
            // logger.log('[UriRouter] find( ' + uri + ', ' + verb + ' )');

            var route,
                match,
                ret,
                i,
                id;

            // TODO: don't assign to parameter.
            verb = verb || 'GET';

            route = this._matchToInternal(uri, verb, this._routes);
            if (!route) {
                return null;
            }

            // logger.log('[UriRouter] found route: ' + JSON.stringify(route));

            match = copy(route);

            // Add the extracted URI params to the query obj
            ret = new RegExp(route.ext_match).exec(uri);
            i = 1;

            for (id in match.query) {
                if (match.query.hasOwnProperty(id)) {
                    match.query[id] = ret[i];
                    i += 1;
                }
            }

            // Add the fixed params to a query obj if they are not there
            for (i in match.params) {
                if (match.params.hasOwnProperty(i) && !match.query[i]) {
                    match.query[i] = match.params[i];
                }
            }

            return match;
        },

        /**
         * For optimization. Call this to get the computed routes that can be
         * passed to the constructor to avoid recomputing the routes.
         * @method getComputedRoutes
         * @return {object} computed routes.
         */
        getComputedRoutes: function() {
            return this._routes;
        },

        /**
         * Returns a matching route for the given URI
         * @method _matchToInternal
         * @param {string} uri The uri to find a route for.
         * @param {string} verb. The HTTP verb for the route.
         * @private
         */
        _matchToInternal: function(uri, verb, routes) {
            var name;

            // TODO: don't assign to a parameter.
            if (!verb) {
                verb = 'GET';
            }

            verb = verb.toUpperCase();

            // logger.log('[UriRouter] Start Matching ...');
            for (name in routes) {
                if (routes.hasOwnProperty(name)) {
                    // logger.log('[UriRouter] testing ' + name);

                    // TODO: [Issue 74] See comment elsewhere
                    // about regexes being created... we need to stash these
                    // objects somewhere instead of creating them on every
                    // request
                    if (new RegExp(routes[name].ext_match).test(uri) &&
                            routes[name].verbs &&
                            routes[name].verbs.hasOwnProperty(verb)) {

                        // TODO: [Issue 74] Prevent more Regex creations.
                        return doCallReplacement(routes[name], uri);
                    }
                    // logger.log('[UriRouter] ' + verb + ' ' + uri + ' ' +
                    //     routes[name].ext_match);
                }
            }
            return false;
        },

        /*
         * @method _matchToExternal
         * @private
         */
        _matchToExternal: function(call, params, verb, routes) {
            var match,
                callParts = call.split('.'),
                callId = callParts[0],
                callAction = callParts[1];

            Y.Object.some(routes, function(route) {
                var routeCall,
                    routeId,
                    routeAction,
                    wildId,
                    wildAction;

                // it might be an exact match
                if (call === route.call && route.verbs[verb]) {
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }

                // if we have a wild card try a match
                if ('*.*' === route.call && route.verbs[verb]) {
                    params.module = callId;
                    params.action = callAction;
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }

                routeCall = route.call.split('.');
                routeId = routeCall[0];
                routeAction = routeCall[1];

                wildId = wild(routeId);
                if (wildId) {
                    params[wildId] = callId;
                }
                wildAction = wild(routeAction);
                if (wildAction) {
                    params[wildAction] = callAction;
                }

                // if action is wild, or action matches
                if ((wildAction || (callAction === routeAction)) &&
                        // and if id is wild, or id matches
                        ((wildId || (callId === routeId))) &&
                        // and if the verb is correct
                        route.verbs[verb]) {

                    // then we can try a param match
                    match = resolveParams(route, params);
                    if (match) {
                        return true;
                    }
                }
            });
            return match;
        }
    };

    Y.mojito.RouteMaker = Maker;

}, '0.1.0', {  requires: [
    'querystring-stringify-simple',
    'querystring-parse',
    'mojito-util'
]});
<|endoftext|>


<commit_before>/**
 * @license
 * Patterns @VERSION@ parser - argument parser
 *
 * Copyright 2012 Simplon B.V.
 * Copyright 2012 Florian Friesdorf
 */
define([
    'require',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('parser');

    function ArgumentParser(spec) {
        this.params = [];
        this.defaults = {};
        if (spec) this.add_spec(spec);
    }

    ArgumentParser.prototype = {
        named_param_pattern: /^\s*([a-zA-Z0-9]+)\s*:(.*)/,

        add_argument: function(name, default_value) {
            if (default_value === undefined) default_value = "";
            this.params.push(name);
            this.defaults[name] = default_value;
        },

        add_spec: function(spec) {
            var parts = spec.split(';'),
                parser = this;
            for (var i=0, part; i<parts.length; i++) {
                part = parts[i].trim();
                var match = part.match(parser.named_param_pattern);
                if (match) {
                    parser.add_argument(match[1], match[2].trim());
                } else {
                    parser.add_argument(part);
                }
            }
        },

        parse: function(parameter, defaults) {
            defaults = defaults || {};
            if (!parameter) {
                return defaults;
            }
            if (parameter.match(/&&/)) {
                return parameter.split(/\s*&&\s*/).map(function(parameter) {
                    return this.parse(parameter, defaults);
                }, this);
            }

            var parts = parameter.split(";"),
                opts = {},
                part, matches, i, name;

            // Popuplate options with default values
            for (i=0; i<this.params.length; i++) {
                name = this.params[i];
                opts[name] = defaults[name] || this.defaults[name];
            }

            // Grab all positional parameters
            i=-1;
            while (parts.length) {
                i++;
                if (i>=this.params.length) {
                    break;
                }
                part = parts.shift().trim();
                if (!part)
                    continue;
                if (this.named_param_pattern.test(part)) {
                    parts.unshift(part);
                    break;
                }
                opts[this.params[i]] = part.trim();
            }

            // Handle all named parameters
            for (i=0; i<parts.length; i++) {
                matches = parts[i].match(this.named_param_pattern);
                if (!matches) {
                    log.warn("Positional parameters not allowed after named parameters");
                    break;
                }
                if (this.defaults[matches[1]] === undefined) {
                    log.warn("Unknown named parameter " + matches[1]);
                    continue;
                }
                opts[matches[1]] = matches[2].trim();
            }

            for (name in opts) {
                if (opts[name].slice(0,1) === "$") {
                    opts[name] = opts[opts[name].slice(1)];
                }
            }

            return opts;
        }
    };

    return ArgumentParser;

});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Fix parser test errors.<commit_after>/**
 * @license
 * Patterns @VERSION@ parser - argument parser
 *
 * Copyright 2012 Simplon B.V.
 * Copyright 2012 Florian Friesdorf
 */
define([
    'require',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('parser');

    function ArgumentParser(spec) {
        this.params = [];
        this.defaults = {};
        if (spec)
            this.add_spec(spec);
    }

    ArgumentParser.prototype = {
        named_param_pattern: /^\s*([a-zA-Z0-9]+)\s*:(.*)/,

        add_argument: function(name, default_value) {
            if (default_value === undefined)
                default_value = null;
            this.params.push(name);
            this.defaults[name] = default_value;
        },

        add_spec: function(spec) {
            var parts = spec.split(';'),
                parser = this;
            for (var i=0, part; i<parts.length; i++) {
                part = parts[i].trim();
                var match = part.match(parser.named_param_pattern);
                if (match) {
                    parser.add_argument(match[1], match[2].trim());
                } else {
                    parser.add_argument(part);
                }
            }
        },

        parse: function(parameter, defaults) {
            if (parameter && parameter.match(/&&/)) {
                return parameter.split(/\s*&&\s*/).map(function(parameter) {
                    return this.parse(parameter, defaults);
                }, this);
            }

            var opts = {}, i, name;

            // Copy all defaults to opts.
            if (typeof defaults === "object")
                for (i in defaults)
                    opts[i] = defaults[i];
            for (i in this.defaults)
                opts[i] = opts[i] || this.defaults[i];

            if (!parameter)
                return opts;

            var parts = parameter.split(";"),
                part, matches;

            // Grab all positional parameters
            i=-1;
            while (parts.length) {
                i++;
                if (i>=this.params.length) {
                    break;
                }
                part = parts.shift().trim();
                if (!part)
                    continue;
                if (this.named_param_pattern.test(part)) {
                    parts.unshift(part);
                    break;
                }
                opts[this.params[i]] = part.trim();
            }

            // Handle all named parameters
            for (i=0; i<parts.length; i++) {
                matches = parts[i].match(this.named_param_pattern);
                if (!matches) {
                    log.warn("Positional parameters not allowed after named parameters");
                    break;
                }
                if (this.defaults[matches[1]] === undefined) {
                    log.warn("Unknown named parameter " + matches[1]);
                    continue;
                }
                opts[matches[1]] = matches[2].trim();
            }

            for (name in opts) {
                if (typeof opts[name]==="string" && opts[name].slice(0,1) === "$")
                    opts[name] = opts[opts[name].slice(1)];
            }

            return opts;
        }
    };

    return ArgumentParser;

});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>/**
 * Copyright Dailymotion S.A.
 *
 * 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.
 *
 * @provides dm.player
 * @requires dm.prelude
 *           dm.qs
 *           dm.xdcom
 */

/**
 * Dailymotion Player.
 *
 * @class dm
 * @static
 * @access private
 */
DM.provide('',
{
    player: function(element, options)
    {
        return DM.Player.create(element, options);
    }
});

/**
 * The Player object.
 *
 * @class DM.Player
 * @access private
 */
DM.provide('Player',
{
    _INSTANCES: {},
    _INTERVAL_ID: null,
    _PROTOCOL: null,
    API_MODE: null,
    EVENT_HANDLERS: {},

    // video properties
    apiReady: false,
    autoplay: false,
    currentTime: 0,
    bufferedTime: 0,
    duration: NaN,
    seeking: false,
    error: null,
    ended: false,
    muted: false,
    volume: 1,
    paused: true,
    fullscreen: false,
    rebuffering: false,

    play: function() {this.api('play');},
    togglePlay: function() {this.api('toggle-play');},
    pause: function() {this.api('pause');},
    seek: function(time) {this.api('seek', time);},
    load: function(id) {this.api('load', id);},
    setMuted: function(muted) {this.api('muted', muted);},
    toggleMuted: function() {this.api('toggle-muted');},
    setVolume: function(volume) {this.api('volume', volume);},
    setFullscreen: function(fullscreen) {this.api('fullscreen', fullscreen);},
    watchOnSite: function(muted) {this.api('watch-on-site');},

    api: function(command, arg)
    {
        if(typeof arg !== 'undefined') command += '=' + arg;
        this._send(command);
    },

    create: function(element, options)
    {
        element = DM.$(element);
        if (!element || element.nodeType != 1)
            throw new Error("Invalid first argument sent to DM.player(), requires a HTML element or element id: " + element);
        if (!options || typeof options != 'object')
            throw new Error("Missing `options' parameter for DM.player()");

        options = DM.copy(options,
        {
            width: 480,
            height: 270,
            title: "video player",
            params: {},
            events: {}
        });

        // see #5 : _domain.www should be protocol independent
        // remove protocol from existing value to preserve backward compatibility
        DM._domain.www = DM._domain.www.replace(/^https?\:/, '');
        DM.Player._PROTOCOL = (window.location && /^https?:$/.test(window.location.protocol)) ? window.location.protocol : 'http:';

        var player = document.createElement("iframe");
        DM.Array.forEach(['id', 'style', 'class'], function(attr)
        {
            var val = element.getAttribute(attr);
            if (val) player.setAttribute(attr, val);
        });
        player.setAttribute("frameborder", "0");
        player.setAttribute("allowfullscreen", "true");
        player.setAttribute("webkitallowfullscreen", "true");
        player.setAttribute("mozallowfullscreen", "true");
        player.title = "Dailymotion " + options.title;
        player.type = "text/html";
        player.width = options.width;
        player.height = options.height;
        element.parentNode.replaceChild(player, element);

        DM.copy(player, DM.Player);

        player.init(options.video, options.params);

        if (typeof options.events == "object")
        {
            for (var name in options.events)
            {
                player.addEventListener(name, options.events[name], false);
            }
        }

        return player;
    },

    init: function(video, params)
    {
        var self = this;
        DM.Player._installHandlers(function()
        {
            // ask the peer to resend the apiready event in case it missed it while installing handlers
            self._send('check');
        });
        params = typeof params == "object" ? params : {};
        params.api = DM.Player.API_MODE;
        if (DM.Player.API_MODE == 'xdcom')
        {
            params.xdcomId = DM.Player.xdcomChannel.connectionId;
        }
        if (DM._apiKey)
        {
            params.apiKey = DM._apiKey;
        }
        this.id = params.id = this.id ? this.id : DM.guid();
        this.src = DM.Player._PROTOCOL + DM._domain.www + "/embed" + (video ? "/video/" + video : "") + '?' + DM.QS.encode(params);
        if (DM.Player._INSTANCES[this.id] != this)
        {
            DM.Player._INSTANCES[this.id] = this;
            this.addEventListener('unload', function() {delete DM.Player._INSTANCES[this.id];});
        }

        this.autoplay = DM.parseBool(params.autoplay);
    },

    _installHandlers: function(initedCallback)
    {
        if (DM.Player.API_MODE !== null) return;
        if (window.postMessage)
        {
            DM.Player.API_MODE = "postMessage";

            var handler = function(e)
            {
                if (!e.origin || e.origin.indexOf(DM.Player._PROTOCOL + DM._domain.www) !== 0) return;
                var event = DM.QS.decode(e.data);
                if (!event.id || !event.event) return;
                var player = DM.$(event.id);
                player._recvEvent(event);
            };
            if (window.addEventListener) window.addEventListener("message", handler, false);
            else if (window.attachEvent) window.attachEvent("onmessage", handler);
        }
        else if(DM.XDCom.capable())
        {
            DM.Player.API_MODE = "xdcom";
            DM.Player.xdcomChannel = DM.XDCom.createChannel(function(data)
            {
                var event = DM.QS.decode(data);
                if (!event.id || !event.event) return;
                var player = DM.$(event.id);
                player._recvEvent(event);
            }, initedCallback);
        }

        if (DM.Player.API_MODE === null)
        {
            DM.Player.API_MODE = "fragment";
            return; // no yet ready

            if (!DM.Player._INTERVAL_ID)
            {
                DM.Player._INTERVAL_ID = setInterval(function()
                {
                    for (var id in DM.Player._INSTANCES)
                    {
                        var player = DM.Player._INSTANCES[id], pos;
                        if ((pos = player.src.indexOf('#')) != -1)
                        {
                            var event = DM.QS.decode(src.substring(pos + 1));
                            player.src = src.substring(0, pos); // reset fragment
                            if (event.id && event.event) player._recvEvent(event);
                        }
                    }
                    if (DM.Player._INSTANCES.length === 0) clearInterval(DM.Player._INTERVAL_ID);
                }, 0);
            }
        }
    },

    _send: function(command) // fragment API mode fallback
    {
        switch (DM.Player.API_MODE)
        {
            case 'postMessage':
                this.contentWindow.postMessage(command, DM.Player._PROTOCOL + DM._domain.www);
                break;

            case 'xdcom':
                DM.Player.xdcomChannel.postMessage(this.id, command);
                break;

            case 'fragment':
                var src = this.src, pos;
                if ((pos = src.indexOf('#')) != -1) src = src.substring(0, pos);
                this.src = src + '#' + command;
                break;
        }
    },

    _dispatch: document.createEvent ? function(type)
    {
        var e = document.createEvent("HTMLEvents");
        e.initEvent(type, true, true);
        this.dispatchEvent(e);
    }
    : function(type) // IE compat
    {
        if ('on' + type in this)
        {
            e = document.createEventObject();
            this.fireEvent('on' + type, e);
        }
        else if (type in this.EVENT_HANDLERS)
        {
            var e = {type: type, target: this};
            DM.Array.forEach(this.EVENT_HANDLERS[type], function(handler)
            {
                handler(e);
            });
        }
    },

    _recvEvent: function(event)
    {
        switch (event.event)
        {
            case 'apiready': if (this.apiReady) return /* dispatch only once */; else this.apiReady = true; break;
            case 'loadedmetadata': this.error = null; this.ended = false; break;
            case 'timeupdate': this.currentTime = parseFloat(event.time); break;
            case 'progress': this.bufferedTime = parseFloat(event.time); break;
            case 'durationchange': this.duration = parseFloat(event.duration); break;
            case 'seeking': this.seeking = true; this.currentTime = parseFloat(event.time); break;
            case 'seeked': this.seeking = false; this.currentTime = parseFloat(event.time); break;
            case 'fullscreenchange': this.fullscreen = DM.parseBool(event.fullscreen); break;
            case 'volumechange': this.volume = parseFloat(event.volume); this.muted = DM.parseBool(event.muted); break;
            case 'playing':
            case 'play': this.paused = false; break;
            case 'ended': this.ended = true; break; // no break, also set paused
            case 'ended':
            case 'pause': this.paused = true; break;
            case 'error': this.error = {code: event.code, title: event.title, message: event.message}; break;
            case 'rebuffer': this.rebuffering = DM.parseBool(event.rebuffering); break;
        }

        this._dispatch(event.event);
    },

    // IE compat (DM.copy won't set this if already defined)
    addEventListener: function(name, callback, capture)
    {
        if ('on' + name in this && this.attachEvent)
        {
            this.attachEvent("on" + name, callback, capture);
        }
        else
        {
            if (!(name in this.EVENT_HANDLERS))
            {
                this.EVENT_HANDLERS[name] = [];
            }
            this.EVENT_HANDLERS[name].push(callback);
        }
    }
});
<commit_msg>Update public properties according to ads playback events<commit_after>/**
 * Copyright Dailymotion S.A.
 *
 * 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.
 *
 * @provides dm.player
 * @requires dm.prelude
 *           dm.qs
 *           dm.xdcom
 */

/**
 * Dailymotion Player.
 *
 * @class dm
 * @static
 * @access private
 */
DM.provide('',
{
    player: function(element, options)
    {
        return DM.Player.create(element, options);
    }
});

/**
 * The Player object.
 *
 * @class DM.Player
 * @access private
 */
DM.provide('Player',
{
    _INSTANCES: {},
    _INTERVAL_ID: null,
    _PROTOCOL: null,
    API_MODE: null,
    EVENT_HANDLERS: {},

    // video properties
    apiReady: false,
    autoplay: false,
    currentTime: 0,
    bufferedTime: 0,
    duration: NaN,
    seeking: false,
    error: null,
    ended: false,
    muted: false,
    volume: 1,
    paused: true,
    fullscreen: false,
    rebuffering: false,

    play: function() {this.api('play');},
    togglePlay: function() {this.api('toggle-play');},
    pause: function() {this.api('pause');},
    seek: function(time) {this.api('seek', time);},
    load: function(id) {this.api('load', id);},
    setMuted: function(muted) {this.api('muted', muted);},
    toggleMuted: function() {this.api('toggle-muted');},
    setVolume: function(volume) {this.api('volume', volume);},
    setFullscreen: function(fullscreen) {this.api('fullscreen', fullscreen);},
    watchOnSite: function(muted) {this.api('watch-on-site');},

    api: function(command, arg)
    {
        if(typeof arg !== 'undefined') command += '=' + arg;
        this._send(command);
    },

    create: function(element, options)
    {
        element = DM.$(element);
        if (!element || element.nodeType != 1)
            throw new Error("Invalid first argument sent to DM.player(), requires a HTML element or element id: " + element);
        if (!options || typeof options != 'object')
            throw new Error("Missing `options' parameter for DM.player()");

        options = DM.copy(options,
        {
            width: 480,
            height: 270,
            title: "video player",
            params: {},
            events: {}
        });

        // see #5 : _domain.www should be protocol independent
        // remove protocol from existing value to preserve backward compatibility
        DM._domain.www = DM._domain.www.replace(/^https?\:/, '');
        DM.Player._PROTOCOL = (window.location && /^https?:$/.test(window.location.protocol)) ? window.location.protocol : 'http:';

        var player = document.createElement("iframe");
        DM.Array.forEach(['id', 'style', 'class'], function(attr)
        {
            var val = element.getAttribute(attr);
            if (val) player.setAttribute(attr, val);
        });
        player.setAttribute("frameborder", "0");
        player.setAttribute("allowfullscreen", "true");
        player.setAttribute("webkitallowfullscreen", "true");
        player.setAttribute("mozallowfullscreen", "true");
        player.title = "Dailymotion " + options.title;
        player.type = "text/html";
        player.width = options.width;
        player.height = options.height;
        element.parentNode.replaceChild(player, element);

        DM.copy(player, DM.Player);

        player.init(options.video, options.params);

        if (typeof options.events == "object")
        {
            for (var name in options.events)
            {
                player.addEventListener(name, options.events[name], false);
            }
        }

        return player;
    },

    init: function(video, params)
    {
        var self = this;
        DM.Player._installHandlers(function()
        {
            // ask the peer to resend the apiready event in case it missed it while installing handlers
            self._send('check');
        });
        params = typeof params == "object" ? params : {};
        params.api = DM.Player.API_MODE;
        if (DM.Player.API_MODE == 'xdcom')
        {
            params.xdcomId = DM.Player.xdcomChannel.connectionId;
        }
        if (DM._apiKey)
        {
            params.apiKey = DM._apiKey;
        }
        this.id = params.id = this.id ? this.id : DM.guid();
        this.src = DM.Player._PROTOCOL + DM._domain.www + "/embed" + (video ? "/video/" + video : "") + '?' + DM.QS.encode(params);
        if (DM.Player._INSTANCES[this.id] != this)
        {
            DM.Player._INSTANCES[this.id] = this;
            this.addEventListener('unload', function() {delete DM.Player._INSTANCES[this.id];});
        }

        this.autoplay = DM.parseBool(params.autoplay);
    },

    _installHandlers: function(initedCallback)
    {
        if (DM.Player.API_MODE !== null) return;
        if (window.postMessage)
        {
            DM.Player.API_MODE = "postMessage";

            var handler = function(e)
            {
                if (!e.origin || e.origin.indexOf(DM.Player._PROTOCOL + DM._domain.www) !== 0) return;
                var event = DM.QS.decode(e.data);
                if (!event.id || !event.event) return;
                var player = DM.$(event.id);
                player._recvEvent(event);
            };
            if (window.addEventListener) window.addEventListener("message", handler, false);
            else if (window.attachEvent) window.attachEvent("onmessage", handler);
        }
        else if(DM.XDCom.capable())
        {
            DM.Player.API_MODE = "xdcom";
            DM.Player.xdcomChannel = DM.XDCom.createChannel(function(data)
            {
                var event = DM.QS.decode(data);
                if (!event.id || !event.event) return;
                var player = DM.$(event.id);
                player._recvEvent(event);
            }, initedCallback);
        }

        if (DM.Player.API_MODE === null)
        {
            DM.Player.API_MODE = "fragment";
            return; // no yet ready

            if (!DM.Player._INTERVAL_ID)
            {
                DM.Player._INTERVAL_ID = setInterval(function()
                {
                    for (var id in DM.Player._INSTANCES)
                    {
                        var player = DM.Player._INSTANCES[id], pos;
                        if ((pos = player.src.indexOf('#')) != -1)
                        {
                            var event = DM.QS.decode(src.substring(pos + 1));
                            player.src = src.substring(0, pos); // reset fragment
                            if (event.id && event.event) player._recvEvent(event);
                        }
                    }
                    if (DM.Player._INSTANCES.length === 0) clearInterval(DM.Player._INTERVAL_ID);
                }, 0);
            }
        }
    },

    _send: function(command) // fragment API mode fallback
    {
        switch (DM.Player.API_MODE)
        {
            case 'postMessage':
                this.contentWindow.postMessage(command, DM.Player._PROTOCOL + DM._domain.www);
                break;

            case 'xdcom':
                DM.Player.xdcomChannel.postMessage(this.id, command);
                break;

            case 'fragment':
                var src = this.src, pos;
                if ((pos = src.indexOf('#')) != -1) src = src.substring(0, pos);
                this.src = src + '#' + command;
                break;
        }
    },

    _dispatch: document.createEvent ? function(type)
    {
        var e = document.createEvent("HTMLEvents");
        e.initEvent(type, true, true);
        this.dispatchEvent(e);
    }
    : function(type) // IE compat
    {
        if ('on' + type in this)
        {
            e = document.createEventObject();
            this.fireEvent('on' + type, e);
        }
        else if (type in this.EVENT_HANDLERS)
        {
            var e = {type: type, target: this};
            DM.Array.forEach(this.EVENT_HANDLERS[type], function(handler)
            {
                handler(e);
            });
        }
    },

    _recvEvent: function(event)
    {
        switch (event.event)
        {
            case 'apiready': if (this.apiReady) return /* dispatch only once */; else this.apiReady = true; break;
            case 'loadedmetadata': this.error = null; this.ended = false; break;
            case 'timeupdate': // no break statement here
            case 'ad_timeupdate': this.currentTime = parseFloat(event.time); break;
            case 'progress': this.bufferedTime = parseFloat(event.time); break;
            case 'durationchange': this.duration = parseFloat(event.duration); break;
            case 'seeking': this.seeking = true; this.currentTime = parseFloat(event.time); break;
            case 'seeked': this.seeking = false; this.currentTime = parseFloat(event.time); break;
            case 'fullscreenchange': this.fullscreen = DM.parseBool(event.fullscreen); break;
            case 'volumechange': this.volume = parseFloat(event.volume); this.muted = DM.parseBool(event.muted); break;
            case 'ad_start':
            case 'ad_play':
            case 'playing':
            case 'play': this.paused = false; break;
            case 'ended': this.ended = true; break; // no break, also set paused
            case 'ad_pause':
            case 'ad_end':
            case 'ended':
            case 'pause': this.paused = true; break;
            case 'error': this.error = {code: event.code, title: event.title, message: event.message}; break;
            case 'rebuffer': this.rebuffering = DM.parseBool(event.rebuffering); break;
        }

        this._dispatch(event.event);
    },

    // IE compat (DM.copy won't set this if already defined)
    addEventListener: function(name, callback, capture)
    {
        if ('on' + name in this && this.attachEvent)
        {
            this.attachEvent("on" + name, callback, capture);
        }
        else
        {
            if (!(name in this.EVENT_HANDLERS))
            {
                this.EVENT_HANDLERS[name] = [];
            }
            this.EVENT_HANDLERS[name].push(callback);
        }
    }
});
<|endoftext|>


<commit_before>var path = require('path');
var express = require('express');
var extend = require('extend');
var configReader = require('./gyConfig.js');

var defaultsGamayun = {
   configFilePath: path.join(__dirname, 'gamayun.conf')
};

module.exports = function(optionsGamayun){
   var app = express();

   var options = extend({}, defaultsGamayun, optionsGamayun);
   var setupGamayun = configReader(options);

   return app;
};<commit_msg>read Autumn exports from the designated paths<commit_after>var path = require('path');
var express = require('express');
var extend = require('extend');
var configReader = require('./gyConfig.js');

var defaultsGamayun = {
   configFilePath: path.join(__dirname, 'gamayun.conf')
};

module.exports = function(optionsGamayun){
   var app = express();

   var options = extend({}, defaultsGamayun, optionsGamayun);
   var setupGamayun = configReader(options);

   setupGamayun.autumnUsers = setupGamayun.autumnUsers.map(function(nextUser){
      var fullPath = path.resolve(__dirname, nextUser.path);
      (function(){
         try {
            nextUser.autumn = require(fullPath);
         } catch(e) {
            nextUser = null;
         }
      })();
   }).filter(function(nextAutumnUserDef){
      return nextAutumnUserDef !== null;
   });

   return app;
};<|endoftext|>


<commit_before>var http 	= 	require('http'),
	https 	= 	require('https'),
	url 	= 	require('url'),
	request = 	require('request'),
	Q 		=	require('q'),
	cheerio = 	require('cheerio');

Array.prototype.uniq = function() {
   var uniq = {}, arr = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(uniq.hasOwnProperty(this[i])) {
         continue;
      }
      arr.push(this[i]);
      uniq[this[i]] = 1;
   }
   return arr;
}

function getProtocol(url) {
	if(url.slice(0,5) == 'https') return https
	if(url.slice(0,4) == 'http') return http
}

module.exports.Scraper = function() {
	var _this = this;
	this.clean = function(candidates) {
		var clean = [];
		for(var i = 0; i < candidates.length; i++) {
			if(	_this.httpmatch(candidates[i]) &&
			(	_this.extmatch(candidates[i]) == 'jpg' 	||
				_this.extmatch(candidates[i]) == 'png' 	||
				_this.extmatch(candidates[i]) == 'gif'	))
			{
				clean.push(_this.httpmatch(candidates[i]));
			}
		}
		return clean.uniq();
	}
	this.extmatch = function(path) {
		if(!path) return null;
		var extregexp = new RegExp(/.+\.([^?]+)(\?|$)/);
		return path && path.match(extregexp) && path.match(extregexp)[1];
	}
	this.getImages = function(url) {
		var promise = Q.defer();
		var candidates = [];
		if(_this.clean([url]).length > 0){
			promise.resolve([url]);
			return promise.promise;
		}
		request(url, function(error, response, html) {
			if(!error && response.statusCode == 200) {
				var $ = cheerio.load(html);
				var imagetags = $('img');
				var metatags = $('meta');
				for(var i=0; i<imagetags.length; i++){
					candidates.push(imagetags[i].attribs.src);
				}
				for(var i=0; i<metatags.length; i++){
					candidates.push(metatags[i].attribs.content);
				}
				candidates = _this.clean(candidates);
				promise.resolve(candidates);
			} else {
				promise.reject(new Error('Bad Request'));
			}
		});
		return promise.promise;
	}
	this.httpmatch = function(url) {
		var httpregexp = new RegExp(/^(\/\/|f|ht)tps?:\/\//i);
		if(url && url.indexOf("//") == 0) { return 'http:' + url;}
		if(url && url.match(httpregexp) && url.match(httpregexp)[0]) return url;
	}
	this.judge = function(finalists) {
		var promise = Q.defer();
		var medalists = [];
		for(var i=0; i<finalists.length; i++) {
			medalists.push(finalists[i]);
		}
		promise.resolve(medalists);
		return promise.promise;
	}
	this.minSize = function(finalist) {
		if(finalist.size > 1000) {
			return true;
		}
		return false;
	}
	this.narrow = function(candidates) {
		var promise = Q.defer();
		var finalists = [];

		var seen = 0;
		for(var i=0; i<candidates.length; i++) {
			request({
				url: candidates[i],
				method: 'HEAD'
			}, function(error, response, body) {
				finalists.push({
					url: response.request.href,
					size: response.headers['content-length']
				});
				if(++seen == candidates.length) {
					finalists = finalists.filter(_this.minSize);
					finalists.sort(function(a,b) {
						return b.size - a.size;
					});
					for(var j= 0; j<finalists.length; j++) {
						finalists[j] = finalists[j].url;
					}
					promise.resolve(finalists);
				}
			});

		}
		return promise.promise;
	}
	this.scrape = function(address) {
		var promise = Q.defer();
		if(address) {
			_this.getImages(address).then(function(candidates) {
				_this.narrow(candidates).then(function(finalists) {
					_this.judge(finalists).then(function(medalists) {
						promise.resolve(medalists);
					});
				});
			});
		} else {
			promise.reject('Scraper cant scrape nil bro. Give me a url in the params.');
		}
		return promise.promise;
	}
}<commit_msg>added parse method for keyword generation from url<commit_after>var http 	= 	require('http'),
	https 	= 	require('https'),
	url 	= 	require('url'),
	request = 	require('request'),
	Q 		=	require('q'),
	cheerio = 	require('cheerio');

Array.prototype.uniq = function() {
   var uniq = {}, arr = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(uniq.hasOwnProperty(this[i])) {
         continue;
      }
      arr.push(this[i]);
      uniq[this[i]] = 1;
   }
   return arr;
};
Array.prototype.diff = function(list) {
	var ret = [];
	for(i in this) {
		if(list.indexOf( this[i] ) > -1) {
			ret.push(this[i]);
		}
	}
	return ret;
};

function getProtocol(url) {
	if(url.slice(0,5) == 'https') return https
	if(url.slice(0,4) == 'http') return http
};

module.exports.Scraper = function() {
	var _this = this;
	this.clean = function(candidates) {
		var clean = [];
		for(var i = 0; i < candidates.length; i++) {
			if(	_this.httpmatch(candidates[i]) &&
			(	_this.extmatch(candidates[i]) == 'jpg' 	||
				_this.extmatch(candidates[i]) == 'png' 	||
				_this.extmatch(candidates[i]) == 'gif'	))
			{
				clean.push(_this.httpmatch(candidates[i]));
			}
		}
		return clean.uniq();
	}
	this.extmatch = function(path) {
		if(!path) return null;
		var extregexp = new RegExp(/.+\.([^?]+)(\?|$)/);
		return path && path.match(extregexp) && path.match(extregexp)[1];
	}
	this.getImages = function(url) {
		var promise = Q.defer();
		var candidates = [];
		if(_this.clean([url]).length > 0){
			promise.resolve([url]);
			return promise.promise;
		}
		request(url, function(error, response, html) {
			if(!error && response.statusCode == 200) {
				var $ = cheerio.load(html);
				var imagetags = $('img');
				var metatags = $('meta');
				for(var i=0; i<imagetags.length; i++){
					candidates.push(imagetags[i].attribs.src);
				}
				for(var i=0; i<metatags.length; i++){
					candidates.push(metatags[i].attribs.content);
				}
				candidates = _this.clean(candidates);
				promise.resolve(candidates);
			} else {
				promise.reject(new Error('Bad Request'));
			}
		});
		return promise.promise;
	}
	this.httpmatch = function(url) {
		var httpregexp = new RegExp(/^(\/\/|f|ht)tps?:\/\//i);
		if(url && url.indexOf("//") == 0) { return 'http:' + url;}
		if(url && url.match(httpregexp) && url.match(httpregexp)[0]) return url;
	}
	this.judge = function(finalists, address) {
		var promise = Q.defer();
		var medalists = [];
		var keywords = _this.parse(address);
		for(var i=0; i<finalists.length; i++) {
			medalists.push(finalists[i]);
		}
		promise.resolve(medalists);
		return promise.promise;
	}
	this.minSize = function(finalist) {
		if(finalist.size > 1000) {
			return true;
		}
		return false;
	}
	this.narrow = function(candidates) {
		var promise = Q.defer();
		var finalists = [];

		var seen = 0;
		for(var i=0; i<candidates.length; i++) {
			request({
				url: candidates[i],
				method: 'HEAD'
			}, function(error, response, body) {
				finalists.push({
					url: response.request.href,
					size: response.headers['content-length']
				});
				if(++seen == candidates.length) {
					finalists = finalists.filter(_this.minSize);
					finalists.sort(function(a,b) {
						return b.size - a.size;
					});
					for(var j= 0; j<finalists.length; j++) {
						finalists[j] = finalists[j].url;
					}
					promise.resolve(finalists);
				}
			});

		}
		return promise.promise;
	}
	this.parse = function(url) {
		// break the url into as many distinct words as possible.
		var wordreg = new RegExp(/^(http|https|www|com)/);
		var words = url.split('/').filter(function(el){return( el != "")});
		var parsed = [];
		for(var i=0; i<words.length; i++) {
			if(!words[i].match(wordreg)){
				var subwords = words[i].split(".");
				if(subwords.length > 0) {
					for(var j=0; j<subwords.length; j++) {
						if(!subwords[j].match(wordreg)) {
							parsed.push(subwords[j]);
						}
					}
				} else {
					parsed.push(words[i]);
				}
			}
		}
		return parsed;
	}
	this.scrape = function(address) {
		var promise = Q.defer();
		if(address) {
			_this.getImages(address).then(function(candidates) {
				_this.narrow(candidates).then(function(finalists) {
					_this.judge(finalists, address).then(function(medalists) {
						promise.resolve(medalists);
					});
				});
			});
		} else {
			promise.reject('Scraper cant scrape nil bro. Give me a url in the params.');
		}
		return promise.promise;
	}
};<|endoftext|>


<commit_before>import EventEmitter from 'eventemitter3';
import uuid from 'node-uuid';

import { CALL, FORK, REDUCE, CANCEL, SELECT } from './CommandTypes';

const EMIT = 'ACTIONIZER.EMITTER.NOTIFY';

export default function(initialState, notify = (emit) => { emit(); }) {
  let state = initialState;
  const emitter = new EventEmitter();
  const processes = {};

  const subscribe = (listener) => {
    emitter.on(EMIT, listener);
    return () => { emitter.removeListener(EMIT, listener); };
  };

  const emit = () => {
    emitter.emit(EMIT, state);
  };

  const getState = () => {
    return state;
  };

  const setState = (nextState) => {
    if (state !== nextState) {
      state = nextState;
      notify(emit);
    }
    return state;
  };

  const openProcess = (action) => {
    const actionId = uuid.v4();
    processes[actionId] = action;
    return actionId;
  };

  const closeProcess = (actionId) => {
    if (!processes[actionId]) { return; }
    processes[actionId].return();
    delete processes[actionId];
  };

  const dispatch = (action) => {
    const actionId = openProcess(action);

    const step = (result) => {
      const { done, value } = result;

      if (done) { return closeProcess(actionId); }

      switch (value.type) {
        case SELECT:
          step(action.next(value.selector(state)));
          break;
        case REDUCE:
          step(action.next(setState(value.reducer(state, ...value.args))));
          break;
        case CALL:
          value
            .fn(...value.args)
            .then((val) => { step(action.next(val)); })
            .catch((e) => { step(action.throw(e)); });
          break;
        case FORK:
          step(action.next(dispatch(value.actionCreator(...value.args))));
          break;
        case CANCEL:
          closeProcess(value.actionId);
          step(action.next());
          break;
        default:
          step(action.throw(new Error('Received unknown command.')));
          break;
      }
    };

    step(action.next());
    return actionId;
  };

  return {
    subscribe,
    getState,
    dispatch
  };
};
<commit_msg>Remove semicolon<commit_after>import EventEmitter from 'eventemitter3';
import uuid from 'node-uuid';

import { CALL, FORK, REDUCE, CANCEL, SELECT } from './CommandTypes';

const EMIT = 'ACTIONIZER.EMITTER.NOTIFY';

export default function(initialState, notify = (emit) => { emit(); }) {
  let state = initialState;
  const emitter = new EventEmitter();
  const processes = {};

  const subscribe = (listener) => {
    emitter.on(EMIT, listener);
    return () => { emitter.removeListener(EMIT, listener); };
  };

  const emit = () => {
    emitter.emit(EMIT, state);
  };

  const getState = () => {
    return state;
  };

  const setState = (nextState) => {
    if (state !== nextState) {
      state = nextState;
      notify(emit);
    }
    return state;
  };

  const openProcess = (action) => {
    const actionId = uuid.v4();
    processes[actionId] = action;
    return actionId;
  };

  const closeProcess = (actionId) => {
    if (!processes[actionId]) { return; }
    processes[actionId].return();
    delete processes[actionId];
  };

  const dispatch = (action) => {
    const actionId = openProcess(action);

    const step = (result) => {
      const { done, value } = result;

      if (done) { return closeProcess(actionId); }

      switch (value.type) {
        case SELECT:
          step(action.next(value.selector(state)));
          break;
        case REDUCE:
          step(action.next(setState(value.reducer(state, ...value.args))));
          break;
        case CALL:
          value
            .fn(...value.args)
            .then((val) => { step(action.next(val)); })
            .catch((e) => { step(action.throw(e)); });
          break;
        case FORK:
          step(action.next(dispatch(value.actionCreator(...value.args))));
          break;
        case CANCEL:
          closeProcess(value.actionId);
          step(action.next());
          break;
        default:
          step(action.throw(new Error('Received unknown command.')));
          break;
      }
    };

    step(action.next());
    return actionId;
  };

  return {
    subscribe,
    getState,
    dispatch
  };
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 modern JavaScript (ES5)
"use strict"

// Returns Address for Polling location from polling location servlet.
function listPollingLocations() {
  const userAddress = document.getElementById("polling-location-input").elements[0].value;
  fetch(`/pollingLocation?address=${encodeURIComponent(userAddress).replace(/ /g, "%20")}`).then(response => response.json()).then((pollingAddress) => {
    const pollingAddressElement = document.getElementById('poll-address');
    for (const fields in pollingAddress.address){
      pollingAddressElement.innerHTML += pollingAddress.address[fields] + "
";
    }
  }).catch(() => {
    document.getElementById('poll-address').innerText =
        "Polling location not found. Please verify that you have entered a valid address.";
  });
}
<commit_msg>Resolving comments<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 modern JavaScript (ES5)
"use strict"

// Returns Address for Polling location from polling location servlet.
function listPollingLocations() {
  const userAddress = document.getElementById("polling-location-input").elements[0].value;
  fetch(`/pollingLocation?address=${encodeURIComponent(userAddress).replace(/ /g, "%20")}`)
      .then(response => response.json()).then((pollingAddress) => {
    const pollingAddressElement = document.getElementById('poll-address');
    for (const fields in pollingAddress.address){
      pollingAddressElement.innerHTML += pollingAddress.address[fields] + "
";
    }
  }).catch(() => {
    document.getElementById('poll-address').innerText =
        "Polling location not found. Please verify that you have entered a valid address.";
  });
}
<|endoftext|>


<commit_before>$(function() {
    $('#btn-apigen').on('click', function(e) {
        var el = $(this);

        $.get(el.attr('href'), function (data) {
            el.prev().text(data);
        })

        return false;
    });

    $('#btn-remove-profile').on('click', function(e) {
        var el = $(this),
            message = el.attr('data-message'),
            doAction = function() {
                $.ajax({
                    url: Routing.generate('oro_api_delete_profile', { id: el.attr('data-id') }),
                    type: 'DELETE',
                    success: function (data) {
                        window.location.href = Routing.generate('oro_user_index');
                    }
                });
            };

        if (!_.isUndefined(Oro.BootstrapModal)) {
            confirm = new Oro.BootstrapModal({
                title: 'Delete Confirmation',
                content: message,
                okText: 'Yes, Delete'
            });
            confirm.on('ok', doAction);
            confirm.open();
        } else if (window.confirm(message)) {
            doAction();
        }

        return false;
    });

    $('#roles-list input')
        .on('click', function() {
            var inputs = $(this).closest('.controls');

            inputs.find(':checkbox').attr('required', inputs.find(':checked').length > 0 ? null : 'required');
        })
        .triggerHandler('click');

    $('#btn-enable input').on('change', function(e) {
//        if ($(this).is(':checked')) {
//
//        }
        $('.status-enabled').toggleClass('hide');
        $('.status-disabled').toggleClass('hide');
    });
});<commit_msg>BAP-687: Delete confirmation message is not useful  - added "Cancel" button on delete modal<commit_after>$(function() {
    $('#btn-apigen').on('click', function(e) {
        var el = $(this);

        $.get(el.attr('href'), function (data) {
            el.prev().text(data);
        })

        return false;
    });

    $('#btn-remove-profile').on('click', function(e) {
        var el = $(this),
            message = el.attr('data-message'),
            doAction = function() {
                $.ajax({
                    url: Routing.generate('oro_api_delete_profile', { id: el.attr('data-id') }),
                    type: 'DELETE',
                    success: function (data) {
                        window.location.href = Routing.generate('oro_user_index');
                    }
                });
            };

        if (!_.isUndefined(Oro.BootstrapModal)) {
            var confirm = new Oro.BootstrapModal({
                title: 'Delete Confirmation',
                content: message,
                okText: 'Yes, Delete',
                cancelText: 'Cancel'

            });
            confirm.on('ok', doAction);
            confirm.open();
        } else if (window.confirm(message)) {
            doAction();
        }

        return false;
    });

    $('#roles-list input')
        .on('click', function() {
            var inputs = $(this).closest('.controls');

            inputs.find(':checkbox').attr('required', inputs.find(':checked').length > 0 ? null : 'required');
        })
        .triggerHandler('click');

    $('#btn-enable input').on('change', function(e) {
//        if ($(this).is(':checked')) {
//
//        }
        $('.status-enabled').toggleClass('hide');
        $('.status-disabled').toggleClass('hide');
    });
});
<|endoftext|>


<commit_before>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    // Find element with `autofocus` attribute or first form control
    var first_form_ctrl = null;
    var first_autofocus = null;
    var traverse = function(root) {
      for (var i = 0; i < root.children.length; i++) {
        var elem = root.children[i];
        if (first_form_ctrl === null && (
            elem.nodeName == 'BUTTON' ||
            elem.nodeName == 'INPUT'  ||
            elem.nodeName == 'KEYGEN' ||
            elem.nodeName == 'SELECT' ||
            elem.nodeName == 'TEXTAREA')) {
          first_form_ctrl = elem;
        }
        if (first_autofocus === null &&
            elem.getAttribute('autofocus') === '') {
          first_autofocus = elem;
        }

        if (first_form_ctrl && first_autofocus) {
          break;
        } else {
          traverse(elem);
        }
      }
    };

    traverse(this);

    if (first_autofocus) {
      first_autofocus.focus();
    } else if (first_form_ctrl) {
      first_form_ctrl.focus();
    }

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    var forms = element.getElementsByTagName('form');
    var found = -1;
    for (var i = 0; i < forms.length; i++) {
      if (forms[i].getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
        found = i;
        break;
      }
    }
    if (found !== -1) {
      addEventListenerFn(forms[found], 'click', function(event) {
        if (event.target.type == 'submit') {
          element.close(event.target.value);
        }
      });
    }
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      if (dialog) {
        var cancelEvent = document.createEvent('Event');
        cancelEvent.initEvent('cancel', false, true);
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

  return dialogPolyfill;
})();
<commit_msg>forms now propagate custom events for dialog<commit_after>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    // Find element with `autofocus` attribute or first form control
    var first_form_ctrl = null;
    var first_autofocus = null;
    var findElementToFocus = function(root) {
      for (var i = 0; i < root.children.length; i++) {
        var elem = root.children[i];
        if (first_form_ctrl === null &&
            elem.disabled === false && (
            elem.nodeName == 'BUTTON' ||
            elem.nodeName == 'INPUT'  ||
            elem.nodeName == 'KEYGEN' ||
            elem.nodeName == 'SELECT' ||
            elem.nodeName == 'TEXTAREA')) {
          first_form_ctrl = elem;
        }
        if (first_autofocus === null &&
            elem.getAttribute('autofocus') === '') {
          first_autofocus = elem;
          break;
        }
        findElementToFocus(elem);
      }
    };

    findElementToFocus(this);

    if (first_autofocus) {
      first_autofocus.focus();
    } else if (first_form_ctrl) {
      first_form_ctrl.focus();
    }

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    addEventListenerFn(element, 'dialog_submit', function(e) {
      element.close(e.detail.target.value);
      e.preventDefault();
      e.stopPropagation();
    });
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
    addEventListenerFn(window, 'load', function() {
      var forms = document.getElementsByTagName('form');
      Array.prototype.forEach.call(forms, function(form) {
        if (form.getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
          addEventListenerFn(form, 'click', function(e) {
            if (e.target.type == 'submit') {
              var event;
              if (CustomEvent) {
                event = new CustomEvent('dialog_submit', {
                  bubbles:  true,
                  detail:   { target: e.target }
                });
              } else {
                event = document.createEvent('HTMLEvents');
                event.initEvent('dialog_submit', true, true);
                event.detail = {target: e.target};
              }
              this.dispatchEvent(event);
              e.preventDefault();
            }
          });
        }
      });
    })
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      var cancelEvent;
      if (dialog) {
        if (CustomEvent) {
          cancelEvent = new CustomEvent('cancel', {
            bubbles:    false
          });
        } else {
          cancelEvent = document.createEvent('HTMLEvents');
          cancelEvent.initEvent('cancel', false, true);
        }
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

  return dialogPolyfill;
})();
<|endoftext|>


<commit_before>'use strict';

var  ensureDb = require('dbjs/valid-dbjs')
  , memoize = require('memoizee');

module.exports = memoize(function (db/* options */) {
	// ensure db
	ensureDb(db);

	var catalogs = [];
	// all enums
	var enums = db.StringLine.extensions.toArray().filter(function (extension) {
		return extension.meta && extension.members;
	}).map(function (extension) {
		var catalogItem = { name: extension.__id__ };
		catalogItem.options = extension.members.toArray().map(function (option) {
			return { name: option, label: extension.meta[option].label };
		});
		return catalogItem;
	});
	[].push.apply(catalogs, enums);

	// services
	var services = db.BusinessProcess.extensions.toArray().map(function (bp) {
		return { name: bp.__id__, label: bp.label };
	});
	catalogs.push({ services: services });

	// registrations
	var registrations = db.Registration.extensions.toArray().map(function (reg) {
		return { name: reg.__id__, label: reg.label };
	});
	catalogs.push({ registrations: registrations });

	// documents
	var documents = db.Document.extensions.toArray().map(function (doc) {
		return { name: doc.__id__, label: doc.label };
	});
	catalogs.push({ documents: documents });

	// costs
	var costs = db.Cost.extensions.toArray().map(function (cost) {
		return { name: cost.__id__, label: cost.label };
	});
	catalogs.push({ costs: costs });

	// institutions
	var institutions = db.Institution.instances.toArray().map(function (institution) {
		return { name: institution.__id__, label: institution.name };
	});
	catalogs.push({ institutions: institutions });

	return catalogs;

}, { length: 0 });
<commit_msg>--lint<commit_after>'use strict';

var  ensureDb = require('dbjs/valid-dbjs')
  , memoize = require('memoizee');

module.exports = memoize(function (db/* options */) {
	// ensure db
	ensureDb(db);

	var catalogs = [];
	// all enums
	var enums = db.StringLine.extensions.toArray().filter(function (extension) {
		return extension.meta && extension.members;
	}).map(function (extension) {
		var catalogItem = { name: extension.__id__ };
		catalogItem.options = extension.members.toArray().map(function (option) {
			return { name: option, label: extension.meta[option].label };
		});
		return catalogItem;
	});
	[].push.apply(catalogs, enums);

	// services
	var services = db.BusinessProcess.extensions.toArray().map(function (bp) {
		return { name: bp.__id__, label: bp.label };
	});
	catalogs.push({ services: services });

	// registrations
	var registrations = db.Registration.extensions.toArray().map(function (reg) {
		return { name: reg.__id__, label: reg.label };
	});
	catalogs.push({ registrations: registrations });

	// documents
	var documents = db.Document.extensions.toArray().map(function (doc) {
		return { name: doc.__id__, label: doc.label };
	});
	catalogs.push({ documents: documents });

	// costs
	var costs = db.Cost.extensions.toArray().map(function (cost) {
		return { name: cost.__id__, label: cost.label };
	});
	catalogs.push({ costs: costs });

	// institutions
	var institutions = db.Institution.instances.toArray().map(function (institution) {
		return { name: institution.__id__, label: institution.name };
	});
	catalogs.push({ institutions: institutions });

	return catalogs;

}, { length: 0 });
<|endoftext|>