<commit_before>  //////////////////////////////////////////////////////////////////////////////
/**
 * @module geo.gl
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of polygonFeature
 *
 * @class
 * @returns {geo.gl.polygonFeature}
 */
//////////////////////////////////////////////////////////////////////////////
geo.gl.polygonFeature = function (arg) {
  'use strict';
  if (!(this instanceof geo.gl.polygonFeature)) {
    return new geo.gl.polygonFeature(arg);
  }
  arg = arg || {};
  geo.polygonFeature.call(this, arg);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  ////////////////////////////////////////////////////////////////////////////
  var m_this = this,
      m_actor = null,
      s_init = this._init,
      s_update = this._update;

  function createVertexShader() {
      var vertexShaderSource = [
        'attribute vec3 pos;',
        'attribute vec3 fillColor;',
        'attribute float fillOpacity;',
        'uniform mat4 modelViewMatrix;',
        'uniform mat4 projectionMatrix;',
        'uniform float pixelWidth;',
        'varying vec3 fillColorVar;',
        'varying float fillOpacityVar;',

        'void main(void)',
        '{',
        '  vec4 clipPos = projectionMatrix * modelViewMatrix * vec4(pos.xyz, 1);',
        '  if (clipPos.w != 0.0) {',
        '    clipPos = clipPos/clipPos.w;',
        '  }',
        '  fillColorVar = fillColor;',
        '  fillOpacityVar = fillOpacity;',
        '  gl_Position = clipPos;',
        '}'
      ].join('\n'),
      shader = new vgl.shader(gl.VERTEX_SHADER);
      shader.setShaderSource(vertexShaderSource);
      return shader;
    }

  function createFragmentShader() {
    var fragmentShaderSource = [
      '#ifdef GL_ES',
      '  precision highp float;',
      '#endif',
      'varying vec3 fillColorVar;',
      'varying float fillOpacityVar;',
      'void main () {',
      '  gl_FragColor = vec4 (fillColorVar, fillOpacityVar);',
      '}'
    ].join('\n'),
    shader = new vgl.shader(gl.FRAGMENT_SHADER);
    shader.setShaderSource(fragmentShaderSource);
    return shader;
  }

  function createGLPolygons() {
    var i = null,
        numPolygons = m_this.data().length,
        p = null,
        numPts = null,
        start = null,
        itemIndex = 0,
        polygonItemCoordIndex = 0,
        position = [],
        polygonItemCoords = null,
        fillColor = [],
        fillOpacity = [],
        fillColorNew = [],
        fillOpacityNew = [],
        posFunc = null,
        fillColorFunc = null,
        polygonItem = null,
        fillOpacityFunc = null,
        buffers = vgl.DataBuffers(1024),
        sourcePositions = vgl.sourceDataP3fv(),
        sourceFillColor =
          vgl.sourceDataAnyfv(3, vgl.vertexAttributeKeysIndexed.Two),
        sourceFillOpacity =
          vgl.sourceDataAnyfv(1, vgl.vertexAttributeKeysIndexed.Three),
        trianglePrimitive = vgl.triangles(),
        mat = vgl.material(), blend = vgl.blend(),
        prog = vgl.shaderProgram(), vertexShader = createVertexShader(),
        fragmentShader = createFragmentShader(),
        posAttr = vgl.vertexAttribute('pos'),
        fillColorAttr = vgl.vertexAttribute('fillColor'),
        fillOpacityAttr = vgl.vertexAttribute('fillOpacity'),
        modelViewUniform = new vgl.modelViewUniform('modelViewMatrix'),
        projectionUniform = new vgl.projectionUniform('projectionMatrix'),
        geom = vgl.geometryData(),
        mapper = vgl.mapper(),
        polygon = null,
        holes = null,
        extRing = null,
        extIndex = 0,
        extLength = null,
        intIndex = 0,
        posInstance = null;

    posFunc = m_this.position();
    fillColorFunc = m_this.style.get('fillColor');
    fillOpacityFunc = m_this.style.get('fillOpacity');

    m_this.data().forEach(function (item) {
      polygon = m_this.polygon()(item, itemIndex);
      polygonItem = polygon.outer;
      holes = polygon.inner;
      polygonItemCoordIndex = 0;
      extRing = [], extIndex = 0, extLength = polygonItem.length - 1;
      extRing[0] = [];
      intIndex = 0;

      polygonItem.forEach(function (extRingCoords) {
        if (extIndex !== extLength) {
          //extRing = extRing.concat(extRingCoords);
          posInstance = posFunc(item, itemIndex,
                                extRingCoords, polygonItemCoordIndex);
          if (posInstance instanceof geo.latlng) {
            extRing[0].push({x: posInstance.x(), y: posInstance.y()});
          } else {
            extRing[0].push({x: posInstance.x, y: posInstance.y});
          }

          var sc = fillColorFunc(item, itemIndex, polygonItemCoords, polygonItemCoordIndex);
          fillColor.push([sc.r, sc.g, sc.b]);
          fillOpacity.push(fillOpacityFunc(item, itemIndex, polygonItemCoords, polygonItemCoordIndex));
          polygonItemCoordIndex += 1;
        }
        ++extIndex;
      });

      polygonItemCoordIndex = 0;
      holes.forEach(function (hole) {
        extRing[intIndex + 1] = [];
        hole.forEach(function (intRingCoords) {
          posInstance = posFunc(item, itemIndex,
                                intRingCoords, polygonItemCoordIndex);
          var sc = fillColorFunc(item, itemIndex, intRingCoords, polygonItemCoordIndex);
          fillColor.push([sc.r, sc.g, sc.b]);
          fillOpacity.push(fillOpacityFunc(item, itemIndex, intRingCoords, polygonItemCoordIndex));
          polygonItemCoordIndex += 1;
          extRing[intIndex + 1].push({x: intRingCoords[0], y: intRingCoords[1]});
        });
        ++intIndex;
      });

      //console.log("extRing ", extRing);
      //console.log("result", PolyK.Triangulate(extRing));
      var myTriangulator = new PNLTRI.Triangulator();
      var triangList = myTriangulator.triangulate_polygon( extRing );
      var newTriangList = [];
      //var result = PolyK.Triangulate(extRing)
      //console.log(triangList);

      triangList.forEach(function (newIndices) {
        newTriangList = newTriangList.concat(newIndices);
      });

      console.log("newTriangList length ", newTriangList.length);
      newTriangList.forEach(function (polygonIndex) {
        if (polygonIndex < extRing[0].length) {
          polygonItemCoords = extRing[0][polygonIndex];
        } else {
          polygonItemCoords = extRing[1][polygonIndex - extRing[0].length];
        }
        position.push([polygonItemCoords.x, polygonItemCoords.y, polygonItemCoords.z || 0.0]);
        fillColorNew.push(fillColor[polygonIndex]);
        fillOpacityNew.push(fillOpacity[polygonIndex]);
      });

      itemIndex += 1;
    });

    position = geo.transform.transformCoordinates(
                 m_this.gcs(), m_this.layer().map().gcs(),
                 position, 3);

    buffers.create('pos', 3);
    buffers.create('indices', 1);
    buffers.create('fillColor', 3);
    buffers.create('fillOpacity', 1);

    numPts = position.length;

    // TODO: Right now this is ugly but we will fix it.
    prog.addVertexAttribute(posAttr,
      vgl.vertexAttributeKeys.Position);
    prog.addVertexAttribute(fillColorAttr,
      vgl.vertexAttributeKeysIndexed.Two);
    prog.addVertexAttribute(fillOpacityAttr,
      vgl.vertexAttributeKeysIndexed.Three);

    prog.addUniform(modelViewUniform);
    prog.addUniform(projectionUniform);

    prog.addShader(fragmentShader);
    prog.addShader(vertexShader);

    mat.addAttribute(prog);
    mat.addAttribute(blend);

    m_actor = vgl.actor();
    m_actor.setMaterial(mat);

    start = buffers.alloc(numPts);
    var currentIndex = start;

    //console.log("numPts ", numPts);
    for (i = 0; i < numPts; i += 1) {
      console.log("i is ", i);
      buffers.write('pos', position[i], start + i, 1);
      buffers.write('indices', [i], start + i, 1);
      buffers.write('fillColor', fillColorNew[i], start + i, 1);
      buffers.write('fillOpacity', [fillOpacityNew[i]], start + i, 1);
    }

    //console.log(buffers.get('fillColor'));
    sourcePositions.pushBack(buffers.get('pos'));
    geom.addSource(sourcePositions);

    sourceFillColor.pushBack(buffers.get('fillColor'));
    geom.addSource(sourceFillColor);

    sourceFillOpacity.pushBack(buffers.get('fillOpacity'));
    geom.addSource(sourceFillOpacity);

    //console.log(buffers.get('indices'));
    trianglePrimitive.setIndices(buffers.get('indices'));
    geom.addPrimitive(trianglePrimitive);

    mapper.setGeometryData(geom);
    m_actor.setMapper(mapper);
  }

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Initialize
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function (arg) {
    s_init.call(m_this, arg);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Build
   *
   * @override
   */
  ////////////////////////////////////////////////////////////////////////////
  this._build = function () {
    if (m_actor) {
      m_this.renderer().contextRenderer().removeActor(m_actor);
    }

    createGLPolygons();

    m_this.renderer().contextRenderer().addActor(m_actor);
    m_this.buildTime().modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update
   *
   * @override
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function () {
    s_update.call(m_this);

    if (m_this.dataTime().getMTime() >= m_this.buildTime().getMTime() ||
        m_this.updateTime().getMTime() <= m_this.getMTime()) {
      m_this._build();
    }

    m_actor.setVisible(m_this.visible());
    m_actor.material().setBinNumber(m_this.bin());
    m_this.updateTime().modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Destroy
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function () {
    m_this.renderer().contextRenderer().removeActor(m_actor);
  };

  this._init(arg);
  return this;
};

inherit(geo.gl.polygonFeature, geo.polygonFeature);

// Now register it
geo.registerFeature('vgl', 'polygon', geo.gl.polygonFeature);
<commit_msg>Updated the code so that it will work with multiple holes<commit_after>  //////////////////////////////////////////////////////////////////////////////
/**
 * @module geo.gl
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of polygonFeature
 *
 * @class
 * @returns {geo.gl.polygonFeature}
 */
//////////////////////////////////////////////////////////////////////////////
geo.gl.polygonFeature = function (arg) {
  'use strict';
  if (!(this instanceof geo.gl.polygonFeature)) {
    return new geo.gl.polygonFeature(arg);
  }
  arg = arg || {};
  geo.polygonFeature.call(this, arg);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  ////////////////////////////////////////////////////////////////////////////
  var m_this = this,
      m_actor = null,
      s_init = this._init,
      s_update = this._update;

  function createVertexShader() {
      var vertexShaderSource = [
        'attribute vec3 pos;',
        'attribute vec3 fillColor;',
        'attribute float fillOpacity;',
        'uniform mat4 modelViewMatrix;',
        'uniform mat4 projectionMatrix;',
        'uniform float pixelWidth;',
        'varying vec3 fillColorVar;',
        'varying float fillOpacityVar;',

        'void main(void)',
        '{',
        '  vec4 clipPos = projectionMatrix * modelViewMatrix * vec4(pos.xyz, 1);',
        '  if (clipPos.w != 0.0) {',
        '    clipPos = clipPos/clipPos.w;',
        '  }',
        '  fillColorVar = fillColor;',
        '  fillOpacityVar = fillOpacity;',
        '  gl_Position = clipPos;',
        '}'
      ].join('\n'),
      shader = new vgl.shader(gl.VERTEX_SHADER);
      shader.setShaderSource(vertexShaderSource);
      return shader;
    }

  function createFragmentShader() {
    var fragmentShaderSource = [
      '#ifdef GL_ES',
      '  precision highp float;',
      '#endif',
      'varying vec3 fillColorVar;',
      'varying float fillOpacityVar;',
      'void main () {',
      '  gl_FragColor = vec4 (fillColorVar, fillOpacityVar);',
      '}'
    ].join('\n'),
    shader = new vgl.shader(gl.FRAGMENT_SHADER);
    shader.setShaderSource(fragmentShaderSource);
    return shader;
  }

  function createGLPolygons() {
    var i = null,
        numPolygons = m_this.data().length,
        p = null,
        numPts = null,
        start = null,
        itemIndex = 0,
        polygonItemCoordIndex = 0,
        position = [],
        polygonItemCoords = null,
        fillColor = [],
        fillOpacity = [],
        fillColorNew = [],
        fillOpacityNew = [],
        posFunc = null,
        fillColorFunc = null,
        polygonItem = null,
        fillOpacityFunc = null,
        buffers = vgl.DataBuffers(1024),
        sourcePositions = vgl.sourceDataP3fv(),
        sourceFillColor =
          vgl.sourceDataAnyfv(3, vgl.vertexAttributeKeysIndexed.Two),
        sourceFillOpacity =
          vgl.sourceDataAnyfv(1, vgl.vertexAttributeKeysIndexed.Three),
        trianglePrimitive = vgl.triangles(),
        mat = vgl.material(), blend = vgl.blend(),
        prog = vgl.shaderProgram(), vertexShader = createVertexShader(),
        fragmentShader = createFragmentShader(),
        posAttr = vgl.vertexAttribute('pos'),
        fillColorAttr = vgl.vertexAttribute('fillColor'),
        fillOpacityAttr = vgl.vertexAttribute('fillOpacity'),
        modelViewUniform = new vgl.modelViewUniform('modelViewMatrix'),
        projectionUniform = new vgl.projectionUniform('projectionMatrix'),
        geom = vgl.geometryData(),
        mapper = vgl.mapper(),
        polygon = null,
        holes = null,
        extRing = null,
        extIndex = 0,
        extLength = null,
        intIndex = 0,
        posInstance = null;

    posFunc = m_this.position();
    fillColorFunc = m_this.style.get('fillColor');
    fillOpacityFunc = m_this.style.get('fillOpacity');

    m_this.data().forEach(function (item) {
      polygon = m_this.polygon()(item, itemIndex);
      polygonItem = polygon.outer;
      holes = polygon.inner;
      polygonItemCoordIndex = 0;
      extRing = [], extIndex = 0, extLength = polygonItem.length - 1;
      extRing[0] = [];
      intIndex = 0;

      polygonItem.forEach(function (extRingCoords) {
        if (extIndex !== extLength) {
          //extRing = extRing.concat(extRingCoords);
          posInstance = posFunc(item, itemIndex,
                                extRingCoords, polygonItemCoordIndex);
          if (posInstance instanceof geo.latlng) {
            extRing[0].push({x: posInstance.x(), y: posInstance.y()});
          } else {
            extRing[0].push({x: posInstance.x, y: posInstance.y});
          }

          var sc = fillColorFunc(item, itemIndex, polygonItemCoords, polygonItemCoordIndex);
          fillColor.push([sc.r, sc.g, sc.b]);
          fillOpacity.push(fillOpacityFunc(item, itemIndex, polygonItemCoords, polygonItemCoordIndex));
          polygonItemCoordIndex += 1;
        }
        ++extIndex;
      });

      polygonItemCoordIndex = 0;
      holes.forEach(function (hole) {
        extRing[intIndex + 1] = [];
        hole.forEach(function (intRingCoords) {
          posInstance = posFunc(item, itemIndex,
                                intRingCoords, polygonItemCoordIndex);
          var sc = fillColorFunc(item, itemIndex, intRingCoords, polygonItemCoordIndex);
          fillColor.push([sc.r, sc.g, sc.b]);
          fillOpacity.push(fillOpacityFunc(item, itemIndex, intRingCoords, polygonItemCoordIndex));
          polygonItemCoordIndex += 1;
          extRing[intIndex + 1].push({x: intRingCoords[0], y: intRingCoords[1]});
        });
        ++intIndex;
      });

      //console.log("extRing ", extRing);
      //console.log("result", PolyK.Triangulate(extRing));
      var myTriangulator = new PNLTRI.Triangulator();
      var triangList = myTriangulator.triangulate_polygon( extRing );
      var newTriangList = [];
      //var result = PolyK.Triangulate(extRing)
      //console.log(triangList);

      triangList.forEach(function (newIndices) {
        newTriangList = newTriangList.concat(newIndices);
      });

      for (i = 1; i < extRing.length; ++i) {
        extRing[0] = extRing[0].concat(extRing[i]);
      }

      console.log("newTriangList length ", newTriangList.length);
      newTriangList.forEach(function (polygonIndex) {
        // if (polygonIndex < extRing[0].length) {
        //   polygonItemCoords = extRing[0][polygonIndex];
        // } else {
        //   polygonItemCoords = extRing[1][polygonIndex - extRing[0].length];
        // }
        polygonItemCoords = extRing[0][polygonIndex];
        position.push([polygonItemCoords.x, polygonItemCoords.y, polygonItemCoords.z || 0.0]);
        fillColorNew.push(fillColor[polygonIndex]);
        fillOpacityNew.push(fillOpacity[polygonIndex]);
      });

      itemIndex += 1;
    });

    position = geo.transform.transformCoordinates(
                 m_this.gcs(), m_this.layer().map().gcs(),
                 position, 3);

    buffers.create('pos', 3);
    buffers.create('indices', 1);
    buffers.create('fillColor', 3);
    buffers.create('fillOpacity', 1);

    numPts = position.length;

    // TODO: Right now this is ugly but we will fix it.
    prog.addVertexAttribute(posAttr,
      vgl.vertexAttributeKeys.Position);
    prog.addVertexAttribute(fillColorAttr,
      vgl.vertexAttributeKeysIndexed.Two);
    prog.addVertexAttribute(fillOpacityAttr,
      vgl.vertexAttributeKeysIndexed.Three);

    prog.addUniform(modelViewUniform);
    prog.addUniform(projectionUniform);

    prog.addShader(fragmentShader);
    prog.addShader(vertexShader);

    mat.addAttribute(prog);
    mat.addAttribute(blend);

    m_actor = vgl.actor();
    m_actor.setMaterial(mat);

    start = buffers.alloc(numPts);
    var currentIndex = start;

    //console.log("numPts ", numPts);
    for (i = 0; i < numPts; i += 1) {
      console.log("i is ", i);
      buffers.write('pos', position[i], start + i, 1);
      buffers.write('indices', [i], start + i, 1);
      buffers.write('fillColor', fillColorNew[i], start + i, 1);
      buffers.write('fillOpacity', [fillOpacityNew[i]], start + i, 1);
    }

    //console.log(buffers.get('fillColor'));
    sourcePositions.pushBack(buffers.get('pos'));
    geom.addSource(sourcePositions);

    sourceFillColor.pushBack(buffers.get('fillColor'));
    geom.addSource(sourceFillColor);

    sourceFillOpacity.pushBack(buffers.get('fillOpacity'));
    geom.addSource(sourceFillOpacity);

    //console.log(buffers.get('indices'));
    trianglePrimitive.setIndices(buffers.get('indices'));
    geom.addPrimitive(trianglePrimitive);

    mapper.setGeometryData(geom);
    m_actor.setMapper(mapper);
  }

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Initialize
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function (arg) {
    s_init.call(m_this, arg);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Build
   *
   * @override
   */
  ////////////////////////////////////////////////////////////////////////////
  this._build = function () {
    if (m_actor) {
      m_this.renderer().contextRenderer().removeActor(m_actor);
    }

    createGLPolygons();

    m_this.renderer().contextRenderer().addActor(m_actor);
    m_this.buildTime().modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update
   *
   * @override
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function () {
    s_update.call(m_this);

    if (m_this.dataTime().getMTime() >= m_this.buildTime().getMTime() ||
        m_this.updateTime().getMTime() <= m_this.getMTime()) {
      m_this._build();
    }

    m_actor.setVisible(m_this.visible());
    m_actor.material().setBinNumber(m_this.bin());
    m_this.updateTime().modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Destroy
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function () {
    m_this.renderer().contextRenderer().removeActor(m_actor);
  };

  this._init(arg);
  return this;
};

inherit(geo.gl.polygonFeature, geo.polygonFeature);

// Now register it
geo.registerFeature('vgl', 'polygon', geo.gl.polygonFeature);
<|endoftext|>


<commit_before>/**
 * Determine if call expression is part of a computed property
 * @example `foo: Ember.computed('a', function () {})`
 * @example `foo: computed('a', function () {})`
 * @param {ESLintNode} node - call expression node
 * @param {String} computedVarName - destructured variable name for Ember.computed
 * @returns {Boolean} whether or not call expression is part of a computed property
 */
function isComputedProperty (node, computedVarName) {
  if (!node.parent || !node.parent.callee) {
    return false
  }

  var isStructuredComputedProperyCall = (
    node.parent.callee.property && node.parent.callee.property.name === 'computed'
  )

  var isUnstructuredComputedPropertyCall = node.parent.callee.name === computedVarName

  return isStructuredComputedProperyCall || isUnstructuredComputedPropertyCall
}

/**
 * Determine if call expression is part of a decorator computed property
 * @example
 *   ```
 *   @computed('bar')
 *   foo (bar) {}
 *   ```
 * @param {ESLintNode} node - call expression node
 * @param {String} computedDecoratorVarName - imported default for ember-computed-decorators
 * @returns {Boolean} whether or not call expression is part of a decorator CP
 */
function isDecoratorComputedProperty (node, computedDecoratorVarName) {
  if (!node.parent || !node.parent.decorators) {
    return false
  }

  return node.parent.decorators
    .some(function (decorator) {
      return (
        decorator.expression &&
        decorator.expression.callee &&
        decorator.expression.callee.name === computedDecoratorVarName
      )
    })
}

/**
 * Determine if current call expression is a call to Ember.set() or this.set()
 * @param {ESLintNode} node - call expression node
 * @param {String} setVarName - destructured variable name for Ember.set
 * @param {String} emberVarName - variable name for Ember import
 * @returns {Boolean} whether or not call is a set call
 */
function isSetCall (node, setVarName, emberVarName) {
  // Structured set call (i.e. `Ember.set()`` or `this.set()`)
  if (
    node.callee.property &&
    node.callee.property.name === 'set' &&
    node.callee.object &&
    (node.callee.object.type === 'ThisExpression' || node.callee.object.name === emberVarName)
  ) {
    return true
  }

  // Unstructured call (i.e. `set()`)
  return node.callee.name === setVarName
}

module.exports = {
  create: function (context) {
    var computedDecoratorVarName = null
    var computedVarName = null
    var currentComputedProperty = null
    var emberVarName = 'Ember'
    var setVarName = null

    return {
      /**
       * Determine if a set call is being made while we are within a computed
       * property
       * @param {ESLintNode} node - call expression node
       */
      CallExpression: function (node) {
        if (
          currentComputedProperty &&
          isSetCall(node, setVarName, emberVarName)
        ) {
          context.report(node, 'Do not call this.set() or Ember.set() in a computed property')
        }
      },

      /**
       * Determine if we are entering a computed property
       * @param {ESLintNode} node - function expression node
       */
      FunctionExpression: function (node) {
        if (
          isComputedProperty(node, computedVarName) ||
          isDecoratorComputedProperty(node, computedDecoratorVarName)
        ) {
          currentComputedProperty = node
        }
      },

      /**
       * Determine if we are leaving a computed property
       * @param {ESLintNode} node - function expression node
       */
      'FunctionExpression:exit': function (node) {
        if (node === currentComputedProperty) {
          currentComputedProperty = null
        }
      },

      /**
       * Get Ember variable name from import statement
       * @example `import Ember from 'ember'` would yield "Ember"
       * @example `import Foo from 'ember'` would yield "Foo"
       * @param {ESLintNode} node - import declaration node
       */
      ImportDeclaration: function (node) {
        switch (node.source.value) {
          case 'ember':
            emberVarName = node.specifiers[0].local.name
            break

          case 'ember-computed-decorators':
            computedDecoratorVarName = node.specifiers[0].local.name
            break
        }
      },

      /**
       * Get destructured variable names that effect this rule
       * @example `const {computed} = Ember` would use "computed" when looking
       * for computed properties whereas `const {computed: react} = Ember` would
       * use "react" instead of "computed"
       * @param {ESLintNode} node - variable declarator node
       */
      VariableDeclarator: function (node) {
        if (
          node.id.type === 'ObjectPattern' &&
          node.init.name === emberVarName &&
          node.id.properties.length !== 0
        ) {
          node.id.properties.forEach(function (property) {
            switch (property.key.name) {
              case 'computed':
                computedVarName = property.value.name
                break

              case 'set':
                setVarName = property.value.name
                break
            }
          })
        }
      }
    }
  },
  meta: {
    deprecated: false,
    docs: {
      category: 'Possible Errors',
      description: 'Prevent usage of this.set and Ember.set in computed properties',
      recommended: true
    }
  }
}
<commit_msg>Use consistent ESLint API<commit_after>/**
 * Determine if call expression is part of a computed property
 * @example `foo: Ember.computed('a', function () {})`
 * @example `foo: computed('a', function () {})`
 * @param {ESLintNode} node - call expression node
 * @param {String} computedVarName - destructured variable name for Ember.computed
 * @returns {Boolean} whether or not call expression is part of a computed property
 */
function isComputedProperty (node, computedVarName) {
  if (!node.parent || !node.parent.callee) {
    return false
  }

  var isStructuredComputedProperyCall = (
    node.parent.callee.property && node.parent.callee.property.name === 'computed'
  )

  var isUnstructuredComputedPropertyCall = node.parent.callee.name === computedVarName

  return isStructuredComputedProperyCall || isUnstructuredComputedPropertyCall
}

/**
 * Determine if call expression is part of a decorator computed property
 * @example
 *   ```
 *   @computed('bar')
 *   foo (bar) {}
 *   ```
 * @param {ESLintNode} node - call expression node
 * @param {String} computedDecoratorVarName - imported default for ember-computed-decorators
 * @returns {Boolean} whether or not call expression is part of a decorator CP
 */
function isDecoratorComputedProperty (node, computedDecoratorVarName) {
  if (!node.parent || !node.parent.decorators) {
    return false
  }

  return node.parent.decorators
    .some(function (decorator) {
      return (
        decorator.expression &&
        decorator.expression.callee &&
        decorator.expression.callee.name === computedDecoratorVarName
      )
    })
}

/**
 * Determine if current call expression is a call to Ember.set() or this.set()
 * @param {ESLintNode} node - call expression node
 * @param {String} setVarName - destructured variable name for Ember.set
 * @param {String} emberVarName - variable name for Ember import
 * @returns {Boolean} whether or not call is a set call
 */
function isSetCall (node, setVarName, emberVarName) {
  // Structured set call (i.e. `Ember.set()`` or `this.set()`)
  if (
    node.callee.property &&
    node.callee.property.name === 'set' &&
    node.callee.object &&
    (node.callee.object.type === 'ThisExpression' || node.callee.object.name === emberVarName)
  ) {
    return true
  }

  // Unstructured call (i.e. `set()`)
  return node.callee.name === setVarName
}

module.exports = {
  create: function (context) {
    var computedDecoratorVarName = null
    var computedVarName = null
    var currentComputedProperty = null
    var emberVarName = 'Ember'
    var setVarName = null

    return {
      /**
       * Determine if a set call is being made while we are within a computed
       * property
       * @param {ESLintNode} node - call expression node
       */
      CallExpression: function (node) {
        if (
          currentComputedProperty &&
          isSetCall(node, setVarName, emberVarName)
        ) {
          context.report({
            message: 'Do not call this.set() or Ember.set() in a computed property',
            node: node
          })
        }
      },

      /**
       * Determine if we are entering a computed property
       * @param {ESLintNode} node - function expression node
       */
      FunctionExpression: function (node) {
        if (
          isComputedProperty(node, computedVarName) ||
          isDecoratorComputedProperty(node, computedDecoratorVarName)
        ) {
          currentComputedProperty = node
        }
      },

      /**
       * Determine if we are leaving a computed property
       * @param {ESLintNode} node - function expression node
       */
      'FunctionExpression:exit': function (node) {
        if (node === currentComputedProperty) {
          currentComputedProperty = null
        }
      },

      /**
       * Get Ember variable name from import statement
       * @example `import Ember from 'ember'` would yield "Ember"
       * @example `import Foo from 'ember'` would yield "Foo"
       * @param {ESLintNode} node - import declaration node
       */
      ImportDeclaration: function (node) {
        switch (node.source.value) {
          case 'ember':
            emberVarName = node.specifiers[0].local.name
            break

          case 'ember-computed-decorators':
            computedDecoratorVarName = node.specifiers[0].local.name
            break
        }
      },

      /**
       * Get destructured variable names that effect this rule
       * @example `const {computed} = Ember` would use "computed" when looking
       * for computed properties whereas `const {computed: react} = Ember` would
       * use "react" instead of "computed"
       * @param {ESLintNode} node - variable declarator node
       */
      VariableDeclarator: function (node) {
        if (
          node.id.type === 'ObjectPattern' &&
          node.init.name === emberVarName &&
          node.id.properties.length !== 0
        ) {
          node.id.properties.forEach(function (property) {
            switch (property.key.name) {
              case 'computed':
                computedVarName = property.value.name
                break

              case 'set':
                setVarName = property.value.name
                break
            }
          })
        }
      }
    }
  },
  meta: {
    deprecated: false,
    docs: {
      category: 'Possible Errors',
      description: 'Prevent usage of this.set and Ember.set in computed properties',
      recommended: true
    }
  }
}
<|endoftext|>


<commit_before>// Convert users
//

'use strict';

const Promise       = require('bluebird');
const co            = require('bluebird-co').co;
const mongoose      = require('mongoose');
const progress      = require('./utils').progress;
const html_unescape = require('./utils').html_unescape;

const UNCONFIRMED = 3;
const MEMBERS     = 11;
const VIOLATORS   = 12;

module.exports = co.wrap(function* (N) {
  let usergroups = yield N.models.vbconvert.UserGroupMapping.find().lean(true);

  let mongoid = {};

  usergroups.forEach(function (usergroup) {
    mongoid[usergroup.mysql] = usergroup.mongo;
  });

  let conn = yield N.vbconvert.getConnection();

  let gi_rows = yield conn.query('SELECT value FROM setting WHERE varname = "globalignore" LIMIT 1');

  let hellbanned_ids = [];

  if (gi_rows.length) {
    hellbanned_ids = gi_rows[0].value.split(' ').map(Number);
  }

  let rows = yield conn.query(`
    SELECT userid,usergroupid,membergroupids,username,email,
           password,salt,passworddate,ipaddress,joindate,lastactivity,posts,
           field5 as firstname,field6 as lastname
    FROM user JOIN userfield USING(userid)
    ORDER BY userid ASC
  `);

  let bar = progress(' users :current/:total [:bar] :percent', rows.length);

  yield Promise.map(rows, co.wrap(function* (row) {
    bar.tick();

    if (yield N.models.users.User.findOne({ hid: row.userid }).lean(true)) {
      // user with this id is already imported
      return;
    }

    let user = new N.models.users.User();

    user._id            = new mongoose.Types.ObjectId(row.joindate);
    user.hid            = row.userid;
    user.nick           = html_unescape(row.username);
    user.email          = row.email;
    user.joined_ts      = new Date(row.joindate * 1000);
    user.joined_ip      = row.ipaddress;
    user.last_active_ts = new Date(row.lastactivity * 1000);
    user.post_count     = row.posts;
    user.first_name     = html_unescape(row.firstname);
    user.last_name      = html_unescape(row.lastname);
    user.usergroups     = [];

    if (row.usergroupid === UNCONFIRMED) {
      // Process users with unconfirmed email:
      //
      //  - there are 25 users with old ids (< 200k) with forum messages,
      //    which we're moving to "members" group
      //
      //  - the rest are users with new ids that we can just remove
      //
      if (row.userid > 200000) {
        return;
      }

      // replace this usergroup with members
      user.usergroups.push(mongoid[MEMBERS]);

    } else if (row.usergroupid === VIOLATORS) {
      // for violators: fetch old usergroup before ban, and add it as well
      user.usergroups.push(mongoid[row.usergroupid]);

      let result = yield conn.query(`
        SELECT usergroupid FROM userban WHERE userid = ?
      `, [ row.userid ]);
      let ban = (result || [])[0];

      if (ban.usergroupid && mongoid[ban.usergroupid]) {
        user.usergroups.push(mongoid[ban.usergroupid]);
      } else {
        user.usergroups.push(mongoid[MEMBERS]);
      }

    } else if (mongoid[row.usergroupid]) {
      user.usergroups.push(mongoid[row.usergroupid]);
    }

    if (row.membergroupids) {
      user.usergroups = user.usergroups.concat(row.membergroupids.split(',').map(function (id) {
        return mongoid[id];
      }).filter(Boolean));
    }

    if (user.usergroups.length === 0) {
      N.logger.warn('User has no usergroups: ' + row.userid);
    }

    if (hellbanned_ids.indexOf(row.userid) !== -1) {
      user.hb = true;
    }

    yield user.save();

    let authLink = new N.models.users.AuthLink();

    authLink.user    = user._id;
    authLink.type    = 'vb';
    authLink.email   = row.email;
    authLink.ts      = new Date(row.passworddate);
    authLink.last_ts = new Date(row.passworddate);
    authLink.ip      = row.ipaddress;
    authLink.last_ip = row.ipaddress;
    authLink._id     = new mongoose.Types.ObjectId(authLink.ts / 1000);
    authLink.meta    = {
      pass: row.password,
      salt: row.salt
    };

    yield authLink.save();
  }), { concurrency: 100 });

  bar.terminate();

  yield N.models.core.Increment.update(
          { key: 'user' },
          { $set: { value: rows[rows.length - 1].userid } },
          { upsert: true }
        );

  conn.release();
  N.logger.info('User import finished');
});
<commit_msg>Import profile fields<commit_after>// Convert users
//

'use strict';

const Promise       = require('bluebird');
const co            = require('bluebird-co').co;
const mongoose      = require('mongoose');
const progress      = require('./utils').progress;
const html_unescape = require('./utils').html_unescape;

const UNCONFIRMED = 3;
const MEMBERS     = 11;
const VIOLATORS   = 12;

module.exports = co.wrap(function* (N) {
  let usergroups = yield N.models.vbconvert.UserGroupMapping.find().lean(true);

  let mongoid = {};

  usergroups.forEach(function (usergroup) {
    mongoid[usergroup.mysql] = usergroup.mongo;
  });

  let conn = yield N.vbconvert.getConnection();

  let gi_rows = yield conn.query('SELECT value FROM setting WHERE varname = "globalignore" LIMIT 1');

  let hellbanned_ids = [];

  if (gi_rows.length) {
    hellbanned_ids = gi_rows[0].value.split(' ').map(Number);
  }

  let rows = yield conn.query(`
    SELECT userid,usergroupid,membergroupids,username,email,password,salt,
           passworddate,ipaddress,joindate,lastactivity,posts,icq,skype,
           birthday_search,field5 as firstname,field6 as lastname
    FROM user JOIN userfield USING(userid)
    ORDER BY userid ASC
  `);

  let bar = progress(' users :current/:total [:bar] :percent', rows.length);

  yield Promise.map(rows, co.wrap(function* (row) {
    bar.tick();

    if (yield N.models.users.User.findOne({ hid: row.userid }).lean(true)) {
      // user with this id is already imported
      return;
    }

    let user = new N.models.users.User();

    user._id            = new mongoose.Types.ObjectId(row.joindate);
    user.hid            = row.userid;
    user.nick           = html_unescape(row.username);
    user.email          = row.email;
    user.joined_ts      = new Date(row.joindate * 1000);
    user.joined_ip      = row.ipaddress;
    user.last_active_ts = new Date(row.lastactivity * 1000);
    user.post_count     = row.posts;
    user.first_name     = html_unescape(row.firstname);
    user.last_name      = html_unescape(row.lastname);
    user.usergroups     = [];
    user.about          = {};

    if (row.icq && Number(row.icq)) user.about.icq = row.icq;
    if (row.skype) user.about.skype = row.skype;

    if (typeof row.birthday_search === 'object' && row.birthday_search !== null) {
      user.about.birthday = row.birthday_search;
    }

    if (row.usergroupid === UNCONFIRMED) {
      // Process users with unconfirmed email:
      //
      //  - there are 25 users with old ids (< 200k) with forum messages,
      //    which we're moving to "members" group
      //
      //  - the rest are users with new ids that we can just remove
      //
      if (row.userid > 200000) {
        return;
      }

      // replace this usergroup with members
      user.usergroups.push(mongoid[MEMBERS]);

    } else if (row.usergroupid === VIOLATORS) {
      // for violators: fetch old usergroup before ban, and add it as well
      user.usergroups.push(mongoid[row.usergroupid]);

      let result = yield conn.query(`
        SELECT usergroupid FROM userban WHERE userid = ?
      `, [ row.userid ]);
      let ban = (result || [])[0];

      if (ban.usergroupid && mongoid[ban.usergroupid]) {
        user.usergroups.push(mongoid[ban.usergroupid]);
      } else {
        user.usergroups.push(mongoid[MEMBERS]);
      }

    } else if (mongoid[row.usergroupid]) {
      user.usergroups.push(mongoid[row.usergroupid]);
    }

    if (row.membergroupids) {
      user.usergroups = user.usergroups.concat(row.membergroupids.split(',').map(function (id) {
        return mongoid[id];
      }).filter(Boolean));
    }

    if (user.usergroups.length === 0) {
      N.logger.warn('User has no usergroups: ' + row.userid);
    }

    if (hellbanned_ids.indexOf(row.userid) !== -1) {
      user.hb = true;
    }

    yield user.save();

    let authLink = new N.models.users.AuthLink();

    authLink.user    = user._id;
    authLink.type    = 'vb';
    authLink.email   = row.email;
    authLink.ts      = new Date(row.passworddate);
    authLink.last_ts = new Date(row.passworddate);
    authLink.ip      = row.ipaddress;
    authLink.last_ip = row.ipaddress;
    authLink._id     = new mongoose.Types.ObjectId(authLink.ts / 1000);
    authLink.meta    = {
      pass: row.password,
      salt: row.salt
    };

    yield authLink.save();
  }), { concurrency: 100 });

  bar.terminate();

  yield N.models.core.Increment.update(
          { key: 'user' },
          { $set: { value: rows[rows.length - 1].userid } },
          { upsert: true }
        );

  conn.release();
  N.logger.info('User import finished');
});
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import Radium, { StyleRoot } from 'radium';

import Panels from './components/Panels/Panels';
import Header from './components/Header/Header';
import Footer from './components/Footer/Footer';

class App extends React.Component {

  constructor(props, context){
      super(props, context);

  }

  render() {
    return (

    );
  }
}

const styles = {
    container: {
        position: 'absolute',
        width: '100%',
        height: '100%',
        backgroundImage: 'url("https://unsplash.it/1920/1080/?image=993")',
        backgroundSize: 'cover',
        fontFamily: '"Roboto", sans-serif',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'space-between',
        overflow: 'hidden'
    }
};

export default Radium(App);
<commit_msg>remove whitespace<commit_after>import React, { PropTypes } from 'react';
import Radium, { StyleRoot } from 'radium';

import Panels from './components/Panels/Panels';
import Header from './components/Header/Header';
import Footer from './components/Footer/Footer';

class App extends React.Component {

  constructor(props, context){
      super(props, context);
  }

  render() {
    return (

    );
  }
}

const styles = {
    container: {
        position: 'absolute',
        width: '100%',
        height: '100%',
        backgroundImage: 'url("https://unsplash.it/1920/1080/?image=993")',
        backgroundSize: 'cover',
        fontFamily: '"Roboto", sans-serif',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'space-between',
        overflow: 'hidden'
    }
};

export default Radium(App);
<|endoftext|>


<commit_before>'use strict';

define(['Three', 'Detector', 'Renderer', 'DomContainer', 'Scene', 'loaders/ObjectLoader', 'loaders/GUILoader', 'loaders/ScriptsLoader', 'utils/QueryString', 'World', 'API'],
    function(THREE, detector, renderer, container, scene, objectLoader, guiLoader, scriptsLoader, queryString, world, api) {
        // TODO use same style as other objects
        var App = function() {
            this.load = function(json) {
                scene.setScene(objectLoader.parse(json.scene));
                scene.setCSS3DScene(guiLoader.parse(json));

                // Perhaps we could pass more things -- the most important thing is that later on we document which things we expose to scripts
                // We can also pass other things like renderer directly as params (such as when we pass scene) but I think it's OK to pass just scene as a distinct param
                var relevantApp = {
                    setCamera: renderer.setCamera,
                    play: world.play,
                    stop: world.stop,
                    renderer: renderer.webGL
                };

                scriptsLoader.load(json, relevantApp);
            };

            this.init = function() {
                if (!detector.webgl) {
                    detector.addGetWebGLMessage();
                    return;
                }

                var _this = this;

                var sceneId = queryString.sceneId;

                api.getScene(sceneId).then(function(json) {
                    _this.load(json);

                    world.start();

                    container.appendChild(renderer.getDomElement());
                });
            };
        };

        new App().init();
    });
<commit_msg>fixing texture not loaded issue<commit_after>'use strict';

define(['Three', 'Detector', 'Renderer', 'DomContainer', 'Scene', 'loaders/ObjectLoader', 'loaders/GUILoader', 'loaders/ScriptsLoader', 'utils/QueryString', 'World', 'API'],
    function(THREE, detector, renderer, container, scene, objectLoader, guiLoader, scriptsLoader, queryString, world, api) {
        // TODO use same style as other objects
        var App = function() {
            this.load = function(json) {
                objectLoader.parse(json.scene, function(object) {
                    scene.setScene(object);
                    scene.setCSS3DScene(guiLoader.parse(json));

                    // Perhaps we could pass more things -- the most important thing is that later on we document which things we expose to scripts
                    // We can also pass other things like renderer directly as params (such as when we pass scene) but I think it's OK to pass just scene as a distinct param
                    var relevantApp = {
                        setCamera: renderer.setCamera,
                        play: world.play,
                        stop: world.stop,
                        renderer: renderer.webGL
                    };

                    scriptsLoader.load(json, relevantApp);

                    world.start();

                    container.appendChild(renderer.getDomElement());
                });
            };

            this.init = function() {
                if (!detector.webgl) {
                    detector.addGetWebGLMessage();
                    return;
                }

                var _this = this;

                var sceneId = queryString.sceneId;

                api.getScene(sceneId).then(function(json) {
                    _this.load(json);
                });
            };
        };

        new App().init();
    });
<|endoftext|>


<commit_before>

//Provides: caml_CamlinternalMod_init_mod
//Requires: caml_raise_with_arg, caml_global_data
function caml_CamlinternalMod_init_mod(loc,shape) {
    function undef_module (_x) {
      caml_raise_with_arg(caml_global_data[12], loc);
    }
    function loop (shape,struct,idx){
        switch(shape){
        case 0://function
            struct[idx]={fun:undef_module};
            break;
        case 1://lazy
            struct[idx]=[246, undef_module];
            break;
        case 2://class
            struct[idx]=[];
            break;
        default://module
            struct[idx] = [0];
            for(var i=1;i<shape[1].length;i++)
                loop(shape[1][i],struct[idx],i)
        }
    }
    var res = [];
    loop(shape,res,0);
    return res[0]
}
//Provides: caml_CamlinternalMod_update_mod
//Requires: caml_update_dummy
function caml_CamlinternalMod_update_mod(shape,real,x) {
  switch(shape){
  case 0://function
    real.fun = x;
    break;
  case 1://lazy
  case 2://class
    caml_update_dummy(real,x);
    break;
  default://module
    for(var i=1;i<shape[1].length;i++)
      caml_CamlinternalMod_update_mod(shape[1][i],real[i],x[i])
  };
  return 0
}
<commit_msg>Runtime: update internalMod.js<commit_after>

//Provides: caml_CamlinternalMod_init_mod
//Requires: caml_raise_with_arg, caml_global_data
function caml_CamlinternalMod_init_mod(loc,shape) {
  function undef_module (_x) {
    caml_raise_with_arg(caml_global_data[12], loc);
  }
  function loop (shape,struct,idx){
    if(typeof shape === "number")
      switch(shape){
      case 0://function
        struct[idx]={fun:undef_module};
        break;
      case 1://lazy
        struct[idx]=[246, undef_module];
        break;
      default://case 2://class
        struct[idx]=[];
      }
    else
      switch(shape[0]){
      case 0://module
        struct[idx] = [0];
        for(var i=1;i<shape[1].length;i++)
          loop(shape[1][i],struct[idx],i);
        break;
      default://case 1://Value
        struct[idx] = shape[1];
      }
  }
  var res = [];
  loop(shape,res,0);
  return res[0]
}
//Provides: caml_CamlinternalMod_update_mod
//Requires: caml_update_dummy
function caml_CamlinternalMod_update_mod(shape,real,x) {
  if(typeof shape === "number")
    switch(shape){
    case 0://function
      real.fun = x;
      break;
    case 1://lazy
    case 2://class
      caml_update_dummy(real,x);
    }
  else
    switch(shape[0]){
    case 0://module
      for(var i=1;i<shape[1].length;i++)
        caml_CamlinternalMod_update_mod(shape[1][i],real[i],x[i]);
      break;
    //case 1://Value
    default:
      caml_update_dummy(real,x);
    };
  return 0
}
<|endoftext|>


<commit_before>/**
 * document.ready currently sponsored by snipplr.com :)
 * @copyright http://snipplr.com/view/6156/documentready/
 */
(function () {
    var ie = !!(window.attachEvent && !window.opera);
    var wk = /webkit\/(\d+)/i.test(navigator.userAgent) && (RegExp.$1 < 525);
    var fn = [];
    var run = function () {
        for (var i = 0; i < fn.length; i++) fn[i]();
    };
    var d = document;
    d.ready = function (f) {
        if (!ie && !wk && d.addEventListener)
            return d.addEventListener('DOMContentLoaded', f, false);
        if (fn.push(f) > 1) return;
        if (ie)
            (function () {
                try {
                    d.documentElement.doScroll('left');
                    run();
                }
                catch (err) {
                    setTimeout(arguments.callee, 0);
                }
            })();
        else if (wk)
            var t = setInterval(function () {
                if (/^(loaded|complete)$/.test(d.readyState))
                    clearInterval(t),run();
            }, 0);
    };
})();

//@TODO implement own ready-method

/**
 * just for testing-purpose
 */
DEBUG_LEVEL = true;
debug = function(arg) {
    if (DEBUG_LEVEL && console != undefined)
        console.info(arg);
};

/**
 * Cyricles
 *
 * @license see LICENSE file
 * @copyright Florian Purchess <florian@purchess.de>
 *
 * ####################################################################################
 */

/**
 * Initalize a new Cyricles-Object
 * @param canvas
 * @param options
 */
Cyricles = function (canvas, options) {
    var type = typeof(canvas);

    if (type == "string")
        this.canvas = document.getElementById(canvas);
    else if (type == "object")
        this.canvas = canvas;
    else
        return null;

    this.ctx = this.canvas.getContext("2d");

    // set up options
    this.options = Cyricles.extend({
            renderInterval : 20,
            background : 'transparent',
            width : 800,
            height : 600
        }, options);

    // init object-stack
    this.items = new Array();

    this.renderingInterval = null;
};

Cyricles.extend = function(defaults, options) {
    //@TODO Secure extending + extending of Cyricles
    if (options == undefined) return defaults;

    for(var i in defaults) {
        if (options[i] == undefined)
            options[i] = defaults[i];
    }

    return options;
};

Cyricles.prototype.loadImages = function(images, callback) {
    var load = images.length; // amount of load images

    for(var i=0; i < images.length; i++) {
        var img = new Image();
        img.onload = img.onabort = img.onerror = function() {load--;};
        img.src = images[i];
        images[i] = img;
    }

    var t = setInterval(function() {
        if (!load) {
            clearInterval(t);
            if (typeof(callback) == "function")
                callback(images);
        }
    }, 0);

    return images;
};

/**
 * clear the canvas
 */
Cyricles.prototype.clearScreen = function() {
    this.canvas.width = this.canvas.width;
    if (this.options.background == 'transparent') return;

    this.ctx.save();
    this.ctx.fillStyle = this.options.background;
    this.ctx.fillRect(0,0,this.canvas.width, this.canvas.height);
    this.ctx.restore();
};

/**
 * render the current rendering-stack
 * @param that
 */
Cyricles.prototype.render = function(that) {
    //@TODO find a better solution than passing "this"-context
    that.clearScreen();

    for (var i=0; i < that.items.length; i++) {
        if (typeof(that.items[i]) == "function")
            that.items[i](that);
        else
            that.items[i].draw(this.ctx);
    }
};

/**
 * start rendering-interval
 */
Cyricles.prototype.startRender = function(){
    if (this.isRendering()) return false;

    this.render(this);
    this.renderingInterval = setInterval(function(that){that.render(that)}, this.options.renderInterval, this);

    return true;
};

/**
 * stop rendering-interval
 */
Cyricles.prototype.stopRender = function(){
    if (!this.isRendering()) return false;

    clearInterval(this.renderingInterval);
    this.renderingInterval = null;

    return true;
};

/**
 * return current rendering-status
 */
Cyricles.prototype.isRendering = function(){
    return this.renderingInterval !== null;
};

/**
 * Add an item to the rendering-stack
 * @param item
 */
Cyricles.prototype.addItem = function(item) {
    this.items.push(item);
};

//@TODO Add some rendering-stack manipulation methods

/**
 * CyObject
 * ####################################################################################
 */

/**
 * Initalize a CyObject
 * @param type
 */
CyObject = function(type) {
    this.type = type;
};

/**
 * Set drawing-attributes
 * @param ctx
 */
CyObject.prototype.setDrawingAttributes = function(ctx){
    for (var name in this.options)
        ctx[name] = this.options[name];

};

/**
 * Retrieve all options that will be animated
 * @param user
 * @param options
 */
CyObject.prototype.getAnimatables = function(user, options) {
    var animatables = {}, key;

    if (options == undefined)
        options = this.options;

    for(key in user) {
        if (options[key] != undefined) {
            if (typeof(user[key]) == "object")
                animatables[key] = this.getAnimatables(user[key], options[key]);
            else
                animatables[key] = user[key];
        }
    }

    return animatables;
};

/**
 * Get the increase-value <addifier> for every <animatable> in relation to <duration> / <steps>
 * @param animatable
 * @param duration
 * @param steps
 * @param options
 */
CyObject.prototype.getAddifiers = function(animatable, duration, steps, options) {
    var addifiers = {}, key;

    if (options == undefined)
        options = this.options;

    for(key in animatable) {
        if (options[key] != undefined) {
            if (typeof(animatable[key]) == "object")
                addifiers[key] = this.getAddifiers(animatable[key], duration, steps, options[key]);
            else if (typeof(animatable[key]) == "number") {
                addifiers[key] = (animatable[key] - options[key]) / (duration / steps);
            }
        }
    }

    return addifiers;
};

/**
 * Add the values of <addifiers> to the values of <options>
 * @param addifiers
 * @param options
 */
CyObject.prototype.addOptionValues = function(addifiers, options) {
    var key;

    if (options == undefined)
        options = this.options;

    for(key in addifiers) {
        if (options[key] != undefined) {
            if (typeof(addifiers[key]) == "object")
                addifiers[key] = this.addOptionValues(addifiers[key], options[key]);
            else if (typeof(addifiers[key]) == "number")
                options[key] += addifiers[key];
        }
    }

    return options;
};

/**
 * Executes a function <fn> for <duration> (in <steps> ms), passing <parameters>, executing callback at the end
 * @param fn
 * @param duration
 * @param steps
 * @param parameters
 * @param callback
 */
CyObject.prototype.timer = function(fn, duration, steps, parameters, callback) {
    if (duration < steps)
        throw("timer duration < steps!");

    var i = setInterval(function(fn, parameters){
        fn(parameters);

        if ((duration -= steps) <= 0)
            clearInterval(i),callback();
    }, steps, fn, parameters);

};

/**
 * Animates CyObject's options until values of <options> over duration, calling <callback> at the end
 * @param options
 * @param duration
 * @param callback
 */
CyObject.prototype.animate = function(options, duration, callback) {
    var animatables = this.getAnimatables(options);
    var addifiers = this.getAddifiers(animatables, duration, 1);

    this.timer(function(that){
        that.options = that.addOptionValues(addifiers);
    }, duration, 1, this, callback);
};

/**
 * CyTransform
 * ####################################################################################
 */

/**
 * Initalize a transformation-object
 * @param options
 */
CyTransformation = function(options) {
    this.options = Cyricles.extend({scale:[1,1], rotate:0, translate:[0,0], transform:[0, 0, 0, 0, 0, 0]}, options);
};

/**
 * Inheritance of CyObject
 */
CyTransformation.prototype = new CyObject("CyTransformation");
CyTransformation.prototype.constructor = CyTransformation;

/**
 * apply a scale to a context
 * @param ctx
 */
CyTransformation.prototype.draw = function(ctx) {
    ctx.scale(this.options.scale[0],this.options.scale[1]);
    ctx.rotate(this.options.rotate);
    ctx.translate(this.options.translate[0], this.options.translate[1]);
//    ctx.transform(this.options.transform[0], this.options.transform[1], this.options.transform[2],
//            this.options.transform[3], this.options.transform[4], this.options.transform[5]);
};

/**
 * CyRect
 * ####################################################################################
 */

/**
 * Initalize a new Cyricles-Rectangle
 *
 * @param x
 * @param y
 * @param width
 * @param height
 * @param options
 */
CyRect = function(x, y, width, height, options) {
    CyObject.call(this, "CyRect");
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.options = Cyricles.extend({strokeStyle: false, fillStyle: false}, options);
};

/**
 * Inheritance of CyObject
 */
CyRect.prototype = new CyObject("CyRect");
CyRect.prototype.constructor = CyRect;

/**
 * draw rectangle on the canvas-context
 * @param ctx
 */
CyRect.prototype.draw = function(ctx){
    ctx.save();

    this.setDrawingAttributes(ctx);

    if (this.options.fillStyle !== false)
        ctx.fillRect(this.x, this.y, this.width, this.height);

    if (this.options.strokeStyle !== false)
        ctx.strokeRect(this.x, this.y, this.width, this.height);

    ctx.restore();
};

//@TODO implement rectangle-animations
//@TODO implement animation-algorithm for colors

/**
 * CyText
 * ####################################################################################
 */

/**
 * Initalize a new CyText-Object
 * @param text
 * @param x
 * @param y
 * @param options
 */
CyText = function(text, x, y, options) {
    this.text = text;
    this.x = x;
    this.y = y;
    this.options = Cyricles.extend({font: "10px Arial", textAlign: "start", fillStyle: "#000"}, options);
};

/**
 * Inheritance of CyObject
 */
CyText.prototype = new CyObject("CyText");
CyText.prototype.constructor = CyText;

/**
 * draw text on the canvas-context
 * @param ctx
 */
CyText.prototype.draw = function(ctx){
    ctx.save();

    this.setDrawingAttributes(ctx);
    ctx.fillText(this.text, this.x, this.y);

    ctx.restore();
};

//@TODO implement text-animations

//@TODO implement some gradient-handling<commit_msg>implemented rendering-stack manipulations<commit_after>/**
 * document.ready currently sponsored by snipplr.com :)
 * @copyright http://snipplr.com/view/6156/documentready/
 */
(function () {
    var ie = !!(window.attachEvent && !window.opera);
    var wk = /webkit\/(\d+)/i.test(navigator.userAgent) && (RegExp.$1 < 525);
    var fn = [];
    var run = function () {
        for (var i = 0; i < fn.length; i++) fn[i]();
    };
    var d = document;
    d.ready = function (f) {
        if (!ie && !wk && d.addEventListener)
            return d.addEventListener('DOMContentLoaded', f, false);
        if (fn.push(f) > 1) return;
        if (ie)
            (function () {
                try {
                    d.documentElement.doScroll('left');
                    run();
                }
                catch (err) {
                    setTimeout(arguments.callee, 0);
                }
            })();
        else if (wk)
            var t = setInterval(function () {
                if (/^(loaded|complete)$/.test(d.readyState))
                    clearInterval(t),run();
            }, 0);
    };
})();

//@TODO implement own ready-method

/**
 * just for testing-purpose
 */
DEBUG_LEVEL = true;
debug = function(arg) {
    if (DEBUG_LEVEL && console != undefined)
        console.info(arg);
};

/**
 * Cyricles
 *
 * @license see LICENSE file
 * @copyright Florian Purchess <florian@purchess.de>
 *
 * ####################################################################################
 */

/**
 * Initalize a new Cyricles-Object
 * @param canvas
 * @param options
 */
Cyricles = function (canvas, options) {
    var type = typeof(canvas);

    if (type == "string")
        this.canvas = document.getElementById(canvas);
    else if (type == "object")
        this.canvas = canvas;
    else
        return null;

    this.ctx = this.canvas.getContext("2d");

    // set up options
    this.options = Cyricles.extend({
            renderInterval : 20,
            background : 'transparent',
            width : 800,
            height : 600
        }, options);

    // init object-stack
    this.items = new Array();

    this.renderingInterval = null;
};

Cyricles.extend = function(defaults, options) {
    //@TODO Secure extending + extending of Cyricles
    if (options == undefined) return defaults;

    for(var i in defaults) {
        if (options[i] == undefined)
            options[i] = defaults[i];
    }

    return options;
};

Cyricles.prototype.loadImages = function(images, callback) {
    var load = images.length; // amount of load images

    for(var i=0; i < images.length; i++) {
        var img = new Image();
        img.onload = img.onabort = img.onerror = function() {load--;};
        img.src = images[i];
        images[i] = img;
    }

    var t = setInterval(function() {
        if (!load) {
            clearInterval(t);
            if (typeof(callback) == "function")
                callback(images);
        }
    }, 0);

    return images;
};

/**
 * clear the canvas
 */
Cyricles.prototype.clearScreen = function() {
    this.canvas.width = this.canvas.width;
    if (this.options.background == 'transparent') return;

    this.ctx.save();
    this.ctx.fillStyle = this.options.background;
    this.ctx.fillRect(0,0,this.canvas.width, this.canvas.height);
    this.ctx.restore();
};

/**
 * render the current rendering-stack
 * @param that
 */
Cyricles.prototype.render = function(that) {
    //@TODO find a better solution than passing "this"-context
    that.clearScreen();

    for (var i=0; i < that.items.length; i++) {
        if (typeof(that.items[i]) == "function")
            that.items[i](that);
        else
            that.items[i].draw(this.ctx);
    }
};

/**
 * start rendering-interval
 */
Cyricles.prototype.startRender = function(){
    if (this.isRendering()) return false;

    this.render(this);
    this.renderingInterval = setInterval(function(that){that.render(that)}, this.options.renderInterval, this);

    return true;
};

/**
 * stop rendering-interval
 */
Cyricles.prototype.stopRender = function(){
    if (!this.isRendering()) return false;

    clearInterval(this.renderingInterval);
    this.renderingInterval = null;

    return true;
};

/**
 * return current rendering-status
 */
Cyricles.prototype.isRendering = function(){
    return this.renderingInterval !== null;
};

/**
 * Add an item to the rendering-stack
 * @param item
 */
Cyricles.prototype.addItem = function(item) {
    this.items.push(item);
};

/**
 * Add an item to the rendering-stack at position <index>
 * @param item
 * @param index
 */
Cyricles.prototype.addItemAt = function(item, index) {
    if (index == 0) {
        this.items.unshift(item);
    } else if (index == this.items.length) {
        this.items.push(item);
    } else {
        var tmp1 = this.items.slice(0, index),
            tmp2 = this.items.slice(index, this.items.length);
        tmp1.push(item);
        this.items = tmp1.concat(tmp2);
    }

};

/**
 * Remove an item off the rendering-stack
 * @param item
 * @param index
 */
Cyricles.prototype.removeItem = function(item, index) {
    if (index == undefined)
        this.items.pop();
    else
        delete this.items[index];
};

//@TODO Add some rendering-stack manipulation methods

/**
 * CyObject
 * ####################################################################################
 */

/**
 * Initalize a CyObject
 * @param type
 */
CyObject = function(type) {
    this.type = type;
};

/**
 * Set drawing-attributes
 * @param ctx
 */
CyObject.prototype.setDrawingAttributes = function(ctx){
    for (var name in this.options)
        ctx[name] = this.options[name];

};

/**
 * Retrieve all options that will be animated
 * @param user
 * @param options
 */
CyObject.prototype.getAnimatables = function(user, options) {
    var animatables = {}, key;

    if (options == undefined)
        options = this.options;

    for(key in user) {
        if (options[key] != undefined) {
            if (typeof(user[key]) == "object")
                animatables[key] = this.getAnimatables(user[key], options[key]);
            else
                animatables[key] = user[key];
        }
    }

    return animatables;
};

/**
 * Get the increase-value <addifier> for every <animatable> in relation to <duration> / <steps>
 * @param animatable
 * @param duration
 * @param steps
 * @param options
 */
CyObject.prototype.getAddifiers = function(animatable, duration, steps, options) {
    var addifiers = {}, key;

    if (options == undefined)
        options = this.options;

    for(key in animatable) {
        if (options[key] != undefined) {
            if (typeof(animatable[key]) == "object")
                addifiers[key] = this.getAddifiers(animatable[key], duration, steps, options[key]);
            else if (typeof(animatable[key]) == "number") {
                addifiers[key] = (animatable[key] - options[key]) / (duration / steps);
            }
        }
    }

    return addifiers;
};

/**
 * Add the values of <addifiers> to the values of <options>
 * @param addifiers
 * @param options
 */
CyObject.prototype.addOptionValues = function(addifiers, options) {
    var key;

    if (options == undefined)
        options = this.options;

    for(key in addifiers) {
        if (options[key] != undefined) {
            if (typeof(addifiers[key]) == "object")
                addifiers[key] = this.addOptionValues(addifiers[key], options[key]);
            else if (typeof(addifiers[key]) == "number")
                options[key] += addifiers[key];
        }
    }

    return options;
};

/**
 * Executes a function <fn> for <duration> (in <steps> ms), passing <parameters>, executing callback at the end
 * @param fn
 * @param duration
 * @param steps
 * @param parameters
 * @param callback
 */
CyObject.prototype.timer = function(fn, duration, steps, parameters, callback) {
    if (duration < steps)
        throw("timer duration < steps!");

    var i = setInterval(function(fn, parameters){
        fn(parameters);

        if ((duration -= steps) <= 0)
            clearInterval(i),callback();
    }, steps, fn, parameters);

};

/**
 * Animates CyObject's options until values of <options> over duration, calling <callback> at the end
 * @param options
 * @param duration
 * @param callback
 */
CyObject.prototype.animate = function(options, duration, callback) {
    var animatables = this.getAnimatables(options);
    var addifiers = this.getAddifiers(animatables, duration, 1);

    this.timer(function(that){
        that.options = that.addOptionValues(addifiers);
    }, duration, 1, this, callback);
};

/**
 * CyTransform
 * ####################################################################################
 */

/**
 * Initalize a transformation-object
 * @param options
 */
CyTransformation = function(options) {
    this.options = Cyricles.extend({scale:[1,1], rotate:0, translate:[0,0], transform:[0, 0, 0, 0, 0, 0]}, options);
};

/**
 * Inheritance of CyObject
 */
CyTransformation.prototype = new CyObject("CyTransformation");
CyTransformation.prototype.constructor = CyTransformation;

/**
 * apply a scale to a context
 * @param ctx
 */
CyTransformation.prototype.draw = function(ctx) {
    ctx.scale(this.options.scale[0],this.options.scale[1]);
    ctx.rotate(this.options.rotate);
    ctx.translate(this.options.translate[0], this.options.translate[1]);
//    ctx.transform(this.options.transform[0], this.options.transform[1], this.options.transform[2],
//            this.options.transform[3], this.options.transform[4], this.options.transform[5]);
};

/**
 * CyRect
 * ####################################################################################
 */

/**
 * Initalize a new Cyricles-Rectangle
 *
 * @param x
 * @param y
 * @param width
 * @param height
 * @param options
 */
CyRect = function(x, y, width, height, options) {
    CyObject.call(this, "CyRect");
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.options = Cyricles.extend({strokeStyle: false, fillStyle: false}, options);
};

/**
 * Inheritance of CyObject
 */
CyRect.prototype = new CyObject("CyRect");
CyRect.prototype.constructor = CyRect;

/**
 * draw rectangle on the canvas-context
 * @param ctx
 */
CyRect.prototype.draw = function(ctx){
    ctx.save();

    this.setDrawingAttributes(ctx);

    if (this.options.fillStyle !== false)
        ctx.fillRect(this.x, this.y, this.width, this.height);

    if (this.options.strokeStyle !== false)
        ctx.strokeRect(this.x, this.y, this.width, this.height);

    ctx.restore();
};

//@TODO implement rectangle-animations
//@TODO implement animation-algorithm for colors

/**
 * CyText
 * ####################################################################################
 */

/**
 * Initalize a new CyText-Object
 * @param text
 * @param x
 * @param y
 * @param options
 */
CyText = function(text, x, y, options) {
    this.text = text;
    this.x = x;
    this.y = y;
    this.options = Cyricles.extend({font: "10px Arial", textAlign: "start", fillStyle: "#000"}, options);
};

/**
 * Inheritance of CyObject
 */
CyText.prototype = new CyObject("CyText");
CyText.prototype.constructor = CyText;

/**
 * draw text on the canvas-context
 * @param ctx
 */
CyText.prototype.draw = function(ctx){
    ctx.save();

    this.setDrawingAttributes(ctx);
    ctx.fillText(this.text, this.x, this.y);

    ctx.restore();
};

//@TODO implement text-animations

//@TODO implement some gradient-handling<|endoftext|>


<commit_before>require(['lib/knockout', 'Connector', 'Brain', 'History', 'Messenger', 'MergeConstant', 'HistoryConstant',
    'NotificationConstant', 'ConfigViewModel', 'DynamicViewModel', 'utils/getValues', 'utils/parseUrlParams',
    'utils/orIfUndefined', 'UrlJuggler', 'lib/domReady'], function (ko, Connector, Brain, History, Messenger, MergeConstant, HistoryConstant, NotificationConstant, ConfigViewModel, DynamicViewModel, getValues, parseUrlParams, orIfUndefined, UrlJuggler) {

    var INPUT_PREFIX = 'input';
    var INPUT_DISABLED_POSTFIX = 'Disabled';
    var INPUT_SELECTED_POSTFIX = 'Selected';

    var URL = location.origin;

    var connector = new Connector();
    var brain = new Brain();
    var history = new History();
    var messenger = new Messenger();
    var urlJuggler = new UrlJuggler(location.pathname, window.history.pushState.bind(window.history));
    var urlParams = parseUrlParams(location.search);

    var configView = new ConfigViewModel(getValues(MergeConstant), getValues(HistoryConstant),
        getValues(NotificationConstant),
        urlParams['merge'], urlParams['history'], urlParams['notification'], urlParams['user']);

    var mergeStrategy = orIfUndefined.call(urlParams['merge'], MergeConstant.PLAIN);
    var historyStrategy = orIfUndefined.call(urlParams['history'], HistoryConstant.BY_TIME);
    var notificationStrategy = orIfUndefined.call(urlParams['notification'], NotificationConstant.BUBBLE);

    var userName = urlParams['user'];

    var inputIds = [];
    var inputs = document.querySelectorAll('input[id*=' + INPUT_PREFIX + ']');
    for (var i = 0; i < inputs.length; i++) {
        inputIds.push(inputs[i].id);
    }

    var view = new DynamicViewModel(INPUT_DISABLED_POSTFIX, INPUT_SELECTED_POSTFIX, inputIds);

    ko.applyBindings(configView, document.getElementById('config'));
    ko.applyBindings(view, document.getElementById('mainView'));

    var mergeSubscription = configView.merge.subscribe(function (newVal) {
        console.log('merge update: ' + newVal);

        urlParams['merge'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var historySubscription = configView.history.subscribe(function (newVal) {
        console.log('history update: ' + newVal);

        urlParams['history'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var notificationSubscription = configView.notification.subscribe(function (newVal) {
        console.log('notify update: ' + newVal);

        urlParams['notification'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var userSubscription = configView.user.subscribe(function (newVal) {
        console.log('user update: ' + newVal);

        urlParams['user'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var isInputVar = function (key) {
        return key.toUpperCase().indexOf(INPUT_PREFIX.toUpperCase()) !== -1 &&
            key.toUpperCase().indexOf(INPUT_DISABLED_POSTFIX.toUpperCase()) === -1 &&
            key.toUpperCase().indexOf(INPUT_SELECTED_POSTFIX.toUpperCase()) === -1
    };

    var isSelectVar = function (key) {
        return key.toUpperCase().indexOf(INPUT_PREFIX.toUpperCase()) !== -1 &&
            key.toUpperCase().indexOf(INPUT_DISABLED_POSTFIX.toUpperCase()) === -1 &&
            key.toUpperCase().indexOf(INPUT_SELECTED_POSTFIX.toUpperCase()) !== -1;
    };

    var subscriptionDict = {};
    Object.getOwnPropertyNames(view).forEach(function (key) {

        if (isInputVar(key)) {

            subscriptionDict[key] = view[key].subscribe(function (newVal) {

                console.log('update from: ' + key + ' with value: ' + newVal);

                var data = {
                    client: brain.clientId,
                    field: key,
                    value: newVal
                };

//                history.add(data);
                connector.send(data);

            });

        } else if (isSelectVar(key)) {
            subscriptionDict[key] = view[key].subscribe(function (newVal) {

                console.log('update from: ' + key + ' with value: ' + newVal);

                var data = {
                    client: brain.clientId,
                    field: key.slice(0, - INPUT_SELECTED_POSTFIX.length)
                };

                if (newVal) {
                    connector.lock(data);
                } else {
                    connector.unlock(data);
                }
            });
        }
    });

    connector.connect(URL);

    connector.socket.on('info', function (data) {
        console.log('new socket info with data: ' + data);

        brain.register(data);
    });

    connector.socket.on('update', function (data) {
        console.log('new socket update with data: ' + data);

//        history.add(data);

        view.update(data.field, data.value);
    });

    connector.socket.on('unlock', function (data) {
        view.unlock(data.field);
    });

    connector.socket.on('lock', function (data) {
        view.lock(data.field);
    });

});<commit_msg>switch between lock and plain merge mode<commit_after>require(['lib/knockout', 'Connector', 'Brain', 'History', 'Messenger', 'MergeConstant', 'HistoryConstant',
    'NotificationConstant', 'ConfigViewModel', 'DynamicViewModel', 'utils/getValues', 'utils/parseUrlParams',
    'utils/orIfUndefined', 'UrlJuggler', 'lib/domReady'], function (ko, Connector, Brain, History, Messenger, MergeConstant, HistoryConstant, NotificationConstant, ConfigViewModel, DynamicViewModel, getValues, parseUrlParams, orIfUndefined, UrlJuggler) {

    var INPUT_PREFIX = 'input';
    var INPUT_DISABLED_POSTFIX = 'Disabled';
    var INPUT_SELECTED_POSTFIX = 'Selected';

    var URL = location.origin;

    var connector = new Connector();
    var brain = new Brain();
    var history = new History();
    var messenger = new Messenger();
    var urlJuggler = new UrlJuggler(location.pathname, window.history.pushState.bind(window.history));
    var urlParams = parseUrlParams(location.search);

    var configView = new ConfigViewModel(getValues(MergeConstant), getValues(HistoryConstant),
        getValues(NotificationConstant),
        urlParams['merge'], urlParams['history'], urlParams['notification'], urlParams['user']);

    var mergeStrategy = orIfUndefined.call(urlParams['merge'], MergeConstant.PLAIN);
    var historyStrategy = orIfUndefined.call(urlParams['history'], HistoryConstant.BY_TIME);
    var notificationStrategy = orIfUndefined.call(urlParams['notification'], NotificationConstant.BUBBLE);

    var userName = urlParams['user'];

    var inputIds = [];
    var inputs = document.querySelectorAll('input[id*=' + INPUT_PREFIX + ']');
    for (var i = 0; i < inputs.length; i++) {
        inputIds.push(inputs[i].id);
    }

    var view = new DynamicViewModel(INPUT_DISABLED_POSTFIX, INPUT_SELECTED_POSTFIX, inputIds);

    ko.applyBindings(configView, document.getElementById('config'));
    ko.applyBindings(view, document.getElementById('mainView'));

    var mergeSubscription = configView.merge.subscribe(function (newVal) {
        console.log('merge update: ' + newVal);

        urlParams['merge'] = newVal;
        urlJuggler.updateParams(urlParams);
        mergeStrategy = newVal;
    });

    var historySubscription = configView.history.subscribe(function (newVal) {
        console.log('history update: ' + newVal);

        urlParams['history'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var notificationSubscription = configView.notification.subscribe(function (newVal) {
        console.log('notify update: ' + newVal);

        urlParams['notification'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var userSubscription = configView.user.subscribe(function (newVal) {
        console.log('user update: ' + newVal);

        urlParams['user'] = newVal;
        urlJuggler.updateParams(urlParams);
    });

    var isInputVar = function (key) {
        return key.toUpperCase().indexOf(INPUT_PREFIX.toUpperCase()) !== -1 &&
            key.toUpperCase().indexOf(INPUT_DISABLED_POSTFIX.toUpperCase()) === -1 &&
            key.toUpperCase().indexOf(INPUT_SELECTED_POSTFIX.toUpperCase()) === -1
    };

    var isSelectVar = function (key) {
        return key.toUpperCase().indexOf(INPUT_PREFIX.toUpperCase()) !== -1 &&
            key.toUpperCase().indexOf(INPUT_DISABLED_POSTFIX.toUpperCase()) === -1 &&
            key.toUpperCase().indexOf(INPUT_SELECTED_POSTFIX.toUpperCase()) !== -1;
    };

    var subscriptionDict = {};
    Object.getOwnPropertyNames(view).forEach(function (key) {

        if (isInputVar(key)) {

            subscriptionDict[key] = view[key].subscribe(function (newVal) {

                console.log('update from: ' + key + ' with value: ' + newVal);

                var data = {
                    client: brain.clientId,
                    field: key,
                    value: newVal
                };

                history.add(data);
                connector.send(data);

            });

        } else if (isSelectVar(key)) {
            subscriptionDict[key] = view[key].subscribe(function (newVal) {

                console.log('update from: ' + key + ' with value: ' + newVal);

                if (mergeStrategy === MergeConstant.LOCK) {

                    var data = {
                        client: brain.clientId,
                        field: key.slice(0, -INPUT_SELECTED_POSTFIX.length)
                    };

                    if (newVal) {
                        connector.lock(data);
                    } else {
                        connector.unlock(data);
                    }
                }
            });
        }
    });

    connector.connect(URL);

    connector.socket.on('info', function (data) {
        console.log('new socket info with data: ' + data);

        brain.register(data);
    });

    connector.socket.on('update', function (data) {
        console.log('new socket update with data: ' + data);

        history.add(data);
        view.update(data.field, data.value);
    });

    connector.socket.on('unlock', function (data) {
        view.unlock(data.field);
    });

    connector.socket.on('lock', function (data) {
        view.lock(data.field);
    });

});<|endoftext|>