<commit_before>import VectorLayer from 'ol/layer/Vector';
import {Circle, Icon, Style} from 'ol/style';
import {GeoJSON} from 'ol/format';
import {ImageArcGISRest, ImageStatic, TileArcGISRest, TileWMS} from 'ol/source';
import {Image as ImageLayer, Tile} from 'ol/layer';
import {ImageWMS, XYZ} from 'ol/source';

/**
 * @param HsMapService
 * @param HsUtilsService
 * @param $window
 * @param HsLayoutService
 * @param $log
 * @param $document
 */
export default function (
  HsMapService,
  HsUtilsService,
  $window,
  HsLayoutService,
  $log,
  $document
) {
  'ngInject';
  const me = {
    /**
     * Create Json object which stores information about composition, user, map state and map layers (including layer data)
     *
     * @memberof HsSaveMapService
     * @function map2json
     * @param {Ol.map} map Selected map object
     * @param {object} compoData Composition general metadata
     * @param {object} userData Metadata about user
     * @param {object} statusData Metadata about permissions
     * @returns {object} JSON object with all required map composition metadata
     */
    map2json: function (map, compoData, userData, statusData) {
      const groups = {};
      angular.forEach(statusData.groups, (g) => {
        if (g.r || g.w) {
          groups[g.roleName] = (g.r ? 'r' : '') + (g.w ? 'w' : '');
        }
      });
      if (angular.isUndefined(groups.guest)) {
        groups.guest = 'r';
      }
      const json = {
        abstract: compoData.abstract,
        title: compoData.title,
        keywords: compoData.keywords,
        extent: compoData.bbox,
        user: {
          address: userData.address,
          city: userData.city,
          country: userData.country,
          email: userData.email || 'none@none',
          name: userData.name,
          organization: userData.organization,
          phone: userData.phone,
          position: userData.position,
          postalcode: userData.postalcode,
          state: userData.state,
        },
        groups: groups,
      };

      // Map properties
      json.scale = map.getView().getProjection().getMetersPerUnit();
      json.projection = map.getView().getProjection().getCode().toLowerCase();
      const center = map.getView().getCenter();
      if (center) {
        json.center = [center[0], center[1]];
      }
      json.units = map.getView().getProjection().getUnits();

      if (map.maxExtent) {
        json.maxExtent = {};
        json.maxExtent.left = map.maxExtent.left;
        json.maxExtent.bottom = map.maxExtent.bottom;
        json.maxExtent.right = map.maxExtent.right;
        json.maxExtent.top = map.maxExtent.top;
      }

      //json.minResolution = map.minResolution;
      //json.maxResolution = map.maxResolution;
      //json.numZoomLevels = map.numZoomLevels;

      //json.resolutions = map.resolutions;
      //json.scales = map.scales;
      //json.sphericalMercator = map.sphericalMercator;

      // Layers properties
      let layers = map.getLayers().getArray();
      layers = layers.filter(
        (l) =>
          angular.isUndefined(l.get('show_in_manager')) ||
          l.get('show_in_manager')
      );
      json.layers = me.layers2json(layers, compoData.layers);
      json.current_base_layer = me.getCurrentBaseLayer(map);
      return json;
    },
    /**
     * Returns object about current selected base layer
     *
     * @memberof HsSaveMapService
     * @function getCurrentBaseLayer
     * @param {Ol.map} map Selected map object
     * @returns {object} Returns object with current current selected base layers title as attribute
     */
    getCurrentBaseLayer: function (map) {
      let current_base_layer = null;
      angular.forEach(map.getLayers().getArray(), (lyr) => {
        if (
          (angular.isUndefined(lyr.get('show_in_manager')) ||
            lyr.get('show_in_manager') == true) &&
          lyr.get('base') == true &&
          lyr.getVisible()
        ) {
          current_base_layer = {
            title: lyr.get('title'),
          };
        }
      });
      return current_base_layer;
    },

    /**
     * Converts map layers into a JSON object. If $scope is defined, stores only layers checked in form
     * Uses layer2json().
     *
     * @memberof HsSaveMapService
     * @function layer2json
     * @param {Array} layers All map layers
     * @param {Array} tickedLayers List of layers and if they have been ticked
     * @returns {Array} JSON object representing the layers
     */
    layers2json: function (layers, tickedLayers) {
      const json = [];
      layers.forEach((lyr) => {
        if (angular.isDefined(tickedLayers)) {
          //From form
          angular.forEach(tickedLayers, (list_item) => {
            if (list_item.layer == lyr && list_item.checked) {
              const l = me.layer2json(lyr);
              if (l) {
                json.push(l);
              }
            }
          });
        } else {
          //From unloading
          const l = me.layer2json(lyr);
          if (l) {
            json.push(l);
          }
        }
      });

      return json;
    },

    /**
     * Converts map layer from Layer object to text in JSON notation.
     *
     * Syntactic sugar for layer2json() UNUSED?
     *
     * @memberof HsSaveMapService
     * @function layer2string
     * @param {object} layer Layer to be converted
     * @param {boolean} pretty Whether to use pretty notation
     * @returns {string} Text in JSON notation representing the layer
     */
    layer2string: function (layer, pretty) {
      const json = me.layer2json(layer);
      const text = angular.toJson(json, pretty);
      return text;
    },

    /**
     * Convert layer style object into JSON object, partial function of layer2style (saves Fill color, Stroke color/width, Image fill, stroke, radius, src and type)
     *
     * @memberof HsSaveMapService
     * @function serializeStyle
     * @param {ol.style.Style} s Style to convert
     * @returns {object} Converted JSON object for style
     */
    serializeStyle: function (s) {
      const o = {};
      if (angular.isDefined(s.getFill()) && s.getFill() !== null) {
        o.fill = s.getFill().getColor();
      }
      if (angular.isDefined(s.getStroke()) && s.getStroke() !== null) {
        o.stroke = {
          color: s.getStroke().getColor(),
          width: s.getStroke().getWidth(),
        };
      }
      if (angular.isDefined(s.getImage()) && s.getImage() !== null) {
        const style_img = s.getImage();
        const ima = {};
        if (
          angular.isDefined(style_img.getFill) &&
          angular.isDefined(style_img.getFill()) &&
          style_img.getFill() !== null
        ) {
          ima.fill = style_img.getFill().getColor();
        }

        if (
          angular.isDefined(style_img.getStroke) &&
          angular.isDefined(style_img.getStroke()) &&
          style_img.getStroke() !== null
        ) {
          ima.stroke = {
            color: style_img.getStroke().getColor(),
            width: style_img.getStroke().getWidth(),
          };
        }

        if (angular.isDefined(style_img.getRadius)) {
          ima.radius = style_img.getRadius();
        }

        if (
          angular.isFunction(style_img.getSrc) &&
          angular.isString(style_img.getSrc())
        ) {
          ima.src = HsUtilsService.proxify(style_img.getSrc());
        } else if (
          angular.isFunction(style_img.getImage) &&
          style_img.getImage() !== null
        ) {
          if (angular.isDefined(style_img.getImage().src)) {
            ima.src = style_img.getImage().src;
          }
        }

        if (HsUtilsService.instOf(style_img, Circle)) {
          ima.type = 'circle';
        }

        if (HsUtilsService.instOf(style_img, Icon)) {
          ima.type = 'icon';
        }

        o.image = ima;
      }
      return o;
    },

    /**
     * Converts map layer into a JSON object (only for ol.layer.Layer)
     * Layer properties covered:  (CLASS_NAME), name, url, params,
     *                            group, displayInLayerSwitcher, *visibility, *opacity
     *                            attribution, transitionEffect,
     *                             isBaseLayer, minResolution,
     *                            maxResolution, minScale, maxScale, metadata,
     *                            abstract, opacity, singleTile, removable,
     *                            queryable, legend, projections,
     *                            wmsMinScale, wmsMaxScale
     *
     * The layer index is not covered, as we assume
     * that it is corresponding to the layers order.
     *
     * @memberof HsSaveMapService
     * @function layer2json
     * @param {object} layer Map layer that should be converted
     * @returns {object} JSON object representing the layer
     */
    layer2json: function (layer) {
      const json = {
        metadata: {},
      };

      /*
            Commented out because we cant reliably use instanceof.
            utils.instOf is also not possible, because Layer is a base type

            if (!layer instanceof Layer) {
                return;
            }
            */

      // Common stuff

      // type
      //json.className = layer.CLASS_NAME;
      //json.origClassName = layer.CLASS_NAME; // the original type

      // options
      json.visibility = layer.getVisible();
      json.opacity = layer.getOpacity();
      json.title = layer.get('title');
      //json.index = layer.map.getLayerIndex(layer);
      json.path = layer.get('path');

      if (layer.getExtent()) {
        const ex = layer.getExtent();
        json.maxExtent = {
          left: ex[0],
          bottom: ex[3],
          right: ex[2],
          top: ex[1],
        };
      }

      // HTTPRequest
      if (HsUtilsService.instOf(layer, Tile) || HsUtilsService.instOf(layer, ImageLayer)) {
        const src = layer.getSource();
        if (layer.getMaxResolution() !== null) {
          json.maxResolution = layer.getMaxResolution();
        }
        if (layer.getMinResolution() !== null) {
          json.minResolution = layer.getMinResolution();
        }
        if (layer.get('minScale') !== null) {
          json.wmsMinScale = layer.get('minScale');
        }
        if (layer.get('maxScale') !== null) {
          json.wmsMaxScale = layer.get('maxScale');
        }
        json.displayInLayerSwitcher = layer.get('show_in_manager');
        if (layer.get('dimensions')) {
          json.dimensions = layer.get('dimensions');
        }
        if (HsUtilsService.instOf(src, XYZ)) {
          json.className = 'XYZ';
        }
        if (
          HsUtilsService.instOf(src, ImageArcGISRest) ||
          HsUtilsService.instOf(src, TileArcGISRest)
        ) {
          json.className = 'ArcGISRest';
          json.singleTile = HsUtilsService.instOf(src, ImageArcGISRest);
        }
        if (HsUtilsService.instOf(src, ImageStatic)) {
          json.className = 'StaticImage';
          json.extent = src.getImageExtent();
        }
        if (HsUtilsService.instOf(src, ImageWMS) || HsUtilsService.instOf(src, TileWMS)) {
          json.className = 'HSLayers.Layer.WMS';
          json.singleTile = HsUtilsService.instOf(src, ImageWMS);
          if (layer.get('legends')) {
            json.legends = [];
            const legends = layer.get('legends');
            for (let i = 0; i < legends.length; i++) {
              json.legends.push(encodeURIComponent(legends[i]));
            }
          }
          if (src.getProjection()) {
            json.projection = src.getProjection().getCode().toLowerCase();
          }
          json.params = src.getParams();
          json.ratio = src.get('ratio') || src.ratio_;
          json.subLayers = layer.get('subLayers');
          json.metadata.styles = src.get('styles');
        }
        if (src.getUrl) {
          json.url = encodeURIComponent(src.getUrl());
        }
        if (src.getUrls) {
          json.url = encodeURIComponent(src.getUrls()[0]);
        }
        if (src.attributions_) {
          json.attributions = encodeURIComponent(src.attributions_);
        }
      }

      // Vector
      if (HsUtilsService.instOf(layer, VectorLayer)) {
        const src = layer.getSource();
        json.className = 'OpenLayers.Layer.Vector';
        const definition = layer.get('definition');
        if (
          angular.isDefined(definition) &&
          angular.isDefined(definition.url)
        ) {
          json.protocol = {
            url: encodeURIComponent(definition.url),
            format: definition.format,
          };
        } else {
          try {
            json.features = me.serializeFeatures(src.getFeatures());
          } catch (ex) {
            //Do nothing
          }
        }
        if (layer.get('synchronize')) {
          json.protocol = {format: 'hs.format.LaymanWfs'};
          delete json.features;
        }
        if (angular.isDefined(src.defOptions)) {
          json.defOptions = src.defOptions;
        }
        json.maxResolution = layer.getMaxResolution();
        json.minResolution = layer.getMinResolution();
        json.projection = 'epsg:4326';
        if (HsUtilsService.instOf(layer.getStyle(), Style)) {
          json.style = me.serializeStyle(layer.getStyle());
        }
      }
      return json;
    },

    /**
     * Convert feature array to GeoJSON string
     *
     * @memberof HsSaveMapService
     * @function serializeFeatures
     * @param {Array} features Array of features
     * @returns {string} GeoJSON string
     */
    serializeFeatures: function (features) {
      const f = new GeoJSON();
      return f.writeFeatures(features, {
        dataProjection: 'EPSG:4326',
        featureProjection: HsMapService.map.getView().getProjection().getCode(),
      });
    },

    /**
     * Generate random Uuid
     *
     * @memberof HsSaveMapService
     * @function generateUuid
     * @returns {string} Random Uuid in string format
     */
    generateUuid: HsUtilsService.generateUuid,

    /**
     * Create thumbnail of map view and save it into selected element
     *
     * @memberof HsSaveMapService
     * @function generateThumbnail
     * @param {$element} $element Selected element
     * @param {object} localThis Context to be passed to postcompose event handler
     * @param {boolean} newRender Force new render?
     */
    generateThumbnail: function ($element, localThis, newRender) {
      /**
       * @param event
       */
      function rendered(event) {
        const canvas = HsMapService.getCanvas();
        const canvas2 = $document[0].createElement('canvas');
        const width = 256,
          height = 256;
        canvas2.style.width = width + 'px';
        canvas2.style.height = height + 'px';
        canvas2.width = width;
        canvas2.height = height;
        const ctx2 = canvas2.getContext('2d');
        ctx2.drawImage(
          canvas,
          canvas.width / 2 - height / 2,
          canvas.height / 2 - width / 2,
          width,
          height,
          0,
          0,
          width,
          height
        );
        try {
          $element.setAttribute('src', canvas2.toDataURL('image/png'));
          this.thumbnail = canvas2.toDataURL('image/jpeg', 0.8);
        } catch (e) {
          $log.warn(e);
          $element.setAttribute('src', require('./notAvailable.png'));
        }
        $element.style.width = width + 'px';
        $element.style.height = height + 'px';
      }
      if (
        HsLayoutService.mainpanel == 'save-map' ||
        HsLayoutService.mainpanel == 'permalink' ||
        HsLayoutService.mainpanel == 'statusCreator'
      ) {
        if ($element === null) {
          return;
        }
        $element.setAttribute('crossOrigin', 'Anonymous');

        HsMapService.map.once('postcompose', rendered, localThis);
        if (newRender) {
          HsMapService.map.renderSync();
        } else {
          rendered();
        }
      }
    },
  };

  $window.addEventListener('beforeunload', (event) => {
    const data = {};
    const layers = [];
    angular.forEach(HsMapService.map.getLayers(), (layer) => {
      if (layer.get('saveState')) {
        layers.push(me.layer2json(layer));
      }
    });
    data.layers = layers;
    localStorage.setItem('hs_layers', angular.toJson(data));
  });
  return me;
}
<commit_msg>Debugger when layer title is undefined in saving layers to cookie<commit_after>import VectorLayer from 'ol/layer/Vector';
import {Circle, Icon, Style} from 'ol/style';
import {GeoJSON} from 'ol/format';
import {ImageArcGISRest, ImageStatic, TileArcGISRest, TileWMS} from 'ol/source';
import {Image as ImageLayer, Tile} from 'ol/layer';
import {ImageWMS, XYZ} from 'ol/source';

/**
 * @param HsMapService
 * @param HsUtilsService
 * @param $window
 * @param HsLayoutService
 * @param $log
 * @param $document
 */
export default function (
  HsMapService,
  HsUtilsService,
  $window,
  HsLayoutService,
  $log,
  $document
) {
  'ngInject';
  const me = {
    /**
     * Create Json object which stores information about composition, user, map state and map layers (including layer data)
     *
     * @memberof HsSaveMapService
     * @function map2json
     * @param {Ol.map} map Selected map object
     * @param {object} compoData Composition general metadata
     * @param {object} userData Metadata about user
     * @param {object} statusData Metadata about permissions
     * @returns {object} JSON object with all required map composition metadata
     */
    map2json: function (map, compoData, userData, statusData) {
      const groups = {};
      angular.forEach(statusData.groups, (g) => {
        if (g.r || g.w) {
          groups[g.roleName] = (g.r ? 'r' : '') + (g.w ? 'w' : '');
        }
      });
      if (angular.isUndefined(groups.guest)) {
        groups.guest = 'r';
      }
      const json = {
        abstract: compoData.abstract,
        title: compoData.title,
        keywords: compoData.keywords,
        extent: compoData.bbox,
        user: {
          address: userData.address,
          city: userData.city,
          country: userData.country,
          email: userData.email || 'none@none',
          name: userData.name,
          organization: userData.organization,
          phone: userData.phone,
          position: userData.position,
          postalcode: userData.postalcode,
          state: userData.state,
        },
        groups: groups,
      };

      // Map properties
      json.scale = map.getView().getProjection().getMetersPerUnit();
      json.projection = map.getView().getProjection().getCode().toLowerCase();
      const center = map.getView().getCenter();
      if (center) {
        json.center = [center[0], center[1]];
      }
      json.units = map.getView().getProjection().getUnits();

      if (map.maxExtent) {
        json.maxExtent = {};
        json.maxExtent.left = map.maxExtent.left;
        json.maxExtent.bottom = map.maxExtent.bottom;
        json.maxExtent.right = map.maxExtent.right;
        json.maxExtent.top = map.maxExtent.top;
      }

      //json.minResolution = map.minResolution;
      //json.maxResolution = map.maxResolution;
      //json.numZoomLevels = map.numZoomLevels;

      //json.resolutions = map.resolutions;
      //json.scales = map.scales;
      //json.sphericalMercator = map.sphericalMercator;

      // Layers properties
      let layers = map.getLayers().getArray();
      layers = layers.filter(
        (l) =>
          angular.isUndefined(l.get('show_in_manager')) ||
          l.get('show_in_manager')
      );
      json.layers = me.layers2json(layers, compoData.layers);
      json.current_base_layer = me.getCurrentBaseLayer(map);
      return json;
    },
    /**
     * Returns object about current selected base layer
     *
     * @memberof HsSaveMapService
     * @function getCurrentBaseLayer
     * @param {Ol.map} map Selected map object
     * @returns {object} Returns object with current current selected base layers title as attribute
     */
    getCurrentBaseLayer: function (map) {
      let current_base_layer = null;
      angular.forEach(map.getLayers().getArray(), (lyr) => {
        if (
          (angular.isUndefined(lyr.get('show_in_manager')) ||
            lyr.get('show_in_manager') == true) &&
          lyr.get('base') == true &&
          lyr.getVisible()
        ) {
          current_base_layer = {
            title: lyr.get('title'),
          };
        }
      });
      return current_base_layer;
    },

    /**
     * Converts map layers into a JSON object. If $scope is defined, stores only layers checked in form
     * Uses layer2json().
     *
     * @memberof HsSaveMapService
     * @function layer2json
     * @param {Array} layers All map layers
     * @param {Array} tickedLayers List of layers and if they have been ticked
     * @returns {Array} JSON object representing the layers
     */
    layers2json: function (layers, tickedLayers) {
      const json = [];
      layers.forEach((lyr) => {
        if (angular.isDefined(tickedLayers)) {
          //From form
          angular.forEach(tickedLayers, (list_item) => {
            if (list_item.layer == lyr && list_item.checked) {
              const l = me.layer2json(lyr);
              if (l) {
                json.push(l);
              }
            }
          });
        } else {
          //From unloading
          const l = me.layer2json(lyr);
          if (l) {
            json.push(l);
          }
        }
      });

      return json;
    },

    /**
     * Converts map layer from Layer object to text in JSON notation.
     *
     * Syntactic sugar for layer2json() UNUSED?
     *
     * @memberof HsSaveMapService
     * @function layer2string
     * @param {object} layer Layer to be converted
     * @param {boolean} pretty Whether to use pretty notation
     * @returns {string} Text in JSON notation representing the layer
     */
    layer2string: function (layer, pretty) {
      const json = me.layer2json(layer);
      const text = angular.toJson(json, pretty);
      return text;
    },

    /**
     * Convert layer style object into JSON object, partial function of layer2style (saves Fill color, Stroke color/width, Image fill, stroke, radius, src and type)
     *
     * @memberof HsSaveMapService
     * @function serializeStyle
     * @param {ol.style.Style} s Style to convert
     * @returns {object} Converted JSON object for style
     */
    serializeStyle: function (s) {
      const o = {};
      if (angular.isDefined(s.getFill()) && s.getFill() !== null) {
        o.fill = s.getFill().getColor();
      }
      if (angular.isDefined(s.getStroke()) && s.getStroke() !== null) {
        o.stroke = {
          color: s.getStroke().getColor(),
          width: s.getStroke().getWidth(),
        };
      }
      if (angular.isDefined(s.getImage()) && s.getImage() !== null) {
        const style_img = s.getImage();
        const ima = {};
        if (
          angular.isDefined(style_img.getFill) &&
          angular.isDefined(style_img.getFill()) &&
          style_img.getFill() !== null
        ) {
          ima.fill = style_img.getFill().getColor();
        }

        if (
          angular.isDefined(style_img.getStroke) &&
          angular.isDefined(style_img.getStroke()) &&
          style_img.getStroke() !== null
        ) {
          ima.stroke = {
            color: style_img.getStroke().getColor(),
            width: style_img.getStroke().getWidth(),
          };
        }

        if (angular.isDefined(style_img.getRadius)) {
          ima.radius = style_img.getRadius();
        }

        if (
          angular.isFunction(style_img.getSrc) &&
          angular.isString(style_img.getSrc())
        ) {
          ima.src = HsUtilsService.proxify(style_img.getSrc());
        } else if (
          angular.isFunction(style_img.getImage) &&
          style_img.getImage() !== null
        ) {
          if (angular.isDefined(style_img.getImage().src)) {
            ima.src = style_img.getImage().src;
          }
        }

        if (HsUtilsService.instOf(style_img, Circle)) {
          ima.type = 'circle';
        }

        if (HsUtilsService.instOf(style_img, Icon)) {
          ima.type = 'icon';
        }

        o.image = ima;
      }
      return o;
    },

    /**
     * Converts map layer into a JSON object (only for ol.layer.Layer)
     * Layer properties covered:  (CLASS_NAME), name, url, params,
     *                            group, displayInLayerSwitcher, *visibility, *opacity
     *                            attribution, transitionEffect,
     *                             isBaseLayer, minResolution,
     *                            maxResolution, minScale, maxScale, metadata,
     *                            abstract, opacity, singleTile, removable,
     *                            queryable, legend, projections,
     *                            wmsMinScale, wmsMaxScale
     *
     * The layer index is not covered, as we assume
     * that it is corresponding to the layers order.
     *
     * @memberof HsSaveMapService
     * @function layer2json
     * @param {object} layer Map layer that should be converted
     * @returns {object} JSON object representing the layer
     */
    layer2json: function (layer) {
      const json = {
        metadata: {},
      };

      /*
            Commented out because we cant reliably use instanceof.
            utils.instOf is also not possible, because Layer is a base type

            if (!layer instanceof Layer) {
                return;
            }
            */

      // Common stuff

      // type
      //json.className = layer.CLASS_NAME;
      //json.origClassName = layer.CLASS_NAME; // the original type

      // options
      json.visibility = layer.getVisible();
      json.opacity = layer.getOpacity();
      json.title = layer.get('title');
      if (angular.isUndefined(layer.get('title'))) {
        $log.warn('Layer title undefined', layer);
        debugger;
      }
      //json.index = layer.map.getLayerIndex(layer);
      json.path = layer.get('path');

      if (layer.getExtent()) {
        const ex = layer.getExtent();
        json.maxExtent = {
          left: ex[0],
          bottom: ex[3],
          right: ex[2],
          top: ex[1],
        };
      }

      // HTTPRequest
      if (HsUtilsService.instOf(layer, Tile) || HsUtilsService.instOf(layer, ImageLayer)) {
        const src = layer.getSource();
        if (layer.getMaxResolution() !== null) {
          json.maxResolution = layer.getMaxResolution();
        }
        if (layer.getMinResolution() !== null) {
          json.minResolution = layer.getMinResolution();
        }
        if (layer.get('minScale') !== null) {
          json.wmsMinScale = layer.get('minScale');
        }
        if (layer.get('maxScale') !== null) {
          json.wmsMaxScale = layer.get('maxScale');
        }
        json.displayInLayerSwitcher = layer.get('show_in_manager');
        if (layer.get('dimensions')) {
          json.dimensions = layer.get('dimensions');
        }
        if (HsUtilsService.instOf(src, XYZ)) {
          json.className = 'XYZ';
        }
        if (
          HsUtilsService.instOf(src, ImageArcGISRest) ||
          HsUtilsService.instOf(src, TileArcGISRest)
        ) {
          json.className = 'ArcGISRest';
          json.singleTile = HsUtilsService.instOf(src, ImageArcGISRest);
        }
        if (HsUtilsService.instOf(src, ImageStatic)) {
          json.className = 'StaticImage';
          json.extent = src.getImageExtent();
        }
        if (HsUtilsService.instOf(src, ImageWMS) || HsUtilsService.instOf(src, TileWMS)) {
          json.className = 'HSLayers.Layer.WMS';
          json.singleTile = HsUtilsService.instOf(src, ImageWMS);
          if (layer.get('legends')) {
            json.legends = [];
            const legends = layer.get('legends');
            for (let i = 0; i < legends.length; i++) {
              json.legends.push(encodeURIComponent(legends[i]));
            }
          }
          if (src.getProjection()) {
            json.projection = src.getProjection().getCode().toLowerCase();
          }
          json.params = src.getParams();
          json.ratio = src.get('ratio') || src.ratio_;
          json.subLayers = layer.get('subLayers');
          json.metadata.styles = src.get('styles');
        }
        if (src.getUrl) {
          json.url = encodeURIComponent(src.getUrl());
        }
        if (src.getUrls) {
          json.url = encodeURIComponent(src.getUrls()[0]);
        }
        if (src.attributions_) {
          json.attributions = encodeURIComponent(src.attributions_);
        }
      }

      // Vector
      if (HsUtilsService.instOf(layer, VectorLayer)) {
        const src = layer.getSource();
        json.className = 'OpenLayers.Layer.Vector';
        const definition = layer.get('definition');
        if (
          angular.isDefined(definition) &&
          angular.isDefined(definition.url)
        ) {
          json.protocol = {
            url: encodeURIComponent(definition.url),
            format: definition.format,
          };
        } else {
          try {
            json.features = me.serializeFeatures(src.getFeatures());
          } catch (ex) {
            //Do nothing
          }
        }
        if (layer.get('synchronize')) {
          json.protocol = {format: 'hs.format.LaymanWfs'};
          delete json.features;
        }
        if (angular.isDefined(src.defOptions)) {
          json.defOptions = src.defOptions;
        }
        json.maxResolution = layer.getMaxResolution();
        json.minResolution = layer.getMinResolution();
        json.projection = 'epsg:4326';
        if (HsUtilsService.instOf(layer.getStyle(), Style)) {
          json.style = me.serializeStyle(layer.getStyle());
        }
      }
      return json;
    },

    /**
     * Convert feature array to GeoJSON string
     *
     * @memberof HsSaveMapService
     * @function serializeFeatures
     * @param {Array} features Array of features
     * @returns {string} GeoJSON string
     */
    serializeFeatures: function (features) {
      const f = new GeoJSON();
      return f.writeFeatures(features, {
        dataProjection: 'EPSG:4326',
        featureProjection: HsMapService.map.getView().getProjection().getCode(),
      });
    },

    /**
     * Generate random Uuid
     *
     * @memberof HsSaveMapService
     * @function generateUuid
     * @returns {string} Random Uuid in string format
     */
    generateUuid: HsUtilsService.generateUuid,

    /**
     * Create thumbnail of map view and save it into selected element
     *
     * @memberof HsSaveMapService
     * @function generateThumbnail
     * @param {$element} $element Selected element
     * @param {object} localThis Context to be passed to postcompose event handler
     * @param {boolean} newRender Force new render?
     */
    generateThumbnail: function ($element, localThis, newRender) {
      /**
       * @param event
       */
      function rendered(event) {
        const canvas = HsMapService.getCanvas();
        const canvas2 = $document[0].createElement('canvas');
        const width = 256,
          height = 256;
        canvas2.style.width = width + 'px';
        canvas2.style.height = height + 'px';
        canvas2.width = width;
        canvas2.height = height;
        const ctx2 = canvas2.getContext('2d');
        ctx2.drawImage(
          canvas,
          canvas.width / 2 - height / 2,
          canvas.height / 2 - width / 2,
          width,
          height,
          0,
          0,
          width,
          height
        );
        try {
          $element.setAttribute('src', canvas2.toDataURL('image/png'));
          this.thumbnail = canvas2.toDataURL('image/jpeg', 0.8);
        } catch (e) {
          $log.warn(e);
          $element.setAttribute('src', require('./notAvailable.png'));
        }
        $element.style.width = width + 'px';
        $element.style.height = height + 'px';
      }
      if (
        HsLayoutService.mainpanel == 'save-map' ||
        HsLayoutService.mainpanel == 'permalink' ||
        HsLayoutService.mainpanel == 'statusCreator'
      ) {
        if ($element === null) {
          return;
        }
        $element.setAttribute('crossOrigin', 'Anonymous');

        HsMapService.map.once('postcompose', rendered, localThis);
        if (newRender) {
          HsMapService.map.renderSync();
        } else {
          rendered();
        }
      }
    },
  };

  $window.addEventListener('beforeunload', (event) => {
    const data = {};
    const layers = [];
    angular.forEach(HsMapService.map.getLayers(), (layer) => {
      if (layer.get('saveState')) {
        layers.push(me.layer2json(layer));
      }
    });
    data.layers = layers;
    localStorage.setItem('hs_layers', angular.toJson(data));
  });
  return me;
}
<|endoftext|>


<commit_before>/*global define, window, clearTimeout*/
define([
    'jquery',
    'logger',
    'kernel',
    'jabbr/events',
    'livestamp'
], function ($, Logger, kernel, events) {
    var logger = new Logger('jabbr/viewmodels/message'),
        ru = null,
        client = null;

    events.bind(events.activated, function () {
        client = kernel.get('jabbr/client');

        logger.trace('activated');
    });

    function RoomUser(roomUi, user, roomName, room) {
        ru = roomUi;

        this.user = user;

        this.roomName = roomName;
        this.room = room;

        this.$roomUser = null;
    }

    RoomUser.prototype.bind = function () {
        this.$roomUser.find('.art').bind(
            "transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",
            $.proxy(this.artTransitionEnded, this)
        );
    };

    RoomUser.prototype.setOwner = function (isOwner) {
        var $roomUser = this.$roomUser.data('owner', isOwner);

        if (isOwner) {
            $roomUser.attr('data-owner', true);
        } else {
            $roomUser.removeAttr('data-owner');
        }

        this.room.updateUserStatus($roomUser);
    };

    RoomUser.prototype.setAdmin = function (isAdmin) {
        var $roomUser = this.$roomUser.data('admin', isAdmin);

        if (isAdmin) {
            $roomUser.attr('data-admin', true)
                     .find('.admin')
                     .text('(admin)');
        } else {
            $roomUser.removeAttr('data-admin')
                     .find('.admin')
                     .text('');
        }

        this.room.updateUserStatus($roomUser);
    };

    RoomUser.prototype.setActive = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.$roomUser.data('active') === true) {
            return false;
        }

        this.$roomUser.attr('data-active', true);
        this.$roomUser.data('active', true);
        this.$roomUser.removeClass('inactive');

        if ($inactiveSince.livestamp('isLiveStamp')) {
            $inactiveSince.livestamp('destroy');
        }

        return true;
    };

    RoomUser.prototype.setInActive = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.$roomUser.data('active') === false) {
            return false;
        }

        this.$roomUser.attr('data-active', false);
        this.$roomUser.data('active', false);
        this.$roomUser.addClass('inactive');

        if (!$inactiveSince.html()) {
            $inactiveSince.livestamp(new Date());
        }

        return true;
    };

    RoomUser.prototype.updateNote = function () {
        var $extended = this.$roomUser.find('.extended'),
            $note = $extended.find('.note'),
            noteText = this.user.note,
            noteTextEncoded = null,
            requireRoomUpdate = false;

        if (this.user.noteClass === 'afk') {
            noteText = this.user.note + ' (' + this.user.timeAgo + ')';
            requireRoomUpdate = this.setInActive();
        } else if (this.user.active) {
            requireRoomUpdate = this.setActive();
        } else {
            requireRoomUpdate = this.setInActive();
        }

        noteTextEncoded = $('
').html(noteText).text();

        // Update note
        if (this.user.note) {
            // Add note status element if one doesn't exist
            if ($note.length === 0) {
                $note = $('

');

                $extended.append($note);
            }

            $note.attr('title', noteTextEncoded);
            $('span', $note).text(noteTextEncoded);
        } else {
            $note.remove();
        }

        this.updateExtended();

        if (requireRoomUpdate) {
            this.$roomUser.each(function () {
                var room = ru.getRoomElements($(this).data('inroom'));
                room.updateUserStatus($(this));
                room.sortLists($(this));
            });
        }
    };

    RoomUser.prototype.updateFlag = function () {
        var $flag = this.$roomUser.find('.flag');

        $flag.removeAttr('class');
        $flag.addClass('flag');
        $flag.removeAttr('title');

        if (this.user.flagClass) {
            $flag.addClass(this.user.flagClass);
            $flag.show();
        } else {
            $flag.hide();
        }

        if (this.user.country) {
            $flag.attr('title', this.user.country);
        }
    };

    RoomUser.prototype.updateExternalStatus = function () {
        var $extended = this.$roomUser.find('.extended'),
            $externalStatus = $extended.find('.external-status');

        if ($externalStatus.length === 0) {
            $externalStatus = $('

');

            $externalStatus.hover(
                $.proxy(this.statusHoverEnter, this),
                $.proxy(this.statusHoverLeave, this)
            );

            $extended.prepend($externalStatus);
        }

        if (this.user.status_type !== null &&
            this.user.status_result !== null) {
            var result = this.user.status_result;

            var $titleSpan = $('span', $externalStatus),
                tooltipFragments = [];

            $titleSpan.empty();

            // Construct title and tooltip from result
            if (result.titles !== undefined) {
                for (var i = 0; i < result.titles.length; i++) {
                    var title = result.titles[i];

                    // Construct status elements from non-extended titles
                    if (title.extended === undefined || title.extended == false) {
                        var $elem;

                        if (title.url !== undefined) {
                            $elem = $('');

                            $elem.attr('href', title.url)
                                .text(title.value);
                        } else {
                            $elem = $('');

                            $elem.text(title.value);
                        }

                        $titleSpan.append($elem);

                        // Insert separator
                        if (i < result.titles.length - 1) {
                            $titleSpan.append(' - ');
                        }
                    }

                    tooltipFragments.push(title.value);
                }
            }

            // Update Tooltip
            $externalStatus.attr('title', tooltipFragments.join(' - '));

            // Set status icon
            if (this.user.status_type == 'music') {
                $('i', $externalStatus).attr('class', 'icon-music');
            } else if (this.user.status_type == 'video') {
                $('i', $externalStatus).attr('class', 'icon-film');
            } else if (this.user.status_type == 'game') {
                $('i', $externalStatus).attr('class', 'icon-gamepad');
            }

            // Animate status art
            var $statusArt = this.$roomUser.find('.art .status');

            if (result.art !== undefined) {
                this.updateStatusArt(result.art);
            } else {
                $statusArt.css('background-image', '');
            }
        } else {
            $externalStatus.remove();
        }

        this.updateExtended();
    };

    RoomUser.prototype.updateStatusArt = function (url) {
        if (url === null || url.length == 0) {
            return;
        }

        var $art = this.$roomUser.find('.art'),
            $statusArt = $art.find('.status');

        $statusArt.attr('class', 'status ' + this.user.status_source);

        // Ensure we aren't already preloading
        if ($art.data('preloading') === true) {
            return;
        }

        $art.data('preloading', true);

        var c = new Image();

        c.onload = $.proxy(function () {
            $art.data('preloading', false);

            $statusArt.css('background-image', "url('" + url + "')");

            // Ensure we only animate from gravatar state
            if ($art.hasClass('show-gravatar')) {
                $art.removeClass('show-gravatar').addClass('show-status');
            }
        }, this);

        c.src = url;
    };

    RoomUser.prototype.artTransitionEnded = function () {
        var $art = this.$roomUser.find('.art');

        if ($art.hasClass('show-status') && !$art.data('transition-ended') && !$art.data('manual')) {
            $art.data('transition-ended', true);

            $art.delay(5000).queue(function (next) {
                // Re-check to ensure we haven't manually triggered the animation since the delay
                if (!$art.data('manual')) {
                    $(this).removeClass('show-status')
                        .addClass('show-gravatar')
                        .data('transition-ended', false);
                }

                next();
            });
        }
    };

    RoomUser.prototype.statusHoverEnter = function () {
        var $art = this.$roomUser.find('.art');

        $art.data('manual', true)
            .removeClass('show-gravatar')
            .addClass('show-status');
    };

    RoomUser.prototype.statusHoverLeave = function () {
        var $art = this.$roomUser.find('.art');

        $art.data('manual', false)
            .removeClass('show-status')
            .addClass('show-gravatar');
    };

    RoomUser.prototype.updateActivity = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.user.active === true) {
            if (this.$roomUser.hasClass('inactive')) {
                this.$roomUser.removeClass('inactive');
                $inactiveSince.livestamp('destroy');
            }
        } else {
            if (!this.$roomUser.hasClass('inactive')) {
                this.$roomUser.addClass('inactive');
            }

            if (!$inactiveSince.html()) {
                $inactiveSince.livestamp(this.user.lastActive);
            }
        }

        this.updateNote();
    };

    RoomUser.prototype.updateExtended = function () {
        var $extended = this.$roomUser.find('.extended'),
            $items = $extended.find('li');

        if ($items.length === 2) {
            $extended.addClass('dual');
        } else {
            $extended.removeClass('dual');
        }
    };

    RoomUser.prototype.setTyping = function () {
        var $roomUser = this.$roomUser,
            timeout = null;

        // Do not show typing indicator for current user
        if (this.user.name === client.chat.state.name) {
            return;
        }

        // Mark the user as typing
        $roomUser.addClass('typing');
        $(".user-status-container", $roomUser).addClass('animated pulse');
        var oldTimeout = $roomUser.data('typing');

        if (oldTimeout) {
            clearTimeout(oldTimeout);
        }

        timeout = window.setTimeout(function () {
            $roomUser.removeClass('typing');
            $(".user-status-container", $roomUser).removeClass('animated pulse');
        },
            3000);

        $roomUser.data('typing', timeout);
    };

    RoomUser.prototype.updateUserName = function () {
        var user = this.user;

        this.$roomUser.find('.name').fadeOut('normal', function () {
            $(this).html(user.name);
            $(this).fadeIn('normal');
        });

        this.$roomUser.data('name', user.name);
        this.$roomUser.attr('data-name', user.name);
        this.room.sortLists(this.$roomUser);
    };

    RoomUser.prototype.updateGravatar = function () {
        var src = 'https://secure.gravatar.com/avatar/' + this.user.hash + '?s=16&d=mm';

        this.$roomUser.find('.gravatar').attr('src', src);
    };

    RoomUser.prototype.updateMentions = function () {
        this.$roomUser.data('mention', this.user.mention);
        this.$roomUser.attr('data-mention', this.user.mention);
    };

    return RoomUser;
});<commit_msg>jshint fixes<commit_after>/*global define, window, clearTimeout*/
define([
    'jquery',
    'logger',
    'kernel',
    'jabbr/events',
    'livestamp'
], function ($, Logger, kernel, events) {
    var logger = new Logger('jabbr/viewmodels/message'),
        ru = null,
        client = null;

    events.bind(events.activated, function () {
        client = kernel.get('jabbr/client');

        logger.trace('activated');
    });

    function RoomUser(roomUi, user, roomName, room) {
        ru = roomUi;

        this.user = user;

        this.roomName = roomName;
        this.room = room;

        this.$roomUser = null;
    }

    RoomUser.prototype.bind = function () {
        this.$roomUser.find('.art').bind(
            "transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",
            $.proxy(this.artTransitionEnded, this)
        );
    };

    RoomUser.prototype.setOwner = function (isOwner) {
        var $roomUser = this.$roomUser.data('owner', isOwner);

        if (isOwner) {
            $roomUser.attr('data-owner', true);
        } else {
            $roomUser.removeAttr('data-owner');
        }

        this.room.updateUserStatus($roomUser);
    };

    RoomUser.prototype.setAdmin = function (isAdmin) {
        var $roomUser = this.$roomUser.data('admin', isAdmin);

        if (isAdmin) {
            $roomUser.attr('data-admin', true)
                     .find('.admin')
                     .text('(admin)');
        } else {
            $roomUser.removeAttr('data-admin')
                     .find('.admin')
                     .text('');
        }

        this.room.updateUserStatus($roomUser);
    };

    RoomUser.prototype.setActive = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.$roomUser.data('active') === true) {
            return false;
        }

        this.$roomUser.attr('data-active', true);
        this.$roomUser.data('active', true);
        this.$roomUser.removeClass('inactive');

        if ($inactiveSince.livestamp('isLiveStamp')) {
            $inactiveSince.livestamp('destroy');
        }

        return true;
    };

    RoomUser.prototype.setInActive = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.$roomUser.data('active') === false) {
            return false;
        }

        this.$roomUser.attr('data-active', false);
        this.$roomUser.data('active', false);
        this.$roomUser.addClass('inactive');

        if (!$inactiveSince.html()) {
            $inactiveSince.livestamp(new Date());
        }

        return true;
    };

    RoomUser.prototype.updateNote = function () {
        var $extended = this.$roomUser.find('.extended'),
            $note = $extended.find('.note'),
            noteText = this.user.note,
            noteTextEncoded = null,
            requireRoomUpdate = false;

        if (this.user.noteClass === 'afk') {
            noteText = this.user.note + ' (' + this.user.timeAgo + ')';
            requireRoomUpdate = this.setInActive();
        } else if (this.user.active) {
            requireRoomUpdate = this.setActive();
        } else {
            requireRoomUpdate = this.setInActive();
        }

        noteTextEncoded = $('
').html(noteText).text();

        // Update note
        if (this.user.note) {
            // Add note status element if one doesn't exist
            if ($note.length === 0) {
                $note = $('

');

                $extended.append($note);
            }

            $note.attr('title', noteTextEncoded);
            $('span', $note).text(noteTextEncoded);
        } else {
            $note.remove();
        }

        this.updateExtended();

        if (requireRoomUpdate) {
            this.$roomUser.each(function () {
                var room = ru.getRoomElements($(this).data('inroom'));
                room.updateUserStatus($(this));
                room.sortLists($(this));
            });
        }
    };

    RoomUser.prototype.updateFlag = function () {
        var $flag = this.$roomUser.find('.flag');

        $flag.removeAttr('class');
        $flag.addClass('flag');
        $flag.removeAttr('title');

        if (this.user.flagClass) {
            $flag.addClass(this.user.flagClass);
            $flag.show();
        } else {
            $flag.hide();
        }

        if (this.user.country) {
            $flag.attr('title', this.user.country);
        }
    };

    RoomUser.prototype.updateExternalStatus = function () {
        var $extended = this.$roomUser.find('.extended'),
            $externalStatus = $extended.find('.external-status');

        if ($externalStatus.length === 0) {
            $externalStatus = $('

');

            $externalStatus.hover(
                $.proxy(this.statusHoverEnter, this),
                $.proxy(this.statusHoverLeave, this)
            );

            $extended.prepend($externalStatus);
        }

        if (this.user.status_type !== null &&
            this.user.status_result !== null) {
            var result = this.user.status_result;

            var $titleSpan = $('span', $externalStatus),
                tooltipFragments = [];

            $titleSpan.empty();

            // Construct title and tooltip from result
            if (result.titles !== undefined) {
                for (var i = 0; i < result.titles.length; i++) {
                    var title = result.titles[i];

                    // Construct status elements from non-extended titles
                    if (title.extended === undefined || title.extended === false) {
                        var $elem;

                        if (title.url !== undefined) {
                            $elem = $('');

                            $elem.attr('href', title.url)
                                .text(title.value);
                        } else {
                            $elem = $('');

                            $elem.text(title.value);
                        }

                        $titleSpan.append($elem);

                        // Insert separator
                        if (i < result.titles.length - 1) {
                            $titleSpan.append(' - ');
                        }
                    }

                    tooltipFragments.push(title.value);
                }
            }

            // Update Tooltip
            $externalStatus.attr('title', tooltipFragments.join(' - '));

            // Set status icon
            if (this.user.status_type == 'music') {
                $('i', $externalStatus).attr('class', 'icon-music');
            } else if (this.user.status_type == 'video') {
                $('i', $externalStatus).attr('class', 'icon-film');
            } else if (this.user.status_type == 'game') {
                $('i', $externalStatus).attr('class', 'icon-gamepad');
            }

            // Animate status art
            var $statusArt = this.$roomUser.find('.art .status');

            if (result.art !== undefined) {
                this.updateStatusArt(result.art);
            } else {
                $statusArt.css('background-image', '');
            }
        } else {
            $externalStatus.remove();
        }

        this.updateExtended();
    };

    RoomUser.prototype.updateStatusArt = function (url) {
        if (url === null || url.length === 0) {
            return;
        }

        var $art = this.$roomUser.find('.art'),
            $statusArt = $art.find('.status');

        $statusArt.attr('class', 'status ' + this.user.status_source);

        // Ensure we aren't already preloading
        if ($art.data('preloading') === true) {
            return;
        }

        $art.data('preloading', true);

        var c = new Image();

        c.onload = $.proxy(function () {
            $art.data('preloading', false);

            $statusArt.css('background-image', "url('" + url + "')");

            // Ensure we only animate from gravatar state
            if ($art.hasClass('show-gravatar')) {
                $art.removeClass('show-gravatar').addClass('show-status');
            }
        }, this);

        c.src = url;
    };

    RoomUser.prototype.artTransitionEnded = function () {
        var $art = this.$roomUser.find('.art');

        if ($art.hasClass('show-status') && !$art.data('transition-ended') && !$art.data('manual')) {
            $art.data('transition-ended', true);

            $art.delay(5000).queue(function (next) {
                // Re-check to ensure we haven't manually triggered the animation since the delay
                if (!$art.data('manual')) {
                    $(this).removeClass('show-status')
                        .addClass('show-gravatar')
                        .data('transition-ended', false);
                }

                next();
            });
        }
    };

    RoomUser.prototype.statusHoverEnter = function () {
        var $art = this.$roomUser.find('.art');

        $art.data('manual', true)
            .removeClass('show-gravatar')
            .addClass('show-status');
    };

    RoomUser.prototype.statusHoverLeave = function () {
        var $art = this.$roomUser.find('.art');

        $art.data('manual', false)
            .removeClass('show-status')
            .addClass('show-gravatar');
    };

    RoomUser.prototype.updateActivity = function () {
        var $inactiveSince = this.$roomUser.find('.inactive-since');

        if (this.user.active === true) {
            if (this.$roomUser.hasClass('inactive')) {
                this.$roomUser.removeClass('inactive');
                $inactiveSince.livestamp('destroy');
            }
        } else {
            if (!this.$roomUser.hasClass('inactive')) {
                this.$roomUser.addClass('inactive');
            }

            if (!$inactiveSince.html()) {
                $inactiveSince.livestamp(this.user.lastActive);
            }
        }

        this.updateNote();
    };

    RoomUser.prototype.updateExtended = function () {
        var $extended = this.$roomUser.find('.extended'),
            $items = $extended.find('li');

        if ($items.length === 2) {
            $extended.addClass('dual');
        } else {
            $extended.removeClass('dual');
        }
    };

    RoomUser.prototype.setTyping = function () {
        var $roomUser = this.$roomUser,
            timeout = null;

        // Do not show typing indicator for current user
        if (this.user.name === client.chat.state.name) {
            return;
        }

        // Mark the user as typing
        $roomUser.addClass('typing');
        $(".user-status-container", $roomUser).addClass('animated pulse');
        var oldTimeout = $roomUser.data('typing');

        if (oldTimeout) {
            clearTimeout(oldTimeout);
        }

        timeout = window.setTimeout(function () {
            $roomUser.removeClass('typing');
            $(".user-status-container", $roomUser).removeClass('animated pulse');
        },
            3000);

        $roomUser.data('typing', timeout);
    };

    RoomUser.prototype.updateUserName = function () {
        var user = this.user;

        this.$roomUser.find('.name').fadeOut('normal', function () {
            $(this).html(user.name);
            $(this).fadeIn('normal');
        });

        this.$roomUser.data('name', user.name);
        this.$roomUser.attr('data-name', user.name);
        this.room.sortLists(this.$roomUser);
    };

    RoomUser.prototype.updateGravatar = function () {
        var src = 'https://secure.gravatar.com/avatar/' + this.user.hash + '?s=16&d=mm';

        this.$roomUser.find('.gravatar').attr('src', src);
    };

    RoomUser.prototype.updateMentions = function () {
        this.$roomUser.data('mention', this.user.mention);
        this.$roomUser.attr('data-mention', this.user.mention);
    };

    return RoomUser;
});<|endoftext|>


<commit_before>export default function Auth0 () {}

Auth0.version = 'mock'
Auth0.clientInfo = { name: 'auth0.js', version: Auth0.version }

Auth0.prototype.refreshToken = function (token, callback) {
  if (token === 'token-that-produces-error') {
    callback('an error')
  } else {
    callback(null, { id_token: 'fake-token' })
  }
}
<commit_msg>refactor(auth0): remove unneeded mock for auth0-js<commit_after><|endoftext|>


<commit_before>function location_widget(el) {
    widget = $('#widget-location');
    widget.insertAfter(el);
    widget.show();

    if (!widget.data('isInitialized')) {
        map = new OpenLayers.Map (widget.find('.map').get(0), {
            controls:[
                new OpenLayers.Control.Navigation(),
                new OpenLayers.Control.PanZoomBar(),
                new OpenLayers.Control.ScaleLine(),
                //new OpenLayers.Control.LayerSwitcher(),
                new OpenLayers.Control.MousePosition(),
                new OpenLayers.Control.Attribution()],
            maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
                        maxResolution: 156543.0399,
            numZoomLevels: 19,
            units: 'm',
            projection: new OpenLayers.Projection("EPSG:900913"),
            //projection: new OpenLayers.Projection("EPSG:4326"),
            displayProjection: new OpenLayers.Projection("EPSG:4326")
        } );

        layer_osm = new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap");
        layer_osm.attribution = 'Map ' + layer_osm.attribution;
        map.addLayer(layer_osm);

        layer_vector = new OpenLayers.Layer.Vector("Vectors", {
            projection: new OpenLayers.Projection("EPSG:4326"),
        });
        map.addLayer(layer_vector);

        var style = {
            externalGraphic: STATIC_URL + "openresources/images/marker.png",
            graphicWidth: 21,
            graphicHeight: 25,
            graphicXOffset: -10,
            graphicYOffset: -25,
            graphicTitle: 'Current Location',
            cursor: 'pointer',
            graphicOpacity:0.7
        }

        var marker = null;
        var lonLat = new OpenLayers.LonLat(16.35, 48.2).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());

        var value = $(el).html();
        if (value.startsWith("lonlat:")) {
          try {
              value = value.substring(7);
              value = value.split(",");
              lonLat = new OpenLayers.LonLat(parseFloat(value[0]), parseFloat(value[1])).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
              marker = new OpenLayers.Feature.Vector(
                 new OpenLayers.Geometry.Point(parseFloat(value[0]), parseFloat(value[1])).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),
                 {title: 'Location'},
                 style);
              layer_vector.addFeatures([marker]);
           }
           catch(ex) {
                // fail silently in case of parse error
           }
        }

        map.setCenter (lonLat, 4);

        /*
        var control = new OpenLayers.Control.DrawFeature(layer_vector,
                            OpenLayers.Handler.Point, {
                                featureAdded: function(feature) {
                                        if (marker) {
                                            layer_vector.destroyFeatures([marker]);
                                        }
                                        marker = feature;

                                        p2 = feature.geometry.transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
                                        $(el).html('lonlat:' + p2.x + ',' + p2.y);
                                    }
                                });
        */

        var control = new OpenLayers.Control();
        OpenLayers.Util.extend(control, {
            draw: function () {
                // this Handler.Box will intercept the shift-mousedown
                // before Control.MouseDefault gets to see it
                this.click_handler = new OpenLayers.Handler.Click( control, {
                     //pixelTolerance: 20,
                    click: function(ev){
                        lonLat = this.map.getLonLatFromPixel(ev.xy);
                        if (!lonLat) {
                            // map has not yet been properly initialized
                            return;
                        }
                        if (this.displayProjection) {
                            lonLat.transform(this.map.getProjectionObject(),
                                             this.displayProjection );
                        }
                        $(el).html('lonlat:' + lonLat.lon + ',' + lonLat.lat);

                        if (marker) {
                             layer_vector.destroyFeatures([marker]);
                        }
                         marker = new OpenLayers.Feature.Vector(
                             new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),
                             {title: 'Location'},
                             style);
                         layer_vector.addFeatures([marker]);
                    }});
                this.click_handler.activate();
            }
        });
        map.addControl(control);
        control.activate();

        widget.data('isInitialized', true);
    }
}

function choice_widget(el, key) {
    var widget = $('
loading choices...
');
    widget.insertAfter(el);
    widget.show();

    $.getJSON('/resources/tag/' + key + '/choices.json',function(data) {
        var ul = $('Existing Values: <select><option value="">-</option></select>');
        for (var i=0; i<data.choices.length; i++) {
           ul.append('<option value="' + data.choices[i] + '">' + data.choices[i] + '</option>');
        }
        widget.html('');
        widget.append(ul);

        ul.change(function(ev) {
            $(el).val(ul.val());
        });
    });
}

function resource_choice(el, key) {
    var widget = $('
loading choices...
');
    widget.insertAfter(el);
    widget.show();

    $.getJSON('/resources/choices.json',function(data) {
        var ul = $('Resource: <select><option value="">-</option></select>');
        for (var i=0; i<data.choices.length; i++) {
           ul.append('<option value="' + data.choices[i] + '">' + data.choices[i] + '</option>');
        }
        widget.html('');
        widget.append(ul);

        ul.change(function(ev) {
            $(el).val(ul.val());
        });
    });
}

var editor_lookup = {
    'location': location_widget,
    'activity': choice_widget,
    'lang': choice_widget,
    'mode_of_production': choice_widget,
    'mode_of_access': choice_widget,
    'mode_of_distribution': choice_widget,
    'decisionmaking': choice_widget,
    'motivation': choice_widget,
    'category': choice_widget,
    'spatial_unit': choice_widget,
    'organizational_unit': choice_widget,
    'organizational_type': choice_widget,
    'organisationsform': choice_widget,
    'ownership': choice_widget,
    'license': choice_widget,
    'part_of': resource_choice,
    'available_at': resource_choice,
    'hosted_by': resource_choice
}

jQuery(function($) {
    if ($('.advanced .errorlist li').size() > 0) {
        $('.advanced').show();
    }
    $('#id_shortname, #id_view-shortname').change(function() {
        this._dirty = true;
    });
    $('#id_shortname, #id_view-shortname').each(function() {
        if (this.value) this._dirty = true;
    });
    $('#id_name, #id_view-name, #id_view-name_en').keyup(function() {
        var el = $('#id_shortname, #id_view-shortname');
        if (! el[0]._dirty) {
            el.val(URLify($(this).val(), 100));
        }
    });

    /*
    $('input[type=text][id$=-key]').change(function() {
        var key_field = $(this);
        var key = key_field.val();

        var widget = editor_lookup[key];
        if (widget) {
            var value_field_id = this.id.substring(0, this.id.indexOf('-key')) + '-value';

            var value_field = $('#' + value_field_id);

            value_field.after('
' + widget + '
');
            //value_field.css({'display': 'none'});
        }
    });
    */

    $('textarea').focus(function() {
        $('.widget').hide();
        var key = $(this).parents('tr').find('td input[name$="-key"]').val();
        var widget_func = editor_lookup[key];
        if (widget_func) {
            widget_func(this, key);
        }

    });

    $('.popular-tags').change(function(ev) {
    	var $table = $(this).parents('.edit-table')
        $table.find('tr.extra td.edit-key input[type=text]').val($(this).val());
        ev.preventDefault();
        $table.find('tr.extra td.edit-value textarea')[0].focus();
    });

    $('.combo-select').change(function(ev) {
        var id = this.id.substring(0,this.id.length - 7); // our id is target_id + "_SELECT"
        $('#'+id).val($(this).val());
        ev.preventDefault();
        $(this).parents('tr').find('textarea')[0].focus();
    });
});

/*
TODO:
http://djangosnippets.org/snippets/1389/

function updateElementIndex(el, prefix, ndx) {
		var id_regex = new RegExp('(' + prefix + '-\\d+)');
		var replacement = prefix + '-' + ndx;
		if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
		if (el.id) el.id = el.id.replace(id_regex, replacement);
		if (el.name) el.name = el.name.replace(id_regex, replacement);
	}

    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        var row = $('.dynamic-form:first').clone(true).get(0);
        $(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
        $(row).children().not(':last').children().each(function() {
    	    updateElementIndex(this, prefix, formCount);
    	    $(this).val('');
        });
        $(row).find('.delete-row').click(function() {
    	    deleteForm(this, prefix);
        });
        $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
        return false;
    }

    function deleteForm(btn, prefix) {
        $(btn).parents('.dynamic-form').remove();
        var forms = $('.dynamic-form');
        $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
        for (var i=0, formCount=forms.length; i<formCount; i++) {
    	    $(forms.get(i)).children().not(':last').children().each(function() {
    	        updateElementIndex(this, prefix, i);
    	    });
        }
        return false;
    }
*/
<commit_msg>fix marker url<commit_after>function location_widget(el) {
    widget = $('#widget-location');
    widget.insertAfter(el);
    widget.show();

    if (!widget.data('isInitialized')) {
        map = new OpenLayers.Map (widget.find('.map').get(0), {
            controls:[
                new OpenLayers.Control.Navigation(),
                new OpenLayers.Control.PanZoomBar(),
                new OpenLayers.Control.ScaleLine(),
                //new OpenLayers.Control.LayerSwitcher(),
                new OpenLayers.Control.MousePosition(),
                new OpenLayers.Control.Attribution()],
            maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
                        maxResolution: 156543.0399,
            numZoomLevels: 19,
            units: 'm',
            projection: new OpenLayers.Projection("EPSG:900913"),
            //projection: new OpenLayers.Projection("EPSG:4326"),
            displayProjection: new OpenLayers.Projection("EPSG:4326")
        } );

        layer_osm = new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap");
        layer_osm.attribution = 'Map ' + layer_osm.attribution;
        map.addLayer(layer_osm);

        layer_vector = new OpenLayers.Layer.Vector("Vectors", {
            projection: new OpenLayers.Projection("EPSG:4326"),
        });
        map.addLayer(layer_vector);

        var style = {
            externalGraphic: STATIC_URL + "openresources/map_marker/marker.png",
            graphicWidth: 21,
            graphicHeight: 25,
            graphicXOffset: -10,
            graphicYOffset: -25,
            graphicTitle: 'Current Location',
            cursor: 'pointer',
            graphicOpacity:0.7
        }

        var marker = null;
        var lonLat = new OpenLayers.LonLat(16.35, 48.2).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());

        var value = $(el).html();
        if (value.startsWith("lonlat:")) {
          try {
              value = value.substring(7);
              value = value.split(",");
              lonLat = new OpenLayers.LonLat(parseFloat(value[0]), parseFloat(value[1])).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
              marker = new OpenLayers.Feature.Vector(
                 new OpenLayers.Geometry.Point(parseFloat(value[0]), parseFloat(value[1])).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),
                 {title: 'Location'},
                 style);
              layer_vector.addFeatures([marker]);
           }
           catch(ex) {
                // fail silently in case of parse error
           }
        }

        map.setCenter (lonLat, 4);

        /*
        var control = new OpenLayers.Control.DrawFeature(layer_vector,
                            OpenLayers.Handler.Point, {
                                featureAdded: function(feature) {
                                        if (marker) {
                                            layer_vector.destroyFeatures([marker]);
                                        }
                                        marker = feature;

                                        p2 = feature.geometry.transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
                                        $(el).html('lonlat:' + p2.x + ',' + p2.y);
                                    }
                                });
        */

        var control = new OpenLayers.Control();
        OpenLayers.Util.extend(control, {
            draw: function () {
                // this Handler.Box will intercept the shift-mousedown
                // before Control.MouseDefault gets to see it
                this.click_handler = new OpenLayers.Handler.Click( control, {
                     //pixelTolerance: 20,
                    click: function(ev){
                        lonLat = this.map.getLonLatFromPixel(ev.xy);
                        if (!lonLat) {
                            // map has not yet been properly initialized
                            return;
                        }
                        if (this.displayProjection) {
                            lonLat.transform(this.map.getProjectionObject(),
                                             this.displayProjection );
                        }
                        $(el).html('lonlat:' + lonLat.lon + ',' + lonLat.lat);

                        if (marker) {
                             layer_vector.destroyFeatures([marker]);
                        }
                         marker = new OpenLayers.Feature.Vector(
                             new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),
                             {title: 'Location'},
                             style);
                         layer_vector.addFeatures([marker]);
                    }});
                this.click_handler.activate();
            }
        });
        map.addControl(control);
        control.activate();

        widget.data('isInitialized', true);
    }
}

function choice_widget(el, key) {
    var widget = $('
loading choices...
');
    widget.insertAfter(el);
    widget.show();

    $.getJSON('/resources/tag/' + key + '/choices.json',function(data) {
        var ul = $('Existing Values: <select><option value="">-</option></select>');
        for (var i=0; i<data.choices.length; i++) {
           ul.append('<option value="' + data.choices[i] + '">' + data.choices[i] + '</option>');
        }
        widget.html('');
        widget.append(ul);

        ul.change(function(ev) {
            $(el).val(ul.val());
        });
    });
}

function resource_choice(el, key) {
    var widget = $('
loading choices...
');
    widget.insertAfter(el);
    widget.show();

    $.getJSON('/resources/choices.json',function(data) {
        var ul = $('Resource: <select><option value="">-</option></select>');
        for (var i=0; i<data.choices.length; i++) {
           ul.append('<option value="' + data.choices[i] + '">' + data.choices[i] + '</option>');
        }
        widget.html('');
        widget.append(ul);

        ul.change(function(ev) {
            $(el).val(ul.val());
        });
    });
}

var editor_lookup = {
    'location': location_widget,
    'activity': choice_widget,
    'lang': choice_widget,
    'mode_of_production': choice_widget,
    'mode_of_access': choice_widget,
    'mode_of_distribution': choice_widget,
    'decisionmaking': choice_widget,
    'motivation': choice_widget,
    'category': choice_widget,
    'spatial_unit': choice_widget,
    'organizational_unit': choice_widget,
    'organizational_type': choice_widget,
    'organisationsform': choice_widget,
    'ownership': choice_widget,
    'license': choice_widget,
    'part_of': resource_choice,
    'available_at': resource_choice,
    'hosted_by': resource_choice
}

jQuery(function($) {
    if ($('.advanced .errorlist li').size() > 0) {
        $('.advanced').show();
    }
    $('#id_shortname, #id_view-shortname').change(function() {
        this._dirty = true;
    });
    $('#id_shortname, #id_view-shortname').each(function() {
        if (this.value) this._dirty = true;
    });
    $('#id_name, #id_view-name, #id_view-name_en').keyup(function() {
        var el = $('#id_shortname, #id_view-shortname');
        if (! el[0]._dirty) {
            el.val(URLify($(this).val(), 100));
        }
    });

    /*
    $('input[type=text][id$=-key]').change(function() {
        var key_field = $(this);
        var key = key_field.val();

        var widget = editor_lookup[key];
        if (widget) {
            var value_field_id = this.id.substring(0, this.id.indexOf('-key')) + '-value';

            var value_field = $('#' + value_field_id);

            value_field.after('
' + widget + '
');
            //value_field.css({'display': 'none'});
        }
    });
    */

    $('textarea').focus(function() {
        $('.widget').hide();
        var key = $(this).parents('tr').find('td input[name$="-key"]').val();
        var widget_func = editor_lookup[key];
        if (widget_func) {
            widget_func(this, key);
        }

    });

    $('.popular-tags').change(function(ev) {
    	var $table = $(this).parents('.edit-table')
        $table.find('tr.extra td.edit-key input[type=text]').val($(this).val());
        ev.preventDefault();
        $table.find('tr.extra td.edit-value textarea')[0].focus();
    });

    $('.combo-select').change(function(ev) {
        var id = this.id.substring(0,this.id.length - 7); // our id is target_id + "_SELECT"
        $('#'+id).val($(this).val());
        ev.preventDefault();
        $(this).parents('tr').find('textarea')[0].focus();
    });
});

/*
TODO:
http://djangosnippets.org/snippets/1389/

function updateElementIndex(el, prefix, ndx) {
		var id_regex = new RegExp('(' + prefix + '-\\d+)');
		var replacement = prefix + '-' + ndx;
		if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
		if (el.id) el.id = el.id.replace(id_regex, replacement);
		if (el.name) el.name = el.name.replace(id_regex, replacement);
	}

    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        var row = $('.dynamic-form:first').clone(true).get(0);
        $(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
        $(row).children().not(':last').children().each(function() {
    	    updateElementIndex(this, prefix, formCount);
    	    $(this).val('');
        });
        $(row).find('.delete-row').click(function() {
    	    deleteForm(this, prefix);
        });
        $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
        return false;
    }

    function deleteForm(btn, prefix) {
        $(btn).parents('.dynamic-form').remove();
        var forms = $('.dynamic-form');
        $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
        for (var i=0, formCount=forms.length; i<formCount; i++) {
    	    $(forms.get(i)).children().not(':last').children().each(function() {
    	        updateElementIndex(this, prefix, i);
    	    });
        }
        return false;
    }
*/
<|endoftext|>


<commit_before>function convertObjectToArray(obj) {
  var outputArray = [];

  Object.keys(obj).forEach(function (key) {
    var keyAsIndex = Number(key);
    if (!isNaN(keyAsIndex) && keyAsIndex > -1) {
      outputArray[keyAsIndex] = obj[key];
    } else {
      // attach it as a property
      outputArray[key] = obj[key];
    }
  });

  return outputArray;
}

function isComparingObjectAndArray(lhs, rhs) {
  var typeLhs = lhs && typeof lhs;
  var typeRhs = rhs && typeof rhs;

  return ((Array.isArray(lhs) && isObject(rhs)) ||
          (Array.isArray(rhs) && isObject(lhs)));
}

function isDate(x) {
  if (!x) {
    return false;
  }

  return Object.prototype.toString.call(x) === '[object Date]';
}

function isObject(x) {
  return typeof x === 'object';
}

function isRegExp(x) {
  return x instanceof RegExp;
}

function isString(x) {
  return typeof x === 'string';
}

function assertTheUnexpected(expect) {
  function AssertionError(err, assertMessage) {
    Error.call(this, '');

    this.name = 'AssertionError';

    if (assertMessage) {
      assertMessage = this.name + ': ' + assertMessage;
    }

    this.stack = (assertMessage ? assertMessage + '\n\n' : '') + err.stack;
    this.message = (assertMessage || '');
  }

  AssertionError.prototype = Object.create(Error.prototype);

  function createWrappedExpect(localExpect) {
    return function wrappedExpect() {
      var args = Array.prototype.slice.apply(arguments);
      // convert UnexpectedError to AssertionError
      try {
        localExpect.apply(localExpect, args);
      } catch (err) {
        throw new AssertionError(err);
      }
    };
  }

  var wrappedExpect = createWrappedExpect(expect);

  function checkTruthy(value) {
    wrappedExpect(value, 'to be truthy');
  }

  function prepareDeepEqual(actual, expected) {
    var a = actual;
    var b = expected;

    if (Array.isArray(a) && Array.isArray(b)) {
      a = a.slice(0);
      b = b.slice(0);

      for (var i = 0; i < a.length; i += 1) {
        var comparisonValues = prepareEqual(a[i], b[i]);
        a[i] = comparisonValues.a;
        b[i] = comparisonValues.b;
      }

      return {
        a: a,
        b: b
      };
    } else if (
        (isObject(a) && isObject(b)) &&
        !(isDate(a) && isDate(b)) &&
        !(isRegExp(a) && isRegExp(b)) &&
        !(a === null || b === null)
    ) {
      return {
        a: Object.assign({}, a),
        b: Object.assign({}, b)
      }
    } else if (isComparingObjectAndArray(a, b)) {
      if (Array.isArray(a)) {
        return {
          a: a,
          b: convertObjectToArray(b)
        };
      } else {
        return {
          a: convertObjectToArray(a),
          b: b
        };
      }
    }

    return null;
  }

  function prepareEqual(actual, expected) {
    var a = !actual;
    var b = !expected;

    // undo the null and undefined evaluate equal
    if (!(a && b) && !(typeof actual === 'boolean' || typeof expected === 'boolean')) {
      a = actual;
      b = expected;
    }

    if ((Number(a) || Number(b)) && (isString(a) || isString(b))) {
      a = String(a);
      b = String(b);
    }

    return {
      a: a,
      b: b
    };
  }

  return Object.assign(function (value) {
    checkTruthy(value);
  }, {
    AssertionError: AssertionError,
    deepEqual: function deepEqual(actual, expected) {
      var a = actual;
      var b = expected;
      var comparisonValues;

      // first type deep equal preparation
      comparisonValues = prepareDeepEqual(a, b);

      if (!comparisonValues && !(isObject(a) || isObject(b))) {
        comparisonValues = prepareEqual(a, b);
      }

      if (comparisonValues) {
        a = comparisonValues.a;
        b = comparisonValues.b;
      }

      wrappedExpect(a, 'to equal', b);

      // handle the lastIndex property
      if (actual instanceof RegExp && actual.hasOwnProperty('lastIndex')) {
        wrappedExpect(actual.lastIndex, 'to equal', expected.lastIndex);
      }
    },
    deepStrictEqual: function deepStrictEqual(actual, expected) {
      wrappedExpect(actual, 'to equal', expected);
    },
    equal: function equal(actual, expected) {
      var comarisonValues = prepareEqual(actual, expected);
      var a = comarisonValues.a;
      var b = comarisonValues.b;

      wrappedExpect(a, 'to be', b);
    },
    ifError: function ifError(value) {
      wrappedExpect(value, 'to be falsy').then(function () {
        throw value;
      });
    },
    notEqual: function notEqual(actual, expected) {
      wrappedExpect(actual, 'not to be', expected);
    },
    notDeepEqual: function notEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    notDeepStrictEqual: function notDeepStrictEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    notStrictEqual: function strictEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    ok: function (value) {
      checkTruthy(value);
    },
    strictEqual: function strictEqual(actual, expected) {
      wrappedExpect(actual, 'to equal', expected);
    },
  });
}

module.exports = assertTheUnexpected(require('unexpected'));
<commit_msg>Correct naming of not*Equal() functions.<commit_after>function convertObjectToArray(obj) {
  var outputArray = [];

  Object.keys(obj).forEach(function (key) {
    var keyAsIndex = Number(key);
    if (!isNaN(keyAsIndex) && keyAsIndex > -1) {
      outputArray[keyAsIndex] = obj[key];
    } else {
      // attach it as a property
      outputArray[key] = obj[key];
    }
  });

  return outputArray;
}

function isComparingObjectAndArray(lhs, rhs) {
  var typeLhs = lhs && typeof lhs;
  var typeRhs = rhs && typeof rhs;

  return ((Array.isArray(lhs) && isObject(rhs)) ||
          (Array.isArray(rhs) && isObject(lhs)));
}

function isDate(x) {
  if (!x) {
    return false;
  }

  return Object.prototype.toString.call(x) === '[object Date]';
}

function isObject(x) {
  return typeof x === 'object';
}

function isRegExp(x) {
  return x instanceof RegExp;
}

function isString(x) {
  return typeof x === 'string';
}

function assertTheUnexpected(expect) {
  function AssertionError(err, assertMessage) {
    Error.call(this, '');

    this.name = 'AssertionError';

    if (assertMessage) {
      assertMessage = this.name + ': ' + assertMessage;
    }

    this.stack = (assertMessage ? assertMessage + '\n\n' : '') + err.stack;
    this.message = (assertMessage || '');
  }

  AssertionError.prototype = Object.create(Error.prototype);

  function createWrappedExpect(localExpect) {
    return function wrappedExpect() {
      var args = Array.prototype.slice.apply(arguments);
      // convert UnexpectedError to AssertionError
      try {
        localExpect.apply(localExpect, args);
      } catch (err) {
        throw new AssertionError(err);
      }
    };
  }

  var wrappedExpect = createWrappedExpect(expect);

  function checkTruthy(value) {
    wrappedExpect(value, 'to be truthy');
  }

  function prepareDeepEqual(actual, expected) {
    var a = actual;
    var b = expected;

    if (Array.isArray(a) && Array.isArray(b)) {
      a = a.slice(0);
      b = b.slice(0);

      for (var i = 0; i < a.length; i += 1) {
        var comparisonValues = prepareEqual(a[i], b[i]);
        a[i] = comparisonValues.a;
        b[i] = comparisonValues.b;
      }

      return {
        a: a,
        b: b
      };
    } else if (
        (isObject(a) && isObject(b)) &&
        !(isDate(a) && isDate(b)) &&
        !(isRegExp(a) && isRegExp(b)) &&
        !(a === null || b === null)
    ) {
      return {
        a: Object.assign({}, a),
        b: Object.assign({}, b)
      }
    } else if (isComparingObjectAndArray(a, b)) {
      if (Array.isArray(a)) {
        return {
          a: a,
          b: convertObjectToArray(b)
        };
      } else {
        return {
          a: convertObjectToArray(a),
          b: b
        };
      }
    }

    return null;
  }

  function prepareEqual(actual, expected) {
    var a = !actual;
    var b = !expected;

    // undo the null and undefined evaluate equal
    if (!(a && b) && !(typeof actual === 'boolean' || typeof expected === 'boolean')) {
      a = actual;
      b = expected;
    }

    if ((Number(a) || Number(b)) && (isString(a) || isString(b))) {
      a = String(a);
      b = String(b);
    }

    return {
      a: a,
      b: b
    };
  }

  return Object.assign(function (value) {
    checkTruthy(value);
  }, {
    AssertionError: AssertionError,
    deepEqual: function deepEqual(actual, expected) {
      var a = actual;
      var b = expected;
      var comparisonValues;

      // first type deep equal preparation
      comparisonValues = prepareDeepEqual(a, b);

      if (!comparisonValues && !(isObject(a) || isObject(b))) {
        comparisonValues = prepareEqual(a, b);
      }

      if (comparisonValues) {
        a = comparisonValues.a;
        b = comparisonValues.b;
      }

      wrappedExpect(a, 'to equal', b);

      // handle the lastIndex property
      if (actual instanceof RegExp && actual.hasOwnProperty('lastIndex')) {
        wrappedExpect(actual.lastIndex, 'to equal', expected.lastIndex);
      }
    },
    deepStrictEqual: function deepStrictEqual(actual, expected) {
      wrappedExpect(actual, 'to equal', expected);
    },
    equal: function equal(actual, expected) {
      var comarisonValues = prepareEqual(actual, expected);
      var a = comarisonValues.a;
      var b = comarisonValues.b;

      wrappedExpect(a, 'to be', b);
    },
    ifError: function ifError(value) {
      wrappedExpect(value, 'to be falsy').then(function () {
        throw value;
      });
    },
    notEqual: function notEqual(actual, expected) {
      wrappedExpect(actual, 'not to be', expected);
    },
    notDeepEqual: function notDeepEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    notDeepStrictEqual: function notDeepStrictEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    notStrictEqual: function notStrictEqual(actual, expected) {
      wrappedExpect(actual, 'not to equal', expected);
    },
    ok: function (value) {
      checkTruthy(value);
    },
    strictEqual: function strictEqual(actual, expected) {
      wrappedExpect(actual, 'to equal', expected);
    },
  });
}

module.exports = assertTheUnexpected(require('unexpected'));
<|endoftext|>


<commit_before>mini.Module(
		"assets/assetmanager"
)
.requires(
		"basic/uniqueidgenerator"
)
.defines(function() {
	var AssetManager = {
			"maps": {}
	};

	AssetManager.hasMap = function(mapPath) {
		return typeof Bloob.AssetManager.maps[mapPath] !== "undefined";
	};

	AssetManager.addMap = function(mapPath, mapJson) {
		Bloob.AssetManager.maps[mapPath] = mapJson;
	};

	AssetManager.getMap = function(mapPath) {
		return Bloob.AssetManager.maps[mapPath];
	};

	Bloob.AssetManager = AssetManager;

	return AssetManager;
});

<commit_msg>clarified dependencies of AssetManager<commit_after>mini.Module(
	"assets/assetmanager"
)
.requires(

)
.defines(function() {
	var AssetManager = {
			"maps": {}
	};

	AssetManager.hasMap = function(mapPath) {
		return typeof AssetManager.maps[mapPath] !== "undefined";
	};

	AssetManager.addMap = function(mapPath, mapJson) {
		AssetManager.maps[mapPath] = mapJson;
	};

	AssetManager.getMap = function(mapPath) {
		return AssetManager.maps[mapPath];
	};

	return AssetManager;
});

<|endoftext|>


<commit_before>var DOMProperty = require('react-dom-core/lib/DOMProperty');
var propertyConfig = require('./property-config');
var styleToObject = require('style-to-object');
var utilities = require('./utilities');

var config = propertyConfig.config;
var isCustomAttribute = propertyConfig.HTMLDOMPropertyConfig.isCustomAttribute;
DOMProperty.injection.injectDOMPropertyConfig(
  propertyConfig.HTMLDOMPropertyConfig
);

/**
 * Makes attributes compatible with React props.
 *
 * @param  {Object} attributes - The attributes.
 * @return {Object}            - The props.
 */
function attributesToProps(attributes = {}) {
  var props = {};
  var propertyName;
  var propertyValue;
  var reactProperty;

  for (propertyName in attributes) {
    propertyValue = attributes[propertyName];

    // custom attributes (`data-` and `aria-`)
    if (isCustomAttribute(propertyName)) {
      props[propertyName] = propertyValue;
      continue;
    }

    // make HTML DOM attribute/property consistent with React attribute/property
    reactProperty = config.html[propertyName.toLowerCase()];
    if (reactProperty) {
      if (
        DOMProperty.properties.hasOwnProperty(reactProperty) &&
        DOMProperty.properties[reactProperty].hasBooleanValue
      ) {
        props[reactProperty] = true;
      } else {
        props[reactProperty] = propertyValue;
      }
      continue;
    }

    // make SVG DOM attribute/property consistent with React attribute/property
    reactProperty = config.svg[propertyName];
    if (reactProperty) {
      props[reactProperty] = propertyValue;
    } else if (utilities.reactSupportsUnknownAttributes()) {
      props[propertyName] = propertyValue;
    }
  }

  // convert inline style to object
  if (attributes.style != null) {
    props.style = cssToJs(attributes.style);
  }
  return props;
}

/**
 * Converts CSS style string to JS style object.
 *
 * @param  {String} style - The CSS style.
 * @return {Object}       - The JS style object.
 */
function cssToJs(style) {
  if (typeof style !== 'string') {
    throw new TypeError('First argument must be a string.');
  }
  var styleObj = {};

  styleToObject(style, function(propName, propValue) {
    // Check if it's not a comment node
    if (propName && propValue) {
      styleObj[utilities.camelCase(propName)] = propValue;
    }
  });
  return styleObj;
}

module.exports = attributesToProps;
<commit_msg>fix(attributes-to-props): undo default function parameter<commit_after>var DOMProperty = require('react-dom-core/lib/DOMProperty');
var propertyConfig = require('./property-config');
var styleToObject = require('style-to-object');
var utilities = require('./utilities');

var config = propertyConfig.config;
var isCustomAttribute = propertyConfig.HTMLDOMPropertyConfig.isCustomAttribute;
DOMProperty.injection.injectDOMPropertyConfig(
  propertyConfig.HTMLDOMPropertyConfig
);

/**
 * Makes attributes compatible with React props.
 *
 * @param  {Object} [attributes={}] - The attributes.
 * @return {Object}                 - The props.
 */
function attributesToProps(attributes) {
  attributes = attributes || {};
  var props = {};
  var propertyName;
  var propertyValue;
  var reactProperty;

  for (propertyName in attributes) {
    propertyValue = attributes[propertyName];

    // custom attributes (`data-` and `aria-`)
    if (isCustomAttribute(propertyName)) {
      props[propertyName] = propertyValue;
      continue;
    }

    // make HTML DOM attribute/property consistent with React attribute/property
    reactProperty = config.html[propertyName.toLowerCase()];
    if (reactProperty) {
      if (
        DOMProperty.properties.hasOwnProperty(reactProperty) &&
        DOMProperty.properties[reactProperty].hasBooleanValue
      ) {
        props[reactProperty] = true;
      } else {
        props[reactProperty] = propertyValue;
      }
      continue;
    }

    // make SVG DOM attribute/property consistent with React attribute/property
    reactProperty = config.svg[propertyName];
    if (reactProperty) {
      props[reactProperty] = propertyValue;
    } else if (utilities.reactSupportsUnknownAttributes()) {
      props[propertyName] = propertyValue;
    }
  }

  // convert inline style to object
  if (attributes.style != null) {
    props.style = cssToJs(attributes.style);
  }
  return props;
}

/**
 * Converts CSS style string to JS style object.
 *
 * @param  {String} style - The CSS style.
 * @return {Object}       - The JS style object.
 */
function cssToJs(style) {
  if (typeof style !== 'string') {
    throw new TypeError('First argument must be a string.');
  }
  var styleObj = {};

  styleToObject(style, function(propName, propValue) {
    // Check if it's not a comment node
    if (propName && propValue) {
      styleObj[utilities.camelCase(propName)] = propValue;
    }
  });
  return styleObj;
}

module.exports = attributesToProps;
<|endoftext|>


<commit_before><commit_msg>commit<commit_after><|endoftext|>