<commit_before>(function() {

var checkVersion = Dagaz.Model.checkVersion;

Dagaz.Model.checkVersion = function(design, name, value) {
  if (name != "renju-invariant") {
      checkVersion(design, name, value);
  }
}

var addKo = function(board, move) {
  if ((move.actions.length > 0) && (move.actions[0][1] !== null)) {
       pos = move.actions[0][1][0];
       if (_.isUndefined(board.ko)) {
           board.ko = [];
       }
       if (_.indexOf(board.ko, pos) < 0) {
           board.ko.push(pos);
       }
  }
}

var getRank = function(design, board, player, pos, dir, opposite) {
  var cnt = 1;
  var p = design.navigate(player, pos, opposite);
  while (p !== null) {
      var piece = board.getPiece(p);
      if ((piece === null) || (piece.player != player)) break;
      p = design.navigate(player, p, opposite);
      cnt++;
  }
  p = design.navigate(player, pos, dir);
  while (p !== null) {
      var piece = board.getPiece(p);
      if (piece === null) {
          p = design.navigate(player, p, dir);
          var sign = 1;
          while (p !== null) {
              piece = board.getPiece(p);
              if (piece === null) break;
              if (piece.player != player) return cnt * sign;
              p = design.navigate(player, p, dir);
              cnt++;
              sign = -1;
          }
          return cnt;
      }
      if (piece.player != player) return 0;
      p = design.navigate(player, p, dir);
      cnt++;
  }
  return 0;
}

var calcRank = function(x, y) {
  if ((x < 0) && (y < 0)) {
      if (x < y) {
          return x;
      } else {
          return y;
      }
  }
  if (Math.abs(x) > 3) return x;
  if (Math.abs(y) > 3) return y;
  if ((x <= 0) && (y <= 0)) return 0;
  if (Math.abs(x) > Math.abs(y)) {
      return x;
  } else {
      return y;
  }
}

var isTriplet = function(design, board, player, pos, dir, opposite) {
  p = design.navigate(player, pos, dir);
  while (p !== null) {
      if (board.getPiece(p) === null) {
          var x = getRank(design, board, player, p, dir, opposite);
          var y = getRank(design, board, player, p, opposite, dir);
          return calcRank(x, y) == 4;
      }
      p = design.navigate(player, p, dir);
  }
  return false;
}

var CheckInvariants = Dagaz.Model.CheckInvariants;

Dagaz.Model.CheckInvariants = function(board) {
  var design = Dagaz.Model.design;
  var dirs   = [];
  dirs.push(design.getDirection("n")); dirs.push(design.getDirection("ne"));
  dirs.push(design.getDirection("e")); dirs.push(design.getDirection("se"));
  dirs.push(design.getDirection("s")); dirs.push(design.getDirection("sw"));
  dirs.push(design.getDirection("w")); dirs.push(design.getDirection("nw"));
  _.each(board.moves, function(move) {
      if (board.player == 1) {
          var pos   = move.actions[0][1][0];
          var piece = move.actions[0][2][0];
          var res   = [];
          for (var ix = 0; ix < 4; ix++) {
               var v = +piece.getValue(ix);
               if (v > 5) {
                   addKo(board, move);
                   move.failed = true;
                   return;
               }
               var x = getRank(design, board, board.player, pos, dirs[ix], dirs[ix + 4]);
               var y = getRank(design, board, board.player, pos, dirs[ix + 4], dirs[ix]);
               res.push(calcRank(x, y));
          }
          if (_.filter(res, function(x) { return Math.abs(x) >= 4; }).length >= 2) {
               addKo(board, move);
               move.failed = true;
               return;
          }
          if (_.filter(res, function(x) { return (x < -3) || (x >= 3); }).length >= 2) {
               var b = board.apply(move);
               var cnt = 0;
               for (var ix = 0; ix < 4; ix++) {
                   if (Math.abs(res[ix]) > 3) {
                       cnt++;
                       continue;
                   }
                   if (res[ix] == 3) {
                       if (isTriplet(design, b, board.player, pos, dirs[ix], dirs[ix + 4]) ||
                           isTriplet(design, b, board.player, pos, dirs[ix + 4], dirs[ix])) cnt++;
                   }
               }
               if (cnt >= 2) {
                   addKo(board, move);
                   move.failed = true;
                   return;
               }
          }
      }
  });
  CheckInvariants(board);
}

})();
<commit_msg>Renju (fix)<commit_after>(function() {

var checkVersion = Dagaz.Model.checkVersion;

Dagaz.Model.checkVersion = function(design, name, value) {
  if (name != "renju-invariant") {
      checkVersion(design, name, value);
  }
}

var addKo = function(board, move) {
  if ((move.actions.length > 0) && (move.actions[0][1] !== null)) {
       pos = move.actions[0][1][0];
       if (_.isUndefined(board.ko)) {
           board.ko = [];
       }
       if (_.indexOf(board.ko, pos) < 0) {
           board.ko.push(pos);
       }
  }
}

var getRank = function(design, board, player, pos, dir, opposite) {
  var cnt = 1;
  var p = design.navigate(player, pos, opposite);
  while (p !== null) {
      var piece = board.getPiece(p);
      if ((piece === null) || (piece.player != player)) return -cnt; // break;
      p = design.navigate(player, p, opposite);
      cnt++;
  }
  p = design.navigate(player, pos, dir);
  while (p !== null) {
      var piece = board.getPiece(p);
      if (piece === null) {
          p = design.navigate(player, p, dir);
          var sign = 1;
          while (p !== null) {
              piece = board.getPiece(p);
              if (piece === null) break;
              if (piece.player != player) return cnt * sign;
              p = design.navigate(player, p, dir);
              cnt++;
              sign = -1;
          }
          return cnt;
      }
      if (piece.player != player) return 0;
      p = design.navigate(player, p, dir);
      cnt++;
  }
  return 0;
}

var calcRank = function(x, y) {
  if ((x < 0) && (y < 0)) {
      if (x < y) {
          return x;
      } else {
          return y;
      }
  }
  if (Math.abs(x) > 3) return x;
  if (Math.abs(y) > 3) return y;
  if ((x <= 0) && (y <= 0)) return 0;
  if (Math.abs(x) > Math.abs(y)) {
      return x;
  } else {
      return y;
  }
}

var isTriplet = function(design, board, player, pos, dir, opposite) {
  p = design.navigate(player, pos, dir);
  while (p !== null) {
      if (board.getPiece(p) === null) {
          var x = getRank(design, board, player, p, dir, opposite);
          var y = getRank(design, board, player, p, opposite, dir);
          return calcRank(x, y) == 4;
      }
      p = design.navigate(player, p, dir);
  }
  return false;
}

var CheckInvariants = Dagaz.Model.CheckInvariants;

Dagaz.Model.CheckInvariants = function(board) {
  var design = Dagaz.Model.design;
  var dirs   = [];
  dirs.push(design.getDirection("n")); dirs.push(design.getDirection("ne"));
  dirs.push(design.getDirection("e")); dirs.push(design.getDirection("se"));
  dirs.push(design.getDirection("s")); dirs.push(design.getDirection("sw"));
  dirs.push(design.getDirection("w")); dirs.push(design.getDirection("nw"));
  _.each(board.moves, function(move) {
      if (board.player == 1) {
          var pos   = move.actions[0][1][0];
          var piece = move.actions[0][2][0];
          var res   = [];
          for (var ix = 0; ix < 4; ix++) {
               var v = +piece.getValue(ix);
               if (v > 5) {
                   addKo(board, move);
                   move.failed = true;
                   return;
               }
               var x = getRank(design, board, board.player, pos, dirs[ix], dirs[ix + 4]);
               var y = getRank(design, board, board.player, pos, dirs[ix + 4], dirs[ix]);
               res.push(calcRank(x, y));
          }
          if (_.filter(res, function(x) { return Math.abs(x) >= 4; }).length >= 2) {
               addKo(board, move);
               move.failed = true;
               return;
          }
          if (_.filter(res, function(x) { return (x < -3) || (x >= 3); }).length >= 2) {
               var b = board.apply(move);
               var cnt = 0;
               for (var ix = 0; ix < 4; ix++) {
                   if (Math.abs(res[ix]) > 3) {
                       cnt++;
                       continue;
                   }
                   if (res[ix] == 3) {
                       if (isTriplet(design, b, board.player, pos, dirs[ix], dirs[ix + 4]) ||
                           isTriplet(design, b, board.player, pos, dirs[ix + 4], dirs[ix])) cnt++;
                   }
               }
               if (cnt >= 2) {
                   addKo(board, move);
                   move.failed = true;
                   return;
               }
          }
      }
  });
  CheckInvariants(board);
}

})();
<|endoftext|>


<commit_before>import {
  spawn,
  current,
  stop
} from './scheduler';
import Ember from 'ember';
const {
  set,
  ComputedProperty
} = Ember;

export function task(...args) {
  return new TaskProperty(...args);
}

function TaskProperty(taskFn) {
  let tp = this;
  ComputedProperty.call(this, function() {
    return new Task(this, taskFn, tp);
  });
  this._bufferPolicy = null;
  this._observes = null;
}

TaskProperty.prototype = Object.create(ComputedProperty.prototype);
Object.assign(TaskProperty.prototype, {
  constructor: TaskProperty,
  restartable() {
    this._bufferPolicy = cancelAllButLast;
    return this;
  },
  observes(...deps) {
    this._observes = deps;
    return this;
  },
  setup(proto, taskName) {
    registerOnPrototype(Ember.addObserver, proto, this._observes, taskName, 'perform', true);
  },

});

let priv = new WeakMap();

class Task {
  constructor(context, implementation, taskProperty) {
    priv.set(this, {
      context,
      implementation,
      instances: [],
      taskProperty
    });
    this.concurrency = 0;
    this.isRunning = false;
  }
  perform(...args) {
    let self = this;
    let privSelf = priv.get(this);
    let context = privSelf.context;
    let implementation = privSelf.implementation;
    let policy = privSelf.taskProperty._bufferPolicy;
    cleanupOnDestroy(context, this, 'cancelAll');
    let instance = spawn(function * () {
      try {
        self._addInstance(current());
        if (policy) {
          let maybeWait = policy(self, privSelf);
          if (maybeWait) {
            yield maybeWait;
          }
        }
        let finalValue = yield * withRunLoop(implementation.call(context, ...args));
        return finalValue;
      } finally {
        Ember.run.join(() => {
          self._removeInstance(current());
        });
      }
    });
    return rsvpIfy(instance);
  }
  cancelAll() {
    priv.get(this).instances.forEach(i => stop(i));
  }
  _addInstance(i) {
    priv.get(this).instances.push(i);
    set(this, 'isRunning', true);
    set(this, 'concurrency', this.concurrency + 1);
  }
  _removeInstance(i) {
    let instances = priv.get(this).instances;
    instances.splice(instances.indexOf(i), 1);
    set(this, 'concurrency', this.concurrency - 1);
    set(this, 'isRunning', this.concurrency > 1);
  }
}

// cribbed from machty's ember-concurrency
function cleanupOnDestroy(owner, object, cleanupMethodName) {
  if (!owner.willDestroy)
  {
    // we're running in non Ember object (possibly in a test mock)
    return;
  }

  if (!owner.willDestroy.__ember_processes_destroyers__) {
    let oldWillDestroy = owner.willDestroy;
    let disposers = [];

    owner.willDestroy = function() {
      for (let i = 0, l = disposers.length; i < l; i ++) {
        disposers[i]();
      }
      oldWillDestroy.apply(owner, arguments);
    };
    owner.willDestroy.__ember_processes_destroyers__ = disposers;
  }

  owner.willDestroy.__ember_processes_destroyers__.push(() => {
    object[cleanupMethodName]();
  });
}
function registerOnPrototype(addListenerOrObserver, proto, names, taskName, taskMethod, once) {
  if (names) {
    for (let i = 0; i < names.length; ++i) {
      let name = names[i];
      addListenerOrObserver(proto, name, null, makeTaskCallback(taskName, taskMethod, once));
    }
  }
}
function makeTaskCallback(taskName, method, once) {
  return function() {
    let task = this.get(taskName);

    if (once) {
      Ember.run.scheduleOnce('actions', task, method, ...arguments);
    } else {
      task[method].apply(task, arguments);
    }
  };
}

function cancelAllButLast(task, privTask) {
  let instances = privTask.instances;
  for (let i = 0; i < instances.length - 1; i++) {
    stop(instances[i]);
  }
}

function * withRunLoop(generator) {
  let state;
  let nextValue;
  let fulfilled = true;
  while (true) {
    Ember.run.join(() => {
      if (fulfilled) {
        state = generator.next(nextValue);
      } else {
        state = generator.throw(nextValue);
      }
    });

    if (state.done) {
      return state.value;
    }
    try {
      nextValue = yield state.value;
      fulfilled = true;
    } catch(err) {
      nextValue = err;
      fulfilled = false;
    }
  }
}

function rsvpIfy(promise) {
  let p = Ember.RSVP.Promise.resolve(promise);
  p.__ec_cancel__ = promise.__ec_cancel__;
  return p;
}

export function timeout(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
<commit_msg>fix jshint<commit_after>import {
  spawn,
  current,
  stop
} from './scheduler';
import Ember from 'ember';
const {
  set,
  ComputedProperty
} = Ember;

export function task(...args) {
  return new TaskProperty(...args);
}

function TaskProperty(taskFn) {
  let tp = this;
  ComputedProperty.call(this, function() {
    return new Task(this, taskFn, tp);
  });
  this._bufferPolicy = null;
  this._observes = null;
}

TaskProperty.prototype = Object.create(ComputedProperty.prototype);
Object.assign(TaskProperty.prototype, {
  constructor: TaskProperty,
  restartable() {
    this._bufferPolicy = cancelAllButLast;
    return this;
  },
  observes(...deps) {
    this._observes = deps;
    return this;
  },
  setup(proto, taskName) {
    registerOnPrototype(Ember.addObserver, proto, this._observes, taskName, 'perform', true);
  },

});

let priv = new WeakMap();

class Task {
  constructor(context, implementation, taskProperty) {
    priv.set(this, {
      context,
      implementation,
      instances: [],
      taskProperty
    });
    this.concurrency = 0;
    this.isRunning = false;
  }
  perform(...args) {
    let self = this;
    let privSelf = priv.get(this);
    let context = privSelf.context;
    let implementation = privSelf.implementation;
    let policy = privSelf.taskProperty._bufferPolicy;
    cleanupOnDestroy(context, this, 'cancelAll');
    let instance = spawn(function * () {
      try {
        self._addInstance(current());
        if (policy) {
          let maybeWait = policy(self, privSelf);
          if (maybeWait) {
            yield maybeWait;
          }
        }
        let finalValue = yield * withRunLoop(implementation.call(context, ...args));
        return finalValue;
      } finally {
        Ember.run.join(() => {
          self._removeInstance(current());
        });
      }
    });
    return rsvpIfy(instance);
  }
  cancelAll() {
    priv.get(this).instances.forEach(i => stop(i));
  }
  _addInstance(i) {
    priv.get(this).instances.push(i);
    set(this, 'isRunning', true);
    set(this, 'concurrency', this.concurrency + 1);
  }
  _removeInstance(i) {
    let instances = priv.get(this).instances;
    instances.splice(instances.indexOf(i), 1);
    set(this, 'concurrency', this.concurrency - 1);
    set(this, 'isRunning', this.concurrency > 1);
  }
}

// cribbed from machty's ember-concurrency
function cleanupOnDestroy(owner, object, cleanupMethodName) {
  if (!owner.willDestroy)
  {
    // we're running in non Ember object (possibly in a test mock)
    return;
  }

  if (!owner.willDestroy.__ember_processes_destroyers__) {
    let oldWillDestroy = owner.willDestroy;
    let disposers = [];

    owner.willDestroy = function() {
      for (let i = 0, l = disposers.length; i < l; i ++) {
        disposers[i]();
      }
      oldWillDestroy.apply(owner, arguments);
    };
    owner.willDestroy.__ember_processes_destroyers__ = disposers;
  }

  owner.willDestroy.__ember_processes_destroyers__.push(() => {
    object[cleanupMethodName]();
  });
}
function registerOnPrototype(addListenerOrObserver, proto, names, taskName, taskMethod, once) {
  if (names) {
    for (let i = 0; i < names.length; ++i) {
      let name = names[i];
      addListenerOrObserver(proto, name, null, makeTaskCallback(taskName, taskMethod, once));
    }
  }
}
function makeTaskCallback(taskName, method, once) {
  return function() {
    let task = this.get(taskName);

    if (once) {
      Ember.run.scheduleOnce('actions', task, method, ...arguments);
    } else {
      task[method].apply(task, arguments);
    }
  };
}

function cancelAllButLast(task, privTask) {
  let instances = privTask.instances;
  for (let i = 0; i < instances.length - 1; i++) {
    stop(instances[i]);
  }
}

function * withRunLoop(generator) {
  let state;
  let nextValue;
  let fulfilled = true;
  while (true) {
    Ember.run.join(() => {
      if (fulfilled) {
        state = generator.next(nextValue);
      } else {
        state = generator.throw(nextValue);
      }
    });

    if (state.done) {
      return state.value;
    }
    try {
      nextValue = yield state.value;
      fulfilled = true;
    } catch(err) {
      nextValue = err;
      fulfilled = false;
    }
  }
}

function rsvpIfy(promise) {
  let p = Ember.RSVP.Promise.resolve(promise);
  p.__ec_cancel__ = promise.__ec_cancel__;
  return p;
}

export function timeout(ms) {
  return new Ember.RSVP.Promise(resolve => setTimeout(resolve, ms));
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import emberRequire from '../ext-require';
const outlet = emberRequire('ember-htmlbars/keywords/outlet');
const isEnabled = emberRequire('ember-metal/features');
const ViewNodeManager = emberRequire('ember-htmlbars/node-managers/view-node-manager');
const RenderEnv = emberRequire('ember-htmlbars/system/render-env');
const info = emberRequire('ember-metal/debug', 'info');

const {
  get
} = Ember;

outlet.render = function(renderNode, _env, scope, params, hash, template, inverse, visitor) {
  let env = _env;
  var state = renderNode.getState();
  var parentView = env.view;
  var outletState = state.outletState;
  var toRender = outletState.render;
  var namespace = env.owner.lookup('application:main');
  var LOG_VIEW_LOOKUPS = get(namespace, 'LOG_VIEW_LOOKUPS');

  var ViewClass = outletState.render.ViewClass;

  if (!state.hasParentOutlet && !ViewClass) {
    ViewClass = env.owner._lookupFactory('view:toplevel');
  }

  var Component;

  if (isEnabled('ember-routing-routable-components')) {
    Component = outletState.render.Component;
  }

  var options;
  var attrs = {};
  if (Component) {
    options = {
      component: Component
    };
    attrs = toRender.attrs;
  } else {
    options = {
      component: ViewClass,
      self: toRender.controller,
      createOptions: {
        controller: toRender.controller
      }
    };

    template = template || toRender.template && toRender.template.raw;

    if (LOG_VIEW_LOOKUPS && ViewClass) {
      info('Rendering ' + toRender.name + ' with ' + ViewClass, { fullName: 'view:' + toRender.name });
    }
  }

  if (state.manager) {
    state.manager.destroy();
    state.manager = null;
  }

  let owner = outletState.render.owner;
  // detect if we are crossing into an engine
  if (owner !== env.owner) {
    env = new RenderEnv({
      view: null,
      outletState: outletState.outlets,
      owner,
      renderer: _env.renderer,
      dom: _env.renderer._dom,
      meta: env.meta
    });
  }

  var nodeManager = ViewNodeManager.create(renderNode, env, attrs, options, parentView, null, null, template);
  state.manager = nodeManager;

  if (!env.view) {
    env.view = nodeManager.component;
  }

  nodeManager.render(env, hash, visitor);
};
<commit_msg>Ensure a `ViewClass` is provided whenever crossing into an Engine.<commit_after>import Ember from 'ember';
import emberRequire from '../ext-require';
const outlet = emberRequire('ember-htmlbars/keywords/outlet');
const isEnabled = emberRequire('ember-metal/features');
const ViewNodeManager = emberRequire('ember-htmlbars/node-managers/view-node-manager');
const RenderEnv = emberRequire('ember-htmlbars/system/render-env');
const info = emberRequire('ember-metal/debug', 'info');

const {
  get
} = Ember;

outlet.render = function(renderNode, _env, scope, params, hash, template, inverse, visitor) {
  let env = _env;
  var state = renderNode.getState();
  var parentView = env.view;
  var outletState = state.outletState;
  var toRender = outletState.render;
  var namespace = env.owner.lookup('application:main');
  var LOG_VIEW_LOOKUPS = get(namespace, 'LOG_VIEW_LOOKUPS');

  var ViewClass = outletState.render.ViewClass;

  if (!state.hasParentOutlet && !ViewClass) {
    ViewClass = env.owner._lookupFactory('view:toplevel');
  }

  var Component;

  if (isEnabled('ember-routing-routable-components')) {
    Component = outletState.render.Component;
  }

  var options;
  var attrs = {};
  if (Component) {
    options = {
      component: Component
    };
    attrs = toRender.attrs;
  } else {
    options = {
      component: ViewClass,
      self: toRender.controller,
      createOptions: {
        controller: toRender.controller
      }
    };

    template = template || toRender.template && toRender.template.raw;

    if (LOG_VIEW_LOOKUPS && ViewClass) {
      info('Rendering ' + toRender.name + ' with ' + ViewClass, { fullName: 'view:' + toRender.name });
    }
  }

  if (state.manager) {
    state.manager.destroy();
    state.manager = null;
  }

  let owner = outletState.render.owner;
  // detect if we are crossing into an engine
  if (owner !== env.owner) {
    env = new RenderEnv({
      view: null,
      outletState: outletState.outlets,
      owner,
      renderer: _env.renderer,
      dom: _env.renderer._dom,
      meta: env.meta
    });

    // when this outlet represents an engine we must ensure that a `ViewClass` is present
    // even if the engine does not contain a `view:application`. We need a `ViewClass` to
    // ensure that an `ownerView` is set on the `env` created just above
    options.component = options.component || owner._lookupFactory('view:toplevel');
  }

  var nodeManager = ViewNodeManager.create(renderNode, env, attrs, options, parentView, null, null, template);
  state.manager = nodeManager;

  if (!env.view) {
    env.view = nodeManager.component;
  }

  nodeManager.render(env, hash, visitor);
};
<|endoftext|>


<commit_before>import Ember from 'ember';

/**
 * A mixin for attaching autosize to a component's element.  Is also capable of reading the `min-height` and
 * `max-height` property to initialize the extents of the component's height.
 * @see http://www.jacklmoore.com/autosize/
 */
export default Ember.Mixin.create({
  /**
   * Once this textarea is being destroyed let's help clean up the DOM by removing the autosize binding.
   * @see http://www.jacklmoore.com/autosize/
   */
  _removeAutosize: Ember.on('willDestroyElement', function () {
    autosize.destroy(this.$());
  }),
  /**
   * Once this textarea is inserted in the DOM initialize on autosize.
   * @see https://github.com/jackmoore/autosize
   */
  _initializeAutosize: Ember.on('didInsertElement', function () {
    autosize(this.$());
    if (Ember.isPresent(this.get('min-height'))) {
      this.$().css('min-height', this.get('min-height'));
    }
    if (Ember.isPresent(this.get('max-height'))) {
      this.$().css('max-height', this.get('max-height'));
    }
  })
});
<commit_msg>Fix code review problems<commit_after>import Ember from 'ember';

/**
 * A mixin for attaching autosize to a component's element.  Is also capable of reading the `min-height` and
 * `max-height` property to initialize the extents of the component's height.
 * @see http://www.jacklmoore.com/autosize/
 */
export default Ember.Mixin.create({
  /**
   * Once this textarea is being destroyed let's help clean up the DOM by removing the autosize binding.
   * @see http://www.jacklmoore.com/autosize/
   */
  _removeAutosize: Ember.on('willDestroyElement', function () {
    autosize.destroy(this.$());
  }),
  /**
   * Once this textarea is inserted in the DOM initialize on autosize.
   * @see https://github.com/jackmoore/autosize
   */
  _initializeAutosize: Ember.on('didInsertElement', function () {
    autosize(this.$());
    this._setCss('min-height');
    this._setCss('max-height');
  }),
  /**
   * Set the jquery css property `propertyName` with the component property `propertyName`.
   * @param propertyName the css property.
   * @private
   */
  _setCss(propertyName) {
    if (Ember.isPresent(this.get(propertyName))) {
      this.$().css(propertyName, this.get(propertyName));
    }
  }
});
<|endoftext|>


<commit_before>import DS from 'ember-data';

export default DS.Model.extend({

	name: DS.attr('string'),

	url: DS.attr('string'),

	default_owner: DS.belongsTo('user', { async: true }),

	location: DS.belongsTo('location', { async: true }),

	locations: DS.hasMany('location', { async: true }),

	//

	content_photo_en: DS.attr('string'),

	content_title_en: DS.attr('string'),

	content_subtitle_en: DS.attr('string'),

	content_description_en: DS.attr('string'),

	content_footer_en: DS.attr('string'),

	//

	content_photo_ar: DS.attr('string'),

	content_title_ar: DS.attr('string'),

	content_subtitle_ar: DS.attr('string'),

	content_description_ar: DS.attr('string'),

	content_footer_ar: DS.attr('string'),

	//

	content_photo_fr: DS.attr('string'),

	content_title_fr: DS.attr('string'),

	content_subtitle_fr: DS.attr('string'),

	content_description_fr: DS.attr('string'),

	content_footer_fr: DS.attr('string'),

	///

	floodlight_1_id: DS.attr('string'),

	floodlight_1_cat: DS.attr('string'),

	floodlight_1_type: DS.attr('string'),

	floodlight_2_id: DS.attr('string'),

	floodlight_2_cat: DS.attr('string'),

	floodlight_2_type: DS.attr('string'),

	floodlight_3_id: DS.attr('string'),

	floodlight_3_cat: DS.attr('string'),

	floodlight_3_type: DS.attr('string'),

	floodlight_4_id: DS.attr('string'),

	floodlight_4_cat: DS.attr('string'),

	floodlight_4_type: DS.attr('string'),

	remarketing_id: DS.attr('string'),

	facebook_1_id: DS.attr('string'),

	facebook_1_action: DS.attr('string'),

	//

});
<commit_msg>Adding crimtan tags.<commit_after>import DS from 'ember-data';

export default DS.Model.extend({

	name: DS.attr('string'),

	url: DS.attr('string'),

	default_owner: DS.belongsTo('user', { async: true }),

	location: DS.belongsTo('location', { async: true }),

	locations: DS.hasMany('location', { async: true }),

	//

	content_photo_en: DS.attr('string'),

	content_title_en: DS.attr('string'),

	content_subtitle_en: DS.attr('string'),

	content_description_en: DS.attr('string'),

	content_footer_en: DS.attr('string'),

	//

	content_photo_ar: DS.attr('string'),

	content_title_ar: DS.attr('string'),

	content_subtitle_ar: DS.attr('string'),

	content_description_ar: DS.attr('string'),

	content_footer_ar: DS.attr('string'),

	//

	content_photo_fr: DS.attr('string'),

	content_title_fr: DS.attr('string'),

	content_subtitle_fr: DS.attr('string'),

	content_description_fr: DS.attr('string'),

	content_footer_fr: DS.attr('string'),

	///

	floodlight_1_id: DS.attr('string'),

	floodlight_1_cat: DS.attr('string'),

	floodlight_1_type: DS.attr('string'),

	floodlight_2_id: DS.attr('string'),

	floodlight_2_cat: DS.attr('string'),

	floodlight_2_type: DS.attr('string'),

	floodlight_3_id: DS.attr('string'),

	floodlight_3_cat: DS.attr('string'),

	floodlight_3_type: DS.attr('string'),

	floodlight_4_id: DS.attr('string'),

	floodlight_4_cat: DS.attr('string'),

	floodlight_4_type: DS.attr('string'),

	remarketing_id: DS.attr('string'),

	facebook_1_id: DS.attr('string'),

	facebook_1_action: DS.attr('string'),

	js_tag: DS.attr('string'),

	image_tag: DS.attr('string'),

	//

});
<|endoftext|>


<commit_before>/*global PUBNUB */
/*jshint -W030 */
import Ember from "ember";

export default Ember.Service.extend(Ember.Evented, {
	PN: null,
	pnState: {},

	setup: function() {
		let config = this.container.lookupFactory("config:environment");

		if (PUBNUB === void 0) {
			throw new Ember.Error("ember-cli-pubnub: PubNub JS SDK not found");
		}

		if (config.pubnub === void 0){
			throw new Ember.Error("ember-cli-pubnub: no configuration in config.environment");
		}

		let pn = PUBNUB.init(config.pubnub);

		// ************************************************* Ember.A, Ember.Object
		this.get("pnState")["_channels"] = [];
		this.get("pnState")["_presence"] = {};
		this.get("pnState")["_presData"] = {};

		return this.set("PN", pn);

	}.on("init"),

	listChannels: function() {
		return this.get("pnState")["_channels"].slice(0);
	},

	listPresence: function(channel) {
		let _ref;
		return (_ref = this.get("pnState")["_presence"][channel]) != null ? _ref.slice(0) : void 0;
	},

	presenceData: function(channel) {
		return this.get("pnState")["_presData"][channel] || {};
	},

	msgEvent: function(channel) {
		return `pn-message:${channel}`;
	},

	prsEvent: function(channel) {
		return `pn-presence:${channel}`;
	},

	publish: function(args) {
		console.dir(args);
		return this.get("PN")["publish"].apply(this.get("PN"), args);
	},

	state: function(args) {
		return this.get("PN")["state"](args);
	},

	auth: function(){
		return this.get("PN")["auth"].apply(this.get("PN"), arguments);
	},

	audit: function(){
		return this.get("PN")["audit"].apply(this.get("PN"), arguments);
	},

	grant: function(){
		return this.get("PN")["grant"].apply(this.get("PN"), arguments);
	},

	whereNow: function(args) {
		return this.get("PN")["where_now"](args);
	},

	hereNow: function(args) {
		args          = this._installHandlers(args);
		args.state    = true;
		args.callback = args.presence;
		delete args.presence;
		delete args.message;
		return this.get("PN")["here_now"](args);
	},

	history: function(args) {
		args.callback = this._fireMessages(args.channel);
		return this.get("PN")["history"](args);
	},

	subscribe: function(args) {
		let _base, _name;
		let pnState = this.get("pnState");
		let PN = this.get("PN");

		args = this._installHandlers(args);

		if (pnState["_channels"].indexOf(args.channel) < 0) {
			pnState["_channels"].push(args.channel);
		}

		(_base = pnState["_presence"])[_name = args.channel] || (_base[_name] = []);

		return PN["subscribe"](args);
	},

	unsubscribe: function(args) {
		let cpos, pnState = this.get("pnState");

		cpos = pnState["_channels"].indexOf(args.channel);

		if (cpos !== -1) {
			pnState["_channels"].splice(cpos, 1);
		}

		pnState["_presence"][args.channel] = null;
		this.off(this.msgEvent(args.channel));
		this.off(this.prsEvent(args.channel));

		return this.get("PN")["unsubscribe"](args);
	},

	_fireMessages: function(channel) {
		let PN   = this.get("PN");
		let self = this;

		return function(payload) {
			return PN.each(payload[0], function(message) {
				return self.trigger(self.msgEvent(channel), {
					message: message,
					channel: channel
				});
			});
		};
	},

	_installHandlers: function(args) {
		let self      = this;
		let PN        = this.get("PN");
		let pnState   = this.get("pnState");
		let _message  = args.message;
		let _presence = args.presence;

		args.message = function() {
			self.trigger(self.msgEvent(args.channel), {
				channel:args.channel,
				message: arguments[0],
				env    : arguments[1]
			});

			if (_message) {
				return _message(arguments);
			}
		};

		args.presence = function() {
			let _base1, _base2, cpos;
			let channel = args.channel;
			let event   = arguments[0];

			if (event.uuids) {
				PN.each(event.uuids, function(uuid) {
					let state = uuid.state || null;

					uuid = uuid.uuid | uuid;

					(_base1 = pnState["_presence"])[channel] || (_base1[channel] = []);

					if (pnState["_presence"][channel].indexOf(uuid) < 0) {
						pnState["_presence"][channel].push(uuid);
					}

					(_base2 = pnState["_presData"])[channel] || (_base2[channel] = []);

					if (state) {
						return pnState["_presData"][channel][uuid] = state;
					}
				});
			}
			else {
				if (event.uuid && event.action) {
					(_base1 = pnState["_presence"])[channel] || (_base1[channel] = []);
					(_base2 = pnState["_presData"])[channel] || (_base2[channel] = {});

					if (event.action === "leave") {
						cpos = pnState["_presence"][channel].indexOf(event.uuid);

						if (cpos !== -1) {
							pnState["_presence"][channel].splice(cpos, 1);
						}
						delete pnState["_presData"][channel][event.uuid];
					}
					else {
						if (pnState["_presence"][channel].indexOf(event.uuid) < 0) {
							pnState["_presence"][channel].push(event.uuid);
						}
						if (event.data) {
							pnState["_presData"][channel][event.uuid] = event.data;
						}
					}
				}
			}

			return self.trigger(self.prsEvent(args.channel), {
				event  : event,
				channel: channel,
				message: arguments[1]
			});
		};
		return args;
	}
});
<commit_msg>debugging<commit_after>/*global PUBNUB */
/*jshint -W030 */
import Ember from "ember";

export default Ember.Service.extend(Ember.Evented, {
	PN: null,
	pnState: {},

	setup: function() {
		let config = this.container.lookupFactory("config:environment");

		if (PUBNUB === void 0) {
			throw new Ember.Error("ember-cli-pubnub: PubNub JS SDK not found");
		}

		if (config.pubnub === void 0){
			throw new Ember.Error("ember-cli-pubnub: no configuration in config.environment");
		}

		let pn = PUBNUB.init(config.pubnub);

		// ************************************************* Ember.A, Ember.Object
		this.get("pnState")["_channels"] = [];
		this.get("pnState")["_presence"] = {};
		this.get("pnState")["_presData"] = {};

		return this.set("PN", pn);

	}.on("init"),

	listChannels: function() {
		return this.get("pnState")["_channels"].slice(0);
	},

	listPresence: function(channel) {
		let _ref;
		return (_ref = this.get("pnState")["_presence"][channel]) != null ? _ref.slice(0) : void 0;
	},

	presenceData: function(channel) {
		return this.get("pnState")["_presData"][channel] || {};
	},

	msgEvent: function(channel) {
		return `pn-message:${channel}`;
	},

	prsEvent: function(channel) {
		return `pn-presence:${channel}`;
	},

	publish: function(args) {
		console.dir(args);
		return this.get("PN")["publish"](args);
		//return this.get("PN")["publish"].apply(this.get("PN"), args);
	},

	state: function(args) {
		return this.get("PN")["state"](args);
	},

	auth: function(){
		return this.get("PN")["auth"].apply(this.get("PN"), arguments);
	},

	audit: function(){
		return this.get("PN")["audit"].apply(this.get("PN"), arguments);
	},

	grant: function(){
		return this.get("PN")["grant"].apply(this.get("PN"), arguments);
	},

	whereNow: function(args) {
		return this.get("PN")["where_now"](args);
	},

	hereNow: function(args) {
		args          = this._installHandlers(args);
		args.state    = true;
		args.callback = args.presence;
		delete args.presence;
		delete args.message;
		return this.get("PN")["here_now"](args);
	},

	history: function(args) {
		args.callback = this._fireMessages(args.channel);
		return this.get("PN")["history"](args);
	},

	subscribe: function(args) {
		let _base, _name;
		let pnState = this.get("pnState");
		let PN = this.get("PN");

		args = this._installHandlers(args);

		if (pnState["_channels"].indexOf(args.channel) < 0) {
			pnState["_channels"].push(args.channel);
		}

		(_base = pnState["_presence"])[_name = args.channel] || (_base[_name] = []);

		return PN["subscribe"](args);
	},

	unsubscribe: function(args) {
		let cpos, pnState = this.get("pnState");

		cpos = pnState["_channels"].indexOf(args.channel);

		if (cpos !== -1) {
			pnState["_channels"].splice(cpos, 1);
		}

		pnState["_presence"][args.channel] = null;
		this.off(this.msgEvent(args.channel));
		this.off(this.prsEvent(args.channel));

		return this.get("PN")["unsubscribe"](args);
	},

	_fireMessages: function(channel) {
		let PN   = this.get("PN");
		let self = this;

		return function(payload) {
			return PN.each(payload[0], function(message) {
				return self.trigger(self.msgEvent(channel), {
					message: message,
					channel: channel
				});
			});
		};
	},

	_installHandlers: function(args) {
		let self      = this;
		let PN        = this.get("PN");
		let pnState   = this.get("pnState");
		let _message  = args.message;
		let _presence = args.presence;

		args.message = function() {
			self.trigger(self.msgEvent(args.channel), {
				channel:args.channel,
				message: arguments[0],
				env    : arguments[1]
			});

			if (_message) {
				return _message(arguments);
			}
		};

		args.presence = function() {
			let _base1, _base2, cpos;
			let channel = args.channel;
			let event   = arguments[0];

			if (event.uuids) {
				PN.each(event.uuids, function(uuid) {
					let state = uuid.state || null;

					uuid = uuid.uuid | uuid;

					(_base1 = pnState["_presence"])[channel] || (_base1[channel] = []);

					if (pnState["_presence"][channel].indexOf(uuid) < 0) {
						pnState["_presence"][channel].push(uuid);
					}

					(_base2 = pnState["_presData"])[channel] || (_base2[channel] = []);

					if (state) {
						return pnState["_presData"][channel][uuid] = state;
					}
				});
			}
			else {
				if (event.uuid && event.action) {
					(_base1 = pnState["_presence"])[channel] || (_base1[channel] = []);
					(_base2 = pnState["_presData"])[channel] || (_base2[channel] = {});

					if (event.action === "leave") {
						cpos = pnState["_presence"][channel].indexOf(event.uuid);

						if (cpos !== -1) {
							pnState["_presence"][channel].splice(cpos, 1);
						}
						delete pnState["_presData"][channel][event.uuid];
					}
					else {
						if (pnState["_presence"][channel].indexOf(event.uuid) < 0) {
							pnState["_presence"][channel].push(event.uuid);
						}
						if (event.data) {
							pnState["_presData"][channel][event.uuid] = event.data;
						}
					}
				}
			}

			return self.trigger(self.prsEvent(args.channel), {
				event  : event,
				channel: channel,
				message: arguments[1]
			});
		};
		return args;
	}
});
<|endoftext|>


<commit_before>/**
 * Copyright 2016, Yahoo! Inc.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

import Ember from 'ember';
import Messages from 'ember-cp-validations/validators/messages';
import getOwner from 'ember-getowner-polyfill';
import { unwrapString } from 'ember-cp-validations/utils/utils';

const {
  get,
  set,
  isNone
} = Ember;

const assign = Ember.assign || Ember.merge;

/**
 * @class Base
 * @module Validators
 */
const Base = Ember.Object.extend({

  /**
   * Options passed in to the validator when defined in the model
   * @property options
   * @type {Object}
   */
  options: null,

  /**
   * Default validation options for this specific attribute
   * @property defaultOptions
   * @type {Object}
   */
  defaultOptions: null,

  /**
   * Global validation options for this model
   * @property globalOptions
   * @type {Object}
   */
  globalOptions: null,

  /**
   * Model instance
   * @property model
   * @type {Model}
   */
  model: null,

  /**
   * Attributed name of the model this validator is attached to
   * @property attribute
   * @type {String}
   */
  attribute: null,

  /**
   * Error message object. Populated by validators/messages
   * @property errorMessages
   * @type {Object}
   */
  errorMessages: null,

  /**
   * Validator type
   * @property _type
   * @private
   * @type {String}
   */
  _type: null,

  init() {
    this._super(...arguments);
    const globalOptions = get(this, 'globalOptions');
    const defaultOptions = get(this, 'defaultOptions');
    const options = get(this, 'options');
    const owner = getOwner(this);
    let errorMessages;

    if (!isNone(owner)) {
      // Since default error messages are stored in app/validators/messages, we have to look it up via the owner
      errorMessages = owner._lookupFactory('validator:messages');
    }

    // If for some reason, we can't find the messages object (i.e. unit tests), use default
    errorMessages = errorMessages || Messages;

    set(this, 'options', this.buildOptions(options || {}, defaultOptions || {}, globalOptions || {}));
    set(this, 'errorMessages', errorMessages.create());
  },

  /**
   * Build options hook. Merges default options into options object.
   * This method gets called on init and is the ideal place to normalize your options.
   * The [presence validator](https://github.com/offirgolan/ember-cp-validations/blob/master/app/validators/presence.js) is a good example to checkout
   * @method buildOptions
   * @param  {Object} options
   * @param  {Object} defaultOptions
   * @param  {Object} globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    const builtOptions = assign(assign(assign({}, globalOptions), defaultOptions), options);

    // Overwrite the validator's value method if it exists in the options and remove it since
    // there is no need for it to be passed around
    this.value = builtOptions.value || this.value;
    delete builtOptions.value;

    return builtOptions;
  },

  /**
   * Creates a new object and calls any option property that is a function with the validator context.
   * This method is called right before `validate` and the returned object gets passed into the validate method as its options
   * @method processOptions
   * @return {Object}
   */
  processOptions() {
    const options = assign({}, get(this, 'options') || {});
    const model = get(this, 'model');
    const attribute = get(this, 'attribute');

    Object.keys(options).forEach(key => {
      const option = options[key];

      if (typeof option === 'function' && key !== 'message') {
        options[key] = option.call(this, model, attribute);
      }
    });

    return options;
  },

  /**
   * Used to retrieve the value to validate.
   * This method gets called right before `validate` and the returned value
   * gets passed into the validate method.
   *
   * @method value
   * @param {Object} model
   * @param {String} attribute
   * @return The current value of `model[attribute]`
   */
  value(model, attribute) {
    return get(model, attribute);
  },

  /**
   * Wrapper method to `value` that passes the necessary parameters
   *
   * @method getValue
   * @private
   * @return {Unknown} value
   */
  getValue() {
    return this.value(get(this, 'model'), get(this, 'attribute'));
  },

  /**
   * The validate method is where all of your logic should go.
   * It will get passed in the current value of the attribute this validator is attached to.
   * Within the validator object, you will have access to the following properties:
   * @method validate
   * @param  {Unknown} value        The current value of the attribute
   * @param  {Object} options       The built and processed options
   * @param  {Object} model         The current model being evaluated
   * @param  {String} attribute     The current attribute being evaluated
   * @return
   * One of the following types:
   * - `Boolean`:  `true` if the current value passed the validation
   * - `String`: The error message
   * - `Promise`: A promise that will either resolve or reject, and will finally return either `true` or the final error message string.
   */
  validate() {
    return true;
  },

  /**
   * Used by all pre-defined validators to build an error message that is present
   * in `validators/message` or declared in your i18n solution.
   *
   * If we extended our default messages to include `uniqueUsername: '{username} already exists'`,
   * we can use this method to generate our error message.
   *
   * ```javascript
   * validate(value, options) {
   *   var exists = false;
   *
   *   options.description = 'Username';
   *   options.username = value;
   *
   *   // check with server if username exists...
   *
   *   if(exists) {
   *     return this.createErrorMessage('uniqueUsername', value, options);
   *   }
   *
   *   return true;
   * }
   * ```
   *
   * If we input `johndoe` and that username already exists, the returned message would be `'johndoe already exists'`.
   *
   * @method createErrorMessage
   * @param  {String} type        The type of message template to use
   * @param  {Unknown} value                Current value being evaluated
   * @param  {Object} options     Validator built and processed options (used as the message string context)
   * @return {String}             The generated message
   */
  createErrorMessage(type, value, options = {}) {
    const messages = this.get('errorMessages');
    let message = unwrapString(options.message);

    options.description = messages.getDescriptionFor(get(this, 'attribute'), options);

    if (message) {
      if (typeof message === 'string') {
        message = messages.formatMessage(message, options);
      } else if (typeof message === 'function') {
        message = message.apply(this, arguments);
        message = isNone(message) ? messages.getMessageFor(type, options) : messages.formatMessage(message, options);
      }
    } else {
      message = messages.getMessageFor(type, options);
    }

    return message.trim();
  }
});

Base.reopenClass({
  /**
   * Generate the needed depenent keys for this validator
   *
   * @method getDependentsFor
   * @static
   * @param  {String} attribute
   * @param  {Object} options
   * @return {Array} dependent keys
   */
  getDependentsFor() {
    return [];
  }
});

export default Base;

/**
 * Creating custom validators is very simple. To generate a validator named `unique-username` in Ember CLI
 *
 * ```bash
 * ember generate validator unique-username
 * ```
 *
 * This will create the following files
 *
 * * `app/validators/unique-username.js`
 * * `tests/unit/validators/unique-username-test.js`
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({
 *   validate(value, options, model, attribute) {
 *     return true;
 *   }
 * });
 *
 * UniqueUsername.reopenClass({
 *   getDependentsFor(attribute, options) {
 *     return [];
 *   }
 * });
 *
 * export default UniqueUsername;
 * ```
 *
 * **Side Node**: Before we continue, I would suggest checking out the documentation for the {{#crossLink 'Base'}}Base Validator{{/crossLink}}.
 *
 * If you want to interact with the `store` within your validator, you can simply inject the service like you would a component.
 * Since you have access to your model and the current value, you should be able to send the server the right information to determine if this username is unique.
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import Ember from 'ember';
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({
 *   store: Ember.inject.service(),
 *
 *   validate(value, options, model, attribute) {
 *     return this.get('store').findRecord('user', value).then((user) => {
 *       if(user && user.id === value) {
 *         let message = `The username '${value}' already exists.`;
 *         let meta = user.get('meta');
 *
 *         if(options.showSuggestions && meta && meta.suggestions) {
 *           message += "What about one of the these: " + meta.suggestions.join(', ');
 *         }
 *         return message;
 *       } else {
 *         return true;
 *       }
 *     })
 *   }
 * });
 * ```
 *
 * ## Dependent Keys
 *
 * There will be times when your validator will be dependent on some other property or object. Instead of having to
 * include them in your option's `dependentKeys`, you can declare them in the static `getDependentsFor` hook. This hook
 * recieves two parameters. The first is the `attribute` that this validator is being added to, and the second are the `options`
 * there were passed to this validator.
 *
 * From the above code sample:
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({});
 *
 * UniqueUsername.reopenClass({
 *   getDependentsFor(attribute, options) {
 *     return [];
 *   }
 * });
 *
 * export default UniqueUsername;
 * ```
 *
 * All dependent keys are in reference to the model. So when you return `['username']`, it will add a dependent to `model.username`.
 * This means that if you have a dependent on a service, that service must be injected into the model since returning `['myService.someProperty']`
 * will be interpreted as `model.myService.someProperty`.
 *
 * ## Usage
 *
 * To use our unique-username validator we just have to add it to the model definition
 *
 * ```javascript
 * var Validations = buildValidations({
 *   username: validator('unique-username', {
 *     showSuggestions: true
 *   }),
 * });
 *
 * export default DS.Model.extend(Validations, {
 *   'username': DS.attr('string'),
 * });
 * ```
 *
 * ## Testing
 * As mentioned before, the generator created a unit test for your new custom validator.
 *
 * ```javascript
 * // tests/unit/validators/unique-username-test.js
 *
 * import Ember from 'ember';
 * import { moduleFor, test } from 'ember-qunit';
 *
 * moduleFor('validator:unique-username', 'Unit | Validator | unique-username', {
 *     needs: ['validator:messages']
 * });
 *
 * test('it works', function(assert) {
 *     var validator =  this.subject();
 *     assert.ok(validator);
 * });
 * ```
 *
 * A simple test for our validation method can be as such
 *
 * ```javascript
 * test('username is unique', function(assert) {
 *     assert.expect(1);
 *
 *     let validator =  this.subject();
 *     let done = assert.async();
 *
 *     validator.validate('johndoe42').then((message) => {
 *       assert.equal(message, true);
 *       done();
 *     });
 * });
 * ```
 *  @class Custom
 *  @module Validators
 *  @extends Base
 */

/**
 * A validator can also be declared with an inline function. The function will be then wrapped in the {{#crossLink 'Base'}}Base Validator{{/crossLink}} class and used just like any other pre-defined validator.
 *
 * ```javascript
 * // Example
 * validator(function(value, options, model, attribute) {
 *   return value === options.username ? true : `must be ${options.username}`;
 * } , {
 *   username: 'John' // Any options can be passed here
 * })
 * ```
 *
 * @class Inline
 * @module Validators
 * @extends Base
 */
<commit_msg>Fix custom validator dependent key docs<commit_after>/**
 * Copyright 2016, Yahoo! Inc.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

import Ember from 'ember';
import Messages from 'ember-cp-validations/validators/messages';
import getOwner from 'ember-getowner-polyfill';
import { unwrapString } from 'ember-cp-validations/utils/utils';

const {
  get,
  set,
  isNone
} = Ember;

const assign = Ember.assign || Ember.merge;

/**
 * @class Base
 * @module Validators
 */
const Base = Ember.Object.extend({

  /**
   * Options passed in to the validator when defined in the model
   * @property options
   * @type {Object}
   */
  options: null,

  /**
   * Default validation options for this specific attribute
   * @property defaultOptions
   * @type {Object}
   */
  defaultOptions: null,

  /**
   * Global validation options for this model
   * @property globalOptions
   * @type {Object}
   */
  globalOptions: null,

  /**
   * Model instance
   * @property model
   * @type {Model}
   */
  model: null,

  /**
   * Attributed name of the model this validator is attached to
   * @property attribute
   * @type {String}
   */
  attribute: null,

  /**
   * Error message object. Populated by validators/messages
   * @property errorMessages
   * @type {Object}
   */
  errorMessages: null,

  /**
   * Validator type
   * @property _type
   * @private
   * @type {String}
   */
  _type: null,

  init() {
    this._super(...arguments);
    const globalOptions = get(this, 'globalOptions');
    const defaultOptions = get(this, 'defaultOptions');
    const options = get(this, 'options');
    const owner = getOwner(this);
    let errorMessages;

    if (!isNone(owner)) {
      // Since default error messages are stored in app/validators/messages, we have to look it up via the owner
      errorMessages = owner._lookupFactory('validator:messages');
    }

    // If for some reason, we can't find the messages object (i.e. unit tests), use default
    errorMessages = errorMessages || Messages;

    set(this, 'options', this.buildOptions(options || {}, defaultOptions || {}, globalOptions || {}));
    set(this, 'errorMessages', errorMessages.create());
  },

  /**
   * Build options hook. Merges default options into options object.
   * This method gets called on init and is the ideal place to normalize your options.
   * The [presence validator](https://github.com/offirgolan/ember-cp-validations/blob/master/app/validators/presence.js) is a good example to checkout
   * @method buildOptions
   * @param  {Object} options
   * @param  {Object} defaultOptions
   * @param  {Object} globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    const builtOptions = assign(assign(assign({}, globalOptions), defaultOptions), options);

    // Overwrite the validator's value method if it exists in the options and remove it since
    // there is no need for it to be passed around
    this.value = builtOptions.value || this.value;
    delete builtOptions.value;

    return builtOptions;
  },

  /**
   * Creates a new object and calls any option property that is a function with the validator context.
   * This method is called right before `validate` and the returned object gets passed into the validate method as its options
   * @method processOptions
   * @return {Object}
   */
  processOptions() {
    const options = assign({}, get(this, 'options') || {});
    const model = get(this, 'model');
    const attribute = get(this, 'attribute');

    Object.keys(options).forEach(key => {
      const option = options[key];

      if (typeof option === 'function' && key !== 'message') {
        options[key] = option.call(this, model, attribute);
      }
    });

    return options;
  },

  /**
   * Used to retrieve the value to validate.
   * This method gets called right before `validate` and the returned value
   * gets passed into the validate method.
   *
   * @method value
   * @param {Object} model
   * @param {String} attribute
   * @return The current value of `model[attribute]`
   */
  value(model, attribute) {
    return get(model, attribute);
  },

  /**
   * Wrapper method to `value` that passes the necessary parameters
   *
   * @method getValue
   * @private
   * @return {Unknown} value
   */
  getValue() {
    return this.value(get(this, 'model'), get(this, 'attribute'));
  },

  /**
   * The validate method is where all of your logic should go.
   * It will get passed in the current value of the attribute this validator is attached to.
   * Within the validator object, you will have access to the following properties:
   * @method validate
   * @param  {Unknown} value        The current value of the attribute
   * @param  {Object} options       The built and processed options
   * @param  {Object} model         The current model being evaluated
   * @param  {String} attribute     The current attribute being evaluated
   * @return
   * One of the following types:
   * - `Boolean`:  `true` if the current value passed the validation
   * - `String`: The error message
   * - `Promise`: A promise that will either resolve or reject, and will finally return either `true` or the final error message string.
   */
  validate() {
    return true;
  },

  /**
   * Used by all pre-defined validators to build an error message that is present
   * in `validators/message` or declared in your i18n solution.
   *
   * If we extended our default messages to include `uniqueUsername: '{username} already exists'`,
   * we can use this method to generate our error message.
   *
   * ```javascript
   * validate(value, options) {
   *   var exists = false;
   *
   *   options.description = 'Username';
   *   options.username = value;
   *
   *   // check with server if username exists...
   *
   *   if(exists) {
   *     return this.createErrorMessage('uniqueUsername', value, options);
   *   }
   *
   *   return true;
   * }
   * ```
   *
   * If we input `johndoe` and that username already exists, the returned message would be `'johndoe already exists'`.
   *
   * @method createErrorMessage
   * @param  {String} type        The type of message template to use
   * @param  {Unknown} value                Current value being evaluated
   * @param  {Object} options     Validator built and processed options (used as the message string context)
   * @return {String}             The generated message
   */
  createErrorMessage(type, value, options = {}) {
    const messages = this.get('errorMessages');
    let message = unwrapString(options.message);

    options.description = messages.getDescriptionFor(get(this, 'attribute'), options);

    if (message) {
      if (typeof message === 'string') {
        message = messages.formatMessage(message, options);
      } else if (typeof message === 'function') {
        message = message.apply(this, arguments);
        message = isNone(message) ? messages.getMessageFor(type, options) : messages.formatMessage(message, options);
      }
    } else {
      message = messages.getMessageFor(type, options);
    }

    return message.trim();
  }
});

Base.reopenClass({
  /**
   * Generate the needed depenent keys for this validator
   *
   * @method getDependentsFor
   * @static
   * @param  {String} attribute
   * @param  {Object} options
   * @return {Array} dependent keys
   */
  getDependentsFor() {
    return [];
  }
});

export default Base;

/**
 * Creating custom validators is very simple. To generate a validator named `unique-username` in Ember CLI
 *
 * ```bash
 * ember generate validator unique-username
 * ```
 *
 * This will create the following files
 *
 * * `app/validators/unique-username.js`
 * * `tests/unit/validators/unique-username-test.js`
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({
 *   validate(value, options, model, attribute) {
 *     return true;
 *   }
 * });
 *
 * UniqueUsername.reopenClass({
 *   getDependentsFor(attribute, options) {
 *     return [];
 *   }
 * });
 *
 * export default UniqueUsername;
 * ```
 *
 * **Side Node**: Before we continue, I would suggest checking out the documentation for the {{#crossLink 'Base'}}Base Validator{{/crossLink}}.
 *
 * If you want to interact with the `store` within your validator, you can simply inject the service like you would a component.
 * Since you have access to your model and the current value, you should be able to send the server the right information to determine if this username is unique.
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import Ember from 'ember';
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({
 *   store: Ember.inject.service(),
 *
 *   validate(value, options, model, attribute) {
 *     return this.get('store').findRecord('user', value).then((user) => {
 *       if(user && user.id === value) {
 *         let message = `The username '${value}' already exists.`;
 *         let meta = user.get('meta');
 *
 *         if(options.showSuggestions && meta && meta.suggestions) {
 *           message += "What about one of the these: " + meta.suggestions.join(', ');
 *         }
 *         return message;
 *       } else {
 *         return true;
 *       }
 *     })
 *   }
 * });
 * ```
 *
 * ## Dependent Keys
 *
 * There will be times when your validator will be dependent on some other property or object. Instead of having to
 * include them in your option's `dependentKeys`, you can declare them in the static `getDependentsFor` hook. This hook
 * recieves two parameters. The first is the `attribute` that this validator is being added to, and the second are the `options`
 * there were passed to this validator.
 *
 * From the above code sample:
 *
 * ```javascript
 * // app/validators/unique-username.js
 *
 * import BaseValidator from 'ember-cp-validations/validators/base';
 *
 * const UniqueUsername = BaseValidator.extend({});
 *
 * UniqueUsername.reopenClass({
 *   getDependentsFor(attribute, options) {
 *     return [];
 *   }
 * });
 *
 * export default UniqueUsername;
 * ```
 *
 * All dependent keys are in reference to the model's `validations.attrs` object. So when you return `['username']`,
 * it will add a dependent to `model.validations.attrs.username`. If you want to add a dependent on the model, your
 * key needs to be prefixed with `_model`. So when you return `['_model.username']`, it will add a dependent to `model.username`.
 * This means that if you have a dependent on a service, that service must be injected into the model since returning `['_model.myService.someProperty']`
 * will be interpreted as `model.myService.someProperty`.
 *
 * ## Usage
 *
 * To use our unique-username validator we just have to add it to the model definition
 *
 * ```javascript
 * var Validations = buildValidations({
 *   username: validator('unique-username', {
 *     showSuggestions: true
 *   }),
 * });
 *
 * export default DS.Model.extend(Validations, {
 *   'username': DS.attr('string'),
 * });
 * ```
 *
 * ## Testing
 * As mentioned before, the generator created a unit test for your new custom validator.
 *
 * ```javascript
 * // tests/unit/validators/unique-username-test.js
 *
 * import Ember from 'ember';
 * import { moduleFor, test } from 'ember-qunit';
 *
 * moduleFor('validator:unique-username', 'Unit | Validator | unique-username', {
 *     needs: ['validator:messages']
 * });
 *
 * test('it works', function(assert) {
 *     var validator =  this.subject();
 *     assert.ok(validator);
 * });
 * ```
 *
 * A simple test for our validation method can be as such
 *
 * ```javascript
 * test('username is unique', function(assert) {
 *     assert.expect(1);
 *
 *     let validator =  this.subject();
 *     let done = assert.async();
 *
 *     validator.validate('johndoe42').then((message) => {
 *       assert.equal(message, true);
 *       done();
 *     });
 * });
 * ```
 *  @class Custom
 *  @module Validators
 *  @extends Base
 */

/**
 * A validator can also be declared with an inline function. The function will be then wrapped in the {{#crossLink 'Base'}}Base Validator{{/crossLink}} class and used just like any other pre-defined validator.
 *
 * ```javascript
 * // Example
 * validator(function(value, options, model, attribute) {
 *   return value === options.username ? true : `must be ${options.username}`;
 * } , {
 *   username: 'John' // Any options can be passed here
 * })
 * ```
 *
 * @class Inline
 * @module Validators
 * @extends Base
 */
<|endoftext|>


<commit_before>/**
 * @file DynamicRenderList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import List from '../List';
import Tip from '../Tip';
import Theme from '../Theme';

import SelectMode from '../_statics/SelectMode';
import LIST_SEPARATOR from '../_statics/ListSeparator';

import Util from '../_vendors/Util';
import Calculation from '../_vendors/Calculation';
import ComponentUtil from '../_vendors/ComponentUtil';

class DynamicRenderList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.lastDisplayIndex = null;
        this.displayIndex = null;

        this.state = {
            value: Calculation.getInitValue(props),
            scrollTop: 0
        };

    }

    /**
     * public
     */
    adjustScroll = () => {
        this.refs.list.adjustScroll();
    };

    /**
     * calculate final display index in list
     * @returns
     *  {
     *      start,
     *      stop,
     *      startWithBuffer,
     *      stopWithBuffer
     *  }
     */
    getIndex = () => {

        const {data, listHeight, itemHeight, scrollBuffer} = this.props,
            {scrollTop} = this.state;

        return this.displayIndex =
            Calculation.displayIndexByScrollTop(data, listHeight, itemHeight, scrollTop, scrollBuffer);

    };

    scrollHandler = e => {
        this.setState({
            scrollTop: this.dynamicRenderListEl.scrollTop
        }, () => {
            const {onScroll} = this.props;
            onScroll && onScroll(e);
        });
    };

    changeHandler = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    componentDidMount() {
        this.dynamicRenderListEl = this.refs.dynamicRenderList;
    }

    componentDidUpdate() {

        const {onRenderItemChange} = this.props;

        if (onRenderItemChange &&
            ((!this.displayIndex && this.lastDisplayIndex) || (this.displayIndex && !this.lastDisplayIndex)
                || (this.displayIndex && this.lastDisplayIndex
                    && (this.displayIndex.start !== this.lastDisplayIndex.start
                        || this.displayIndex.stop !== this.lastDisplayIndex.stop
                        || this.displayIndex.startWithBuffer !== this.lastDisplayIndex.startWithBuffer
                        || this.displayIndex.stopWithBuffer !== this.lastDisplayIndex.stopWithBuffer)))) {
            this.lastDisplayIndex = this.displayIndex;
            onRenderItemChange(this.displayIndex);
        }

    }

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            value: Calculation.getInitValue({
                value: ComponentUtil.getDerivedState(props, state, 'value'),
                selectMode: props.selectMode
            })
        };
    }

    render() {

        const {

                className, style, data, listHeight, itemHeight,

                // not passing down these props
                scrollBuffer, onRenderItemChange,

                ...restProps

            } = this.props,
            {value} = this.state,

            listClassName = classNames('dynamic-render-list', {
                [className]: className
            }),

            scrollerStyle = {
                height: data.length * itemHeight
            },

            index = this.getIndex(),

            filteredData = data && index ? data.slice(index.startWithBuffer, index.stopWithBuffer + 1) : data;

        return (

                    <List {...restProps}
                          ref="list"
                          style={{transform: `translateY(${index.startWithBuffer * itemHeight}px)`}}
                          data={filteredData}
                          value={value}
                          onChange={this.changeHandler}/>

        );

    }
}

DynamicRenderList.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The theme of the list item.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme of the list item select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * Children passed into the ListItem.
     */
    data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the list button.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the list button.
         */
        style: PropTypes.object,

        /**
         * The theme of the list button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the list button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The list item's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the list button. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the list item will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * If true,the element's ripple effect will be disabled.
         */
        disableTouchRipple: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        tip: PropTypes.string,

        /**
         * The position of tip.
         */
        tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

        /**
         * If true,the item will have center displayed ripple effect.
         */
        rippleDisplayCenter: PropTypes.bool,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a list item touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.string, PropTypes.number, PropTypes.symbol])).isRequired,

    /**
     * The id field name in data. (default: "id")
     */
    idField: PropTypes.string,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the list will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * List item disabled callback.
     */
    itemDisabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

    /**
     * If true, the list will be at loading status.
     */
    isLoading: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * Callback function fired when the list-item touch tap.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when the list-item select.
     */
    onItemSelect: PropTypes.func,

    /**
     * Callback function fired when the list-item deselect.
     */
    onItemDeselect: PropTypes.func,

    /**
     * Callback function fired when the list changed.
     */
    onChange: PropTypes.func,

    onRenderItemChange: PropTypes.func,

    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number

};

DynamicRenderList.defaultProps = {

    theme: Theme.DEFAULT,
    selectTheme: Theme.DEFAULT,

    data: [],

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    itemDisabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    listHeight: 200,
    itemHeight: 40,
    scrollBuffer: 6

};

export default DynamicRenderList;
<commit_msg>update DynamicRenderList<commit_after>/**
 * @file DynamicRenderList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import List from '../List';
import Tip from '../Tip';

import Theme from '../Theme';
import SelectMode from '../_statics/SelectMode';
import LIST_SEPARATOR from '../_statics/ListSeparator';

import Util from '../_vendors/Util';
import Calculation from '../_vendors/Calculation';
import ComponentUtil from '../_vendors/ComponentUtil';

class DynamicRenderList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.lastDisplayIndex = null;
        this.displayIndex = null;
        this.wrapper = createRef();
        this.wrapperEl = null;
        this.list = createRef();
        this.listInstance = null;

        this.state = {
            value: Calculation.getInitValue(props),
            scrollTop: 0
        };

    }

    /**
     * public
     */
    adjustScroll = () => {
        this.listInstance && this.listInstance.adjustScroll();
    };

    /**
     * calculate final display index in list
     * @returns
     *  {
     *      start,
     *      stop,
     *      startWithBuffer,
     *      stopWithBuffer
     *  }
     */
    getIndex = () => {

        const {data, listHeight, itemHeight, scrollBuffer} = this.props,
            {scrollTop} = this.state;

        return this.displayIndex =
            Calculation.displayIndexByScrollTop(data, listHeight, itemHeight, scrollTop, scrollBuffer);

    };

    handleScroll = e => {
        this.setState({
            scrollTop: this.wrapperEl ? this.wrapperEl.scrollTop : 0
        }, () => {
            const {onScroll} = this.props;
            onScroll && onScroll(e);
        });
    };

    handleChange = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    componentDidMount() {
        this.wrapperEl = this.wrapper && this.wrapper.current;
        this.listInstance = this.list && this.list.current;
    }

    componentDidUpdate() {

        const {onRenderItemChange} = this.props;

        if (onRenderItemChange &&
            ((!this.displayIndex && this.lastDisplayIndex) || (this.displayIndex && !this.lastDisplayIndex)
                || (this.displayIndex && this.lastDisplayIndex
                    && (this.displayIndex.start !== this.lastDisplayIndex.start
                        || this.displayIndex.stop !== this.lastDisplayIndex.stop
                        || this.displayIndex.startWithBuffer !== this.lastDisplayIndex.startWithBuffer
                        || this.displayIndex.stopWithBuffer !== this.lastDisplayIndex.stopWithBuffer)))) {
            this.lastDisplayIndex = this.displayIndex;
            onRenderItemChange(this.displayIndex);
        }

    }

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            value: Calculation.getInitValue({
                value: ComponentUtil.getDerivedState(props, state, 'value'),
                selectMode: props.selectMode
            })
        };
    }

    render() {

        const {

                className, style, data, listHeight, itemHeight,

                // not passing down these props
                scrollBuffer, onRenderItemChange,

                ...restProps

            } = this.props,
            {value} = this.state,

            index = this.getIndex(),
            filteredData = data && index ? data.slice(index.startWithBuffer, index.stopWithBuffer + 1) : data;

        return (

                    <List {...restProps}
                          ref={this.list}
                          style={{transform: `translateY(${index.startWithBuffer * itemHeight}px)`}}
                          data={filteredData}
                          value={value}
                          onChange={this.handleChange}/>

        );

    }
}

DynamicRenderList.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The theme of the list item.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme of the list item select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * Children passed into the ListItem.
     */
    data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the list button.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the list button.
         */
        style: PropTypes.object,

        /**
         * The theme of the list button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the list button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The list item's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the list button. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the list item will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * If true,the element's ripple effect will be disabled.
         */
        disableTouchRipple: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        tip: PropTypes.string,

        /**
         * The position of tip.
         */
        tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

        /**
         * If true,the item will have center displayed ripple effect.
         */
        rippleDisplayCenter: PropTypes.bool,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a list item touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.string, PropTypes.number, PropTypes.symbol])).isRequired,

    /**
     * The id field name in data. (default: "id")
     */
    idField: PropTypes.string,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the list will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * List item disabled callback.
     */
    itemDisabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

    /**
     * If true, the list will be at loading status.
     */
    isLoading: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * Callback function fired when the list-item touch tap.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when the list-item select.
     */
    onItemSelect: PropTypes.func,

    /**
     * Callback function fired when the list-item deselect.
     */
    onItemDeselect: PropTypes.func,

    /**
     * Callback function fired when the list changed.
     */
    onChange: PropTypes.func,

    onRenderItemChange: PropTypes.func,
    onScroll: PropTypes.func,

    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number

};

DynamicRenderList.defaultProps = {

    theme: Theme.DEFAULT,
    selectTheme: Theme.DEFAULT,

    data: [],

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    itemDisabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    listHeight: 200,
    itemHeight: 40,
    scrollBuffer: 6

};

export default DynamicRenderList;
<|endoftext|>


<commit_before>/*$AMPERSAND_VERSION*/
var View = require('ampersand-view');

function InfiniteScrollClosure(options){
	var def = {
		reverse: false,
		threshold: 20,
		fetch: {
			limit: 10
		}
	};
	options || (options = {});
	var reverse = (options.reverse || def.reverse);
	var threshold = (options.threshold || def.threshold);
	var fetch = (options.fetch || def.fetch);

	this.events.scroll = 'infiniteScroll';

	this.infiniteScroll = function cb(){
		if(this.el.scrollHeight - this.el.scrollTop >= this.el.clientHeight - threshold){
			this.collection({data: fetch});
		}
	};
}

var InfiniteScrollView;

InfiniteScrollView = function(options){
	InfiniteScrollClosure.call(this, options.infiniteScroll);
	BaseView.call(this, options);
};

var BaseView = View.extend();
InfiniteScrollView.prototype = Object.create(BaseView.prototype);
InfiniteScrollView.extend = BaseView.extend;

module.exports = InfiniteScrollView;<commit_msg>working version<commit_after>/*$AMPERSAND_VERSION*/
var View = require('ampersand-view');
var _ = require('underscore');

function InfiniteScrollClosure(options){
	var def = {
		reverse: false,
		gap: 20,
		fetch: {
			limit: 10
		}
	};
	options || (options = {});
	var reverse = (options.reverse || def.reverse);
	var gap = (options.gap || def.gap);
	var fetch = (options.fetch || def.fetch);

	_.extend(this, {events: {scroll: 'infiniteScroll'}});

	this.infiniteScroll = function cb(){
		if(this.el.scrollHeight - this.el.scrollTop <= this.el.clientHeight + gap){
			this.collection({data: fetch});
		}
	};
}

var InfiniteScrollView;

InfiniteScrollView = function(options){
	options || (options = {});
	BaseView.call(this, options);
	InfiniteScrollClosure.call(this, options);
};

var BaseView = View.extend();
InfiniteScrollView.prototype = Object.create(BaseView.prototype);
InfiniteScrollView.extend = BaseView.extend;

module.exports = InfiniteScrollView;<|endoftext|>


<commit_before>/**
 * Copyright 2016 PT Inovação e Sistemas SA
 * Copyright 2016 INESC-ID
 * Copyright 2016 QUOBIS NETWORKS SL
 * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
 * Copyright 2016 ORANGE SA
 * Copyright 2016 Deutsche Telekom AG
 * Copyright 2016 Apizee
 * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
var dataObject = require('./dataObject');
var hyperty = require('./hyperty');
var Request = require('./request');

var RegistryConnector = function(url, retries) {

  this._request = new Request(retries);
  this._registryURL = url;
};

RegistryConnector.prototype.processMessage = function(msg, callback) {
  switch(msg.type.toLowerCase()) {
    case "read":
      this.readOperation(msg, callback);
    break;

    case "create":
      this.createOperation(msg, callback);
    break;

    case "update":
      this.updateOperation(msg, callback);
    break;

    case "delete":
      this.deleteOperation(msg, callback);
    break;
  }
};

RegistryConnector.prototype.checkResourceType = function(url) {

  var prefix = url.split('://')[0];

  if(prefix === 'user'){
    return 'hyperty';
  }else {
    return 'dataObject';
  }
};

RegistryConnector.prototype.checkUrlType = function(url) {

  var prefix = url.split('://')[0];

  if(prefix === 'hyperty' || prefix === 'user'){
    return 'hyperty';
  }else {
    return 'dataObject';
  }
};

RegistryConnector.prototype.readOperation = function(msg, callback) {
  if('criteria' in msg.body) {
    if(this.checkResourceType(msg.body.resource) === 'hyperty') {
      hyperty.read(msg.body, this._request, this._registryURL, true, callback);
    }else {
      dataObject.read(msg.body, this._request, this._registryURL, true, callback);
    }
  }else {
    if(this.checkResourceType(msg.body.resource) === 'hyperty') {
      hyperty.read(msg.body, this._request, this._registryURL, false, callback);
    }else {
      dataObject.read(msg.body, this._request, this._registryURL, false, callback);
    }
  }
};

RegistryConnector.prototype.createOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.value.url) === 'hyperty') {
    hyperty.create(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.create(msg.body, this._request, this._registryURL, callback);
  }
};

RegistryConnector.prototype.updateOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.value.url) === 'hyperty') {
    hyperty.update(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.update(msg.body, this._request, this._registryURL, callback);
  }
};

RegistryConnector.prototype.deleteOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.value.url) === 'hyperty') {
    hyperty.del(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.del(msg.body, this._request, this._registryURL, callback);
  }
};

module.exports = RegistryConnector;
<commit_msg>Fix update message verification accordingly to specs. #28<commit_after>/**
 * Copyright 2016 PT Inovação e Sistemas SA
 * Copyright 2016 INESC-ID
 * Copyright 2016 QUOBIS NETWORKS SL
 * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
 * Copyright 2016 ORANGE SA
 * Copyright 2016 Deutsche Telekom AG
 * Copyright 2016 Apizee
 * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
var dataObject = require('./dataObject');
var hyperty = require('./hyperty');
var Request = require('./request');

var RegistryConnector = function(url, retries) {

  this._request = new Request(retries);
  this._registryURL = url;
};

RegistryConnector.prototype.processMessage = function(msg, callback) {
  switch(msg.type.toLowerCase()) {
    case "read":
      this.readOperation(msg, callback);
    break;

    case "create":
      this.createOperation(msg, callback);
    break;

    case "update":
      this.updateOperation(msg, callback);
    break;

    case "delete":
      this.deleteOperation(msg, callback);
    break;
  }
};

RegistryConnector.prototype.checkResourceType = function(url) {

  var prefix = url.split('://')[0];

  if(prefix === 'user'){
    return 'hyperty';
  }else {
    return 'dataObject';
  }
};

RegistryConnector.prototype.checkUrlType = function(url) {

  var prefix = url.split('://')[0];

  if(prefix === 'hyperty' || prefix === 'user'){
    return 'hyperty';
  }else {
    return 'dataObject';
  }
};

RegistryConnector.prototype.readOperation = function(msg, callback) {
  if('criteria' in msg.body) {
    if(this.checkResourceType(msg.body.resource) === 'hyperty') {
      hyperty.read(msg.body, this._request, this._registryURL, true, callback);
    }else {
      dataObject.read(msg.body, this._request, this._registryURL, true, callback);
    }
  }else {
    if(this.checkResourceType(msg.body.resource) === 'hyperty') {
      hyperty.read(msg.body, this._request, this._registryURL, false, callback);
    }else {
      dataObject.read(msg.body, this._request, this._registryURL, false, callback);
    }
  }
};

RegistryConnector.prototype.createOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.value.url) === 'hyperty') {
    hyperty.create(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.create(msg.body, this._request, this._registryURL, callback);
  }
};

RegistryConnector.prototype.updateOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.resource) === 'hyperty') {
    hyperty.update(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.update(msg.body, this._request, this._registryURL, callback);
  }
};

RegistryConnector.prototype.deleteOperation = function(msg, callback) {
  if(this.checkUrlType(msg.body.value.url) === 'hyperty') {
    hyperty.del(msg.body, this._request, this._registryURL, callback);
  }else {
    dataObject.del(msg.body, this._request, this._registryURL, callback);
  }
};

module.exports = RegistryConnector;
<|endoftext|>