<commit_before>import Feature from 'ol/Feature';
import VectorLayer from 'ol/layer/Vector';
import {Circle, Fill, Stroke, Style} from 'ol/style';
import {Point} from 'ol/geom';
import {Vector} from 'ol/source';
import {createStringXY, toStringHDMS} from 'ol/coordinate';
import {transform} from 'ol/proj';

/**
 * @param $rootScope
 * @param HsMapService
 * @param HsCore
 * @param $sce
 * @param HsConfig
 * @param HsLayoutService
 * @param HsUtilsService
 * @param $timeout
 * @param gettext
 */
export default function (
  $rootScope,
  HsMapService,
  HsCore,
  $sce,
  HsConfig,
  HsLayoutService,
  HsUtilsService,
  $timeout,
  gettext
) {
  'ngInject';
  const me = this;

  let map;

  this.queryPoint = new Point([0, 0]);
  this.queryLayer = new VectorLayer({
    title: 'Point clicked',
    queryable: false,
    source: new Vector({
      features: [
        new Feature({
          geometry: me.queryPoint,
        }),
      ],
    }),
    show_in_manager: false,
    removable: false,
    style: pointClickedStyle,
  });

  this.data = {};
  this.data.attributes = [];
  this.data.features = [];
  this.data.featureInfoHtmls = [];
  this.data.customFeatures = [];
  this.data.coordinates = [];
  this.queryActive = false;
  this.popupClassname = '';
  this.selector = null;
  this.currentQuery = null;
  this.featuresUnderMouse = [];
  this.featureLayersUnderMouse = [];
  this.dataCleared = true;

  /**
   *
   */
  function init() {
    map = HsMapService.map;
    me.activateQueries();
    map.on('singleclick', (evt) => {
      $rootScope.$broadcast(
        'mapClicked',
        angular.extend(evt, {
          coordinates: getCoordinate(evt.coordinate),
        })
      );
      if (!me.queryActive) {
        return;
      }
      me.popupClassname = '';
      if (!me.dataCleared) {
        me.clearData();
      }
      me.dataCleared = false;
      me.currentQuery = (Math.random() + 1).toString(36).substring(7);
      me.setData(getCoordinate(evt.coordinate), 'coordinates', true);
      me.last_coordinate_clicked = evt.coordinate; //It is used in some examples and apps
      $rootScope.$broadcast('mapQueryStarted', evt);
    });

    /**
     * @param e
     */
    function showPopUp(e) {
      if (e.dragging) {
        return;
      }
      const map = e.map;
      $timeout((_) => {
        me.featuresUnderMouse = map.getFeaturesAtPixel(e.pixel);
        if (me.featuresUnderMouse !== null) {
          me.featuresUnderMouse = me.featuresUnderMouse.filter((feature) => {
            return (
              feature.getLayer &&
              feature.getLayer(map) &&
              feature.getLayer(map).get('title').length > 0
            );
          });
          me.featureLayersUnderMouse = me.featuresUnderMouse.map((f) =>
            f.getLayer(HsMapService.map)
          );
          me.featureLayersUnderMouse = HsUtilsService.removeDuplicates(
            me.featureLayersUnderMouse,
            'title'
          );
          me.featureLayersUnderMouse = me.featureLayersUnderMouse.map((l) => {
            return {
              layer: l.get('title'),
              features: me.featuresUnderMouse.filter(
                (f) => f.getLayer(HsMapService.map) == l
              ),
            };
          });
          me.featuresUnderMouse.forEach((feature) => {
            serializeFeatureAttributes(feature);
            if (feature.get('features')) {
              feature
                .get('features')
                .forEach((subfeature) =>
                  serializeFeatureAttributes(subfeature)
                );
            }
          });
          const pixel = e.pixel;
          pixel[0] += 2;
          pixel[1] += 4;
          me.hoverPopup.setPosition(map.getCoordinateFromPixel(pixel));
        } else {
          me.featuresUnderMouse = [];
        }
      }, 0);
    }
    map.on('pointermove', HsUtilsService.debounce(showPopUp, 500, false, me));
  }

  /**
   * @param feature
   */
  function serializeFeatureAttributes(feature) {
    if (angular.isUndefined(feature.getLayer)) {
      return;
    }
    const layer = feature.getLayer(HsMapService.map);
    let attrsConfig = [];
    if (
      angular.isDefined(layer.get('popUp')) &&
      angular.isDefined(layer.get('popUp').attributes)
    ) {
      //must be an array
      attrsConfig = layer.get('popUp').attributes;
    } else if (angular.isDefined(layer.get('hoveredKeys'))) {
      //only for backwards-compatibility with HSLayers 1.10 .. 1.22
      //should be dropped in future releases
      //expected to be an array
      attrsConfig = layer.get('hoveredKeys');
      if (angular.isDefined(layer.get('hoveredKeysTranslations'))) {
        //expected to be an object
        for (const [key, val] of Object.entries(
          layer.get('hoveredKeysTranslations')
        )) {
          const index = attrsConfig.indexOf(key);
          if (index > -1) {
            attrsConfig[index] = {
              'attribute': key,
              'label': val,
            };
          }
        }
      }
    } else {
      // Layer is not configured to show pop-ups
      return;
    }
    feature.attributesForHover = [];
    for (const attr of attrsConfig) {
      let attrName, attrLabel;
      let attrFunction = (x) => x;
      if (typeof attr === 'string' || attr instanceof String) {
        //simple case when only attribute name is provided in the layer config
        attrName = attr;
        attrLabel = attr;
      } else {
        if (angular.isUndefined(attr.attribute)) {
          //implies malformed layer config - 'attribute' is obligatory in this case
          continue;
        }
        attrName = attr.attribute;
        attrLabel = angular.isDefined(attr.label) ? attr.label : attr.attribute;
        if (angular.isDefined(attr.displayFunction)) {
          attrFunction = attr.displayFunction;
        }
      }
      if (angular.isDefined(feature.get(attrName))) {
        feature.attributesForHover.push({
          key: attrLabel,
          value: feature.get(attrName),
          displayFunction: attrFunction,
        });
      }
    }
  }

  HsMapService.loaded().then(init);

  this.setData = function (data, type, overwrite) {
    if (angular.isDefined(type)) {
      if (angular.isDefined(overwrite) && overwrite) {
        me.data[type].length = 0;
      }
      if (angular.isArray(data)) {
        me.data[type] = me.data[type].concat(data);
      } else {
        me.data[type].push(data);
      }
      $rootScope.$broadcast('infopanel.updated'); //Compatibility, deprecated
      $rootScope.$broadcast('query.dataUpdated', me.data);
    } else if (console) {
      console.log('Query.BaseService.setData type not passed');
    }
  };

  this.clearData = function (type) {
    if (type) {
      me.data[type].length = 0;
    } else {
      me.data.attributes.length = 0;
      me.data.features = [];
      me.data.coordinates.length = 0;
      me.data.featureInfoHtmls = [];
      me.data.customFeatures = [];
    }
    const invisiblePopup = me.getInvisiblePopup();
    if (invisiblePopup) {
      invisiblePopup.contentDocument.body.innerHTML = '';
      invisiblePopup.style.height = 0;
      invisiblePopup.style.width = 0;
    }
    me.dataCleared = true;
  };

  this.getInvisiblePopup = function () {
    return document.getElementById('invisible_popup');
  };

  this.pushFeatureInfoHtml = (html) => {
    me.data.featureInfoHtmls.push($sce.trustAsHtml(html));
    me.dataCleared = false;
  };

  this.fillIframeAndResize = function (iframe, response, append) {
    var iframe = me.getInvisiblePopup();
    if (append) {
      iframe.contentDocument.body.innerHTML += response;
    } else {
      iframe.contentDocument.body.innerHTML = response;
    }
    let tmp_width = iframe.contentDocument.innerWidth;
    if (
      tmp_width >
      HsLayoutService.contentWrapper.querySelector('.hs-ol-map').clientWidth -
        60
    ) {
      tmp_width =
        HsLayoutService.contentWrapper.querySelector('.hs-ol-map').clientWidth -
        60;
    }
    iframe.style.width = tmp_width + 'px';
    let tmp_height = iframe.contentDocument.innerHeight;
    if (tmp_height > 700) {
      tmp_height = 700;
    }
    iframe.style.height = tmp_height + 'px';
  };

  /**
   * @param coordinate
   */
  function getCoordinate(coordinate) {
    me.queryPoint.setCoordinates(coordinate, 'XY');
    const epsg4326Coordinate = transform(
      coordinate,
      map.getView().getProjection(),
      'EPSG:4326'
    );
    const coords = {
      name: gettext('Coordinates'),
      mapProjCoordinate: coordinate,
      epsg4326Coordinate,
      projections: [
        {
          'name': 'EPSG:4326',
          'value': toStringHDMS(epsg4326Coordinate),
        },
        {
          'name': 'EPSG:4326',
          'value': createStringXY(7)(epsg4326Coordinate),
        },
        {
          'name': map.getView().getProjection().getCode(),
          'value': createStringXY(7)(coordinate),
        },
      ],
    };
    return coords;
  }

  this.activateQueries = function () {
    if (me.queryActive) {
      return;
    }
    me.queryActive = true;
    HsMapService.loaded().then((map) => {
      map.addLayer(me.queryLayer);
      $rootScope.$broadcast('queryStatusChanged', true);
    });
  };

  this.deactivateQueries = function () {
    if (!me.queryActive) {
      return;
    }
    me.queryActive = false;
    HsMapService.loaded().then((map) => {
      map.removeLayer(me.queryLayer);
      $rootScope.$broadcast('queryStatusChanged', false);
    });
  };

  me.nonQueryablePanels = [
    'measure',
    'composition_browser',
    'analysis',
    'sensors',
  ];

  this.currentPanelQueryable = function () {
    return (
      me.nonQueryablePanels.indexOf(HsLayoutService.mainpanel) == -1 &&
      me.nonQueryablePanels.indexOf('*') == -1
    );
  };

  /**
   * @param feature
   */
  function pointClickedStyle(feature) {
    const defaultStyle = new Style({
      image: new Circle({
        fill: new Fill({
          color: 'rgba(255, 156, 156, 0.4)',
        }),
        stroke: new Stroke({
          color: '#cc3333',
          width: 1,
        }),
        radius: 5,
      }),
    });
    if (angular.isDefined(HsConfig.queryPoint)) {
      if (HsConfig.queryPoint == 'hidden') {
        defaultStyle.getImage().setRadius(0);
      } else if (HsConfig.queryPoint == 'notWithin') {
        if (me.selector.getFeatures().getLength() > 0) {
          defaultStyle.getImage().setRadius(0);
        }
      }
    }
    return defaultStyle;
  }

  if (me.deregisterVectorSelectorCreated) {
    me.deregisterVectorSelectorCreated();
  }
  me.deregisterVectorSelectorCreated = $rootScope.$on(
    'vectorSelectorCreated',
    (e, selector) => {
      me.selector = selector;
    }
  );
  return me;
}
<commit_msg>Configurable popUpDisplay<commit_after>import Feature from 'ol/Feature';
import VectorLayer from 'ol/layer/Vector';
import {Circle, Fill, Stroke, Style} from 'ol/style';
import {Point} from 'ol/geom';
import {Vector} from 'ol/source';
import {createStringXY, toStringHDMS} from 'ol/coordinate';
import {transform} from 'ol/proj';

/**
 * @param $rootScope
 * @param HsMapService
 * @param HsCore
 * @param $sce
 * @param HsConfig
 * @param HsLayoutService
 * @param HsUtilsService
 * @param $timeout
 * @param gettext
 */
export default function (
  $rootScope,
  HsMapService,
  HsCore,
  $sce,
  HsConfig,
  HsLayoutService,
  HsUtilsService,
  $timeout,
  gettext
) {
  'ngInject';
  const me = this;

  let map;

  this.queryPoint = new Point([0, 0]);
  this.queryLayer = new VectorLayer({
    title: 'Point clicked',
    queryable: false,
    source: new Vector({
      features: [
        new Feature({
          geometry: me.queryPoint,
        }),
      ],
    }),
    show_in_manager: false,
    removable: false,
    style: pointClickedStyle,
  });

  this.data = {};
  this.data.attributes = [];
  this.data.features = [];
  this.data.featureInfoHtmls = [];
  this.data.customFeatures = [];
  this.data.coordinates = [];
  this.queryActive = false;
  this.popupClassname = '';
  this.selector = null;
  this.currentQuery = null;
  this.featuresUnderMouse = [];
  this.featureLayersUnderMouse = [];
  this.dataCleared = true;

  /**
   *
   */
  function init() {
    map = HsMapService.map;
    me.activateQueries();
    map.on('singleclick', (evt) => {
      $rootScope.$broadcast(
        'mapClicked',
        angular.extend(evt, {
          coordinates: getCoordinate(evt.coordinate),
        })
      );
      if (!me.queryActive) {
        return;
      }
      me.popupClassname = '';
      if (!me.dataCleared) {
        me.clearData();
      }
      me.dataCleared = false;
      me.currentQuery = (Math.random() + 1).toString(36).substring(7);
      me.setData(getCoordinate(evt.coordinate), 'coordinates', true);
      me.last_coordinate_clicked = evt.coordinate; //It is used in some examples and apps
      $rootScope.$broadcast('mapQueryStarted', evt);
    });

    /**
     * @param e
     */
    function showPopUp(e) {
      if (e.dragging) {
        return;
      }
      const map = e.map;
      $timeout((_) => {
        me.featuresUnderMouse = map.getFeaturesAtPixel(e.pixel);
        if (me.featuresUnderMouse !== null) {
          me.featuresUnderMouse = me.featuresUnderMouse.filter((feature) => {
            return (
              feature.getLayer &&
              feature.getLayer(map) &&
              feature.getLayer(map).get('title').length > 0 &&
              feature.getLayer(map).get('title') !== 'Point clicked'
            );
          });
          me.featureLayersUnderMouse = me.featuresUnderMouse.map((f) =>
            f.getLayer(HsMapService.map)
          );
          me.featureLayersUnderMouse = HsUtilsService.removeDuplicates(
            me.featureLayersUnderMouse,
            'values_.title'
          );
          me.featureLayersUnderMouse = me.featureLayersUnderMouse.map((l) => {
            return {
              layer: l.get('title'),
              features: me.featuresUnderMouse.filter(
                (f) => f.getLayer(HsMapService.map) == l
              ),
            };
          });
          me.featuresUnderMouse.forEach((feature) => {
            serializeFeatureAttributes(feature);
            if (feature.get('features')) {
              feature
                .get('features')
                .forEach((subfeature) =>
                  serializeFeatureAttributes(subfeature)
                );
            }
          });
          const pixel = e.pixel;
          pixel[0] += 2;
          pixel[1] += 4;
          me.hoverPopup.setPosition(map.getCoordinateFromPixel(pixel));
        } else {
          me.featuresUnderMouse = [];
        }
      }, 0);
    }
    if (
      angular.isDefined(HsConfig.popUpDisplay) &&
      HsConfig.popUpDisplay === 'hover'
    ) {
      map.on('pointermove', HsUtilsService.debounce(showPopUp, 500, false, me));
    } else if (
      angular.isDefined(HsConfig.popUpDisplay) &&
      HsConfig.popUpDisplay === 'click'
    ) {
      map.on('singleclick', HsUtilsService.debounce(showPopUp, 500, false, me));
    } /* else none */
  }

  /**
   * @param feature
   */
  function serializeFeatureAttributes(feature) {
    if (angular.isUndefined(feature.getLayer)) {
      return;
    }
    const layer = feature.getLayer(HsMapService.map);
    let attrsConfig = [];
    if (
      angular.isDefined(layer.get('popUp')) &&
      angular.isDefined(layer.get('popUp').attributes)
    ) {
      //must be an array
      attrsConfig = layer.get('popUp').attributes;
    } else if (angular.isDefined(layer.get('hoveredKeys'))) {
      //only for backwards-compatibility with HSLayers 1.10 .. 1.22
      //should be dropped in future releases
      //expected to be an array
      attrsConfig = layer.get('hoveredKeys');
      if (angular.isDefined(layer.get('hoveredKeysTranslations'))) {
        //expected to be an object
        for (const [key, val] of Object.entries(
          layer.get('hoveredKeysTranslations')
        )) {
          const index = attrsConfig.indexOf(key);
          if (index > -1) {
            attrsConfig[index] = {
              'attribute': key,
              'label': val,
            };
          }
        }
      }
    } else {
      // Layer is not configured to show pop-ups
      return;
    }
    feature.attributesForHover = [];
    for (const attr of attrsConfig) {
      let attrName, attrLabel;
      let attrFunction = (x) => x;
      if (typeof attr === 'string' || attr instanceof String) {
        //simple case when only attribute name is provided in the layer config
        attrName = attr;
        attrLabel = attr;
      } else {
        if (angular.isUndefined(attr.attribute)) {
          //implies malformed layer config - 'attribute' is obligatory in this case
          continue;
        }
        attrName = attr.attribute;
        attrLabel = angular.isDefined(attr.label) ? attr.label : attr.attribute;
        if (angular.isDefined(attr.displayFunction)) {
          attrFunction = attr.displayFunction;
        }
      }
      if (angular.isDefined(feature.get(attrName))) {
        feature.attributesForHover.push({
          key: attrLabel,
          value: feature.get(attrName),
          displayFunction: attrFunction,
        });
      }
    }
  }

  HsMapService.loaded().then(init);

  this.setData = function (data, type, overwrite) {
    if (angular.isDefined(type)) {
      if (angular.isDefined(overwrite) && overwrite) {
        me.data[type].length = 0;
      }
      if (angular.isArray(data)) {
        me.data[type] = me.data[type].concat(data);
      } else {
        me.data[type].push(data);
      }
      $rootScope.$broadcast('infopanel.updated'); //Compatibility, deprecated
      $rootScope.$broadcast('query.dataUpdated', me.data);
    } else if (console) {
      console.log('Query.BaseService.setData type not passed');
    }
  };

  this.clearData = function (type) {
    if (type) {
      me.data[type].length = 0;
    } else {
      me.data.attributes.length = 0;
      me.data.features = [];
      me.data.coordinates.length = 0;
      me.data.featureInfoHtmls = [];
      me.data.customFeatures = [];
    }
    const invisiblePopup = me.getInvisiblePopup();
    if (invisiblePopup) {
      invisiblePopup.contentDocument.body.innerHTML = '';
      invisiblePopup.style.height = 0;
      invisiblePopup.style.width = 0;
    }
    me.dataCleared = true;
  };

  this.getInvisiblePopup = function () {
    return document.getElementById('invisible_popup');
  };

  this.pushFeatureInfoHtml = (html) => {
    me.data.featureInfoHtmls.push($sce.trustAsHtml(html));
    me.dataCleared = false;
  };

  this.fillIframeAndResize = function (iframe, response, append) {
    var iframe = me.getInvisiblePopup();
    if (append) {
      iframe.contentDocument.body.innerHTML += response;
    } else {
      iframe.contentDocument.body.innerHTML = response;
    }
    let tmp_width = iframe.contentDocument.innerWidth;
    if (
      tmp_width >
      HsLayoutService.contentWrapper.querySelector('.hs-ol-map').clientWidth -
        60
    ) {
      tmp_width =
        HsLayoutService.contentWrapper.querySelector('.hs-ol-map').clientWidth -
        60;
    }
    iframe.style.width = tmp_width + 'px';
    let tmp_height = iframe.contentDocument.innerHeight;
    if (tmp_height > 700) {
      tmp_height = 700;
    }
    iframe.style.height = tmp_height + 'px';
  };

  /**
   * @param coordinate
   */
  function getCoordinate(coordinate) {
    me.queryPoint.setCoordinates(coordinate, 'XY');
    const epsg4326Coordinate = transform(
      coordinate,
      map.getView().getProjection(),
      'EPSG:4326'
    );
    const coords = {
      name: gettext('Coordinates'),
      mapProjCoordinate: coordinate,
      epsg4326Coordinate,
      projections: [
        {
          'name': 'EPSG:4326',
          'value': toStringHDMS(epsg4326Coordinate),
        },
        {
          'name': 'EPSG:4326',
          'value': createStringXY(7)(epsg4326Coordinate),
        },
        {
          'name': map.getView().getProjection().getCode(),
          'value': createStringXY(7)(coordinate),
        },
      ],
    };
    return coords;
  }

  this.activateQueries = function () {
    if (me.queryActive) {
      return;
    }
    me.queryActive = true;
    HsMapService.loaded().then((map) => {
      map.addLayer(me.queryLayer);
      $rootScope.$broadcast('queryStatusChanged', true);
    });
  };

  this.deactivateQueries = function () {
    if (!me.queryActive) {
      return;
    }
    me.queryActive = false;
    HsMapService.loaded().then((map) => {
      map.removeLayer(me.queryLayer);
      $rootScope.$broadcast('queryStatusChanged', false);
    });
  };

  me.nonQueryablePanels = [
    'measure',
    'composition_browser',
    'analysis',
    'sensors',
  ];

  this.currentPanelQueryable = function () {
    return (
      me.nonQueryablePanels.indexOf(HsLayoutService.mainpanel) == -1 &&
      me.nonQueryablePanels.indexOf('*') == -1
    );
  };

  /**
   * @param feature
   */
  function pointClickedStyle(feature) {
    const defaultStyle = new Style({
      image: new Circle({
        fill: new Fill({
          color: 'rgba(255, 156, 156, 0.4)',
        }),
        stroke: new Stroke({
          color: '#cc3333',
          width: 1,
        }),
        radius: 5,
      }),
    });
    if (angular.isDefined(HsConfig.queryPoint)) {
      if (HsConfig.queryPoint == 'hidden') {
        defaultStyle.getImage().setRadius(0);
      } else if (HsConfig.queryPoint == 'notWithin') {
        if (me.selector.getFeatures().getLength() > 0) {
          defaultStyle.getImage().setRadius(0);
        }
      }
    }
    return defaultStyle;
  }

  if (me.deregisterVectorSelectorCreated) {
    me.deregisterVectorSelectorCreated();
  }
  me.deregisterVectorSelectorCreated = $rootScope.$on(
    'vectorSelectorCreated',
    (e, selector) => {
      me.selector = selector;
    }
  );
  return me;
}
<|endoftext|>


<commit_before>var path  = require('path');
var async = require('async');
var exec  = require("child_process").exec;
var fs    = require("fs");
var url   = require("url");

var log = function log(/*args*/) {
    console.log.apply(console, arguments);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function withDBDo(doFunc) {
    // FIXME
    var db = lively.repository.fs.storage.db;
    doFunc(db ? null : new Error('Cannot access database'), db);
}

function withRecordsDo(queryString, thenDo) {
    var getRecordsQuery;
    try {
        getRecordsQuery = JSON.parse(decodeURIComponent(queryString));
    } catch (e) {
        thenDo(new Error("Error parsing records query:\n" + e), null);
        return;
    }
    if (getRecordsQuery.paths) getRecordsQuery.paths = getRecordsQuery.paths.map(decodeURI);
    lively.repository.getRecords(getRecordsQuery, thenDo);
}

module.exports = function(route, app) {

    app.get(route, function(req, res) {
        var query = url.parse(req.url, true).query;
        if (query.getRecords) {
            withRecordsDo(query.getRecords, function(err, rows) {
                if (err) res.status(400).json({error: String(err)});
                else res.json(rows);
            });
        } else {
            res.status(400).json({error: 'no getRecords query found'});
        }
    });

    app.get(route + 'diff', function(req, res) {
        // a prototypical diff implementation. Needs cleanup and extraction
        var err, query = req.query;
        if (!query.getRecordsA) {
            res.status(400).json({error: 'Need query.getRecordsA!'});
        } else if (!query.getRecordsB) {
            res.status(400).json({error: 'Need query.getRecordsB!'});
        } else {
            var isJSON = query.isJSON === 'true';
            var isLivelyWorld = query.isLivelyWorld === 'true';

            async.parallel([
                function(next) { withRecordsDo(query.getRecordsA, next); },
                function(next) { withRecordsDo(query.getRecordsB, next); }
            ], function(err, results) {
                err && console.error(err);
                if (err) res.status(400).json({error: String(err)})
                var a = results[0][0], b = results[1][0];
                if (!a || !a.content || !b || !b.content) {
                    res.status(400).json({error: "query result not diffable!"});
                    return;
                }

                var contentA = a.content;
                var contentB = b.content;

                if (isLivelyWorld) {
                    var roughly = contentA.slice(contentA.indexOf('<script type="text/x-lively-world"')+6, contentA.lastIndexOf("</script>"));
                    contentA = roughly.slice(roughly.indexOf('{'));
                    var roughly = contentB.slice(contentB.indexOf('<script type="text/x-lively-world"')+6, contentB.lastIndexOf("</script>"));
                    contentB = roughly.slice(roughly.indexOf('{'));
                }

                if (isJSON) {
                    try { contentA = JSON.stringify(JSON.parse(contentA), null, 2); } catch (e) { console.log('Cannot parse content a: ' + e + '\n' + contentA.slice(0,250)); }
                    try { contentB = JSON.stringify(JSON.parse(contentB), null, 2); } catch (e) { console.log('Cannot parse content b: ' + e + '\n' + contentB.slice(0,250)); }
                }

                var diffResult = 'nothing yet';
                async.series([
                    function(next) { exec('mkdir -p diff-tmp/', next); },
                    function(next) { fs.writeFile("diff-tmp/a", contentA, next); },
                    function(next) { fs.writeFile("diff-tmp/b", contentB, next); },
                    function(next) {
                        exec('git diff --no-index --histogram diff-tmp/a diff-tmp/b',
                        {maxBuffer: 10000*1024},
                        function(code, out, err) {
                            if (!out && code) { next(new Error("Diff error: " + code + ' ' + err)); }
                            else { diffResult = out +'\n' + err; next(); }
                        });
                    },
                    function(next) { exec('rm -rfd diff-tmp/', next); }
                ], function(err) {
                    if (err) {
                        console.error(err);
                        res.status(400).json({error: String(err)});
                    } else res.json({diff: diffResult});
                });
            })
        }
    });

}

module.exports.withDBDo = withDBDo;
<commit_msg>ObjectRepositoryServer: ensuring query parse<commit_after>var path  = require('path');
var async = require('async');
var exec  = require("child_process").exec;
var fs    = require("fs");
var url   = require("url");

var log = function log(/*args*/) {
    console.log.apply(console, arguments);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function withDBDo(doFunc) {
    // FIXME
    var db = lively.repository.fs.storage.db;
    doFunc(db ? null : new Error('Cannot access database'), db);
}

function withRecordsDo(queryString, thenDo) {
    var getRecordsQuery;
    try {
        getRecordsQuery = JSON.parse(decodeURIComponent(queryString));
    } catch (e) {
        thenDo(new Error("Error parsing records query:\n" + e), null);
        return;
    }
    if (getRecordsQuery.paths) getRecordsQuery.paths = getRecordsQuery.paths.map(decodeURI);
    lively.repository.getRecords(getRecordsQuery, thenDo);
}

module.exports = function(route, app) {

    app.get(route, function(req, res) {
        var query = url.parse(req.url, true).query;
        if (query.getRecords) {
            withRecordsDo(query.getRecords, function(err, rows) {
                if (err) res.status(400).json({error: String(err)});
                else res.json(rows);
            });
        } else {
            res.status(400).json({error: 'no getRecords query found'});
        }
    });

    app.get(route + 'diff', function(req, res) {
        // a prototypical diff implementation. Needs cleanup and extraction
        var err, query = url.parse(req.url, true).query;
        if (!query.getRecordsA) {
            res.status(400).json({error: 'Need query.getRecordsA!'});
        } else if (!query.getRecordsB) {
            res.status(400).json({error: 'Need query.getRecordsB!'});
        } else {
            var isJSON = query.isJSON === 'true';
            var isLivelyWorld = query.isLivelyWorld === 'true';

            async.parallel([
                function(next) { withRecordsDo(query.getRecordsA, next); },
                function(next) { withRecordsDo(query.getRecordsB, next); }
            ], function(err, results) {
                err && console.error(err);
                if (err) res.status(400).json({error: String(err)})
                var a = results[0][0], b = results[1][0];
                if (!a || !a.content || !b || !b.content) {
                    res.status(400).json({error: "query result not diffable!"});
                    return;
                }

                var contentA = a.content;
                var contentB = b.content;

                if (isLivelyWorld) {
                    var roughly = contentA.slice(contentA.indexOf('<script type="text/x-lively-world"')+6, contentA.lastIndexOf("</script>"));
                    contentA = roughly.slice(roughly.indexOf('{'));
                    var roughly = contentB.slice(contentB.indexOf('<script type="text/x-lively-world"')+6, contentB.lastIndexOf("</script>"));
                    contentB = roughly.slice(roughly.indexOf('{'));
                }

                if (isJSON) {
                    try { contentA = JSON.stringify(JSON.parse(contentA), null, 2); } catch (e) { console.log('Cannot parse content a: ' + e + '\n' + contentA.slice(0,250)); }
                    try { contentB = JSON.stringify(JSON.parse(contentB), null, 2); } catch (e) { console.log('Cannot parse content b: ' + e + '\n' + contentB.slice(0,250)); }
                }

                var diffResult = 'nothing yet';
                async.series([
                    function(next) { exec('mkdir -p diff-tmp/', next); },
                    function(next) { fs.writeFile("diff-tmp/a", contentA, next); },
                    function(next) { fs.writeFile("diff-tmp/b", contentB, next); },
                    function(next) {
                        exec('git diff --no-index --histogram diff-tmp/a diff-tmp/b',
                        {maxBuffer: 10000*1024},
                        function(code, out, err) {
                            if (!out && code) { next(new Error("Diff error: " + code + ' ' + err)); }
                            else { diffResult = out +'\n' + err; next(); }
                        });
                    },
                    function(next) { exec('rm -rfd diff-tmp/', next); }
                ], function(err) {
                    if (err) {
                        console.error(err);
                        res.status(400).json({error: String(err)});
                    } else res.json({diff: diffResult});
                });
            })
        }
    });

}

module.exports.withDBDo = withDBDo;
<|endoftext|>


<commit_before>var currentLoginUserObj;
var currentLoginUsername;
var currentLoginUsernameFull;
$(document).ready(function () {})
firebase.auth().onAuthStateChanged(function (user) {
    if (user) {
        currentLoginUserObj = user;
        currentLoginUsernameFull = user.uid;
        getCurrentUsername();
    }
});

function getCurrentUsername() {
    firebase.database().ref('usernames/' + currentLoginUserObj.uid).once('value').then(function (snapshot) {
        currentLoginUsername = snapshot.val().username;
        currentLoginUsernameFull = currentLoginUserObj.uid;
        addUserToMemberList();
    });
}
//Get window height for scrolling of chat box
var windowHeight = $(window).height();
$('#chat-ul').css("max-height", windowHeight - 175);
$('#questions-tab').css("max-height", windowHeight - 80);
/*console.log($('#chat-ul').length);
if ($('#chat-ul').children().length === 0) {
    writeChatData("Welcome to 20 Questions. People will be able to join this room with the code: " + roomName + '.', "System");
}*/
//alert("Welcome to 20 Questions. People will be able to join this room with the code: " + roomName + '.');
function addUserToMemberList() {
    var userRef = firebase.database().ref("/rooms/" + roomName + "/members/" + currentLoginUsername);
    userRef.once('value', function (snapshot) {
            console.log(snapshot.val());
            if (snapshot.val() == "answer") {
                $("#ask-tab").addClass("hidden");
            }
            else if (!snapshot.val() || snapshot.val() == "ask") {
                userRef.set("ask");
                $("#answer-tab").addClass("hidden");
                listenForQuestionsToAnswer();
            }
        })
        //updateMembersList();
}
/*
function updateMembersList() {
	firebase.database().ref('rooms/' + roomName + "/members").once('value').then(function (snapshot) {
		playersList = snapshot.val();
	}).then(function () {
		for (var player in playersList) {
			addPlayer(player);
		}
	});
}
*/
function showNextQuestion() {
    console.log("called")
    if (questionsToAnswer.length > 0) {
        $('.answer-question').text(questionsToAnswer[0].question);
        $('.answer-question').attr("id", questionsToAnswer[0].id);
    }
    else {
        $('#answer-choices').addClass('hidden');
        $('.answer-question').text("No questions right now");
    }
}

function sendQuestionResponse(val) {
    var response = "";
    var gameFinished = false;
    switch (val) {
    case 0:
        response = "done";
        break;
    case 1:
        response = "clear";
        break;
    case 2:
        response = "done";
        gameFinished = true;
        break;
    }
    console.log(response);
    var qId = $('.answer-question').attr("id");
    firebase.database().ref('/questions/' + roomName + "/" + questionsToAnswer[0].id).update({
        status: response
    }).then(function () {
        questionsToAnswer.splice(0, 1);
        console.log("new questionsToAnswer", questionsToAnswer);
        if (gameFinished) {
            writeChatData("Congrats, you got it!", "System");
        }
        else {
            showNextQuestion();
        }
    })
}
var questionsToAnswer = [];

function listenForQuestionsToAnswer() {
    firebase.database().ref('questions/' + roomName).orderByChild('status').equalTo("help").on('child_added', function (snapshot) {
        console.log(snapshot.key);
        var myObj = snapshot.val();
        myObj.id = snapshot.key;
        questionsToAnswer.push(myObj);
        console.log(questionsToAnswer);
        console.log("query result", snapshot.val());
        $('#answer-choices').removeClass('hidden');
        showNextQuestion();
    })
}
firebase.database().ref('questions/' + roomName).on('child_changed', function (snapshot) {
    console.log("li#" + snapshot.key + " > i");
    $("li#" + snapshot.key + " > i").text(snapshot.val().status);
    if (snapshot.val().status == "done") {
        $("li#" + snapshot.key + " > i").addClass("right");
    }
    else if (snapshot.val().status == "clear") {
        $("li#" + snapshot.key + " > i").addClass("wrong");
    }
});
//Adds data to actual html
function playerDataAddFunction(snapshot) {
    if (snapshot.val() == "ask") {
        console.log("You are in ask");
        $("#players-ul").append('
  person' + snapshot.key + '
');
    }
    else if (snapshot.val() == "answer") {
        console.log("You are in answer");
        $("#players-ul").prepend('
  star rate' + snapshot.key + '
');
        listenForQuestionsToAnswer();
    }
}
var playerDataAdder = firebase.database().ref("/rooms/" + roomName + "/members");
playerDataAdder.on('child_added', function (snapshot) {
    playerDataAddFunction(snapshot);
    //$('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
});
/*
var playersList;
function addPlayer(player) {
	firebase.database().ref('usernames/' + player).once('value').then(function (snapshot) {
		var username = snapshot.val().username;
		if (playersList[player] == "ask") {
			$("#players-ul").append('
  person' + username + '
');
		} else if (playersList[player] == "answer") {
			$("#players-ul").prepend('
  star rate' + username + '
');
		}
	})
}
*/
//All Below edits chat data
var chatUL = $('#chat-ul');
//Adds data to actual html
function chatDataAddFunction(snapshot) {
    chatUL.append('
 ' + snapshot.sender + ": " + snapshot.message + '
');
}
//Takes data from firebase and call function above
var chatDataAdder = firebase.database().ref('chats/' + roomName);
chatDataAdder.on('child_added', function (snapshot) {
    chatDataAddFunction(snapshot.val());
    chatUL.scrollTop(chatUL.prop("scrollHeight"));
});
//Function called to write chat data to firebase
function writeChatData(message, sender) {
    firebase.database().ref('chats/' + roomName).push({
        message: message
        , sender: sender
        , timestamp: firebase.database.ServerValue.TIMESTAMP
    });
}
//Adds data if current user types
$('#chat-input').keydown(function (event) {
    if (event.keyCode == 13) {
        if ($('#chat-input').val() != "") {
            writeChatData($('#chat-input').val(), currentLoginUsername);
            $('#chat-input').val('');
            chatUL.scrollTop(chatUL.prop("scrollHeight"));
        }
    }
});
//All Below edits question data
var questionUL = $('#questions-ul');
//Adds data to actual html
function questionDataAddFunction(snapshot) {
    questionUL.append('
' + snapshot.val().question + ' ' + snapshot.val().status + '
')
    if (snapshot.val().status == "done") {
        $("li#" + snapshot.key + " > i").addClass("right");
    }
    else if (snapshot.val().status == "clear") {
        $("li#" + snapshot.key + " > i").addClass("wrong");
    }
    //$("#answer-question").empty().append(snapshot.question);
}
//Takes data from firebase and call function above
var questionDataAdder = firebase.database().ref('questions/' + roomName);
questionDataAdder.on('child_added', function (snapshot) {
    questionDataAddFunction(snapshot);
    $('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
});
//Function called to write question data to firebase
function writeQuestionData(question, sender, status) {
    firebase.database().ref('questions/' + roomName).push({
        question: question
        , sender: sender
        , status: status
        , timestamp: firebase.database.ServerValue.TIMESTAMP
    });
}
//Adds data if current user types
$("#question-input").keydown(function (event) {
    if (event.keyCode == 13) {
        if ($("#question-input").val() != "") {
            writeQuestionData($("#question-input").val(), currentLoginUsername, 'help');
            $("#question-input").val('');
            $('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
        }
    }
});<commit_msg>Change correct answer message<commit_after>var currentLoginUserObj;
var currentLoginUsername;
var currentLoginUsernameFull;
$(document).ready(function () {})
firebase.auth().onAuthStateChanged(function (user) {
    if (user) {
        currentLoginUserObj = user;
        currentLoginUsernameFull = user.uid;
        getCurrentUsername();
    }
});

function getCurrentUsername() {
    firebase.database().ref('usernames/' + currentLoginUserObj.uid).once('value').then(function (snapshot) {
        currentLoginUsername = snapshot.val().username;
        currentLoginUsernameFull = currentLoginUserObj.uid;
        addUserToMemberList();
    });
}
//Get window height for scrolling of chat box
var windowHeight = $(window).height();
$('#chat-ul').css("max-height", windowHeight - 175);
$('#questions-tab').css("max-height", windowHeight - 80);
/*console.log($('#chat-ul').length);
if ($('#chat-ul').children().length === 0) {
    writeChatData("Welcome to 20 Questions. People will be able to join this room with the code: " + roomName + '.', "System");
}*/
//alert("Welcome to 20 Questions. People will be able to join this room with the code: " + roomName + '.');
function addUserToMemberList() {
    var userRef = firebase.database().ref("/rooms/" + roomName + "/members/" + currentLoginUsername);
    userRef.once('value', function (snapshot) {
            console.log(snapshot.val());
            if (snapshot.val() == "answer") {
                $("#ask-tab").addClass("hidden");
            }
            else if (!snapshot.val() || snapshot.val() == "ask") {
                userRef.set("ask");
                $("#answer-tab").addClass("hidden");
                listenForQuestionsToAnswer();
            }
        })
        //updateMembersList();
}
/*
function updateMembersList() {
	firebase.database().ref('rooms/' + roomName + "/members").once('value').then(function (snapshot) {
		playersList = snapshot.val();
	}).then(function () {
		for (var player in playersList) {
			addPlayer(player);
		}
	});
}
*/
function showNextQuestion() {
    console.log("called")
    if (questionsToAnswer.length > 0) {
        $('.answer-question').text(questionsToAnswer[0].question);
        $('.answer-question').attr("id", questionsToAnswer[0].id);
    }
    else {
        $('#answer-choices').addClass('hidden');
        $('.answer-question').text("No questions right now");
    }
}

function sendQuestionResponse(val) {
    var response = "";
    var gameFinished = false;
    switch (val) {
    case 0:
        response = "done";
        break;
    case 1:
        response = "clear";
        break;
    case 2:
        response = "done";
        gameFinished = true;
        break;
    }
    console.log(response);
    var qId = $('.answer-question').attr("id");
    firebase.database().ref('/questions/' + roomName + "/" + questionsToAnswer[0].id).update({
        status: response
    }).then(function () {
        questionsToAnswer.splice(0, 1);
        console.log("new questionsToAnswer", questionsToAnswer);
        if (gameFinished) {
            writeChatData("Congrats, you got it! Create a new game", "System");
        }
        else {
            showNextQuestion();
        }
    })
}
var questionsToAnswer = [];

function listenForQuestionsToAnswer() {
    firebase.database().ref('questions/' + roomName).orderByChild('status').equalTo("help").on('child_added', function (snapshot) {
        console.log(snapshot.key);
        var myObj = snapshot.val();
        myObj.id = snapshot.key;
        questionsToAnswer.push(myObj);
        console.log(questionsToAnswer);
        console.log("query result", snapshot.val());
        $('#answer-choices').removeClass('hidden');
        showNextQuestion();
    })
}
firebase.database().ref('questions/' + roomName).on('child_changed', function (snapshot) {
    console.log("li#" + snapshot.key + " > i");
    $("li#" + snapshot.key + " > i").text(snapshot.val().status);
    if (snapshot.val().status == "done") {
        $("li#" + snapshot.key + " > i").addClass("right");
    }
    else if (snapshot.val().status == "clear") {
        $("li#" + snapshot.key + " > i").addClass("wrong");
    }
});
//Adds data to actual html
function playerDataAddFunction(snapshot) {
    if (snapshot.val() == "ask") {
        console.log("You are in ask");
        $("#players-ul").append('
  person' + snapshot.key + '
');
    }
    else if (snapshot.val() == "answer") {
        console.log("You are in answer");
        $("#players-ul").prepend('
  star rate' + snapshot.key + '
');
        listenForQuestionsToAnswer();
    }
}
var playerDataAdder = firebase.database().ref("/rooms/" + roomName + "/members");
playerDataAdder.on('child_added', function (snapshot) {
    playerDataAddFunction(snapshot);
    //$('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
});
/*
var playersList;
function addPlayer(player) {
	firebase.database().ref('usernames/' + player).once('value').then(function (snapshot) {
		var username = snapshot.val().username;
		if (playersList[player] == "ask") {
			$("#players-ul").append('
  person' + username + '
');
		} else if (playersList[player] == "answer") {
			$("#players-ul").prepend('
  star rate' + username + '
');
		}
	})
}
*/
//All Below edits chat data
var chatUL = $('#chat-ul');
//Adds data to actual html
function chatDataAddFunction(snapshot) {
    chatUL.append('
 ' + snapshot.sender + ": " + snapshot.message + '
');
}
//Takes data from firebase and call function above
var chatDataAdder = firebase.database().ref('chats/' + roomName);
chatDataAdder.on('child_added', function (snapshot) {
    chatDataAddFunction(snapshot.val());
    chatUL.scrollTop(chatUL.prop("scrollHeight"));
});
//Function called to write chat data to firebase
function writeChatData(message, sender) {
    firebase.database().ref('chats/' + roomName).push({
        message: message
        , sender: sender
        , timestamp: firebase.database.ServerValue.TIMESTAMP
    });
}
//Adds data if current user types
$('#chat-input').keydown(function (event) {
    if (event.keyCode == 13) {
        if ($('#chat-input').val() != "") {
            writeChatData($('#chat-input').val(), currentLoginUsername);
            $('#chat-input').val('');
            chatUL.scrollTop(chatUL.prop("scrollHeight"));
        }
    }
});
//All Below edits question data
var questionUL = $('#questions-ul');
//Adds data to actual html
function questionDataAddFunction(snapshot) {
    questionUL.append('
' + snapshot.val().question + ' ' + snapshot.val().status + '
')
    if (snapshot.val().status == "done") {
        $("li#" + snapshot.key + " > i").addClass("right");
    }
    else if (snapshot.val().status == "clear") {
        $("li#" + snapshot.key + " > i").addClass("wrong");
    }
    //$("#answer-question").empty().append(snapshot.question);
}
//Takes data from firebase and call function above
var questionDataAdder = firebase.database().ref('questions/' + roomName);
questionDataAdder.on('child_added', function (snapshot) {
    questionDataAddFunction(snapshot);
    $('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
});
//Function called to write question data to firebase
function writeQuestionData(question, sender, status) {
    firebase.database().ref('questions/' + roomName).push({
        question: question
        , sender: sender
        , status: status
        , timestamp: firebase.database.ServerValue.TIMESTAMP
    });
}
//Adds data if current user types
$("#question-input").keydown(function (event) {
    if (event.keyCode == 13) {
        if ($("#question-input").val() != "") {
            writeQuestionData($("#question-input").val(), currentLoginUsername, 'help');
            $("#question-input").val('');
            $('#questions-tab').scrollTop($('#questions-tab').prop("scrollHeight"));
        }
    }
});<|endoftext|>


<commit_before>var portfolio = portfolio || {};

(function(app){
  var repos = {};

  repos.repoTemplate = Handlebars.compile($('#repo-template').html());

  repos.fetchData = function(){
    // $.ajax({
    //   url:'https://api.github.com/users/desdemonhu/repos',
    //   method:'GET',
    //   headers: {
    //     'Authorization': `token ${process.env.GITHUB_TOKEN}`
    //   }
    // })
    $.get('/github/users/codefellows/repos')
    .then(results =>{
      var modifiedResults = results.sort(function(a,b){
        let aDate = new Date(a['updated_at']);
        let bDate = new Date(b['updated_at']);
        return bDate - aDate;
      }).reduce(function(acc, value, index){
        if(index < 5){
          acc.push(value);
        }
        return acc;
      },[]);
      modifiedResults.forEach(repo =>{
        $('#repos').append(repos.repoTemplate(repo));
      })
    }, err =>{console.log(err);
    });
  }
  app.repos = repos;
})(portfolio);
<commit_msg>Nothing new<commit_after>var portfolio = portfolio || {};

(function(app){
  var repos = {};

  repos.repoTemplate = Handlebars.compile($('#repo-template').html());

  repos.fetchData = function(){
    // $.ajax({
    //   url:'https://api.github.com/users/desdemonhu/repos',
    //   method:'GET',
    //   headers: {
    //     'Authorization': `token ${process.env.GITHUB_TOKEN}`
    //   }
    // })
    $.get('/github/users/desdemonhu/repos')
    .then(results =>{
      var modifiedResults = results.sort(function(a,b){
        let aDate = new Date(a['updated_at']);
        let bDate = new Date(b['updated_at']);
        return bDate - aDate;
      }).reduce(function(acc, value, index){
        if(index < 5){
          acc.push(value);
        }
        return acc;
      },[]);
      modifiedResults.forEach(repo =>{
        $('#repos').append(repos.repoTemplate(repo));
      })
    }, err =>{console.log(err);
    });
  }
  app.repos = repos;
})(portfolio);
<|endoftext|>


<commit_before>var url = require('url');
var net = require('net');
var https = require('https');
var http = require('http');
var util = require('../lib/util');

function request(req, res, port, weinre) {
	var options = url.parse(util.getFullUrl(req));
	if (options.protocol == 'https:') {
		options.protocol = 'http:';
		req.headers['x-whistle-https'] = 'true';
	}
	options.host = '127.0.0.1';
	options.method = req.method;
	options.hostname = null;
	options.protocol = null;
	if (port) {
		options.port = port;
	}
	req.headers['x-forwarded-for'] = util.getClientIp(req);
	options.headers = req.headers;
	req.pipe(http.request(options, function(_res) {
		if (weinre && options.pathname == '/target/target-script-min.js') {
			_res.headers['access-control-allow-origin'] = '*';
		}
		res.writeHead(_res.statusCode || 0, _res.headers);
		res.src(_res);
	}));
}

function response(req, res, statusCode, msg) {
	res.writeHead(statusCode || 404, {
    	'content-type': 'text/html; charset=utf-8'
    });
	res.src(util.wrapResponse({
				body: msg || 'Not Found'
			}));
}

module.exports = function(req, res, next) {
	var host = req.headers.host || '';
	var config = this.config;
	var hostname = host.split(':');
	var port = hostname[1] || 80
	hostname = hostname[0];
	if (net.isIP(hostname) && util.isLocalAddress(hostname)) {
		if (port == config.port || port == config.uiport) {
			host = config.localUIHost;
		} else if (port == config.weinreport) {
			host = config.WEINRE_HOST;
		}
	}

	var pluginMgr = this.pluginMgr;
	var homePage;
	if (host == config.localUIHost) {
		request(req, res, config.uiport);
	} else if (host == config.WEINRE_HOST) {
		request(req, res, config.weinreport, true);
	} else if (homePage = pluginMgr.getPluginFromHomePage(util.getFullUrl(req))) {
		pluginMgr.loadPlugin(homePage, function(err, ports) {
			if (err) {
				response(req, res, 503, err);
				return;
			}

			if (!ports.uiPort) {
				response(req, res);
				return;
			}

			request(req, res, ports.uiPort);
		});
	} else {
		next();
	}
};
<commit_msg>refine code<commit_after>var url = require('url');
var net = require('net');
var https = require('https');
var http = require('http');
var util = require('../lib/util');

function request(req, res, port, weinre) {
	var options = url.parse(util.getFullUrl(req));
	if (options.protocol == 'https:') {
		options.protocol = 'http:';
		req.headers['x-whistle-https'] = 'true';
	}
	options.host = '127.0.0.1';
	options.method = req.method;
	options.hostname = null;
	options.protocol = null;
	if (port) {
		options.port = port;
	}
	req.headers['x-forwarded-for'] = util.getClientIp(req);
	options.headers = req.headers;
	req.pipe(http.request(options, function(_res) {
		if (weinre && options.pathname == '/target/target-script-min.js') {
			_res.headers['access-control-allow-origin'] = '*';
		}
		res.writeHead(_res.statusCode || 0, _res.headers);
		res.src(_res);
	}));
}

function response(req, res, statusCode, msg) {
	res.writeHead(statusCode || 404, {
    	'content-type': 'text/html; charset=utf-8'
    });
	res.src(util.wrapResponse({
				body: msg || 'Not Found'
			}));
}

module.exports = function(req, res, next) {
	var host = req.headers.host || '';
	var config = this.config;
	var hostname = host.split(':');
	var port = hostname[1] || 80
	hostname = hostname[0];
	if (net.isIP(hostname) && util.isLocalAddress(hostname)) {
		if (port == config.port || port == config.uiport) {
			host = config.localUIHost;
		} else if (port == config.weinreport) {
			host = config.WEINRE_HOST;
		}
	}

	var pluginMgr = this.pluginMgr;
	var pluginHomePage;
	if (host == config.localUIHost) {
		request(req, res, config.uiport);
	} else if (host == config.WEINRE_HOST) {
		request(req, res, config.weinreport, true);
	} else if (pluginHomePage = pluginMgr.getPluginFromHomePage(util.getFullUrl(req))) {
		pluginMgr.loadPlugin(pluginHomePage, function(err, ports) {
			if (err) {
				response(req, res, 503, err);
				return;
			}

			if (!ports.uiPort) {
				response(req, res);
				return;
			}

			request(req, res, ports.uiPort);
		});
	} else {
		next();
	}
};
<|endoftext|>


<commit_before>// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');
const jasmineReporters = require('jasmine-reporters')
var HTMLReport = require('protractor-html-reporter')
var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');

exports.config = {
  suites: {
    all: './e2e/specs/index.ts',
    auth: './e2e/specs/auth/auth.ts'
  },
  capabilities: {
    'browserName': 'chrome',
    chromeOptions: {
      args: ["--headless", "--disable-gpu", "--window-size=1920,1080" ]
      //args: ["--window-size=1600,1000"]
    }
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  allScriptsTimeout: 220000,
  getPageTimeout: 70000,
  jasmineNodeOpts: {
    showTiming: true,
    showColors: true,
    includeStackTrace: true,
    defaultTimeoutInterval: 220000,
    print: function() {}
  },
  onPrepare() {
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });

    //HTML report
    jasmine.getEnv().addReporter(new Jasmine2HtmlReporter({
      takeScreenshots: true,
      takeScreenshotsOnlyOnFailures: true,
      consolidateAll: true,
      savePath: './e2e/reports/',
      filePrefix: 'html-report'
    }));

    jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
      consolidateAll: true,
      savePath: './e2e/reports',
      filePrefix: 'xmlresults'
    }))

    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  },

  //HTMLReport called once tests are finished
  onComplete: function() {
    console.log('FINISHED: creating xml report');
    var browserName, browserVersion;
    var capsPromise = browser.getCapabilities();

    capsPromise.then(function (caps) {
      browserName = caps.get('browserName');
      browserVersion = caps.get('version');

      testConfig = {
        reportTitle: 'Opsdirector-Test Execution Report',
        outputPath: './e2e/reports/',
        screenshotPath: 'screenshots',
        testBrowser: browserName,
        browserVersion: browserVersion,
        modifiedSuiteName: false,
        screenshotsOnlyOnFailure: true
      };
      new HTMLReport().from('./e2e/reports/xmlresults.xml', testConfig);
    });
  },

  useAllAngular2AppRoots: true
};
<commit_msg>go non headless and change the window size<commit_after>// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');
const jasmineReporters = require('jasmine-reporters')
var HTMLReport = require('protractor-html-reporter')
var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');

exports.config = {
  suites: {
    all: './e2e/specs/index.ts',
    auth: './e2e/specs/auth/auth.ts'
  },
  capabilities: {
    'browserName': 'chrome',
    chromeOptions: {
      //args: ["--headless", "--disable-gpu", "--window-size=1920,1080" ]
      args: ["--window-size=1920,1080"]
    }
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  allScriptsTimeout: 220000,
  getPageTimeout: 70000,
  jasmineNodeOpts: {
    showTiming: true,
    showColors: true,
    includeStackTrace: true,
    defaultTimeoutInterval: 220000,
    print: function() {}
  },
  onPrepare() {
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });

    //HTML report
    jasmine.getEnv().addReporter(new Jasmine2HtmlReporter({
      takeScreenshots: true,
      takeScreenshotsOnlyOnFailures: true,
      consolidateAll: true,
      savePath: './e2e/reports/',
      filePrefix: 'html-report'
    }));

    jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
      consolidateAll: true,
      savePath: './e2e/reports',
      filePrefix: 'xmlresults'
    }))

    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  },

  //HTMLReport called once tests are finished
  onComplete: function() {
    console.log('FINISHED: creating xml report');
    var browserName, browserVersion;
    var capsPromise = browser.getCapabilities();

    capsPromise.then(function (caps) {
      browserName = caps.get('browserName');
      browserVersion = caps.get('version');

      testConfig = {
        reportTitle: 'Opsdirector-Test Execution Report',
        outputPath: './e2e/reports/',
        screenshotPath: 'screenshots',
        testBrowser: browserName,
        browserVersion: browserVersion,
        modifiedSuiteName: false,
        screenshotsOnlyOnFailure: true
      };
      new HTMLReport().from('./e2e/reports/xmlresults.xml', testConfig);
    });
  },

  useAllAngular2AppRoots: true
};
<|endoftext|>


<commit_before>$(function() {

    var options = {
        'tr_selected_class': 'table-tr-selected-class',
        'state_disable_class': 'toolbar-button__item_state_disable',
        'table_checkboxes': 'input[name="selected_item"]',
        'table_checkboxes_checked': 'input[name="selected_item"]:checked',
        'input_selected_action': 'input[name="selected_action"]',
        'div_action_button': '.action_button',
    };

    $('table > tbody').selectable({
        // filter: ':not(td)',
        filter: 'tr',
        cancel: 'a, input',
        selected: function (event, ui) {
            $(ui.selected).addClass(options.tr_selected_class);
            $(ui.selected).find(options.table_checkboxes).prop('checked', true).change();
            // console.log(ui.selected);
            // console.log($(this).data('uiSelectable').selectees.filter('.ui-selected'));
        },
        unselected: function (event, ui) {
            $(ui.unselected).removeClass(options.tr_selected_class);
            $(ui.unselected).find(options.table_checkboxes).prop('checked', false).change();
        },
    });

    function change_button () {
        if ($(options.table_checkboxes_checked).length) {
            $('.'+options.state_disable_class).removeClass(options.state_disable_class);
        } else {
            $(options.div_action_button).addClass(options.state_disable_class);
        }
    }

    function check_checkbox (checkbox) {
        var $parent_tr = checkbox.parents('.sacrud-grid-content-grid__body-row');
        if (checkbox.prop('checked')) {
            $parent_tr.addClass(options.tr_selected_class);
            $parent_tr.addClass('ui-selected');
        } else {
            $parent_tr.removeClass(options.tr_selected_class);
            $parent_tr.removeClass('ui-selected');
        }
    }

    $(options.table_checkboxes_checked).each(function (){
        check_checkbox($(this));
    });

    change_button();

    $(document).on('change', options.table_checkboxes , function () {
        check_checkbox($(this));
        change_button();
    });

    $(document).on('click', '.'+options.state_disable_class , function (event) {
        event.stopImmediatePropagation();
    });

    $(document).on('change', '#selected_all_item' , function () {
        $(options.table_checkboxes).prop('checked', $(this).prop('checked')).change();
    });

    $(document).on('click', options.div_action_button, function () {
        $(options.input_selected_action).val($(this).data('status'));
        $('#sacrud-form').submit();
    });
});
<commit_msg>fix select all checkboxes<commit_after>$(function() {

    var options = {
        'tr_selected_class': 'table-tr-selected-class',
        'state_disable_class': 'toolbar-button__item_state_disable',
        'all_checkboxes_button': '#selected_all_item',
        'table_checkboxes': 'input[name="selected_item"]',
        'table_checkboxes_checked': 'input[name="selected_item"]:checked',
        'input_selected_action': 'input[name="selected_action"]',
        'div_action_button': '.action_button',
    };

    $('table > tbody').selectable({
        // filter: ':not(td)',
        filter: 'tr',
        cancel: 'a, input',
        selected: function (event, ui) {
            $(ui.selected).addClass(options.tr_selected_class);
            $(ui.selected).find(options.table_checkboxes).prop('checked', true).change();
            $(options.all_checkboxes_button).prop('checked', false);
            // console.log(ui.selected);
            // console.log($(this).data('uiSelectable').selectees.filter('.ui-selected'));
        },
        unselected: function (event, ui) {
            $(ui.unselected).removeClass(options.tr_selected_class);
            $(ui.unselected).find(options.table_checkboxes).prop('checked', false).change();
        },
    });

    function change_buttons () {
        if ($(options.table_checkboxes_checked).length) {
            $('.'+options.state_disable_class).removeClass(options.state_disable_class);
        } else {
            $(options.div_action_button).addClass(options.state_disable_class);
            $(options.all_checkboxes_button).prop('checked', false);
        }
    }

    function check_checkbox (checkbox) {
        var $parent_tr = checkbox.parents('.sacrud-grid-content-grid__body-row');
        if (checkbox.prop('checked')) {
            $parent_tr.addClass(options.tr_selected_class);
            $parent_tr.addClass('ui-selected');
        } else {
            $parent_tr.removeClass(options.tr_selected_class);
            $parent_tr.removeClass('ui-selected');
        }
    }

    $(options.table_checkboxes_checked).each(function (){
        check_checkbox($(this));
    });

    change_buttons();

    $(document).on('change', options.table_checkboxes , function () {
        check_checkbox($(this));
        change_buttons();
    });

    $(document).on('click', '.'+options.state_disable_class , function (event) {
        event.stopImmediatePropagation();
    });

    $(document).on('change', options.all_checkboxes_button , function () {
        $(options.table_checkboxes).prop('checked', $(this).prop('checked')).change();
    });

    $(document).on('click', options.div_action_button, function () {
        $(options.input_selected_action).val($(this).data('status'));
        $('#sacrud-form').submit();
    });
});
<|endoftext|>


<commit_before>goog.provide('my.LineRing');

goog.require('og.scene.RenderNode');
goog.require('og.inheritance');

goog.require('og.EntityCollection');
goog.require('og.Entity');
goog.require('og.Label');
goog.require('og.LonLat');
goog.require('og.Extent');

function getIntersection(start1, end1, start2, end2) {
    if (!start1.equal(start2)) {
        var dir = end2.sub(start2);
        var perp = new og.math.Vector2(-dir.y, dir.x);
        var d2 = perp.dot(start2);
        var seg = perp.dot(start1) - d2;
        var u = seg / (seg - perp.dot(end1) + d2);
        return start1.add(end1.sub(start1).scale(u));
    }
    return start1;
}

function test0(order) {
    thickness = 20;
    current = og.math.vector2(100, 300), prev = og.math.vector2(700, 300), next = og.math.vector2(700, 300);
    dirNext = next.sub(current).normalize(), dirPrev = next.sub(current).normalize();
    normalNext = og.math.vector2(-dirNext.y, dirNext.x).normalize();
    normalPrev = og.math.vector2(dirPrev.y, -dirPrev.x).normalize();
    d = thickness * Math.sign(order);
    //vec2 m = getIntersection( current + normalPrev * d, prev + normalPrev * d,
    //    current + normalNext * d, next + normalNext * d );
    m = getIntersection(current.add(normalPrev.scaleTo(d)), prev.add(normalPrev.scaleTo(d)),
        current.add(normalNext.scaleTo(d)), next.add(normalNext.scaleTo(d)));

    ccw = Math.sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);
    if (ccw == 0.0) ccw = 1.0;
}

my.LineRing = function(name) {
    og.inheritance.base(this, name);
    this.thickness = 5;

    this._mainData = [];
    this._orderData = [];
    this._indexData = [];
};

og.inheritance.extend(my.LineRing, og.scene.RenderNode);

my.LineRing.prototype.initialization = function() {
    this.renderer.events.on("charkeypress", og.input.KEY_X, function() {
        if (this._drawType == this.renderer.handler.gl.LINE_STRIP) {
            this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;
        } else {
            this._drawType = this.renderer.handler.gl.LINE_STRIP;
        }
    }, this);

    this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;

    this.renderer.handler.addShaderProgram(new og.shaderProgram.ShaderProgram("lineRing", {
        uniforms: {
            'viewport': {
                type: og.shaderProgram.types.VEC2
            },
            'thickness': {
                type: og.shaderProgram.types.FLOAT
            },
            'alpha': {
                type: og.shaderProgram.types.FLOAT
            },
            'color': {
                type: og.shaderProgram.types.VEC4
            },
            'extentParams': {
                type: og.shaderProgram.types.VEC4
            }

        },
        attributes: {
            'prev': {
                type: og.shaderProgram.types.VEC2
            },
            'current': {
                type: og.shaderProgram.types.VEC2
            },
            'next': {
                type: og.shaderProgram.types.VEC2
            },
            'order': {
                type: og.shaderProgram.types.FLOAT
            }
        },
        vertexShader: 'attribute vec2 prev;\
                attribute vec2 current;\
                attribute vec2 next;\
                attribute float order;\
                uniform float thickness;\
                uniform vec2 viewport;\
                uniform vec4 extentParams;\
                \
                vec2 getIntersection(vec2 start1, vec2 end1, vec2 start2, vec2 end2){\
                    vec2 dir = end2 - start2;\
                    vec2 perp = vec2(-dir.y, dir.x);\
                    float d2 = dot(perp, start2);\
                    float seg = dot(perp, start1) - d2;\
                    float u = seg / (seg - dot(perp, end1) + d2);\
                    return start1 + u * (end1 - start1);\
                }\
                \
                vec2 proj(vec2 coordinates){\
                    return vec2(-1.0 + (coordinates - extentParams.xy) * extentParams.zw) * vec2(1.0, -1.0);\
                }\
                \
                void main(){\
                    vec2 _next = next;\
                    vec2 _prev = prev;\
                    if(prev == current){\
                        if(next == current){\
                            _next = current + vec2(1.0, 0.0);\
                            _prev = current - next;\
                        }else{\
                            _prev = current + normalize(current - next);\
                        }\
                    }\
                    if(next == current){\
                        _next = current + normalize(current - _prev);\
                    }\
                    \
                    vec2 sNext = proj(_next),\
                         sCurrent = proj(current),\
                         sPrev = proj(_prev);\
                    vec2 dirNext = normalize(sNext - sCurrent);\
                    vec2 dirPrev = normalize(sPrev - sCurrent);\
                    vec2 normalNext = normalize(vec2(-dirNext.y, dirNext.x));\
                    vec2 normalPrev = normalize(vec2(dirPrev.y, -dirPrev.x));\
                    vec2 d = thickness * sign(order) / viewport;\
                    \
                    vec2 m;\
                    float dotNP = dot(dirNext, dirPrev);\
                    if(abs(dotNP) != 1.0){\
                        m = getIntersection( sCurrent + normalPrev * d, sPrev + normalPrev * d,\
                            sCurrent + normalNext * d, sNext + normalNext * d );\
                    }else{\
                        m = sCurrent + normalPrev * d;\
                    }\
                    \
                    if( dotNP > 0.5 && dot(dirNext + dirPrev, m - sCurrent) < 0.0 ){\
                        float ccw = sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);\
                        float occw = order * ccw;\
                        if(occw == -1.0){\
                            m = sCurrent + normalPrev * d;\
                        }else if(occw == 1.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == -2.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == 2.0){\
                            m = sCurrent + normalPrev * d;\
                        }\
                    }else{\
                        float maxDist = max(distance(sCurrent, sNext), distance(sCurrent, sPrev));\
                        if(distance(sCurrent, m) > maxDist){\
                            m = sCurrent + maxDist * normalize(m - sCurrent);\
                        }\
                    }\
                    gl_Position = vec4(m.x, m.y, 0.0, 1.0);\
                }',
        fragmentShader: 'precision highp float;\
                uniform float alpha;\
                uniform vec4 color;\
                void main() {\
                    gl_FragColor = vec4(color.rgb, alpha * color.a);\
                }'
    }));

    var path = [
        [0, 0],
        [0, 40],
        [40, 40],
        [40, 0]
    ];

    var last = path[path.length - 1];
    var prev = last;
    this._mainData.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
    this._orderData.push(1, -1, 2, -2);
    var k = 0;
    for (var i = 0; i < path.length; i++) {
        var cur = path[i];
        this._mainData.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
        this._orderData.push(1, -1, 2, -2);
        this._indexData.push(k++, k++, k++, k++);
    }
    var first = path[0];
    this._mainData.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
    this._orderData.push(1, -1, 2, -2);
    this._indexData.push(0, 1);

    var h = this.renderer.handler;
    this._orderBuffer = h.createArrayBuffer(new Float32Array(this._orderData), 1, this._orderData.length / 2);
    this._mainBuffer = h.createArrayBuffer(new Float32Array(this._mainData), 2, this._mainData.length / 4);
    this._indexBuffer = h.createElementArrayBuffer(new Uint16Array(this._indexData), 1, this._indexData.length);
};

my.LineRing.prototype.frame = function() {

    var rn = this;
    var r = rn.renderer;
    var sh = r.handler.shaderPrograms.lineRing;
    var p = sh._program;
    var gl = r.handler.gl,
        sha = p.attributes,
        shu = p.uniforms;

    sh.activate();

    gl.enable(gl.BLEND);
    gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
    gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    gl.disable(gl.DEPTH_TEST);
    gl.disable(gl.CULL_FACE);

    gl.uniform2fv(shu.viewport._pName, [512, 512]);
    gl.uniform4fv(shu.color._pName, [1.0, 1.0, 1.0, 1]);

    var extent = new og.Extent(new og.LonLat(-180, -90), new og.LonLat(180, 90));
    gl.uniform4fv(shu.extentParams._pName, [extent.southWest.lon, extent.southWest.lat, 2.0 / extent.getWidth(), 2.0 / extent.getHeight()]);

    var mb = this._mainBuffer;
    gl.bindBuffer(gl.ARRAY_BUFFER, mb);
    gl.vertexAttribPointer(sha.prev._pName, mb.itemSize, gl.FLOAT, false, 0, 0);
    gl.vertexAttribPointer(sha.current._pName, mb.itemSize, gl.FLOAT, false, 0, 32);
    gl.vertexAttribPointer(sha.next._pName, mb.itemSize, gl.FLOAT, false, 0, 64);
    gl.bindBuffer(gl.ARRAY_BUFFER, this._orderBuffer);
    gl.vertexAttribPointer(sha.order._pName, this._orderBuffer.itemSize, gl.FLOAT, false, 4, 0);

    //Antialiase pass
    gl.uniform1f(shu.thickness._pName, (this.thickness + 2) * 0.5);
    gl.uniform1f(shu.alpha._pName, 0.54);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    //Aliased pass
    gl.uniform1f(shu.thickness._pName, this.thickness * 0.5);
    gl.uniform1f(shu.alpha._pName, 1.0);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
};
<commit_msg>multiple lines to one render pass<commit_after>goog.provide('my.LineRing');

goog.require('og.scene.RenderNode');
goog.require('og.inheritance');

goog.require('og.EntityCollection');
goog.require('og.Entity');
goog.require('og.Label');
goog.require('og.LonLat');
goog.require('og.Extent');

function getIntersection(start1, end1, start2, end2) {
    if (!start1.equal(start2)) {
        var dir = end2.sub(start2);
        var perp = new og.math.Vector2(-dir.y, dir.x);
        var d2 = perp.dot(start2);
        var seg = perp.dot(start1) - d2;
        var u = seg / (seg - perp.dot(end1) + d2);
        return start1.add(end1.sub(start1).scale(u));
    }
    return start1;
}

function test0(order) {
    thickness = 20;
    current = og.math.vector2(100, 300), prev = og.math.vector2(700, 300), next = og.math.vector2(700, 300);
    dirNext = next.sub(current).normalize(), dirPrev = next.sub(current).normalize();
    normalNext = og.math.vector2(-dirNext.y, dirNext.x).normalize();
    normalPrev = og.math.vector2(dirPrev.y, -dirPrev.x).normalize();
    d = thickness * Math.sign(order);
    //vec2 m = getIntersection( current + normalPrev * d, prev + normalPrev * d,
    //    current + normalNext * d, next + normalNext * d );
    m = getIntersection(current.add(normalPrev.scaleTo(d)), prev.add(normalPrev.scaleTo(d)),
        current.add(normalNext.scaleTo(d)), next.add(normalNext.scaleTo(d)));

    ccw = Math.sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);
    if (ccw == 0.0) ccw = 1.0;
}

my.LineRing = function(name) {
    og.inheritance.base(this, name);
    this.thickness = 5;

    this._mainData = [];
    this._orderData = [];
    this._indexData = [];
    this._thicknessData = [];
    this._colorData = [];
};

og.inheritance.extend(my.LineRing, og.scene.RenderNode);

my.LineRing.prototype.initialization = function() {
    this.renderer.events.on("charkeypress", og.input.KEY_X, function() {
        if (this._drawType == this.renderer.handler.gl.LINE_STRIP) {
            this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;
        } else {
            this._drawType = this.renderer.handler.gl.LINE_STRIP;
        }
    }, this);

    this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;

    this.renderer.handler.addShaderProgram(new og.shaderProgram.ShaderProgram("lineRing", {
        uniforms: {
            'viewport': {
                type: og.shaderProgram.types.VEC2
            },
            'thicknessOutline': {
                type: og.shaderProgram.types.FLOAT
            },
            'alpha': {
                type: og.shaderProgram.types.FLOAT
            },
            'extentParams': {
                type: og.shaderProgram.types.VEC4
            }
        },
        attributes: {
            'prev': {
                type: og.shaderProgram.types.VEC2
            },
            'current': {
                type: og.shaderProgram.types.VEC2
            },
            'next': {
                type: og.shaderProgram.types.VEC2
            },
            'order': {
                type: og.shaderProgram.types.FLOAT
            },
            'color': {
                type: og.shaderProgram.types.VEC4
            },
            'thickness': {
                type: og.shaderProgram.types.FLOAT
            }
        },
        vertexShader: 'attribute vec2 prev;\
                attribute vec2 current;\
                attribute vec2 next;\
                attribute float order;\
                attribute float thickness;\
                attribute vec4 color;\
                uniform float thicknessOutline;\
                uniform vec2 viewport;\
                uniform vec4 extentParams;\
                varying vec4 vColor;\
                \
                vec2 getIntersection(vec2 start1, vec2 end1, vec2 start2, vec2 end2){\
                    vec2 dir = end2 - start2;\
                    vec2 perp = vec2(-dir.y, dir.x);\
                    float d2 = dot(perp, start2);\
                    float seg = dot(perp, start1) - d2;\
                    float u = seg / (seg - dot(perp, end1) + d2);\
                    return start1 + u * (end1 - start1);\
                }\
                \
                vec2 proj(vec2 coordinates){\
                    return vec2(-1.0 + (coordinates - extentParams.xy) * extentParams.zw) * vec2(1.0, -1.0);\
                }\
                \
                void main(){\
                    vColor = color;\
                    vec2 _next = next;\
                    vec2 _prev = prev;\
                    if(prev == current){\
                        if(next == current){\
                            _next = current + vec2(1.0, 0.0);\
                            _prev = current - next;\
                        }else{\
                            _prev = current + normalize(current - next);\
                        }\
                    }\
                    if(next == current){\
                        _next = current + normalize(current - _prev);\
                    }\
                    \
                    vec2 sNext = proj(_next),\
                         sCurrent = proj(current),\
                         sPrev = proj(_prev);\
                    vec2 dirNext = normalize(sNext - sCurrent);\
                    vec2 dirPrev = normalize(sPrev - sCurrent);\
                    vec2 normalNext = normalize(vec2(-dirNext.y, dirNext.x));\
                    vec2 normalPrev = normalize(vec2(dirPrev.y, -dirPrev.x));\
                    vec2 d = (thickness + thicknessOutline) * 0.5 * sign(order) / viewport;\
                    \
                    vec2 m;\
                    float dotNP = dot(dirNext, dirPrev);\
                    if(abs(dotNP) != 1.0){\
                        m = getIntersection( sCurrent + normalPrev * d, sPrev + normalPrev * d,\
                            sCurrent + normalNext * d, sNext + normalNext * d );\
                    }else{\
                        m = sCurrent + normalPrev * d;\
                    }\
                    \
                    if( dotNP > 0.5 && dot(dirNext + dirPrev, m - sCurrent) < 0.0 ){\
                        float ccw = sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);\
                        float occw = order * ccw;\
                        if(occw == -1.0){\
                            m = sCurrent + normalPrev * d;\
                        }else if(occw == 1.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == -2.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == 2.0){\
                            m = sCurrent + normalPrev * d;\
                        }\
                    }else{\
                        float maxDist = max(distance(sCurrent, sNext), distance(sCurrent, sPrev));\
                        if(distance(sCurrent, m) > maxDist){\
                            m = sCurrent + maxDist * normalize(m - sCurrent);\
                        }\
                    }\
                    gl_Position = vec4(m.x, m.y, 0.0, 1.0);\
                }',
        fragmentShader: 'precision highp float;\
                uniform float alpha;\
                varying vec4 vColor;\
                void main() {\
                    gl_FragColor = vec4(vColor.rgb, alpha * vColor.a);\
                }'
    }));

    var pathArr = [
        [
            [0, 0],
            [70, 0],
            [50, 50]
        ],
        [
            [-10, -10],
            [-12, -40],
            [100, -70]
        ],
        [
            [0, 0],
            [-50, -70],
            [-90, -20],
            [-50, 50]
        ]
    ];

    var colors = [
        [1, 0, 0, 1],
        [0, 1, 0, 1],
        [1, 1, 1, 1]
    ];
    var thickness = [24, 14, 15];

    var index = 0;
    for (var j = 0; j < pathArr.length; j++) {
        path = pathArr[j];
        var startIndex = index;
        var last = path[path.length - 1];
        var prev = last;
        this._mainData.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
        this._orderData.push(1, -1, 2, -2);
        var t = thickness[j],
            c = colors[j];
        this._thicknessData.push(t, t, t, t);
        this._colorData.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);

        for (var i = 0; i < path.length; i++) {
            var cur = path[i];
            this._mainData.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
            this._orderData.push(1, -1, 2, -2);
            this._thicknessData.push(t, t, t, t);
            this._colorData.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
            this._indexData.push(index++, index++, index++, index++);
        }

        var first = path[0];
        this._mainData.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
        this._orderData.push(1, -1, 2, -2);
        this._thicknessData.push(t, t, t, t);
        this._colorData.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
        this._indexData.push(startIndex, startIndex + 1);

        this._indexData.push(startIndex, startIndex);
        if (j < pathArr.length - 1) {
            this._indexData.push(index + 8, index + 8);
        }

        index += 8;
    }

    var h = this.renderer.handler;
    this._orderBuffer = h.createArrayBuffer(new Float32Array(this._orderData), 1, this._orderData.length / 2);
    this._mainBuffer = h.createArrayBuffer(new Float32Array(this._mainData), 2, this._mainData.length / 2);
    this._indexBuffer = h.createElementArrayBuffer(new Uint16Array(this._indexData), 1, this._indexData.length);

    this._thicknessBuffer = h.createArrayBuffer(new Float32Array(this._thicknessData), 1, this._thicknessData.length);
    this._colorBuffer = h.createArrayBuffer(new Float32Array(this._colorData), 4, this._colorData.length / 4);
};

my.LineRing.prototype.frame = function() {

    var rn = this;
    var r = rn.renderer;
    var sh = r.handler.shaderPrograms.lineRing;
    var p = sh._program;
    var gl = r.handler.gl,
        sha = p.attributes,
        shu = p.uniforms;

    sh.activate();

    gl.enable(gl.BLEND);
    gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
    gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    gl.disable(gl.DEPTH_TEST);
    gl.disable(gl.CULL_FACE);

    gl.uniform2fv(shu.viewport._pName, [512, 512]);

    var extent = new og.Extent(new og.LonLat(-180, -90), new og.LonLat(180, 90));
    gl.uniform4fv(shu.extentParams._pName, [extent.southWest.lon, extent.southWest.lat, 2.0 / extent.getWidth(), 2.0 / extent.getHeight()]);

    //thickness
    gl.bindBuffer(gl.ARRAY_BUFFER, this._thicknessBuffer);
    gl.vertexAttribPointer(sha.thickness._pName, this._thicknessBuffer.itemSize, gl.FLOAT, false, 0, 0);

    //color
    gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
    gl.vertexAttribPointer(sha.color._pName, this._colorBuffer.itemSize, gl.FLOAT, false, 0, 0);

    //vertex
    var mb = this._mainBuffer;
    gl.bindBuffer(gl.ARRAY_BUFFER, mb);
    gl.vertexAttribPointer(sha.prev._pName, mb.itemSize, gl.FLOAT, false, 8, 0);
    gl.vertexAttribPointer(sha.current._pName, mb.itemSize, gl.FLOAT, false, 8, 32);
    gl.vertexAttribPointer(sha.next._pName, mb.itemSize, gl.FLOAT, false, 8, 64);

    //order
    gl.bindBuffer(gl.ARRAY_BUFFER, this._orderBuffer);
    gl.vertexAttribPointer(sha.order._pName, this._orderBuffer.itemSize, gl.FLOAT, false, 4, 0);

    //
    //Antialiase pass
    gl.uniform1f(shu.thicknessOutline._pName, 2);
    gl.uniform1f(shu.alpha._pName, 0.54);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    //
    //Aliased pass
    gl.uniform1f(shu.thicknessOutline._pName, 1);
    gl.uniform1f(shu.alpha._pName, 1.0);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
};
<|endoftext|>