<commit_before>(function(carto) {
var tree = require('./tree');
var _ = require('underscore');

function CartoCSS(style, options) {
  this.options = options || {};
  if(style) {
    this.setStyle(style);
  }
}

CartoCSS.Layer = function(shader, options) {
  this.options = options;
  this.shader = shader;
};

CartoCSS.Layer.prototype = {

  fullName: function() {
    return this.shader.attachment;
  },

  name: function() {
    return this.fullName().split('::')[0];
  },

  // frames this layer need to be rendered
  frames: function() {
    return this.shader.frames;
  },

  attachment: function() {
    return this.fullName().split('::')[1];
  },

  eval: function(prop) {
    var p = this.shader[prop];
    if (!p || !p.style) return;
    return p.style({}, { zoom: 0, 'frame-offset': 0 });
  },

  /*
   * `target`: style, 'svg', 'canvas-2d'...
   * `props`: feature properties
   * `context`: rendering properties, i.e zoom
   */
  getStyle: function(props, context) {
    var style = {};
    for(var i in this.shader) {
      if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') {
        style[i] = this.shader[i].style(props, context);
      }
    }
    return style;
  },

  /**
   * return the symbolizers that need to be rendered with
   * this style. The order is the rendering order.
   * @returns a list with 3 possible values 'line', 'marker', 'polygon'
   */
  getSymbolizers: function() {
    return this.shader.symbolizers;
  },

  /**
   * returns if the style varies with some feature property.
   * Useful to optimize rendering
   */
  isVariable: function() {
    for(var i in this.shader) {
      if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') {
        if (!this.shader[i].constant) {
          return true;
        }
      }
    }
    return false;
  },

  getShader: function() {
    return this.shader;
  },

  /**
   * returns true if a feature needs to be rendered
   */
  filter: function(featureType, props, context) {
    for(var i in this.shader) {
     var s = this.shader[i](props, context);
     if(s) {
       return true;
     }
    }
    return false;
  },

  //
  // given a geoemtry type returns the transformed one acording the CartoCSS
  // For points there are two kind of types: point and sprite, the first one
  // is a circle, second one is an image sprite
  //
  // the other geometry types are the same than geojson (polygon, linestring...)
  //
  transformGeometry: function(type) {
    return type;
  },

  transformGeometries: function(geojson) {
    return geojson;
  }

};

CartoCSS.prototype = {

  setStyle: function(style) {
    var layers = this.parse(style);
    if(!layers) {
      throw new Error(this.parse_env.errors);
    }
    this.layers = layers.map(function(shader) {
        return new CartoCSS.Layer(shader);
    });
  },

  getLayers: function() {
    return this.layers;
  },

  getDefault: function() {
    return this.findLayer({ attachment: '__default__' });
  },

  findLayer: function(where) {
    return _.find(this.layers, function(value) {
      for (var key in where) {
        var v = value[key];
        if (typeof(v) === 'function') {
          v = v.call(value);
        }
        if (where[key] !== v) return false;
      }
      return true;
    });
  },

  _createFn: function(ops) {
    var body = ops.join('\n');
    if(this.options.debug) console.log(body);
    return Function("data","ctx", "var _value = null; " +  body + "; return _value; ");
  },

  _compile: function(shader) {
    if(typeof shader === 'string') {
        shader = eval("(function() { return " + shader +"; })()");
    }
    this.shader_src = shader;
    for(var attr in shader) {
        var c = mapper[attr];
        if(c) {
            this.compiled[c] = eval("(function() { return shader[attr]; })();");
        }
    }
  },

  parse: function(cartocss) {
    var parse_env = {
      frames: [],
      errors: [],
      error: function(obj) {
        this.errors.push(obj);
      }
    };
    this.parse_env = parse_env;

    var ruleset = null;
    try {
      ruleset = (new carto.Parser(parse_env)).parse(cartocss);
    } catch(e) {
      // add the style.mss string to match the response from the server
      parse_env.errors.push(e.message);
      return;
    }
    if(ruleset) {

      function defKey(def) {
        return def.elements[0] + "::" + def.attachment;
      }
      var defs = ruleset.toList(parse_env);
      defs.reverse();
      // group by elements[0].value::attachment
      var layers = {};
      for(var i = 0; i < defs.length; ++i) {
        var def = defs[i];
        var key = defKey(def);
        var layer = layers[key] = (layers[key] || {
          symbolizers: []
        });
        layer.frames = [];
        layer.zoom = tree.Zoom.all;
        var props = def.toJS(parse_env);
        if (this.options.debug) console.log("props", props);
        for(var v in props) {
          var lyr = layer[v] = layer[v] || {
            constant: false,
            symbolizer: null,
            js: [],
            index: 0
          };
          // build javascript statements
          lyr.js.push(props[v].map(function(a) { return a.js; }).join('\n'));
          // get symbolizer for prop
          lyr.symbolizer = _.first(props[v].map(function(a) { return a.symbolizer; }));
          // serach the max index to know rendering order
          lyr.index = _.max(props[v].map(function(a) { return a.index; }).concat(lyr.index));
          lyr.constant = !_.any(props[v].map(function(a) { return !a.constant; }));
        }
      }

      var ordered_layers = [];
      if (this.options.debug) console.log(layers);

      var done = {};
      for(var i = 0; i < defs.length; ++i) {
        var def = defs[i];
        var k = defKey(def);
        var layer = layers[k];
        if(!done[k]) {
          if(this.options.debug) console.log("**", k);
          for(var prop in layer) {
            if (prop !== 'zoom' && prop !== 'frames' && prop !== 'symbolizers') {
              if(this.options.debug) console.log("*", prop);
              layer[prop].style = this._createFn(layer[prop].js);
              layer.symbolizers.push(layer[prop].symbolizer);
              layer.symbolizers = _.uniq(layer.symbolizers);
            }
          }
          layer.attachment = k;
          ordered_layers.push(layer);
          done[k] = true;
        }
        layer.zoom |= def.zoom;
        layer.frames.push(def.frame_offset);
      }

      // uniq the frames
      for(i = 0; i < ordered_layers.length; ++i) {
        ordered_layers[i].frames = _.uniq(ordered_layers[i].frames);
      }

      return ordered_layers;

    }
    return null;
  }
};

carto.RendererJS = function (options) {
    this.options = options || {};
    this.options.mapnik_version = this.options.mapnik_version || 'latest';
};

// Prepare a javascript object which contains the layers
carto.RendererJS.prototype.render = function render(cartocss, callback) {
    var reference = require('./torque-reference');
    tree.Reference.setData(reference.version.latest);
    return new CartoCSS(cartocss, this.options);
}

if(typeof(module) !== 'undefined') {
  module.exports = carto.RendererJS;
}

})(require('../carto'));
<commit_msg>Remove doc block for non-existent param<commit_after>(function(carto) {
var tree = require('./tree');
var _ = require('underscore');

function CartoCSS(style, options) {
  this.options = options || {};
  if(style) {
    this.setStyle(style);
  }
}

CartoCSS.Layer = function(shader, options) {
  this.options = options;
  this.shader = shader;
};

CartoCSS.Layer.prototype = {

  fullName: function() {
    return this.shader.attachment;
  },

  name: function() {
    return this.fullName().split('::')[0];
  },

  // frames this layer need to be rendered
  frames: function() {
    return this.shader.frames;
  },

  attachment: function() {
    return this.fullName().split('::')[1];
  },

  eval: function(prop) {
    var p = this.shader[prop];
    if (!p || !p.style) return;
    return p.style({}, { zoom: 0, 'frame-offset': 0 });
  },

  /*
   * `props`: feature properties
   * `context`: rendering properties, i.e zoom
   */
  getStyle: function(props, context) {
    var style = {};
    for(var i in this.shader) {
      if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') {
        style[i] = this.shader[i].style(props, context);
      }
    }
    return style;
  },

  /**
   * return the symbolizers that need to be rendered with
   * this style. The order is the rendering order.
   * @returns a list with 3 possible values 'line', 'marker', 'polygon'
   */
  getSymbolizers: function() {
    return this.shader.symbolizers;
  },

  /**
   * returns if the style varies with some feature property.
   * Useful to optimize rendering
   */
  isVariable: function() {
    for(var i in this.shader) {
      if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') {
        if (!this.shader[i].constant) {
          return true;
        }
      }
    }
    return false;
  },

  getShader: function() {
    return this.shader;
  },

  /**
   * returns true if a feature needs to be rendered
   */
  filter: function(featureType, props, context) {
    for(var i in this.shader) {
     var s = this.shader[i](props, context);
     if(s) {
       return true;
     }
    }
    return false;
  },

  //
  // given a geoemtry type returns the transformed one acording the CartoCSS
  // For points there are two kind of types: point and sprite, the first one
  // is a circle, second one is an image sprite
  //
  // the other geometry types are the same than geojson (polygon, linestring...)
  //
  transformGeometry: function(type) {
    return type;
  },

  transformGeometries: function(geojson) {
    return geojson;
  }

};

CartoCSS.prototype = {

  setStyle: function(style) {
    var layers = this.parse(style);
    if(!layers) {
      throw new Error(this.parse_env.errors);
    }
    this.layers = layers.map(function(shader) {
        return new CartoCSS.Layer(shader);
    });
  },

  getLayers: function() {
    return this.layers;
  },

  getDefault: function() {
    return this.findLayer({ attachment: '__default__' });
  },

  findLayer: function(where) {
    return _.find(this.layers, function(value) {
      for (var key in where) {
        var v = value[key];
        if (typeof(v) === 'function') {
          v = v.call(value);
        }
        if (where[key] !== v) return false;
      }
      return true;
    });
  },

  _createFn: function(ops) {
    var body = ops.join('\n');
    if(this.options.debug) console.log(body);
    return Function("data","ctx", "var _value = null; " +  body + "; return _value; ");
  },

  _compile: function(shader) {
    if(typeof shader === 'string') {
        shader = eval("(function() { return " + shader +"; })()");
    }
    this.shader_src = shader;
    for(var attr in shader) {
        var c = mapper[attr];
        if(c) {
            this.compiled[c] = eval("(function() { return shader[attr]; })();");
        }
    }
  },

  parse: function(cartocss) {
    var parse_env = {
      frames: [],
      errors: [],
      error: function(obj) {
        this.errors.push(obj);
      }
    };
    this.parse_env = parse_env;

    var ruleset = null;
    try {
      ruleset = (new carto.Parser(parse_env)).parse(cartocss);
    } catch(e) {
      // add the style.mss string to match the response from the server
      parse_env.errors.push(e.message);
      return;
    }
    if(ruleset) {

      function defKey(def) {
        return def.elements[0] + "::" + def.attachment;
      }
      var defs = ruleset.toList(parse_env);
      defs.reverse();
      // group by elements[0].value::attachment
      var layers = {};
      for(var i = 0; i < defs.length; ++i) {
        var def = defs[i];
        var key = defKey(def);
        var layer = layers[key] = (layers[key] || {
          symbolizers: []
        });
        layer.frames = [];
        layer.zoom = tree.Zoom.all;
        var props = def.toJS(parse_env);
        if (this.options.debug) console.log("props", props);
        for(var v in props) {
          var lyr = layer[v] = layer[v] || {
            constant: false,
            symbolizer: null,
            js: [],
            index: 0
          };
          // build javascript statements
          lyr.js.push(props[v].map(function(a) { return a.js; }).join('\n'));
          // get symbolizer for prop
          lyr.symbolizer = _.first(props[v].map(function(a) { return a.symbolizer; }));
          // serach the max index to know rendering order
          lyr.index = _.max(props[v].map(function(a) { return a.index; }).concat(lyr.index));
          lyr.constant = !_.any(props[v].map(function(a) { return !a.constant; }));
        }
      }

      var ordered_layers = [];
      if (this.options.debug) console.log(layers);

      var done = {};
      for(var i = 0; i < defs.length; ++i) {
        var def = defs[i];
        var k = defKey(def);
        var layer = layers[k];
        if(!done[k]) {
          if(this.options.debug) console.log("**", k);
          for(var prop in layer) {
            if (prop !== 'zoom' && prop !== 'frames' && prop !== 'symbolizers') {
              if(this.options.debug) console.log("*", prop);
              layer[prop].style = this._createFn(layer[prop].js);
              layer.symbolizers.push(layer[prop].symbolizer);
              layer.symbolizers = _.uniq(layer.symbolizers);
            }
          }
          layer.attachment = k;
          ordered_layers.push(layer);
          done[k] = true;
        }
        layer.zoom |= def.zoom;
        layer.frames.push(def.frame_offset);
      }

      // uniq the frames
      for(i = 0; i < ordered_layers.length; ++i) {
        ordered_layers[i].frames = _.uniq(ordered_layers[i].frames);
      }

      return ordered_layers;

    }
    return null;
  }
};

carto.RendererJS = function (options) {
    this.options = options || {};
    this.options.mapnik_version = this.options.mapnik_version || 'latest';
};

// Prepare a javascript object which contains the layers
carto.RendererJS.prototype.render = function render(cartocss, callback) {
    var reference = require('./torque-reference');
    tree.Reference.setData(reference.version.latest);
    return new CartoCSS(cartocss, this.options);
}

if(typeof(module) !== 'undefined') {
  module.exports = carto.RendererJS;
}

})(require('../carto'));
<|endoftext|>


<commit_before>var Controller = function(args) {
  this.actorCanvas = args.actorCanvas;
  this.pac = new Actor({
    context: this.actorCanvas.context,
    startX: 113,
    startY: 212,
    name: "m",
    direction: "right"
  });
  this.blinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "left",
    name: "b",
    startX: 112,
    startY: 116
  });
  this.inky = new Ghost({
    context: this.actorCanvas.context,
    direction: "up",
    name: "i",
    startX: 96,
    startY: 139
  });
  this.pinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "right",
    name: "p",
    startX: 112,
    startY: 139
  });
  this.clyde = new Ghost({
    context: this.actorCanvas.context,
    direction: "down",
    name: "c",
    startX: 128,
    startY: 139
  });
}
Controller.prototype.handleKeyDown = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    this.pac.handleKeyDown(keyPressed);
  }
}
<commit_msg>Add Controller.handleKeyUp<commit_after>var Controller = function(args) {
  this.actorCanvas = args.actorCanvas;
  this.pac = new Actor({
    context: this.actorCanvas.context,
    startX: 113,
    startY: 212,
    name: "m",
    direction: "right"
  });
  this.blinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "left",
    name: "b",
    startX: 112,
    startY: 116
  });
  this.inky = new Ghost({
    context: this.actorCanvas.context,
    direction: "up",
    name: "i",
    startX: 96,
    startY: 139
  });
  this.pinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "right",
    name: "p",
    startX: 112,
    startY: 139
  });
  this.clyde = new Ghost({
    context: this.actorCanvas.context,
    direction: "down",
    name: "c",
    startX: 128,
    startY: 139
  });
}
Controller.prototype.handleKeyDown = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    this.pac.handleKeyDown(keyPressed);
  }
};
Controller.prototype.handleKeyUp = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    this.pac.handleKeyUp(keyPressed);
  }
};
<|endoftext|>


<commit_before>import { Meteor } from "meteor/meteor";
import { DDP } from "meteor/ddp-client";

// Variables exported by this module can be imported by other packages and
// applications. See meteor-serversync-tests.js for an example of importing.
// export const name = 'chfritz:serversync';

/** Server code */
export default class ServerSyncClient {

  /** establish the connection and setup onReconnect handler */
  constructor(URL, onConnected) {
    const self = this;

    this._initialized = false;
    this._connection = DDP.connect(URL);
    this._connection.onReconnect = function() {
      // #HERE: can we update the query of the existing subscriptions
      // to avoid getting a complete re-sync of the entire collection?
      // And/Or implement a remote counter part after all?
      // (ServerSyncServer)
      // there: timestamp all docs with updated time
      // - use https://atmospherejs.com/matb33/collection-hooks to decorate

      console.log("reconnected");

      if (!this._initialized) {
        onConnected && onConnected();
        this._initialized = true;
      } else {
      // Note: on reconnect, Meteor will perform a complete refresh of
      // the remote collections, i.e., it will remove all items and
      // re-add them. This also means that DDP.connect + subscribe are
      // only useful for fairly small collections (in terms of bytes).
        self._rescheduleSyncDirty();
      }
    }

    // objects of the form { remote: .. , local: .., subscription: ..,
    // options: .. }
    this._collections = {};

    // whether or not the initial sync is completed
    this._ready = false;

    // -- sync logging: this is needed in order to break the cycle.
    // ids that have just been updated, i.e., do not sync
    this._changeSets = { remote: {}, local: {} };
  }

  /** schedule a syncDirty for some time from now, if it is already
      scheduled, reschedule. Each remote reschedules this. This way we
      won't syncDirty while changes are still coming in. TODO: This is
      a bit of a #hack. It would be better to have a signal when the
      sync from server is all caught up.
  */
  _rescheduleSyncDirty() {
    const self = this;
    if (this._syncDirtyTimeout) {
      Meteor.clearTimeout(this._syncDirtyTimeout);
    }
    this._syncDirtyTimeout = Meteor.setTimeout(function() {
      self._syncDirty();
    }, 2000);
  }

  /** Subscribe to the given remote collection, creating a synced
      local copy of the result set for the given query.
   @param collectionName: name of publication to sync with
   @param options: an object containing:
    - mode: "online-write" (default), or "read"
    - args: subscription arguments (as given to Meteor.subscribe(.., args))
   */
  sync(collectionName, options = {mode: "online-write", args: []}) {
    const self = this;

    const query = options.query || {};

    this._connection.reconnect();
    // if (!this._connection.status().connected) {
    //   console.log("not connected", this._connection.status());
    //   return false;
    // }

    // check(collectionName, String);
    if (_.has(this._collections, collectionName)) {
      console.log("already subscribed to", collectionName);
      return;
    }

    this._collections[collectionName] = {
      options: options
    };

    // remote collection
    const remoteCollection =
      new Mongo.Collection(collectionName, this._connection);
    this._collections[collectionName].remote = remoteCollection;
    // local collection
    let localCollection = null;
    if (options.mode == "read"
        && options.collection) {

      localCollection = options.collection;
    } else {
      localCollection = new Mongo.Collection(collectionName);
    }
    this._collections[collectionName].local = localCollection;

    // add subscription arguments
    let args = options.args || [];
    args.unshift(collectionName);
    args.push({
      onReady: function() {
        console.log("onReady", collectionName);
        self._ready = true;
        if (options.onReady) {
          options.onReady();
        }

        collectionName && self._syncDirty(collectionName);
      },
      onError: function(e) {
        console.log("onError", e);
      },
      onStop: function(e) {
        console.log("onStop", e);
      }
    });
    const subscription = this._connection.subscribe.apply(this._connection, args);
    this._collections[collectionName].subscription = subscription;

    // ---------------------------------------------------------

    // sync down (from remote to local)
    // each remote change resets the timer for syncDirty
    remoteCollection.find(query).observeChanges({

      added(id, fields) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]) {
          // this remote addition just confirms the local addition
          delete self._changeSets.local[id];
        } else {
          var obj = fields;
          obj._id = id;
          self._changeSets.remote[id] = true;
          localCollection.upsert(id, obj);
          console.log("added by remote");
        }
      },

      changed(id, fields) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]
            && self._changeSets.local[id]._synced) {
          // remote confirmed update
          delete self._changeSets.local[id];
        } else {

          var obj = fields;
          obj._id = id;
          self._changeSets.remote[id] = true;
          // remote changes invalidates local changes:
          delete self._changeSets.local[id];
          localCollection.upsert(id, {$set: obj});
          console.log("changed by remote");
        }
      },

      removed(id) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]
            && self._changeSets.local[id]._synced) {
          // remote confirmed removal
          delete self._changeSets.local[id];
        } else {
          self._changeSets.remote[id] = true;
          // remote changes invalidates local changes:
          delete self._changeSets.local[id];
          localCollection.remove(id);
          console.log("removed by remote");
        }
      }
    });

    // ---------------------------------------------------------

    // sync up (from local to remote)
    if (options.mode != "read") {
      localCollection.find().observeChanges({

        added(id, fields) {
          if (!self._changeSets.remote[id]) {
            // this addition was not initiated by remote; sync up remote
            self._changeSets.local[id] = {
                collectionName: collectionName,
                _synced: true
            };
            var obj = fields;
            obj._id = id;

            if (self._ready && self._connection.status().connected) {
              remoteCollection.upsert(id, obj);
              console.log("added to remote");
            } else {
              // can't sync this right now, add to change set
              console.log("insert queued until reconnect", id);
              self._changeSets.local[id].obj = obj;
              self._changeSets.local[id].action = "insert";
            }
          } else {
            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        },

        changed(id, fields) {
          if (!self._changeSets.remote[id]) {
            // this change was not initiated by remote; sync up remote
            if (!self._changeSets.local[id]) {
              self._changeSets.local[id] = {
                collectionName: collectionName,
                _synced: true
              };
            }

            var obj = fields;
            if (self._ready && self._connection.status().connected) {
              // obj._updated = Date.now();
              // delete obj._dirty;
              remoteCollection.upsert(id, {$set: obj});
              console.log("changed in remote");
            } else {
              // localCollection.update(id, {$set: {"_dirty": true}});
              // console.warn("cannot reach server, not updating;",
                           // "local change will be lost on reconnect");
              console.log("update queued until reconnect", id);
              if (!self._changeSets.local[id].obj) {
                self._changeSets.local[id].obj = {};
              }
              _.extend(self._changeSets.local[id].obj, obj);
              self._changeSets.local[id].action = "update"; // may overwrite "insert"
            }
          } else {
            // else either self was just changed remotely, or it was
            // marked dirty by offline insert locally; don't do anything

            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        },

        removed(id) {
          if (!self._changeSets.remote[id]) {
            // this removal was not initiated by remote; sync up remote
            self._changeSets.local[id] = {
                collectionName: collectionName,
                _synced: true
            }; // this will overwrite any updates or inserts, but that's OK

            if (self._ready && self._connection.status().connected) {
              remoteCollection.remove(id);
              console.log("removed in remote");
            } else {
              // queue up for remote deletion
              // self._locallyDeleted.push({
              //   collectionName: collectionName,
              //   id: id
              // });
              // console.warn("cannot reach server, not removing;",
                           // "local change will be lost on reconnect");
              console.log("removal queued until reconnect", id);
              self._changeSets.local[id].action = "remove";
            }
          } else {
            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        }
      });
    }

  }

  /** sync dirty things, but only if not changed remotely */
  _syncDirty(collectionName) {
    if (this._syncDirtyTimeout) {
      Meteor.clearTimeout(this._syncDirtyTimeout);
    }
    if (!this._connection.status().connected) {
      console.warn("syncDirty failed;",
                   "lost connection again before we could sync",
                   this._connection.status());
      return;
    }

    const self = this;

    // wait for heartbeat:
    // console.log("connection", self._connection);
    // const heartbeat = this._connection._heartbeat;
    // if (!heartbeat) {
    //   Meteor.setTimeout(function() {
    //     // console.log("delayed connection", self._connection);
    //     console.log("waiting for master heartbeat", heartbeat);
    //     self._syncDirty(collectionName);
    //   }, 2000);
    // }

    // console.log("_syncDirty", self._changeSets.local, collectionName);
    console.log("_syncDirty");

    _.each(self._changeSets.local, function(changeInfo, id) {

      changeInfo._synced = true;
      // ^ we need to mark this changeInfo as sync, so we can
      // recognize it when remote confirms it

      // console.log("_syncDirty one", changeInfo, collectionName);
      if (changeInfo.collectionName == collectionName
          || collectionName == undefined) {

        const remoteCollection =
          self._collections[changeInfo.collectionName].remote;

        if (changeInfo.action == "insert") {
          remoteCollection.upsert(id, changeInfo.obj, function(err, res) {
            console.log("insert local -> remote:", id, err, res);
          });
        } else if (changeInfo.action == "update") {
          remoteCollection.upsert(id, {$set: changeInfo.obj}, function(err, res) {
            console.log("update local -> remote:", id, err, res);
          });
        } else if (changeInfo.action == "remove") {
          remoteCollection.remove(id, function(err, res) {
            console.log("removed local -> remote:", id, err, res);
          });
        }
      }
    });

  }

  /** get (local) collection by name */
  getCollection(name) {
    return this._collections[name].local;
  }

};

<commit_msg>Small fix<commit_after>import { Meteor } from "meteor/meteor";
import { DDP } from "meteor/ddp-client";

/** Server code */
export default class ServerSyncClient {

  /** establish the connection and setup onReconnect handler */
  constructor(URL, onConnected) {
    const self = this;

    this._initialized = false;
    this._connection = DDP.connect(URL);
    this._connection.onReconnect = function() {
      console.log("reconnected");

      if (!this._initialized) {
        onConnected && onConnected();
        this._initialized = true;
      } else {
        // Note: on reconnect, Meteor will perform a complete refresh of
        // the remote collections, i.e., it will remove all items and
        // re-add them. This also means that DDP.connect + subscribe are
        // only useful for fairly small collections (in terms of bytes).
        self._rescheduleSyncDirty();
      }
    }

    // objects of the form { remote: .. , local: .., subscription: ..,
    // options: .. }
    this._collections = {};

    // whether or not the initial sync is completed
    this._ready = false;

    // -- sync logging: this is needed in order to break the cycle.
    // ids that have just been updated, i.e., do not sync
    this._changeSets = { remote: {}, local: {} };
  }

  /** schedule a syncDirty for some time from now, if it is already
      scheduled, reschedule. Each remote reschedules this. This way we
      won't syncDirty while changes are still coming in. TODO: This is
      a bit of a #hack. It would be better to have a signal when the
      sync from server is all caught up.
  */
  _rescheduleSyncDirty() {
    const self = this;
    if (this._syncDirtyTimeout) {
      Meteor.clearTimeout(this._syncDirtyTimeout);
    }
    this._syncDirtyTimeout = Meteor.setTimeout(function() {
      self._syncDirty();
    }, 2000);
  }

  /** Subscribe to the given remote collection, creating a synced
      local copy of the result set for the given query.
      @param collectionName: name of publication to sync with
      @param options: an object containing:
      - mode: "write" (default), or "read"
      - args: subscription arguments (as given to Meteor.subscribe(.., args))
  */
  sync(collectionName, options = {mode: "write", args: []}) {
    const self = this;

    const query = options.query || {};

    this._connection.reconnect();

    // check(collectionName, String);
    if (_.has(this._collections, collectionName)) {
      console.log("already subscribed to", collectionName);
      return;
    }

    this._collections[collectionName] = {
      options: options
    };

    // remote collection
    const remoteCollection =
      new Mongo.Collection(collectionName, this._connection);
    this._collections[collectionName].remote = remoteCollection;
    // local collection
    let localCollection = null;
    if (options.mode == "read"
        && options.collection) {

      localCollection = options.collection;
    } else {
      localCollection = new Mongo.Collection(collectionName);
    }
    this._collections[collectionName].local = localCollection;

    // add subscription arguments
    let args = options.args || [];
    args.unshift(collectionName);
    args.push({
      onReady: function() {
        console.log("onReady", collectionName);
        self._ready = true;
        if (options.onReady) {
          options.onReady();
        }

        collectionName && self._syncDirty(collectionName);
      },
      onError: function(e) {
        console.log("onError", e);
      },
      onStop: function(e) {
        console.log("onStop", e);
      }
    });
    const subscription = this._connection.subscribe.apply(this._connection, args);
    this._collections[collectionName].subscription = subscription;

    // ---------------------------------------------------------

    // sync down (from remote to local)
    // each remote change resets the timer for syncDirty
    remoteCollection.find(query).observeChanges({
      // TODO: I may need to use observe here, for the case where a
      // remotely changed document was removed locally: we'll need to
      // reconstruct it

      added(id, fields) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]) {
          // this remote addition just confirms the local addition
          delete self._changeSets.local[id];
        } else {
          var obj = fields;
          obj._id = id;
          self._changeSets.remote[id] = true;
          localCollection.upsert(id, obj);
          console.log("added by remote");
        }
      },

      changed(id, fields) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]
            && self._changeSets.local[id]._synced) {
          // TODO: this trumps remote changes while offline (fix that),
          // at least if set in online-sync, too

          // remote confirmed update
          delete self._changeSets.local[id];
        } else {

          var obj = fields;
          obj._id = id;
          self._changeSets.remote[id] = true;
          // remote changes invalidates local changes:
          delete self._changeSets.local[id];
          if (localCollection.findOne(id)) {
            localCollection.upsert(id, {$set: obj});
          } else {
            // document was removed locally (presumably while
            // offline), recreate it
            localCollection.insert(remoteCollection.findOne(id));
          }
          console.log("changed by remote");
        }
      },

      removed(id) {
        if (self._syncDirtyTimeout) {
          self._rescheduleSyncDirty();
        }
        if (self._changeSets.local[id]
            && self._changeSets.local[id]._synced) {
          // remote confirmed removal
          delete self._changeSets.local[id];
        } else {
          self._changeSets.remote[id] = true;
          // remote changes invalidates local changes:
          delete self._changeSets.local[id];
          localCollection.remove(id);
          console.log("removed by remote");
        }
      }
    });

    // ---------------------------------------------------------

    // sync up (from local to remote)
    if (options.mode != "read") {
      localCollection.find().observeChanges({

        added(id, fields) {
          if (!self._changeSets.remote[id]) {
            // this addition was not initiated by remote; sync up remote
            self._changeSets.local[id] = {
              collectionName: collectionName,
              _synced: true
            };
            var obj = fields;
            obj._id = id;

            if (self._ready && self._connection.status().connected) {
              remoteCollection.upsert(id, obj);
              console.log("added to remote");
            } else {
              // can't sync this right now, add to change set
              console.log("insert queued until reconnect", id);
              self._changeSets.local[id].obj = obj;
              self._changeSets.local[id].action = "insert";
            }
          } else {
            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        },

        changed(id, fields) {
          if (!self._changeSets.remote[id]) {
            // this change was not initiated by remote; sync up remote
            if (!self._changeSets.local[id]) {
              self._changeSets.local[id] = {
                collectionName: collectionName,
                _synced: true
              };
            }

            var obj = fields;
            if (self._ready && self._connection.status().connected) {
              // obj._updated = Date.now();
              // delete obj._dirty;
              remoteCollection.upsert(id, {$set: obj});
              console.log("changed in remote");
            } else {
              // localCollection.update(id, {$set: {"_dirty": true}});
              // console.warn("cannot reach server, not updating;",
              // "local change will be lost on reconnect");
              console.log("update queued until reconnect", id);
              if (!self._changeSets.local[id].obj) {
                self._changeSets.local[id].obj = {};
              }
              _.extend(self._changeSets.local[id].obj, obj);
              self._changeSets.local[id].action = "update"; // may overwrite "insert"
            }
          } else {
            // else either self was just changed remotely, or it was
            // marked dirty by offline insert locally; don't do anything

            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        },

        removed(id) {
          if (!self._changeSets.remote[id]) {
            // this removal was not initiated by remote; sync up remote
            self._changeSets.local[id] = {
              collectionName: collectionName,
              _synced: true
            }; // this will overwrite any updates or inserts, but that's OK

            if (self._ready && self._connection.status().connected) {
              remoteCollection.remove(id);
              console.log("removed in remote");
            } else {
              // queue up for remote deletion
              // self._locallyDeleted.push({
              //   collectionName: collectionName,
              //   id: id
              // });
              // console.warn("cannot reach server, not removing;",
              // "local change will be lost on reconnect");
              console.log("removal queued until reconnect", id);
              self._changeSets.local[id].action = "remove";
            }
          } else {
            // acknowledged, clear flag for next update
            delete self._changeSets.remote[id];
          }
        }
      });
    }

  }

  /** sync dirty things, but only if not changed remotely */
  _syncDirty(collectionName) {
    if (this._syncDirtyTimeout) {
      Meteor.clearTimeout(this._syncDirtyTimeout);
    }
    if (!this._connection.status().connected) {
      console.warn("syncDirty failed;",
                   "lost connection again before we could sync",
                   this._connection.status());
      return;
    }

    const self = this;

    // wait for heartbeat:
    // console.log("connection", self._connection);
    // const heartbeat = this._connection._heartbeat;
    // if (!heartbeat) {
    //   Meteor.setTimeout(function() {
    //     // console.log("delayed connection", self._connection);
    //     console.log("waiting for master heartbeat", heartbeat);
    //     self._syncDirty(collectionName);
    //   }, 2000);
    // }

    // console.log("_syncDirty", self._changeSets.local, collectionName);
    console.log("_syncDirty");

    _.each(self._changeSets.local, function(changeInfo, id) {

      changeInfo._synced = true;
      // ^ we need to mark this changeInfo as sync, so we can
      // recognize it when remote confirms it

      // console.log("_syncDirty one", changeInfo, collectionName);
      if (changeInfo.collectionName == collectionName
          || collectionName == undefined) {

        const remoteCollection =
          self._collections[changeInfo.collectionName].remote;

        if (changeInfo.action == "insert") {
          remoteCollection.upsert(id, changeInfo.obj, function(err, res) {
            console.log("insert local -> remote:", id, err, res);
          });
        } else if (changeInfo.action == "update") {
          remoteCollection.upsert(id, {$set: changeInfo.obj}, function(err, res) {
            console.log("update local -> remote:", id, err, res);
          });
        } else if (changeInfo.action == "remove") {
          remoteCollection.remove(id, function(err, res) {
            console.log("removed local -> remote:", id, err, res);
          });
        }
      }
    });

  }

  /** get (local) collection by name */
  getCollection(name) {
    return this._collections[name].local;
  }

};
<|endoftext|>


<commit_before>Core.Object.extend('Anim.AnimationManager',
/**@lends Anim.AnimationManager#*/
{
	clocks: undefined,
	start: 0,

	/**
    *   @constructs
	*	@class The TimeManager handle animations clocks
    *   @extends Core.Object
	*/
	constructor: function(config) {
		this.onTick.scope = this;
		this.clocks = [];
		this.start = new Date().getTime();
		this.addEvents('tick');
	},

	add: function(clock) {
		this.clocks.push(clock);
		if(this.clocks.length == 1) {
			if('webkitRequestAnimationFrame' in window)
				webkitRequestAnimationFrame(this.onTick);
			else if('mozRequestAnimationFrame' in window)
				mozRequestAnimationFrame(this.onTick);
			else if('msRequestAnimationFrame' in window)
				msRequestAnimationFrame(this.onTick);
			else
				setTimeout(this.onTick, 1/60);
		}
	},

	remove: function(clock) {
		var i = 0;
		while((i < this.clocks.length) && (this.clocks[i] != clock)) { i++ };
		if(i < this.clocks.length)
			this.clocks.splice(i, 1);
	},

	/**	@Private*/
	onTick: function() {
		var scope = arguments.callee.scope;
		var startTime = (new Date().getTime())/1000;

		var current = (new Date().getTime()) - scope.start;
		current /= 1000;
		for(var i = 0; i < scope.clocks.length; i++)
			scope.clocks[i].update(current);
		scope.fireEvent('tick');

		if(scope.clocks.length > 0) {
			if('webkitRequestAnimationFrame' in window)
				webkitRequestAnimationFrame(scope.onTick);
			else if('mozRequestAnimationFrame' in window)
				mozRequestAnimationFrame(scope.onTick);
			else if('msRequestAnimationFrame' in window)
				msRequestAnimationFrame(scope.onTick);
			else {
				var endTime = (new Date().getTime())/1000;
				var deltaTime = endTime - startTime;
				if(deltaTime < 0)
					deltaTime = 0;
				setTimeout(scope.onTick, Math.max(1/60 - deltaTime, 0));
			}
		}
	}
});

Anim.AnimationManager.current = new Anim.AnimationManager();
<commit_msg>provide a useless foreTick in Anim.AnimationManager for the futur<commit_after>Core.Object.extend('Anim.AnimationManager',
/**@lends Anim.AnimationManager#*/
{
	clocks: undefined,
	start: 0,

	/**
    *   @constructs
	*	@class The TimeManager handle animations clocks
    *   @extends Core.Object
	*/
	constructor: function(config) {
		this.onTick.scope = this;
		this.clocks = [];
		this.start = new Date().getTime();
		this.addEvents('tick');
	},

	add: function(clock) {
		this.clocks.push(clock);
		if(this.clocks.length == 1) {
			if('webkitRequestAnimationFrame' in window)
				webkitRequestAnimationFrame(this.onTick);
			else if('mozRequestAnimationFrame' in window)
				mozRequestAnimationFrame(this.onTick);
			else if('msRequestAnimationFrame' in window)
				msRequestAnimationFrame(this.onTick);
			else
				setTimeout(this.onTick, 1/60);
		}
	},

	remove: function(clock) {
		var i = 0;
		while((i < this.clocks.length) && (this.clocks[i] != clock)) { i++ };
		if(i < this.clocks.length)
			this.clocks.splice(i, 1);
	},

	forceTick: function() {
		if(this.clocks.length > 0)
			this.onTick();
	},

	/**	@Private*/
	onTick: function() {
		var scope = arguments.callee.scope;
		var startTime = (new Date().getTime())/1000;

		var current = (new Date().getTime()) - scope.start;
		current /= 1000;
		for(var i = 0; i < scope.clocks.length; i++)
			scope.clocks[i].update(current);
		scope.fireEvent('tick');

		if(scope.clocks.length > 0) {
			if('webkitRequestAnimationFrame' in window)
				webkitRequestAnimationFrame(scope.onTick);
			else if('mozRequestAnimationFrame' in window)
				mozRequestAnimationFrame(scope.onTick);
			else if('msRequestAnimationFrame' in window)
				msRequestAnimationFrame(scope.onTick);
			else {
				var endTime = (new Date().getTime())/1000;
				var deltaTime = endTime - startTime;
				if(deltaTime < 0)
					deltaTime = 0;
				setTimeout(scope.onTick, Math.max(1/60 - deltaTime, 0));
			}
		}
	}
});

Anim.AnimationManager.current = new Anim.AnimationManager();
<|endoftext|>


<commit_before>import React from 'react';
import TextField from 'material-ui/TextField';

const TextFieldExampleSimple = () => (

    <TextField
      hintText="Hint Text"
    />

    <TextField
      hintText="The hint text can be as long as you want, it will wrap."
    />

    <TextField
      id="text-field-default"
      defaultValue="Default Value"
    />

    <TextField
      hintText="Hint Text"
      floatingLabelText="Floating Label Text"
    />

    <TextField
      hintText="Hint Text"
      floatingLabelText="Fixed Floating Label Text"
      floatingLabelFixed={true}
    />

    <TextField
      hintText="Password Field"
      floatingLabelText="Password"
      type="password"
    />

    <TextField
      hintText="MultiLine with rows: 2 and rowsMax: 4"
      multiLine={true}
      rows={2}
      rowsMax={4}
    />

    <TextField
      hintText="Message Field"
      floatingLabelText="MultiLine and FloatingLabel"
      multiLine={true}
      rows={2}
    />

);

export default TextFieldExampleSimple;
<commit_msg>[Docs] Add TextField fullWidth example<commit_after>import React from 'react';
import TextField from 'material-ui/TextField';

const TextFieldExampleSimple = () => (

    <TextField
      hintText="Hint Text"
    />

    <TextField
      hintText="The hint text can be as long as you want, it will wrap."
    />

    <TextField
      id="text-field-default"
      defaultValue="Default Value"
    />

    <TextField
      hintText="Hint Text"
      floatingLabelText="Floating Label Text"
    />

    <TextField
      hintText="Hint Text"
      floatingLabelText="Fixed Floating Label Text"
      floatingLabelFixed={true}
    />

    <TextField
      hintText="Password Field"
      floatingLabelText="Password"
      type="password"
    />

    <TextField
      hintText="MultiLine with rows: 2 and rowsMax: 4"
      multiLine={true}
      rows={2}
      rowsMax={4}
    />

    <TextField
      hintText="Message Field"
      floatingLabelText="MultiLine and FloatingLabel"
      multiLine={true}
      rows={2}
    />

    <TextField
      hintText="Full width"
      fullWidth={true}
    />

);

export default TextFieldExampleSimple;
<|endoftext|>


<commit_before>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009-2010 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

var sys = require('sys');
var http = require('http');
var fs = require('fs');

var application_directory = process.cwd() + "/";

require('./util');

require("./StringToolkit");

require("./Config");

/**
 * The global configuration object.
 *
 * @type Config
 */
config = new Config();

try {
    require(application_directory + "config");
} catch (e) {
    /*
     * It's a pitty, we don't have a config file :(.
     */
}

require("./Options");
require("./Logging");

require("./BootstrapManager");

/**
 * The global bootstrap manager
 *
 * @type BootstrapManager
 */
bootstrap_manager = new BootstrapManager();

require("./ContextToolkit");
require("./Context");

require("./MemoryStorage");
require("./StorageManager");

/**
 * The global storage manager.
 *
 * @type StorageManager
 */
storage_manager = new StorageManager();

require("./server/SessionManager");

require("./server/StaticFilesManager");
static_files_manager = new StaticFilesManager();

require("./Controller");
require("./ControllerManager");

/**
 * The global controller manager.
 *
 * @type ControllerManager
 */
controller_manager = new ControllerManager();

require("./JsView");
require("./EjsView");
require("./ViewManager");

/**
 * The global view manager.
 *
 * @type ViewManager
 */
view_manager = new ViewManager();
view_manager.addViewEngine('ejs', 'EjsView');

require("./DataMapper");
require("./DataMapperManager");

/**
 * The global data mapper manager.
 *
 * @type DataMapperManager
 */
data_mapper_manager = new DataMapperManager();

if (!config.get('core', {}).disable_core_data_mappers) {
    require("./core-data-mappers");
}

require("./Validator");
require("./ValidatorManager");

/**
 * The global validator manager.
 *
 * @type ValidatorManager
 */
validator_manager = new ValidatorManager();

require("./Validation");

if (!config.get('core', {}).disable_core_validators) {
    require("./core-validators");
}
var plugin_names = [];

try {
    plugin_names = fs.readdirSync(application_directory + "plugins");
} catch (e) {
    /*
     * We can't read the plugins directory, cause there is none :(
     */
}

/*
 * Find all /lib, plugin_name/lib folders and append them to the require path.
 */
var lib_folders = [application_directory + "lib"];
for ( var m = 0; m < plugin_names.length; m++) {
    lib_folders.push(application_directory + "plugins/" + plugin_names[m] + "/lib");
}

for ( var f = 0; f < lib_folders.length; f++) {
    var lib_folder_exists = false;
    try {
        var lib_folder_stats = fs.statSync(lib_folders[f]);
        if (lib_folder_stats.isDirectory()) {
            require.paths.push(lib_folders[f]);
            lib_folder_exists = true;
        }
    } catch (e) {
        /*
         * Folder does not exist!
         */
    }
    if (lib_folder_exists) {
        var lib_index_file_exists = false;
        try {
            index_js_stats = fs.statSync(lib_folders[f] + "/index.js");
            lib_index_file_exists = true;
        } catch (e) {
            /*
             * Index file does not exist!
             */
        }

        if (lib_index_file_exists) {
            require(lib_folders[f] + "/index");
        }
    }
}

/*
 * Load the static folder, if the core has one.
 */
try {
    static_folder_stats = fs.statSync(application_directory + "static");
    static_files_manager.addFolder(application_directory + "static/");
} catch (e) {
    /*
    * Folder does not exist!
    */
}

var session_manager_engine = GLOBAL[config.get("session_manager_engine", "SessionManager")];

/**
 * The global session manager.
 *
 * @type SessionManager
 */
session_manager = new session_manager_engine(config.get("session", {}));

/*
 * Load controllers and views
 */
controller_manager.loadControllers(application_directory);
view_manager.loadViews(application_directory);

/*
 * For each plugin, load what needs to be loaded.
 */
for ( var i = 0; i < plugin_names.length; i++) {
    (function (plugin_name) {
        var plugin_folder = application_directory + "plugins/" + plugin_name + "/";

        var plugin_token = bootstrap_manager.createMandatoryElement('plugin.' + plugin_name);

        controller_manager.loadControllers(plugin_folder, plugin_name);
        view_manager.loadViews(plugin_folder, plugin_name);

        try {
            plugin_static_folder_stats = fs.statSync(plugin_folder + "static/");
            static_files_manager.addFolder(plugin_folder + "static/");
        } catch (e) {
            /*
            * Folder does not exist!
            */
        }

        bootstrap_manager.whenReady([
            'plugin.' + plugin_name + '.controllers',
            'plugin.' + plugin_name + '.views'
        ], function() {
            bootstrap_manager.finishMandatoryElement(plugin_token);
        });
    })(plugin_names[i]);
}

require("./BaseApplication");
require("./server/ServerApplication");
require("./console/ConsoleApplication");
require("./test/TestApplication");
<commit_msg>added log_core option to logging, which can be used to automaticly hide the core classes from logging output.<commit_after>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009-2010 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

var sys = require('sys');
var http = require('http');
var fs = require('fs');

var application_directory = process.cwd() + "/";

require('./util');

require("./StringToolkit");

require("./Config");

/**
 * The global configuration object.
 *
 * @type Config
 */
config = new Config();

try {
    require(application_directory + "config");
} catch (e) {
    /*
     * It's a pitty, we don't have a config file :(.
     */
}

if (!config.get('logging', {}).log_core) {
    (function() {
        var logging_config = config.get('logging', {});
        logging_config.hide_classes = logging_config.hide_classes || [];

        var core_classes = [
            "BootstrapManager",
            "ControllerManager",
            "DataMapperManager",
            "StaticFilesManager",
            "StorageManager",
            "ViewManager",
            "ValidatorManager",
            'TestSuiteManager'
        ];

        var core_classes_length = core_classes.length;

        for (var i = 0; i < core_classes_length; i++) {
            logging_config.hide_classes.push(core_classes[i]);
        }

        config.setValues('logging', logging_config);
    })();
}

require("./Options");
require("./Logging");

require("./BootstrapManager");

/**
 * The global bootstrap manager
 *
 * @type BootstrapManager
 */
bootstrap_manager = new BootstrapManager();

require("./ContextToolkit");
require("./Context");

require("./MemoryStorage");
require("./StorageManager");

/**
 * The global storage manager.
 *
 * @type StorageManager
 */
storage_manager = new StorageManager();

require("./server/SessionManager");

require("./server/StaticFilesManager");
static_files_manager = new StaticFilesManager();

require("./Controller");
require("./ControllerManager");

/**
 * The global controller manager.
 *
 * @type ControllerManager
 */
controller_manager = new ControllerManager();

require("./JsView");
require("./EjsView");
require("./ViewManager");

/**
 * The global view manager.
 *
 * @type ViewManager
 */
view_manager = new ViewManager();
view_manager.addViewEngine('ejs', 'EjsView');

require("./DataMapper");
require("./DataMapperManager");

/**
 * The global data mapper manager.
 *
 * @type DataMapperManager
 */
data_mapper_manager = new DataMapperManager();

if (!config.get('core', {}).disable_core_data_mappers) {
    require("./core-data-mappers");
}

require("./Validator");
require("./ValidatorManager");

/**
 * The global validator manager.
 *
 * @type ValidatorManager
 */
validator_manager = new ValidatorManager();

require("./Validation");

if (!config.get('core', {}).disable_core_validators) {
    require("./core-validators");
}
var plugin_names = [];

try {
    plugin_names = fs.readdirSync(application_directory + "plugins");
} catch (e) {
    /*
     * We can't read the plugins directory, cause there is none :(
     */
}

/*
 * Find all /lib, plugin_name/lib folders and append them to the require path.
 */
var lib_folders = [application_directory + "lib"];
for ( var m = 0; m < plugin_names.length; m++) {
    lib_folders.push(application_directory + "plugins/" + plugin_names[m] + "/lib");
}

for ( var f = 0; f < lib_folders.length; f++) {
    var lib_folder_exists = false;
    try {
        var lib_folder_stats = fs.statSync(lib_folders[f]);
        if (lib_folder_stats.isDirectory()) {
            require.paths.push(lib_folders[f]);
            lib_folder_exists = true;
        }
    } catch (e) {
        /*
         * Folder does not exist!
         */
    }
    if (lib_folder_exists) {
        var lib_index_file_exists = false;
        try {
            index_js_stats = fs.statSync(lib_folders[f] + "/index.js");
            lib_index_file_exists = true;
        } catch (e) {
            /*
             * Index file does not exist!
             */
        }

        if (lib_index_file_exists) {
            require(lib_folders[f] + "/index");
        }
    }
}

/*
 * Load the static folder, if the core has one.
 */
try {
    static_folder_stats = fs.statSync(application_directory + "static");
    static_files_manager.addFolder(application_directory + "static/");
} catch (e) {
    /*
    * Folder does not exist!
    */
}

var session_manager_engine = GLOBAL[config.get("session_manager_engine", "SessionManager")];

/**
 * The global session manager.
 *
 * @type SessionManager
 */
session_manager = new session_manager_engine(config.get("session", {}));

/*
 * Load controllers and views
 */
controller_manager.loadControllers(application_directory);
view_manager.loadViews(application_directory);

/*
 * For each plugin, load what needs to be loaded.
 */
for ( var i = 0; i < plugin_names.length; i++) {
    (function (plugin_name) {
        var plugin_folder = application_directory + "plugins/" + plugin_name + "/";

        var plugin_token = bootstrap_manager.createMandatoryElement('plugin.' + plugin_name);

        controller_manager.loadControllers(plugin_folder, plugin_name);
        view_manager.loadViews(plugin_folder, plugin_name);

        try {
            plugin_static_folder_stats = fs.statSync(plugin_folder + "static/");
            static_files_manager.addFolder(plugin_folder + "static/");
        } catch (e) {
            /*
            * Folder does not exist!
            */
        }

        bootstrap_manager.whenReady([
            'plugin.' + plugin_name + '.controllers',
            'plugin.' + plugin_name + '.views'
        ], function() {
            bootstrap_manager.finishMandatoryElement(plugin_token);
        });
    })(plugin_names[i]);
}

require("./BaseApplication");
require("./server/ServerApplication");
require("./console/ConsoleApplication");
require("./test/TestApplication");
<|endoftext|>


<commit_before>Meteor.users.helpers({
	fullName: function() {
		return this.profile.firstName + ' ' + this.profile.lastName.charAt(0) + '.';
	},
	average: function() {
		var sum = 0;
		var result = 0;
		for (var i = 0; i < this.profile.points.length; i++) {
			sum += this.profile.points[i];
		}
		result = Math.round(sum / this.profile.points.length);
		return result;
	},
	nbGames: function() {
		return this.profile.points.length;
	},
	last10GamesPerf: function() {
		var list = [];
		var first = 0;
		var end = 0;
		if (this.profile.points.length > 9) {
			list = this.profile.points.slice(-10);
			first = list[0];
			end = list[9];
			return end - first;
		} else {
			first = this.profile.points[0];
			end = this.profile.points[this.profile.points.length - 1];
			return end - first;
		}
	},
	last5Games: function() {
		var list = [];
		if (this.profile.points.length > 4) {
			list = this.profile.points.slice(-5);
			return list;
		} else {
			return this.profile.points;
		}
	},
	currentPoints: function() {
		return this.profile.points[this.profile.points.length - 1];
	},
	hasPlayed: function() {
		if (this.profile.points.length === 1) {
			return false;
		} else {
			return true;
		}
	}
});

Meteor.methods({
	updateUserData: function(user) {
		check(user.firstName, String);
		check(user.lastName, String);
		check(user.userId, String);
		Meteor.users.update({ _id: user.userId }, {
			$set: {
				'profile.firstName': user.firstName,
				'profile.lastName': user.lastName
			}
		});
	}
});
<commit_msg>Add helper<commit_after>Meteor.users.helpers({
	fullName: function() {
		return this.profile.firstName + ' ' + this.profile.lastName.charAt(0) + '.';
	},
	average: function() {
		var sum = 0;
		var result = 0;
		for (var i = 0; i < this.profile.points.length; i++) {
			sum += this.profile.points[i];
		}
		result = Math.round(sum / this.profile.points.length);
		return result;
	},
	nbGamesWithPoints: function() {
		return this.profile.points.length;
	},
	nbGames: function() {
		return Games.find({ $or: [{ player1: this._id }, { player2: this._id }] }).fetch().length;
	},
	last10GamesPerf: function() {
		var list = [];
		var first = 0;
		var end = 0;
		if (this.profile.points.length > 9) {
			list = this.profile.points.slice(-10);
			first = list[0];
			end = list[9];
			return end - first;
		} else {
			first = this.profile.points[0];
			end = this.profile.points[this.profile.points.length - 1];
			return end - first;
		}
	},
	last5Games: function() {
		var list = [];
		if (this.profile.points.length > 4) {
			list = this.profile.points.slice(-5);
			return list;
		} else {
			return this.profile.points;
		}
	},
	currentPoints: function() {
		return this.profile.points[this.profile.points.length - 1];
	},
	hasPlayed: function() {
		if (this.profile.points.length === 1) {
			return false;
		} else {
			return true;
		}
	}
});

Meteor.methods({
	updateUserData: function(user) {
		check(user.firstName, String);
		check(user.lastName, String);
		check(user.userId, String);
		Meteor.users.update({ _id: user.userId }, {
			$set: {
				'profile.firstName': user.firstName,
				'profile.lastName': user.lastName
			}
		});
	}
});
<|endoftext|>


<commit_before>/*
 * Formatter for Selenium 2 / WebDriver Ruby Test/Unit client.
 */

var subScriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
subScriptLoader.loadSubScript('chrome://selenium-ide/content/formats/webdriver.js', this);

function testClassName(testName) {
  return testName.split(/[^0-9A-Za-z]+/).map(
      function(x) {
        return capitalize(x);
      }).join('');
}

function testMethodName(testName) {
  return "test_" + underscore(testName);
}

function nonBreakingSpace() {
  return "\"\\xa0\"";
}

function array(value) {
  var str = '[';
  for (var i = 0; i < value.length; i++) {
    str += string(value[i]);
    if (i < value.length - 1) str += ", ";
  }
  str += ']';
  return str;
}

notOperator = function() {
  return "!";
};

Equals.prototype.toString = function() {
  return this.e2.toString() + " == " + this.e1.toString();
};

Equals.prototype.assert = function() {
  return "assert_equal " + this.e1.toString() + ", " + this.e2.toString();
};

Equals.prototype.verify = function() {
  return verify(this.assert());
};

NotEquals.prototype.toString = function() {
  return this.e1.toString() + " != " + this.e2.toString();
};

NotEquals.prototype.assert = function() {
  return "assert_not_equal " + this.e1.toString() + ", " + this.e2.toString();
};

NotEquals.prototype.verify = function() {
  return verify(this.assert());
};

function joinExpression(expression) {
  return expression.toString() + ".join(\",\")";
}

function statement(expression) {
  expression.noBraces = true;
  return expression.toString();
}

function assignToVariable(type, variable, expression) {
  return variable + " = " + expression.toString();
}

function ifCondition(expression, callback) {
  return "if " + expression.toString() + "\n" + callback() + "end";
}

function tryCatch(tryStatement, catchStatement, exception) {
  return "begin\n" +
      indents(1) + tryStatement + "\n" +
      "rescue " + exception + " => ex\n" +
      indents(1) + catchStatement + "\n" +
      "end";
}

function assertTrue(expression) {
  return "assert " + expression.toString();
}

function assertFalse(expression) {
  return "assert " + expression.invert().toString();
}

function verify(statement) {
  return "verify { " + statement + " }";
}

function verifyTrue(expression) {
  return verify(assertTrue(expression));
}

function verifyFalse(expression) {
  return verify(assertFalse(expression));
}

RegexpMatch.patternAsRegEx = function(pattern) {
  var str = pattern.replace(/\//g, "\\/");
  if (str.match(/\n/)) {
    str = str.replace(/\n/g, '\\n');
    return '/' + str + '/m';
  } else {
    return str = '/' + str + '/';
  }
};

RegexpMatch.prototype.patternAsRegEx = function() {
  return RegexpMatch.patternAsRegEx(this.pattern);
};

RegexpMatch.prototype.toString = function() {
  return this.expression + " =~ " + this.patternAsRegEx();
};

RegexpMatch.prototype.assert = function() {
  return 'assert_match ' + this.patternAsRegEx() + ', ' + this.expression;
};

RegexpMatch.prototype.verify = function() {
  return verify(this.assert());
};

RegexpNotMatch.prototype.patternAsRegEx = function() {
  return RegexpMatch.patternAsRegEx(this.pattern);
};

RegexpNotMatch.prototype.toString = function() {
  return this.expression + " !~ " + this.patternAsRegEx();
};

RegexpNotMatch.prototype.assert = function() {
  return 'assert_no_match ' + this.patternAsRegEx() + ', ' + this.expression;
};

RegexpNotMatch.prototype.verify = function() {
  return verify(this.assert());
};

function waitFor(expression) {
  if (expression.negative) {
    return "assert !60.times{ break unless (" + expression.invert().toString() + " rescue true); sleep 1 }"
  } else {
    return "assert !60.times{ break if (" + expression.toString() + " rescue false); sleep 1 }"
  }
}

function assertOrVerifyFailure(line, isAssert) {
  return "assert_raise(Kernel) { " + line + "}";
}

function pause(milliseconds) {
  return "sleep " + (parseInt(milliseconds) / 1000);
}

function echo(message) {
  return "p " + xlateArgument(message);
}

function formatComment(comment) {
  return comment.comment.replace(/.+/mg, function(str) {
    return "# " + str;
  });
}

/**
 * Returns a string representing the suite for this formatter language.
 *
 * @param testSuite  the suite to format
 * @param filename   the file the formatted suite will be saved as
 */
function formatSuite(testSuite, filename) {
  formattedSuite = 'require "test/unit"\n' +
      '\n';

  for (var i = 0; i < testSuite.tests.length; ++i) {
    // have saved or loaded a suite
    if (typeof testSuite.tests[i].filename != 'undefined') {
      formattedSuite += 'require "' + testSuite.tests[i].filename.replace(/\.\w+$/, '') + '"\n';
    } else {
      // didn't load / save as a suite
      var testFile = testSuite.tests[i].getTitle();
      formattedSuite += 'require "' + testFile + '"\n';
    }
  }
  return result;
}

function defaultExtension() {
  return this.options.defaultExtension;
}

this.options = {
  receiver: "@driver",
  showSelenese: 'false',
  header:
      'require "selenium-webdriver"\n' +
          'require "test/unit"\n' +
          '\n' +
          'class ${className} < Test::Unit::TestCase\n' +
          '\n' +
          '  def setup\n' +
          '    ${receiver} = Selenium::WebDriver.for :firefox\n' +
          '    @base_url = "${baseURL}"\n' +
          '    ${receiver}.manage.timeouts.implicit_wait = 30\n' +
          '    @verification_errors = []\n' +
          '  end\n' +
          '  \n' +
          '  def teardown\n' +
          '    ${receiver}.quit\n' +
          '    assert_equal [], @verification_errors\n' +
          '  end\n' +
          '  \n' +
          '  def ${methodName}\n',
  footer:
      "  end\n" +
          "  \n" +
          "  def element_present?(how, what)\n" +
          "    @driver.find_element(how, what)\n" +
          "    true\n" +
          "  rescue Selenium::WebDriver::Error::NoSuchElementError\n" +
          "    false\n" +
          "  end\n" +
          "  \n" +
          "  def verify(&blk)\n" +
          "    yield\n" +
          "  rescue Test::Unit::AssertionFailedError => ex\n" +
          "    @verification_errors << ex\n" +
          "  end\n" +
          "end\n",
  indent: "2",
  initialIndents: "2",
  defaultExtension: "rb"
};

this.configForm =
    '<description>Variable for Selenium instance</description>' +
        '<textbox id="options_receiver" />' +
        '<description>Header</description>' +
        '<textbox id="options_header" multiline="true" flex="1" rows="4"/>' +
        '<description>Footer</description>' +
        '<textbox id="options_footer" multiline="true" flex="1" rows="4"/>' +
        '<description>Indent</description>' +
        '<menulist id="options_indent"><menupopup>' +
        '<menuitem label="Tab" value="tab"/>' +
        '<menuitem label="1 space" value="1"/>' +
        '<menuitem label="2 spaces" value="2"/>' +
        '<menuitem label="3 spaces" value="3"/>' +
        '<menuitem label="4 spaces" value="4"/>' +
        '<menuitem label="5 spaces" value="5"/>' +
        '<menuitem label="6 spaces" value="6"/>' +
        '<menuitem label="7 spaces" value="7"/>' +
        '<menuitem label="8 spaces" value="8"/>' +
        '</menupopup></menulist>' +
        '<checkbox id="options_showSelenese" label="Show Selenese"/>';

this.name = "Ruby Test/Unit (WebDriver)";
this.testcaseExtension = ".rb";
this.suiteExtension = ".rb";
this.webdriver = true;

WDAPI.Driver = function() {
  this.ref = options.receiver;
};

WDAPI.Driver.searchContext = function(locatorType, locator) {
  var locatorString = xlateArgument(locator);
  switch (locatorType) {
    case 'xpath':
      return ':xpath, ' + locatorString;
    case 'css':
      return ':css, ' + locatorString;
    case 'id':
      return ':id, ' + locatorString;
    case 'link':
      return ':link, ' + locatorString;
    case 'name':
      return ':name, ' + locatorString;
    case 'tag_name':
      return ':tag_name, ' + locatorString;
  }
  throw 'Error: unknown strategy [' + locatorType + '] for locator [' + locator + ']';
};

WDAPI.Driver.prototype.back = function() {
  return this.ref + ".navigate.back";
};

WDAPI.Driver.prototype.close = function() {
  return this.ref + ".close";
};

WDAPI.Driver.prototype.findElement = function(locatorType, locator) {
  return new WDAPI.Element(this.ref + ".find_element(" + WDAPI.Driver.searchContext(locatorType, locator) + ")");
};

WDAPI.Driver.prototype.findElements = function(locatorType, locator) {
  return new WDAPI.ElementList(this.ref + ".find_elements(" + WDAPI.Driver.searchContext(locatorType, locator) + ")");
};

WDAPI.Driver.prototype.getCurrentUrl = function() {
  return this.ref + ".current_url";
};

WDAPI.Driver.prototype.get = function(url) {
  if (url.length > 1 && (url.substring(1,8) == "http://" || url.substring(1,9) == "https://")) { // url is quoted
    return this.ref + ".get " + url;
  } else {
    return this.ref + ".get(@base_url + " + url + ")";
  }
};

WDAPI.Driver.prototype.getTitle = function() {
  return this.ref + ".title";
};

WDAPI.Driver.prototype.refresh = function() {
  return this.ref + ".navigate.refresh";
};

WDAPI.Element = function(ref) {
  this.ref = ref;
};

WDAPI.Element.prototype.clear = function() {
  return this.ref + ".clear";
};

WDAPI.Element.prototype.click = function() {
  return this.ref + ".click";
};

WDAPI.Element.prototype.getAttribute = function(attributeName) {
  return this.ref + ".attribute(" + xlateArgument(attributeName) + ")";
};

WDAPI.Element.prototype.getText = function() {
  return this.ref + ".text";
};

WDAPI.Element.prototype.isDisplayed = function() {
  return this.ref + ".displayed?";
};

WDAPI.Element.prototype.isSelected = function() {
  return this.ref + ".selected?";
};

WDAPI.Element.prototype.sendKeys = function(text) {
  return this.ref + ".send_keys " + xlateArgument(text) + "";
};

WDAPI.Element.prototype.submit = function() {
  return this.ref + ".submit";
};

WDAPI.Element.prototype.select = function(label) {
  return "Selenium::WebDriver::Support::Select.new(" + this.ref + ").select_by(:text, " + xlateArgument(label) + ")";
};

WDAPI.ElementList = function(ref) {
  this.ref = ref;
};

WDAPI.ElementList.prototype.getItem = function(index) {
  return this.ref + "[" + index + "]";
};

WDAPI.ElementList.prototype.getSize = function() {
  return this.ref + ".size";
};

WDAPI.ElementList.prototype.isEmpty = function() {
  return this.ref + ".empty?";
};

WDAPI.Utils = function() {
};

WDAPI.Utils.isElementPresent = function(how, what) {
  return "element_present?(:" + how + ", " + xlateArgument(what) + ")";
};
<commit_msg>DaveHunt: Corrected typo in Ruby WebDriver test suite export method. Fixes issue 3243<commit_after>/*
 * Formatter for Selenium 2 / WebDriver Ruby Test/Unit client.
 */

var subScriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
subScriptLoader.loadSubScript('chrome://selenium-ide/content/formats/webdriver.js', this);

function testClassName(testName) {
  return testName.split(/[^0-9A-Za-z]+/).map(
      function(x) {
        return capitalize(x);
      }).join('');
}

function testMethodName(testName) {
  return "test_" + underscore(testName);
}

function nonBreakingSpace() {
  return "\"\\xa0\"";
}

function array(value) {
  var str = '[';
  for (var i = 0; i < value.length; i++) {
    str += string(value[i]);
    if (i < value.length - 1) str += ", ";
  }
  str += ']';
  return str;
}

notOperator = function() {
  return "!";
};

Equals.prototype.toString = function() {
  return this.e2.toString() + " == " + this.e1.toString();
};

Equals.prototype.assert = function() {
  return "assert_equal " + this.e1.toString() + ", " + this.e2.toString();
};

Equals.prototype.verify = function() {
  return verify(this.assert());
};

NotEquals.prototype.toString = function() {
  return this.e1.toString() + " != " + this.e2.toString();
};

NotEquals.prototype.assert = function() {
  return "assert_not_equal " + this.e1.toString() + ", " + this.e2.toString();
};

NotEquals.prototype.verify = function() {
  return verify(this.assert());
};

function joinExpression(expression) {
  return expression.toString() + ".join(\",\")";
}

function statement(expression) {
  expression.noBraces = true;
  return expression.toString();
}

function assignToVariable(type, variable, expression) {
  return variable + " = " + expression.toString();
}

function ifCondition(expression, callback) {
  return "if " + expression.toString() + "\n" + callback() + "end";
}

function tryCatch(tryStatement, catchStatement, exception) {
  return "begin\n" +
      indents(1) + tryStatement + "\n" +
      "rescue " + exception + " => ex\n" +
      indents(1) + catchStatement + "\n" +
      "end";
}

function assertTrue(expression) {
  return "assert " + expression.toString();
}

function assertFalse(expression) {
  return "assert " + expression.invert().toString();
}

function verify(statement) {
  return "verify { " + statement + " }";
}

function verifyTrue(expression) {
  return verify(assertTrue(expression));
}

function verifyFalse(expression) {
  return verify(assertFalse(expression));
}

RegexpMatch.patternAsRegEx = function(pattern) {
  var str = pattern.replace(/\//g, "\\/");
  if (str.match(/\n/)) {
    str = str.replace(/\n/g, '\\n');
    return '/' + str + '/m';
  } else {
    return str = '/' + str + '/';
  }
};

RegexpMatch.prototype.patternAsRegEx = function() {
  return RegexpMatch.patternAsRegEx(this.pattern);
};

RegexpMatch.prototype.toString = function() {
  return this.expression + " =~ " + this.patternAsRegEx();
};

RegexpMatch.prototype.assert = function() {
  return 'assert_match ' + this.patternAsRegEx() + ', ' + this.expression;
};

RegexpMatch.prototype.verify = function() {
  return verify(this.assert());
};

RegexpNotMatch.prototype.patternAsRegEx = function() {
  return RegexpMatch.patternAsRegEx(this.pattern);
};

RegexpNotMatch.prototype.toString = function() {
  return this.expression + " !~ " + this.patternAsRegEx();
};

RegexpNotMatch.prototype.assert = function() {
  return 'assert_no_match ' + this.patternAsRegEx() + ', ' + this.expression;
};

RegexpNotMatch.prototype.verify = function() {
  return verify(this.assert());
};

function waitFor(expression) {
  if (expression.negative) {
    return "assert !60.times{ break unless (" + expression.invert().toString() + " rescue true); sleep 1 }"
  } else {
    return "assert !60.times{ break if (" + expression.toString() + " rescue false); sleep 1 }"
  }
}

function assertOrVerifyFailure(line, isAssert) {
  return "assert_raise(Kernel) { " + line + "}";
}

function pause(milliseconds) {
  return "sleep " + (parseInt(milliseconds) / 1000);
}

function echo(message) {
  return "p " + xlateArgument(message);
}

function formatComment(comment) {
  return comment.comment.replace(/.+/mg, function(str) {
    return "# " + str;
  });
}

/**
 * Returns a string representing the suite for this formatter language.
 *
 * @param testSuite  the suite to format
 * @param filename   the file the formatted suite will be saved as
 */
function formatSuite(testSuite, filename) {
  formattedSuite = 'require "test/unit"\n' +
      '\n';

  for (var i = 0; i < testSuite.tests.length; ++i) {
    // have saved or loaded a suite
    if (typeof testSuite.tests[i].filename != 'undefined') {
      formattedSuite += 'require "' + testSuite.tests[i].filename.replace(/\.\w+$/, '') + '"\n';
    } else {
      // didn't load / save as a suite
      var testFile = testSuite.tests[i].getTitle();
      formattedSuite += 'require "' + testFile + '"\n';
    }
  }
  return formattedSuite;
}

function defaultExtension() {
  return this.options.defaultExtension;
}

this.options = {
  receiver: "@driver",
  showSelenese: 'false',
  header:
      'require "selenium-webdriver"\n' +
          'require "test/unit"\n' +
          '\n' +
          'class ${className} < Test::Unit::TestCase\n' +
          '\n' +
          '  def setup\n' +
          '    ${receiver} = Selenium::WebDriver.for :firefox\n' +
          '    @base_url = "${baseURL}"\n' +
          '    ${receiver}.manage.timeouts.implicit_wait = 30\n' +
          '    @verification_errors = []\n' +
          '  end\n' +
          '  \n' +
          '  def teardown\n' +
          '    ${receiver}.quit\n' +
          '    assert_equal [], @verification_errors\n' +
          '  end\n' +
          '  \n' +
          '  def ${methodName}\n',
  footer:
      "  end\n" +
          "  \n" +
          "  def element_present?(how, what)\n" +
          "    @driver.find_element(how, what)\n" +
          "    true\n" +
          "  rescue Selenium::WebDriver::Error::NoSuchElementError\n" +
          "    false\n" +
          "  end\n" +
          "  \n" +
          "  def verify(&blk)\n" +
          "    yield\n" +
          "  rescue Test::Unit::AssertionFailedError => ex\n" +
          "    @verification_errors << ex\n" +
          "  end\n" +
          "end\n",
  indent: "2",
  initialIndents: "2",
  defaultExtension: "rb"
};

this.configForm =
    '<description>Variable for Selenium instance</description>' +
        '<textbox id="options_receiver" />' +
        '<description>Header</description>' +
        '<textbox id="options_header" multiline="true" flex="1" rows="4"/>' +
        '<description>Footer</description>' +
        '<textbox id="options_footer" multiline="true" flex="1" rows="4"/>' +
        '<description>Indent</description>' +
        '<menulist id="options_indent"><menupopup>' +
        '<menuitem label="Tab" value="tab"/>' +
        '<menuitem label="1 space" value="1"/>' +
        '<menuitem label="2 spaces" value="2"/>' +
        '<menuitem label="3 spaces" value="3"/>' +
        '<menuitem label="4 spaces" value="4"/>' +
        '<menuitem label="5 spaces" value="5"/>' +
        '<menuitem label="6 spaces" value="6"/>' +
        '<menuitem label="7 spaces" value="7"/>' +
        '<menuitem label="8 spaces" value="8"/>' +
        '</menupopup></menulist>' +
        '<checkbox id="options_showSelenese" label="Show Selenese"/>';

this.name = "Ruby Test/Unit (WebDriver)";
this.testcaseExtension = ".rb";
this.suiteExtension = ".rb";
this.webdriver = true;

WDAPI.Driver = function() {
  this.ref = options.receiver;
};

WDAPI.Driver.searchContext = function(locatorType, locator) {
  var locatorString = xlateArgument(locator);
  switch (locatorType) {
    case 'xpath':
      return ':xpath, ' + locatorString;
    case 'css':
      return ':css, ' + locatorString;
    case 'id':
      return ':id, ' + locatorString;
    case 'link':
      return ':link, ' + locatorString;
    case 'name':
      return ':name, ' + locatorString;
    case 'tag_name':
      return ':tag_name, ' + locatorString;
  }
  throw 'Error: unknown strategy [' + locatorType + '] for locator [' + locator + ']';
};

WDAPI.Driver.prototype.back = function() {
  return this.ref + ".navigate.back";
};

WDAPI.Driver.prototype.close = function() {
  return this.ref + ".close";
};

WDAPI.Driver.prototype.findElement = function(locatorType, locator) {
  return new WDAPI.Element(this.ref + ".find_element(" + WDAPI.Driver.searchContext(locatorType, locator) + ")");
};

WDAPI.Driver.prototype.findElements = function(locatorType, locator) {
  return new WDAPI.ElementList(this.ref + ".find_elements(" + WDAPI.Driver.searchContext(locatorType, locator) + ")");
};

WDAPI.Driver.prototype.getCurrentUrl = function() {
  return this.ref + ".current_url";
};

WDAPI.Driver.prototype.get = function(url) {
  if (url.length > 1 && (url.substring(1,8) == "http://" || url.substring(1,9) == "https://")) { // url is quoted
    return this.ref + ".get " + url;
  } else {
    return this.ref + ".get(@base_url + " + url + ")";
  }
};

WDAPI.Driver.prototype.getTitle = function() {
  return this.ref + ".title";
};

WDAPI.Driver.prototype.refresh = function() {
  return this.ref + ".navigate.refresh";
};

WDAPI.Element = function(ref) {
  this.ref = ref;
};

WDAPI.Element.prototype.clear = function() {
  return this.ref + ".clear";
};

WDAPI.Element.prototype.click = function() {
  return this.ref + ".click";
};

WDAPI.Element.prototype.getAttribute = function(attributeName) {
  return this.ref + ".attribute(" + xlateArgument(attributeName) + ")";
};

WDAPI.Element.prototype.getText = function() {
  return this.ref + ".text";
};

WDAPI.Element.prototype.isDisplayed = function() {
  return this.ref + ".displayed?";
};

WDAPI.Element.prototype.isSelected = function() {
  return this.ref + ".selected?";
};

WDAPI.Element.prototype.sendKeys = function(text) {
  return this.ref + ".send_keys " + xlateArgument(text) + "";
};

WDAPI.Element.prototype.submit = function() {
  return this.ref + ".submit";
};

WDAPI.Element.prototype.select = function(label) {
  return "Selenium::WebDriver::Support::Select.new(" + this.ref + ").select_by(:text, " + xlateArgument(label) + ")";
};

WDAPI.ElementList = function(ref) {
  this.ref = ref;
};

WDAPI.ElementList.prototype.getItem = function(index) {
  return this.ref + "[" + index + "]";
};

WDAPI.ElementList.prototype.getSize = function() {
  return this.ref + ".size";
};

WDAPI.ElementList.prototype.isEmpty = function() {
  return this.ref + ".empty?";
};

WDAPI.Utils = function() {
};

WDAPI.Utils.isElementPresent = function(how, what) {
  return "element_present?(:" + how + ", " + xlateArgument(what) + ")";
};
<|endoftext|>


<commit_before>// ==========================================
// BOWER: Lookup API
// ==========================================
// Copyright 2012 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================

var Emitter  = require('events').EventEmitter;
var nopt     = require('nopt');
var readline = require('readline');

var template = require('../util/template');
var source   = require('../core/source');
var help     = require('./help');

var optionTypes = { help: Boolean };
var shorthand   = { 'h': ['--help'] };

module.exports = function (name, url) {
  var emitter = new Emitter;
  var rl      = readline.createInterface({ input: process.stdin, output: process.stdout });

  console.log('Registering a package will make it visible and installable via the registry.');
  rl.question('Proceed (y/n)? ', function (res) {
    rl.close();

    res = res.toLowerCase();

    if (res === 'y' || res === 'yes') {
      source.register(name, url, function (err) {
        if (err) return emitter.emit('error', err);

        template('register', {name: name, url: url})
          .on('data', emitter.emit.bind(emitter, 'data'));
      });
    }
  });

  return emitter;
};

module.exports.line = function (argv) {
  var options  = nopt(optionTypes, shorthand, argv);
  var args     = options.argv.remain.slice(1);

  if (options.help || args.length !== 2) return help('register');
  return module.exports(args[0], args[1]);
};<commit_msg>Add silent option to the register command.<commit_after>// ==========================================
// BOWER: Lookup API
// ==========================================
// Copyright 2012 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================

var Emitter  = require('events').EventEmitter;
var nopt     = require('nopt');
var readline = require('readline');

var template = require('../util/template');
var source   = require('../core/source');
var help     = require('./help');

var optionTypes = { help: Boolean };
var shorthand   = { 'h': ['--help'], '-s': ['--silent'] };

var register = function (name, url, emitter)  {
  source.register(name, url, function (err) {
    if (err) return emitter.emit('error', err);

    template('register', {name: name, url: url})
      .on('data', emitter.emit.bind(emitter, 'data'));
  });
};

module.exports = function (name, url, options) {
  var emitter = new Emitter;

  if (options.silent) register(name, url, emitter);
  else {
    var rl = readline.createInterface({ input: process.stdin, output: process.stdout });

    console.log('Registering a package will make it visible and installable via the registry.');
    rl.question('Proceed (y/n)? ', function (res) {
      rl.close();

      res = res.toLowerCase();

      if (res === 'y' || res === 'yes') register(name, url, emitter);
    });
  }

  return emitter;
};

module.exports.line = function (argv) {
  var options  = nopt(optionTypes, shorthand, argv);
  var args     = options.argv.remain.slice(1);

  if (options.help || args.length !== 2) return help('register');
  return module.exports(args[0], args[1], options);
};

module.exports.completion = function (opts, cb) {
  var word = opts.word;

  // completing options?
  if (word.charAt(0) === '-') {
    return cb(null, Object.keys(optionTypes).map(function (option) {
      return '--' + option;
    }));
  }
};<|endoftext|>


<commit_before>var ModelUpdateNothing = 0
var ModelUpdateInsert = 1
var ModelUpdateUpdate = 2

var ModelUpdateRange = function(type, length) {
	this.type = type
	this.length = length
}

exports.ModelUpdate = function() {
	this.count = 0
	this._reset()
}
exports.ModelUpdate.prototype.constructor = exports.ModelUpdate

exports.ModelUpdate.prototype._reset = function() {
	this._ranges = [new ModelUpdateRange(ModelUpdateNothing, this.count)]
	this._updateIndex = this.count
}

exports.ModelUpdate.prototype._setUpdateIndex = function(begin) {
	if (begin < this._updateIndex)
		this._updateIndex = begin
}

exports.ModelUpdate.prototype._find = function(index) {
	var ranges = this._ranges
	var i
	for(i = 0; i < ranges.length; ++i) {
		var range = ranges[i]
		if (index < range.length)
			return { index: i, offset: index }
		if (range.length > 0)
			index -= range.length
	}
	if (index != 0)
		throw new Error('invalid index ' + index)

	return { index: i - 1, offset: 0 }
}

exports.ModelUpdate.prototype.reset = function(model) {
	this.update(model, 0, Math.min(model.count, this.count))
	if (this.count < model.count) {
		this.insert(model, this.count, model.count)
	} else {
		this.remove(model, model.count, this.count)
	}
}

exports.ModelUpdate.prototype._merge = function() {
	var ranges = this._ranges
	for(var index = 1; index < ranges.length; ) {
		var range = ranges[index - 1]
		var nextRange = ranges[index]
		if (range.type === nextRange.type) {
			range.length += nextRange.length
			ranges.splice(index, 1)
		} else
			++index
	}
}

exports.ModelUpdate.prototype._split = function(index, offset, type, length) {
	var ranges = this._ranges
	if (offset == 0) {
		ranges.splice(index, 0, new ModelUpdateRange(type, length))
		return index + 1
	} else {
		var range = ranges[index]
		var right = range.length - offset
		range.length = offset
		if (right != 0) {
			ranges.splice(index + 1, 0,
				new ModelUpdateRange(type, length),
				new ModelUpdateRange(range.type, right))
			return index + 2
		} else {
			ranges.splice(index, 0,
				new ModelUpdateRange(type, length))
			return index + 1
		}
	}
}

exports.ModelUpdate.prototype.insert = function(model, begin, end) {
	if (begin >= end)
		return

	this._setUpdateIndex(begin)
	var ranges = this._ranges
	var d = end - begin
	this.count += d
	if (this.count != model.count)
		throw new Error('unbalanced insert ' + this.count + ' + [' + begin + '-' + end + '], model reported ' + model.count)

	var res = this._find(begin)
	var range = ranges[res.index]
	if (range.length == 0) { //first insert
		range.type = ModelUpdateInsert
		range.length += d
	} else if (range.type == ModelUpdateInsert) {
		range.length += d
	} else {
		this._split(res.index, res.offset, ModelUpdateInsert, d)
	}
	this._merge()
}

exports.ModelUpdate.prototype.remove = function(model, begin, end) {
	if (begin >= end)
		return

	this._setUpdateIndex(begin)
	var ranges = this._ranges
	var d = end - begin
	this.count -= d
	if (this.count != model.count)
		throw new Error('unbalanced remove ' + this.count + ' + [' + begin + '-' + end + '], model reported ' + model.count)

	var res = this._find(begin)
	var range = ranges[res.index]

	if (range.type == ModelUpdateInsert) {
		range.length -= d
	} else {
		var index = this._split(res.index, res.offset, ModelUpdateInsert, -d)
		while(d > 0) {
			var range = ranges[index]
			if (range.length <= d) {
				ranges.splice(index, 1)
				d -= range.length
			} else {
				range.length -= d
			}
		}
	}
	this._merge()
}

exports.ModelUpdate.prototype.update = function(model, begin, end) {
	if (begin >= end)
		return

	var ranges = this._ranges
	var n = end - begin
	var res = this._find(begin)
	var index = res.index

	var range = ranges[index]
	if (res.offset > 0) {
		ranges.splice(index + 1, 0, new ModelUpdateRange(ModelUpdateNothing, range.length - res.offset))
		range.length = res.offset
		++index
		if (range.length == 0)
			throw new Error('invalid offset')
	}

	while(n > 0) {
		var range = ranges[index]
		var length = range.length
		switch(range.type) {
			case ModelUpdateNothing:
				if (length > n) {
					//range larger than needed
					range.length -= n
					ranges.splice(index, 0, new ModelUpdateRange(ModelUpdateUpdate, n))
					n -= length
				} else { //length <= n
					range.type = ModelUpdateUpdate
					n -= length
				}
				break
			case ModelUpdateInsert:
				if (length > 0) {
					n -= length
					++index
				}
				break
			case ModelUpdateUpdate:
				n -= length
				++index
				break
		}
	}
	this._merge()
}

exports.ModelUpdate.prototype.apply = function(view) {
	var index = 0
	this._ranges.forEach(
		function(range) {
			var n = range.length
			switch(range.type) {
				case ModelUpdateInsert:
					if (n > 0) {
						view._insertItems(index, index + n)
						index += n
					} else {
						view._removeItems(index, index - n)
					}
					break
				case ModelUpdateUpdate:
					view._updateItems(index, index + n)
					index += n
					break
				default:
					index += range.length
			}
		}
	)
	if (view._items.length != this.count)
		throw new Error('unbalanced items update, view: ' + view._items.length + ', update:' + this.count)

	for(var i = this._updateIndex; i < this.count; ++i)
		view._updateDelegateIndex(i)
	this._reset()
}
<commit_msg>return real index and offset == length for last segment<commit_after>var ModelUpdateNothing = 0
var ModelUpdateInsert = 1
var ModelUpdateUpdate = 2

var ModelUpdateRange = function(type, length) {
	this.type = type
	this.length = length
}

exports.ModelUpdate = function() {
	this.count = 0
	this._reset()
}
exports.ModelUpdate.prototype.constructor = exports.ModelUpdate

exports.ModelUpdate.prototype._reset = function() {
	this._ranges = [new ModelUpdateRange(ModelUpdateNothing, this.count)]
	this._updateIndex = this.count
}

exports.ModelUpdate.prototype._setUpdateIndex = function(begin) {
	if (begin < this._updateIndex)
		this._updateIndex = begin
}

exports.ModelUpdate.prototype._find = function(index) {
	var ranges = this._ranges
	var i
	for(i = 0; i < ranges.length; ++i) {
		var range = ranges[i]
		if (index < range.length)
			return { index: i, offset: index }
		if (range.length > 0)
			index -= range.length
	}
	if (index != 0)
		throw new Error('invalid index ' + index)

	return { index: i - 1, offset: range.length }
}

exports.ModelUpdate.prototype.reset = function(model) {
	this.update(model, 0, Math.min(model.count, this.count))
	if (this.count < model.count) {
		this.insert(model, this.count, model.count)
	} else {
		this.remove(model, model.count, this.count)
	}
}

exports.ModelUpdate.prototype._merge = function() {
	var ranges = this._ranges
	for(var index = 1; index < ranges.length; ) {
		var range = ranges[index - 1]
		var nextRange = ranges[index]
		if (range.type === nextRange.type) {
			range.length += nextRange.length
			ranges.splice(index, 1)
		} else
			++index
	}
}

exports.ModelUpdate.prototype._split = function(index, offset, type, length) {
	var ranges = this._ranges
	if (offset == 0) {
		ranges.splice(index, 0, new ModelUpdateRange(type, length))
		return index + 1
	} else {
		var range = ranges[index]
		var right = range.length - offset
		range.length = offset
		if (right != 0) {
			ranges.splice(index + 1, 0,
				new ModelUpdateRange(type, length),
				new ModelUpdateRange(range.type, right))
			return index + 2
		} else {
			ranges.splice(index, 0,
				new ModelUpdateRange(type, length))
			return index + 1
		}
	}
}

exports.ModelUpdate.prototype.insert = function(model, begin, end) {
	if (begin >= end)
		return

	this._setUpdateIndex(begin)
	var ranges = this._ranges
	var d = end - begin
	this.count += d
	if (this.count != model.count)
		throw new Error('unbalanced insert ' + this.count + ' + [' + begin + '-' + end + '], model reported ' + model.count)

	var res = this._find(begin)
	var range = ranges[res.index]
	if (range.length == 0) { //first insert
		range.type = ModelUpdateInsert
		range.length += d
	} else if (range.type == ModelUpdateInsert) {
		range.length += d
	} else {
		this._split(res.index, res.offset, ModelUpdateInsert, d)
	}
	this._merge()
}

exports.ModelUpdate.prototype.remove = function(model, begin, end) {
	if (begin >= end)
		return

	this._setUpdateIndex(begin)
	var ranges = this._ranges
	var d = end - begin
	this.count -= d
	if (this.count != model.count)
		throw new Error('unbalanced remove ' + this.count + ' + [' + begin + '-' + end + '], model reported ' + model.count)

	var res = this._find(begin)
	var range = ranges[res.index]

	if (range.type == ModelUpdateInsert) {
		range.length -= d
	} else {
		var index = this._split(res.index, res.offset, ModelUpdateInsert, -d)
		while(d > 0) {
			var range = ranges[index]
			if (range.length <= d) {
				ranges.splice(index, 1)
				d -= range.length
			} else {
				range.length -= d
			}
		}
	}
	this._merge()
}

exports.ModelUpdate.prototype.update = function(model, begin, end) {
	if (begin >= end)
		return

	var ranges = this._ranges
	var n = end - begin
	var res = this._find(begin)
	var index = res.index

	var range = ranges[index]
	if (res.offset > 0) {
		ranges.splice(index + 1, 0, new ModelUpdateRange(ModelUpdateNothing, range.length - res.offset))
		range.length = res.offset
		++index
		if (range.length == 0)
			throw new Error('invalid offset')
	}

	while(n > 0) {
		var range = ranges[index]
		var length = range.length
		switch(range.type) {
			case ModelUpdateNothing:
				if (length > n) {
					//range larger than needed
					range.length -= n
					ranges.splice(index, 0, new ModelUpdateRange(ModelUpdateUpdate, n))
					n -= length
				} else { //length <= n
					range.type = ModelUpdateUpdate
					n -= length
				}
				break
			case ModelUpdateInsert:
				if (length > 0) {
					n -= length
					++index
				}
				break
			case ModelUpdateUpdate:
				n -= length
				++index
				break
		}
	}
	this._merge()
}

exports.ModelUpdate.prototype.apply = function(view) {
	var index = 0
	this._ranges.forEach(
		function(range) {
			var n = range.length
			switch(range.type) {
				case ModelUpdateInsert:
					if (n > 0) {
						view._insertItems(index, index + n)
						index += n
					} else {
						view._removeItems(index, index - n)
					}
					break
				case ModelUpdateUpdate:
					view._updateItems(index, index + n)
					index += n
					break
				default:
					index += range.length
			}
		}
	)
	if (view._items.length != this.count)
		throw new Error('unbalanced items update, view: ' + view._items.length + ', update:' + this.count)

	for(var i = this._updateIndex; i < this.count; ++i)
		view._updateDelegateIndex(i)
	this._reset()
}
<|endoftext|>