<commit_before>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

describe('Reason', function() {

    var ReasonDataBuilder, ValidReasonAssignmentDataBuilder, Reason, reason, repositoryMock, json, $rootScope, $q;

    beforeEach(function() {
        module('stock-reason');

        inject(function($injector) {
            $q = $injector.get('$q');
            Reason = $injector.get('Reason');
            ReasonDataBuilder = $injector.get('ReasonDataBuilder');
            ValidReasonAssignmentDataBuilder = $injector.get('ValidReasonAssignmentDataBuilder');
            $rootScope = $injector.get('$rootScope');
        });

        repositoryMock = jasmine.createSpyObj('StockReasonRepository', ['create', 'update']);

        json = new ReasonDataBuilder()
            .withAssignments([
                new ValidReasonAssignmentDataBuilder().build(),
                new ValidReasonAssignmentDataBuilder().build()
            ])
            .buildJson();
    });

    describe('constructor', function() {

        it('should set properties if json is given', function() {
            var result = new Reason(json, repositoryMock);

            expect(result.id).toEqual(json.id);
            expect(result.name).toEqual(json.name);
            expect(result.reasonType).toEqual(json.reasonType);
            expect(result.reasonCategory).toEqual(json.reasonCategory);
            expect(result.isFreeTextAllowed).toEqual(json.isFreeTextAllowed);
            expect(result.tags).toEqual(json.tags);
            expect(result.assignments).toEqual(json.assignments);
            expect(result.repository).toBe(repositoryMock);
            expect(result.addedAssignments).toEqual([]);
            expect(result.removedAssignments).toEqual([]);
        });

        it('should set defaults if json is not given', function() {
            var result = new Reason();

            expect(result.id).toBeUndefined();
            expect(result.name).toBeUndefined();
            expect(result.reasonType).toBeUndefined();
            expect(result.reasonCategory).toBeUndefined();
            expect(result.isFreeTextAllowed).toBe(false);
            expect(result.tags).toEqual([]);
            expect(result.assignments).toEqual([]);
            expect(result.repository).toBeUndefined();
            expect(result.addedAssignments).toEqual([]);
            expect(result.removedAssignments).toEqual([]);
        });

    });

    describe('isPhysicalReason', function() {

        it('should return true if reason category is Physical Inventory', function() {
            var reason = new ReasonDataBuilder().buildPhysicalInventoryReason();

            expect(reason.isPhysicalReason()).toBe(true);
        });

        it('should return false if reason category is not Physical Inventory', function() {
            var reason = new ReasonDataBuilder().buildTransferReason();

            expect(reason.isPhysicalReason()).toBe(false);

            reason = new ReasonDataBuilder().buildAdjustmentReason();

            expect(reason.isPhysicalReason()).toBe(false);
        });
    });

    describe('addAssignment', function() {

        beforeEach(function() {
            reason = new Reason(json, repositoryMock);
        });

        it('should reject if assignment already exist', function() {
            var result;
            reason.addAssignment(reason.assignments[0])
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toEqual('adminReasonAdd.validReasonDuplicated');
        });

        it('should add assignment if it is not duplicate', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();

            reason.addAssignment(assignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.assignments[2].program).toEqual(assignment.program);
            expect(reason.assignments[2].facilityType).toEqual(assignment.facilityType);
        });

        it('should remove assignment from removed if it was previously removed', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            reason.addAssignment(assignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.addedAssignments.length).toBe(0);
            expect(reason.removedAssignments.length).toBe(0);
        });

        it('should add assignment to added', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            var updatedAssignment = angular.copy(assignment);
            updatedAssignment.hidden = true;

            reason.addAssignment(updatedAssignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.addedAssignments.length).toBe(1);

            expect(reason.assignments[2].program).toEqual(updatedAssignment.program);
            expect(reason.assignments[2].facilityType).toEqual(updatedAssignment.facilityType);
            expect(reason.assignments[2].hidden).toEqual(updatedAssignment.hidden);
        });

        it('should remove from removed if it was updated and hidden value is different', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            var updatedAssignment = angular.copy(assignment);
            updatedAssignment.hidden = false;

            reason.addAssignment(updatedAssignment);
            $rootScope.$apply();

			expect(reason.removedAssignments.length).toBe(0);
        });

    });

    describe('removeAssignment', function() {

        beforeEach(function() {
            reason = new Reason(json, repositoryMock);
        });

        it('should resolve when assignment was remove successfully', function() {
            reason.removeAssignment(reason.assignments[0]);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(1);
        });

        it('should remove assignment from added if it was previously added', function() {
            reason.addedAssignments = [reason.assignments[0]];
            reason.removeAssignment(reason.assignments[0]);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(1);
            expect(reason.addedAssignments.length).toBe(0);
            expect(reason.removedAssignments.length).toBe(0);
        });

        it('should return resolved promise if remove was successful', function() {
            var resolved;
            reason.removeAssignment(reason.assignments[0])
                .then(function() {
                    resolved = true;
                });
            $rootScope.$apply();

            expect(resolved).toBe(true);
        });

        it('should return rejected promise if trying to remove non-existent assignment', function() {
            var result;
            reason.removeAssignment(new ValidReasonAssignmentDataBuilder().build())
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toBe('The given assignment is not on the list');
        });

    });

    describe('save', function() {

        beforeEach(function() {
            json = new ReasonDataBuilder()
                .withoutId()
                .withAssignments([
                    new ValidReasonAssignmentDataBuilder().build(),
                    new ValidReasonAssignmentDataBuilder().build()
                ])
                .buildJson();
            reason = new Reason(json, repositoryMock);
        });

        it('should reject if repository rejects', function() {
            var error = 'Reason for rejection';

            repositoryMock.create.andReturn($q.reject(error));

            var result;
            reason.save()
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toEqual(error);
        });

        it('should call create method from repository', function() {
            var createdReason = new ReasonDataBuilder().withoutId()
                .build();

            repositoryMock.create.andReturn($q.resolve(createdReason));

            var result;
            reason.save()
                .then(function(reason) {
                    result = reason;
                });
            $rootScope.$apply();

            expect(result).toEqual(createdReason);
        });

        it('should call update method from repository', function() {
            json = new ReasonDataBuilder()
                .withAssignments([
                    new ValidReasonAssignmentDataBuilder().build(),
                    new ValidReasonAssignmentDataBuilder().build()
                ])
                .buildJson();

            reason = new Reason(json, repositoryMock);
            var updatedReason = new ReasonDataBuilder().build();

            repositoryMock.update.andReturn($q.resolve(updatedReason));

            var result;
            reason.save()
                .then(function(reason) {
                    result = reason;
                });
            $rootScope.$apply();

            expect(result).toEqual(updatedReason);
        });

    });
});<commit_msg>OLMIS-5945:Add test cases<commit_after>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

describe('Reason', function() {

    var ReasonDataBuilder, ValidReasonAssignmentDataBuilder, Reason, reason, repositoryMock, json, $rootScope, $q;

    beforeEach(function() {
        module('stock-reason');

        inject(function($injector) {
            $q = $injector.get('$q');
            Reason = $injector.get('Reason');
            ReasonDataBuilder = $injector.get('ReasonDataBuilder');
            ValidReasonAssignmentDataBuilder = $injector.get('ValidReasonAssignmentDataBuilder');
            $rootScope = $injector.get('$rootScope');
        });

        repositoryMock = jasmine.createSpyObj('StockReasonRepository', ['create', 'update']);

        json = new ReasonDataBuilder()
            .withAssignments([
                new ValidReasonAssignmentDataBuilder().build(),
                new ValidReasonAssignmentDataBuilder().build()
            ])
            .buildJson();
    });

    describe('constructor', function() {

        it('should set properties if json is given', function() {
            var result = new Reason(json, repositoryMock);

            expect(result.id).toEqual(json.id);
            expect(result.name).toEqual(json.name);
            expect(result.reasonType).toEqual(json.reasonType);
            expect(result.reasonCategory).toEqual(json.reasonCategory);
            expect(result.isFreeTextAllowed).toEqual(json.isFreeTextAllowed);
            expect(result.tags).toEqual(json.tags);
            expect(result.assignments).toEqual(json.assignments);
            expect(result.repository).toBe(repositoryMock);
            expect(result.addedAssignments).toEqual([]);
            expect(result.removedAssignments).toEqual([]);
        });

        it('should set defaults if json is not given', function() {
            var result = new Reason();

            expect(result.id).toBeUndefined();
            expect(result.name).toBeUndefined();
            expect(result.reasonType).toBeUndefined();
            expect(result.reasonCategory).toBeUndefined();
            expect(result.isFreeTextAllowed).toBe(false);
            expect(result.tags).toEqual([]);
            expect(result.assignments).toEqual([]);
            expect(result.repository).toBeUndefined();
            expect(result.addedAssignments).toEqual([]);
            expect(result.removedAssignments).toEqual([]);
        });

    });

    describe('isPhysicalReason', function() {

        it('should return true if reason category is Physical Inventory', function() {
            var reason = new ReasonDataBuilder().buildPhysicalInventoryReason();

            expect(reason.isPhysicalReason()).toBe(true);
        });

        it('should return false if reason category is not Physical Inventory', function() {
            var reason = new ReasonDataBuilder().buildTransferReason();

            expect(reason.isPhysicalReason()).toBe(false);

            reason = new ReasonDataBuilder().buildAdjustmentReason();

            expect(reason.isPhysicalReason()).toBe(false);
        });
    });

    describe('addAssignment', function() {

        beforeEach(function() {
            reason = new Reason(json, repositoryMock);
        });

        it('should reject if assignment already exist', function() {
            var result;
            reason.addAssignment(reason.assignments[0])
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toEqual('adminReasonAdd.validReasonDuplicated');
        });

        it('should add assignment if it is not duplicate', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();

            reason.addAssignment(assignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.assignments[2].program).toEqual(assignment.program);
            expect(reason.assignments[2].facilityType).toEqual(assignment.facilityType);
        });

        it('should remove assignment from removed if it was previously removed', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            reason.addAssignment(assignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.addedAssignments.length).toBe(0);
            expect(reason.removedAssignments.length).toBe(0);
        });

        it('should add assignment to added', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            var updatedAssignment = angular.copy(assignment);
            updatedAssignment.hidden = true;

            reason.addAssignment(updatedAssignment);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(3);
            expect(reason.addedAssignments.length).toBe(1);

            expect(reason.assignments[2].program).toEqual(updatedAssignment.program);
            expect(reason.assignments[2].facilityType).toEqual(updatedAssignment.facilityType);
            expect(reason.assignments[2].hidden).toEqual(updatedAssignment.hidden);
        });

        it('should remove from removed if it was updated and hidden value is different', function() {
            var assignment = new ValidReasonAssignmentDataBuilder().build();
            reason.removedAssignments = [assignment];

            var updatedAssignment = angular.copy(assignment);
            updatedAssignment.hidden = false;

            reason.addAssignment(updatedAssignment);
            $rootScope.$apply();

            expect(reason.removedAssignments.length).toBe(0);
        });

    });

    describe('removeAssignment', function() {

        beforeEach(function() {
            reason = new Reason(json, repositoryMock);
        });

        it('should resolve when assignment was remove successfully', function() {
            reason.removeAssignment(reason.assignments[0]);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(1);
        });

        it('should remove assignment from added if it was previously added', function() {
            reason.addedAssignments = [reason.assignments[0]];
            reason.removeAssignment(reason.assignments[0]);
            $rootScope.$apply();

            expect(reason.assignments.length).toBe(1);
            expect(reason.addedAssignments.length).toBe(0);
            expect(reason.removedAssignments.length).toBe(0);
        });

        it('should return resolved promise if remove was successful', function() {
            var resolved;
            reason.removeAssignment(reason.assignments[0])
                .then(function() {
                    resolved = true;
                });
            $rootScope.$apply();

            expect(resolved).toBe(true);
        });

        it('should return rejected promise if trying to remove non-existent assignment', function() {
            var result;
            reason.removeAssignment(new ValidReasonAssignmentDataBuilder().build())
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toBe('The given assignment is not on the list');
        });

    });

    describe('save', function() {

        beforeEach(function() {
            json = new ReasonDataBuilder()
                .withoutId()
                .withAssignments([
                    new ValidReasonAssignmentDataBuilder().build(),
                    new ValidReasonAssignmentDataBuilder().build()
                ])
                .buildJson();
            reason = new Reason(json, repositoryMock);
        });

        it('should reject if repository rejects', function() {
            var error = 'Reason for rejection';

            repositoryMock.create.andReturn($q.reject(error));

            var result;
            reason.save()
                .catch(function(error) {
                    result = error;
                });
            $rootScope.$apply();

            expect(result).toEqual(error);
        });

        it('should call create method from repository', function() {
            var createdReason = new ReasonDataBuilder().withoutId()
                .build();

            repositoryMock.create.andReturn($q.resolve(createdReason));

            var result;
            reason.save()
                .then(function(reason) {
                    result = reason;
                });
            $rootScope.$apply();

            expect(result).toEqual(createdReason);
        });

        it('should call update method from repository', function() {
            json = new ReasonDataBuilder()
                .withAssignments([
                    new ValidReasonAssignmentDataBuilder().build(),
                    new ValidReasonAssignmentDataBuilder().build()
                ])
                .buildJson();

            reason = new Reason(json, repositoryMock);
            var updatedReason = new ReasonDataBuilder().build();

            repositoryMock.update.andReturn($q.resolve(updatedReason));

            var result;
            reason.save()
                .then(function(reason) {
                    result = reason;
                });
            $rootScope.$apply();

            expect(result).toEqual(updatedReason);
        });

    });
});<|endoftext|>


<commit_before>var BUILD_MODE = require('../const').BUILD_MODE;

var gulp = require('gulp');
var path = require('path');
var through2 = require('through2');
var series = require('stream-series');
var util = require('../util');
var gulpif = require('gulp-if');
var utils = require('../../scripts/gulp-utils.js');

exports.task = function() {
  var stream = series(
      gulp.src(['src/core/', 'src/components/*' ])
          .pipe(through2.obj(function(folder, enc, next) {
            var moduleId = folder.path.indexOf('components') > -1
                ? 'material.components.' + path.basename(folder.path)
                : 'material.' + path.basename(folder.path);
            var stream = BUILD_MODE.useBower
                ? series(util.buildModule(moduleId, true), util.buildModule(moduleId, false))
                : util.buildModule(moduleId, false);
            stream.on('end', function() { next(); });
          })),
      util.themeBuildStream()
          .pipe(
            gulpif(BUILD_MODE.name != 'closure',
              BUILD_MODE.transform()
                .pipe(gulp.dest(path.join(BUILD_MODE.outputDir, 'core')))
            )
          )
  );
  if (BUILD_MODE.name == 'closure') {
    stream.pipe(
      utils.appendToFile(path.join(BUILD_MODE.outputDir, 'core', 'core.js'))
    )
    .pipe(BUILD_MODE.transform())
    .pipe(gulp.dest(path.join(BUILD_MODE.outputDir, 'core')))
  }

  return stream;

};
<commit_msg>update(build): revises build method to remove duplicate `goog.provide` lines from `core.js`<commit_after>var BUILD_MODE = require('../const').BUILD_MODE;

var gulp = require('gulp');
var path = require('path');
var through2 = require('through2');
var series = require('stream-series');
var util = require('../util');
var gulpif = require('gulp-if');
var utils = require('../../scripts/gulp-utils.js');

exports.task = function() {
  return gulp.src(['src/core/', 'src/components/*' ])
      .pipe(through2.obj(function(folder, enc, next) {
        var moduleId = folder.path.indexOf('components') > -1
            ? 'material.components.' + path.basename(folder.path)
            : 'material.' + path.basename(folder.path);
        var stream = BUILD_MODE.useBower
            ? series(util.buildModule(moduleId, true), util.buildModule(moduleId, false))
            : util.buildModule(moduleId, false);
        stream.on('end', function() { next(); });
      }))
      .pipe(BUILD_MODE.transform());

};
<|endoftext|>


<commit_before>'use strict';

import debug from 'gulp-debug';
import gulp from 'gulp';
// import phantom from 'phantomjs2';
import phantom from 'phantomjs';
import plumber from 'gulp-plumber';
import webshot from 'gulp-webshot';

import config from './_config.babel.js';
import reportError from './_report-error.babel.js';

let sourceFiles = config.files.source.markup;

gulp.task('screenshots', () => {
  return gulp.src(sourceFiles)
    .pipe(plumber({
      errorHandler: reportError
    }))
    .pipe(debug({
      title: 'screenshots:'
    }))
    .pipe(webshot({
      phantomPath: phantom.path,
      dest: config.path.destination.screenshots,
      root: config.path.source.base
    }))
    .pipe(plumber.stop())
    .on('error', reportError);
});

gulp.task('screenshots:watch', function() {
  gulp.watch(sourceFiles, ['screenshots']);
});
<commit_msg>Tidy gulp screenshots import directives<commit_after>'use strict';

import debug from 'gulp-debug';
import gulp from 'gulp';
// import phantom from 'phantomjs2';
// import phantom from 'phantomjs';
import plumber from 'gulp-plumber';
import webshot from 'gulp-webshot';

import config from './_config.babel.js';
import reportError from './_report-error.babel.js';

let sourceFiles = config.files.source.markup;

gulp.task('screenshots', () => {
  return gulp.src(sourceFiles)
    .pipe(plumber({
      errorHandler: reportError
    }))
    .pipe(debug({
      title: 'screenshots:'
    }))
    .pipe(webshot({
      phantomPath: phantom.path,
      dest: config.path.destination.screenshots,
      root: config.path.source.base
    }))
    .pipe(plumber.stop())
    .on('error', reportError);
});

gulp.task('screenshots:watch', function() {
  gulp.watch(sourceFiles, ['screenshots']);
});
<|endoftext|>


<commit_before>// Engagment bar ##################################################################################
var ms = require("../ms.js");

module.exports = function debug() {
  var drawArray1 = [];
  var drawArray2 = [];
  var bbox = this.properties.baseGeometry.bbox;
  var x1 = bbox.x1;
  var x2 = bbox.x2;
  var y1 = bbox.y1;
  var y2 = bbox.y2;

  if (this.options.engagementBar !== "") {
    y1 -= 6;
    var fontFamily = "Arial";
    var fontColor =
      this.colors.iconColor[this.properties.affiliation] ||
      this.colors.iconColor["Friend"];

    drawArray2.push({
      type: "text",
      text: this.options.engagementBar,
      x: 100,
      y: bbox.y1 - 11,
      textanchor: "middle",
      fontsize: 22,
      fontfamily: fontFamily,
      fontweight: "bold",
      fill: fontColor,
      stroke: false
    });

    var color = false;
    if (this.properties.fill && this.style.monoColor === "") {
      var colors = {
        TARGET: "rgb(255, 0, 0)",
        "NON-TARGET": "rgb(255, 255, 255)",
        EXPIRED: "rgb(255, 120, 0)"
      };
      color =
        colors[this.options.engagementType.toUpperCase()] ||
        this.colors.fillColor[this.properties.affiliation];
    }
    // Bar width
    var width = Math.max(bbox.width(), this.options.engagementBar.length * 16);
    x1 = Math.min(x1, 100 - width / 2);
    x2 = Math.max(x2, 100 + width / 2);

    //Add the bar to the geometry
    drawArray2.unshift({
      type: "path",
      strokewidth: this.style.strokeWidth,
      fill: color,
      stroke: this.colors.frameColor[this.properties.affiliation],
      d:
        "M" +
        (100 - width / 2) +
        "," +
        y1 +
        " l" +
        width +
        ",0 0,-25 -" +
        width +
        ",0 z"
    });

    //Add the hight of the codition bar to the geometry bounds
    y1 -= 25;
    //outline
    if (this.style.outlineWidth > 0) {
      var outline;
      if (this.properties.fill && this.style.monoColor === "") {
        outline = drawArray2[0];
      } else {
        outline = drawArray2;
      }
      drawArray1.push(
        ms.outline(
          outline,
          this.style.outlineWidth,
          this.style.strokeWidth,
          this.style.outlineColor
        )
      );
    }
  }

  //A bounding box only needs the values that might change
  return {
    pre: drawArray1,
    post: drawArray2,
    bbox: { x1: x1, x2: x2, y1: y1, y2: y2 }
  };
};
<commit_msg>Make engagmentbar adopt to height of symbol<commit_after>// Engagment bar ##################################################################################
var ms = require("../ms.js");

module.exports = function debug() {
  var drawArray1 = [];
  var drawArray2 = [];
  var bbox = this.bbox;
  var x1 = bbox.x1;
  var x2 = bbox.x2;
  var y1 = bbox.y1;
  var y2 = bbox.y2;

  if (this.options.engagementBar !== "") {
    y1 -= 6;
    var fontFamily = "Arial";
    var fontColor =
      this.colors.iconColor[this.properties.affiliation] ||
      this.colors.iconColor["Friend"];

    drawArray2.push({
      type: "text",
      text: this.options.engagementBar,
      x: 100,
      y: bbox.y1 - 11,
      textanchor: "middle",
      fontsize: 22,
      fontfamily: fontFamily,
      fontweight: "bold",
      fill: fontColor,
      stroke: false
    });

    var color = false;
    if (this.properties.fill && this.style.monoColor === "") {
      var colors = {
        TARGET: "rgb(255, 0, 0)",
        "NON-TARGET": "rgb(255, 255, 255)",
        EXPIRED: "rgb(255, 120, 0)"
      };
      color =
        colors[this.options.engagementType.toUpperCase()] ||
        this.colors.fillColor[this.properties.affiliation];
    }
    // Bar width
    var width = Math.max(bbox.width(), this.options.engagementBar.length * 16);
    x1 = Math.min(x1, 100 - width / 2);
    x2 = Math.max(x2, 100 + width / 2);

    //Add the bar to the geometry
    drawArray2.unshift({
      type: "path",
      strokewidth: this.style.strokeWidth,
      fill: color,
      stroke: this.colors.frameColor[this.properties.affiliation],
      d:
        "M" +
        (100 - width / 2) +
        "," +
        y1 +
        " l" +
        width +
        ",0 0,-25 -" +
        width +
        ",0 z"
    });

    //Add the hight of the codition bar to the geometry bounds
    y1 -= 25;
    //outline
    if (this.style.outlineWidth > 0) {
      var outline;
      if (this.properties.fill && this.style.monoColor === "") {
        outline = drawArray2[0];
      } else {
        outline = drawArray2;
      }
      drawArray1.push(
        ms.outline(
          outline,
          this.style.outlineWidth,
          this.style.strokeWidth,
          this.style.outlineColor
        )
      );
    }
  }

  //A bounding box only needs the values that might change
  return {
    pre: drawArray1,
    post: drawArray2,
    bbox: { x1: x1, x2: x2, y1: y1, y2: y2 }
  };
};
<|endoftext|>


<commit_before>/**
 * Geopoint widget(s)
 */

( function( factory ) {
  if ( typeof define === 'function' && define.amd ) {
    // AMD. Register as an anonymous module.
    define( [ 'jquery' ], factory );
  } else {
    // Browser globals
    factory( jQuery );
  }
}( function( $ ) {
  "use strict";
  /**
   * Geopoint widget Class
   * @constructor
   * @param {[type]} element [description]
   * @param {[type]} options [description]
   */
  var Geopointpicker = function( element, options ) {
    var detect =
      '<button name="geodetect" type="button" class="btn" title="detect current location" data-placement="top">' +
      '</button>',
      search =
        '
' +
        '<input class="geo ignore" name="search" type="text" placeholder="search for place or address" disabled="disabled"/>' +
        '<button type="button" class="btn add-on">' +
        '
',
      map = '

';
    this.$inputOrigin = $( element );
    this.$form = this.$inputOrigin.closest( 'form' );
    this.$widget = $(
      '
' +
      '

' +
      '
' +
      'latitude (x.y °)<input class="ignore" name="lat" type="number" step="0.0001" />' +
      'longitude (x.y °)<input class="ignore" name="long" type="number" step="0.0001" />' +
      '<input class="ignore" name="alt" type="number" step="0.1" />altitude (m)' +
      '<input class="ignore" name="acc" type="number" step="0.1" />accuracy (m)' +
      '
' +
      '
'
    );
    //if geodetection is supported, add the button
    if ( navigator.geolocation ) {
      this.$widget.find( '.search-bar' ).append( detect );
      this.$detect = this.$widget.find( 'button[name="geodetect"]' );
    }
    //if not on a mobile device, add the search field
    if ( options.touch !== true ) {
      this.$widget.find( '.search-bar' ).removeClass( 'no-search-input' ).append( search );
      this.$search = this.$widget.find( '[name="search"]' );
    }
    //if not on a mobile device or specifically requested, add the map canvas
    if ( options.touch !== true || ( options.touch === true && this.$inputOrigin.parents( '.jr-appearance-maps' ).length > 0 ) ) {
      this.$widget.find( '.search-bar' ).removeClass( 'no-map' ).after( map );
      this.$map = this.$widget.find( '.map-canvas' );
    }

    this.$lat = this.$widget.find( '[name="lat"]' );
    this.$lng = this.$widget.find( '[name="long"]' );
    this.$alt = this.$widget.find( '[name="alt"]' );
    this.$acc = this.$widget.find( '[name="acc"]' );

    this.$inputOrigin.hide( ).after( this.$widget );
    this.updateMapFn = "updateDynamicMap";
    this.touch = options.touch || false;
    this.init( );
  };

  Geopointpicker.prototype = {

    constructor: Geopointpicker,

    //TODO: this is where the Maps API script load function should be called
    init: function( ) {
      var that = this,
        inputVals = this.$inputOrigin.val( ).split( ' ' );

      this.$inputOrigin.parent( ).addClass( 'clearfix' );

      this.$widget.find( 'input:not([name="search"])' ).on( 'change change.bymap change.bysearch', function( event ) {
        //console.debug('change event detected');
        var lat = ( that.$lat.val( ) !== '' ) ? that.$lat.val( ) : 0.0,
          lng = ( that.$lng.val( ) !== '' ) ? that.$lng.val( ) : 0.0,
          alt = ( that.$alt.val( ) !== '' ) ? that.$alt.val( ) : 0.0,
          acc = that.$acc.val( ),
          value = ( lat === 0 && lng === 0 ) ? '' : lat + ' ' + lng + ' ' + alt + ' ' + acc;

        event.stopImmediatePropagation( );

        that.$inputOrigin.val( value ).trigger( 'change' );

        if ( event.namespace !== 'bymap' && event.namespace !== 'bysearch' ) {
          that.updateMap( lat, lng );
        }

        if ( event.namespace !== 'bysearch' && this.$search ) {
          that.$search.val( '' );
        }
      } );

      this.$widget.on( 'focus blur', 'input', function( event ) {
        that.$inputOrigin.trigger( event.type );
      } );

      if ( inputVals[ 3 ] ) this.$acc.val( inputVals[ 3 ] );
      if ( inputVals[ 2 ] ) this.$alt.val( inputVals[ 2 ] );
      if ( inputVals[ 1 ] ) this.$lng.val( inputVals[ 1 ] );
      if ( inputVals[ 0 ].length > 0 ) this.$lat.val( inputVals[ 0 ] ).trigger( 'change' );

      if ( this.$detect ) {
        this.enableDetection( );
      }

      if ( !this.touch ) {
        if ( that.dynamicMapAvailable( ) ) {
          that.updateMap( 0, 0, 1 );
          if ( that.$search ) {
            that.enableSearch( );
          }
        } else {
          this.$form.on( 'googlemapsscriptloaded', function( ) {
            if ( that.dynamicMapAvailable( ) ) {
              //default map view
              that.updateMap( 0, 0, 1 );
              if ( that.$search ) {
                that.enableSearch( );
              }
            }
          } );
        }
      } else if ( this.$map ) {
        this.updateMapFn = "updateStaticMap";
        this.updateMap( 0, 0, 1 );
        $( window ).on( 'resize', function( ) {
          var resizeCount = $( window ).data( 'resizecount' ) || 0;
          resizeCount++;
          $( window ).data( 'resizecount', resizeCount );
          window.setTimeout( function( ) {
            if ( resizeCount == $( window ).data( 'resizecount' ) ) {
              $( window ).data( 'resizecount', 0 );
              //do the things
              console.debug( 'resizing stopped' );
              that.updateMap( );
            }
          }, 500 );
        } );
      }
    },
    /**
     * Enables geo detection using the built-in browser geoLocation functionality
     */
    enableDetection: function( ) {
      var that = this;
      this.$detect.click( function( event ) {
        event.preventDefault( );
        navigator.geolocation.getCurrentPosition( function( position ) {
          that.updateMap( position.coords.latitude, position.coords.longitude );
          that.updateInputs( position.coords.latitude, position.coords.longitude, position.coords.altitude, position.coords.accuracy );
        } );
        return false;
      } );
    },
    /**
     * Enables search functionality using the Google Maps API v3
     */
    enableSearch: function( ) {
      var geocoder = new google.maps.Geocoder( ),
        that = this;
      this.$search.prop( 'disabled', false );
      this.$search.on( 'change', function( event ) {
        event.stopImmediatePropagation( );
        //console.debug('search field click event');
        var address = $( this ).val( );
        if ( typeof geocoder !== 'undefined' ) {
          geocoder.geocode( {
              'address': address,
              'bounds': that.map.getBounds( )
            },
            function( results, status ) {
              if ( status == google.maps.GeocoderStatus.OK ) {
                that.$search.attr( 'placeholder', 'search' );
                var loc = results[ 0 ].geometry.location;
                //console.log(loc);
                that.updateMap( loc.lat( ), loc.lng( ) );
                that.updateInputs( loc.lat( ), loc.lng( ), null, null, 'change.bysearch' );
              } else {
                that.$search.val( '' );
                that.$search.attr( 'placeholder', address + ' not found, try something else.' );
              }
            }
          );
        }
        return false;
      } );
    },
    /**
     * Whether google maps are available (whether scripts have loaded).
     */
    dynamicMapAvailable: function( ) {
      return ( this.$map && typeof google !== 'undefined' && typeof google.maps !== 'undefined' );
    },
    /**
     * Calls the appropriate map update function.
     * @param  {number=} lat  latitude
     * @param  {number=} lng  longitude
     * @param  {number=} zoom zoom level which defaults to 15
     */
    updateMap: function( lat, lng, zoom ) {
      if ( !this.$map ) {
        return;
      }
      lat = lat || Number( this.$lat.val( ) );
      lng = lng || Number( this.$lng.val( ) );
      zoom = zoom || 15;
      if ( lat === 0 && lng === 0 ) zoom = 1;
      return this[ this.updateMapFn ]( lat, lng, zoom );
    },
    /**
     * Loads a static map with placemarker. Does not use Google Maps v3 API (uses Static Maps API instead)
     * @param  {number} lat  latitude
     * @param  {number} lng  longitude
     * @param  {number} zoom default zoom level is 15
     */
    updateStaticMap: function( lat, lng, zoom ) {
      var params,
        width = this.$map.width( ),
        height = this.$map.height( ),
        mapsAPIKey = settings[ 'mapsStaticAPIKey' ] || '';

      params = "center=" + lat + "," + lng + "&size=" + width + "x" + height + "&zoom=" + zoom + "&sensor=false&key=" + mapsAPIKey;
      this.$map.empty( ).append( '' );
    },
    /**
     * Updates the dynamic (Maps API v3) map to show the provided coordinates (in the center), with the provided zoom level
     * @param  {number} lat  latitude
     * @param  {number} lng  longitude
     * @param  {number} zoom zoom
     */
    updateDynamicMap: function( lat, lng, zoom ) {
      var $map = this.$map,
        that = this;

      if ( this.dynamicMapAvailable( ) && typeof google.maps.LatLng !== 'undefined' ) {
        var mapOptions = {
          zoom: zoom,
          center: new google.maps.LatLng( lat, lng ),
          mapTypeId: google.maps.MapTypeId.ROADMAP,
          streetViewControl: false
        };
        this.map = new google.maps.Map( this.$map[ 0 ], mapOptions );
        this.placeMarker( );
        // place marker where user clicks
        google.maps.event.addListener( this.map, 'click', function( event ) {
          that.updateInputs( event.latLng.lat( ), event.latLng.lng( ), '', '', 'change.bymap' );
          that.placeMarker( event.latLng );
        } );
      }
    },
    /**
     * Moves the existing marker to the provided coordinates or places a new one in the center of the map
     * @param  {Object.<string, number>=} latLng [description]
     */
    placeMarker: function( latLng ) {
      var that;
      latLng = latLng || this.map.getCenter( );
      if ( typeof this.marker !== 'undefined' ) {
        this.marker.setMap( null );
      }
      this.marker = new google.maps.Marker( {
        position: latLng,
        map: this.map,
        draggable: true
      } );
      that = this;
      // dragging markers for non-touch screens
      if ( !this.touch ) {
        google.maps.event.addListener( this.marker, 'dragend', function( ) {
          that.updateInputs( that.marker.getPosition( ).lat( ), that.marker.getPosition( ).lng( ), '', '', 'change.bymap' );
          that.centralizeWithDelay( );
        } );
        this.centralizeWithDelay( 5000 );
      }
      this.centralizeWithDelay( 0 );
    },
    /**
     * Shifts the map so that the marker is in the center after a small delay.
     */
    centralizeWithDelay: function( delay ) {
      var that = this;
      window.setTimeout( function( ) {
        that.map.panTo( that.marker.getPosition( ) );
      }, delay );
    },
    /**
     * Updates the (fake) input element for latitude, longitude, altitude and accuracy
     * @param  {number} lat [description]
     * @param  {number} lng [description]
     * @param  {?(string|number)} alt [description]
     * @param  {?(string|number)} acc [description]
     * @param  {string=} ev  [description]
     */
    updateInputs: function( lat, lng, alt, acc, ev ) {
      alt = alt || '';
      acc = acc || '';
      ev = ev || 'change';
      this.$lat.val( Math.round( lat * 10000 ) / 10000 );
      this.$lng.val( Math.round( lng * 10000 ) / 10000 );
      this.$alt.val( Math.round( alt * 10 ) / 10 );
      this.$acc.val( Math.round( acc * 10 ) / 10 ).trigger( ev );
    },
    /**
     * In enketo the loading of the GMaps resources is dealt with in the Connection class.
     */
    loadMapsScript: function( ) {}
  };

  $.fn.geopointpicker = function( option ) {
    var loadStarted = false;

    return this.each( function( ) {
      var $this = $( this ),
        data = $( this ).data( 'geopointwidget' ),
        options = typeof option == 'object' && option;
      //for some reason, calling this inside the Geopointpicker class does not work properly
      if ( !loadStarted && ( typeof connection !== 'undefined' ) && ( typeof google == 'undefined' || typeof google.maps == 'undefined' ) && !option.touch ) {
        loadStarted = true;
        console.debug( 'loading maps script asynchronously' );
        connection.loadGoogleMaps( function( ) {
          $( 'form.jr' ).trigger( 'googlemapsscriptloaded' );
        } );
      }

      if ( !data ) {
        $this.data( 'geopointwidget', ( data = new Geopointpicker( this, options ) ) );
      }
      if ( typeof option == 'string' ) {
        data[ option ]( );
      }
    } );
  };

  $.fn.geopointpicker.Constructor = Geopointpicker;

} ) );<commit_msg>quick and dirty addition of the google maps script loader to the geopoint widget<commit_after>/**
 * Geopoint widget(s)
 */

( function( factory ) {
  if ( typeof define === 'function' && define.amd ) {
    // AMD. Register as an anonymous module.
    define( [ 'jquery' ], factory );
  } else {
    // Browser globals
    factory( jQuery );
  }
}( function( $ ) {
  "use strict";
  /**
   * Geopoint widget Class
   * @constructor
   * @param {[type]} element [description]
   * @param {[type]} options [description]
   */
  var Geopointpicker = function( element, options ) {
    var detect =
      '<button name="geodetect" type="button" class="btn" title="detect current location" data-placement="top">' +
      '</button>',
      search =
        '
' +
        '<input class="geo ignore" name="search" type="text" placeholder="search for place or address" disabled="disabled"/>' +
        '<button type="button" class="btn add-on">' +
        '
',
      map = '

';
    this.$inputOrigin = $( element );
    this.$form = this.$inputOrigin.closest( 'form' );
    this.$widget = $(
      '
' +
      '

' +
      '
' +
      'latitude (x.y °)<input class="ignore" name="lat" type="number" step="0.0001" />' +
      'longitude (x.y °)<input class="ignore" name="long" type="number" step="0.0001" />' +
      '<input class="ignore" name="alt" type="number" step="0.1" />altitude (m)' +
      '<input class="ignore" name="acc" type="number" step="0.1" />accuracy (m)' +
      '
' +
      '
'
    );
    //if geodetection is supported, add the button
    if ( navigator.geolocation ) {
      this.$widget.find( '.search-bar' ).append( detect );
      this.$detect = this.$widget.find( 'button[name="geodetect"]' );
    }
    //if not on a mobile device, add the search field
    if ( options.touch !== true ) {
      this.$widget.find( '.search-bar' ).removeClass( 'no-search-input' ).append( search );
      this.$search = this.$widget.find( '[name="search"]' );
    }
    //if not on a mobile device or specifically requested, add the map canvas
    if ( options.touch !== true || ( options.touch === true && this.$inputOrigin.parents( '.jr-appearance-maps' ).length > 0 ) ) {
      this.$widget.find( '.search-bar' ).removeClass( 'no-map' ).after( map );
      this.$map = this.$widget.find( '.map-canvas' );
    }

    this.$lat = this.$widget.find( '[name="lat"]' );
    this.$lng = this.$widget.find( '[name="long"]' );
    this.$alt = this.$widget.find( '[name="alt"]' );
    this.$acc = this.$widget.find( '[name="acc"]' );

    this.$inputOrigin.hide( ).after( this.$widget );
    this.updateMapFn = "updateDynamicMap";
    this.touch = options.touch || false;
    this.init( );
  };

  Geopointpicker.prototype = {

    constructor: Geopointpicker,

    //TODO: this is where the Maps API script load function should be called
    init: function( ) {
      var that = this,
        inputVals = this.$inputOrigin.val( ).split( ' ' );

      this.$inputOrigin.parent( ).addClass( 'clearfix' );

      this.$widget.find( 'input:not([name="search"])' ).on( 'change change.bymap change.bysearch', function( event ) {
        //console.debug('change event detected');
        var lat = ( that.$lat.val( ) !== '' ) ? that.$lat.val( ) : 0.0,
          lng = ( that.$lng.val( ) !== '' ) ? that.$lng.val( ) : 0.0,
          alt = ( that.$alt.val( ) !== '' ) ? that.$alt.val( ) : 0.0,
          acc = that.$acc.val( ),
          value = ( lat === 0 && lng === 0 ) ? '' : lat + ' ' + lng + ' ' + alt + ' ' + acc;

        event.stopImmediatePropagation( );

        that.$inputOrigin.val( value ).trigger( 'change' );

        if ( event.namespace !== 'bymap' && event.namespace !== 'bysearch' ) {
          that.updateMap( lat, lng );
        }

        if ( event.namespace !== 'bysearch' && this.$search ) {
          that.$search.val( '' );
        }
      } );

      this.$widget.on( 'focus blur', 'input', function( event ) {
        that.$inputOrigin.trigger( event.type );
      } );

      if ( inputVals[ 3 ] ) this.$acc.val( inputVals[ 3 ] );
      if ( inputVals[ 2 ] ) this.$alt.val( inputVals[ 2 ] );
      if ( inputVals[ 1 ] ) this.$lng.val( inputVals[ 1 ] );
      if ( inputVals[ 0 ].length > 0 ) this.$lat.val( inputVals[ 0 ] ).trigger( 'change' );

      if ( this.$detect ) {
        this.enableDetection( );
      }

      if ( !this.touch ) {
        if ( that.dynamicMapAvailable( ) ) {
          that.updateMap( 0, 0, 1 );
          if ( that.$search ) {
            that.enableSearch( );
          }
        } else {
          this.$form.on( 'googlemapsscriptloaded', function( ) {
            if ( that.dynamicMapAvailable( ) ) {
              //default map view
              that.updateMap( 0, 0, 1 );
              if ( that.$search ) {
                that.enableSearch( );
              }
            }
          } );
        }
      } else if ( this.$map ) {
        this.updateMapFn = "updateStaticMap";
        this.updateMap( 0, 0, 1 );
        $( window ).on( 'resize', function( ) {
          var resizeCount = $( window ).data( 'resizecount' ) || 0;
          resizeCount++;
          $( window ).data( 'resizecount', resizeCount );
          window.setTimeout( function( ) {
            if ( resizeCount == $( window ).data( 'resizecount' ) ) {
              $( window ).data( 'resizecount', 0 );
              //do the things
              console.debug( 'resizing stopped' );
              that.updateMap( );
            }
          }, 500 );
        } );
      }
    },
    /**
     * Enables geo detection using the built-in browser geoLocation functionality
     */
    enableDetection: function( ) {
      var that = this;
      this.$detect.click( function( event ) {
        event.preventDefault( );
        navigator.geolocation.getCurrentPosition( function( position ) {
          that.updateMap( position.coords.latitude, position.coords.longitude );
          that.updateInputs( position.coords.latitude, position.coords.longitude, position.coords.altitude, position.coords.accuracy );
        } );
        return false;
      } );
    },
    /**
     * Enables search functionality using the Google Maps API v3
     */
    enableSearch: function( ) {
      var geocoder = new google.maps.Geocoder( ),
        that = this;
      this.$search.prop( 'disabled', false );
      this.$search.on( 'change', function( event ) {
        event.stopImmediatePropagation( );
        //console.debug('search field click event');
        var address = $( this ).val( );
        if ( typeof geocoder !== 'undefined' ) {
          geocoder.geocode( {
              'address': address,
              'bounds': that.map.getBounds( )
            },
            function( results, status ) {
              if ( status == google.maps.GeocoderStatus.OK ) {
                that.$search.attr( 'placeholder', 'search' );
                var loc = results[ 0 ].geometry.location;
                //console.log(loc);
                that.updateMap( loc.lat( ), loc.lng( ) );
                that.updateInputs( loc.lat( ), loc.lng( ), null, null, 'change.bysearch' );
              } else {
                that.$search.val( '' );
                that.$search.attr( 'placeholder', address + ' not found, try something else.' );
              }
            }
          );
        }
        return false;
      } );
    },
    /**
     * Whether google maps are available (whether scripts have loaded).
     */
    dynamicMapAvailable: function( ) {
      return ( this.$map && typeof google !== 'undefined' && typeof google.maps !== 'undefined' );
    },
    /**
     * Calls the appropriate map update function.
     * @param  {number=} lat  latitude
     * @param  {number=} lng  longitude
     * @param  {number=} zoom zoom level which defaults to 15
     */
    updateMap: function( lat, lng, zoom ) {
      if ( !this.$map ) {
        return;
      }
      lat = lat || Number( this.$lat.val( ) );
      lng = lng || Number( this.$lng.val( ) );
      zoom = zoom || 15;
      if ( lat === 0 && lng === 0 ) zoom = 1;
      return this[ this.updateMapFn ]( lat, lng, zoom );
    },
    /**
     * Loads a static map with placemarker. Does not use Google Maps v3 API (uses Static Maps API instead)
     * @param  {number} lat  latitude
     * @param  {number} lng  longitude
     * @param  {number} zoom default zoom level is 15
     */
    updateStaticMap: function( lat, lng, zoom ) {
      var params,
        width = this.$map.width( ),
        height = this.$map.height( ),
        mapsAPIKey = settings[ 'mapsStaticAPIKey' ] || '';

      params = "center=" + lat + "," + lng + "&size=" + width + "x" + height + "&zoom=" + zoom + "&sensor=false&key=" + mapsAPIKey;
      this.$map.empty( ).append( '' );
    },
    /**
     * Updates the dynamic (Maps API v3) map to show the provided coordinates (in the center), with the provided zoom level
     * @param  {number} lat  latitude
     * @param  {number} lng  longitude
     * @param  {number} zoom zoom
     */
    updateDynamicMap: function( lat, lng, zoom ) {
      var $map = this.$map,
        that = this;

      if ( this.dynamicMapAvailable( ) && typeof google.maps.LatLng !== 'undefined' ) {
        var mapOptions = {
          zoom: zoom,
          center: new google.maps.LatLng( lat, lng ),
          mapTypeId: google.maps.MapTypeId.ROADMAP,
          streetViewControl: false
        };
        this.map = new google.maps.Map( this.$map[ 0 ], mapOptions );
        this.placeMarker( );
        // place marker where user clicks
        google.maps.event.addListener( this.map, 'click', function( event ) {
          that.updateInputs( event.latLng.lat( ), event.latLng.lng( ), '', '', 'change.bymap' );
          that.placeMarker( event.latLng );
        } );
      }
    },
    /**
     * Moves the existing marker to the provided coordinates or places a new one in the center of the map
     * @param  {Object.<string, number>=} latLng [description]
     */
    placeMarker: function( latLng ) {
      var that;
      latLng = latLng || this.map.getCenter( );
      if ( typeof this.marker !== 'undefined' ) {
        this.marker.setMap( null );
      }
      this.marker = new google.maps.Marker( {
        position: latLng,
        map: this.map,
        draggable: true
      } );
      that = this;
      // dragging markers for non-touch screens
      if ( !this.touch ) {
        google.maps.event.addListener( this.marker, 'dragend', function( ) {
          that.updateInputs( that.marker.getPosition( ).lat( ), that.marker.getPosition( ).lng( ), '', '', 'change.bymap' );
          that.centralizeWithDelay( );
        } );
        this.centralizeWithDelay( 5000 );
      }
      this.centralizeWithDelay( 0 );
    },
    /**
     * Shifts the map so that the marker is in the center after a small delay.
     */
    centralizeWithDelay: function( delay ) {
      var that = this;
      window.setTimeout( function( ) {
        that.map.panTo( that.marker.getPosition( ) );
      }, delay );
    },
    /**
     * Updates the (fake) input element for latitude, longitude, altitude and accuracy
     * @param  {number} lat [description]
     * @param  {number} lng [description]
     * @param  {?(string|number)} alt [description]
     * @param  {?(string|number)} acc [description]
     * @param  {string=} ev  [description]
     */
    updateInputs: function( lat, lng, alt, acc, ev ) {
      alt = alt || '';
      acc = acc || '';
      ev = ev || 'change';
      this.$lat.val( Math.round( lat * 10000 ) / 10000 );
      this.$lng.val( Math.round( lng * 10000 ) / 10000 );
      this.$alt.val( Math.round( alt * 10 ) / 10 );
      this.$acc.val( Math.round( acc * 10 ) / 10 ).trigger( ev );
    },
    /**
     * In enketo the loading of the GMaps resources is dealt with in the Connection class.
     */
    loadMapsScript: function( ) {}
  };

  $.fn.geopointpicker = function( option ) {
    var loadStarted = false;

    return this.each( function( ) {
      var $this = $( this ),
        data = $( this ).data( 'geopointwidget' ),
        options = typeof option == 'object' && option;
      //for some reason, calling this inside the Geopointpicker class does not work properly
      if ( !loadStarted && ( typeof google == 'undefined' || typeof google.maps == 'undefined' ) && !option.touch ) {
        loadStarted = true;
        var apiKey = option.apiKey || '',
          script = document.createElement( "script" );
        window.googleMapsInit = function( ) {
          $( 'form.jr' ).trigger( 'googlemapsscriptloaded' );
        };
        script.type = "text/javascript";
        script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&key=" + apiKey +
          "&sensor=false&libraries=places&callback=googleMapsInit";
        document.body.appendChild( script );
      }
      if ( !data ) {
        $this.data( 'geopointwidget', ( data = new Geopointpicker( this, options ) ) );
      }
      if ( typeof option == 'string' ) {
        data[ option ]( );
      }
    } );
  };

  $.fn.geopointpicker.Constructor = Geopointpicker;

} ) );<|endoftext|>


<commit_before>/*global DS*/
var get = Ember.get,
  set = Ember.set;

DS.FLOWRESTAdapter = DS.RESTAdapter.extend({
  serializer: DS.RESTSerializer.extend({
    primaryKey: function (type) {
      return "keyId";
    },
    keyForAttributeName: function (type, name) {
      return name;
    }
  }),

  sideload: function (store, type, json, root) {
    var msg, status, metaObj;
    this._super(store, type, json, root);

    this.setQueryCursor(type, json);

    // only change metaControl info if there is actual meta info in the server response
    // and if it does not come from a delete action. We detect this by looking if num == null
    metaObj = this.extractMeta(json);
    if (metaObj && !Ember.none(metaObj.message)) {

      if (type == FLOW.SurveyInstance
          || type == FLOW.SurveyedLocale
          && !Ember.none(this.extractMeta(json).num)) {
        FLOW.metaControl.set(type == FLOW.SurveyInstance ? 'numSILoaded' : 'numSLLoaded', this.extractMeta(json).num);
        FLOW.metaControl.set('since', this.extractMeta(json).since);
        FLOW.metaControl.set('num', this.extractMeta(json).num);
        FLOW.metaControl.set('cursorType', type);
      }
      msg = this.extractMeta(json).message;
      status = this.extractMeta(json).status;
      keyId = this.extractMeta(json).keyId;

      if (msg.indexOf('_') === 0) { // Response is a translatable message
        msg = Ember.String.loc(msg);
      }
      FLOW.metaControl.set('message', msg);
      FLOW.metaControl.set('status', status);
      FLOW.metaControl.set('keyId', keyId);
      FLOW.savingMessageControl.numLoadingChange(-1);
      FLOW.savingMessageControl.set('areSavingBool', false);

      if (status === 'preflight-delete-question') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.questionControl.deleteQuestion(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_question'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_question_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-questiongroup') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.questionGroupControl.deleteQuestionGroup(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_questiongroup'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_questiongroup_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-survey') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.surveyControl.deleteSurvey(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_survey'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_survey_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-surveygroup') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.surveyGroupControl.deleteSurveyGroup(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_surveygroup'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_surveygroup_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (this.extractMeta(json).status === 'failed' || FLOW.metaControl.get('message') !== '') {
        FLOW.dialogControl.set('activeAction', 'ignore');
        FLOW.dialogControl.set('header', '' /*Ember.String.loc('_action_failed')*/ ); //FIXME
        FLOW.dialogControl.set('message', FLOW.metaControl.get('message'));
        FLOW.dialogControl.set('showCANCEL', false);
        FLOW.dialogControl.set('showDialog', true);
      }
    }
  },

  /*  Process the cursor returned by the query. The cursor is used for pagination requests
      and is based on the type of entities queried */
  setQueryCursor: function(type, json) {
    var cursorArray, cursorStart, cursorIndex;
    if (type === FLOW.SurveyedLocale) {
      cursorArray = FLOW.router.surveyedLocaleController.get('sinceArray');
    } else if (type === FLOW.SurveyInstance) {
      cursorArray = FLOW.surveyInstanceControl.get('sinceArray');
    } else {
      return;
    }

    cursorStart = this.extractSince(json);
    if (!cursorStart) {
      return;
    }

    cursorIndex = cursorArray.indexOf(cursorStart);
    if (cursorIndex === -1) {
      cursorArray.pushObject(cursorStart);
    } else {
      // drop all cursors after the current one
      cursorArray.splice(cursorIndex + 1, cursorArray.length);
    }

    if (type === FLOW.SurveyedLocale) {
      FLOW.router.surveyedLocaleController.set('sinceArray', cursorArray);
    } else if (type === FLOW.SurveyInstance) {
      FLOW.surveyInstanceControl.set('sinceArray', cursorArray);
    }
  },

  ajax: function (url, type, hash) {
    if (type === 'GET' && url.indexOf('rest/survey_groups/0') >= 0) {
      // Don't fetch the root folder. It doesn't exist.
      return;
    }

    this._super(url, type, hash);
    if (type == "GET") {
      if (url.indexOf('rest/survey_groups') >= 0) {
        FLOW.projectControl.set('isLoading', true);
      }
      FLOW.savingMessageControl.numLoadingChange(1);
    }
  },

  didFindRecord: function (store, type, json, id) {
    this._super(store, type, json, id);
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
  },

  didFindAll: function (store, type, json) {
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
    this._super(store, type, json);
  },

  didFindQuery: function (store, type, json, recordArray) {
    this._super(store, type, json, recordArray);
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
  },

  // adapted from standard ember rest_adapter
  // includes 'bulk' in the POST call, to allign
  // with updateRecords and deleteRecords behaviour.
  createRecords: function (store, type, records) {
    //do not bulk commit when creating questions and question groups
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', false);
    }

    if (get(this, 'bulkCommit') === false) {
      return this._super(store, type, records);
    }

    var root = this.rootForType(type),
      plural = this.pluralize(root);

    var data = {};
    data[plural] = [];
    records.forEach(function (record) {
      data[plural].push(this.serialize(record, {
        includeId: true
      }));
    }, this);

    this.ajax(this.buildURL(root, 'bulk'), "POST", {
      data: data,
      context: this,
      success: function (json) {
        this.didCreateRecords(store, type, records, json);
      }
    });
  },

  updateRecords: function(store, type, records) {
    //if updating questions and question groups ordering, enable bulkCommit
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', true);
    }
    this._super(store, type, records);
  },

  deleteRecords: function(store, type, records) {
    //do not bulk commit when deleting questions and question groups
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', false);
    }
    this._super(store, type, records);
  }
});
<commit_msg>[#2827] store data before changing the loading flags<commit_after>/*global DS*/
var get = Ember.get,
  set = Ember.set;

DS.FLOWRESTAdapter = DS.RESTAdapter.extend({
  serializer: DS.RESTSerializer.extend({
    primaryKey: function (type) {
      return "keyId";
    },
    keyForAttributeName: function (type, name) {
      return name;
    }
  }),

  sideload: function (store, type, json, root) {
    var msg, status, metaObj;
    this._super(store, type, json, root);

    this.setQueryCursor(type, json);

    // only change metaControl info if there is actual meta info in the server response
    // and if it does not come from a delete action. We detect this by looking if num == null
    metaObj = this.extractMeta(json);
    if (metaObj && !Ember.none(metaObj.message)) {

      if (type == FLOW.SurveyInstance
          || type == FLOW.SurveyedLocale
          && !Ember.none(this.extractMeta(json).num)) {
        FLOW.metaControl.set(type == FLOW.SurveyInstance ? 'numSILoaded' : 'numSLLoaded', this.extractMeta(json).num);
        FLOW.metaControl.set('since', this.extractMeta(json).since);
        FLOW.metaControl.set('num', this.extractMeta(json).num);
        FLOW.metaControl.set('cursorType', type);
      }
      msg = this.extractMeta(json).message;
      status = this.extractMeta(json).status;
      keyId = this.extractMeta(json).keyId;

      if (msg.indexOf('_') === 0) { // Response is a translatable message
        msg = Ember.String.loc(msg);
      }
      FLOW.metaControl.set('message', msg);
      FLOW.metaControl.set('status', status);
      FLOW.metaControl.set('keyId', keyId);
      FLOW.savingMessageControl.numLoadingChange(-1);
      FLOW.savingMessageControl.set('areSavingBool', false);

      if (status === 'preflight-delete-question') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.questionControl.deleteQuestion(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_question'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_question_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-questiongroup') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.questionGroupControl.deleteQuestionGroup(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_questiongroup'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_questiongroup_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-survey') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.surveyControl.deleteSurvey(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_survey'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_survey_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (status === 'preflight-delete-surveygroup') {
        if (msg === 'can_delete') {
          // do deletion
          FLOW.surveyGroupControl.deleteSurveyGroup(keyId);
        } else {
          FLOW.dialogControl.set('activeAction', 'ignore');
          FLOW.dialogControl.set('header', Ember.String.loc('_cannot_delete_surveygroup'));
          FLOW.dialogControl.set('message', Ember.String.loc('_cannot_delete_surveygroup_text'));
          FLOW.dialogControl.set('showCANCEL', false);
          FLOW.dialogControl.set('showDialog', true);
        }
        return;
      }

      if (this.extractMeta(json).status === 'failed' || FLOW.metaControl.get('message') !== '') {
        FLOW.dialogControl.set('activeAction', 'ignore');
        FLOW.dialogControl.set('header', '' /*Ember.String.loc('_action_failed')*/ ); //FIXME
        FLOW.dialogControl.set('message', FLOW.metaControl.get('message'));
        FLOW.dialogControl.set('showCANCEL', false);
        FLOW.dialogControl.set('showDialog', true);
      }
    }
  },

  /*  Process the cursor returned by the query. The cursor is used for pagination requests
      and is based on the type of entities queried */
  setQueryCursor: function(type, json) {
    var cursorArray, cursorStart, cursorIndex;
    if (type === FLOW.SurveyedLocale) {
      cursorArray = FLOW.router.surveyedLocaleController.get('sinceArray');
    } else if (type === FLOW.SurveyInstance) {
      cursorArray = FLOW.surveyInstanceControl.get('sinceArray');
    } else {
      return;
    }

    cursorStart = this.extractSince(json);
    if (!cursorStart) {
      return;
    }

    cursorIndex = cursorArray.indexOf(cursorStart);
    if (cursorIndex === -1) {
      cursorArray.pushObject(cursorStart);
    } else {
      // drop all cursors after the current one
      cursorArray.splice(cursorIndex + 1, cursorArray.length);
    }

    if (type === FLOW.SurveyedLocale) {
      FLOW.router.surveyedLocaleController.set('sinceArray', cursorArray);
    } else if (type === FLOW.SurveyInstance) {
      FLOW.surveyInstanceControl.set('sinceArray', cursorArray);
    }
  },

  ajax: function (url, type, hash) {
    if (type === 'GET' && url.indexOf('rest/survey_groups/0') >= 0) {
      // Don't fetch the root folder. It doesn't exist.
      return;
    }

    this._super(url, type, hash);
    if (type == "GET") {
      if (url.indexOf('rest/survey_groups') >= 0) {
        FLOW.projectControl.set('isLoading', true);
      }
      FLOW.savingMessageControl.numLoadingChange(1);
    }
  },

  didFindRecord: function (store, type, json, id) {
    this._super(store, type, json, id);
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
  },

  didFindAll: function (store, type, json) {
    this._super(store, type, json);
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
  },

  didFindQuery: function (store, type, json, recordArray) {
    this._super(store, type, json, recordArray);
    if (type === FLOW.SurveyGroup) {
      FLOW.projectControl.set('isLoading', false);
    }
    FLOW.savingMessageControl.numLoadingChange(-1);
  },

  // adapted from standard ember rest_adapter
  // includes 'bulk' in the POST call, to allign
  // with updateRecords and deleteRecords behaviour.
  createRecords: function (store, type, records) {
    //do not bulk commit when creating questions and question groups
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', false);
    }

    if (get(this, 'bulkCommit') === false) {
      return this._super(store, type, records);
    }

    var root = this.rootForType(type),
      plural = this.pluralize(root);

    var data = {};
    data[plural] = [];
    records.forEach(function (record) {
      data[plural].push(this.serialize(record, {
        includeId: true
      }));
    }, this);

    this.ajax(this.buildURL(root, 'bulk'), "POST", {
      data: data,
      context: this,
      success: function (json) {
        this.didCreateRecords(store, type, records, json);
      }
    });
  },

  updateRecords: function(store, type, records) {
    //if updating questions and question groups ordering, enable bulkCommit
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', true);
    }
    this._super(store, type, records);
  },

  deleteRecords: function(store, type, records) {
    //do not bulk commit when deleting questions and question groups
    if (FLOW.questionControl.get('bulkCommit')) {
      this.set('bulkCommit', false);
    }
    this._super(store, type, records);
  }
});
<|endoftext|>


<commit_before>var _ = require('lodash');
var assetGraphConditions = require('assetgraph/lib/assetGraphConditions');

module.exports = function (queryObj, options) {
    options = options || {};
    var splitConditions = options.splitConditions || [];
    if (typeof splitConditions === 'string') {
        splitConditions = [splitConditions];
    }

    return function cloneForEachConditionValue(assetGraph) {
        // Discover all condition values:
        splitConditions.forEach(function (splitCondition) {
            var isSeenByConditionValue = {};
            assetGraph.findAssets(_.extend({type: 'Html', isInline: false}, queryObj)).forEach(function (htmlAsset) {
                assetGraph.findRelations({from: htmlAsset}).forEach(function (relation) {
                    var dataSystemJsConditions = relation.node && assetGraphConditions.parse(relation.node);
                    if (dataSystemJsConditions) {
                        var key = splitCondition + '.js|default';
                        var value = dataSystemJsConditions[key];
                        if (!value) {
                            key = splitCondition + '|default';
                            value = dataSystemJsConditions[key];
                        }
                        if (value) {
                            isSeenByConditionValue[value] = true;
                        }
                    }
                });
                var conditionValues = (options.conditions && options.conditions[splitCondition]) || Object.keys(isSeenByConditionValue);
                if (typeof conditionValues === 'string') {
                    conditionValues = [conditionValues];
                }
                if (conditionValues.length > 0) {
                    conditionValues.forEach(function (conditionValue) {
                        var clonedHtmlAsset = htmlAsset.clone();
                        var documentElement = clonedHtmlAsset.parseTree.documentElement;
                        if (documentElement) {
                            var htmlSystemJsConditionals = assetGraphConditions.parse(documentElement) || {};
                            htmlSystemJsConditionals[splitCondition] = conditionValue;
                            documentElement.setAttribute('data-assetgraph-conditions', assetGraphConditions.stringify(htmlSystemJsConditionals));
                            clonedHtmlAsset.markDirty();
                        }
                        var targetUrl = htmlAsset.url.replace(/(\.\w+)?$/, '.' + conditionValue + '$1');
                        clonedHtmlAsset.url = targetUrl;

                        assetGraph.findRelations({from: clonedHtmlAsset}).forEach(function (relation) {
                            var dataSystemJsConditions = relation.node && assetGraphConditions.parse(relation.node);
                            if (dataSystemJsConditions) {
                                var key = splitCondition + '.js|default';
                                var value = dataSystemJsConditions[key];
                                if (!value) {
                                    key = splitCondition + '|default';
                                    value = dataSystemJsConditions[key];
                                }
                                if (value) {
                                    if (value === conditionValue) {
                                        delete dataSystemJsConditions[key];
                                        if (Object.keys(dataSystemJsConditions).length === 0) {
                                            relation.node.removeAttribute('data-assetgraph-conditions');
                                        } else {
                                            relation.node.setAttribute('data-assetgraph-conditions', assetGraphConditions.stringify(dataSystemJsConditions));
                                        }
                                        relation.from.markDirty();
                                    } else {
                                        relation.detach();
                                    }
                                    return;
                                }
                            }
                        });
                    });
                    assetGraph.removeAsset(htmlAsset);
                }
            });
        });
    };
};
<commit_msg>es6ify the cloneForEachConditionValue transform<commit_after>var assetGraphConditions = require('assetgraph/lib/assetGraphConditions');

module.exports = function (queryObj, options) {
    options = options || {};
    var splitConditions = options.splitConditions || [];
    if (typeof splitConditions === 'string') {
        splitConditions = [splitConditions];
    }

    return function cloneForEachConditionValue(assetGraph) {
        // Discover all condition values:
        for (const splitCondition of splitConditions) {
            const isSeenByConditionValue = {};
            for (const htmlAsset of assetGraph.findAssets({type: 'Html', isInline: false, ...queryObj})) {
                for (const relation of assetGraph.findRelations({from: htmlAsset})) {
                    const dataSystemJsConditions = relation.node && assetGraphConditions.parse(relation.node);
                    if (dataSystemJsConditions) {
                        let key = splitCondition + '.js|default';
                        let value = dataSystemJsConditions[key];
                        if (!value) {
                            key = splitCondition + '|default';
                            value = dataSystemJsConditions[key];
                        }
                        if (value) {
                            isSeenByConditionValue[value] = true;
                        }
                    }
                }
                let conditionValues = (options.conditions && options.conditions[splitCondition]) || Object.keys(isSeenByConditionValue);
                if (typeof conditionValues === 'string') {
                    conditionValues = [conditionValues];
                }
                if (conditionValues.length > 0) {
                    for (const conditionValue of conditionValues) {
                        const clonedHtmlAsset = htmlAsset.clone();
                        const documentElement = clonedHtmlAsset.parseTree.documentElement;
                        if (documentElement) {
                            const htmlSystemJsConditionals = assetGraphConditions.parse(documentElement) || {};
                            htmlSystemJsConditionals[splitCondition] = conditionValue;
                            documentElement.setAttribute('data-assetgraph-conditions', assetGraphConditions.stringify(htmlSystemJsConditionals));
                            clonedHtmlAsset.markDirty();
                        }
                        const targetUrl = htmlAsset.url.replace(/(\.\w+)?$/, '.' + conditionValue + '$1');
                        clonedHtmlAsset.url = targetUrl;

                        for (const relation of assetGraph.findRelations({from: clonedHtmlAsset})) {
                            const dataSystemJsConditions = relation.node && assetGraphConditions.parse(relation.node);
                            if (dataSystemJsConditions) {
                                let key = splitCondition + '.js|default';
                                let value = dataSystemJsConditions[key];
                                if (!value) {
                                    key = splitCondition + '|default';
                                    value = dataSystemJsConditions[key];
                                }
                                if (value) {
                                    if (value === conditionValue) {
                                        delete dataSystemJsConditions[key];
                                        if (Object.keys(dataSystemJsConditions).length === 0) {
                                            relation.node.removeAttribute('data-assetgraph-conditions');
                                        } else {
                                            relation.node.setAttribute('data-assetgraph-conditions', assetGraphConditions.stringify(dataSystemJsConditions));
                                        }
                                        relation.from.markDirty();
                                    } else {
                                        relation.detach();
                                    }
                                    continue;
                                }
                            }
                        }
                    }
                    assetGraph.removeAsset(htmlAsset);
                }
            }
        }
    };
};
<|endoftext|>


<commit_before>var transformComps = require('./transform-composed-nodes'),
    async = require('async'),
    _ = require('underscore'),
    awaiter = require('collect').awaiter
    compositionRelationCypherList = require('./composition-relation-cypher-list')
    sortComps = require('./sort-compositions');

module.exports = {
  read: function(node, opts, callback) {
    var self = this;

    if (typeof node == 'function') {
      callback = node;
      opts = { depth: 2 };
      node = null;
    } else if (typeof opts == 'function') {
      callback = opts;
      opts = { depth: 2 };
    }

    var id = node == null ? null : this.db._getId(node);

    if (typeof opts == 'number') opts = { depth: opts };

    var depth = opts.depth == null ? 2 : opts.depth;

    if (opts.restrictToComp) {
      if (!this.compositions[opts.restrictToComp])
        callback(new Error(opts.restrictToComp + " is not a valid composition"));
      ++depth;
    }

    if (!Object.keys(this.compositions).length) depth = 0;

    var query = [ 'MATCH (root:' + this.type + ')' ];
    var params = {};

    if (id != null) {
      query.unshift('START root = node({__sm_root})')
      params['__sm_root'] = id;
    }

    if (opts.query)
      query.push(opts.query);
    if (opts.params)
      params = _.extend(opts.params, params);

    var comps;
    var compMapping = [];
    for (var level = 0; level < depth; ++level) {
      if (!comps) comps = opts.restrictToComp
                            ? [ this.compositions[opts.restrictToComp] ]
                            : _.values(this.compositions);
      else comps = _.flatten(comps.map(function(comp) {
          return _.values(comp.model.compositions);
        }), true);

      if (!comps.length) {
        depth = level;
        break;
      }

      compMapping.push(_.object(_.pluck(comps, 'rel'), comps));

      var rels = compositionRelationCypherList(comps);
      var start = level ? 'level' + (level - 1) : 'root';
      query.push('OPTIONAL MATCH');
      query.push(start + '-[r' + level + ':' + rels + ']->(level' + level + ')');
    }

    var returnVars = ['root', 'timestamp() as __ts'];
    for (var level = 0; level < depth; ++level) {
      returnVars.push('COLLECT( level' + level + ' ) as level' + level);
      returnVars.push('COLLECT( DISTINCT r' + level + ' ) as r' + level);
    }

    query.push("RETURN " + returnVars.join(','));

    this.db.query(query.join(' '), params, function(err, data) {
      if (err) {
        if (err.neo4jException == 'EntityNotFoundException') callback(null, false);
        else callback(err);
        return;
      };
      if (data.__ts) return self.compute(data.root, callback);
      if (!data.length) return callback(null, false);

      async.map(data, function(data, callback) {
        var node = data.root;

        async.forEach(_.range(depth -1, -1, -1), function(level, callback) {
          var startNodes = data['level' + (level - 1)] || [node];
          var endNodes = data['level' + level];

          var rels = data['r' + level];

          async.forEach(rels, function(rel, callback) {
            var start = _.find(startNodes, function(node) {
              return node[self.db.options.id] == rel.start;
            });
            var end = _.find(endNodes, function(node) {
              return node[self.db.options.id] == rel.end;
            });

            var comp = compMapping[level][rel.type];
            self.compute.call(comp.model, end, function(err, end) {
              if (err) return callback(err);

              if (start[comp.name]) {
                if (Array.isArray(start[comp.name])) start[comp.name].push(end);
                else start[comp.name] = [ start[comp.name], end ];
              } else start[comp.name] = comp.many ? [ end ] : end;

              callback();
            });
          }, callback);
        }, function(err) {
          if (err) callback(err);
          else {
            sortComps.call(self, node);
            if (opts.restrictToComp)
              callback(null, node[opts.restrictToComp]);
            else
              self.compute(node, callback);
          }
        });
      }, function(err, data) {
        if (err) return callback(err);
        callback(null, data.length > 1 ? data : data[0]);
      });
    });
  },
  readComposition: function(node, comp, depth, callback) {
    if (typeof depth == 'function') {
      callback = depth;
      depth = 2;
    }
    module.exports.read.call(this, node, { restrictToComp: comp, depth: depth }, callback);
  }
}
<commit_msg>removed last redundant dep<commit_after>var transformComps = require('./transform-composed-nodes'),
    async = require('async'),
    _ = require('underscore'),
    compositionRelationCypherList = require('./composition-relation-cypher-list')
    sortComps = require('./sort-compositions');

module.exports = {
  read: function(node, opts, callback) {
    var self = this;

    if (typeof node == 'function') {
      callback = node;
      opts = { depth: 2 };
      node = null;
    } else if (typeof opts == 'function') {
      callback = opts;
      opts = { depth: 2 };
    }

    var id = node == null ? null : this.db._getId(node);

    if (typeof opts == 'number') opts = { depth: opts };

    var depth = opts.depth == null ? 2 : opts.depth;

    if (opts.restrictToComp) {
      if (!this.compositions[opts.restrictToComp])
        callback(new Error(opts.restrictToComp + " is not a valid composition"));
      ++depth;
    }

    if (!Object.keys(this.compositions).length) depth = 0;

    var query = [ 'MATCH (root:' + this.type + ')' ];
    var params = {};

    if (id != null) {
      query.unshift('START root = node({__sm_root})')
      params['__sm_root'] = id;
    }

    if (opts.query)
      query.push(opts.query);
    if (opts.params)
      params = _.extend(opts.params, params);

    var comps;
    var compMapping = [];
    for (var level = 0; level < depth; ++level) {
      if (!comps) comps = opts.restrictToComp
                            ? [ this.compositions[opts.restrictToComp] ]
                            : _.values(this.compositions);
      else comps = _.flatten(comps.map(function(comp) {
          return _.values(comp.model.compositions);
        }), true);

      if (!comps.length) {
        depth = level;
        break;
      }

      compMapping.push(_.object(_.pluck(comps, 'rel'), comps));

      var rels = compositionRelationCypherList(comps);
      var start = level ? 'level' + (level - 1) : 'root';
      query.push('OPTIONAL MATCH');
      query.push(start + '-[r' + level + ':' + rels + ']->(level' + level + ')');
    }

    var returnVars = ['root', 'timestamp() as __ts'];
    for (var level = 0; level < depth; ++level) {
      returnVars.push('COLLECT( level' + level + ' ) as level' + level);
      returnVars.push('COLLECT( DISTINCT r' + level + ' ) as r' + level);
    }

    query.push("RETURN " + returnVars.join(','));

    this.db.query(query.join(' '), params, function(err, data) {
      if (err) {
        if (err.neo4jException == 'EntityNotFoundException') callback(null, false);
        else callback(err);
        return;
      };
      if (data.__ts) return self.compute(data.root, callback);
      if (!data.length) return callback(null, false);

      async.map(data, function(data, callback) {
        var node = data.root;

        async.forEach(_.range(depth -1, -1, -1), function(level, callback) {
          var startNodes = data['level' + (level - 1)] || [node];
          var endNodes = data['level' + level];

          var rels = data['r' + level];

          async.forEach(rels, function(rel, callback) {
            var start = _.find(startNodes, function(node) {
              return node[self.db.options.id] == rel.start;
            });
            var end = _.find(endNodes, function(node) {
              return node[self.db.options.id] == rel.end;
            });

            var comp = compMapping[level][rel.type];
            self.compute.call(comp.model, end, function(err, end) {
              if (err) return callback(err);

              if (start[comp.name]) {
                if (Array.isArray(start[comp.name])) start[comp.name].push(end);
                else start[comp.name] = [ start[comp.name], end ];
              } else start[comp.name] = comp.many ? [ end ] : end;

              callback();
            });
          }, callback);
        }, function(err) {
          if (err) callback(err);
          else {
            sortComps.call(self, node);
            if (opts.restrictToComp)
              callback(null, node[opts.restrictToComp]);
            else
              self.compute(node, callback);
          }
        });
      }, function(err, data) {
        if (err) return callback(err);
        callback(null, data.length > 1 ? data : data[0]);
      });
    });
  },
  readComposition: function(node, comp, depth, callback) {
    if (typeof depth == 'function') {
      callback = depth;
      depth = 2;
    }
    module.exports.read.call(this, node, { restrictToComp: comp, depth: depth }, callback);
  }
}
<|endoftext|>


<commit_before>'use strict'; // eslint-disable-line strict

const path = require('path');
const mute = require('mute');
const childProcess = require('child_process');
const fsh = require('./fsh');

function getRepoTypeForParams(repoPath, repoType) {
  if (repoType === undefined) {
    return this.getRepoTypeForLocalPath(repoPath);
  }
  return repoType;
}

module.exports = {

  isGitRepository(repository) {
    const unmute = mute();
    try {
      // KISS and get git to check. Hard to be definitive by hand, especially with scp URLs.
      childProcess.execFileSync(
        'git', ['ls-remote', repository]
      );
      unmute();
      return true;
    } catch (err) {
      unmute();
      return false;
    }
  },

  isHgRepository(repository) {
    const unmute = mute();
    try {
      // KISS and get hg to check. Hard to be definitive by hand, especially with scp URLs.
      childProcess.execFileSync(
        'hg', ['id', repository]
      );
      unmute();
      return true;
    } catch (err) {
      unmute();
      return false;
    }
  },

  getRepoTypeForLocalPath(repoPath) {
    if (fsh.dirExistsSync(path.join(repoPath, '.git'))) {
      return 'git';
    } else if (fsh.dirExistsSync(path.join(repoPath, '.hg'))) {
      return 'hg';
    }

    return undefined;
  },

  getOrigin(repoPath, repoTypeParam) {
    let origin;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      try {
        origin = childProcess.execFileSync(
          'git', ['-C', repoPath, 'config', '--get', 'remote.origin.url']
        ).toString().trim();
      } catch (err) {
        // May have created repo locally and does not yet have an origin
      }
    } else if (repoType === 'hg') {
      origin = childProcess.execFileSync(
        'hg', ['--repository', repoPath, 'config', 'paths.default']
      ).toString().trim();
    }
    return origin;
  },

  getBranch(repoPath, repoTypeParam) {
    let branch;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      const unmute = mute();
      try {
        // This will fail if have detached head, but does work for an empty repo
        branch = childProcess.execFileSync(
           'git', ['symbolic-ref', '--short', 'HEAD'], { cwd: repoPath }
        ).toString().trim();
      } catch (err) {
        branch = undefined;
      }
      unmute();
    } else if (repoType === 'hg') {
      branch = childProcess.execFileSync(
        'hg', ['--repository', repoPath, 'branch']
      ).toString().trim();
    }
    return branch;
  },

  getRevision(repoPath, repoTypeParam) {
    let revision;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      revision = childProcess.execFileSync(
         'git', ['rev-parse', 'HEAD'], { cwd: repoPath }
      ).toString().trim();
    } else if (repoType === 'hg') {
      revision = childProcess.execFileSync(
        'hg', ['log', '--rev', '.', '--template', '{node}'], { cwd: repoPath }
      ).toString().trim();
    }
    return revision;
  },

};
<commit_msg>Consistently use cwd rather than command specific repository path changes<commit_after>'use strict'; // eslint-disable-line strict

const path = require('path');
const mute = require('mute');
const childProcess = require('child_process');
const fsh = require('./fsh');

function getRepoTypeForParams(repoPath, repoType) {
  if (repoType === undefined) {
    return this.getRepoTypeForLocalPath(repoPath);
  }
  return repoType;
}

module.exports = {

  isGitRepository(repository) {
    const unmute = mute();
    try {
      // KISS and get git to check. Hard to be definitive by hand, especially with scp URLs.
      childProcess.execFileSync(
        'git', ['ls-remote', repository]
      );
      unmute();
      return true;
    } catch (err) {
      unmute();
      return false;
    }
  },

  isHgRepository(repository) {
    const unmute = mute();
    try {
      // KISS and get hg to check. Hard to be definitive by hand, especially with scp URLs.
      childProcess.execFileSync(
        'hg', ['id', repository]
      );
      unmute();
      return true;
    } catch (err) {
      unmute();
      return false;
    }
  },

  getRepoTypeForLocalPath(repoPath) {
    if (fsh.dirExistsSync(path.join(repoPath, '.git'))) {
      return 'git';
    } else if (fsh.dirExistsSync(path.join(repoPath, '.hg'))) {
      return 'hg';
    }

    return undefined;
  },

  getOrigin(repoPath, repoTypeParam) {
    let origin;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      try {
        origin = childProcess.execFileSync(
          'git', ['config', '--get', 'remote.origin.url'], { cwd: repoPath }
        ).toString().trim();
      } catch (err) {
        // May have created repo locally and does not yet have an origin
      }
    } else if (repoType === 'hg') {
      origin = childProcess.execFileSync(
        'hg', ['config', 'paths.default'], { cwd: repoPath }
      ).toString().trim();
    }
    return origin;
  },

  getBranch(repoPath, repoTypeParam) {
    let branch;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      const unmute = mute();
      try {
        // This will fail if have detached head, but does work for an empty repo
        branch = childProcess.execFileSync(
           'git', ['symbolic-ref', '--short', 'HEAD'], { cwd: repoPath }
        ).toString().trim();
      } catch (err) {
        branch = undefined;
      }
      unmute();
    } else if (repoType === 'hg') {
      branch = childProcess.execFileSync(
        'hg', ['branch'], { cwd: repoPath }
      ).toString().trim();
    }
    return branch;
  },

  getRevision(repoPath, repoTypeParam) {
    let revision;
    const repoType = getRepoTypeForParams(repoPath, repoTypeParam);

    if (repoType === 'git') {
      revision = childProcess.execFileSync(
         'git', ['rev-parse', 'HEAD'], { cwd: repoPath }
      ).toString().trim();
    } else if (repoType === 'hg') {
      revision = childProcess.execFileSync(
        'hg', ['log', '--rev', '.', '--template', '{node}'], { cwd: repoPath }
      ).toString().trim();
    }
    return revision;
  },

};
<|endoftext|>