<commit_before>//Copyright 2012 Telefonica Investigación y Desarrollo, S.A.U
//
//This file is part of RUSH.
//
//  RUSH is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//  RUSH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License along with RUSH
//  . If not, seehttp://www.gnu.org/licenses/.
//
//For those usages not covered by the GNU Affero General Public License please contact with::dtc_support@tid.es

/**
 * Level for logger
 * debug
 * warning
 * error
 *
 * @type {String}
 */
exports.logger = {};
exports.logger.logLevel = 'debug';
exports.logger.inspectDepth = 1 ;
exports.logger.Console = {
    level: 'debug', timestamp:true
};
exports.logger.File ={
    level:'debug', filename:'pditclogger.log', timestamp:true, json:false ,
    maxsize: 1024*1024,
    maxFiles: 3
};

// redis host
exports.queue= {};
exports.queue.redis_host = 'localhost';

exports.dbrelayer = {};
exports.dbrelayer.key_prefix = 'wrH:';
exports.dbrelayer.redis_host = 'localhost';
exports.expire_time = 60*60;

exports.consumer_id = "consumerA:";

exports.ev_lsnr = {};
exports.ev_lsnr.mongo_host = "localhost";
exports.ev_lsnr.mongo_port = 27017;
exports.ev_lsnr.mongo_db =  'rush';
exports.ev_lsnr.collectionState= 'RushState';
exports.ev_lsnr.collectionError= 'RushError';

exports.listener = {};
exports.listener.port = 3001;
exports.listener.evModules = ['./ev_lsnr'];

exports.consumer = {};
exports.consumer.evModules = ['./ev_lsnr', './ev_callback', './ev_persistence'];
exports.consumer.max_poppers = 500;
// agent: undefined -> globalAgent | false -> no agent
exports.consumer.agent = undefined;
exports.consumer.max_sockets = 10;

<commit_msg>generic ev listener loaded at startup<commit_after>//Copyright 2012 Telefonica Investigación y Desarrollo, S.A.U
//
//This file is part of RUSH.
//
//  RUSH is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//  RUSH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License along with RUSH
//  . If not, seehttp://www.gnu.org/licenses/.
//
//For those usages not covered by the GNU Affero General Public License please contact with::dtc_support@tid.es

/**
 * Level for logger
 * debug
 * warning
 * error
 *
 * @type {String}
 */
exports.logger = {};
exports.logger.logLevel = 'debug';
exports.logger.inspectDepth = 1 ;
exports.logger.Console = {
    level: 'debug', timestamp:true
};
exports.logger.File ={
    level:'debug', filename:'pditclogger.log', timestamp:true, json:false ,
    maxsize: 1024*1024,
    maxFiles: 3
};

// redis host
exports.queue= {};
exports.queue.redis_host = 'localhost';

exports.dbrelayer = {};
exports.dbrelayer.key_prefix = 'wrH:';
exports.dbrelayer.redis_host = 'localhost';
exports.expire_time = 60*60;

exports.consumer_id = "consumerA:";

exports.ev_lsnr = {};
exports.ev_lsnr.mongo_host = "localhost";
exports.ev_lsnr.mongo_port = 27017;
exports.ev_lsnr.mongo_db =  'rush';
exports.ev_lsnr.collectionState= 'RushState';
exports.ev_lsnr.collectionError= 'RushError';

exports.listener = {};
exports.listener.port = 3001;
exports.listener.evModules = ['./ev_lsnr'];

exports.consumer = {};
exports.consumer.evModules = ['./ev_lsnr', './ev_callback', './ev_persistence','./gevlsnr'];

exports.consumer.max_poppers = 500;
// agent: undefined -> globalAgent | false -> no agent
exports.consumer.agent = undefined;
exports.consumer.max_sockets = 10;

<|endoftext|>


<commit_before>import Control from './control.js';
import mustache from 'mustache';
import cadPng from '../../img/cad.png';

/**
 * Control with snapping functionality for geometry alignment.
 * @extends {ole.Control}
 * @alias ole.CadControl
 */
export default class CadControl extends Control {
  /**
   * @param {Object} options Tool options.
   * @param {Number} [options.snapTolerance] Snap tolerance in pixel
   *   for snap lines. Default is 10.
   * @param {Boolean} [options.showSnapLines] Whether to show
   *   snap lines (default is true).
   * @param {Boolean} [options.showSnapPoints] Whether to show
   *  snap points around the closest feature.
   * @param {Number} [options.snapPointDist] Distance of the
   *   snap points (default is 30).
   * @param {Boolean} [options.useMapUnits] Whether to use map units
   *   as measurement for point snapping. Default is false (pixel are used).
   */
  constructor(options) {
    super(
      Object.assign(options, {
        title: 'CAD control',
        className: 'ole-control-cad',
        image: cadPng
      })
    );

    /**
     * If true, map units are used for point snapping.
     * The default measurement are pixels.
     */
    this.useMapUnits = options.useMapUnits;

    /**
     * Interaction for handling move events.
     * @type {ol.interactionPointer}
     * @private
     */
    this.pointerInteraction = new ol.interaction.Pointer({
      handleMoveEvent: this.onMove.bind(this)
    });

    /**
     * Layer for drawing snapping geometries.
     * @type {ol.layer.Vector}
     * @private
     */
    this.snapLayer = new ol.layer.Vector({
      source: new ol.source.Vector(),
      style: [
        new ol.style.Style({
          image: new ol.style.RegularShape({
            fill: new ol.style.Fill({
              color: '#E8841F'
            }),
            stroke: new ol.style.Stroke({
              width: 1,
              color: '#618496'
            }),
            points: 4,
            radius: 5,
            radius2: 0,
            angle: Math.PI / 4
          }),
          stroke: new ol.style.Stroke({
            width: 1,
            lineDash: [5, 10],
            color: '#618496'
          })
        })
      ]
    });

    /**
     * Snap tolerance in pixel.
     * @type {Number}
     * @private
     */
    this.snapTolerance = options.snapTolerance || 10;

    /**
     * Interaction for snapping
     * @type {ol.interaction.Snap}
     * @private
     */
    this.snapInteraction = new ol.interaction.Snap({
      pixelTolerance: this.snapTolerance,
      source: this.snapLayer.getSource()
    });

    /**
     * Whether to show the snap points.
     * @type {Boolean}
     * @private
     */
    this.showSnapPoints = options.showSnapPoints;

    /**
     * Initial distance of snap points.
     * @type {Number}
     * @private
     */
    this.snapPointDist = options.snapPointDist || 30;

    /**
     * Whether to show snap lines.
     * @type {Boolean}
     * @private
     */
    this.showSnapLines = options.showSnapLines;

    if (this.showSnapLines === 'undefined') {
      this.showSnapLines = true;
    }

    this.standalone = false;
  }

  /**
   * @inheritdoc
   */
  setMap(map) {
    super.setMap(map);
    this.map.addLayer(this.snapLayer);

    // Ensure that the snap interaction is at the last position
    // as it must be the first to handle the  pointermove event.
    this.map.getInteractions().on(
      'change:length',
      function(e) {
        var pos = e.target.getArray().indexOf(this.snapInteraction);

        if (this.active && pos > -1 && pos !== e.target.getLength() - 1) {
          this.deactivate();
          this.activate();
        }
      },
      this
    );
  }

  /**
   * Handle move event.
   * @private
   * @param {ol.MapBrowserEvent} evt Move event.
   */
  onMove(evt) {
    var features = this.getClosestFeatures(evt.coordinate, 5);

    // Don't snap on the edit feature
    var editFeature = this.editor.getEditFeature();
    if (editFeature && features.indexOf(editFeature) > -1) {
      features.splice(features.indexOf(editFeature), 1);
    }

    this.snapLayer.getSource().clear();

    if (this.showSnapLines) {
      this.drawSnapLines(features, evt.coordinate);
    }

    if (this.showSnapPoints && features.length) {
      this.drawSnapPoints(evt.coordinate, features[0]);
    }
  }

  /**
   * Returns a list of the {num} closest features
   * to a given coordinate.
   * @private
   * @param {ol.Coordinate} coordinate Coordinate.
   * @param {Number} num Number of features to search.
   * @returns {Array.
} List of closest features.
   */
  getClosestFeatures(coordinate, num) {
    num = num || 1;
    var ext = [-Infinity, -Infinity, Infinity, Infinity];
    var featureDict = {};

    this.source.forEachFeatureInExtent(ext, function(f) {
      var cCoord = f.getGeometry().getClosestPoint(coordinate);
      var dx = cCoord[0] - coordinate[0];
      var dy = cCoord[1] - coordinate[1];
      var dist = dx * dx + dy * dy;
      featureDict[dist] = f;
    });

    var dists = Object.keys(featureDict);
    var features = [];
    var count = Math.min(dists.length, num);

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

    for (var i = 0; i < count; i++) {
      features.push(featureDict[dists[i]]);
    }

    return features;
  }

  /**
   * Draws snap lines by building the extent for
   * a pair of features.
   * @private
   * @param {Array.
} features List of features.
   * @param {ol.Coordinate} coordinate Mouse pointer coordinate.
   */
  drawSnapLines(features, coordinate) {
    var auxCoords = [];
    for (var i = 0; i < features.length; i++) {
      var geom = features[i].getGeometry();

      if (geom instanceof ol.geom.Point) {
        auxCoords.push(geom.getCoordinates());
      } else {
        var coords = ol.geom.Polygon
          .fromExtent(geom.getExtent())
          .getCoordinates()[0];
        auxCoords = auxCoords.concat(coords);
      }
    }

    var px = this.map.getPixelFromCoordinate(coordinate);
    var lineCoords;

    for (i = 0; i < auxCoords.length; i++) {
      var auxPx = this.map.getPixelFromCoordinate(auxCoords[i]);
      if (
        px[0] > auxPx[0] - this.snapTolerance / 2 &&
        px[0] < auxPx[0] + this.snapTolerance / 2
      ) {
        var newY = px[1];
        newY += px[1] < auxPx[1]
          ? -this.snapTolerance * 2
          : this.snapTolerance * 2;

        lineCoords = [
          this.map.getCoordinateFromPixel([auxPx[0], newY]),
          auxCoords[i]
        ];
      } else if (
        px[1] > auxPx[1] - this.snapTolerance / 2 &&
        px[1] < auxPx[1] + this.snapTolerance / 2
      ) {
        var newX = px[0];
        newX += px[0] < auxPx[0]
          ? -this.snapTolerance * 2
          : this.snapTolerance * 2;

        lineCoords = [
          this.map.getCoordinateFromPixel([newX, auxPx[1]]),
          auxCoords[i]
        ];
      }

      if (lineCoords) {
        var g = new ol.geom.LineString(lineCoords);
        this.snapLayer.getSource().addFeature(new ol.Feature(g));
      }
    }
  }

  /**
   * Adds snap points to the snapping layer.
   * @private
   * @param {ol.Coordinate} coordinateMouse cursor coordinate.
   * @param {ol.eaturee} feature Feature to draw the snap points for.
   */
  drawSnapPoints(coordinate, feature) {
    var featCoord = feature.getGeometry().getClosestPoint(coordinate);

    var px = this.map.getPixelFromCoordinate(featCoord);
    var snapCoords = [];

    if (this.useMapUnits) {
      snapCoords = [
        [featCoord[0] - this.snapPointDist, featCoord[1]],
        [featCoord[0] + this.snapPointDist, featCoord[1]],
        [featCoord[0], featCoord[1] - this.snapPointDist],
        [featCoord[0], featCoord[1] + this.snapPointDist]
      ];
    } else {
      var snapPx = [
        [px[0] - this.snapPointDist, px[1]],
        [px[0] + this.snapPointDist, px[1]],
        [px[0], px[1] - this.snapPointDist],
        [px[0], px[1] + this.snapPointDist]
      ];

      for (var j = 0; j < snapPx.length; j++) {
        snapCoords.push(this.map.getCoordinateFromPixel(snapPx[j]));
      }
    }

    var snapGeom = new ol.geom.MultiPoint(snapCoords);
    this.snapLayer.getSource().addFeature(new ol.Feature(snapGeom));
  }

  /**
   * Open the control's dialog.
   * @private
   */
  openDialog() {
    var distLabel = this.useMapUnits ? 'map units' : 'px';

    var tpl = [
      '
' +
        '
<input type="radio" name="radioBtn" {{#c1}}checked{{/c1}} id="aux-cb">' +
        'Show snap lines
' +
        '
<input type="radio" name="radioBtn" {{#c2}}checked{{/c2}} id="dist-cb">' +
        'Show snap points. Distance (' +
        distLabel +
        '): ' +
        '<input type="text" id="width-input" value="{{gridWidth}}">
' +
        '
'
    ].join('');

    var div = document.createElement('div');
    div.innerHTML = mustache.render(tpl, {
      className: this.className,
      gridWidth: this.snapPointDist,
      c1: this.showSnapLines,
      c2: this.showSnapPoints
    });

    this.map.getTargetElement().appendChild(div.firstChild);

    document.getElementById('aux-cb').addEventListener(
      'change',
      function(evt) {
        this.showSnapLines = evt.target.checked;
      }.bind(this)
    );

    document.getElementById('dist-cb').addEventListener(
      'change',
      function(evt) {
        this.showSnapPoints = evt.target.checked;
      }.bind(this)
    );

    document.getElementById('width-input').addEventListener(
      'keyup',
      function(evt) {
        if (parseFloat(evt.target.value)) {
          this.snapPointDist = parseFloat(evt.target.value);
        }
      }.bind(this)
    );
  }

  /**
   * Closes the control dialog.
   * @private
   */
  closeDialog() {
    var div = document.getElementById(this.className + '-dialog');
    if (div) {
      this.map.getTargetElement().removeChild(div);
    }
  }

  /**
   * @inheritdoc
   */
  activate() {
    super.activate();
    this.map.addInteraction(this.pointerInteraction);
    this.map.addInteraction(this.snapInteraction);
    this.openDialog();
  }

  /**
   * @inheritdoc
   */
  deactivate() {
    super.deactivate();
    this.map.removeInteraction(this.pointerInteraction);
    this.map.removeInteraction(this.snapInteraction);
    this.closeDialog();
  }
}
<commit_msg>Don't show snap points and lines together in cad tool.<commit_after>import Control from './control.js';
import mustache from 'mustache';
import cadPng from '../../img/cad.png';

/**
 * Control with snapping functionality for geometry alignment.
 * @extends {ole.Control}
 * @alias ole.CadControl
 */
export default class CadControl extends Control {
  /**
   * @param {Object} options Tool options.
   * @param {Number} [options.snapTolerance] Snap tolerance in pixel
   *   for snap lines. Default is 10.
   * @param {Boolean} [options.showSnapLines] Whether to show
   *   snap lines (default is true).
   * @param {Boolean} [options.showSnapPoints] Whether to show
   *  snap points around the closest feature.
   * @param {Number} [options.snapPointDist] Distance of the
   *   snap points (default is 30).
   * @param {Boolean} [options.useMapUnits] Whether to use map units
   *   as measurement for point snapping. Default is false (pixel are used).
   */
  constructor(options) {
    super(
      Object.assign(options, {
        title: 'CAD control',
        className: 'ole-control-cad',
        image: cadPng
      })
    );

    /**
     * If true, map units are used for point snapping.
     * The default measurement are pixels.
     */
    this.useMapUnits = options.useMapUnits;

    /**
     * Interaction for handling move events.
     * @type {ol.interactionPointer}
     * @private
     */
    this.pointerInteraction = new ol.interaction.Pointer({
      handleMoveEvent: this.onMove.bind(this)
    });

    /**
     * Layer for drawing snapping geometries.
     * @type {ol.layer.Vector}
     * @private
     */
    this.snapLayer = new ol.layer.Vector({
      source: new ol.source.Vector(),
      style: [
        new ol.style.Style({
          image: new ol.style.RegularShape({
            fill: new ol.style.Fill({
              color: '#E8841F'
            }),
            stroke: new ol.style.Stroke({
              width: 1,
              color: '#618496'
            }),
            points: 4,
            radius: 5,
            radius2: 0,
            angle: Math.PI / 4
          }),
          stroke: new ol.style.Stroke({
            width: 1,
            lineDash: [5, 10],
            color: '#618496'
          })
        })
      ]
    });

    /**
     * Snap tolerance in pixel.
     * @type {Number}
     * @private
     */
    this.snapTolerance = options.snapTolerance || 10;

    /**
     * Interaction for snapping
     * @type {ol.interaction.Snap}
     * @private
     */
    this.snapInteraction = new ol.interaction.Snap({
      pixelTolerance: this.snapTolerance,
      source: this.snapLayer.getSource()
    });

    /**
     * Whether to show the snap points.
     * @type {Boolean}
     * @private
     */
    this.showSnapPoints = options.showSnapPoints;

    /**
     * Initial distance of snap points.
     * @type {Number}
     * @private
     */
    this.snapPointDist = options.snapPointDist || 30;

    /**
     * Whether to show snap lines.
     * @type {Boolean}
     * @private
     */
    this.showSnapLines = options.showSnapLines;

    if (this.showSnapLines === 'undefined') {
      this.showSnapLines = true;
    }

    this.standalone = false;
  }

  /**
   * @inheritdoc
   */
  setMap(map) {
    super.setMap(map);
    this.map.addLayer(this.snapLayer);

    // Ensure that the snap interaction is at the last position
    // as it must be the first to handle the  pointermove event.
    this.map.getInteractions().on(
      'change:length',
      function(e) {
        var pos = e.target.getArray().indexOf(this.snapInteraction);

        if (this.active && pos > -1 && pos !== e.target.getLength() - 1) {
          this.deactivate();
          this.activate();
        }
      },
      this
    );
  }

  /**
   * Handle move event.
   * @private
   * @param {ol.MapBrowserEvent} evt Move event.
   */
  onMove(evt) {
    var features = this.getClosestFeatures(evt.coordinate, 5);

    // Don't snap on the edit feature
    var editFeature = this.editor.getEditFeature();
    if (editFeature && features.indexOf(editFeature) > -1) {
      features.splice(features.indexOf(editFeature), 1);
    }

    this.snapLayer.getSource().clear();

    if (this.showSnapLines) {
      this.drawSnapLines(features, evt.coordinate);
    }

    if (this.showSnapPoints && features.length) {
      this.drawSnapPoints(evt.coordinate, features[0]);
    }
  }

  /**
   * Returns a list of the {num} closest features
   * to a given coordinate.
   * @private
   * @param {ol.Coordinate} coordinate Coordinate.
   * @param {Number} num Number of features to search.
   * @returns {Array.
} List of closest features.
   */
  getClosestFeatures(coordinate, num) {
    num = num || 1;
    var ext = [-Infinity, -Infinity, Infinity, Infinity];
    var featureDict = {};

    this.source.forEachFeatureInExtent(ext, function(f) {
      var cCoord = f.getGeometry().getClosestPoint(coordinate);
      var dx = cCoord[0] - coordinate[0];
      var dy = cCoord[1] - coordinate[1];
      var dist = dx * dx + dy * dy;
      featureDict[dist] = f;
    });

    var dists = Object.keys(featureDict);
    var features = [];
    var count = Math.min(dists.length, num);

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

    for (var i = 0; i < count; i++) {
      features.push(featureDict[dists[i]]);
    }

    return features;
  }

  /**
   * Draws snap lines by building the extent for
   * a pair of features.
   * @private
   * @param {Array.
} features List of features.
   * @param {ol.Coordinate} coordinate Mouse pointer coordinate.
   */
  drawSnapLines(features, coordinate) {
    var auxCoords = [];
    for (var i = 0; i < features.length; i++) {
      var geom = features[i].getGeometry();

      if (geom instanceof ol.geom.Point) {
        auxCoords.push(geom.getCoordinates());
      } else {
        var coords = ol.geom.Polygon
          .fromExtent(geom.getExtent())
          .getCoordinates()[0];
        auxCoords = auxCoords.concat(coords);
      }
    }

    var px = this.map.getPixelFromCoordinate(coordinate);
    var lineCoords;

    for (i = 0; i < auxCoords.length; i++) {
      var auxPx = this.map.getPixelFromCoordinate(auxCoords[i]);
      if (
        px[0] > auxPx[0] - this.snapTolerance / 2 &&
        px[0] < auxPx[0] + this.snapTolerance / 2
      ) {
        var newY = px[1];
        newY += px[1] < auxPx[1]
          ? -this.snapTolerance * 2
          : this.snapTolerance * 2;

        lineCoords = [
          this.map.getCoordinateFromPixel([auxPx[0], newY]),
          auxCoords[i]
        ];
      } else if (
        px[1] > auxPx[1] - this.snapTolerance / 2 &&
        px[1] < auxPx[1] + this.snapTolerance / 2
      ) {
        var newX = px[0];
        newX += px[0] < auxPx[0]
          ? -this.snapTolerance * 2
          : this.snapTolerance * 2;

        lineCoords = [
          this.map.getCoordinateFromPixel([newX, auxPx[1]]),
          auxCoords[i]
        ];
      }

      if (lineCoords) {
        var g = new ol.geom.LineString(lineCoords);
        this.snapLayer.getSource().addFeature(new ol.Feature(g));
      }
    }
  }

  /**
   * Adds snap points to the snapping layer.
   * @private
   * @param {ol.Coordinate} coordinateMouse cursor coordinate.
   * @param {ol.eaturee} feature Feature to draw the snap points for.
   */
  drawSnapPoints(coordinate, feature) {
    var featCoord = feature.getGeometry().getClosestPoint(coordinate);

    var px = this.map.getPixelFromCoordinate(featCoord);
    var snapCoords = [];

    if (this.useMapUnits) {
      snapCoords = [
        [featCoord[0] - this.snapPointDist, featCoord[1]],
        [featCoord[0] + this.snapPointDist, featCoord[1]],
        [featCoord[0], featCoord[1] - this.snapPointDist],
        [featCoord[0], featCoord[1] + this.snapPointDist]
      ];
    } else {
      var snapPx = [
        [px[0] - this.snapPointDist, px[1]],
        [px[0] + this.snapPointDist, px[1]],
        [px[0], px[1] - this.snapPointDist],
        [px[0], px[1] + this.snapPointDist]
      ];

      for (var j = 0; j < snapPx.length; j++) {
        snapCoords.push(this.map.getCoordinateFromPixel(snapPx[j]));
      }
    }

    var snapGeom = new ol.geom.MultiPoint(snapCoords);
    this.snapLayer.getSource().addFeature(new ol.Feature(snapGeom));
  }

  /**
   * Open the control's dialog.
   * @private
   */
  openDialog() {
    var distLabel = this.useMapUnits ? 'map units' : 'px';

    var tpl = [
      '
' +
        '
<input type="radio" name="radioBtn" {{#c1}}checked{{/c1}} id="aux-cb">' +
        'Show snap lines
' +
        '
<input type="radio" name="radioBtn" {{#c2}}checked{{/c2}} id="dist-cb">' +
        'Show snap points. Distance (' +
        distLabel +
        '): ' +
        '<input type="text" id="width-input" value="{{gridWidth}}">
' +
        '
'
    ].join('');

    var div = document.createElement('div');
    div.innerHTML = mustache.render(tpl, {
      className: this.className,
      gridWidth: this.snapPointDist,
      c1: this.showSnapLines,
      c2: this.showSnapPoints
    });

    this.map.getTargetElement().appendChild(div.firstChild);

    document.getElementById('aux-cb').addEventListener(
      'change',
      function(evt) {
        this.showSnapLines = evt.target.checked;
        this.showSnapPoints = !this.showSnapLines;
      }.bind(this)
    );

    document.getElementById('dist-cb').addEventListener(
      'change',
      function(evt) {
        this.showSnapPoints = evt.target.checked;
        this.showSnapLines = !this.showSnapPoints;
      }.bind(this)
    );

    document.getElementById('width-input').addEventListener(
      'keyup',
      function(evt) {
        if (parseFloat(evt.target.value)) {
          this.snapPointDist = parseFloat(evt.target.value);
        }
      }.bind(this)
    );
  }

  /**
   * Closes the control dialog.
   * @private
   */
  closeDialog() {
    var div = document.getElementById(this.className + '-dialog');
    if (div) {
      this.map.getTargetElement().removeChild(div);
    }
  }

  /**
   * @inheritdoc
   */
  activate() {
    super.activate();
    this.map.addInteraction(this.pointerInteraction);
    this.map.addInteraction(this.snapInteraction);
    this.openDialog();
  }

  /**
   * @inheritdoc
   */
  deactivate() {
    super.deactivate();
    this.map.removeInteraction(this.pointerInteraction);
    this.map.removeInteraction(this.snapInteraction);
    this.closeDialog();
  }
}
<|endoftext|>


<commit_before>require('es5-shim');

var args   = {};
var system = require('system');

system.args.forEach(function(arg, index) {
    if (index > 0) {
        args[arg.split('=')[0].replace(/^--/, '')] = arg.split('=')[1];
    }
});

// Shim the process variable for chalk
var process = {argv : system.args.join(' '), env : system.env};

var chalk     = require('chalk');
var myConsole = console;
var webpage   = require('webpage');

var execute,
    getDuration,
    getFailures,
    getResults,
    getSummary,
    page,
    testsAreFinished,
    testsWereSuccessful,
    url;

page = webpage.create();
url  = 'http://localhost:' + args.port;

if (! ('trace' in args)) {
    console = {
        log   : function() {},
        error : function() {}
    };
}

page.onError = function(message, trace) {
    var messages, time;

    messages = ['[' + chalk.red(time) + '] ERROR:' + message];
    time     = new Date().toString().split(' ')[4];

    if (trace && trace.length) {
        messages.push('[' + chalk.red(time) + '] TRACE:');

        trace.forEach(function(item) {
            messages.push(
                '[' + chalk.red(time) + '] -> ' + item.file + ': ' + item.line +
                (item.function ? ' (in function "' + item.function +'")' : '')
            );
        });
    }

    console.error(messages.join('\n'));
};

getDuration = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('duration')[0].innerText;
    });
};

getFailures = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('failures')[0].innerText;
    });
};

getResults = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('bar')[0].innerText;
    });
};

getSummary = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('summary')[0].innerText;
    });
};

testsWereSuccessful = function() {
    return page.evaluate(function() {
        return (document.getElementsByClassName('failed').length === 0);
    });
};

testsAreFinished = function() {
    return page.evaluate(function() {
        banner = document.getElementsByClassName('banner')[0];

        if (! banner) {
            return false;
        }

        return banner.getElementsByClassName('duration').length;
    });
};

execute = function() {
    var results, time;

    if ('screenshot' in args) {
        page.render(args.screenshot || 'disyntegrating.png');
    }

    if (testsAreFinished()) {
        var time;

        results = getResults() + ' ' + getDuration();
        time    = new Date().toString().split(' ')[4];

        if (testsWereSuccessful()) {
            myConsole.log('[' + chalk.green(time) + ']', results);
            phantom.exit(0);
        } else {
            myConsole.error('[' + chalk.red(time) + ']', results);
            console.error('[' + chalk.red(time) + ']', getFailures());
            phantom.exit(1);
        }
    } else {
        setTimeout(execute, 200);
    }
};

setTimeout(function() {
    page.open(url, function(status) {
        var time;

        time = new Date().toString().split(' ')[4];

        if(status === 'success') {
            myConsole.log('[' + chalk.dim(time) + ']', 'Spec Runner loaded');
            execute();
        } else {
            myConsole.error('[' + chalk.red(time) + ']', 'Spec Runner not loaded');
            phantom.exit(1);
        }
    });
}, 200);
<commit_msg>Adding phantom timeout to prevent neverending builds<commit_after>require('es5-shim');

var args   = {};
var system = require('system');

system.args.forEach(function(arg, index) {
    if (index > 0) {
        args[arg.split('=')[0].replace(/^--/, '')] = arg.split('=')[1];
    }
});

// Shim the process variable for chalk
var process = {argv : system.args.join(' '), env : system.env};

var chalk     = require('chalk');
var myConsole = console;
var webpage   = require('webpage');

var DEFAULT_TIMEOUT = 3 * (1000 * 60);

var execute,
    getDuration,
    getFailures,
    getResults,
    getSummary,
    page,
    testsAreFinished,
    testsWereSuccessful,
    url;

page = webpage.create();
url  = 'http://localhost:' + args.port;

if (! ('trace' in args)) {
    console = {
        log   : function() {},
        error : function() {}
    };
}

page.onError = function(message, trace) {
    var messages, time;

    messages = ['[' + chalk.red(time) + '] ERROR:' + message];
    time     = new Date().toString().split(' ')[4];

    if (trace && trace.length) {
        messages.push('[' + chalk.red(time) + '] TRACE:');

        trace.forEach(function(item) {
            messages.push(
                '[' + chalk.red(time) + '] -> ' + item.file + ': ' + item.line +
                (item.function ? ' (in function "' + item.function +'")' : '')
            );
        });
    }

    console.error(messages.join('\n'));
};

getDuration = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('duration')[0].innerText;
    });
};

getFailures = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('failures')[0].innerText;
    });
};

getResults = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('bar')[0].innerText;
    });
};

getSummary = function() {
    return page.evaluate(function() {
        return document.getElementsByClassName('summary')[0].innerText;
    });
};

testsWereSuccessful = function() {
    return page.evaluate(function() {
        return (document.getElementsByClassName('failed').length === 0);
    });
};

testsAreFinished = function() {
    return page.evaluate(function() {
        banner = document.getElementsByClassName('banner')[0];

        if (! banner) {
            return false;
        }

        return banner.getElementsByClassName('duration').length;
    });
};

execute = function() {
    var results, time;

    if ('screenshot' in args) {
        page.render(args.screenshot || 'disyntegrating.png');
    }

    if (testsAreFinished()) {
        var time;

        results = getResults() + ' ' + getDuration();
        time    = new Date().toString().split(' ')[4];

        if (testsWereSuccessful()) {
            myConsole.log('[' + chalk.green(time) + ']', results);
            phantom.exit(0);
        } else {
            myConsole.error('[' + chalk.red(time) + ']', results);
            console.error('[' + chalk.red(time) + ']', getFailures());
            phantom.exit(1);
        }
    } else {
        setTimeout(execute, 200);
    }
};

setTimeout(function() {
    page.open(url, function(status) {
        var time;

        time = new Date().toString().split(' ')[4];

        if(status === 'success') {
            myConsole.log('[' + chalk.dim(time) + ']', 'Spec Runner loaded');
            execute();
        } else {
            myConsole.error('[' + chalk.red(time) + ']', 'Spec Runner not loaded');
            phantom.exit(1);
        }
    });
}, 200);

setTimeout(function() {
    var time;

    time = new Date().toString().split(' ')[4];

    myConsole.error('[' + chalk.red(time) + ']', 'Timeout exceeded');
    phantom.exit(1);
}, args.phantomTimeout || DEFAULT_TIMEOUT);
<|endoftext|>


<commit_before>const shell = require('shelljs')

const cmdArguments = process.argv.slice(2)
const semverType = cmdArguments[0]

if (!semverType || !semverType.match(/^(major|minor|patch)$/)) {
   console.log(`Usage: major|minor|patch`)
   process.exit(1)
}

execCommand(`npm version ${semverType}`)
execCommand(`yarn run build`)
execCommand(`yarn run test:rules`)
execCommand(`git push`)
execCommand(`git push --tags`)
execCommand(`npm publish`)

function execCommand(command) {
   const result = shell.exec(command)
   if (!!result.code) {
      console.log(result.stdout)
      process.exit(1)
   }
}
<commit_msg>Update publish script to use npm exclusively<commit_after>const shell = require('shelljs')

const cmdArguments = process.argv.slice(2)
const semverType = cmdArguments[0]

if (!semverType || !semverType.match(/^(major|minor|patch)$/)) {
   console.log(`Usage: major|minor|patch`)
   process.exit(1)
}

execCommand(`npm version ${semverType}`)
execCommand(`npm run build`)
execCommand(`npm run test:rules`)
execCommand(`git push`)
execCommand(`git push --tags`)
execCommand(`npm publish`)

function execCommand(command) {
   const result = shell.exec(command)
   if (!!result.code) {
      console.log(result.stdout)
      process.exit(1)
   }
}
<|endoftext|>


<commit_before>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

/**
 * @author aarranz
 */

/////////////////////////////////////
// DragboardLayout
/////////////////////////////////////

/**
 * Represents a dragboard layout to be used to place igadgets into the dragboard.
 * Despite javascript not having a way to mark classes abstract, this class is
 * abstract, so please do not try to create an instance of this clase.
 *
 * @param dragboard      associated dragboard
 * @param scrollbarSpace space reserved for the right scroll bar in pixels
 */
function DragboardLayout(dragboard, scrollbarSpace) {
	if (arguments.length == 0)
		return; // Allow empty constructor (allowing hierarchy)

	this.dragboard = dragboard;
	this.scrollbarSpace = scrollbarSpace;
	this.iGadgets = new Hash();
}

DragboardLayout.prototype.getMenubarSize = function() {
	return 18; // TODO calculate this
}

DragboardLayout.prototype.getMenubarSizeInCells = function() {
	return Math.ceil(this.fromPixelsToVCells(this.getMenubarSize()));
}

DragboardLayout.prototype.getStatusbarSize = function() {
	return 16; // TODO calculate this
}

DragboardLayout.prototype.getExtraCells = function() {
	var sizeInPixels = this.getMenubarSize() + this.getStatusbarSize();
	return Math.ceil(this.fromPixelsToVCells(sizeInPixels));
}

/**
 * This function is slow. Please, only call it when really necessary.
 */
DragboardLayout.prototype._recomputeSize = function() {
	var dragboardElement = this.dragboard.dragboardElement;
	this.dragboardWidth = parseInt(dragboardElement.offsetWidth);

	var tmp = this.dragboardWidth;
	tmp-= parseInt(dragboardElement.clientWidth);

	if (tmp > this.scrollbarSpace)
		this.dragboardWidth-= tmp;
	else
		this.dragboardWidth-= this.scrollbarSpace;
}

/**
 * Returns true if the point is inside the dragboard
 */
DragboardLayout.prototype.isInside = function (x, y) {
	return (x >= 0) && (x < this.dragboardWidth) && (y >= 0);
}

DragboardLayout.prototype.getWidth = function() {
	return this.dragboardWidth;
}

DragboardLayout.prototype.addIGadget = function(iGadget, affectsDragboard) {
	if (affectsDragboard) {
		this.dragboard._registerIGadget(iGadget);

		if (iGadget.element != null) // TODO
			this.dragboard.dragboardElement.appendChild(iGadget.element);
	}

	this.iGadgets[iGadget.code] = iGadget;
}

DragboardLayout.prototype.removeIGadget = function(iGadget, affectsDragboard) {
	if (affectsDragboard) {
		this.dragboard._deregisterIGadget(iGadget);

		if (iGadget.element != null) // TODO
			this.dragboard.dragboardElement.removeChild(iGadget.element);
	}

	delete this.iGadgets[iGadget.code];
}

/**
 * This method must be called to avoid memory leaks caused by circular references.
 */
DragboardLayout.prototype.destroy = function() {
	var keys = this.iGadgets.keys();
	for (var i = 0; i < keys.length; i++) {
		this.iGadgets[keys[i]].destroy();
	}
	this.iGadgets = null;
}

DragboardLayout.prototype.acceptMove = function(iGadget, newposition) {
	iGadget.setPosition(newposition);
}<commit_msg>refs #288. Remove the igadget from the hash before removing the igadget from the dragboard (as this cleans the code field of the igadget).<commit_after>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

/**
 * @author aarranz
 */

/////////////////////////////////////
// DragboardLayout
/////////////////////////////////////

/**
 * Represents a dragboard layout to be used to place igadgets into the dragboard.
 * Despite javascript not having a way to mark classes abstract, this class is
 * abstract, so please do not try to create an instance of this clase.
 *
 * @param dragboard      associated dragboard
 * @param scrollbarSpace space reserved for the right scroll bar in pixels
 */
function DragboardLayout(dragboard, scrollbarSpace) {
	if (arguments.length == 0)
		return; // Allow empty constructor (allowing hierarchy)

	this.dragboard = dragboard;
	this.scrollbarSpace = scrollbarSpace;
	this.iGadgets = new Hash();
}

DragboardLayout.prototype.getMenubarSize = function() {
	return 18; // TODO calculate this
}

DragboardLayout.prototype.getMenubarSizeInCells = function() {
	return Math.ceil(this.fromPixelsToVCells(this.getMenubarSize()));
}

DragboardLayout.prototype.getStatusbarSize = function() {
	return 16; // TODO calculate this
}

DragboardLayout.prototype.getExtraCells = function() {
	var sizeInPixels = this.getMenubarSize() + this.getStatusbarSize();
	return Math.ceil(this.fromPixelsToVCells(sizeInPixels));
}

/**
 * This function is slow. Please, only call it when really necessary.
 */
DragboardLayout.prototype._recomputeSize = function() {
	var dragboardElement = this.dragboard.dragboardElement;
	this.dragboardWidth = parseInt(dragboardElement.offsetWidth);

	var tmp = this.dragboardWidth;
	tmp-= parseInt(dragboardElement.clientWidth);

	if (tmp > this.scrollbarSpace)
		this.dragboardWidth-= tmp;
	else
		this.dragboardWidth-= this.scrollbarSpace;
}

/**
 * Returns true if the point is inside the dragboard
 */
DragboardLayout.prototype.isInside = function (x, y) {
	return (x >= 0) && (x < this.dragboardWidth) && (y >= 0);
}

DragboardLayout.prototype.getWidth = function() {
	return this.dragboardWidth;
}

DragboardLayout.prototype.addIGadget = function(iGadget, affectsDragboard) {
	if (affectsDragboard) {
		this.dragboard._registerIGadget(iGadget);

		if (iGadget.element != null) // TODO
			this.dragboard.dragboardElement.appendChild(iGadget.element);
	}

	this.iGadgets[iGadget.code] = iGadget;
}

DragboardLayout.prototype.removeIGadget = function(iGadget, affectsDragboard) {
	delete this.iGadgets[iGadget.code];

	if (affectsDragboard) {
		this.dragboard._deregisterIGadget(iGadget);

		if (iGadget.element != null) // TODO
			this.dragboard.dragboardElement.removeChild(iGadget.element);
	}
}

/**
 * This method must be called to avoid memory leaks caused by circular references.
 */
DragboardLayout.prototype.destroy = function() {
	var keys = this.iGadgets.keys();
	for (var i = 0; i < keys.length; i++) {
		this.iGadgets[keys[i]].destroy();
	}
	this.iGadgets = null;
}

DragboardLayout.prototype.acceptMove = function(iGadget, newposition) {
	iGadget.setPosition(newposition);
}<|endoftext|>


<commit_before>(function(Gear, Global, Constants) {

	var _pixelRatio = (function() {
		var canvas = _.element(Constants.CANVAS),
			context = canvas.getContext(Constants.CONTEXT_2D),
			devicePixelRatio = Global.WIN.devicePixelRatio || 1,
			backingStoreRatio = context.webkitBackingStorePixelRatio      ||
										context.mozBackingStorePixelRatio ||
										context.msBackingStorePixelRatio  ||
										context.oBackingStorePixelRatio   ||
										context.backingStorePixelRatio    ||
										1;
		return (devicePixelRatio / backingStoreRatio);
	}());

	var Canvas = function(config) {
		config = config || {};
		Gear.Node.call(this, config);

		this._contextType = config.contextType || Constants.CONTEXT_2D;
		this._pixelRatio = config.pixelRatio || _pixelRatio;
		this._saveCounter = 0;
		this.elem = _.element(Constants.CANVAS, {
			className: Constants.CANVAS_CLASS + ' ' + (config.className || '')
		});

		this.setContext(this.elem);
		this.setSize(config);
	};

	_.extend(Canvas.prototype, Gear.Node.prototype, {

		reset: function() {
			var pxRatio = this.getPixelRatio();
			this.getContext().setTransform(pxRatio, 0, 0, pxRatio, 0, 0);
		},

		getElem: function() {
			return this.elem;
		},

		getContext: function() {
			return this.context;
		},

		setContext: function(elem) {
			elem = elem || this.elem;
			this.context = elem.getContext(this._contextType);
		},

		save: function() {
			this._saveCounter += 1;
			if (this._saveCounter > 1) { return this; }

			this.getContext().save();
			return this;
		},

		restore: function() {
			this._saveCounter -= 1;
			if (this._saveCounter !== 0) { return this; }

			this.getContext().restore();
			return this;
		},

		clear: function(clip) {
			var context = this.getContext(),
				plane;

			if (clip) {
				plane = Gear.Plane(clip);
				context.clearRect(plane.x, plane.y, plane.width, plane.height);
				plane.destroy();
			} else {
				context.clearRect(0, 0, this.getWidth(), this.getHeight());
			}
		},

		/**
		 * Creates a data URL for the image of the defined area
		 * @param {Object} config
		 * @param {Function} config.callback function executed when the composite has completed
		 * @param {String} [config.mimeType] can be 'image/png' or 'image/jpeg'. 'image/png' is the default
		 * @param {Number} [config.x] x position of canvas section
		 * @param {Number} [config.y] y position of canvas section
		 * @param {Number} [config.width] width of canvas section
		 * @param {Number} [config.height] height of canvas section
		 * @param {Number} [config.quality] jpeg quality (if 'image/jpeg' mimeType). 0 low, 1 high.
		 */
		toDataURL: function(mimeType, quality) {
			return this.elem.toDataURL(mimeType, quality);
		},

		/**
		 * Fill and stroke a shape
		 * @param  {Shape} shape
		 */
		fillAndStroke: function(shape) {
			this._fill(shape);
			this._stroke(shape, shape.hasShadow() && shape.hasFill());
		},

		applyOpacity: function(shape) {
			var absOpacity = shape.getAbsoluteOpacity();
			if (absOpacity !== 1) {
				this.getContext().globalAlpha = absOpacity;
			}
		},

		applyLineJoin: function(shape) {
			var lineJoin = shape.getLineJoin();
			if (lineJoin) {
				this.getContext().lineJoin = lineJoin;
			}
		},

		applyAncestorTransforms: function(node) {
			var matrix = node.getAbsoluteTransform().getMatrix(),
				context = this.getContext();

			context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
		},

		applyRotation: function(node) {
			var context = this.getContext(),
				rotate = node.getRotate();
			// After matrix transformations are applied
			// rotate around a pivot point
			if (rotate) {
				var pivot = node.getPivot();
				if (pivot.x !== 0 && pivot.y !== 0) {
					// The node is rotating around a point and not
					// using the matrix transformation. Instead the context
					// is translated and rotated the appropriate amount
					context.translate(pivot.x, pivot.y);
					context.rotate(Gear.Math.degToRad(rotate));
					context.translate(pivot.x * -1, pivot.y * -1);
				}
			}
		},

		clip: function(container) {
			var context = this.getContext(),
				clip = container.getClip();

			this.applyAncestorTransforms(container);
			context.beginPath();
			context.rect(clip.x, clip.y, clip.width, clip.height);
			context.clip();
			this.reset();
		},

		/*
		 * Gear automatically handles pixel ratio adustments. Unless otherwise
		 * specificed, the pixel ratio will be defaulted to the actual device pixel ratio.
		 * You can override the device pixel ratio for special situations, or, if you don't
		 * want the pixel ratio to be taken into account, you can set it to 1.
		 */
		getPixelRatio: function() {
			return this._pixelRatio;
		},

		/**
		 * Manually set the pixel ratio
		 * @param {Number} pixelRatio
		 */
		setPixelRatio: function(pixelRatio) {
			this._pixelRatio = pixelRatio;
			this.setSize({ width: this.width, height: this.height });
		},

		setWidth: function(width) {
			width = width || 0;
			// take into account pixel ratio
			this.attr.width = this.elem.width = (width * this.getPixelRatio());
			this.elem.style.width = _.toPx(width);
			var pixelRatio = this.getPixelRatio();
			this.context.scale(pixelRatio, pixelRatio);
		},

		setHeight: function(height) {
			height = height || 0;
			// take into account pixel ratio
			this.attr.height = this.elem.height = (height * this.getPixelRatio());
			this.elem.style.height = _.toPx(height);
			var pixelRatio = this.getPixelRatio();
			this.context.scale(pixelRatio, pixelRatio);
		},

		toString: function() {
			return '[Canvas]';
		}
	});

	Gear.Canvas = Canvas;

}(Gear, Gear.Global, Gear.Constants));
<commit_msg>Add a getCanvas to getElem<commit_after>(function(Gear, Global, Constants) {

	var _pixelRatio = (function() {
		var canvas = _.element(Constants.CANVAS),
			context = canvas.getContext(Constants.CONTEXT_2D),
			devicePixelRatio = Global.WIN.devicePixelRatio || 1,
			backingStoreRatio = context.webkitBackingStorePixelRatio      ||
										context.mozBackingStorePixelRatio ||
										context.msBackingStorePixelRatio  ||
										context.oBackingStorePixelRatio   ||
										context.backingStorePixelRatio    ||
										1;
		return (devicePixelRatio / backingStoreRatio);
	}());

	var Canvas = function(config) {
		config = config || {};
		Gear.Node.call(this, config);

		this._contextType = config.contextType || Constants.CONTEXT_2D;
		this._pixelRatio = config.pixelRatio || _pixelRatio;
		this._saveCounter = 0;
		this.elem = _.element(Constants.CANVAS, {
			className: Constants.CANVAS_CLASS + ' ' + (config.className || '')
		});

		this.setContext(this.elem);
		this.setSize(config);
	};

	_.extend(Canvas.prototype, Gear.Node.prototype, {

		reset: function() {
			var pxRatio = this.getPixelRatio();
			this.getContext().setTransform(pxRatio, 0, 0, pxRatio, 0, 0);
		},

		getElem: function() {
			return this.elem;
		},
		getCanvas: function() {
			return this.elem;
		},

		getContext: function() {
			return this.context;
		},

		setContext: function(elem) {
			elem = elem || this.elem;
			this.context = elem.getContext(this._contextType);
		},

		save: function() {
			this._saveCounter += 1;
			if (this._saveCounter > 1) { return this; }

			this.getContext().save();
			return this;
		},

		restore: function() {
			this._saveCounter -= 1;
			if (this._saveCounter !== 0) { return this; }

			this.getContext().restore();
			return this;
		},

		clear: function(clip) {
			var context = this.getContext(),
				plane;

			if (clip) {
				plane = Gear.Plane(clip);
				context.clearRect(plane.x, plane.y, plane.width, plane.height);
				plane.destroy();
			} else {
				context.clearRect(0, 0, this.getWidth(), this.getHeight());
			}
		},

		/**
		 * Creates a data URL for the image of the defined area
		 * @param {Object} config
		 * @param {Function} config.callback function executed when the composite has completed
		 * @param {String} [config.mimeType] can be 'image/png' or 'image/jpeg'. 'image/png' is the default
		 * @param {Number} [config.x] x position of canvas section
		 * @param {Number} [config.y] y position of canvas section
		 * @param {Number} [config.width] width of canvas section
		 * @param {Number} [config.height] height of canvas section
		 * @param {Number} [config.quality] jpeg quality (if 'image/jpeg' mimeType). 0 low, 1 high.
		 */
		toDataURL: function(mimeType, quality) {
			return this.elem.toDataURL(mimeType, quality);
		},

		/**
		 * Fill and stroke a shape
		 * @param  {Shape} shape
		 */
		fillAndStroke: function(shape) {
			this._fill(shape);
			this._stroke(shape, shape.hasShadow() && shape.hasFill());
		},

		applyOpacity: function(shape) {
			var absOpacity = shape.getAbsoluteOpacity();
			if (absOpacity !== 1) {
				this.getContext().globalAlpha = absOpacity;
			}
		},

		applyLineJoin: function(shape) {
			var lineJoin = shape.getLineJoin();
			if (lineJoin) {
				this.getContext().lineJoin = lineJoin;
			}
		},

		applyAncestorTransforms: function(node) {
			var matrix = node.getAbsoluteTransform().getMatrix(),
				context = this.getContext();

			context.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
		},

		applyRotation: function(node) {
			var context = this.getContext(),
				rotate = node.getRotate();
			// After matrix transformations are applied
			// rotate around a pivot point
			if (rotate) {
				var pivot = node.getPivot();
				if (pivot.x !== 0 && pivot.y !== 0) {
					// The node is rotating around a point and not
					// using the matrix transformation. Instead the context
					// is translated and rotated the appropriate amount
					context.translate(pivot.x, pivot.y);
					context.rotate(Gear.Math.degToRad(rotate));
					context.translate(pivot.x * -1, pivot.y * -1);
				}
			}
		},

		clip: function(container) {
			var context = this.getContext(),
				clip = container.getClip();

			this.applyAncestorTransforms(container);
			context.beginPath();
			context.rect(clip.x, clip.y, clip.width, clip.height);
			context.clip();
			this.reset();
		},

		/*
		 * Gear automatically handles pixel ratio adustments. Unless otherwise
		 * specificed, the pixel ratio will be defaulted to the actual device pixel ratio.
		 * You can override the device pixel ratio for special situations, or, if you don't
		 * want the pixel ratio to be taken into account, you can set it to 1.
		 */
		getPixelRatio: function() {
			return this._pixelRatio;
		},

		/**
		 * Manually set the pixel ratio
		 * @param {Number} pixelRatio
		 */
		setPixelRatio: function(pixelRatio) {
			this._pixelRatio = pixelRatio;
			this.setSize({ width: this.width, height: this.height });
		},

		setWidth: function(width) {
			width = width || 0;
			// take into account pixel ratio
			this.attr.width = this.elem.width = (width * this.getPixelRatio());
			this.elem.style.width = _.toPx(width);
			var pixelRatio = this.getPixelRatio();
			this.context.scale(pixelRatio, pixelRatio);
		},

		setHeight: function(height) {
			height = height || 0;
			// take into account pixel ratio
			this.attr.height = this.elem.height = (height * this.getPixelRatio());
			this.elem.style.height = _.toPx(height);
			var pixelRatio = this.getPixelRatio();
			this.context.scale(pixelRatio, pixelRatio);
		},

		toString: function() {
			return '[Canvas]';
		}
	});

	Gear.Canvas = Canvas;

}(Gear, Gear.Global, Gear.Constants));
<|endoftext|>


<commit_before>
/**
 * @class
 *
 * @emits Canvas#event:"canvas.init"
 */
function Canvas(config, events, svgFactory) {
  'use strict';

  var paper = Snap(config.container);

  /**
   * Adds a shape to the canvas
   *
   * @method Canvas#addShape
   *
   * @param {Object} shape a descriptor for the shape
   */
  function addShape(shape) {
    var gfx = svgFactory.createShape(paper, shape);

    /**
     * An event indicating that a new shape has been added to the canvas.
     *
     * @memberOf Canvas
     *
     * @event shape.added
     * @type {Object}
     * @property {Object} element the shape descriptor
     * @property {Object} gfx the graphical representation of the shape
     */
    events.fire('shape.added', { element: shape, gfx: gfx });
  }

  /**
   * Adds a connection to the canvas
   *
   * @method Canvas#addConnection
   *
   * @param {Object} connection a descriptor for the connection
   */
  function addConnection(connection) {
    var gfx = svgFactory.createConnection(paper, connection);

    /**
     * An event indicating that a new connection has been added to the canvas.
     *
     * @memberOf Canvas
     *
     * @event connection.added
     * @type {Object}
     * @property {Object} element the connection descriptor
     * @property {Object} gfx the graphical representation of the connection
     */
    events.fire('connection.added', { element: connection, gfx: gfx });
  }

  /**
   * Returns the actual graphics context.
   *
   * @returns {Object} the global paper object
   */
  function getContext() {
    return paper;
  }

  /**
   * An event indicating that the canvas is ready to be drawn on.
   *
   * @event Canvas#"canvas.init"
   * @type {Object}
   * @property {Object} paper the initialized drawing paper
   */
  events.fire('canvas.init', { paper: paper });

  return {
    addShape: addShape,
    addConnection: addConnection,
    getContext: getContext
  };
}

Canvas.$inject = ['config', 'events', 'svgFactory'];

module.exports = Canvas;<commit_msg>feat(canvas): add sendToFront method<commit_after>var IdGenerator = require('../util/IdGenerator'),
    _ = require('../util/underscore');

/**
 * @type djs.ShapeDescriptor
 */

/**
 * @class
 *
 * @emits Canvas#canvas.init
 */
function Canvas(config, events, svgFactory) {

  'use strict';

  var ids = new IdGenerator('s');

  var paper = Snap(config.container);

  // holds id -> { element, gfx } mappings
  var elementMap = {};

  function addElement(e, gfx) {
    if (!e.id) {
      e.id = ids.next();
    }

    elementMap[e.id] = { element: e, gfx: gfx };
  }

  function addChild(parent, child) {
    if (parent.children) {
      parent.children.push(child);
    } else {
      parent.children = [ child ];
    }
  }

  /**
   * Adds a shape to the canvas
   *
   * @method Canvas#addShape
   *
   * @param {djs.ShapeDescriptor} shape a descriptor for the shape
   */
  function addShape(shape) {
    var gfx = svgFactory.createShape(paper, shape);

    if (shape.parent) {
      addChild(shape.parent, shape);
    }

    addElement(shape, gfx);

    /**
     * An event indicating that a new shape has been added to the canvas.
     *
     * @memberOf Canvas
     *
     * @event shape.added
     * @type {Object}
     * @property {djs.ElementDescriptor} element the shape descriptor
     * @property {Object} gfx the graphical representation of the shape
     */
    events.fire('shape.added', { element: shape, gfx: gfx });

    return this;
  }

  /**
   * Adds a connection to the canvas
   *
   * @method Canvas#addConnection
   *
   * @param {djs.ElementDescriptor} connection a descriptor for the connection
   */
  function addConnection(connection) {
    var gfx = svgFactory.createConnection(paper, connection);

    addElement(connection, gfx);

    /**
     * An event indicating that a new connection has been added to the canvas.
     *
     * @memberOf Canvas
     *
     * @event connection.added
     * @type {Object}
     * @property {djs.ElementDescriptor} element the connection descriptor
     * @property {Object} gfx the graphical representation of the connection
     */
    events.fire('connection.added', { element: connection, gfx: gfx });

    return this;
  }

  /**
   * Sends a shape to the front.
   *
   * This method takes parent / child relationships between shapes into account
   * and makes sure that children are properly handled, too.
   *
   * @method Canvas#sendToFront
   *
   * @param {djs.ElementDescriptor} shape descriptor of the shape to be sent to front
   * @param {boolean} bubble=true whether to send parent shapes to front, too
   */
  function sendToFront(shape, bubble) {

    if (bubble !== false) {
      bubble = true;
    }

    if (bubble && shape.parent) {
      sendToFront(shape.parent);
    }

    if (shape.children) {
      shape.children.forEach(function(child) {
        sendToFront(child, false);
      });
    }

    var gfx = getGraphics(shape),
        gfxParent = gfx.parent();

    gfx.remove().appendTo(gfxParent);
  }

  /**
   * Return the graphical object underlaying a certain diagram element
   *
   * @method Canvas#getGraphics
   *
   * @param {djs.ElementDescriptor} element descriptor of the element for which the grapical representation should be returned
   */
  function getGraphics(element) {
    return elementMap[element.id].gfx;
  }

  /**
   * Returns the actual graphics context.
   *
   * @returns {snapsvg.Paper} the global paper object
   */
  function getContext() {
    return paper;
  }

  events.on('diagram.init', function(event) {

    /**
     * An event indicating that the canvas is ready to be drawn on.
     *
     * @memberOf Canvas
     *
     * @event canvas.init
     *
     * @type {Object}
     * @property {snapsvg.Paper} paper the initialized drawing paper
     */
    events.fire('canvas.init', { paper: paper });
  });

  return {
    addShape: addShape,
    addConnection: addConnection,
    getContext: getContext,
    getGraphics: getGraphics,
    sendToFront: sendToFront
  };
}

Canvas.$inject = ['config', 'events', 'svgFactory'];

module.exports = Canvas;<|endoftext|>


<commit_before>'use strict';

/**
* merkurClientApp.services Module
*
* Provides services and constants for Merkur-Client
*/
var merkurClientAppServices = angular.module('merkurClientApp.services', []);

// Stomp service
merkurClientAppServices.service('stompService', ['messages.serverWebsocketEndpoint', function (messagesServerWebsocketEndpoint) {
  var socket = new SockJS(messagesServerWebsocketEndpoint);
  this.client = Stomp.over(socket);
}]);

// endpoint address for websocket server
merkurClientAppServices.value('messages.serverWebsocketEndpoint', 'http://localhost:9090/merkur-server/socket');

// number of maximum entries shown
merkurClientAppServices.value('messages.maxEntriesShown', 10);

// topic of messages fetched from stomp client
// TODO : Über GUI konfigurierbar machen
merkurClientAppServices. value('messages.topic', '/topic/de.#');
// merkurClientAppServices. value('messages.topic', '/topic/counter');
// merkurClientAppServices. value('messages.topic', '/topic/uuid');<commit_msg>Routing-Key angepasst.<commit_after>'use strict';

/**
* merkurClientApp.services Module
*
* Provides services and constants for Merkur-Client
*/
var merkurClientAppServices = angular.module('merkurClientApp.services', []);

// Stomp service
merkurClientAppServices.service('stompService', ['messages.serverWebsocketEndpoint', function (messagesServerWebsocketEndpoint) {
  var socket = new SockJS(messagesServerWebsocketEndpoint);
  this.client = Stomp.over(socket);
}]);

// endpoint address for websocket server
merkurClientAppServices.value('messages.serverWebsocketEndpoint', 'http://localhost:9090/merkur-server/socket');

// number of maximum entries shown
merkurClientAppServices.value('messages.maxEntriesShown', 10);

// topic of messages fetched from stomp client
// TODO : Über GUI konfigurierbar machen
merkurClientAppServices. value('messages.topic', '/topic/Generator.#');
// merkurClientAppServices. value('messages.topic', '/topic/counter');
// merkurClientAppServices. value('messages.topic', '/topic/uuid');<|endoftext|>


<commit_before>/**
 * Mobile Custom JS
 */

var pvl_player;

var is_playing = false;

var jp_is_playing = false;

var is_first_load = true;
var volume = 100;

var nowplaying_data;
var nowplaying_last_run = 0;
var nowplaying_url;
var nowplaying_timeout;
var nowplaying_interval;

var check_interval;

$(document).on("pageinit", function() {
	if (is_first_load)
	{
		$('#btn_back').hide();

		if (!DF_IsApp)
		{
			$("#pvl-jplayer").jPlayer({
				play: function() {
					jp_is_playing = true;

					// Progress event doesn't fire on iOS.
					if (isIOS())
						$.mobile.loading("hide");
				},
				progress: function(event) {
					if (event.jPlayer.status.currentTime > 0)
						$.mobile.loading("hide");
				},
				suspend: function(event) {
					console.log('Stream Suspended');
					jp_is_playing = false;
				},
				error: function(event) {
					var error_details = event.jPlayer.error;
					console.error(error_details.message+' - '+error_details.hint);
					jp_is_playing = false;
				},
				swfPath: DF_ContentPath+'/jplayer/jplayer.swf',
				solution: getPlaybackSolution(),
				supplied: 'mp3',
				preload: 'none',
				volume: (volume / 100),
				muted: false,
				backgroundColor: '#000000',
				cssSelectorAncestor: '#pvl-jplayer-controls',
				errorAlerts: false,
				warningAlerts: false
			});

			if (isIOS())
				$('#player_volume').prop('disabled', true);
		}

		$('#player_controls').hide();

		$('#player_volume').attr('value', volume);
		$('#player_volume').slider({
			stop: function(event, ui) {
				volume = parseInt(event.target.value);
				playerSetVolume(volume);
			}
		});

		$('#player_controls #player_pause').on("click", function(event, ui) {
			stopAllPlayers();
		});

		$('body').on('click', '.btn_tunein', function(event) {
			playStation($(this).closest('.station').attr('id'));
		});

		$("[data-role='navbar']").navbar();
		$("[data-role='header'], [data-role='footer']").toolbar();

		nowplaying_interval = setInterval('verifyNowPlaying()', 30000);
	}
});

$(window).on("pagecontainershow", function(event) {
	is_first_load = false;

	// Force old page to be deleted.
	$("[data-role='page']:not(.ui-page-active)").remove();

	// Add "Home" button.
	var page_url = $("[data-role='page']").jqmData("url");
	if (page_url != '/mobile')
		$('#btn_back').show();
	else
		$('#btn_back').hide();

	// Change the heading
	var current = $('#page').jqmData("title");
	$("[data-role='header'] h1").text(current);

	// Remove active class from nav buttons
	$("[data-role='navbar'] a.ui-btn-active").removeClass("ui-btn-active");

	// Add active class to current nav button
	var page_url = window.location.href;

	$("[data-role='navbar'] a").each(function() {
		if ($(this).attr('href') == page_url)
			$(this).addClass("ui-btn-active");
	});

	// Force a reload (or re-print) of now playing data.
	checkNowPlaying();
});

// Ensure now-playing is being checked, in spite of any interruptions.
function verifyNowPlaying()
{
	var current_timestamp = getUnixTimestamp();
	if (current_timestamp - nowplaying_last_run > 25)
		checkNowPlaying();
}

function checkNowPlaying(force_update)
{
	force_update = (typeof force_update !== 'undefined') ? force_update : false;

	// Only run now-playing once every 10 seconds max.
	var current_timestamp = getUnixTimestamp();
	if (current_timestamp - nowplaying_last_run < 10 && !force_update)
	{
		processNowPlaying();
	}
	else
	{
		jQuery.ajax({
			cache: false,
			url: DF_ContentPath+'/api/nowplaying.json',
			dataType: 'json'
		}).done(function(data) {
			nowplaying_data = data;
			processNowPlaying();
		});
	}
}

function processNowPlaying()
{
	if (typeof nowplaying_data === 'undefined')
		return;

	for (var station_id in nowplaying_data)
	{
		var station_info = nowplaying_data[station_id];
		var station = $('[data-role="page"].ui-page-active #station_'+station_id);
		var station_exists = (station.length != 0);

		if (station_exists)
		{
			// Format title.
			if (!station_info.title)
			{
				station.find('.nowplaying-artist').text(station_info.text);
				station.find('.nowplaying-title').text('');
			}
			else
			{
				station.find('.nowplaying-artist').text(station_info.title);
				station.find('.nowplaying-title').text(station_info.artist);
			}

			// Post listener count.
			if (station_info.listeners)
				station.find('.nowplaying-listeners').show().html(' '+station_info.listeners);
			else
				station.find('.nowplaying-listeners').hide();

			// Set station "live" status or "offline" status.
			if (station_info.text == 'Stream Offline')
			{
				station.find('.nowplaying-live').hide();
				station.removeClass('live').addClass('offline');

				if (station.data('inactive') == 'hide')
					station.hide();
			}
			else
			{
				station.find('.nowplaying-live').hide();
				station.removeClass('live offline');

				if (!station.is(':visible'))
					station.show();
			}

			// Set event data.
			if (station_info.event)
			{
				var event_info = station_info.event;
				station.find('.nowplaying-onair').show().find('.nowplaying-onair-inner').html(' On Air: '+event_info.title);
			}
			else if (station_info.event_upcoming)
			{
				var event_info = station_info.event_upcoming;
				station.find('.nowplaying-onair').show().find('.nowplaying-onair-inner').html(' In '+event_info.minutes_until+' mins: '+event_info.title);
			}
			else
			{
				station.find('.nowplaying-onair').hide();
			}

			// Set station history.
			if (station_info.song_history)
			{
				var history_block = '';

				for (var j in station_info.song_history)
				{
					var song_num = parseInt(j)+1;
					var history_row = station_info.song_history[j];

					history_block += '
#'+song_num+": "+history_row.text+'
';
				}

				station.find('.station-history').html(history_block);
			}

			if (station_info.song_id)
			{
				// Detect a change in song.
				var current_song_id = station.data('song_id');
				if (station_info.song_id != current_song_id)
				{
					station.find('.btn-like').removeClass('btn-disabled').addClass('btn-success');
				}

				station.data('song_id', station_info.song_id);
			}

		}
	}

	nowplaying_last_run = getUnixTimestamp();
	// nowplaying_timeout = setTimeout('checkNowPlaying()', 20000);
}

function playStation(id)
{
	console.log('Playing station: '+id);

	var station = $('[data-role="page"].ui-page-active #'+id);

	var stream_type = station.data('type');
	var stream_url = station.data('stream');

	var currently_playing = station.hasClass('playing');

	if (stream_url && stream_type)
	{
		stopAllPlayers();

		if (stream_type == "stream")
		{
			if (DF_IsApp)
				window.open(stream_url);
			else
				window.location.href = stream_url;
			return false;
		}
		else
		{
			nowplaying_url = stream_url;

			if (!DF_IsApp)
			{
				$.mobile.loading( "show", {
		            text: 'Playing Station...',
		            textVisible: true,
		            theme: 'b',
		            textonly: false
			    });
			}

			startPlayer();

			// Trigger an immediate now-playing check.
			checkNowPlaying(true);
		}

		// Log in Google Analytics
		try {
			ga('send', 'event', 'Station', 'Play', station.data('name'));
		} catch(e) {}
	}
}

function startPlayer()
{
	if (DF_IsApp)
	{
		pvl_player = new Media(nowplaying_url, function() {
			playerSetVolume(volume);
            console.log("playAudio(): Audio Success");
        },
        function(err) {
            console.error("playAudio(): Audio Error");
            console.error(err);
    	},
    	function(status) {
    		console.log(status);
    	});

		pvl_player.play();
	}
	else
	{
		var stream = {
			title: "Ponyville Live!",
			mp3: nowplaying_url
		};
		$("#pvl-jplayer").jPlayer("setMedia", stream);
		$("#pvl-jplayer").jPlayer("play");

		check_interval = setInterval('checkPlayer()', 1500);
	}

	is_playing = true;
	$('.btn_tunein').hide();

	$('#player_controls').show();
	$("[data-role='header'], [data-role='footer']").toolbar("updatePagePadding");
}

function checkPlayer()
{
	if (is_playing && !DF_IsApp && !jp_is_playing && !isIOS())
	{
		clearInterval(check_interval);
		startPlayer();
	}
}

function stopAllPlayers()
{
	if (is_playing)
	{
		if (DF_IsApp && typeof pvl_player !== 'undefined')
		{
			pvl_player.stop();
			pvl_player.release();
		}
		else if ($("#pvl-jplayer").length > 0)
		{
			try
			{
				$('#pvl-jplayer').jPlayer('stop');
			}
			catch(e) {}

			try
			{
				$('#pvl-jplayer').jPlayer("clearMedia");
			}
			catch(e) {}
		}
	}

	is_playing = false;
	if (!DF_IsApp)
		clearInterval(check_interval);

	$('.btn_tunein').show();

	$('#player_controls').hide();
	$.mobile.loading("hide");

	nowplaying_url = null;
}

function playerSetVolume(volume)
{
	if (DF_IsApp)
	{
		pvl_player.setVolume(volume / 100);
	}
	else if (is_playing)
	{
		$('#pvl-jplayer').jPlayer('volume', (volume / 100));
	}
}

function getPlaybackSolution()
{
	if (isIOS())
		return 'html';
	else if (canPlayMp3())
		return 'html, flash';
	else
		return 'flash';
}

function canPlayMp3()
{
	if (isIOS())
		return true;

	if (isIE() || isSteam())
		return false;

	var a = document.createElement('audio');
	var can_play_mp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
	return can_play_mp3;
}

function isIE () {
	var myNav = navigator.userAgent.toLowerCase();
	return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}
function isIOS() {
	return navigator.userAgent.match(/(iPod|iPhone|iPad)/i);
}
function isSteam() {
	var myNav = navigator.userAgent.toLowerCase();
	return (myNav.indexOf('gameoverlay') != -1) ? true : false;
}

function getUnixTimestamp()
{
	return Math.round((new Date()).getTime() / 1000);
}<commit_msg>Fix "Undefined event" problem on mobile.<commit_after>/**
 * Mobile Custom JS
 */

var pvl_player;

var is_playing = false;

var jp_is_playing = false;

var is_first_load = true;
var volume = 100;

var nowplaying_data;
var nowplaying_last_run = 0;
var nowplaying_url;
var nowplaying_timeout;
var nowplaying_interval;

var check_interval;

$(document).on("pageinit", function() {
	if (is_first_load)
	{
		$('#btn_back').hide();

		if (!DF_IsApp)
		{
			$("#pvl-jplayer").jPlayer({
				play: function() {
					jp_is_playing = true;

					// Progress event doesn't fire on iOS.
					if (isIOS())
						$.mobile.loading("hide");
				},
				progress: function(event) {
					if (event.jPlayer.status.currentTime > 0)
						$.mobile.loading("hide");
				},
				suspend: function(event) {
					console.log('Stream Suspended');
					jp_is_playing = false;
				},
				error: function(event) {
					var error_details = event.jPlayer.error;
					console.error(error_details.message+' - '+error_details.hint);
					jp_is_playing = false;
				},
				swfPath: DF_ContentPath+'/jplayer/jplayer.swf',
				solution: getPlaybackSolution(),
				supplied: 'mp3',
				preload: 'none',
				volume: (volume / 100),
				muted: false,
				backgroundColor: '#000000',
				cssSelectorAncestor: '#pvl-jplayer-controls',
				errorAlerts: false,
				warningAlerts: false
			});

			if (isIOS())
				$('#player_volume').prop('disabled', true);
		}

		$('#player_controls').hide();

		$('#player_volume').attr('value', volume);
		$('#player_volume').slider({
			stop: function(event, ui) {
				volume = parseInt(event.target.value);
				playerSetVolume(volume);
			}
		});

		$('#player_controls #player_pause').on("click", function(event, ui) {
			stopAllPlayers();
		});

		$('body').on('click', '.btn_tunein', function(event) {
			playStation($(this).closest('.station').attr('id'));
		});

		$("[data-role='navbar']").navbar();
		$("[data-role='header'], [data-role='footer']").toolbar();

		nowplaying_interval = setInterval('verifyNowPlaying()', 30000);
	}
});

$(window).on("pagecontainershow", function(event) {
	is_first_load = false;

	// Force old page to be deleted.
	$("[data-role='page']:not(.ui-page-active)").remove();

	// Add "Home" button.
	var page_url = $("[data-role='page']").jqmData("url");
	if (page_url != '/mobile')
		$('#btn_back').show();
	else
		$('#btn_back').hide();

	// Change the heading
	var current = $('#page').jqmData("title");
	$("[data-role='header'] h1").text(current);

	// Remove active class from nav buttons
	$("[data-role='navbar'] a.ui-btn-active").removeClass("ui-btn-active");

	// Add active class to current nav button
	var page_url = window.location.href;

	$("[data-role='navbar'] a").each(function() {
		if ($(this).attr('href') == page_url)
			$(this).addClass("ui-btn-active");
	});

	// Force a reload (or re-print) of now playing data.
	checkNowPlaying();
});

// Ensure now-playing is being checked, in spite of any interruptions.
function verifyNowPlaying()
{
	var current_timestamp = getUnixTimestamp();
	if (current_timestamp - nowplaying_last_run > 25)
		checkNowPlaying();
}

function checkNowPlaying(force_update)
{
	force_update = (typeof force_update !== 'undefined') ? force_update : false;

	// Only run now-playing once every 10 seconds max.
	var current_timestamp = getUnixTimestamp();
	if (current_timestamp - nowplaying_last_run < 10 && !force_update)
	{
		processNowPlaying();
	}
	else
	{
		jQuery.ajax({
			cache: false,
			url: DF_ContentPath+'/api/nowplaying.json',
			dataType: 'json'
		}).done(function(data) {
			nowplaying_data = data;
			processNowPlaying();
		});
	}
}

function processNowPlaying()
{
	if (typeof nowplaying_data === 'undefined')
		return;

	for (var station_id in nowplaying_data)
	{
		var station_info = nowplaying_data[station_id];
		var station = $('[data-role="page"].ui-page-active #station_'+station_id);
		var station_exists = (station.length != 0);

		if (station_exists)
		{
			// Format title.
			if (!station_info.title)
			{
				station.find('.nowplaying-artist').text(station_info.text);
				station.find('.nowplaying-title').text('');
			}
			else
			{
				station.find('.nowplaying-artist').text(station_info.title);
				station.find('.nowplaying-title').text(station_info.artist);
			}

			// Post listener count.
			if (station_info.listeners)
				station.find('.nowplaying-listeners').show().html(' '+station_info.listeners);
			else
				station.find('.nowplaying-listeners').hide();

			// Set station "live" status or "offline" status.
			if (station_info.text == 'Stream Offline')
			{
				station.find('.nowplaying-live').hide();
				station.removeClass('live').addClass('offline');

				if (station.data('inactive') == 'hide')
					station.hide();
			}
			else
			{
				station.find('.nowplaying-live').hide();
				station.removeClass('live offline');

				if (!station.is(':visible'))
					station.show();
			}

			// Set event data.
			if (station_info.event.title)
			{
				var event_info = station_info.event;
				station.find('.nowplaying-onair').show().find('.nowplaying-onair-inner').html(' On Air: '+event_info.title);
			}
			else if (station_info.event_upcoming.title)
			{
				var event_info = station_info.event_upcoming;
				station.find('.nowplaying-onair').show().find('.nowplaying-onair-inner').html(' In '+event_info.minutes_until+' mins: '+event_info.title);
			}
			else
			{
				station.find('.nowplaying-onair').hide();
			}

			// Set station history.
			if (station_info.song_history)
			{
				var history_block = '';

				for (var j in station_info.song_history)
				{
					var song_num = parseInt(j)+1;
					var history_row = station_info.song_history[j];

					history_block += '
#'+song_num+": "+history_row.text+'
';
				}

				station.find('.station-history').html(history_block);
			}

			if (station_info.song_id)
			{
				// Detect a change in song.
				var current_song_id = station.data('song_id');
				if (station_info.song_id != current_song_id)
				{
					station.find('.btn-like').removeClass('btn-disabled').addClass('btn-success');
				}

				station.data('song_id', station_info.song_id);
			}

		}
	}

	nowplaying_last_run = getUnixTimestamp();
	// nowplaying_timeout = setTimeout('checkNowPlaying()', 20000);
}

function playStation(id)
{
	console.log('Playing station: '+id);

	var station = $('[data-role="page"].ui-page-active #'+id);

	var stream_type = station.data('type');
	var stream_url = station.data('stream');

	var currently_playing = station.hasClass('playing');

	if (stream_url && stream_type)
	{
		stopAllPlayers();

		if (stream_type == "stream")
		{
			if (DF_IsApp)
				window.open(stream_url);
			else
				window.location.href = stream_url;
			return false;
		}
		else
		{
			nowplaying_url = stream_url;

			if (!DF_IsApp)
			{
				$.mobile.loading( "show", {
		            text: 'Playing Station...',
		            textVisible: true,
		            theme: 'b',
		            textonly: false
			    });
			}

			startPlayer();

			// Trigger an immediate now-playing check.
			checkNowPlaying(true);
		}

		// Log in Google Analytics
		try {
			ga('send', 'event', 'Station', 'Play', station.data('name'));
		} catch(e) {}
	}
}

function startPlayer()
{
	if (DF_IsApp)
	{
		pvl_player = new Media(nowplaying_url, function() {
			playerSetVolume(volume);
            console.log("playAudio(): Audio Success");
        },
        function(err) {
            console.error("playAudio(): Audio Error");
            console.error(err);
    	},
    	function(status) {
    		console.log(status);
    	});

		pvl_player.play();
	}
	else
	{
		var stream = {
			title: "Ponyville Live!",
			mp3: nowplaying_url
		};
		$("#pvl-jplayer").jPlayer("setMedia", stream);
		$("#pvl-jplayer").jPlayer("play");

		check_interval = setInterval('checkPlayer()', 1500);
	}

	is_playing = true;
	$('.btn_tunein').hide();

	$('#player_controls').show();
	$("[data-role='header'], [data-role='footer']").toolbar("updatePagePadding");
}

function checkPlayer()
{
	if (is_playing && !DF_IsApp && !jp_is_playing && !isIOS())
	{
		clearInterval(check_interval);
		startPlayer();
	}
}

function stopAllPlayers()
{
	if (is_playing)
	{
		if (DF_IsApp && typeof pvl_player !== 'undefined')
		{
			pvl_player.stop();
			pvl_player.release();
		}
		else if ($("#pvl-jplayer").length > 0)
		{
			try
			{
				$('#pvl-jplayer').jPlayer('stop');
			}
			catch(e) {}

			try
			{
				$('#pvl-jplayer').jPlayer("clearMedia");
			}
			catch(e) {}
		}
	}

	is_playing = false;
	if (!DF_IsApp)
		clearInterval(check_interval);

	$('.btn_tunein').show();

	$('#player_controls').hide();
	$.mobile.loading("hide");

	nowplaying_url = null;
}

function playerSetVolume(volume)
{
	if (DF_IsApp)
	{
		pvl_player.setVolume(volume / 100);
	}
	else if (is_playing)
	{
		$('#pvl-jplayer').jPlayer('volume', (volume / 100));
	}
}

function getPlaybackSolution()
{
	if (isIOS())
		return 'html';
	else if (canPlayMp3())
		return 'html, flash';
	else
		return 'flash';
}

function canPlayMp3()
{
	if (isIOS())
		return true;

	if (isIE() || isSteam())
		return false;

	var a = document.createElement('audio');
	var can_play_mp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
	return can_play_mp3;
}

function isIE () {
	var myNav = navigator.userAgent.toLowerCase();
	return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}
function isIOS() {
	return navigator.userAgent.match(/(iPod|iPhone|iPad)/i);
}
function isSteam() {
	var myNav = navigator.userAgent.toLowerCase();
	return (myNav.indexOf('gameoverlay') != -1) ? true : false;
}

function getUnixTimestamp()
{
	return Math.round((new Date()).getTime() / 1000);
}<|endoftext|>


<commit_before>'use strict';

angular.module('berlinerSchulenApp')
	.controller('FilterCtrl', ['$scope', '$timeout', '$mdSidenav', 'schoolFactory',
		function ($scope, $timeout, $mdSidenav, schoolFactory) {

			// Initialize Filter in Front-End
			$scope.searchFilter = {
				main: 'marie'
			};

			$scope.showFilter = true;
			$scope.loading = false;

			$scope.filter = function () {
				$scope.loading = true;
				$timeout(function () {
					schoolFactory.setFilter($scope.searchFilter);
					schoolFactory.applyFilter();
					$scope.loading = false;
				}, 600);
			};

			$scope.cbDistricts = {
				districts: [],

				selectedDistricts: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.districts = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbDistricts.districts = list;
					$scope.cbDistricts.loading = false;
				},

				addCallback: function () {
					$scope.cbDistricts.loading = true;

					schoolFactory.addFilterCallback('Region', this.populate);
				}
			};

			$scope.cbSchooltypes = {
				schooltypes: [],

				selectedTypes: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.schooltypes = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbSchooltypes.schooltypes = list;
					$scope.cbSchooltypes.loading = false;
				},

				addCallback: function () {
					$scope.cbSchooltypes.loading = true;

					schoolFactory.addFilterCallback('Schulart', this.populate);
				}
			};

			$scope.cbSchoolSupporter = {
				supporter: [],

				selectedSupporter: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.supporter = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbSchoolSupporter.supporter = list;
					$scope.cbSchoolSupporter.loading = false;
				},

				addCallback: function () {
					$scope.cbSchoolSupporter.loading = true;

					schoolFactory.addFilterCallback('Schultraeger', this.populate);
				}
			};

			$scope.cbLanguages = {
				languages: [
					{name: 'Griechisch'},
					{name: 'Arabisch'},
					{name: 'Chinesisch'},
					{name: 'Englisch'},
					{name: 'Französisch'},
					{name: 'Hebräisch'},
					{name: 'Italienisch'},
					{name: 'Japanisch'},
					{name: 'Latein'},
					{name: 'Niederländisch'},
					{name: 'Polnisch'},
					{name: 'Portugiesisch'},
					{name: 'Russisch'},
					{name: 'Spanisch'},
					{name: 'Türkisch'}
				],

				selectedLang: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.languages = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbLanguages.languages = list;
					$scope.cbLanguages.loading = false;
				},

				addCallback: function () {
					$scope.cbLanguages.loading = true;

					schoolFactory.addFilterCallback('Fremdsprachen', this.populate);
				}
			};

			$scope.cbAccessibility = {
				accessibilities: [],

				selectedAccessibilities: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.accessibilities = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						if (set[s] !== '') {
							list.push({name: set[s]});
						}
					}

					$scope.cbAccessibility.accessibilities = list;
					$scope.cbAccessibility.loading = false;
				},

				addCallback: function () {
					$scope.cbAccessibility.loading = true;

					schoolFactory.addFilterCallback('Bauten', this.populate);
				}
			};

			$scope.cbCourses = {
				courses: [],

				selectedCourses: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.courses = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						if (set[s] !== '') {
							list.push({name: set[s]});
						}
					}

					$scope.cbCourses.courses = list;
					$scope.cbCourses.loading = false;
				},

				addCallback: function () {
					$scope.cbCourses.loading = true;

					schoolFactory.addFilterCallback('Leistungskurse', this.populate);
				}
			};

			$scope.toogleFilter = function () {
				$scope.showFilter = ( $scope.showFilter === true ) ? false : true;
			};

			this.runFilter = function () {
				if (schoolFactory.hasData()) {
					// Get Select Box Choices
					var set = schoolFactory.getChoiceByName('Region');
					$scope.cbDistricts.populate(set);

					set = schoolFactory.getChoiceByName('Schultraeger');
					$scope.cbSchoolSupporter.populate(set);

					set = schoolFactory.getChoiceByName('Bauten');
					$scope.cbAccessibility.populate(set);

					set = schoolFactory.getChoiceByName('Leistungskurse');
					$scope.cbCourses.populate(set);

					set = schoolFactory.getChoiceByName('Schulart');
					$scope.cbSchooltypes.populate(set);

					//If school data is already loaded just apply filter
					$scope.filter();
				} else {
					$scope.cbDistricts.addCallback();
					$scope.cbSchoolSupporter.addCallback();
					$scope.cbAccessibility.addCallback();
					$scope.cbCourses.addCallback();
					$scope.cbSchooltypes.addCallback();
					// else set the filter and wait. The schoolFactory will load
					// the data and then apply the filter
					schoolFactory.setFilter($scope.searchFilter);
				}
			};

			// Run or set filter depending if data is available
			this.runFilter();

		}]);
<commit_msg>Hide filter by default<commit_after>'use strict';

angular.module('berlinerSchulenApp')
	.controller('FilterCtrl', ['$scope', '$timeout', '$mdSidenav', 'schoolFactory',
		function ($scope, $timeout, $mdSidenav, schoolFactory) {

			// Initialize Filter in Front-End
			$scope.searchFilter = {
				main: 'marie'
			};

			$scope.showFilter = false;
			$scope.loading = false;

			$scope.filter = function () {
				$scope.loading = true;
				$timeout(function () {
					schoolFactory.setFilter($scope.searchFilter);
					schoolFactory.applyFilter();
					$scope.loading = false;
				}, 600);
			};

			$scope.cbDistricts = {
				districts: [],

				selectedDistricts: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.districts = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbDistricts.districts = list;
					$scope.cbDistricts.loading = false;
				},

				addCallback: function () {
					$scope.cbDistricts.loading = true;

					schoolFactory.addFilterCallback('Region', this.populate);
				}
			};

			$scope.cbSchooltypes = {
				schooltypes: [],

				selectedTypes: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.schooltypes = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbSchooltypes.schooltypes = list;
					$scope.cbSchooltypes.loading = false;
				},

				addCallback: function () {
					$scope.cbSchooltypes.loading = true;

					schoolFactory.addFilterCallback('Schulart', this.populate);
				}
			};

			$scope.cbSchoolSupporter = {
				supporter: [],

				selectedSupporter: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.supporter = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbSchoolSupporter.supporter = list;
					$scope.cbSchoolSupporter.loading = false;
				},

				addCallback: function () {
					$scope.cbSchoolSupporter.loading = true;

					schoolFactory.addFilterCallback('Schultraeger', this.populate);
				}
			};

			$scope.cbLanguages = {
				languages: [
					{name: 'Griechisch'},
					{name: 'Arabisch'},
					{name: 'Chinesisch'},
					{name: 'Englisch'},
					{name: 'Französisch'},
					{name: 'Hebräisch'},
					{name: 'Italienisch'},
					{name: 'Japanisch'},
					{name: 'Latein'},
					{name: 'Niederländisch'},
					{name: 'Polnisch'},
					{name: 'Portugiesisch'},
					{name: 'Russisch'},
					{name: 'Spanisch'},
					{name: 'Türkisch'}
				],

				selectedLang: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.languages = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						list.push({name: set[s]});
					}
					$scope.cbLanguages.languages = list;
					$scope.cbLanguages.loading = false;
				},

				addCallback: function () {
					$scope.cbLanguages.loading = true;

					schoolFactory.addFilterCallback('Fremdsprachen', this.populate);
				}
			};

			$scope.cbAccessibility = {
				accessibilities: [],

				selectedAccessibilities: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.accessibilities = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						if (set[s] !== '') {
							list.push({name: set[s]});
						}
					}

					$scope.cbAccessibility.accessibilities = list;
					$scope.cbAccessibility.loading = false;
				},

				addCallback: function () {
					$scope.cbAccessibility.loading = true;

					schoolFactory.addFilterCallback('Bauten', this.populate);
				}
			};

			$scope.cbCourses = {
				courses: [],

				selectedCourses: [],

				loading: false,

				exec: function (values) {
					$scope.searchFilter.courses = values.newValue;
					$scope.filter();
				},

				populate: function (set) {
					var list = [];
					for (var s in set) {
						if (set[s] !== '') {
							list.push({name: set[s]});
						}
					}

					$scope.cbCourses.courses = list;
					$scope.cbCourses.loading = false;
				},

				addCallback: function () {
					$scope.cbCourses.loading = true;

					schoolFactory.addFilterCallback('Leistungskurse', this.populate);
				}
			};

			$scope.toogleFilter = function () {
				$scope.showFilter = ( $scope.showFilter === true ) ? false : true;
			};

			this.runFilter = function () {
				if (schoolFactory.hasData()) {
					// Get Select Box Choices
					var set = schoolFactory.getChoiceByName('Region');
					$scope.cbDistricts.populate(set);

					set = schoolFactory.getChoiceByName('Schultraeger');
					$scope.cbSchoolSupporter.populate(set);

					set = schoolFactory.getChoiceByName('Bauten');
					$scope.cbAccessibility.populate(set);

					set = schoolFactory.getChoiceByName('Leistungskurse');
					$scope.cbCourses.populate(set);

					set = schoolFactory.getChoiceByName('Schulart');
					$scope.cbSchooltypes.populate(set);

					//If school data is already loaded just apply filter
					$scope.filter();
				} else {
					$scope.cbDistricts.addCallback();
					$scope.cbSchoolSupporter.addCallback();
					$scope.cbAccessibility.addCallback();
					$scope.cbCourses.addCallback();
					$scope.cbSchooltypes.addCallback();
					// else set the filter and wait. The schoolFactory will load
					// the data and then apply the filter
					schoolFactory.setFilter($scope.searchFilter);
				}
			};

			// Run or set filter depending if data is available
			this.runFilter();

		}]);
<|endoftext|>


<commit_before>const fs = require('fs')

const processors = fs.readdirSync(__dirname)
.filter((file) => file !== 'index.js')
.map((file) => {
  const {processMessage, order} = require(`./${file}`)
  return {
    order,
    processMessage: processMessage || ((msg) => msg),
  }
})
.sort(({order: o1}, {order: o2}) => o1 - o2)

module.exports = {processors}
<commit_msg>Fix message processor pipeline initialization<commit_after>const fs = require('fs')

const processors = fs.readdirSync(__dirname)
.filter((file) => file !== 'index.js')
.map((file) => {
  const {processMessage, order} = require(`./${file}`)
  return {
    order,
    processMessage: processMessage || ((msg) => msg),
  }
})
.sort(({order: o1}, {order: o2}) => o1 - o2)
.map(({processMessage}) => processMessage)

module.exports = {processors}
<|endoftext|>