<commit_before>/**
 * OpenSlides agenda functions
 *
 * :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
 * :license: GNU GPL, see LICENSE for more details.
 */

function hideLine(object) {
    if (object == []) {
        return;
    }
    object.hide();
    id = object.children('td.tabledrag-hide').children('input.menu-mlid').attr('value');
    $('.menu-plid[value=\'' + id + '\']').parent().parent().each(function() {
        hideLine($(this));
    });
}

function hideClosedSlides(hide) {
    if (hide) {
        $('#hidelink').attr('title', 'show');
        $('#hidelink').removeClass('hide').addClass('show');
        $('.close_link.closed').parent().parent().each(function() {
            hideLine($(this));
        });
        hidden = $('#menu-overview tr:hidden').size();
        $('#hiddencount').text(', davon ' + hidden + ' verborgen.');
    } else {
        $('#menu-overview tr').show();
        $('#hidelink').attr('title','hide');
        $('#hidelink').removeClass('show').addClass('hide');
        $('#hiddencount').text('');
    }
    return false;
}

$(function() {
    $('.close_link').click(function(event) {
        event.preventDefault();
        slide = $(this);
        $.ajax({
            type: 'GET',
            url: slide.attr('href'),
            dataType: 'json',
            success: function(data) {
                if (data.closed) {
                    newclass = 'closed';
                } else {
                    newclass = 'open';
                }
                slide.removeClass('closed open').addClass(newclass);
                slide.attr('href', data.link);
            }
        });
    });
    // filter to show/hide closed items
    $('#hide_closed_items').click(function(event) {
        // show all items
        if ($.cookie('Slide.HideClosed') == 1) {
            $.cookie('Slide.HideClosed', 0);
            hideClosedSlides(false);
            $('#hide_closed_items').attr('checked', false);
        }
        else { // hide closed items
            $.cookie('Slide.HideClosed', 1);
            hideClosedSlides(true);
            $('#hide_closed_items').attr('checked', true);
        }
    });
    if ($.cookie('Slide.HideClosed') === null) {
        $('#hide_closed_items').attr('checked', false);
        $.cookie('Slide.HideClosed', 0);
    } else if ($.cookie('Slide.HideClosed') == 1) {
        hideClosedSlides(true);
        $('#hide_closed_items').attr('checked', true);
    }
});
<commit_msg>fix close and unclose link via ajax<commit_after>/**
 * OpenSlides agenda functions
 *
 * :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
 * :license: GNU GPL, see LICENSE for more details.
 */

function hideLine(object) {
    if (object == []) {
        return;
    }
    object.hide();
    id = object.children('td.tabledrag-hide').children('input.menu-mlid').attr('value');
    $('.menu-plid[value=\'' + id + '\']').parent().parent().each(function() {
        hideLine($(this));
    });
}

function hideClosedSlides(hide) {
    if (hide) {
        $('#hidelink').attr('title', 'show');
        $('#hidelink').removeClass('hide').addClass('show');
        $('.close_link.closed').parent().parent().each(function() {
            hideLine($(this));
        });
        hidden = $('#menu-overview tr:hidden').size();
        $('#hiddencount').text(', davon ' + hidden + ' verborgen.');
    } else {
        $('#menu-overview tr').show();
        $('#hidelink').attr('title','hide');
        $('#hidelink').removeClass('show').addClass('hide');
        $('#hiddencount').text('');
    }
    return false;
}

$(function() {
    $('.close_link a').click(function(event) {
        event.preventDefault();
        slide = $(this);
        $.ajax({
            type: 'GET',
            url: slide.attr('href'),
            dataType: 'json',
            success: function(data) {
                if (data.closed) {
                    newclass = 'closed';
                } else {
                    newclass = 'open';
                }
                slide.parent().removeClass('closed open').addClass(newclass);
                slide.attr('href', data.link);
            }
        });
    });
    // filter to show/hide closed items
    $('#hide_closed_items').click(function(event) {
        // show all items
        if ($.cookie('Slide.HideClosed') == 1) {
            $.cookie('Slide.HideClosed', 0);
            hideClosedSlides(false);
            $('#hide_closed_items').attr('checked', false);
        }
        else { // hide closed items
            $.cookie('Slide.HideClosed', 1);
            hideClosedSlides(true);
            $('#hide_closed_items').attr('checked', true);
        }
    });
    if ($.cookie('Slide.HideClosed') === null) {
        $('#hide_closed_items').attr('checked', false);
        $.cookie('Slide.HideClosed', 0);
    } else if ($.cookie('Slide.HideClosed') == 1) {
        hideClosedSlides(true);
        $('#hide_closed_items').attr('checked', true);
    }
});
<|endoftext|>


<commit_before>/**
 * Retrofit legacy code to function as Backbone.Model subclasses.
 */

var Backbone_Retrofit = {};

/**
 * Modify legacy classes to serve as Backbone.Model subclasses.
 *
 * @param object container Container for classes being modified.
 *
 * @param array klasses Class names within container to modify.
 *
 * @param object base Base class to .extend().
 *
 * @return void
 */

Backbone_Retrofit.mod_classes = function ( container, klasses, base ) {

  // Mutation functions to run on legacy classes.

  var mutators = [

    /**
     * Assign return value of mod_class() to the original class's slot in
     * container.
     *
     * @param object container Container for classes being modified.
     *
     * @param object klass Name of class within container to modify.
     *
     * @return void
     */

    function ( container, klass ) {

      container[ klass ] = Backbone_Retrofit.mod_class(

        container[ klass ], base

      );

    },

    /**
     * JMMDEBUG
     */

    function ( container, klass ) {

      Object.keys( container[ klass ].prototype.defaults ).forEach(

        function( key, prop ) {

          prop = container[ klass ].prototype.defaults[ key ];

          if ( prop && prop.backbone ) {

            container[ klass ].prototype.defaults[ key ] =

              prop.backbone.prototype;

          }
          // if

        }

      );
      // forEach

    }

  ];

  // Run each mutator fucntion for each input class.

  mutators.forEach( function ( mutator ) {

    klasses.forEach( function ( klass ) {

      mutator( container, klass );

    } );

  } );

};

/**
 * Modify a legacy class to serve as a Backbone.Model subclass.
 *
 * @param object klass Legacy class.
 *
 * @param object base Base class to call .extend() on.
 *
 * @return object Modified klass.
 */

Backbone_Retrofit.mod_class = function ( klass, base ) {

  // Separate attrs and methods.

  var backbone_proto = { defaults : {} };

  // backbone_proto | backbone_proto.defaults

  var collection;

  // Assign each klass.prototype member to the appropriate collection

  Object.keys( klass.prototype ).forEach( function ( prop ) {

    var value = klass.prototype[ prop ];

    collection = value instanceof Function ?

      backbone_proto :

      backbone_proto.defaults;

    collection[ prop ] = value;

  } );

  if ( klass.prototype.parent && klass.prototype.parent.backbone ) {

    klass.prototype.parent = klass.prototype.parent.backbone.prototype;

  }
  // if

  if ( klass.prototype.hasOwnProperty( 'constructor' ) ) {

    // Copy legacy class constructor to Backbone.Model.initialize.

    backbone_proto.initialize = klass.prototype.constructor;

    // Copy parent class defaults to current class.

    if ( klass.prototype.parent && klass.prototype.parent.defaults ) {

      backbone_proto.defaults = _.defaults(

        backbone_proto.defaults,

        klass.prototype.parent.defaults

      );

    }
    // if

  }
  // if

  var old_klass = klass;

  klass = base.extend( backbone_proto );

  old_klass.prototype.backbone = klass;

  // Properties that may be used in legacy classes and are special-cased by
  // Backbone (treated as regular props not attrs)

  var special_props = [ 'id' ];

  // Prevent special props from being treated as attrs with getters / setters.

  special_props.forEach( function ( prop ) {

    delete klass.prototype[ prop ];

  } );

  // Create getters and setters for legacy props that will be treated as attrs.

  Object.keys( backbone_proto.defaults ).forEach( function ( key ) {

    Object.defineProperty( klass.prototype, key, {

      get : Backbone_Retrofit.get_set( 'get', key ),

      set : Backbone_Retrofit.get_set( 'set', key )

    } );

  } );

  return klass;

};
// mod_class

/**
 * Manufacture a getter|setter function for an attr.
 *
 * @param string meth get|set
 *
 * @param string key Attr name
 *
 * @return function getter|setter
 */

Backbone_Retrofit.get_set = function ( meth, key ) {

  var args = Array.prototype.slice.call( arguments, 1 );

  return function () {

    return base.prototype[ meth ].apply(

      this,

      args.concat( Array.prototype.slice.call( arguments ) )

    );

  };

};
// get_set
<commit_msg>Reorganization and other changes.<commit_after>/**
 * Retrofit legacy code to function as Backbone.Model subclasses.
 */

var Backbone_Retrofit = {};

/**
 * Modify legacy classes to serve as Backbone.Model subclasses.
 *
 * @param object container Container for classes being modified.
 *
 * @param array klasses Class names within container to modify.
 *
 * @param object base Base class to .extend().
 *
 * @return void
 */

Backbone_Retrofit.retrofit_classes = function ( container, klasses, base ) {

  // Retrofitter functions to run on legacy classes.

  var retrofitters = [

    this.retrofit_class,

    this.resync_protos

  ];
  // retrofitters

  // Run each retrofitter function for each input class.

  retrofitters.forEach( function ( retrofitter ) {

    klasses.forEach( function ( klass ) {

      retrofitter( container, klass, base );

    } );

  } );

};
// retrofit_classes

/**
 * Modify a legacy class to serve as a Backbone.Model subclass.
 *
 * @param object container Container for classes being modified.
 *
 * @param object klass Legacy class.
 *
 * @param object base Base class to call .extend() on.
 *
 * @return object Modified klass.
 */

Backbone_Retrofit.retrofit_class = function ( container, klass, base ) {

  var klass_name = klass;

  klass = container[ klass ];

  // Separate attrs and methods.

  var backbone_proto = { defaults : {} };

  // backbone_proto | backbone_proto.defaults

  var collection;

  // Assign each klass.prototype member to the appropriate collection

  Object.keys( klass.prototype ).forEach( function ( prop ) {

    var value = klass.prototype[ prop ];

    collection = value instanceof Function ?

      backbone_proto :

      backbone_proto.defaults;

    collection[ prop ] = value;

  } );

  // If klass has a parent property that refers to a class that has been
  // retrofitted for Backbone, update the property to refer to the retrofitted
  // class.

  if ( klass.prototype.parent && klass.prototype.parent.__backbone__ ) {

    klass.prototype.parent = klass.prototype.parent.__backbone__.prototype;

  }
  // if

  if ( klass.prototype.hasOwnProperty( 'constructor' ) ) {

    // Copy legacy class constructor to `initialize`.

    backbone_proto.initialize = klass.prototype.constructor;

    // Copy parent class defaults to current class.

    if ( klass.prototype.parent && klass.prototype.parent.defaults ) {

      backbone_proto.defaults = _.defaults(

        backbone_proto.defaults,

        klass.prototype.parent.defaults

      );

    }
    // if

  }
  // if

  var old_klass = klass;

  klass = base.extend( backbone_proto );

  // Store a reference to the Backbone-retrofitted class in the original class.

  old_klass.prototype.__backbone__ = klass;

  // Properties that may be used in legacy classes and are special-cased by
  // Backbone (treated as regular props not attrs)

  var special_props = [ 'id' ];

  // Prevent special props from being treated as attrs with getters / setters.

  special_props.forEach( function ( prop ) {

    delete klass.prototype[ prop ];

  } );

  // Create getters and setters for legacy props that will be treated as attrs.

  Object.keys( backbone_proto.defaults ).forEach( function ( key ) {

    Object.defineProperty( klass.prototype, key, {

      get : Backbone_Retrofit.get_set( base, 'get', key ),

      set : Backbone_Retrofit.get_set( base, 'set', key )

    } );

  } );

  container[ klass_name ] = klass;

};
// retrofit_class

/**
 * Adapt retrofitted classes to retrofitting of other classes.
 *
 * Now that all original classes have been retrofitted, process them again
 * to find props from their prototypes (now in prototype.defaults due to
 * retrofitting) that contain classes that have themselves been retrofitted.
 * Update the property to refer to the retrofitted version of the class.
 *
 * @param obj container Container for klasses being modified.
 *
 * @param obj klass Name of class within container to modify.
 *
 * @return void
 */

Backbone_Retrofit.resync_protos = function ( container, klass ) {

  klass = container[ klass ];

  Object.keys( klass.prototype.defaults ).forEach(

    function( key, prop ) {

      prop = klass.prototype.defaults[ key ];

      // The class has been retrofitted, and a reference to the retrofitted
      // version stored in `__backbone__`.

      if ( prop && prop.__backbone__ ) {

        klass.prototype.defaults[ key ] =

          prop.__backbone__.prototype;

      }
      // if

    }

  );
  // forEach

};
// resync_protos

/**
 * Manufacture a getter|setter function for an attr.
 *
 * @param string meth get|set
 *
 * @param string key Attr name
 *
 * @return function getter|setter
 */

Backbone_Retrofit.get_set = function ( base, meth, key ) {

  // Capture `key`

  var args = Array.prototype.slice.call( arguments, 2 );

  return function () {

    return base.prototype[ meth ].apply(

      this,

      args.concat( Array.prototype.slice.call( arguments ) )

    );

  };

};
// get_set
<|endoftext|>


<commit_before>var bot = require('./bot').sharedInstance(),
    inherit = require('./utils/inherit'),
    Context = require('./models/context'),
    rp = require('request-promise'),
    _ = require('lodash'),
    Cron = require('cron').CronJob;

/**
 * Represents the base module to every module
 * @param {Bot}     bot     The current bot instance
 * @constructor
 */
var BaseModule = function() {
    this.bot = bot;
    this.Context = Context;
    this.logger = require('./utils/logger')(this._meta.className);
};

BaseModule.prototype = {

    /**
     * Gets a random item from an array.
     * @param  {Array}      arr     Array to be processed.
     * @return {AnyObject}          A random object from [arr]
     */
    random: function(arr) {
        if(!arr) {
            return undefined;
        }
        if(!arr.length) {
            return undefined;
        }
        if(arr.length < 2) {
            return arr[0];
        }
        return arr[Math.floor(Math.random() * arr.length)];
    },

    /**
     * Sets a listener to a given regex whenever the bot is mentioned.
     * @param  {RegExp}   regex     Regex to be tested
     * @param  {Function} callback  Callback to be executed whenever a received message
     *                              matches the provided Regex. Please notice that this
     *                              function must be declared using the arrow syntax. (=>)
     * @return {Module}             This module instance.
     * @chainable
     */
    respond: function() {
        bot.inputManager.registerMentionInputHandler.apply(bot.inputManager, arguments);
        return this;
    },

    /**
     * Registers a listener to every message, including ones that does not
     * mentions the bot.
     * @param  {RegExp}     regex       Regex to be tested against every incoming
     *                                  message
     * @param  {Function}   callback    Callback to be executed whenever a message
     *                                  matches the provided regex.Please notice that this
     *                                  function must be declared using the arrow syntax. (=>)
     * @return {Module}                 This module instance.
     * @chainable
     */
    hear: function() {
        bot.inputManager.registerInputHandler.apply(bot.inputManager, arguments);
        return this;
    },

    /**
     * Checks if a given text mentions the bot.
     * @param  {String}     text     Text to be checked
     * @return {Bool}                Whether the given text mentions the bot.
     */
    mentionsBot: function() {
        return bot.inputManager.doesTextMentionBot.apply(bot.inputManager, arguments);
    },

    /**
     * Pushes a new context to a given user in a given channel. If another context
     * with the same type is present in the given channel/user combination, the older
     * context is dropped in favour of the new one. The `Promise` returned will be resolved
     * whenever the user sends a message that satisfies the context type. Notice that the
     * resulting Promise will never be rejected, but can also never be resolved.
     * @param   {String}            message         The message containing the prompt to the user.
     * @param   {User|String}       user            The user to which the prompt is directed to.
     *                                              This argument accepts both a User instance, or
     *                                              their ID used by the current Adapter to
     *                                              identify them.
     * @param   {Channel|String}    channel         The channel to which the prompt is directed to.
     *                                              This argument accepts both a Channel instance,
     *                                              or their ID used by the current Adapter to
     *                                              identify them.
     * @param   {Integer}           type            The type of context to be pushed to the user.
     *                                              These types are defined in the `Context` object,
     *                                              and have, actually, three possible values:
     *                                              1. `Context.NUMBER`: Matches any message
     *                                              compound by a sequence of one or more numbers.
     *                                              2. `Context.BOOLEAN`: Matches any message
     *                                              that represents an affirmative or negative
     *                                              value. The regular expression used to match
     *                                              the message is defined in the very same `Context`
     *                                              class.
     *                                              3. `Context.REGEX`: Matches any message that
     *                                              matches a given regular expression.
     * @param   {Regex}             [regex]         Regular expression to be used when type is
     *                                              `Context.REGEX`.
     * @return  {Promise}                           A Promise that will be resolved whenever the bot
     *                                              receives a response from the target user in the
     *                                              target channel. The resulting promise argument
     *                                              will be an `Response` object, in which
     *                                              `response.match` will represent the parsed value
     *                                              of this context. For instance, with a type of
     *                                              `BOOLEAN`, `Response.match` can either be `true`
     *                                              or `false`, representing the answer of the user.
     */
    ask: function() {
        return bot.contextManager.pushContext.apply(bot.contextManager, arguments);
    },

    /**
     * Executes an HTTP request with the given arguments. This function is a proxy
     * to the Request-Promise library. See more: https://github.com/request/request-promise
     * @return {Promise}        A Promise returned by the Request-Promise library.
     */
    http: function() {
        return rp.apply(rp, arguments);
    },

    /**
     * Searches a channel with the given name or ID, where the ID must be a identifier used by
     * the current Adapter to internally represent known channels.
     * @param {String}      nameOrId            Name or ID of the channel to be found.
     * @return {Promise}                        A promise that will be resolved whenever the channel
     *                                          is found. It will be rejected whenever the channel
     *                                          cannot be found or there's an underlying problem
     *                                          during the search process.
     */
    searchChannel: function() {
        return bot.adapter.searchChannel.apply(bot.adapter, arguments);
    },

    /**
     * Searches an user with the given name or ID, where the ID must be a identifier used by
     * the current Adapter to internally represent known channels.
     * @param {String}      nameOrId            Name or ID of the user to be found.
     * @return {Promise}                        A promise that will be resolved whenever the user
     *                                          is found. It will be rejected whenever the user
     *                                          cannot be found or there's an underlying problem
     *                                          during the search process.
     */
    searchUser: function(usernameOrId) {
        return bot.adapter.searchUser.apply(bot.adapter, arguments);
    },

    /**
     * Executes a given function with base on a given Cron schedule.
     * @param  {String|Object}   givenSchedule      A crontab pattern that defines whenever the
     *                                              associated function will be invoked. For
     *                                              further information on this pattern, please
     *                                              refer to cron(5) manpage. Another possible
     *                                              value for this argument, is an object with
     *                                              properties `minute`, `hour`, `monthDay`, `month`,
     *                                              `dayOfWeek`. Missing properties will receive `*`
     *                                              as value. Again, refering to cron(5) is essential.
     * @param  {Function}        callback           Function to be called whenever the provided
     *                                              schedule is met.
     * @return {Module}                             This very same module instance.
     * @chainable
     */
    scheduleTask: function(givenSchedule, callback) {
        givenSchedule = givenSchedule || {};
        var schedule = {
            minute: '*',
            hour: '*',
            monthDay: '*',
            month: '*',
            dayOfWeek: '*'
        };
        if(typeof schedule === 'object') {
            schedule = _.merge(schedule, givenSchedule);
            schedule = Object.keys(schedule).map(k => schedule[k]).join(' ');
        } else {
            schedule = givenSchedule;
        }

        var job = new Cron(schedule, callback, null, true);
        return this;
    }
};

/**
 * Extends an given type to this type
 * @param  {Type}   klass               Type to be extended
 * @param  {String} prettyKlassName     Name of this moduled, used by subsystems to provide
 *                                      identification facilities.
 * @return {undefined}      Nothing
 */
BaseModule.setup = function(klass, prettyKlassName) {
    inherit(klass, BaseModule);
    klass.prototype._meta = { className: prettyKlassName };
};

module.exports = BaseModule;
<commit_msg>Add mongoose abstration to BaseModel through registerModel<commit_after>var bot = require('./bot').sharedInstance(),
    inherit = require('./utils/inherit'),
    Context = require('./models/context'),
    rp = require('request-promise'),
    _ = require('lodash'),
    Cron = require('cron').CronJob,
    mongoose = require('mongoose');

/**
 * Represents the base module to every module
 * @param {Bot}     bot     The current bot instance
 * @constructor
 */
var BaseModule = function() {
    this.bot = bot;
    this.Context = Context;
    this.logger = require('./utils/logger')(this._meta.className);
};

BaseModule.prototype = {

    /**
     * Gets a random item from an array.
     * @param  {Array}      arr     Array to be processed.
     * @return {AnyObject}          A random object from [arr]
     */
    random: function(arr) {
        if(!arr) {
            return undefined;
        }
        if(!arr.length) {
            return undefined;
        }
        if(arr.length < 2) {
            return arr[0];
        }
        return arr[Math.floor(Math.random() * arr.length)];
    },

    /**
     * Sets a listener to a given regex whenever the bot is mentioned.
     * @param  {RegExp}   regex     Regex to be tested
     * @param  {Function} callback  Callback to be executed whenever a received message
     *                              matches the provided Regex. Please notice that this
     *                              function must be declared using the arrow syntax. (=>)
     * @return {Module}             This module instance.
     * @chainable
     */
    respond: function() {
        bot.inputManager.registerMentionInputHandler.apply(bot.inputManager, arguments);
        return this;
    },

    /**
     * Registers a listener to every message, including ones that does not
     * mentions the bot.
     * @param  {RegExp}     regex       Regex to be tested against every incoming
     *                                  message
     * @param  {Function}   callback    Callback to be executed whenever a message
     *                                  matches the provided regex.Please notice that this
     *                                  function must be declared using the arrow syntax. (=>)
     * @return {Module}                 This module instance.
     * @chainable
     */
    hear: function() {
        bot.inputManager.registerInputHandler.apply(bot.inputManager, arguments);
        return this;
    },

    /**
     * Checks if a given text mentions the bot.
     * @param  {String}     text     Text to be checked
     * @return {Bool}                Whether the given text mentions the bot.
     */
    mentionsBot: function() {
        return bot.inputManager.doesTextMentionBot.apply(bot.inputManager, arguments);
    },

    /**
     * Pushes a new context to a given user in a given channel. If another context
     * with the same type is present in the given channel/user combination, the older
     * context is dropped in favour of the new one. The `Promise` returned will be resolved
     * whenever the user sends a message that satisfies the context type. Notice that the
     * resulting Promise will never be rejected, but can also never be resolved.
     * @param   {String}            message         The message containing the prompt to the user.
     * @param   {User|String}       user            The user to which the prompt is directed to.
     *                                              This argument accepts both a User instance, or
     *                                              their ID used by the current Adapter to
     *                                              identify them.
     * @param   {Channel|String}    channel         The channel to which the prompt is directed to.
     *                                              This argument accepts both a Channel instance,
     *                                              or their ID used by the current Adapter to
     *                                              identify them.
     * @param   {Integer}           type            The type of context to be pushed to the user.
     *                                              These types are defined in the `Context` object,
     *                                              and have, actually, three possible values:
     *                                              1. `Context.NUMBER`: Matches any message
     *                                              compound by a sequence of one or more numbers.
     *                                              2. `Context.BOOLEAN`: Matches any message
     *                                              that represents an affirmative or negative
     *                                              value. The regular expression used to match
     *                                              the message is defined in the very same `Context`
     *                                              class.
     *                                              3. `Context.REGEX`: Matches any message that
     *                                              matches a given regular expression.
     * @param   {Regex}             [regex]         Regular expression to be used when type is
     *                                              `Context.REGEX`.
     * @return  {Promise}                           A Promise that will be resolved whenever the bot
     *                                              receives a response from the target user in the
     *                                              target channel. The resulting promise argument
     *                                              will be an `Response` object, in which
     *                                              `response.match` will represent the parsed value
     *                                              of this context. For instance, with a type of
     *                                              `BOOLEAN`, `Response.match` can either be `true`
     *                                              or `false`, representing the answer of the user.
     */
    ask: function() {
        return bot.contextManager.pushContext.apply(bot.contextManager, arguments);
    },

    /**
     * Executes an HTTP request with the given arguments. This function is a proxy
     * to the Request-Promise library. See more: https://github.com/request/request-promise
     * @return {Promise}        A Promise returned by the Request-Promise library.
     */
    http: function() {
        return rp.apply(rp, arguments);
    },

    /**
     * Searches a channel with the given name or ID, where the ID must be a identifier used by
     * the current Adapter to internally represent known channels.
     * @param {String}      nameOrId            Name or ID of the channel to be found.
     * @return {Promise}                        A promise that will be resolved whenever the channel
     *                                          is found. It will be rejected whenever the channel
     *                                          cannot be found or there's an underlying problem
     *                                          during the search process.
     */
    searchChannel: function() {
        return bot.adapter.searchChannel.apply(bot.adapter, arguments);
    },

    /**
     * Searches an user with the given name or ID, where the ID must be a identifier used by
     * the current Adapter to internally represent known channels.
     * @param {String}      nameOrId            Name or ID of the user to be found.
     * @return {Promise}                        A promise that will be resolved whenever the user
     *                                          is found. It will be rejected whenever the user
     *                                          cannot be found or there's an underlying problem
     *                                          during the search process.
     */
    searchUser: function(usernameOrId) {
        return bot.adapter.searchUser.apply(bot.adapter, arguments);
    },

    /**
     * Executes a given function with base on a given Cron schedule.
     * @param  {String|Object}   givenSchedule      A crontab pattern that defines whenever the
     *                                              associated function will be invoked. For
     *                                              further information on this pattern, please
     *                                              refer to cron(5) manpage. Another possible
     *                                              value for this argument, is an object with
     *                                              properties `minute`, `hour`, `monthDay`, `month`,
     *                                              `dayOfWeek`. Missing properties will receive `*`
     *                                              as value. Again, refering to cron(5) is essential.
     * @param  {Function}        callback           Function to be called whenever the provided
     *                                              schedule is met.
     * @return {Module}                             This very same module instance.
     * @chainable
     */
    scheduleTask: function(givenSchedule, callback) {
        givenSchedule = givenSchedule || {};
        var schedule = {
            minute: '*',
            hour: '*',
            monthDay: '*',
            month: '*',
            dayOfWeek: '*'
        };
        if(typeof schedule === 'object') {
            schedule = _.merge(schedule, givenSchedule);
            schedule = Object.keys(schedule).map(k => schedule[k]).join(' ');
        } else {
            schedule = givenSchedule;
        }

        var job = new Cron(schedule, callback, null, true);
        return this;
    },

    /**
     * Registers a new model structure for your module.
     * @param  {String} name      Name of the model to be registered. On the databbase, this name
     *                            will be prefixed with your module's file name.
     * @param  {Object} structure Your model's structure metadata. More information on
     *                            http://mongoosejs.com/docs/2.7.x/docs/model-definition.html
     * @return {Mongoose.Model}           A ready-to-use mongoose model connected to Giskard's
     *                                    database.
     */
    registerModel: function(name, structure) {
        if(!name || typeof name !== 'string') {
            throw new Error('Expected name to be a String.');
        }
        if(!structure || typeof structure !== 'object') {
            throw new Error('Expected structure to be an Object.');
        }

        structure = mongoose.Schema(structure);
        return mongoose.model(`${this._meta.moduleName}__${name}`, channelSchema);
    }
};

/**
 * Extends an given type to this type
 * @param  {Type}   klass               Type to be extended
 * @param  {String} prettyKlassName     Name of this moduled, used by subsystems to provide
 *                                      identification facilities.
 * @return {undefined}      Nothing
 */
BaseModule.setup = function(klass, prettyKlassName) {
    inherit(klass, BaseModule);
    klass.prototype._meta = { className: prettyKlassName };
};

module.exports = BaseModule;
<|endoftext|>


<commit_before>import {
	bettertypeof,
	define,
	is, isPlainObject,
	setConstructor,
	setConstructorProto,
	toString
} from "./helpers"

import {checkDefinition, checkAssertions} from "./definition"

export function BasicModel(def){
	const model = function(val = model.default) {
		model.validate(val)
		return val
	}

	initModel(model, arguments, BasicModel)
	return model
}

Object.assign(BasicModel.prototype, {
	toString(stack){
		return parseDefinition(this.definition).map(d => toString(d, stack)).join(" or ")
	},

	assertions: [],

	validate(obj, errorCollector){
		this._validate(obj, null, this.errorStack, [])
		this.unstackErrors(errorCollector)
	},

	test(obj){
		let failed,
		    initialErrorCollector = this.errorCollector
		this.errorCollector = () => { failed = true }
		new this(obj)
		this.errorCollector = initialErrorCollector
		return !failed
	},

	extend(){
		const args = [...arguments]
		const def = args
			.reduce((def, ext) => def.concat(parseDefinition(ext)), parseDefinition(this.definition))
			.filter((value, index, self) => self.indexOf(value) === index) // remove duplicates

		let assertions = [...this.assertions]
		args.forEach(arg => {
			if(is(BasicModel, arg)) assertions = assertions.concat(arg.assertions)
		})

		const submodel = new this.constructor(def)
		setConstructorProto(submodel, this.prototype)
		submodel.assertions = assertions
		submodel.errorCollector = this.errorCollector
		return submodel
	},

	assert(assertion, description = toString(assertion)){
		define(assertion, "description", description);
		this.assertions = this.assertions.concat(assertion)
		return this
	},

	defaultTo(val){
		this.default = val
		return this
	},

	errorCollector(errors){
		let e = new TypeError(errors.map(e => e.message).join('\n'))
		e.stack = e.stack.replace(/\n.*object-model(.|\n)*object-model.*/, "") // blackbox objectmodel in stacktrace
		throw e
	},

	_validate(obj, path, errorStack, callStack){
		checkDefinition(obj, this.definition, path, errorStack, callStack)
		checkAssertions(obj, this, path, errorStack)
	},

	// throw all errors collected
	unstackErrors(errorCollector){
		if (!this.errorStack.length) return
		if (!errorCollector) errorCollector = this.errorCollector
		const errors = this.errorStack.map(err => {
			if (!err.message) {
				const def = is(Array, err.expected) ? err.expected : [err.expected]
				err.message = ("expecting " + (err.path ? err.path + " to be " : "") + def.map(d => toString(d)).join(" or ")
				+ ", got " + (err.received != null ? bettertypeof(err.received) + " " : "") + toString(err.received))
			}
			return err
		})
		this.errorStack = []
		errorCollector.call(this, errors)
	}

})

BasicModel.prototype.conventionForConstant = key => key.toUpperCase() === key
BasicModel.prototype.conventionForPrivate = key => key[0] === "_"

export function initModel(model, args, constructor){
	if(args.length === 0) throw new Error("Model definition is required");
	setConstructor(model, constructor)
	model.definition = args[0]
	model.assertions = model.assertions.slice()
	define(model, "errorStack", [])
}

export function parseDefinition(def){
	if(!isPlainObject(def)){
		if(!is(Array, def)) return [def]
		if(def.length === 1) return [...def, undefined, null]
	} else {
		for(let key of Object.keys(def))
			def[key] = parseDefinition(def[key])
	}
	return def
}

export default BasicModel<commit_msg>added model.as method<commit_after>import {
	bettertypeof,
	define,
	is, isPlainObject,
	setConstructor,
	setConstructorProto,
	toString
} from "./helpers"

import {checkDefinition, checkAssertions} from "./definition"

export function BasicModel(def){
	const model = function(val = model.default) {
		model.validate(val)
		return val
	}

	initModel(model, arguments, BasicModel)
	return model
}

Object.assign(BasicModel.prototype, {
	toString(stack){
		return parseDefinition(this.definition).map(d => toString(d, stack)).join(" or ")
	},

	name: "Model",
	as(name){
		define(this, "name", name);
		return this
	},

	assertions: [],

	validate(obj, errorCollector){
		this._validate(obj, null, this.errorStack, [])
		this.unstackErrors(errorCollector)
	},

	test(obj){
		let failed,
		    initialErrorCollector = this.errorCollector
		this.errorCollector = () => { failed = true }
		new this(obj)
		this.errorCollector = initialErrorCollector
		return !failed
	},

	extend(){
		const args = [...arguments]
		const def = args
			.reduce((def, ext) => def.concat(parseDefinition(ext)), parseDefinition(this.definition))
			.filter((value, index, self) => self.indexOf(value) === index) // remove duplicates

		let assertions = [...this.assertions]
		args.forEach(arg => {
			if(is(BasicModel, arg)) assertions = assertions.concat(arg.assertions)
		})

		const submodel = new this.constructor(def)
		setConstructorProto(submodel, this.prototype)
		submodel.assertions = assertions
		submodel.errorCollector = this.errorCollector
		return submodel
	},

	assert(assertion, description = toString(assertion)){
		define(assertion, "description", description);
		this.assertions = this.assertions.concat(assertion)
		return this
	},

	defaultTo(val){
		this.default = val
		return this
	},

	errorCollector(errors){
		let e = new TypeError(errors.map(e => e.message).join('\n'))
		e.stack = e.stack.replace(/\n.*object-model(.|\n)*object-model.*/, "") // blackbox objectmodel in stacktrace
		throw e
	},

	_validate(obj, path, errorStack, callStack){
		checkDefinition(obj, this.definition, path, errorStack, callStack)
		checkAssertions(obj, this, path, errorStack)
	},

	// throw all errors collected
	unstackErrors(errorCollector){
		if (!this.errorStack.length) return
		if (!errorCollector) errorCollector = this.errorCollector
		const errors = this.errorStack.map(err => {
			if (!err.message) {
				const def = is(Array, err.expected) ? err.expected : [err.expected]
				err.message = ("expecting " + (err.path ? err.path + " to be " : "") + def.map(d => toString(d)).join(" or ")
				+ ", got " + (err.received != null ? bettertypeof(err.received) + " " : "") + toString(err.received))
			}
			return err
		})
		this.errorStack = []
		errorCollector.call(this, errors)
	}

})

BasicModel.prototype.conventionForConstant = key => key.toUpperCase() === key
BasicModel.prototype.conventionForPrivate = key => key[0] === "_"

export function initModel(model, args, constructor){
	if(args.length === 0) throw new Error("Model definition is required");
	setConstructor(model, constructor)
	model.definition = args[0]
	model.assertions = model.assertions.slice()
	define(model, "errorStack", [])
	delete model.name;
}

export function parseDefinition(def){
	if(!isPlainObject(def)){
		if(!is(Array, def)) return [def]
		if(def.length === 1) return [...def, undefined, null]
	} else {
		for(let key of Object.keys(def))
			def[key] = parseDefinition(def[key])
	}
	return def
}

export default BasicModel<|endoftext|>


<commit_before>'use strict';

module.exports = bestResults;

/* we have 2 criteria to find the best results
 1. best match per zone based on the bestOf parameter
 2. maxResults : maximal number of results
 */
function bestResults(results, bestOf, maxResults, minSimilarity) {
    var newResults = [];

    // in order to find the bestOf we will sort by similarity and take all of them for which there is nothing in a range
    // of the bestOf range

    results.sort(function (a, b) {
        return b.similarity - a.similarity;
    });

    if (minSimilarity) {
        for (var i = 0; i < results.length; i++) {
            if (results[i].similarity < minSimilarity) {
                results = results.slice(0, i);
                break;
            }
        }
    }

    if (bestOf) {
        for (var i = 0; i < results.length && newResults.length < maxResults; i++) {
            for (var j = 0; j < newResults.length; j++) {
                if (Math.abs(newResults[j].msem - results[i].msem) < (bestOf / (results[i].charge || 1))) {
                    break;
                }
            }
            if (j == newResults.length) {
                newResults.push(results[i]);
            }
        }
    } else {
        newResults = results.slice(0, maxResults);
    }

    return newResults;
};
<commit_msg>Check if maxResults is defined<commit_after>'use strict';

module.exports = bestResults;

/* we have 2 criteria to find the best results
 1. best match per zone based on the bestOf parameter
 2. maxResults : maximal number of results
 */
function bestResults(results, bestOf, maxResults, minSimilarity) {
    var newResults = [];

    // in order to find the bestOf we will sort by similarity and take all of them for which there is nothing in a range
    // of the bestOf range

    results.sort(function (a, b) {
        return b.similarity - a.similarity;
    });

    if (minSimilarity) {
        for (var i = 0; i < results.length; i++) {
            if (results[i].similarity < minSimilarity) {
                results = results.slice(0, i);
                break;
            }
        }
    }

    if (bestOf) {
        for (var i = 0; i < results.length; i++) {
            for (var j = 0; j < newResults.length; j++) {
                if (Math.abs(newResults[j].msem - results[i].msem) < (bestOf / (results[i].charge || 1))) {
                    break;
                }
            }
            if (j == newResults.length) {
                newResults.push(results[i]);
            }
        }
    } else {
        newResults=results.slice(0);
    }

    if (maxResults) {
        newResults = newResults.slice(0, maxResults);
    }

    return newResults;
};
<|endoftext|>


<commit_before>const { Knorm, KnormError } = require('@knorm/knorm');
// TODO: remove
const { camelCase } = require('lodash');

class KnormRelationsError extends KnormError {}

class KnormRelations {
  updateField(knorm) {
    const { Field } = knorm;

    class RelationsField extends Field {
      constructor(config = {}) {
        super(config);
        if (config.references) {
          this.references = config.references;
        }
      }

      static async count(options) {
        return this.query.count(options);
      }
    }

    knorm.Field = knorm.Model.Field = RelationsField;
  }

  updateModel(knorm) {
    const { Model } = knorm;

    class RelationsModel extends Model {
      static createConfig() {
        const config = super.createConfig();
        config.references = {};
        return config;
      }

      static addField(field) {
        super.addField(field);

        if (field.references) {
          const toField = field.references;
          const toModel = toField.model;
          const references = this._config.references;

          references[toModel.name] = references[toModel.name] || {};
          references[toModel.name][field.name] = field;
        }
      }

      static removeField(field) {
        super.removeField(field);

        const { name, references } = field;

        if (references) {
          const model = references.model.name;
          delete this._config.references[model][name];
          if (!Object.keys(this._config.references[model]).length) {
            delete this._config.references[model];
          }
        }
      }
    }

    knorm.Model = RelationsModel;
  }

  updateQuery(knorm) {
    const { Query } = knorm;

    class RelationsQuery extends Query {
      constructor(model) {
        super(model);
        this.parsedRows = {};
        this.config.references = model.config.references;
      }

      addJoin(type, joins, options) {
        if (!Array.isArray(joins)) {
          joins = [joins];
        }

        this.options.joins = this.options.joins || [];

        joins.forEach(join => {
          if (join.prototype instanceof this.constructor.Model) {
            join = join.query;
          }

          // TODO: strict mode: throw if join is not a `Query` instance

          const forwardReferences = join.config.references[this.model.name];
          const reverseReferences = this.config.references[join.model.name];

          if (!forwardReferences && !reverseReferences) {
            throw new Error(
              `'${this.model.name}' has no references to '${join.model.name}'`
            );
          }

          join.config.joinType = type;
          join.config.forwardReferences = forwardReferences;
          join.config.reverseReferences = reverseReferences;

          join.setOptions(options);

          this.options.joins.push(join);
        });

        return this;
      }

      leftJoin(queries, options) {
        return this.addJoin('leftJoin', queries, options);
      }

      innerJoin(queries, options) {
        return this.addJoin('innerJoin', queries, options);
      }

      // TODO: require setting `as` when configuring references
      as(as) {
        this.options.as = as;
        return this;
      }

      on(...fields) {
        this.options.on = this.options.on || [];
        this.options.on.push(...fields);
        return this;
      }

      async prepareJoin(query, options) {
        let references = [];
        const isForwardReference = !!this.config.forwardReferences;

        if (this.options.on) {
          if (isForwardReference) {
            this.options.on.forEach(field =>
              references.push(this.config.forwardReferences[field])
            );
          } else {
            const referencesByTo = Object.values(
              this.config.reverseReferences
            ).reduce((references, from) => {
              const to = from.references.name;
              references[to] = references[to] || [];
              references[to].push(from);
              return references;
            }, {});
            this.options.on.forEach(field =>
              references.push(...referencesByTo[field])
            );
          }
        } else {
          references = Object.values(
            this.config.forwardReferences || this.config.reverseReferences
          );
        }

        const on = references.reduce((columns, field) => {
          const fromColumn = field.column;
          const toColumn = field.references.column;
          let from;
          let to;

          if (isForwardReference) {
            from = `${this.quote(this.config.alias)}.${this.quote(fromColumn)}`;
            to = `${this.quote(this.parent.config.alias)}.${this.quote(
              toColumn
            )}`;
          } else {
            from = `${this.quote(this.config.alias)}.${this.quote(toColumn)}`;
            to = `${this.quote(this.parent.config.alias)}.${this.quote(
              fromColumn
            )}`;
          }

          columns[from] = to;

          return columns;
        }, {});

        const method = this.config.joinType || 'leftJoin';
        query[method](this.getTable(), on);

        this.ensureFields();

        return this.prepareQuery(query, options);
      }

      ensureUniqueField(to) {
        const aliases = Object.keys(this.options.fields);
        const fields = Object.values(this.options.fields);
        let unique;

        [this.config.primary].concat(this.config.unique).some(field => {
          const index = fields.indexOf(field);
          if (index > -1) {
            unique = aliases[index];
            return true;
          }
          return false;
        });

        if (!unique) {
          // TODO: throw a QueryError instead of a KnormRelationsError
          throw new KnormRelationsError(
            `${this.model.name}: cannot join ${
              to.model.name
            } with no primary or unique fields selected`
          );
        }

        this.options.unique = unique;
      }

      async prepareJoins(query, options) {
        return Promise.all(
          this.options.joins.map(async join => {
            this.ensureUniqueField(join);

            join.parent = this;
            join.config.index = ++this.config.index;
            join.config.alias = `${join.config.alias}_${join.config.index}`;

            // TODO: remove
            if (!join.options.as) {
              join.options.as = camelCase(join.model.name);
            }

            return join.prepareJoin(query, options);
          })
        );
      }

      async prepareQuery(query, options) {
        query = await super.prepareQuery(query, options);

        if (this.options.joins) {
          await this.prepareJoins(query, options);
        }

        return query;
      }

      throwFetchRequireError() {
        super.throwFetchRequireError();

        if (this.options.joins) {
          this.options.joins.forEach(query => query.throwFetchRequireError());
        }
      }

      // TODO: strict mode: throw if the value for the unique field is null or undefined
      getParsedRow(row) {
        let parsedRow = super.getParsedRow(row);

        if (!this.options.joins) {
          return parsedRow;
        }

        const unique = row[this.formatAlias(this.options.unique)];

        if (unique) {
          if (this.parsedRows[unique]) {
            parsedRow = this.parsedRows[unique];
          } else {
            this.parsedRows[unique] = parsedRow;
          }
        }

        return parsedRow;
      }

      parseJoin(row, parsedRow, options) {
        const as = this.options.as;

        if (this.options.first && parsedRow[as] !== undefined) {
          return;
        }

        const data = this.parseRow(
          row,
          Object.assign({ isNested: true }, options)
        );

        if (this.options.first) {
          parsedRow[as] = data;
        } else {
          if (data) {
            parsedRow[as] = parsedRow[as] || [];
            parsedRow[as].push(data);
          } else if (!parsedRow[as]) {
            parsedRow[as] = data;
          }
        }
      }

      parseRow(row, options) {
        let allFieldsNull = true;
        const handleRowValue = ({ value }) => {
          if (value !== null && allFieldsNull) {
            allFieldsNull = false;
          }
        };

        const superOptions = options.isNested
          ? Object.assign({ handleRowValue }, options)
          : options;

        const parsedRow = super.parseRow(row, superOptions);

        if (this.options.joins) {
          this.options.joins.forEach(join => {
            join.parseJoin(row, parsedRow, options);
          });
        }

        if (options.isNested && allFieldsNull) {
          return null;
        }

        return parsedRow;
      }

      parseRows(rows, options) {
        const parsedRows = super.parseRows(rows, options);

        if (this.options.joins) {
          return Object.values(this.parsedRows);
        }

        return parsedRows;
      }
    }

    RelationsQuery.prototype.join = RelationsQuery.prototype.innerJoin;

    RelationsQuery.CountError = class CountError extends Query.QueryError {};
    RelationsQuery.NoRowsCountedError = class NoRowsCountedError extends Query.QueryError {};

    knorm.Query = knorm.Model.Query = RelationsQuery;
  }

  init(knorm) {
    if (!knorm) {
      throw new KnormRelationsError('no Knorm instance provided');
    }

    if (!(knorm instanceof Knorm)) {
      throw new KnormRelationsError('invalid Knorm instance provided');
    }

    this.updateField(knorm);
    this.updateModel(knorm);
    this.updateQuery(knorm);
  }
}

KnormRelations.KnormRelationsError = KnormRelationsError;

module.exports = KnormRelations;
<commit_msg>chore: delete copy-pasted code<commit_after>const { Knorm, KnormError } = require('@knorm/knorm');
// TODO: remove
const { camelCase } = require('lodash');

class KnormRelationsError extends KnormError {}

class KnormRelations {
  updateField(knorm) {
    const { Field } = knorm;

    class RelationsField extends Field {
      constructor(config = {}) {
        super(config);
        if (config.references) {
          this.references = config.references;
        }
      }
    }

    knorm.Field = knorm.Model.Field = RelationsField;
  }

  updateModel(knorm) {
    const { Model } = knorm;

    class RelationsModel extends Model {
      static createConfig() {
        const config = super.createConfig();
        config.references = {};
        return config;
      }

      static addField(field) {
        super.addField(field);

        if (field.references) {
          const toField = field.references;
          const toModel = toField.model;
          const references = this._config.references;

          references[toModel.name] = references[toModel.name] || {};
          references[toModel.name][field.name] = field;
        }
      }

      static removeField(field) {
        super.removeField(field);

        const { name, references } = field;

        if (references) {
          const model = references.model.name;
          delete this._config.references[model][name];
          if (!Object.keys(this._config.references[model]).length) {
            delete this._config.references[model];
          }
        }
      }
    }

    knorm.Model = RelationsModel;
  }

  updateQuery(knorm) {
    const { Query } = knorm;

    class RelationsQuery extends Query {
      constructor(model) {
        super(model);
        this.parsedRows = {};
        this.config.references = model.config.references;
      }

      addJoin(type, joins, options) {
        if (!Array.isArray(joins)) {
          joins = [joins];
        }

        this.options.joins = this.options.joins || [];

        joins.forEach(join => {
          if (join.prototype instanceof this.constructor.Model) {
            join = join.query;
          }

          // TODO: strict mode: throw if join is not a `Query` instance

          const forwardReferences = join.config.references[this.model.name];
          const reverseReferences = this.config.references[join.model.name];

          if (!forwardReferences && !reverseReferences) {
            throw new Error(
              `'${this.model.name}' has no references to '${join.model.name}'`
            );
          }

          join.config.joinType = type;
          join.config.forwardReferences = forwardReferences;
          join.config.reverseReferences = reverseReferences;

          join.setOptions(options);

          this.options.joins.push(join);
        });

        return this;
      }

      leftJoin(queries, options) {
        return this.addJoin('leftJoin', queries, options);
      }

      innerJoin(queries, options) {
        return this.addJoin('innerJoin', queries, options);
      }

      // TODO: require setting `as` when configuring references
      as(as) {
        this.options.as = as;
        return this;
      }

      on(...fields) {
        this.options.on = this.options.on || [];
        this.options.on.push(...fields);
        return this;
      }

      async prepareJoin(query, options) {
        let references = [];
        const isForwardReference = !!this.config.forwardReferences;

        if (this.options.on) {
          if (isForwardReference) {
            this.options.on.forEach(field =>
              references.push(this.config.forwardReferences[field])
            );
          } else {
            const referencesByTo = Object.values(
              this.config.reverseReferences
            ).reduce((references, from) => {
              const to = from.references.name;
              references[to] = references[to] || [];
              references[to].push(from);
              return references;
            }, {});
            this.options.on.forEach(field =>
              references.push(...referencesByTo[field])
            );
          }
        } else {
          references = Object.values(
            this.config.forwardReferences || this.config.reverseReferences
          );
        }

        const on = references.reduce((columns, field) => {
          const fromColumn = field.column;
          const toColumn = field.references.column;
          let from;
          let to;

          if (isForwardReference) {
            from = `${this.quote(this.config.alias)}.${this.quote(fromColumn)}`;
            to = `${this.quote(this.parent.config.alias)}.${this.quote(
              toColumn
            )}`;
          } else {
            from = `${this.quote(this.config.alias)}.${this.quote(toColumn)}`;
            to = `${this.quote(this.parent.config.alias)}.${this.quote(
              fromColumn
            )}`;
          }

          columns[from] = to;

          return columns;
        }, {});

        const method = this.config.joinType || 'leftJoin';
        query[method](this.getTable(), on);

        this.ensureFields();

        return this.prepareQuery(query, options);
      }

      ensureUniqueField(to) {
        const aliases = Object.keys(this.options.fields);
        const fields = Object.values(this.options.fields);
        let unique;

        [this.config.primary].concat(this.config.unique).some(field => {
          const index = fields.indexOf(field);
          if (index > -1) {
            unique = aliases[index];
            return true;
          }
          return false;
        });

        if (!unique) {
          // TODO: throw a QueryError instead of a KnormRelationsError
          throw new KnormRelationsError(
            `${this.model.name}: cannot join ${
              to.model.name
            } with no primary or unique fields selected`
          );
        }

        this.options.unique = unique;
      }

      async prepareJoins(query, options) {
        return Promise.all(
          this.options.joins.map(async join => {
            this.ensureUniqueField(join);

            join.parent = this;
            join.config.index = ++this.config.index;
            join.config.alias = `${join.config.alias}_${join.config.index}`;

            // TODO: remove
            if (!join.options.as) {
              join.options.as = camelCase(join.model.name);
            }

            return join.prepareJoin(query, options);
          })
        );
      }

      async prepareQuery(query, options) {
        query = await super.prepareQuery(query, options);

        if (this.options.joins) {
          await this.prepareJoins(query, options);
        }

        return query;
      }

      throwFetchRequireError() {
        super.throwFetchRequireError();

        if (this.options.joins) {
          this.options.joins.forEach(query => query.throwFetchRequireError());
        }
      }

      // TODO: strict mode: throw if the value for the unique field is null or undefined
      getParsedRow(row) {
        let parsedRow = super.getParsedRow(row);

        if (!this.options.joins) {
          return parsedRow;
        }

        const unique = row[this.formatAlias(this.options.unique)];

        if (unique) {
          if (this.parsedRows[unique]) {
            parsedRow = this.parsedRows[unique];
          } else {
            this.parsedRows[unique] = parsedRow;
          }
        }

        return parsedRow;
      }

      parseJoin(row, parsedRow, options) {
        const as = this.options.as;

        if (this.options.first && parsedRow[as] !== undefined) {
          return;
        }

        const data = this.parseRow(
          row,
          Object.assign({ isNested: true }, options)
        );

        if (this.options.first) {
          parsedRow[as] = data;
        } else {
          if (data) {
            parsedRow[as] = parsedRow[as] || [];
            parsedRow[as].push(data);
          } else if (!parsedRow[as]) {
            parsedRow[as] = data;
          }
        }
      }

      parseRow(row, options) {
        let allFieldsNull = true;
        const handleRowValue = ({ value }) => {
          if (value !== null && allFieldsNull) {
            allFieldsNull = false;
          }
        };

        const superOptions = options.isNested
          ? Object.assign({ handleRowValue }, options)
          : options;

        const parsedRow = super.parseRow(row, superOptions);

        if (this.options.joins) {
          this.options.joins.forEach(join => {
            join.parseJoin(row, parsedRow, options);
          });
        }

        if (options.isNested && allFieldsNull) {
          return null;
        }

        return parsedRow;
      }

      parseRows(rows, options) {
        const parsedRows = super.parseRows(rows, options);

        if (this.options.joins) {
          return Object.values(this.parsedRows);
        }

        return parsedRows;
      }
    }

    RelationsQuery.prototype.join = RelationsQuery.prototype.innerJoin;

    knorm.Query = knorm.Model.Query = RelationsQuery;
  }

  init(knorm) {
    if (!knorm) {
      throw new KnormRelationsError('no Knorm instance provided');
    }

    if (!(knorm instanceof Knorm)) {
      throw new KnormRelationsError('invalid Knorm instance provided');
    }

    this.updateField(knorm);
    this.updateModel(knorm);
    this.updateQuery(knorm);
  }
}

KnormRelations.KnormRelationsError = KnormRelationsError;

module.exports = KnormRelations;
<|endoftext|>


<commit_before>var url = require('url')

function MDiMapGeocoder(options) {
  this.address_fields = ['Street', 'City', 'State', 'ZIP']

  this.options = {
    browser: false,
    wkid: 4326,
    get_url: {
      protocol: 'http:',
      host: 'mdimap.us',
      pathname: 'ArcGIS/rest/services/GeocodeServices/MD.State.MDCascadingLocatorWithZIPCodes/GeocodeServer/findAddressCandidates'
    }
  }

  if(options) {
    for(var option in options){
      this.options[option] = options[option]
    }
  }

  if (process.title === 'node') {
    this.options.browser = false
    http = require('http')
  } else {
    this.options.browser = true
  }
}

MDiMapGeocoder.prototype.search = function(term, next) {
  var query = {
    outSR: this.options.wkid,
    f: 'json'
  }

  if(typeof term === 'string') {
    query.SingleLine = term
  } else if(typeof term === 'object') {
    for(var i = 0; i < this.address_fields.length; i++){
      var field = this.address_fields[i]
      if(term[field]) {
        query[field] = term[field]
      }
    }
  }

  var get_url = this.options.get_url
  get_url.query = query

  if(this.options.browser){
    this.browserGet(get_url, next)
  } else {
    this.nodeGet(get_url, next)
  }
}

MDiMapGeocoder.prototype.browserGet = function(get_url, next) {
  get_url.query.callback = '_MDiMapGeocoder_cb'
  window._MDiMapGeocoder_cb = function(data){
    next(null, data)
  }
  get_url = url.format(get_url)

  var script = document.createElement('script')
  script.onload = function() {
    document.head.removeChild(this)
  }
  script.src = get_url
  document.getElementsByTagName('head')[0].appendChild(script)
}

MDiMapGeocoder.prototype.nodeGet = function(get_url, next) {
  get_url = url.format(get_url)
  http.get(get_url, function(res){
    var data = ''
    res.on("data", function(chunk) {
      data += chunk
    })
    res.on('end', function(err){
      if(err) {
        next(err)
        return
      } else {
        var obj = JSON.parse(data)
        next(null, obj)
      }
    })
  })
}

module.exports = MDiMapGeocoder<commit_msg>iMap geocoder 2.0<commit_after>var url = require('url')

function MDiMapGeocoder(options) {
  this.address_fields = ['Street', 'City', 'State', 'ZIP']

  this.options = {
    browser: false,
    wkid: 4326,
    get_url: {
      protocol: 'http:',
      host: 'geodata.md.gov',
      pathname: 'imap/rest/services/GeocodeServices/MD_CompositeLocatorWithZIPCodeCentroids/GeocodeServer/findAddressCandidates'
    }
  }

  if(options) {
    for(var option in options){
      this.options[option] = options[option]
    }
  }

  if (process.title === 'node') {
    this.options.browser = false
    http = require('http')
  } else {
    this.options.browser = true
  }
}

MDiMapGeocoder.prototype.search = function(term, next) {
  var query = {
    outSR: this.options.wkid,
    f: 'json'
  }

  if(typeof term === 'string') {
    query.SingleLine = term
  } else if(typeof term === 'object') {
    for(var i = 0; i < this.address_fields.length; i++){
      var field = this.address_fields[i]
      if(term[field]) {
        query[field] = term[field]
      }
    }
  }

  var get_url = this.options.get_url
  get_url.query = query

  if(this.options.browser){
    this.browserGet(get_url, next)
  } else {
    this.nodeGet(get_url, next)
  }
}

MDiMapGeocoder.prototype.browserGet = function(get_url, next) {
  get_url.query.callback = '_MDiMapGeocoder_cb'
  window._MDiMapGeocoder_cb = function(data){
    next(null, data)
  }
  get_url = url.format(get_url)

  var script = document.createElement('script')
  script.onload = function() {
    document.head.removeChild(this)
  }
  script.src = get_url
  document.getElementsByTagName('head')[0].appendChild(script)
}

MDiMapGeocoder.prototype.nodeGet = function(get_url, next) {
  get_url = url.format(get_url)
  console.log(get_url)
  http.get(get_url, function(res){
    var data = ''
    res.on("data", function(chunk) {
      data += chunk
    })
    res.on('end', function(err){
      if(err) {
        next(err)
        return
      } else {
        var obj = JSON.parse(data)
        next(null, obj)
      }
    })
  })
}

module.exports = MDiMapGeocoder<|endoftext|>


<commit_before>
    !function() {
        'use strict';

        var Class          = require('ee-class')
            , log          = require('ee-log')
            , EventEmitter = require('ee-event-emitter');

        module.exports = new Class({
            inherits: EventEmitter

            , _controllerList    : {}

            , _servicesLoadCount : 0
            , _loaded            : false

            , init: function(options) {
                this.options = options || {};

            }

            , _hasController: function(controllerName) {
                return Object.hasOwnProperty.call(this._controllerList, controllerName);
            }

            , request: function(req, res) {
                // var util = require('util');
                // log(util.inspect(req, {colors: true, depth: 5}));
                log(req);
                // for(var property in req){
                //     var buffer = property;
                //     if(typeof req[property] === 'function'){
                //         buffer += '()';
                //     }
                //     log(buffer);
                // }

                var collection = req.getCollection();

                if(this._hasController(collection)) this._controllerList[collection].request(req, res);
                else log(new Error(collection + " not managed by serviceManager")); //TODO: write error on res
            }

            , _handleRequest: function(req, callback) {
                var collection = req.getCollection();

                if(this._hasController(collection)) {
                    this._controllerList[collection].internalRequest(req, callback);
                }
                else {
                    var res = {};
                    res.on('end', callback);

                    this.emit('request', req, res); //TODO: generate res object with callback
                }
            }

            , use: function(service) {
                //TODO: check if service is a ee-service
                var loaded = function() {
                    this._servicesLoadCount--;
                    if(this._servicesLoadCount === 0) {
                        this._loaded = true;
                        this.emit('load');
                    }
                }.bind(this);

                this._servicesLoadCount++;
                this._loaded = false;

                service.onLoad(function(err) {
                    this._addControllers(service.getControllerNames(), service);
                    loaded();
                }.bind(this));

                service.on('request', this._handleRequest.bind(this));
            }

            , onLoad: function(callback) {
                if(this._loaded) callback();
                else this.on('load', callback);
            }

            , _addControllers: function(controllerNames, service) {
                controllerNames.forEach(function(controllerName) {
                    this._addController(controllerName, service);
                }.bind(this));
            }

            , _addController: function(controllerName, service) {
                if(this._hasController(controllerName)) throw new Error(controllerName + ' already managed by servicemanager');
                else this._controllerList[controllerName] = service;
            }

        });

    }();
<commit_msg>added middleware<commit_after>
    !function() {
        'use strict';

        var Class          = require('ee-class')
            , log          = require('ee-log')
            , EventEmitter = require('ee-event-emitter');

        module.exports = new Class({
            inherits: EventEmitter

            , _controllerList       : {}
            , _serviceList          : []

            , _servicesLoadCount    : 0
            , _loaded               : false

            , init: function(options) {
                this.options = options || {};

            }

            , _hasController: function(controllerName) {
                return Object.hasOwnProperty.call(this._controllerList, controllerName);
            }

            , request: function(req, res) {
                log(req);
                // for(var property in req){
                //     var buffer = property;
                //     if(typeof req[property] === 'function'){
                //         buffer += '()';
                //     }
                //     log(buffer);
                // }

                var collection = req.getCollection();

                if(this._hasController(collection)) this._controllerList[collection].request(req, res);
                else log(new Error(collection + " not managed by serviceManager")); //TODO: write error on res
            }

            , _handleRequest: function(req, res) {
                var collection = req.getCollection();

                if(this._hasController(collection)) {
                    this._controllerList[collection].request(req, res);
                }
                else {
                    this.emit('request', req, res);
                }
            }

            , use: function(service) {
                //TODO: check if service is a ee-service
                var loaded = function() {
                    this._servicesLoadCount--;
                    if(this._servicesLoadCount === 0) {
                        this._loaded = true;
                        this.emit('load');
                    }
                }.bind(this);

                this._servicesLoadCount++;
                this._loaded = false;

                service.onLoad(function(err) {
                    this._serviceList.push(service);
                    this._addControllers(service.getControllerNames(), service);
                    loaded();
                }.bind(this));

                service.on('request', this._handleRequest.bind(this));
            }

            , useMiddleware: function(middleware) {
                this.onLoad(function(err) {
                    this._serviceList.forEach(function(service) {
                        service.useMiddleware(middleware);
                    }.bind(this));
                }.bind(this));
            }

            , onLoad: function(callback) {
                if(this._loaded) callback();
                else this.on('load', callback);
            }

            , _addControllers: function(controllerNames, service) {
                controllerNames.forEach(function(controllerName) {
                    this._addController(controllerName, service);
                }.bind(this));
            }

            , _addController: function(controllerName, service) {
                if(this._hasController(controllerName)) throw new Error(controllerName + ' already managed by servicemanager');
                else this._controllerList[controllerName] = service;
            }

        });

    }();
<|endoftext|>


<commit_before>(() => {
    let ws = new WebSocket("ws://" + location.host + "/chat");
    let mb = document.getElementById('responses');
    let input = document.getElementById('input');
    let encoder = new TextEncoder("utf-8");
    let decoder = new TextDecoder("utf-8");
    let identity;
    ws.onopen = function() {
        log('debug', "Connected");
        input.style.visibility = 'visible';
    };

    ws.onclose = function() {
        input.style.visibility = 'hidden';
        log('warning', "Disconnected");
    };

    ws.onerror = function(e) {
        input.style.visibility = 'hidden';
        log('warning', 'ERROR: ' + e);
    };
    ws.onmessage = function(ev) {
        if ("string" === typeof ev.data) {
            log('meta', ev.data);
            const IDENTITY_TOKEN = "identity: ";
            if (ev.data.startsWith(IDENTITY_TOKEN)) {
                identity = ev.data.substr(IDENTITY_TOKEN.length) + ": ";
            }
        } else {
            let reader = new FileReader();
            reader.onload = (event) => log('text', decoder.decode(event.target.result));
            reader.readAsArrayBuffer(ev.data)
        }
    };
    input.onkeydown = function(ev) {
        if(ev.which === 13) {
            let value = (identity || "") + input.value;
            ws.send(encoder.encode(value));
            log('self', value);
            input.value = '';
        }
    };

    function log(type, message) {
        let date = document.createElement('span');
        date.appendChild(document.createTextNode(new Date().toLocaleString()));
        date.className = "date";
        let content = document.createElement('span');
        content.appendChild(document.createTextNode(message));
        let red = document.createElement('div');
        red.className = type;
        red.appendChild(date);
        red.appendChild(content);
        mb.insertBefore(red, mb.childNodes[0]);
    }

})();
<commit_msg>Fix up the rust-server example with channel links<commit_after>(() => {
let mb = document.getElementById('responses');
let input = document.getElementById('input');
let encoder = new TextEncoder("utf-8");
let decoder = new TextDecoder("utf-8");
let identity;
let ws;

function log(type, message, node) {
    let date = document.createElement('span');
    date.appendChild(document.createTextNode(new Date().toLocaleString()));
    date.className = "date";
    let content = node || document.createElement('span');
    content.appendChild(document.createTextNode(message));
    let red = document.createElement('div');
    red.className = type;
    red.appendChild(date);
    red.appendChild(content);
    mb.insertBefore(red, mb.childNodes[0]);
}

function initWebSocket(hash) {
    return new WebSocket("ws://" + location.host + "/" + (hash || location.hash.substr(1)));
}

function hide() {
    input.style.visibility = 'hidden';
}

function onClose(socket) {
    return () => {
        if (socket === ws) {
            hide();
            log('warning', "Disconnected");
        } else {
            log('warning', "(Old) Disconnected");
        }
    }
}

function onError() {
    hide();
    log('warning', 'ERROR: ' + e);
}

function onOpen() {
    log('debug', "Connected");
    input.style.visibility = 'visible';
}

function init(newSocket) {
    ws = newSocket || initWebSocket();
    ws.onopen = onOpen;
    ws.onclose = onClose(ws);
    ws.onerror = onError;

    function onMessage(ev) {
        if ("string" === typeof ev.data) {
            const IDENTITY_TOKEN = "identity: ";
            if (ev.data.startsWith(IDENTITY_TOKEN)) {
                identity = ev.data.substr(IDENTITY_TOKEN.length) + ": ";
            }
            const ADD_TOKEN = "+: ";
            if (ev.data.startsWith(ADD_TOKEN)) {
                let token = ev.data.substr(ADD_TOKEN.length + 1);
                let link = document.createElement('a');
                link.href = `#${token}`;
                link.onclick = () => {
                    hide();
                    ws.close();
                    location.hash = link.href;
                    init(initWebSocket(token));
                };
                log('meta', ev.data, link);
                return;
            }
            log('meta', ev.data);
        } else {
            let reader = new FileReader();
            reader.onload = (event) => log('text', decoder.decode(event.target.result));
            reader.readAsArrayBuffer(ev.data)
        }
    }
    ws.onmessage = onMessage;
}

input.onkeydown = function(ev) {
    if (ev.which === 13) {
        let value = (identity || "") + input.value;
        ws.send(encoder.encode(value));
        log('self', value);
        input.value = '';
    }
};

init();
})()
<|endoftext|>


<commit_before>'use strict';

const symphonySelector = '.player-PlayerInfo__infoEl--2jhHY span:nth-child(3) span:first-child';
const commonNameSelector = '.player-PlayerInfo__infoEl--2jhHY span:nth-child(3) span:nth-child(2)';
const directorSelector = '.player-PlayerInfo__recordingInfo--15VMv>span:first-child span';
const trackSelector = '.player-PlayerInfo__infoEl--2jhHY';
const pauseButtonSelector = '.player-PlayerControls__btn--1r-vy:nth-child(2) .util-IconLabel__component--3Uitr span';

Connector.playerSelector = '.player-PlayerBar__bar--2yos_';

Connector.artistSelector = '.player-PlayerInfo__infoEl--2jhHY span:first-child';

Connector.getTrack = getCurrentTrack;

Connector.getAlbum = getCurrentSymphony;

Connector.currentTimeSelector = '.player-PlayerProgress__progress--2F0qB>span';

Connector.durationSelector = '.player-PlayerProgress__timeTotal--3aHlj span';

Connector.isPlaying = () => Util.getTextFromSelectors(pauseButtonSelector) === 'Pause';

Connector.isScrobblingAllowed = () => Util.getTextFromSelectors('.player-PlayerInfo__recordingInfo--15VMv') !== 'Sponsor message';

function getCurrentTrack() {
	return Util.getTextFromSelectors(trackSelector).split(' – ').slice(1).join(': ');
}

function getCurrentSymphony() {
	const symphonyShort = Util.getTextFromSelectors(symphonySelector).split(/ in [A-G]| op. [0-9]| KV [0-9]/)[0];
	const commonName = Util.getTextFromSelectors(commonNameSelector) || '';
	const director = removeParenthesis(Util.getTextFromSelectors(directorSelector));
	return `${symphonyShort}${commonName} (${director})`;
}

function removeParenthesis(text) {
	return text.replace(/\s*\(.*?\)\s*/g, '');
}
<commit_msg>Improve idagio connector (#2648)<commit_after>'use strict';

const symphonySelector = '.player-PlayerInfo__infoEl--2jhHY span:nth-child(3) span:first-child';
const commonNameSelector = '.player-PlayerInfo__infoEl--2jhHY span:nth-child(3) span:nth-child(2)';
const directorSelector = '.player-PlayerInfo__recordingInfo--15VMv>span:first-child span';
const trackSelector = '.player-PlayerInfo__infoEl--2jhHY';
const pauseButtonSelector = '.player-PlayerControls__btn--1r-vy:nth-child(2) .util-IconLabel__component--3Uitr span';

Connector.playerSelector = '.player-PlayerBar__bar--2yos_';

Connector.artistSelector = '.player-PlayerInfo__infoEl--2jhHY span:first-child';

Connector.getTrack = getCurrentTrack;

Connector.getAlbum = getCurrentSymphony;

Connector.currentTimeSelector = '.player-PlayerProgress__progress--2F0qB>span';

Connector.durationSelector = '.player-PlayerProgress__timeTotal--3aHlj span';

Connector.isPlaying = () => Util.getTextFromSelectors(pauseButtonSelector) === 'Pause';

Connector.isScrobblingAllowed = () => Util.getTextFromSelectors('.player-PlayerInfo__recordingInfo--15VMv') !== 'Sponsor message';

function getCurrentTrack() {
	/*
	 * Idagio puts composer and piece all in the same div element, so we have to undo this.
	 * First split the tag by dashes. Include spaces to avoid issues with names containing dashes.
	 * The first part is the composer name. We want to exclude this, so we slice it off.
	 * Then, replace the dashes with colons, this makes the tag more in line with what is expected.
	 * Finally, trim as a "just in case" in preparation for the next step. Unnecessary in the cases I've seen, but extremely simple and might prevent something down the line.
	 * Example from https://app.idagio.com/albums/saint-saens-violin-sonata-no-1-cello-sonata-no-1-and-piano-trio-no-2:
	 * "Camille Saint-Saëns – Sonata for Violin and Piano No. 1 in D minor op. 75 R 123 – I. Allegro agitato –"
	 * -> ["Camille Saint-Saëns", "Sonata for Violin and Piano No. 1 in D minor op. 75 R 123", "I. Allegro agitato –"]
	 * -> ["Sonata for Violin and Piano No. 1 in D minor op. 75 R 123", "I. Allegro agitato –"]
	 * -> "Sonata for Violin and Piano No. 1 in D minor op. 75 R 123: I. Allegro agitato –"
	 */
	let track = Util.getTextFromSelectors(trackSelector).split(' – ').slice(1).join(': ').trim();
	/*
	 * Now remove trailing dash if exists.
	 * Example: "Sonata for Violin and Piano No. 1 in D minor op. 75 R 123: I. Allegro agitato –"
	 * -> "Sonata for Violin and Piano No. 1 in D minor op. 75 R 123: I. Allegro agitato " (the space is trimmed later in core)
	 */
	if (track.slice(-1) === '–') {
		track = track.slice(0, -1);
	}
	return track;
}

function getCurrentSymphony() {
	const symphonyShort = Util.getTextFromSelectors(symphonySelector).split(/ in [A-G]| op. [0-9]| KV [0-9]/)[0];
	const commonName = Util.getTextFromSelectors(commonNameSelector) || '';
	const director = removeParenthesis(Util.getTextFromSelectors(directorSelector));
	return `${symphonyShort}${commonName} (${director})`;
}

function removeParenthesis(text) {
	return text.replace(/\s*\(.*?\)\s*/g, '');
}
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var event = require("pilot/event");

var RenderLoop = function(onRender, window) {
    this.onRender = onRender;
    this.pending = false;
    this.changes = 0;
    this.setTimeoutZero = this.setTimeoutZero.bind(window);
};

(function() {

    this.schedule = function(change) {
        //this.onRender(change);
        //return;
        this.changes = this.changes | change;
        if (!this.pending) {
            this.pending = true;
            var _self = this;
            this.setTimeoutZero(function() {
                _self.pending = false;
                var changes = _self.changes;
                _self.changes = 0;
                _self.onRender(changes);
            })
        }
    };

    this.setTimeoutZero = window.requestAnimationFrame ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame ||
         window.oRequestAnimationFrame ||
         window.msRequestAnimationFrame;

    if (this.setTimeoutZero) {
        this.setTimeoutZero = this.setTimeoutZero;
    } else if (window.postMessage) {

        this.setTimeoutZero = (function(messageName, attached, listener) {
            return function setTimeoutZero(callback) {
                // Set up listener if not listening already.
                if (!attached) {
                    event.addListener(this, "message", function(e) {
                        if (listener && e.data == messageName) {
                            event.stopPropagation(e);
                            listener();
                        }
                    });
                    attached = true;
                }

                listener = callback;
                this.postMessage(messageName, "*");
            };
        })("zero-timeout-message", false, null);

    } else {

        this.setTimeoutZero = function(callback) {
            this.setTimeout(callback, 0);
        }
    }

}).call(RenderLoop.prototype);

exports.RenderLoop = RenderLoop;
});
<commit_msg>requestAnimationFrame cannot be used in Webkit since it is not fired when the window is not focused/visible.<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var event = require("pilot/event");

var RenderLoop = function(onRender, window) {
    this.onRender = onRender;
    this.pending = false;
    this.changes = 0;
    this.setTimeoutZero = this.setTimeoutZero.bind(window);
};

(function() {

    this.schedule = function(change) {
        //this.onRender(change);
        //return;
        this.changes = this.changes | change;
        if (!this.pending) {
            this.pending = true;
            var _self = this;
            this.setTimeoutZero(function() {
                _self.pending = false;
                var changes = _self.changes;
                _self.changes = 0;
                _self.onRender(changes);
            });
        }
    };

    if (window.postMessage) {
        this.setTimeoutZero = (function(messageName, attached, listener) {
            return function setTimeoutZero(callback) {
                // Set up listener if not listening already.
                if (!attached) {
                    event.addListener(this, "message", function(e) {
                        if (listener && e.data == messageName) {
                            event.stopPropagation(e);
                            listener();
                        }
                    });
                    attached = true;
                }

                listener = callback;
                this.postMessage(messageName, "*");
            };
        })("zero-timeout-message", false, null);
    }
    else {
        this.setTimeoutZero = function(callback) {
            this.setTimeout(callback, 0);
        };
    }

}).call(RenderLoop.prototype);

exports.RenderLoop = RenderLoop;
});
<|endoftext|>


<commit_before>import Router from 'koa-router'
import User from '../models/users'
import config from '../../config'
import jwt from 'jsonwebtoken'
import { ensureUser } from '../middleware/validators'

const router = new Router({ prefix: '/users' })

router.get('/',
  ensureUser,
  async (ctx) => {
    const users = await User.find({}, '-password -salt')
    ctx.body = users
  }
)

router.get('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password -salt')
      if (!user) {
        ctx.throw(404)
      }

      ctx.body = user
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

router.post('/',
  async (ctx) => {
    const user = new User(ctx.request.body.user)
    try {
      await user.save()
      const token = jwt.sign({ id: user.id }, config.token)

      const response = user.toJSON()

      delete response.password
      delete response.salt

      ctx.body = {
        user: response,
        token
      }
    } catch (err) {
      ctx.throw(422, err)
    }
  }
)

router.put('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password -salt')
      if (!user) {
        ctx.throw(404)
      }

      Object.assign(user, ctx.request.body.user)

      await user.save()
      ctx.body = {
        user
      }
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

router.delete('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)
      if (!user) {
        ctx.throw(404)
      }

      await user.remove()

      ctx.body = 200
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

export default router
<commit_msg>Add docs for `GET /user/:id`<commit_after>import Router from 'koa-router'
import User from '../models/users'
import config from '../../config'
import jwt from 'jsonwebtoken'
import { ensureUser } from '../middleware/validators'

const router = new Router({ prefix: '/users' })

/**
 * @api {get} /users Get all users
 * @apiPermission user
 * @apiVersion 1.0.0
 * @apiName GetUsers
 * @apiGroup Users
 *
 * @apiExample Example usage:
 * curl -H "Content-Type: application/json" -X GET localhost:5000/users
 *
 * @apiSuccess {Object[]}   users           Array of user objects
 * @apiSuccess {ObjectId}   users._id       User id
 * @apiSuccess {String}     users.name      User name
 * @apiSuccess {String}     users.username  User username
 *
 * @apiSuccessExample {json} Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "users": [{
 *          "_id": "56bd1da600a526986cf65c80"
 *          "username": "foo"
 *          "username": "johndoe"
 *       }]
 *     }
 *
 * @apiUse TokenError
 */
router.get('/',
  ensureUser,
  async (ctx) => {
    const users = await User.find({}, '-password -salt')
    ctx.body = users
  }
)

/**
 * @api {get} /users/:id Get user by id
 * @apiPermission user
 * @apiVersion 1.0.0
 * @apiName GetUser
 * @apiGroup Users
 *
 * @apiExample Example usage:
 * curl -H "Content-Type: application/json" -X GET localhost:5000/users/56bd1da600a526986cf65c80
 *
 * @apiSuccess {Object}   users             User object
 * @apiSuccess {ObjectId}   users._id       User id
 * @apiSuccess {String}     users.name      User name
 * @apiSuccess {String}     users.username  User username
 *
 * @apiSuccessExample {json} Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "user": {
 *          "_id": "56bd1da600a526986cf65c80"
 *          "username": "foo"
 *          "username": "johndoe"
 *       }
 *     }
 *
 * @apiUse TokenError
 */
router.get('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password -salt')
      if (!user) {
        ctx.throw(404)
      }

      ctx.body = user
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

router.post('/',
  async (ctx) => {
    const user = new User(ctx.request.body.user)
    try {
      await user.save()
      const token = jwt.sign({ id: user.id }, config.token)

      const response = user.toJSON()

      delete response.password
      delete response.salt

      ctx.body = {
        user: response,
        token
      }
    } catch (err) {
      ctx.throw(422, err)
    }
  }
)

router.put('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id, '-password -salt')
      if (!user) {
        ctx.throw(404)
      }

      Object.assign(user, ctx.request.body.user)

      await user.save()
      ctx.body = {
        user
      }
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

router.delete('/:id',
  ensureUser,
  async (ctx) => {
    try {
      const user = await User.findById(ctx.params.id)
      if (!user) {
        ctx.throw(404)
      }

      await user.remove()

      ctx.body = 200
    } catch (err) {
      if (err === 404 || err.name === 'CastError') {
        ctx.throw(404)
      }

      ctx.throw(500)
    }
  }
)

export default router
<|endoftext|>