<commit_before>'use strict';

var gulp = require('gulp'),
    qunit = require('gulp-qunit'),
    gutil = require('gulp-util'),
    size = require('gulp-size'),
    concat = require('gulp-concat'),
    closureCompiler = require('gulp-closure-compiler'),
    through = require('through2'),
    nglob = require('glob'),
    jsSource = './src/**/*.js',

    fs = require('fs'),
    path = require('path');

// Force an ordering on the package structure. It would be nice to use
// gulp-ordering and get ride of the packageReorder function, but that would
// require changing the way namespaces are created.
var ordering = [
  // Top level source package must go first since it defines the namespace
  '.*/src$',
  // I'm not entirely sure why, but util must go first. Probably due to some
  // faulty name-space aliasing.
  '.*/util$',
  // The widgetopt dir depends *directly* on the controllers. Yuck. These need
  // to be refactored, probably by putting the widget options directly in the
  // controller dirs.
  '.*/controllers$',
  // For most packages it doesn't matter. However, to prevent commit thrashing
  // in the HTML tests, we sort the output files.
  // Implicitly, the last entry is '.',
]

// The glob used for determining sources.
var srcGlob = [
  'src/**/*.js',
  // Ignore these groups of files:
  '!src/**/*_test.js',
  '!src/htmltests/*',
  '!src/libs/*',
  '!src/testdata/*']

// The glob used for determining tests
var testGlob = ['src/**/*_test.js']

// The full build-test cycle. This:
// - Updates all the HTML files
// - Recreates the concat-target
// - Runs all the tests
// - Compiles with JSCompiler + TypeChecking
gulp.task('build-test', ['concat', 'compile', 'test'])

gulp.task('test', ['update-html-tests', 'update-html-srcs'], () => {
  return gulp.src('./src/htmltests_gen/QunitTest.html').pipe(qunit())
});

gulp.task('test-simple', () => {
  return gulp.src('./src/htmltests_gen/QunitTest.html').pipe(qunit())
});

// A watcher for the the full build-test cycle.
gulp.task('test-watch', () => {
  return gulp.watch([
    'src/**/*.js',
    'src/**/*_test.js'], ['test'] );
});

// A simpler watcher that just updates the
gulp.task('update-html-watch', () => {
  return gulp.watch([
    'src/**/*.js',
    'src/**/*_test.js'], ['update-html-tests', 'update-html-srcs'] );
})

// Compile the sources with the JS Compiler
gulp.task('compile', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(closureCompiler({
      compilerPath: './compiler-latest/compiler.jar',
      fileName: 'glift.js',
      compilerFlags: {
        // TODO(kashomon): Turn on ADVANCED_OPTIMIZATIONS when all the right
        // functions have been marked @export, where appropriate
        // compilation_level: 'ADVANCED_OPTIMIZATIONS',
        //
        language_in: 'ECMASCRIPT5',
        // Note that warning_level=VERBOSE corresponds to:
        //
        // --jscomp_warning=checkTypes
        // --jscomp_error=checkVars
        // --jscomp_warning=deprecated
        // --jscomp_error=duplicate
        // --jscomp_warning=globalThis
        // --jscomp_warning=missingProperties
        // --jscomp_warning=undefinedNames
        // --jscomp_error=undefinedVars
        //
        // Do some advanced Javascript checks.
        // https://github.com/google/closure-compiler/wiki/Warnings
        jscomp_error: [
          'accessControls',
          'checkRegExp',
          'checkTypes',
          'checkVars',
          'const',
          'constantProperty',
          'deprecated',
          'duplicate',
          'missingProperties',
          'missingProvide',
          'undefinedNames',
          'undefinedVars',
          'globalThis',
          // We don't turn requires into Errors, because the closure compiler
          // reorders the sources based on the requires.
          // 'missingRequire',
        ]
      }
    }))
    .pipe(size())
    .pipe(gulp.dest('./compiled/'))
})

gulp.task('concat', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(concat('glift_combined.js'))
    .pipe(size())
    .pipe(gulp.dest('./compiled/'))
})

// Update the HTML tests with the dev JS source files
gulp.task('update-html-srcs', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/*.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-DEPS -->',
      footer: '<!-- END-AUTO-GEN-DEPS -->',
      dirHeader: '<!-- %s sources -->',
    }))
});

// Update the HTML tests with the test JS files
gulp.task('update-html-tests', () => {
  return gulp.src(testGlob)
    .pipe(packageReorder())
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/QunitTest.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-TESTS -->',
      footer: '<!-- END-AUTO-GEN-TESTS -->',
      dirHeader: '<!-- %s tests -->',
    }))
})

// Update the HTML tests with the compiled glift.
gulp.task('update-html-compiled', () => {
  return gulp.src('./compiled/glift.js')
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/*.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-DEPS -->',
      footer: '<!-- END-AUTO-GEN-DEPS -->',
      dirHeader: '<!-- %s sources -->',
    }))
});

/////////////////////////////////////////////////
/////////////// Library Functions ///////////////
/////////////////////////////////////////////////
//
// Beware! Below lie demons unvanquished.
//
// TODO(kashomon): Move these to a node library for sharing with GPub?

/**
 * Reorder so that the file with the same name as the package comes first.
 */
function packageReorder(orderx) {
  var all = []
  var orderx = (orderx || []).slice()
  orderx = orderx.map((s) => new RegExp(s))
  return through.obj(function(file, enc, cb) {
    all.push(file);
    cb();
  }, function(cb) {
    var tr = [];
    var dirMap = {};
    var dirlist = []; // So we can order the directories.
    all.forEach((f) => {
      var fullpath = f.path;
      var ppath = path.parse(f.path);
      var dir = ppath.dir;
      if (!dirMap[dir]) {
        dirMap[dir] = [];
        dirlist.push(dir);
      }
      var splat = ppath.dir.split(path.sep)
      var last = splat[splat.length - 1]
      if (last === ppath.name) {
        dirMap[dir].unshift(f)
      } else {
        dirMap[dir].push(f)
      }
    });

    // Based on the ordering array passed in, group the directories togther and
    // do sorting based on the groupings.
    var dirlistSorted = []
    var processed = {}
    for (var i = 0; i <= orderx.length; i++) {
      var reg;
      if (i === orderx.length) {
        reg = /.*/;
      } else {
        reg = orderx[i];
      }
      var suborder = []
      dirlist.forEach((d) => {
        if (!processed[d] && reg.test(d)) {
          suborder.push(d)
          processed[d] = true;
        } else {
        }
      })
      suborder.sort()
      dirlistSorted = dirlistSorted.concat(suborder);
    }

    dirlistSorted.forEach((dir) => {
      dirMap[dir].forEach((f) => {
        tr.push(f);
      });
    })
    tr.forEach((f) => {
      this.push(f);
    });
    cb();
  });
};

function updateHtmlFiles(params) {
  var files = nglob.sync(params.filesGlob);
  var header = params.header;
  var footer = params.footer;
  var regexp = new RegExp(`(${header})(.|\n)*(${footer})`, 'g')
  var outDir = params.outDir;

  var dirHeader = params.dirHeader;
  var all = [];
  var template = params.template || '<script type="text/javascript" src="%s"></script>';

  return through.obj(function(file, enc, cb) {
    all.push(file);
    cb();
  }, function(cb) {
    var htmldir = path.dirname(files[0])

    var tags = [];
    var lastdir = null
    all.forEach((f) => {
      var relpath = path.relative(htmldir, f.path)

      var dir = path.dirname(f.path)
      if (dir !== lastdir) {
        tags.push(dirHeader.replace('%s', path.relative(htmldir, dir)))
        lastdir = dir
      }

      tags.push(template.replace('%s', relpath))
      this.push(f)
    })

    var text = tags.join('\n');

    if (!fs.existsSync(outDir)){
      fs.mkdirSync(outDir);
    }

    files.forEach((fname) => {
      var parsedPath = path.parse(fname)
      var outPath = path.join(outDir, parsedPath.base)
      if (!fs.existsSync(outPath)) {
        // First we write the template files.
        var contents = fs.readFileSync(fname, {encoding: 'UTF-8'})
        fs.writeFileSync(outPath, contents)
      }
      // Then, read from the newly-written file and overwrite the template
      // sections.
      var contents = fs.readFileSync(outPath, {encoding: 'UTF-8'})
      var replaced = contents.replace(regexp, '$1\n' + text + '\n$3')
      fs.writeFileSync(outPath, replaced)
    });

    cb();
  })
}
<commit_msg>Enable a couple more compiler checks.<commit_after>'use strict';

var gulp = require('gulp'),
    qunit = require('gulp-qunit'),
    gutil = require('gulp-util'),
    size = require('gulp-size'),
    concat = require('gulp-concat'),
    closureCompiler = require('gulp-closure-compiler'),
    through = require('through2'),
    nglob = require('glob'),
    jsSource = './src/**/*.js',

    fs = require('fs'),
    path = require('path');

// Force an ordering on the package structure. It would be nice to use
// gulp-ordering and get ride of the packageReorder function, but that would
// require changing the way namespaces are created.
var ordering = [
  // Top level source package must go first since it defines the namespace
  '.*/src$',
  // I'm not entirely sure why, but util must go first. Probably due to some
  // faulty name-space aliasing.
  '.*/util$',
  // The widgetopt dir depends *directly* on the controllers. Yuck. These need
  // to be refactored, probably by putting the widget options directly in the
  // controller dirs.
  '.*/controllers$',
  // For most packages it doesn't matter. However, to prevent commit thrashing
  // in the HTML tests, we sort the output files.
  // Implicitly, the last entry is '.',
]

// The glob used for determining sources.
var srcGlob = [
  'src/**/*.js',
  // Ignore these groups of files:
  '!src/**/*_test.js',
  '!src/htmltests/*',
  '!src/libs/*',
  '!src/testdata/*']

// The glob used for determining tests
var testGlob = ['src/**/*_test.js']

// The full build-test cycle. This:
// - Updates all the HTML files
// - Recreates the concat-target
// - Runs all the tests
// - Compiles with JSCompiler + TypeChecking
gulp.task('build-test', ['concat', 'compile', 'test'])

gulp.task('test', ['update-html-tests', 'update-html-srcs'], () => {
  return gulp.src('./src/htmltests_gen/QunitTest.html').pipe(qunit())
});

gulp.task('test-simple', () => {
  return gulp.src('./src/htmltests_gen/QunitTest.html').pipe(qunit())
});

// A watcher for the the full build-test cycle.
gulp.task('test-watch', () => {
  return gulp.watch([
    'src/**/*.js',
    'src/**/*_test.js'], ['test'] );
});

// A simpler watcher that just updates the
gulp.task('update-html-watch', () => {
  return gulp.watch([
    'src/**/*.js',
    'src/**/*_test.js'], ['update-html-tests', 'update-html-srcs'] );
})

// Compile the sources with the JS Compiler
gulp.task('compile', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(closureCompiler({
      compilerPath: './compiler-latest/compiler.jar',
      fileName: 'glift.js',
      compilerFlags: {
        // TODO(kashomon): Turn on ADVANCED_OPTIMIZATIONS when all the right
        // functions have been marked @export, where appropriate
        // compilation_level: 'ADVANCED_OPTIMIZATIONS',
        //
        language_in: 'ECMASCRIPT5',
        // Note that warning_level=VERBOSE corresponds to:
        //
        // --jscomp_warning=checkTypes
        // --jscomp_error=checkVars
        // --jscomp_warning=deprecated
        // --jscomp_error=duplicate
        // --jscomp_warning=globalThis
        // --jscomp_warning=missingProperties
        // --jscomp_warning=undefinedNames
        // --jscomp_error=undefinedVars
        //
        // Do some advanced Javascript checks.
        // https://github.com/google/closure-compiler/wiki/Warnings
        jscomp_error: [
          'accessControls',
          'checkRegExp',
          'checkTypes',
          'checkVars',
          'const',
          'constantProperty',
          'deprecated',
          'duplicate',
          'globalThis',
          'missingProperties',
          'missingProvide',
          'missingReturn',
          'undefinedNames',
          'undefinedVars',
          'visibility',
          // We don't turn requires into Errors, because the closure compiler
          // reorders the sources based on the requires.
          // 'missingRequire',
        ]
      }
    }))
    .pipe(size())
    .pipe(gulp.dest('./compiled/'))
})

gulp.task('concat', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(concat('glift_combined.js'))
    .pipe(size())
    .pipe(gulp.dest('./compiled/'))
})

// Update the HTML tests with the dev JS source files
gulp.task('update-html-srcs', () => {
  return gulp.src(srcGlob)
    .pipe(packageReorder(ordering))
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/*.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-DEPS -->',
      footer: '<!-- END-AUTO-GEN-DEPS -->',
      dirHeader: '<!-- %s sources -->',
    }))
});

// Update the HTML tests with the test JS files
gulp.task('update-html-tests', () => {
  return gulp.src(testGlob)
    .pipe(packageReorder())
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/QunitTest.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-TESTS -->',
      footer: '<!-- END-AUTO-GEN-TESTS -->',
      dirHeader: '<!-- %s tests -->',
    }))
})

// Update the HTML tests with the compiled glift.
gulp.task('update-html-compiled', () => {
  return gulp.src('./compiled/glift.js')
    .pipe(updateHtmlFiles({
      filesGlob: './src/htmltests/*.html',
      outDir: './src/htmltests_gen/',
      header: '<!-- AUTO-GEN-DEPS -->',
      footer: '<!-- END-AUTO-GEN-DEPS -->',
      dirHeader: '<!-- %s sources -->',
    }))
});

/////////////////////////////////////////////////
/////////////// Library Functions ///////////////
/////////////////////////////////////////////////
//
// Beware! Below lie demons unvanquished.
//
// TODO(kashomon): Move these to a node library for sharing with GPub?

/**
 * Reorder so that the file with the same name as the package comes first.
 */
function packageReorder(orderx) {
  var all = []
  var orderx = (orderx || []).slice()
  orderx = orderx.map((s) => new RegExp(s))
  return through.obj(function(file, enc, cb) {
    all.push(file);
    cb();
  }, function(cb) {
    var tr = [];
    var dirMap = {};
    var dirlist = []; // So we can order the directories.
    all.forEach((f) => {
      var fullpath = f.path;
      var ppath = path.parse(f.path);
      var dir = ppath.dir;
      if (!dirMap[dir]) {
        dirMap[dir] = [];
        dirlist.push(dir);
      }
      var splat = ppath.dir.split(path.sep)
      var last = splat[splat.length - 1]
      if (last === ppath.name) {
        dirMap[dir].unshift(f)
      } else {
        dirMap[dir].push(f)
      }
    });

    // Based on the ordering array passed in, group the directories togther and
    // do sorting based on the groupings.
    var dirlistSorted = []
    var processed = {}
    for (var i = 0; i <= orderx.length; i++) {
      var reg;
      if (i === orderx.length) {
        reg = /.*/;
      } else {
        reg = orderx[i];
      }
      var suborder = []
      dirlist.forEach((d) => {
        if (!processed[d] && reg.test(d)) {
          suborder.push(d)
          processed[d] = true;
        } else {
        }
      })
      suborder.sort()
      dirlistSorted = dirlistSorted.concat(suborder);
    }

    dirlistSorted.forEach((dir) => {
      dirMap[dir].forEach((f) => {
        tr.push(f);
      });
    })
    tr.forEach((f) => {
      this.push(f);
    });
    cb();
  });
};

function updateHtmlFiles(params) {
  var files = nglob.sync(params.filesGlob);
  var header = params.header;
  var footer = params.footer;
  var regexp = new RegExp(`(${header})(.|\n)*(${footer})`, 'g')
  var outDir = params.outDir;

  var dirHeader = params.dirHeader;
  var all = [];
  var template = params.template || '<script type="text/javascript" src="%s"></script>';

  return through.obj(function(file, enc, cb) {
    all.push(file);
    cb();
  }, function(cb) {
    var htmldir = path.dirname(files[0])

    var tags = [];
    var lastdir = null
    all.forEach((f) => {
      var relpath = path.relative(htmldir, f.path)

      var dir = path.dirname(f.path)
      if (dir !== lastdir) {
        tags.push(dirHeader.replace('%s', path.relative(htmldir, dir)))
        lastdir = dir
      }

      tags.push(template.replace('%s', relpath))
      this.push(f)
    })

    var text = tags.join('\n');

    if (!fs.existsSync(outDir)){
      fs.mkdirSync(outDir);
    }

    files.forEach((fname) => {
      var parsedPath = path.parse(fname)
      var outPath = path.join(outDir, parsedPath.base)
      if (!fs.existsSync(outPath)) {
        // First we write the template files.
        var contents = fs.readFileSync(fname, {encoding: 'UTF-8'})
        fs.writeFileSync(outPath, contents)
      }
      // Then, read from the newly-written file and overwrite the template
      // sections.
      var contents = fs.readFileSync(outPath, {encoding: 'UTF-8'})
      var replaced = contents.replace(regexp, '$1\n' + text + '\n$3')
      fs.writeFileSync(outPath, replaced)
    });

    cb();
  })
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Requirements
 */
const baseSpec = require(ES_TEST + '/BaseShared.js').spec;
const sinon = require('sinon');
const co = require('co');
const gulp = require('gulp');

/**
 * Shared Task spec
 */
function spec(type, className, prepareParameters, options)
{
    const opts = options || {};

    /**
     * Base Test
     */
    baseSpec(type, className, prepareParameters);

    /**
     * Task Test
     */
    const createTestee = function()
    {
        let parameters = Array.from(arguments);
        if (prepareParameters)
        {
            parameters = prepareParameters(parameters);
        }
        return new type(...parameters);
    };

    /**
     * Reads the given stream and resolves to an array of all chunks
     */
    function readStream(stream)
    {
        const promise = new Promise((resolve) =>
        {
            const data = [];
            stream.on('data', (item) =>
            {
                process.nextTick(() =>
                {
                    data.push(item);
                });
            })
            .on('finish', () =>
            {
                process.nextTick(() =>
                {
                    resolve(data);
                });
            });
        });
        return promise;
    }
    spec.readStream = readStream;

    /**
     * Creates a stream of files
     */
    function filesStream(glob)
    {
        return gulp.src(glob);
    }
    spec.filesStream = filesStream;

    /**
     * Creates a stream of files and waits until they ran through the task
     */
    function feedFiles(task, glob)
    {
        return readStream(task.stream(filesStream(glob)));
    }
    spec.feedFiles = feedFiles;

    describe('#pipe()', function()
    {
        it('should return the piped Task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(result).to.be.equal(pipedTestee);
            return result;
        });

        it('should set previousTask on the piped task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(pipedTestee.previousTask).to.be.equal(testee);
            return result;
        });

        it('should set nextTask on the task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(testee.nextTask).to.be.equal(pipedTestee);
            return result;
        });
    });

    describe('#stream()', function()
    {
        it('should return a stream', function()
        {
            const promise = co(function *()
            {
                const testee = createTestee();
                const result = testee.stream();
                expect(result.pipe).to.be.instanceof(Function); // We want to support through2 here....
                yield readStream(result);
            });
            return promise;
        });
    });

    describe('#run()', function()
    {
        it('should return a promise', function()
        {
            const testee = createTestee();
            const result = testee.run();
            expect(result).to.be.instanceof(Promise);
            return result;
        });

        if (!opts.skipDelegateTest)
        {
            it('should delegate to the root task', function()
            {
                const promise = co(function *()
                {
                    const testee = createTestee();
                    const pipedTestee = createTestee();
                    sinon.spy(testee, 'run');
                    sinon.spy(pipedTestee, 'run');
                    testee.pipe(pipedTestee);
                    yield pipedTestee.run();
                    expect(testee.run.calledOnce).to.be.ok;
                    expect(pipedTestee.run.calledOnce).to.be.ok;
                });
                return promise;
            });
        }
    });

}

/**
 * Exports
 */
module.exports.spec = spec;
<commit_msg>test(task.Task): moved helper out of spec<commit_after>'use strict';

/**
 * Requirements
 */
const baseSpec = require(ES_TEST + '/BaseShared.js').spec;
const sinon = require('sinon');
const co = require('co');
const gulp = require('gulp');

/**
 * Shared Task spec
 */
function spec(type, className, prepareParameters, options)
{
    const opts = options || {};

    /**
     * Base Test
     */
    baseSpec(type, className, prepareParameters);

    /**
     * Task Test
     */
    const createTestee = function()
    {
        let parameters = Array.from(arguments);
        if (prepareParameters)
        {
            parameters = prepareParameters(parameters);
        }
        return new type(...parameters);
    };

    describe('#pipe()', function()
    {
        it('should return the piped Task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(result).to.be.equal(pipedTestee);
            return result;
        });

        it('should set previousTask on the piped task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(pipedTestee.previousTask).to.be.equal(testee);
            return result;
        });

        it('should set nextTask on the task', function()
        {
            const testee = createTestee();
            const pipedTestee = createTestee();
            const result = testee.pipe(pipedTestee);
            expect(testee.nextTask).to.be.equal(pipedTestee);
            return result;
        });
    });

    describe('#stream()', function()
    {
        it('should return a stream', function()
        {
            const promise = co(function *()
            {
                const testee = createTestee();
                const result = testee.stream();
                expect(result.pipe).to.be.instanceof(Function); // We want to support through2 here....
                yield spec.readStream(result);
            });
            return promise;
        });
    });

    describe('#run()', function()
    {
        it('should return a promise', function()
        {
            const testee = createTestee();
            const result = testee.run();
            expect(result).to.be.instanceof(Promise);
            return result;
        });

        if (!opts.skipDelegateTest)
        {
            it('should delegate to the root task', function()
            {
                const promise = co(function *()
                {
                    const testee = createTestee();
                    const pipedTestee = createTestee();
                    sinon.spy(testee, 'run');
                    sinon.spy(pipedTestee, 'run');
                    testee.pipe(pipedTestee);
                    yield pipedTestee.run();
                    expect(testee.run.calledOnce).to.be.ok;
                    expect(pipedTestee.run.calledOnce).to.be.ok;
                });
                return promise;
            });
        }
    });
}

/**
 * Reads the given stream and resolves to an array of all chunks
 */
spec.readStream = function(stream)
{
    const promise = new Promise((resolve) =>
    {
        const data = [];
        stream.on('data', (item) =>
        {
            process.nextTick(() =>
            {
                data.push(item);
            });
        })
        .on('finish', () =>
        {
            process.nextTick(() =>
            {
                resolve(data);
            });
        });
    });
    return promise;
};

/**
 * Creates a stream of files
 */
spec.filesStream = function(glob)
{
    return gulp.src(glob);
};

/**
 * Creates a stream of files and waits until they ran through the task
 */
spec.feedFiles = function(task, glob)
{
    return spec.readStream(task.stream(spec.filesStream(glob)));
};

/**
 * Exports
 */
module.exports.spec = spec;
<|endoftext|>


<commit_before>import ol from 'openlayers'
import $ from 'jquery'

import {Window} from './html/Window'
import {cssClasses} from './globals'
import {finishAllImages} from './utilities'
import {Debug} from './Debug'

import '../less/featurepopup.less'

/**
 * @typedef {object} FeaturePopupOptions
 * @property {string} [className='g4u-featurepopup']
 * @property {number[]} [offset=[0,0]]
 * @property {ol.OverlayPositioning} [positioning='center-center']
 * @property {number[]} [iconSizedOffset=[0,0]]
 * @property {boolean} [centerOnPopup=false]
 * @property {boolean} [animated]
 */

/**
 * @typedef {function} Mutator
 * @param {string} text
 * @returns {string}
 */

/**
 * Displays a Popup bound to a geographical position via an ol.Overlay
 */
export class FeaturePopup extends ol.Object {
  /**
   * @param {FeaturePopupOptions} options
   */
  constructor (options = {}) {
    super()

    /**
     * @type {string}
     * @private
     */
    this.className_ = (options.hasOwnProperty('className')) ? options.className : 'g4u-featurepopup'

    /**
     * @type {string}
     * @private
     */
    this.classNameFeatureName_ = this.className_ + '-feature-name'

    /**
     * @type {string}
     * @private
     */
    this.classNameFeatureDescription_ = this.className_ + '-feature-description'

    /**
     * @type {jQuery}
     * @private
     */
    this.$name_ = $('<h3>').addClass(this.classNameFeatureName_)

    /**
     * @type {jQuery}
     * @private
     */
    this.$description_ = $('<p>').addClass(this.classNameFeatureDescription_)

    /**
     * @type {null|ol.Feature}
     * @private
     */
    this.feature_ = null

    /**
     * @type {boolean}
     * @private
     */
    this.visible_ = false

    /**
     * @type {VectorLayer[]}
     * @private
     */
    this.referencingVisibleLayers_ = []

    /**
     * @type {number[]}
     * @private
     */
    this.pixelOffset_ = (options.hasOwnProperty('offset')) ? options.offset : [ 0, 0 ]

    /**
     * @type {number[]}
     * @private
     */
    this.iconSizedOffset_ = (options.hasOwnProperty('iconSizedOffset')) ? options.iconSizedOffset : [ 0, 0 ]

    /**
     * @type {boolean}
     * @private
     */
    this.centerOnPopup_ = (options.hasOwnProperty('centerOnPopup')) ? options.centerOnPopup : true

    /**
     * @type {boolean}
     * @private
     */
    this.centerOnPopupInitial_ = this.centerOnPopup_

    /**
     * @type {boolean}
     * @private
     */
    this.animated_ = (options.hasOwnProperty('animated')) ? options.animated : false

    /**
     * @type {jQuery}
     * @private
     */
    this.$element_ = $('<div>').addClass(this.className_).addClass(cssClasses.hidden)

    /**
     * @type {ol.Overlay}
     * @private
     */
    this.overlay_ = new ol.Overlay({
      element: this.$element_.get(0),
      offset: this.pixelOffset_,
      positioning: (options.hasOwnProperty('positioning')) ? options.positioning : 'center-center',
      stopEvent: false
    })

    this.overlay_.setOffset(this.pixelOffset_)

    /**
     * @type {Map.<string,function>}
     * @private
     */
    this.mutators_ = new Map()

    /**
     * @type {string[]}
     * @private
     */
    this.defaultMutators_ = options.mutators || []

    /**
     * @type {string[]}
     * @private
     */
    this.useMutators_ = []

    /**
     * @type {?Window}
     * @private
     */
    this.window_ = null

    /**
     * @type {?G4UMap}
     * @private
     */
    this.map__ = null
  }

  /**
   * @param {ol.Feature} feature
   * @returns {boolean}
   * @private
   */
  static filter_ (feature) {
    return !feature.get('disabled') && (feature.get('name') || feature.get('description'))
  }

  /**
   * @param {G4UMap} map
   */
  setMap (map) {
    let popup = this

    let sourceOnFeatureRemove = function (e) {
      if (e.feature === popup.getFeature()) {
        let source = this
        popup.referencingVisibleLayers_.forEach(function (layer) {
          if (layer.getSource() === source) {
            popup.removeReferencingLayer_(layer)
          }
        })
      }
    }

    let layerOnChangeVisible = function () {
      if (this.getVisible() === false) {
        if (this.getSource().getFeatures().indexOf(popup.getFeature()) > -1) {
          popup.removeReferencingLayer_(this)
        }
      } else {
        if (this.getSource().getFeatures().indexOf(popup.getFeature()) > -1) {
          popup.referencingVisibleLayers_.push(this)
        }
      }
    }

    let onForEachLayer = (layer) => {
      if (layer.getSource && layer.getSource().getFeatures) {
        layer.getSource().on('removefeature', sourceOnFeatureRemove)
        layer.on('change:visible', layerOnChangeVisible)
      }
    }

    let unForEachLayer = (layer) => {
      if (layer.getSource && layer.getSource().getFeatures) {
        layer.getSource().un('removefeature', sourceOnFeatureRemove)
        layer.un('change:visible', layerOnChangeVisible)
      }
    }

    let onLayerAdd = (e) => {
      onForEachLayer(e.element)
    }

    let onMapChangeMobile = () => {
      if (map.get('mobile')) {
        this.centerOnPopup_ = false
      } else {
        this.centerOnPopup_ = this.centerOnPopupInitial_
      }
    }

    if (this.getMap()) {
      this.getMap().removeInteraction(this.featureClick_)
      this.getMap().getLayerGroup().recursiveForEach(unForEachLayer)
      this.getMap().getLayerGroup().un('add', onLayerAdd)
      this.getMap().removeInteraction(this.featureHover_)
      this.getMap().removeOverlay(this.overlay_)
      this.getMap().un('change:mobile', onMapChangeMobile)
    }

    if (map) {
      this.window_ = new Window({ draggable: false, fixedPosition: true, map: map })

      this.window_.get$Body().append(this.$name_).append(this.$description_)

      this.window_.on('change:visible', () => {
        if (!this.window_.getVisible()) {
          this.setVisible(false) // notifying the featurepopup about the closing of the window
        }
      })

      this.$element_.append(this.window_.get$Element())

      // feature click

      map.getDefaultInteractions('singleClick')[ 0 ].on('select', e => {
        let selected = e.selected.filter(FeaturePopup.filter_)
        if (selected.length) {
          this.onFeatureClick_(selected[ 0 ])
          e.target.getFeatures().remove(selected[ 0 ]) // remove feature to be able to select feature again
          e.target.changed()
        }
      })

      // feature hover

      map.getDefaultInteractions('mouseMove')[ 0 ].on('select', e => {
        let selected = e.selected.filter(FeaturePopup.filter_)
        let deselected = e.deselected.filter(FeaturePopup.filter_)
        if (selected.length) {
          $(map.getViewport()).addClass(cssClasses.clickable)
        } else if (deselected.length) {
          $(map.getViewport()).removeClass(cssClasses.clickable)
        }
      })

      // hiding feature Popup if the layer gets hidden or the feature gets removed

      map.getLayerGroup().recursiveForEach(onForEachLayer)
      map.getLayerGroup().getLayers().on('add', onLayerAdd)

      map.addOverlay(this.overlay_)

      this.$element_.parent().addClass(this.className_ + '-container')

      // disable scrolling of body and zooming into map while in the feature popup
      this.window_.get$Element().on('mousewheel wheel DOMMouseScroll', function (e) {
        e.stopPropagation()
        e.preventDefault()
      })

      onMapChangeMobile()
      map.on('change:mobile', onMapChangeMobile)

      // limiting size

      map.once('postrender', () => {
        this.window_.updateSize()
      })
    }

    this.map__ = map
  }

  /**
   * @param {ol.Feature} feature
   * @private
   */
  onFeatureClick_ (feature) {
    this.referencingVisibleLayers_ = []

    this.getMap().getLayerGroup().recursiveForEach(layer => {
      if (layer.getVisible() && layer.getSource && layer.getSource().getFeatures) {
        if (layer.getSource().getFeatures().indexOf(feature) > -1) {
          this.referencingVisibleLayers_.push(layer)
        }
      }
    })

    this.setFeature(feature)
    this.setVisible(true)

    if (this.centerOnPopup_) {
      this.centerMapOnPopup()
    }
  }

  /**
   * @param {VectorLayer} layer
   * @private
   */
  removeReferencingLayer_ (layer) {
    this.referencingVisibleLayers_.splice(this.referencingVisibleLayers_.indexOf(layer), 1)
    if (this.referencingVisibleLayers_.length === 0) {
      this.setVisible(false)
    }
  }

  /**
   * @returns {G4UMap}
   */
  getMap () {
    return this.map__
  }

  /**
   * @returns {null|ol.Feature}
   */
  getFeature () {
    return this.feature_
  }

  /**
   * register a text mutator with a name. Which mutator is finally used can be adjusted via the config files.
   * @param {string} name
   * @param {Mutator} mutator
   */
  registerMutator (name, mutator) {
    this.mutators_.set(name, mutator)
  }

  /**
   * Update the Popup. Call this if something in the feature has changed
   */
  update () {
    if (this.getFeature()) {
      const feature = this.getFeature()

      const updateContent = () => {
        let name = feature.get('name')
        let description = feature.get('description')

        if (name) {
          this.$name_.html(name)
        }

        if (description) {
          for (let m of this.useMutators_) {
            let mutator = this.mutators_.get(m)
            if (mutator) {
              description = mutator(description)
            } else {
              Debug.error(`Trying to use unregistered mutator ${m}`)
            }
          }
          this.$description_.html(description)
        }

        if (this.getVisible() && this.window_ && this.window_.updateSize) {
          this.window_.updateSize()
        }
      }

      this.$name_.empty()
      this.$description_.empty()

      updateContent() // this produces one unnecessary call to window.updateSize()

      if (!feature.get('observedByPopup')) {
        feature.on('change:name', updateContent)
        feature.on('change:description', updateContent)
        feature.set('observedByPopup', true)
      }

      this.once('change:feature', () => {
        feature.un('change:name', updateContent)
        feature.un('change:description', updateContent)
        feature.set('observedByPopup', false)
      })

      if (!this.getMap().get('mobile')) {
        let resolution = this.getMap().getView().getResolution()

        this.addIconSizedOffset(this.getFeature(), resolution)
      }

      // apply default offset

      if (this.getVisible()) {
        this.window_.updateSize()
      }
    }
  }

  /**
   * The feature should have a property 'name' and/or 'description' to be shown inside of the popup.
   * @param {ol.Feature} feature
   */
  setFeature (feature) {
    let oldValue = this.feature_
    if (oldValue !== feature) {
      let geometry = feature.getGeometry()
      let coord = ol.extent.getCenter(geometry.getExtent())

      this.overlay_.setPosition(coord)

      if (this.feature_) {
        this.feature_.un('change:geometry', this.geometryChangeHandler_)
      }
      this.feature_ = feature
      this.useMutators_ = [ ...this.defaultMutators_ ]
      for (let layer of this.referencingVisibleLayers_) {
        this.useMutators_ = Array.prototype.concat.apply(this.useMutators_, layer.get('mutators'))
      }
      this.geometryChangeHandler_ = () => {
        this.overlay_.setPosition(ol.extent.getCenter(this.feature_.getGeometry().getExtent()))
        if (this.getVisible()) {
          this.update()
        }
      }
      this.feature_.on('change:geometry', this.geometryChangeHandler_)
      this.dispatchEvent({
        type: 'change:feature',
        oldValue: oldValue,
        key: 'feature'
      })

      this.update()
    }
  }

  /**
   * @returns {boolean}
   */
  getVisible () {
    return this.visible_
  }

  /**
   * @param {boolean} visible
   */
  setVisible (visible) {
    let oldValue = this.visible_
    if (oldValue !== visible) {
      if (visible === true && this.getFeature()) {
        this.$element_.removeClass(cssClasses.hidden)

        this.window_.setVisible(true)
      } else {
        this.$element_.addClass(cssClasses.hidden)
      }

      this.visible_ = visible

      this.dispatchEvent({
        type: 'change:visible',
        oldValue: oldValue,
        key: 'visible'
      })
    }
  }

  /**
   * calculates iconSized Offset and applies it
   * @param {ol.Feature} feature
   * @param {number} resolution
   */

  addIconSizedOffset (feature, resolution) {
    if (this.iconSizedOffset_[ 0 ] !== 0 || this.iconSizedOffset_[ 1 ] !== 0) {
      let featureStyleFunction = feature.getStyleFunction()
      if (featureStyleFunction) {
        let style = featureStyleFunction.call(feature, resolution)[ 0 ]
        if (style) {
          let imageStyle = style.getImage()
          if (imageStyle instanceof ol.style.Icon) {
            (new Promise(resolve => {
              let img = imageStyle.getImage()
              if (img.complete && img.src) {
                resolve()
              } else {
                let $img = $(img)
                $img.load(() => {
                  this.getMap().render() // initiate styles with size and anchor
                  this.getMap().once('postcompose', resolve)
                })
                imageStyle.load()
              }
            })).then(() => {
              let iconSize = imageStyle.getSize()

              let totalOffset = [
                this.pixelOffset_[ 0 ] + this.iconSizedOffset_[ 0 ] * iconSize[ 0 ] * imageStyle.getScale(),
                this.pixelOffset_[ 1 ] + this.iconSizedOffset_[ 1 ] * iconSize[ 1 ] * imageStyle.getScale()
              ]

              this.overlay_.setOffset(totalOffset)
            })
          }
        }
      }
    }
  }

  /**
   * Centers the map on the popup after all images have been loaded
   */
  centerMapOnPopup () {
    const _centerMap = () => {
      this.window_.updateSize()
      this.getMap().get('move').toPoint(this.getCenter(), { animated: this.animated_ })
    }

    finishAllImages(this.window_.get$Body()).then(() => {
      // we need to do this trick to find out if map is already visible/started rendering
      if (this.getMap().getPixelFromCoordinate([ 0, 0 ])) {
        _centerMap()
      } else {
        this.getMap().once('postrender', _centerMap)
      }
    })
  }

  /**
   * calculates Center of the Popup. Be careful, this calculation repositions the popup to calculate the center
   * properly and repostions to the initial Position again.
   * This does only work if the popup is already visible!
   * @returns {ol.Coordinate}
   */
  getCenter () {
    let offset = this.overlay_.getOffset()

    let pixelPosition = this.getMap().getPixelFromCoordinate(this.overlay_.getPosition())

    // apply offset
    pixelPosition[ 0 ] += offset[ 0 ]
    pixelPosition[ 1 ] += offset[ 1 ]

    // applay width/height depending on positioning
    let positioning = this.overlay_.getPositioning().split('-')

    let width = this.$element_.outerWidth()
    let height = this.$element_.outerHeight()

    if (positioning[ 1 ] === 'left') {
      pixelPosition[ 0 ] += width / 2
    }
    if (positioning[ 1 ] === 'right') {
      pixelPosition[ 0 ] -= width / 2
    }

    if (positioning[ 0 ] === 'top') {
      pixelPosition[ 1 ] += height / 2
    }
    if (positioning[ 0 ] === 'bottom') {
      pixelPosition[ 1 ] -= height / 2
    }

    return this.getMap().getCoordinateFromPixel(pixelPosition)
  }
}
<commit_msg>Fixed window positioning problem<commit_after>import ol from 'openlayers'
import $ from 'jquery'

import {Window} from './html/Window'
import {cssClasses} from './globals'
import {finishAllImages} from './utilities'
import {Debug} from './Debug'

import '../less/featurepopup.less'

/**
 * @typedef {object} FeaturePopupOptions
 * @property {string} [className='g4u-featurepopup']
 * @property {number[]} [offset=[0,0]]
 * @property {ol.OverlayPositioning} [positioning='center-center']
 * @property {number[]} [iconSizedOffset=[0,0]]
 * @property {boolean} [centerOnPopup=false]
 * @property {boolean} [animated]
 */

/**
 * @typedef {function} Mutator
 * @param {string} text
 * @returns {string}
 */

/**
 * Displays a Popup bound to a geographical position via an ol.Overlay
 */
export class FeaturePopup extends ol.Object {
  /**
   * @param {FeaturePopupOptions} options
   */
  constructor (options = {}) {
    super()

    /**
     * @type {string}
     * @private
     */
    this.className_ = (options.hasOwnProperty('className')) ? options.className : 'g4u-featurepopup'

    /**
     * @type {string}
     * @private
     */
    this.classNameFeatureName_ = this.className_ + '-feature-name'

    /**
     * @type {string}
     * @private
     */
    this.classNameFeatureDescription_ = this.className_ + '-feature-description'

    /**
     * @type {jQuery}
     * @private
     */
    this.$name_ = $('<h3>').addClass(this.classNameFeatureName_)

    /**
     * @type {jQuery}
     * @private
     */
    this.$description_ = $('<p>').addClass(this.classNameFeatureDescription_)

    /**
     * @type {null|ol.Feature}
     * @private
     */
    this.feature_ = null

    /**
     * @type {boolean}
     * @private
     */
    this.visible_ = false

    /**
     * @type {VectorLayer[]}
     * @private
     */
    this.referencingVisibleLayers_ = []

    /**
     * @type {number[]}
     * @private
     */
    this.pixelOffset_ = (options.hasOwnProperty('offset')) ? options.offset : [ 0, 0 ]

    /**
     * @type {number[]}
     * @private
     */
    this.iconSizedOffset_ = (options.hasOwnProperty('iconSizedOffset')) ? options.iconSizedOffset : [ 0, 0 ]

    /**
     * @type {boolean}
     * @private
     */
    this.centerOnPopup_ = (options.hasOwnProperty('centerOnPopup')) ? options.centerOnPopup : true

    /**
     * @type {boolean}
     * @private
     */
    this.centerOnPopupInitial_ = this.centerOnPopup_

    /**
     * @type {boolean}
     * @private
     */
    this.animated_ = (options.hasOwnProperty('animated')) ? options.animated : false

    /**
     * @type {jQuery}
     * @private
     */
    this.$element_ = $('<div>').addClass(this.className_).addClass(cssClasses.hidden)

    /**
     * @type {ol.Overlay}
     * @private
     */
    this.overlay_ = new ol.Overlay({
      element: this.$element_.get(0),
      offset: this.pixelOffset_,
      positioning: (options.hasOwnProperty('positioning')) ? options.positioning : 'center-center',
      stopEvent: false
    })

    this.overlay_.setOffset(this.pixelOffset_)

    /**
     * @type {Map.<string,function>}
     * @private
     */
    this.mutators_ = new Map()

    /**
     * @type {string[]}
     * @private
     */
    this.defaultMutators_ = options.mutators || []

    /**
     * @type {string[]}
     * @private
     */
    this.useMutators_ = []

    /**
     * @type {?Window}
     * @private
     */
    this.window_ = null

    /**
     * @type {?G4UMap}
     * @private
     */
    this.map__ = null
  }

  /**
   * @param {ol.Feature} feature
   * @returns {boolean}
   * @private
   */
  static filter_ (feature) {
    return !feature.get('disabled') && (feature.get('name') || feature.get('description'))
  }

  /**
   * @param {G4UMap} map
   */
  setMap (map) {
    let popup = this

    let sourceOnFeatureRemove = function (e) {
      if (e.feature === popup.getFeature()) {
        let source = this
        popup.referencingVisibleLayers_.forEach(function (layer) {
          if (layer.getSource() === source) {
            popup.removeReferencingLayer_(layer)
          }
        })
      }
    }

    let layerOnChangeVisible = function () {
      if (this.getVisible() === false) {
        if (this.getSource().getFeatures().indexOf(popup.getFeature()) > -1) {
          popup.removeReferencingLayer_(this)
        }
      } else {
        if (this.getSource().getFeatures().indexOf(popup.getFeature()) > -1) {
          popup.referencingVisibleLayers_.push(this)
        }
      }
    }

    let onForEachLayer = (layer) => {
      if (layer.getSource && layer.getSource().getFeatures) {
        layer.getSource().on('removefeature', sourceOnFeatureRemove)
        layer.on('change:visible', layerOnChangeVisible)
      }
    }

    let unForEachLayer = (layer) => {
      if (layer.getSource && layer.getSource().getFeatures) {
        layer.getSource().un('removefeature', sourceOnFeatureRemove)
        layer.un('change:visible', layerOnChangeVisible)
      }
    }

    let onLayerAdd = (e) => {
      onForEachLayer(e.element)
    }

    let onMapChangeMobile = () => {
      if (map.get('mobile')) {
        this.centerOnPopup_ = false
      } else {
        this.centerOnPopup_ = this.centerOnPopupInitial_
      }
    }

    if (this.getMap()) {
      this.getMap().removeInteraction(this.featureClick_)
      this.getMap().getLayerGroup().recursiveForEach(unForEachLayer)
      this.getMap().getLayerGroup().un('add', onLayerAdd)
      this.getMap().removeInteraction(this.featureHover_)
      this.getMap().removeOverlay(this.overlay_)
      this.getMap().un('change:mobile', onMapChangeMobile)
    }

    if (map) {
      this.window_ = new Window({ draggable: false, fixedPosition: true, map: map })

      this.window_.get$Body().append(this.$name_).append(this.$description_)

      this.window_.on('change:visible', () => {
        if (!this.window_.getVisible()) {
          this.setVisible(false) // notifying the featurepopup about the closing of the window
        }
      })

      this.$element_.append(this.window_.get$Element())

      // feature click

      map.getDefaultInteractions('singleClick')[ 0 ].on('select', e => {
        let selected = e.selected.filter(FeaturePopup.filter_)
        if (selected.length) {
          this.onFeatureClick_(selected[ 0 ])
          e.target.getFeatures().remove(selected[ 0 ]) // remove feature to be able to select feature again
          e.target.changed()
        }
      })

      // feature hover

      map.getDefaultInteractions('mouseMove')[ 0 ].on('select', e => {
        let selected = e.selected.filter(FeaturePopup.filter_)
        let deselected = e.deselected.filter(FeaturePopup.filter_)
        if (selected.length) {
          $(map.getViewport()).addClass(cssClasses.clickable)
        } else if (deselected.length) {
          $(map.getViewport()).removeClass(cssClasses.clickable)
        }
      })

      // hiding feature Popup if the layer gets hidden or the feature gets removed

      map.getLayerGroup().recursiveForEach(onForEachLayer)
      map.getLayerGroup().getLayers().on('add', onLayerAdd)

      map.addOverlay(this.overlay_)

      this.$element_.parent().addClass(this.className_ + '-container')

      // disable scrolling of body and zooming into map while in the feature popup
      this.window_.get$Element().on('mousewheel wheel DOMMouseScroll', function (e) {
        e.stopPropagation()
        e.preventDefault()
      })

      onMapChangeMobile()
      map.on('change:mobile', onMapChangeMobile)

      // limiting size

      map.once('postrender', () => {
        this.window_.updateSize()
      })
    }

    this.map__ = map
  }

  /**
   * @param {ol.Feature} feature
   * @private
   */
  onFeatureClick_ (feature) {
    this.referencingVisibleLayers_ = []

    this.getMap().getLayerGroup().recursiveForEach(layer => {
      if (layer.getVisible() && layer.getSource && layer.getSource().getFeatures) {
        if (layer.getSource().getFeatures().indexOf(feature) > -1) {
          this.referencingVisibleLayers_.push(layer)
        }
      }
    })

    this.setFeature(feature)
    this.setVisible(true)

    if (this.centerOnPopup_) {
      this.centerMapOnPopup()
    }
  }

  /**
   * @param {VectorLayer} layer
   * @private
   */
  removeReferencingLayer_ (layer) {
    this.referencingVisibleLayers_.splice(this.referencingVisibleLayers_.indexOf(layer), 1)
    if (this.referencingVisibleLayers_.length === 0) {
      this.setVisible(false)
    }
  }

  /**
   * @returns {G4UMap}
   */
  getMap () {
    return this.map__
  }

  /**
   * @returns {null|ol.Feature}
   */
  getFeature () {
    return this.feature_
  }

  /**
   * register a text mutator with a name. Which mutator is finally used can be adjusted via the config files.
   * @param {string} name
   * @param {Mutator} mutator
   */
  registerMutator (name, mutator) {
    this.mutators_.set(name, mutator)
  }

  /**
   * Update the Popup. Call this if something in the feature has changed
   */
  update () {
    if (this.getFeature()) {
      const feature = this.getFeature()

      const updateContent = () => {
        let name = feature.get('name')
        let description = feature.get('description')

        if (name) {
          this.$name_.html(name)
        }

        if (description) {
          for (let m of this.useMutators_) {
            let mutator = this.mutators_.get(m)
            if (mutator) {
              description = mutator(description)
            } else {
              Debug.error(`Trying to use unregistered mutator ${m}`)
            }
          }
          this.$description_.html(description)
        }

        if (this.getVisible() && this.window_ && this.window_.updateSize) {
          this.window_.updateSize()
        }
      }

      this.$name_.empty()
      this.$description_.empty()

      updateContent() // this produces one unnecessary call to window.updateSize()

      if (!feature.get('observedByPopup')) {
        feature.on('change:name', updateContent)
        feature.on('change:description', updateContent)
        feature.set('observedByPopup', true)
      }

      this.once('change:feature', () => {
        feature.un('change:name', updateContent)
        feature.un('change:description', updateContent)
        feature.set('observedByPopup', false)
      })

      if (!this.getMap().get('mobile')) {
        let resolution = this.getMap().getView().getResolution()

        this.addIconSizedOffset(this.getFeature(), resolution)
      }

      // apply default offset

      if (this.getVisible()) {
        setTimeout(() => this.window_.updateSize(), 0)
      }
    }
  }

  /**
   * The feature should have a property 'name' and/or 'description' to be shown inside of the popup.
   * @param {ol.Feature} feature
   */
  setFeature (feature) {
    let oldValue = this.feature_
    if (oldValue !== feature) {
      let geometry = feature.getGeometry()
      let coord = ol.extent.getCenter(geometry.getExtent())

      this.overlay_.setPosition(coord)

      if (this.feature_) {
        this.feature_.un('change:geometry', this.geometryChangeHandler_)
      }
      this.feature_ = feature
      this.useMutators_ = [ ...this.defaultMutators_ ]
      for (let layer of this.referencingVisibleLayers_) {
        this.useMutators_ = Array.prototype.concat.apply(this.useMutators_, layer.get('mutators'))
      }
      this.geometryChangeHandler_ = () => {
        this.overlay_.setPosition(ol.extent.getCenter(this.feature_.getGeometry().getExtent()))
        if (this.getVisible()) {
          this.update()
        }
      }
      this.feature_.on('change:geometry', this.geometryChangeHandler_)
      this.dispatchEvent({
        type: 'change:feature',
        oldValue: oldValue,
        key: 'feature'
      })

      this.update()
    }
  }

  /**
   * @returns {boolean}
   */
  getVisible () {
    return this.visible_
  }

  /**
   * @param {boolean} visible
   */
  setVisible (visible) {
    let oldValue = this.visible_
    if (oldValue !== visible) {
      if (visible === true && this.getFeature()) {
        this.$element_.removeClass(cssClasses.hidden)

        this.window_.setVisible(true)
      } else {
        this.$element_.addClass(cssClasses.hidden)
      }

      this.visible_ = visible

      this.dispatchEvent({
        type: 'change:visible',
        oldValue: oldValue,
        key: 'visible'
      })
    }

    if (visible) {
      setTimeout(() => this.window_.updateSize(), 0)
    }
  }

  /**
   * calculates iconSized Offset and applies it
   * @param {ol.Feature} feature
   * @param {number} resolution
   */

  addIconSizedOffset (feature, resolution) {
    if (this.iconSizedOffset_[ 0 ] !== 0 || this.iconSizedOffset_[ 1 ] !== 0) {
      let featureStyleFunction = feature.getStyleFunction()
      if (featureStyleFunction) {
        let style = featureStyleFunction.call(feature, resolution)[ 0 ]
        if (style) {
          let imageStyle = style.getImage()
          if (imageStyle instanceof ol.style.Icon) {
            (new Promise(resolve => {
              let img = imageStyle.getImage()
              if (img.complete && img.src) {
                resolve()
              } else {
                img.addEventListener('load', () => {
                  this.getMap().render() // initiate styles with size and anchor
                  this.getMap().once('postcompose', resolve)
                })
                imageStyle.load()
              }
            })).then(() => {
              let iconSize = imageStyle.getSize()

              let totalOffset = [
                this.pixelOffset_[ 0 ] + this.iconSizedOffset_[ 0 ] * iconSize[ 0 ] * imageStyle.getScale(),
                this.pixelOffset_[ 1 ] + this.iconSizedOffset_[ 1 ] * iconSize[ 1 ] * imageStyle.getScale()
              ]

              this.overlay_.setOffset(totalOffset)
            })
          }
        }
      }
    }
  }

  /**
   * Centers the map on the popup after all images have been loaded
   */
  centerMapOnPopup () {
    const _centerMap = () => {
      this.window_.updateSize()
      this.getMap().get('move').toPoint(this.getCenter(), { animated: this.animated_ })
    }

    finishAllImages(this.window_.get$Body()).then(() => {
      // we need to do this trick to find out if map is already visible/started rendering
      if (this.getMap().getPixelFromCoordinate([ 0, 0 ])) {
        _centerMap()
      } else {
        this.getMap().once('postrender', _centerMap)
      }
    })
  }

  /**
   * calculates Center of the Popup. Be careful, this calculation repositions the popup to calculate the center
   * properly and repostions to the initial Position again.
   * This does only work if the popup is already visible!
   * @returns {ol.Coordinate}
   */
  getCenter () {
    let offset = this.overlay_.getOffset()

    let pixelPosition = this.getMap().getPixelFromCoordinate(this.overlay_.getPosition())

    // apply offset
    pixelPosition[ 0 ] += offset[ 0 ]
    pixelPosition[ 1 ] += offset[ 1 ]

    // applay width/height depending on positioning
    let positioning = this.overlay_.getPositioning().split('-')

    let width = this.$element_.outerWidth()
    let height = this.$element_.outerHeight()

    if (positioning[ 1 ] === 'left') {
      pixelPosition[ 0 ] += width / 2
    }
    if (positioning[ 1 ] === 'right') {
      pixelPosition[ 0 ] -= width / 2
    }

    if (positioning[ 0 ] === 'top') {
      pixelPosition[ 1 ] += height / 2
    }
    if (positioning[ 0 ] === 'bottom') {
      pixelPosition[ 1 ] -= height / 2
    }

    return this.getMap().getCoordinateFromPixel(pixelPosition)
  }
}
<|endoftext|>


<commit_before>'use strict';

var config = require('./gulp/config'),
    fs = require('fs'),
    gulp = require('gulp');

/**
 * gets all tasks
 * @private
 */
var getAllTasks = function() {
    var path = config.gulpTaskPath;
    var files = fs.readdirSync(path);
    files.forEach(function(file, i) {
        require(path + '/' + file)();
    });
};

/**
 * get external defined tasks
 * @param {string} task Taskname
 * @param {string} [path] Optional path
 * @private
 */
var getTask = function(task, path) {
    if (typeof path === 'undefined') {
        path = config.gulpTaskPath;
    }
    require(path + '/' + task)();
};

// load tasks
getAllTasks();

gulp.add('config:watch', function() {
    gulp.watch(['gulp/config.json', 'package.json', 'gulpfile.js'], ['default', 'server:reload']);
});

// main tasks
gulp.task('docs', ['styles:docs', 'scripts:docs']);
gulp.task('vendor', ['vendor:build']);
gulp.task('fonts', ['assets:fonts']);
gulp.task('assets', ['assets:svg:icons', 'assets:images', 'assets:fonts']);
gulp.task('styles', ['styles:build']);
gulp.task('scripts', ['scripts:reset', 'scripts:build']);
gulp.task('styleguide', ['styleguide:build']);

gulp.task('watch', ['config:watch', 'styles:watch', 'scripts:watch', 'styleguide:watch', 'assets:images:watch', 'assets:svg:icons:watch']);
gulp.task('serve', ['default', 'server:start' , 'watch']);
gulp.task('server', ['default', 'server:start']);
gulp.task('all', ['vendor', 'styles', 'scripts', 'styleguide', 'assets', 'docs']);
gulp.task('prod', ['vendor', 'styles', 'scripts', 'assets']);
gulp.task('default', ['vendor', 'styles', 'scripts', 'styleguide', 'assets']);

gulp.task('test', ['test:galen']);
<commit_msg>Updated config:watch task<commit_after>'use strict';

var config = require('./gulp/config'),
    fs = require('fs'),
    gulp = require('gulp');

/**
 * gets all tasks
 * @private
 */
var getAllTasks = function() {
    var path = config.gulpTaskPath;
    var files = fs.readdirSync(path);
    files.forEach(function(file, i) {
        require(path + '/' + file)();
    });
};

/**
 * get external defined tasks
 * @param {string} task Taskname
 * @param {string} [path] Optional path
 * @private
 */
var getTask = function(task, path) {
    if (typeof path === 'undefined') {
        path = config.gulpTaskPath;
    }
    require(path + '/' + task)();
};

// load tasks
getAllTasks();

gulp.add('config:watch', function() {
    gulp.watch(['./gulp/config.js', './package.json', './gulpfile.js'], ['default', 'server:reload']);
});

// main tasks
gulp.task('docs', ['styles:docs', 'scripts:docs']);
gulp.task('vendor', ['vendor:build']);
gulp.task('fonts', ['assets:fonts']);
gulp.task('assets', ['assets:svg:icons', 'assets:images', 'assets:fonts']);
gulp.task('styles', ['styles:build']);
gulp.task('scripts', ['scripts:reset', 'scripts:build']);
gulp.task('styleguide', ['styleguide:build']);

gulp.task('watch', ['config:watch', 'styles:watch', 'scripts:watch', 'styleguide:watch', 'assets:images:watch', 'assets:svg:icons:watch']);
gulp.task('serve', ['default', 'server:start' , 'watch']);
gulp.task('server', ['default', 'server:start']);
gulp.task('all', ['vendor', 'styles', 'scripts', 'styleguide', 'assets', 'docs']);
gulp.task('prod', ['vendor', 'styles', 'scripts', 'assets']);
gulp.task('default', ['vendor', 'styles', 'scripts', 'styleguide', 'assets']);

gulp.task('test', ['test:galen']);
<|endoftext|>


<commit_before>'use strict';

var Transformer = require('../index.js');
var Middleware = require('../index.js').middleware;
var transformer;
var Promise = require('bluebird');
var logger;
var assert = require('assert');
var AssertionError = assert.AssertionError;
var objectPath = require('object-path');

describe('Executing \'jy-transform\' project middleware test suite.', function () {

    var middleware = function (json) {

        function key1(json) {
            objectPath.set(json, 'key1', 'value1');
            logger.info('key1 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        function key2(json) {
            objectPath.set(json, 'key2', 'value2');
            logger.info('key2 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        function key3(json) {
            objectPath.set(json, 'key3', 'value3');
            logger.info('key3 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        return Promise.all([key1(json), key2(json), key3(json)])
            .then(function(result) {
                assert.equal(result.length, 3);
                logger.info('all the elements were created');
                logger.info('result: ' + JSON.stringify(result[result.length - 1]));
                return Promise.resolve(result[result.length - 1]);
            });
    };

    var options = {
        src: {},
        //origin: 'js',
        //target: 'js',
        dest: {}
    };

    /**
     * Init the test logger.
     */
    before(function () {
        logger = require('./logger.js');
        transformer = new Transformer(logger);
    });

    describe('Testing Transformer middleware', function () {

        it('should alter json', function (done) {
            transformer.transform(options, middleware)
                .then(function (msg){
                    logger.info(msg);
                    logger.info('options.dest: ' + JSON.stringify(options.dest, null, 4));
                    assert.equal(options.dest['key1'], 'value1', 'options.dest.key1 should have value: value1, but was ' + options.dest['key1']);
                    assert.equal(options.dest['key2'], 'value2', 'options.dest.key1 should have value: value2, but was ' + options.dest['key2']);
                    assert.equal(options.dest['key3'], 'value3', 'options.dest.key1 should have value: value3, but was ' + options.dest['key3']);
                    done();
                })
                .catch(function (err) {
                    logger.error(err.stack);
                    done(err);
                });
        });

    });

    describe('Testing middleware.ensureMiddleware()', function () {

        var myMiddleware = function (json) {
            return Promise.resolve(json);
        };

        it('should provide passed function', function (done) {
            var func = Middleware.ensureMiddleware(myMiddleware);
            assert(typeof func === 'function');
            assert.deepStrictEqual(func, myMiddleware, 'should return same function');
            done();
        });

        it('should reject Promise if middleware passed is not a function type', function (done) {
            Middleware.ensureMiddleware({})
                .then(function (middleware){
                    done(new AssertionError({
                        message: 'rejecting with TypeError',
                        actual: middleware,
                        expected: TypeError,
                        operator: 'instanceof'
                    }));
                })
                .catch(function (err) {
                    assert.notEqual(err, null, 'Promise rejection err should not be null');
                    assert(err instanceof TypeError);
                    done();
                });
        });

        it('should provide identity Promise if middleware passed is null', function (done) {
            var func = Middleware.ensureMiddleware();
            assert(typeof func === 'function');
            done();
        });

        it('should provide identity Promise if middleware passed is undefined', function (done) {
            var func = Middleware.ensureMiddleware(undefined);
            assert(typeof func === 'function');
            done();
        });

    });
});
<commit_msg>Fix middleware test for node <= 0.12<commit_after>'use strict';

var Transformer = require('../index.js');
var Middleware = require('../index.js').middleware;
var transformer;
var Promise = require('bluebird');
var logger;
var assert = require('assert');
var AssertionError = assert.AssertionError;
var objectPath = require('object-path');

describe('Executing \'jy-transform\' project middleware test suite.', function () {

    var middleware = function (json) {

        function key1(json) {
            objectPath.set(json, 'key1', 'value1');
            logger.info('key1 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        function key2(json) {
            objectPath.set(json, 'key2', 'value2');
            logger.info('key2 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        function key3(json) {
            objectPath.set(json, 'key3', 'value3');
            logger.info('key3 json: ' + JSON.stringify(json));
            return Promise.resolve(json);
        }

        return Promise.all([key1(json), key2(json), key3(json)])
            .then(function(result) {
                assert.equal(result.length, 3);
                logger.info('all the elements were created');
                logger.info('result: ' + JSON.stringify(result[result.length - 1]));
                return Promise.resolve(result[result.length - 1]);
            });
    };

    var options = {
        src: {},
        //origin: 'js',
        //target: 'js',
        dest: {}
    };

    /**
     * Init the test logger.
     */
    before(function () {
        logger = require('./logger.js');
        transformer = new Transformer(logger);
    });

    describe('Testing Transformer middleware', function () {

        it('should alter json', function (done) {
            transformer.transform(options, middleware)
                .then(function (msg){
                    logger.info(msg);
                    logger.info('options.dest: ' + JSON.stringify(options.dest, null, 4));
                    assert.equal(options.dest['key1'], 'value1', 'options.dest.key1 should have value: value1, but was ' + options.dest['key1']);
                    assert.equal(options.dest['key2'], 'value2', 'options.dest.key1 should have value: value2, but was ' + options.dest['key2']);
                    assert.equal(options.dest['key3'], 'value3', 'options.dest.key1 should have value: value3, but was ' + options.dest['key3']);
                    done();
                })
                .catch(function (err) {
                    logger.error(err.stack);
                    done(err);
                });
        });

    });

    describe('Testing middleware.ensureMiddleware()', function () {

        var myMiddleware = function (json) {
            return Promise.resolve(json);
        };

        it('should provide passed function', function (done) {
            var func = Middleware.ensureMiddleware(myMiddleware);
            assert(typeof func === 'function');
            assert(func === myMiddleware, 'should return same function');
            done();
        });

        it('should reject Promise if middleware passed is not a function type', function (done) {
            Middleware.ensureMiddleware({})
                .catch(function (err) {
                    assert.notEqual(err, null, 'Promise rejection err should not be null');
                    assert(err instanceof TypeError);
                    done();
                });
        });

        it('should provide identity Promise if middleware passed is null', function (done) {
            var func = Middleware.ensureMiddleware();
            assert(typeof func === 'function');
            done();
        });

        it('should provide identity Promise if middleware passed is undefined', function (done) {
            var func = Middleware.ensureMiddleware(undefined);
            assert(typeof func === 'function');
            done();
        });

    });
});
<|endoftext|>


<commit_before>const gulp = require('gulp');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');
const plumber = require('gulp-plumber');
const manifest = require('./public/config/webpack.manifest.json');
const writefile = require('./bolg/helpers').writefile;
const browserSync = require('browser-sync');

function sync(done) {
  return browserSync.init({
    proxy: 'localhost:3000',
    open: true,
    logFileChanges: false,
  }, done);
}

function compileSass() {
  return gulp.src('src/styles/post-index.scss')
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass({
      includePaths: ['node_modules'],
    }))
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
    }))
    .pipe(sourcemaps.write('/', {
      sourceMappingURLPrefix: '/css',
    }))
    .pipe(gulp.dest('public/css'))
    .pipe(browserSync.stream({ match: '**/*.css' }))
    .on('end', () => {
      manifest['/bolg.css'] = '/css/post-index.css';
      writefile('bolg/config/webpack.manifest.json', JSON.stringify(manifest));
    });
}

const watch = (done) => {
  gulp.watch('src/styles/**/*.scss', compileSass);
  sync(done);
};

gulp.task('default', watch);
gulp.task('sass', compileSass);
gulp.task('watch', watch);
gulp.task('server', sync);
<commit_msg>Don't cache the manifest<commit_after>const gulp = require('gulp');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');
const plumber = require('gulp-plumber');
const writefile = require('./bolg/helpers').writefile;
const browserSync = require('browser-sync');
const fs = require('fs');

function sync(done) {
  return browserSync.init({
    proxy: 'localhost:3000',
    open: true,
    logFileChanges: false,
  }, done);
}

function compileSass() {
  return gulp.src('src/styles/post-index.scss')
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass({
      includePaths: ['node_modules'],
    }))
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
    }))
    .pipe(sourcemaps.write('/', {
      sourceMappingURLPrefix: '/css',
    }))
    .pipe(gulp.dest('public/css'))
    .pipe(browserSync.stream({ match: '**/*.css' }))
    .on('end', () => {
      const manifest = JSON.parse(fs.readFileSync('./public/config/webpack.manifest.json', 'utf-8'));
      manifest['/bolg.css'] = '/css/post-index.css';
      writefile('public/config/webpack.manifest.json', JSON.stringify(manifest));
    });
}

const watch = (done) => {
  gulp.watch('src/styles/**/*.scss', compileSass);
  sync(done);
};

gulp.task('default', watch);
gulp.task('sass', compileSass);
gulp.task('watch', watch);
gulp.task('server', sync);
<|endoftext|>


<commit_before>import assert from 'assert';

import {
  validateRange,
  validateWidths,
  validateWidthTolerance,
  validateVariableQuality
} from '../src/validators';

describe('Validators:', function () {
  describe('Testing validateWidths', function () {
    it('throws an error if any width is negative', () => {
      assert.throws(() => {
        validateWidths([100, 200, 300, -400])
      })
    });

    it('throws an error if given an empty list', () => {
      assert.throws(() => {
        validateWidths([])
      })
    });

    it('throws an error if given a list of non-numeric input', () => {
      assert.throws(() => {
        validateWidths([100, 200, 300, '400', '500'])
      })
    });

    it('throws an error if given a list of non-integer input', () => {
      assert.throws(() => {
        validateWidths([399.99, 499.50])
      })
    });

    it('succeeds silently', () => {
      let result = validateWidths([100, 200, 300, 400, 500]);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateRange', function () {
    it('throws an error if minWidth is not an integer', () => {
      assert.throws(() => {
        validateRange(500.9123, 1000)
      })
    });

    it('throws an error if maxWidth is not an integer', () => {
      assert.throws(() => {
        validateRange(100, 500.9123)
      })
    });

    it('throws an error if minWidth is not <= 0', () => {
      assert.throws(() => {
        validateRange(-1, 100)
      })
    });

    it('throws an error if maxWidth is not <= 0', () => {
      assert.throws(() => {
        validateRange(100, -1)
      })
    });

    it('throws an error if maxWidth is not >= minWidth', () => {
      assert.throws(() => {
        validateRange(500, 100)
      })
    });

    it('succeeds silently', () => {
      let result = validateRange(100, 8192);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateWidthTolerance', function () {
    it('throws if typeof widthTolerance is not a number', () => {
      assert.throws(() => {
        validateWidthTolerance('0.08')
      })
    });

    it('throws if widthTolerance is <= 0', () => {
      assert.throws(() => {
        validateWidthTolerance(0)
      })
    });

    it('succeeds silently', () => {
      let result = validateWidthTolerance(0.08);
      assert.strictEqual(result, undefined);
    });

    // TODO: should fail.
    it('succeeds silently when widthTolerance === 0.001', () => {
      let result = validateWidthTolerance(0.001);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateVariableQuality', function () {
    it('throws an error if variable quality flag is not a boolean', () => {
      assert.throws(() => {
        validateVariableQuality('false')
      })

      assert.throws(() => {
        validateVariableQuality('true')
      })

      assert.throws(() => {
        validateVariableQuality(0)
      })

      assert.throws(() => {
        validateVariableQuality(1)
      })
    });
  });
});<commit_msg>test: don't use double negatives<commit_after>import assert from 'assert';

import {
  validateRange,
  validateWidths,
  validateWidthTolerance,
  validateVariableQuality
} from '../src/validators';

describe('Validators:', function () {
  describe('Testing validateWidths', function () {
    it('throws an error if any width is negative', () => {
      assert.throws(() => {
        validateWidths([100, 200, 300, -400])
      })
    });

    it('throws an error if given an empty list', () => {
      assert.throws(() => {
        validateWidths([])
      })
    });

    it('throws an error if given a list of non-numeric input', () => {
      assert.throws(() => {
        validateWidths([100, 200, 300, '400', '500'])
      })
    });

    it('throws an error if given a list of non-integer input', () => {
      assert.throws(() => {
        validateWidths([399.99, 499.50])
      })
    });

    it('succeeds silently', () => {
      let result = validateWidths([100, 200, 300, 400, 500]);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateRange', function () {
    it('throws an error if minWidth is not an integer', () => {
      assert.throws(() => {
        validateRange(500.9123, 1000)
      })
    });

    it('throws an error if maxWidth is not an integer', () => {
      assert.throws(() => {
        validateRange(100, 500.9123)
      })
    });

    it('throws an error if minWidth is less than 0', () => {
      assert.throws(() => {
        validateRange(-1, 100)
      })
    });

    it('throws an error if maxWidth is less than 0', () => {
      assert.throws(() => {
        validateRange(100, -1)
      })
    });

    it('throws an error if maxWidth is less than minWidth', () => {
      assert.throws(() => {
        validateRange(500, 100)
      })
    });

    it('succeeds silently', () => {
      let result = validateRange(100, 8192);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateWidthTolerance', function () {
    it('throws if typeof widthTolerance is not a number', () => {
      assert.throws(() => {
        validateWidthTolerance('0.08')
      })
    });

    it('throws if widthTolerance is <= 0', () => {
      assert.throws(() => {
        validateWidthTolerance(0)
      })
    });

    it('succeeds silently', () => {
      let result = validateWidthTolerance(0.08);
      assert.strictEqual(result, undefined);
    });

    // TODO: should fail.
    it('succeeds silently when widthTolerance === 0.001', () => {
      let result = validateWidthTolerance(0.001);
      assert.strictEqual(result, undefined);
    });
  });

  describe('Testing validateVariableQuality', function () {
    it('throws an error if variable quality flag is not a boolean', () => {
      assert.throws(() => {
        validateVariableQuality('false')
      })

      assert.throws(() => {
        validateVariableQuality('true')
      })

      assert.throws(() => {
        validateVariableQuality(0)
      })

      assert.throws(() => {
        validateVariableQuality(1)
      })
    });
  });
});<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var sync = require('browser-sync');
var concat = require('gulp-concat');
var clean = require('gulp-clean');
var gulp  = require('gulp');
var shell = require('gulp-shell');
//var connect = require('gulp-connect');

gulp.task('sass_compile_org', function () {
    return gulp.src('www/assets/sass/components/organization/organization.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_user', function () {
    return gulp.src('www/assets/sass/components/user/user.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_global', function () {
    return gulp.src('www/assets/sass/global/global.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_presentation', function(){
    return gulp.src('www/assets/sass/components/presentation/*.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile', ['sass_compile_global','sass_compile_user', 'sass_compile_org','sass_compile_presentation']);
gulp.task('copy_node_modules', function(){
    return gulp.src('node_modules/**')
        .pipe(gulp.dest('www/node_modules/'));
});

gulp.task('broswer-sync', function () {
    sync.init(["www/assets/css/generated/*.css",
        "www/app/*/*/*/*.html",
        "www/*.html",
        "www/app/*/*/*.html",
        "www/app/dist/*.js"], {
        server: {
            baseDir: "./www"
        }
    });
});
gulp.task('watch', function () {
    gulp.watch('www/assets/sass/**/*.sass', ['sass_compile']);
    gulp.watch('www/app/*/*/*/*.js', ['concat']);
    gulp.watch('www/app/configuration/*.js', ['concat']);
    gulp.watch('www/app/*/*/*.js',['concat']);
});
gulp.task('concat_presentation', function(){
    return gulp.src('www/app/components/presentation/*.js')
        .pipe(concat('controllers_presentation.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_controllers_user', function () {
    return gulp.src('www/app/components/user/*/*.js')
        .pipe(concat('controllers_user.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_controllers_organization', function () {
    return gulp.src('www/app/components/organization/*/*.js')
        .pipe(concat('controllers_org.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_services_directives', function () {
    return gulp.src('www/app/shared/*/*.js')
        .pipe(concat('services_directives.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_configuration', function () {
    return gulp.src('www/app/configuration/*.js')
        .pipe(concat('angular_app_config.js'))
        .pipe(gulp.dest('www/app/dist'));
});

gulp.task('gz-remove', ['production'],  function (){
    return gulp.src('www/node_modules/**/*.gz')
        .pipe(clean());
});

gulp.task('key-remove', ['production'],  function (){
    return gulp.src('www/node_modules/**/*.key')
        .pipe(clean());
});

gulp.task('concat', ['concat_configuration', 'concat_services_directives', 'concat_controllers_organization', 'concat_controllers_user', 'concat_presentation']);

//gulp.task('production', ['sass_compile','concat', 'copy_node_modules']);
gulp.task('production', ['cordova-prepare', 'sass_compile','concat', 'npm-release']);

gulp.task('android-prepare', ['production', 'gz-remove', 'key-remove']);

gulp.task('browser-run', ['production'], shell.task([
    'cordova run browser'
]));

gulp.task('run', shell.task([
    'cordova run android'
]));

gulp.task('release', shell.task([
    'cordova build android --release'
]));

gulp.task('cordova-prepare', shell.task([
    'cordova prepare'
]));

gulp.task('npm-release', shell.task([
    'rm -Rf www/node_modules',
    'mkdir www/node_modules',
    'cp package.json www',
    'npm install --production --prefix www/'
]));

gulp.task('android-execute', ['android-prepare', 'run']);

gulp.task('browser-execute', ['production', 'browser-run']);

gulp.task('dev', ['watch', 'broswer-sync', 'sass_compile', 'concat']);

gulp.task('default', ['watch', 'broswer-sync', 'sass_compile'], function () {

});

gulp.task('clean', shell.task([
    'rm -Rf www/node_modules',
    'rm -Rf plugins',
    'rm -Rf platforms',
]));<commit_msg>gulp fixed<commit_after>var gulp = require('gulp');
var sass = require('gulp-sass');
var sync = require('browser-sync');
var concat = require('gulp-concat');
var clean = require('gulp-clean');
var gulp  = require('gulp');
var shell = require('gulp-shell');
//var connect = require('gulp-connect');

gulp.task('sass_compile_org', function () {
    return gulp.src('www/assets/sass/components/organization/organization.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_user', function () {
    return gulp.src('www/assets/sass/components/user/user.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_global', function () {
    return gulp.src('www/assets/sass/global/global.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile_presentation', function(){
    return gulp.src('www/assets/sass/components/presentation/*.sass', {style: 'expanded'})
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('www/assets/css/generated'))
});
gulp.task('sass_compile', ['sass_compile_global','sass_compile_user', 'sass_compile_org','sass_compile_presentation']);
gulp.task('copy_node_modules', function(){
    return gulp.src('node_modules/**')
        .pipe(gulp.dest('www/node_modules/'));
});

gulp.task('broswer-sync', function () {
    sync.init(["www/assets/css/generated/*.css",
        "www/app/*/*/*/*.html",
        "www/*.html",
        "www/app/*/*/*.html",
        "www/app/dist/*.js"], {
        server: {
            baseDir: "./www"
        }
    });
});
gulp.task('watch', function () {
    gulp.watch('www/assets/sass/**/*.sass', ['sass_compile']);
    gulp.watch('www/app/*/*/*/*.js', ['concat']);
    gulp.watch('www/app/configuration/*.js', ['concat']);
    gulp.watch('www/app/*/*/*.js',['concat']);
});
gulp.task('concat_presentation', function(){
    return gulp.src('www/app/components/presentation/*.js')
        .pipe(concat('controllers_presentation.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_controllers_user', function () {
    return gulp.src('www/app/components/user/*/*.js')
        .pipe(concat('controllers_user.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_controllers_organization', function () {
    return gulp.src('www/app/components/organization/*/*.js')
        .pipe(concat('controllers_org.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_services_directives', function () {
    return gulp.src('www/app/shared/*/*.js')
        .pipe(concat('services_directives.js'))
        .pipe(gulp.dest('www/app/dist'));
});
gulp.task('concat_configuration', function () {
    return gulp.src('www/app/configuration/*.js')
        .pipe(concat('angular_app_config.js'))
        .pipe(gulp.dest('www/app/dist'));
});

gulp.task('gz-remove', ['production'],  function (){
    return gulp.src('www/node_modules/**/*.gz')
        .pipe(clean());
});

gulp.task('key-remove', ['production'],  function (){
    return gulp.src('www/node_modules/**/*.key')
        .pipe(clean());
});

gulp.task('concat', ['concat_configuration', 'concat_services_directives', 'concat_controllers_organization', 'concat_controllers_user', 'concat_presentation']);

//gulp.task('production', ['sass_compile','concat', 'copy_node_modules']);
gulp.task('production', ['cordova-prepare', 'sass_compile','concat', 'npm-release']);

//gulp.task('android-prepare', ['production', 'gz-remove', 'key-remove']);
gulp.task('android-prepare', ['production']);

gulp.task('browser-run', ['production'], shell.task([
    'cordova run browser'
]));

gulp.task('run', shell.task([
    'cordova run android'
]));

gulp.task('release', shell.task([
    'cordova build android --release'
]));

gulp.task('cordova-prepare', shell.task([
    'cordova prepare'
]));

gulp.task('npm-release', shell.task([
    'rm -Rf www/node_modules',
    'mkdir www/node_modules',
    'cp package.json www',
    'npm install --production --prefix www/'
]));

gulp.task('android-execute', ['android-prepare', 'run']);

gulp.task('browser-execute', ['production', 'browser-run']);

gulp.task('dev', ['watch', 'broswer-sync', 'sass_compile', 'concat']);

gulp.task('default', ['watch', 'broswer-sync', 'sass_compile'], function () {

});

gulp.task('clean', shell.task([
    'rm -Rf www/node_modules',
    'rm -Rf plugins',
    'rm -Rf platforms',
]));<|endoftext|>


<commit_before>var gulp = require("gulp");
var browserify = require("gulp-browserify");
var rename = require("gulp-rename");

var browserifyEntryFile = "./lib/browser.js";

gulp.task("browserify", function() {
    return gulp.src(browserifyEntryFile)
        .pipe(browserify())
        .pipe(rename("styx.js"))
        .pipe(gulp.dest("./dist/browser"));
});

gulp.task("browserify-watch", function() {
    return gulp.watch(browserifyEntryFile, ["browserify"]);
});

gulp.task("default", ["browserify-watch"]);
<commit_msg>Runs the "browserify" task before entering watch mode<commit_after>var gulp = require("gulp");
var browserify = require("gulp-browserify");
var rename = require("gulp-rename");

var browserifyEntryFile = "./lib/browser.js";

gulp.task("browserify", function() {
    return gulp.src(browserifyEntryFile)
        .pipe(browserify())
        .pipe(rename("styx.js"))
        .pipe(gulp.dest("./dist/browser"));
});

gulp.task("browserify-watch", function() {
    return gulp.watch(browserifyEntryFile, ["browserify"]);
});

gulp.task("default", ["browserify", "browserify-watch"]);
<|endoftext|>


<commit_before>//defines Openbiz System callbacks
var openbizEventsDelegate = {
	onOpenbizLoaded: function(){
		openbiz.colorSetting = {
			"primary":"#3DA0DB",
                  "info":"#B5D1D8",
                  "success":"#2ECC71",
                  "warning":"#FFCC33",
                  "danger":"#E15258",
                  "inverse":"#62707D",
                  "theme":"#f37864",
                  "theme-inverse":"#6CC3A0",
                  "palevioletred":"#913B53" ,
                  "green":"#99CC00",
                  "lightseagreen":"#1ABC9B"
		}
		openbiz.loadApps(['apps/cubi','apps/dss'/*MORE_APPS*/],function(apps){
			for(var i in apps){
                      apps[i].init();
                  }
			Backbone.history.start();
		})
	}
}<commit_msg>update<commit_after>//defines Openbiz System callbacks
var openbizEventsDelegate = {
	onOpenbizLoaded: function(){
		openbiz.colorSetting = {
			"primary":"#3DA0DB",
                  "info":"#B5D1D8",
                  "success":"#2ECC71",
                  "warning":"#FFCC33",
                  "danger":"#E15258",
                  "inverse":"#62707D",
                  "theme":"#f37864",
                  "theme-inverse":"#6CC3A0",
                  "palevioletred":"#913B53" ,
                  "green":"#99CC00",
                  "lightseagreen":"#1ABC9B"
		}
		openbiz.loadApps(['apps/cubi'/*MORE_APPS*/],function(apps){
			for(var i in apps){
                      apps[i].init();
                  }
			Backbone.history.start();
		})
	}
}<|endoftext|>