<commit_before>"use strict";

var PEG = require('pegjs');
var bonsai = require('../src/index.js');

describe("Bonsai", function () {
    var grammar = [
        'bigrule = simple_word:$("simple " word)?',
        '    intlist:(_:integer ("," ws? &integer)?)*',
        '    actor:("actor " _:actor)?',
        '',
        'simple_sequence = first:word ws second:word',
        '',
        'word = $([a-zA-Z]+)',
        '',
        'integer = [0-9]+ { return parseInt(text()); }',
        '',
        'ws = $([\\t\\n\\r ]+)',
        '',
        'inside_brackets = "[" _:word "]"',
        '',
        'actor = ignored:word ws remembered:word ws also_ignored:word {return remembered;}'].join('\n');
    it("Creates a parser", function() {
        var parser = PEG.buildParser(grammar, {plugins:[bonsai]});
        expect(typeof parser).toBe("object");
        expect(parser.parse).toBeDefined();
    });

    describe("sequence", function () {
        var parser = PEG.buildParser(
                ['simple_sequence = first:word $([ \\n\\r\\t]+) second:word',
                 '',
                 'word = $([a-zA-Z]+)'].join('\n'),
                {plugins:[bonsai]});
        var parsed = parser.parse('hello world', {startRule: 'simple_sequence'});
        it("Produces an object when keys are provided in a sequence", function () {
            expect(typeof parsed).toBe("object");
        });
        it("Maps keys to values", function () {
            expect(parsed.first).toBe('hello');
            expect(parsed.second).toBe('world');
        });
    });

    describe("flattening", function () {
        it("returns a single value when there is only one key and that key is '_'", function () {
            var parser = PEG.buildParser('bracketed = "[" _:$([a-z]+) "]"', {plugins:[bonsai]});
            var parsed = parser.parse('[bracketed]');
            expect(parsed).toBe('bracketed');
        });
        it("returns an object when there is only one key and that key is not '_'", function () {
            var parser = PEG.buildParser('bracketed = "[" matched:$([a-z]+) "]"', {plugins:[bonsai]});
            var parsed = parser.parse('[bracketed]');
            expect(parsed.matched).toBe('bracketed');
        });
        it("can be used to flatten a list", function () {
            var grammar = [
                'intlist = (_:integer ("," ws? &integer)?)*',
                '',
                'integer = [0-9]+ { return parseInt(text()); }',
                '',
                'ws = $([ \\r\\n\\t]+)'
            ].join('\n');
            var parser = PEG.buildParser(grammar, {plugins:[bonsai]});
            var parsed = parser.parse('0, 1,2, 3,4');
            expect(parsed).toEqual([0,1,2,3,4]);
        });
    });
    it("uses an existing action, when available", function () {
        var grammar = [
            'actor = ignored:word ws remembered:word ws also_ignored:word {return remembered;}',
            '',
            'word = $([a-zA-Z]+)',
            '',
            'ws = $([\\t\\n\\r ]+)'].join('\n');
        var parser = PEG.buildParser(grammar, {plugins:[bonsai]});
        var parsed = parser.parse('only keep second');
        expect(parsed).toBe("keep");
    });

});
<commit_msg>spec cleanup and add tests for handling undefined/null<commit_after>"use strict";

var PEG = require('pegjs');
var bonsai = require('../src/index.js');

describe("Bonsai", function () {

    it("creates a parser", function() {
        var parser = PEG.buildParser("word = $([a-zA-Z]+);", {plugins:[bonsai]});
        expect(typeof parser).toBe("object");
        expect(parser.parse).toBeDefined();
    });

    it("uses an existing action, when available", function () {
        var grammar = [
            'actor = ignored:word ws remembered:word ws also_ignored:word {return remembered;};',
            'word = $([a-zA-Z]+);',
            'ws = $([\\t\\n\\r ]+);'].join('\n');
        var parser = PEG.buildParser(grammar, {plugins:[bonsai]});
        var parsed = parser.parse('only keep second');
        expect(parsed).toBe("keep");
    });

    describe("sequence", function () {
        var parser = PEG.buildParser(
                ['simple_sequence = first:word $([ \\n\\r\\t]+) second:word;',
                 'word = $([a-zA-Z]+);'].join('\n'),
                {plugins:[bonsai]});
        var parsed = parser.parse('hello world', {startRule: 'simple_sequence'});
        it("produces an object when keys are provided in a sequence", function () {
            expect(typeof parsed).toBe("object");
        });
        it("maps keys to values", function () {
            expect(parsed.first).toBe('hello');
            expect(parsed.second).toBe('world');
        });
    });

    describe("flattening", function () {
        it("returns a single value when there is only one key and that key is '_'", function () {
            var parser = PEG.buildParser('bracketed = "[" _:$([a-z]+) "]"', {plugins:[bonsai]});
            var parsed = parser.parse('[bracketed]');
            expect(parsed).toBe('bracketed');
        });
        it("returns an object when there is only one key and that key is not '_'", function () {
            var parser = PEG.buildParser('bracketed = "[" matched:$([a-z]+) "]"', {plugins:[bonsai]});
            var parsed = parser.parse('[bracketed]');
            expect(parsed.matched).toBe('bracketed');
        });
        it("can be used to flatten a list", function () {
            var grammar = [
                'intlist = (_:integer ("," ws? &integer)?)*;',
                'integer = [0-9]+ { return parseInt(text()); };',
                'ws = $([ \\r\\n\\t]+);'
            ].join('\n');
            var parser = PEG.buildParser(grammar, {plugins:[bonsai]});
            var parsed = parser.parse('0, 1,2, 3,4');
            expect(parsed).toEqual([0,1,2,3,4]);
        });
    });

    describe("behavior for undefined values", function () {
        it("by default elides key-value pairs where the value is `null` or `undefined`", function () {
            var parser = PEG.buildParser("rule = first:'one' ' '? second:'two'?", {plugins:[bonsai]});
            expect(parser.parse('one two')).toEqual({first: 'one', second: 'two'});
            expect(parser.parse('one')).not.toEqual({first: 'one', second: null});
            expect(parser.parse('one').second).toBeUndefined();
            expect(parser.parse('one')).toEqual({first: 'one'});
        });
        it("can optionally keep attributes with `null` or `undefined` values", function () {
            var parser = PEG.buildParser("rule = first:'one' ' '? second:'two'?", {plugins:[bonsai], bonsaiPlugin:{ keepUndefined:true }});
            expect(parser.parse('one two')).toEqual({first: 'one', second: 'two'});
            expect(parser.parse('one')).toEqual({first: 'one', second: null});
            expect(parser.parse('one').second).toBeDefined();
        });
    });

});
<|endoftext|>


<commit_before>/**
 * Zero helpers
 */

/* eslint-disable no-console */

// Gulp modules
import gulp from 'gulp';
import clean from 'gulp-clean';
import rename from 'gulp-rename';
import replace from 'gulp-replace';
import run from 'gulp-run';
import sequence from 'gulp-sequence';
import shell from 'gulp-shell';

// Helper modules
import fs from 'fs';
// import semver from 'semver';
import yargs from 'yargs';

// Output commands to be executed via "--dry" flag
const DRY_RUN = !!yargs.argv.dry;

// Cloned output files
const CLONE_DIR = './__cloned__';

const CONFIGS_FILE = './gulp-helpers/zero/configs.json';

function readConfigs(platform) {
  const configs = fs.readFileSync(CONFIGS_FILE);

  const {
    packageName,
    moduleName,
    gitRemoteUrl,
    codepush: {
      release: codepushReleaseKey,
      staging: codepushStagingKey,
    },
    [platform]: platformBased,
  } = JSON.parse(configs);

  if (platform === 'general')
    return {
      packageName,
      moduleName,
      gitRemoteUrl,
    };

  const { applicationId, bundleId, ...rest } = platformBased;

  const appId = applicationId || bundleId;
  const appIdNames = {
    android: 'Android applicationId',
    ios: 'iOS bundleId',
  };

  console.assert(
    appId != null,
    `${appIdNames[platform]} must be valid (current: ${appId})`
  );

  return {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
    ...rest,
  };
}

function execCommands(...commands) {
  if (DRY_RUN)
    console.log(['Commands to be executed:\n', ...commands, '\n'].join('\n'));
  else
    gulp.src('.').pipe(shell(commands));
}

// function runSequence(...commands) {
//   if (DRY_RUN)
//     console.log(['Commands to be executed:\n', ...commands, '\n'].join('\n'));
//   else
//     run(commands.join('; ')).exec();
// }

gulp.task('zero:backup', () => {
  gulp.src('./android/**').pipe(gulp.dest('./bak/android'));
  gulp.src('./ios/**').pipe(gulp.dest('./bak/ios'));
  gulp.src('./package.json').pipe(gulp.dest('./bak'));
  gulp.src('./gulp-helpers/codepush/configs.json').pipe(gulp.dest('./bak/gulp-helpers/codepush'));
});

gulp.task('zero:restore', () => (
  execCommands(
    'cp -r ./bak/android .',
    'cp -r ./bak/ios .'
  )
));

gulp.task('zero:setup:cleanup', () => (
  gulp.src(CLONE_DIR).pipe(clean())
));

gulp.task('zero:setup:general', () => {
  const { packageName, moduleName } = readConfigs('general');

  gulp.src('./gulp-helpers/codepush/configs.json')
    .pipe(replace('ZeroProj', moduleName))
    .pipe(gulp.dest(`${CLONE_DIR}/gulp-helpers/codepush`));

  gulp.src('./package.json')
    .pipe(replace('react-native-zero', packageName))
    .pipe(replace('ZeroProj', moduleName))
    .pipe(gulp.dest(CLONE_DIR));
});

gulp.task('zero:setup:android', () => {
  const {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
    signingConfigs: {
      storeFile,
      storePassword,
      keyAlias,
      keyPassword,
    },
  } = readConfigs('android');

  const filesToReplace = [
    'android/**/MainActivity.java',
    'android/**/build.gradle',
    'android/settings.gradle',
  ];

  // Replace specific files
  gulp.src(filesToReplace)
    .pipe(replace('ZeroProj', moduleName))
    .pipe(replace('com.zeroproj', appId))
    .pipe(replace('ZEROPROJ_RELEASE_STORE_FILE', storeFile))
    .pipe(replace('ZEROPROJ_RELEASE_STORE_PASSWORD', storePassword))
    .pipe(replace('ZEROPROJ_RELEASE_KEY_ALIAS', keyAlias))
    .pipe(replace('ZEROPROJ_RELEASE_KEY_PASSWORD', keyPassword))
    .pipe(replace('code_push_release_key', codepushReleaseKey))
    .pipe(replace('code_push_staging_key', codepushStagingKey))
    .pipe(gulp.dest(`${CLONE_DIR}/android`));

  // Copy other files
  gulp.src([
    './android/**',
    ...filesToReplace.map(filename => `!${filename}`),
  ])
    .pipe(gulp.dest(`${CLONE_DIR}/android`));
});

gulp.task('zero:setup:ios', () => {
  const {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
  } = readConfigs('ios');
  const moduleNameReplacement = ['ZeroProj', moduleName];

  gulp.src('./ios/**')
    .pipe(replace(...moduleNameReplacement))
    .pipe(replace('com.zeroproj', appId))
    .pipe(replace('code_push_release_key', codepushReleaseKey))
    .pipe(replace('code_push_staging_key', codepushStagingKey))
    .pipe(rename(path => {
      path.dirname = path.dirname.replace(...moduleNameReplacement);
      path.basename = path.basename.replace(...moduleNameReplacement);
    }))
    .pipe(gulp.dest(`${CLONE_DIR}/ios`));
});

gulp.task('zero:setup:git', () => {
  const { gitRemoteUrl } = readConfigs('general');

  execCommands(
    'rm -rf .git',
    'git init',
    `git remote add origin ${gitRemoteUrl}`,
    'git config --local --add branch.master.remote origin',
    'git config --local --add branch.master.merge refs/heads/master'
  );
});

gulp.task('zero:setup:apply', () => (
  execCommands(
    'rm -rf ./android ./ios',
    `cp -r ${CLONE_DIR}/android .`,
    `cp -r ${CLONE_DIR}/ios .`
  )
));

gulp.task('zero:setup', sequence(
  'zero:setup:cleanup',
  'zero:setup:general',
  'zero:setup:android',
  'zero:setup:ios'
));

gulp.task('zero:apply', sequence(
  'zero:setup:git',
  'zero:setup:apply'
));

gulp.task('zero', sequence(
  'zero:setup',
  'zero:apply'
));

/* eslint-enable no-console */
<commit_msg>Refactor zero tasks<commit_after>/**
 * Zero helpers
 */

/* eslint-disable no-console */

// Gulp modules
import gulp from 'gulp';
import clean from 'gulp-clean';
import rename from 'gulp-rename';
import replace from 'gulp-replace';
import sequence from 'gulp-sequence';
import shell from 'gulp-shell';

// Helper modules
import fs from 'fs';
// import semver from 'semver';
import yargs from 'yargs';

// Output commands to be executed via "--dry" flag
const DRY_RUN = !!yargs.argv.dry;

// Cloned output files
const CLONE_DIR = './__cloned__';

const CONFIGS_FILE = './gulp-helpers/zero/configs.json';

function readConfigs(platform) {
  const configs = fs.readFileSync(CONFIGS_FILE);

  const {
    packageName,
    moduleName,
    gitRemoteUrl,
    codepush: {
      release: codepushReleaseKey,
      staging: codepushStagingKey,
    },
    [platform]: platformBased,
  } = JSON.parse(configs);

  if (platform === 'general')
    return {
      packageName,
      moduleName,
      gitRemoteUrl,
    };

  const { applicationId, bundleId, ...rest } = platformBased;

  const appId = applicationId || bundleId;
  const appIdNames = {
    android: 'Android applicationId',
    ios: 'iOS bundleId',
  };

  console.assert(
    appId != null,
    `${appIdNames[platform]} must be valid (current: ${appId})`
  );

  return {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
    ...rest,
  };
}

function execCommands(...commands) {
  if (DRY_RUN)
    console.log(['Commands to be executed:\n', ...commands, '\n'].join('\n'));
  else
    gulp.src('.').pipe(shell(commands));
}

gulp.task('zero:backup', () => {
  gulp.src('./android/**').pipe(gulp.dest('./bak/android'));
  gulp.src('./ios/**').pipe(gulp.dest('./bak/ios'));
  gulp.src('./package.json').pipe(gulp.dest('./bak'));
  gulp.src('./gulp-helpers/codepush/configs.json').pipe(gulp.dest('./bak/gulp-helpers/codepush'));
});

gulp.task('zero:restore', () => (
  execCommands(
    'cp -r ./bak/android .',
    'cp -r ./bak/ios .'
  )
));

gulp.task('zero:setup:cleanup', () => (
  gulp.src(CLONE_DIR).pipe(clean())
));

gulp.task('zero:setup:general', () => {
  const { packageName, moduleName } = readConfigs('general');

  gulp.src('./gulp-helpers/codepush/configs.json')
    .pipe(replace('ZeroProj', moduleName))
    .pipe(gulp.dest(`${CLONE_DIR}/gulp-helpers/codepush`));

  gulp.src('./package.json')
    .pipe(replace('react-native-zero', packageName))
    .pipe(replace('ZeroProj', moduleName))
    .pipe(gulp.dest(CLONE_DIR));
});

gulp.task('zero:setup:android', () => {
  const {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
    signingConfigs: {
      storeFile,
      storePassword,
      keyAlias,
      keyPassword,
    },
  } = readConfigs('android');

  const filesToReplace = [
    'android/**/MainActivity.java',
    'android/**/build.gradle',
    'android/settings.gradle',
  ];

  // Replace specific files
  gulp.src(filesToReplace)
    .pipe(replace('ZeroProj', moduleName))
    .pipe(replace('com.zeroproj', appId))
    .pipe(replace('ZEROPROJ_RELEASE_STORE_FILE', storeFile))
    .pipe(replace('ZEROPROJ_RELEASE_STORE_PASSWORD', storePassword))
    .pipe(replace('ZEROPROJ_RELEASE_KEY_ALIAS', keyAlias))
    .pipe(replace('ZEROPROJ_RELEASE_KEY_PASSWORD', keyPassword))
    .pipe(replace('code_push_release_key', codepushReleaseKey))
    .pipe(replace('code_push_staging_key', codepushStagingKey))
    .pipe(gulp.dest(`${CLONE_DIR}/android`));

  // Copy other files
  gulp.src([
    './android/**',
    ...filesToReplace.map(filename => `!${filename}`),
  ])
    .pipe(gulp.dest(`${CLONE_DIR}/android`));
});

gulp.task('zero:setup:ios', () => {
  const {
    appId,
    codepushReleaseKey,
    codepushStagingKey,
    moduleName,
  } = readConfigs('ios');
  const moduleNameReplacement = ['ZeroProj', moduleName];

  gulp.src('./ios/**')
    .pipe(replace(...moduleNameReplacement))
    .pipe(replace('com.zeroproj', appId))
    .pipe(replace('code_push_release_key', codepushReleaseKey))
    .pipe(replace('code_push_staging_key', codepushStagingKey))
    .pipe(rename(path => {
      path.dirname = path.dirname.replace(...moduleNameReplacement);
      path.basename = path.basename.replace(...moduleNameReplacement);
    }))
    .pipe(gulp.dest(`${CLONE_DIR}/ios`));
});

gulp.task('zero:setup', sequence(
  'zero:setup:cleanup',
  'zero:setup:android',
  'zero:setup:ios',
  'zero:setup:general'
));

gulp.task('zero:apply:git', () => {
  const { gitRemoteUrl } = readConfigs('general');

  execCommands(
    'rm -rf .git',
    'git init',
    `git remote add origin ${gitRemoteUrl}`,
    'git config --local --add branch.master.remote origin',
    'git config --local --add branch.master.merge refs/heads/master'
  );
});

gulp.task('zero:apply:platforms', () => (
  execCommands(
    'rm -rf ./android ./ios',
    `cp -r ${CLONE_DIR}/android .`,
    `cp -r ${CLONE_DIR}/ios .`
  )
));

gulp.task('zero:apply', sequence(
  'zero:apply:git',
  'zero:apply:platforms'
));

/* eslint-enable no-console */
<|endoftext|>


<commit_before>/**
 * bemhtml-i18n
 * ============
 *
 * Собирает `?.bemhtml.<язык>.js`-файлы на основе `?.keysets.<язык>.js`-файла и исходных шаблонов.
 *
 * Склеивает *bemhtml.xjst* и *bemhtml*-файлы по deps'ам, обрабатывает `bem-xjst`-транслятором,
 * сохраняет (по умолчанию) в виде `?.bemhtml.js`.
 * **Внимание:** поддерживает только js-синтаксис.
 * **Опции**
 *
 * * *String* **target** — Результирующий таргет. По умолчанию — `?.bemhtml.js`.
 * * *String* **lang** — Язык, для которого небходимо собрать файл.
 * * *String* **keysetsFile** — Исходный keysets-файл. По умолчанию — `?.keysets.{lang}.js`.
 * * *String* **filesTarget** — files-таргет, на основе которого получается список исходных файлов
 *   (его предоставляет технология `files`). По умолчанию — `?.files`.
 * * *String* **sourceSuffixes** — суффиксы файлов, по которым строится `files`-таргет.
 *    По умолчанию — `['bemhtml', 'bemhtml.xjst']`.
 * * *String* **exportName** — Имя переменной-обработчика BEMHTML. По умолчанию — `'BEMHTML'`.
 * * *Boolean* **devMode** — Development-режим. По умолчанию — true.
 * * *Boolean* **cache** — Кэширование. Возможно только в production-режиме. По умолчанию — `false`.
 * * *Object* **modulesDeps** — Хэш-объект, прокидывающий в генерируемую для скомпилированных шаблонов обвязку,
 *    необходимые YModules-модули.
 *
 * **Пример**
 *
 * ```javascript
 * nodeConfig.addTech([ require('enb-bem-core-i18n/techs/bemhtml-i18n'), { lang: {lang}, devMode: false } ]);
 * ```
 */
var path = require('path'),
    vow = require('vow'),
    vfs = require('enb/lib/fs/async-fs'),
    bemcompat = require('bemhtml-compat'),
    asyncRequire = require('enb/lib/fs/async-require'),
    dropRequireCache = require('enb/lib/fs/drop-require-cache'),
    keysets = require('../lib/keysets'),
    compile = require('../lib/compile'),
    XJST_SUFFIX = 'xjst';

module.exports = require('enb-bemxjst/techs/bemhtml').buildFlow()
    .name('bemhtml-i18n')
    .target('target', '?.bemhtml.{lang}.js')
    .defineRequiredOption('lang')
    .useFileList(['bemhtml', 'bemhtml.xjst'])
    .useSourceFilename('keysetsFile', '?.keysets.{lang}.js')
    .builder(function (sourceFiles, keysetsFilename) {
        var cache = this.node.getNodeCache(this._target),
            cacheKey = 'keysets-file-' + path.basename(keysetsFilename),
            promise;

        if (cache.needRebuildFile(cacheKey, keysetsFilename)) {
            dropRequireCache(require, keysetsFilename);
            promise = asyncRequire(keysetsFilename)
                .then(function (keysets) {
                    cache.cacheFileInfo(cacheKey, keysetsFilename);

                    return keysets;
                });
        } else {
            promise = asyncRequire(keysetsFilename);
        }

        return promise
            .then(function (sources) {
                var parsed = keysets.parse(sources),
                    template = [
                        'oninit(function(exports, context) {',
                        '    context.BEMContext.prototype.i18n = ' + compile(parsed, this._lang) + ';',
                        '});'
                    ].join('\n');

                return this._readSourceFiles(sourceFiles, true)
                    .then(function (sources) {
                        var source = sources.join('\n') + template;

                        return this._bemxjstProcess(source);
                    }, this);
            }, this);
    })
    .methods({
        _readSourceFiles: function (sourceFiles, oldSyntax) {
            return vow.all(sourceFiles.map(function (file) {
                return vfs.read(file.fullname, 'utf8')
                    .then(function (source) {
                        if (oldSyntax && XJST_SUFFIX !== file.suffix.split('.').pop()) {
                            source = bemcompat.transpile(source);
                        }

                        return '/* begin: ' + file.fullname + ' *' + '/\n' +
                            source +
                            '\n/* end: ' + file.fullname + ' *' + '/';
                    });
            }));
        }
    })
    .createTech();
<commit_msg>Replace \n to EOL<commit_after>/**
 * bemhtml-i18n
 * ============
 *
 * Собирает `?.bemhtml.<язык>.js`-файлы на основе `?.keysets.<язык>.js`-файла и исходных шаблонов.
 *
 * Склеивает *bemhtml.xjst* и *bemhtml*-файлы по deps'ам, обрабатывает `bem-xjst`-транслятором,
 * сохраняет (по умолчанию) в виде `?.bemhtml.js`.
 * **Внимание:** поддерживает только js-синтаксис.
 * **Опции**
 *
 * * *String* **target** — Результирующий таргет. По умолчанию — `?.bemhtml.js`.
 * * *String* **lang** — Язык, для которого небходимо собрать файл.
 * * *String* **keysetsFile** — Исходный keysets-файл. По умолчанию — `?.keysets.{lang}.js`.
 * * *String* **filesTarget** — files-таргет, на основе которого получается список исходных файлов
 *   (его предоставляет технология `files`). По умолчанию — `?.files`.
 * * *String* **sourceSuffixes** — суффиксы файлов, по которым строится `files`-таргет.
 *    По умолчанию — `['bemhtml', 'bemhtml.xjst']`.
 * * *String* **exportName** — Имя переменной-обработчика BEMHTML. По умолчанию — `'BEMHTML'`.
 * * *Boolean* **devMode** — Development-режим. По умолчанию — true.
 * * *Boolean* **cache** — Кэширование. Возможно только в production-режиме. По умолчанию — `false`.
 * * *Object* **modulesDeps** — Хэш-объект, прокидывающий в генерируемую для скомпилированных шаблонов обвязку,
 *    необходимые YModules-модули.
 *
 * **Пример**
 *
 * ```javascript
 * nodeConfig.addTech([ require('enb-bem-core-i18n/techs/bemhtml-i18n'), { lang: {lang}, devMode: false } ]);
 * ```
 */
var EOL = require('os').EOL,
    path = require('path'),
    vow = require('vow'),
    vfs = require('enb/lib/fs/async-fs'),
    bemcompat = require('bemhtml-compat'),
    asyncRequire = require('enb/lib/fs/async-require'),
    dropRequireCache = require('enb/lib/fs/drop-require-cache'),
    keysets = require('../lib/keysets'),
    compile = require('../lib/compile'),
    XJST_SUFFIX = 'xjst';

module.exports = require('enb-bemxjst/techs/bemhtml').buildFlow()
    .name('bemhtml-i18n')
    .target('target', '?.bemhtml.{lang}.js')
    .defineRequiredOption('lang')
    .useFileList(['bemhtml', 'bemhtml.xjst'])
    .useSourceFilename('keysetsFile', '?.keysets.{lang}.js')
    .builder(function (sourceFiles, keysetsFilename) {
        var cache = this.node.getNodeCache(this._target),
            cacheKey = 'keysets-file-' + path.basename(keysetsFilename),
            promise;

        if (cache.needRebuildFile(cacheKey, keysetsFilename)) {
            dropRequireCache(require, keysetsFilename);
            promise = asyncRequire(keysetsFilename)
                .then(function (keysets) {
                    cache.cacheFileInfo(cacheKey, keysetsFilename);

                    return keysets;
                });
        } else {
            promise = asyncRequire(keysetsFilename);
        }

        return promise
            .then(function (sources) {
                var parsed = keysets.parse(sources),
                    template = [
                        'oninit(function(exports, context) {',
                        '    context.BEMContext.prototype.i18n = ' + compile(parsed, this._lang) + ';',
                        '});'
                    ].join(EOL);

                return this._readSourceFiles(sourceFiles, true)
                    .then(function (sources) {
                        var source = sources.join(EOL) + template;
                        return this._bemxjstProcess(source);
                    }, this);
            }, this);
    })
    .methods({
        _readSourceFiles: function (sourceFiles, oldSyntax) {
            return vow.all(sourceFiles.map(function (file) {
                return vfs.read(file.fullname, 'utf8')
                    .then(function (source) {
                        if (oldSyntax && XJST_SUFFIX !== file.suffix.split('.').pop()) {
                            source = bemcompat.transpile(source);
                        }

                        return '/* begin: ' + file.fullname + ' */' + EOL +
                            source +
                            EOL + '/* end: ' + file.fullname + ' *' + '/';
                    });
            }));
        }
    })
    .createTech();
<|endoftext|>


<commit_before>/**
 * i18n-lang-js
 * ============
 *
 * Собирает `?.lang.<язык>.js`-файлы на основе `?.keysets.<язык>.js`-файлов.
 *
 * Используется для локализации в JS с помощью BEM.I18N.
 *
 * **Опции**
 *
 * * *String* **target** — Результирующий таргет. По умолчанию — `?.lang.{lang}.js`.
 * * *String* **lang** — Язык, для которого небходимо собрать файл.
 *
 * **Пример**
 *
 * ```javascript
 * nodeConfig.addTechs([
 *   [ require('enb-bem-i18n/techs/i18n-lang-js'), { lang: 'all'} ],
 *   [ require('enb-bem-i18n/techs/i18n-lang-js'), { lang: '{lang}'} ],
 * ]);
 * ```
 */
var path = require('path'),
    tanker = require('../exlib/tanker'),
    asyncRequire = require('enb/lib/fs/async-require'),
    dropRequireCache = require('enb/lib/fs/drop-require-cache');

module.exports = require('enb/lib/build-flow').create()
    .name('i18n-lang-js')
    .target('target', '?.lang.{lang}.js')
    .defineRequiredOption('lang')
    .useSourceFilename('keysetsFile', '?.keysets.{lang}.js')
    .optionAlias('keysetsFile', 'keysetsTarget')
    .builder(function (keysetsFilename) {
        var node = this.node,
            cache = node.getNodeCache(this._target),
            basename = path.basename(keysetsFilename),
            cacheKey = 'keysets-file-' + basename,
            promise;

        if (cache.needRebuildFile(cacheKey, keysetsFilename)) {
            dropRequireCache(require, keysetsFilename);
            promise = asyncRequire(keysetsFilename)
                .then(function (keysets) {
                    cache.cacheFileInfo(cacheKey, keysetsFilename);
                    return keysets;
                });
        } else {
            promise = asyncRequire(keysetsFilename);
        }

        return promise.then(function (keysets) {
            var lang = this._lang,
                res = Object.keys(keysets).sort().reduce(function (prev, keysetName) {
                    prev.push(this.__self.getKeysetBuildResult(keysetName, keysets[keysetName], lang));
                    return prev;
                }.bind(this), []);
            return this.getPrependJs(lang) + res.join('\n\n') + this.getAppendJs(lang);
        }, this);
    })
    .methods({
        getPrependJs: function (lang) {
            return lang === 'all' ? '' : 'if (typeof BEM !== \'undefined\' && BEM.I18N) {';
        },
        getAppendJs: function (lang) {
            return lang === 'all' ? '' : '\n\nBEM.I18N.lang(\'' + lang + '\');\n\n}\n';
        }
    })
    .staticMethods({
        getKeysetBuildResult: function (keysetName, keyset, lang) {
            var res = [];
            if (keysetName === '') {
                res.push(keyset);
            } else {
                res.push('BEM.I18N.decl(\'' + keysetName + '\', {');
                Object.keys(keyset).map(function (key, i, arr) {
                    tanker.xmlToJs(keyset[key], function (js) {
                        res.push('    ' + JSON.stringify(key) + ': ' + js + (i === arr.length - 1 ? '' : ','));
                    });
                });
                res.push('}, {\n"lang": "' + lang + '"\n});');
            }
            return res.join('\n');
        }
    })
    .createTech();
<commit_msg>Remove old tech source and test files<commit_after><|endoftext|>


<commit_before>import Directory from 'directory-helpers';
import Client from 'phantomjs-promise-es6/lib/client';

const phantomScript = `
'use strict';
var system = require('system');
var request;
while (true) {
  request = JSON.parse(system.stdin.readLine());
  system.stdout.writeLine(JSON.stringify({
    id: request.id,
    result: request
  }));

  if (request.method === 'exit') {
    break;
  }
}
`;

describe('Client', () => {
  let phantomProcess;
  afterEach(async () => {
    const directory = new Directory('temp');
    if (phantomProcess) {
      phantomProcess.kill();
    }
    await directory.remove();
  });

  it('sends and receives JSON messages to/from a child process', async () => {
    const directory = new Directory('temp');
    await directory.write({'phantom-script.js': phantomScript});

    const phantom = directory.spawn('phantomjs', ['phantom-script.js']);
    phantomProcess = phantom.process;

    const client = new Client(phantom.process);

    const promise1 = client.send('call1', []);
    const promise2 = client.send('call2', []);
    expect(await promise1).toEqual({
      id: 1,
      result: {id: 1, method: 'call1', params: []}
    });
    expect(await promise2).toEqual({
      id: 2,
      result: {id: 2, method: 'call2', params: []}
    });

    await client.send('exit');
  });
});
<commit_msg>More Travis debug code<commit_after>import Directory from 'directory-helpers';
import Client from 'phantomjs-promise-es6/lib/client';

const phantomScript = `
'use strict';
var system = require('system');
var request;
while (true) {
  request = JSON.parse(system.stdin.readLine());
  system.stdout.writeLine(JSON.stringify({
    id: request.id,
    result: request
  }));

  if (request.method === 'exit') {
    break;
  }
}
`;

describe('Client', () => {
  let phantomProcess;
  afterEach(async () => {
    const directory = new Directory('temp');
    if (phantomProcess) {
      phantomProcess.kill();
    }
    await directory.remove();
  });

  fit('sends and receives JSON messages to/from a child process', async () => {
    const directory = new Directory('temp');
    await directory.write({'phantom-script.js': phantomScript});

    const phantom = directory.spawn('phantomjs', ['phantom-script.js']);
    phantomProcess = phantom.process;

    const client = new Client(phantom.process);

    const promise1 = client.send('call1', []);
    const promise2 = client.send('call2', []);
    expect(await promise1).toEqual({
      id: 1,
      result: {id: 1, method: 'call1', params: []}
    });
    expect(await promise2).toEqual({
      id: 2,
      result: {id: 2, method: 'call2', params: []}
    });

    await client.send('exit');
  });
});
<|endoftext|>


<commit_before>"use babel"

const {Range} = require("atom")
const {
  it,
  fit,
  ffit,
  fffit,
  emitterEventPromise,
  beforeEach,
  afterEach,
} = require("./async-spec-helpers")

function dispatchCommand(commandName) {
  atom.commands.dispatch(atom.workspace.getElement(), commandName)
}

function ensurePaneLayout(layout) {
  const root = atom.workspace.getActivePane().getContainer().getRoot()
  expect(paneLayoutFor(root)).toEqual(layout)
}

function paneLayoutFor(root) {
  const layout = {}
  layout[root.getOrientation()] = root.getChildren().map(child => {
    switch (child.constructor.name) {
      case "Pane":
      return child.getItems()
      case "PaneAxis":
      return paneLayoutFor(child)
    }
  })
  return layout
}

fdescribe("pane manipulation commands", () => {
  beforeEach(() => {
    // `destroyEmptyPanes` is default true, but atom's spec-helper reset to `false`
    // So set it to `true` again here to test with default value.
    atom.config.set("core.destroyEmptyPanes", true)
    jasmine.attachToDOM(atom.workspace.getElement())

    return atom.packages.activatePackage('vim-mode-plus')
  })

  describe("moveToVery direction", () => {
    describe("all horizontal", () => {
      let e1, e2, e3, p1, p2, p3
      beforeEach(async () => {
        e1 = await atom.workspace.open("file1")
        e2 = await atom.workspace.open("file2", {split: "right"})
        e3 = await atom.workspace.open("file3", {split: "right"})
        const panes = atom.workspace.getCenter().getPanes()
        expect(panes).toHaveLength(3)
        ;[p1, p2, p3] = panes
        ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        expect(atom.workspace.getActivePane()).toBe(p3)
      })

      describe("very-top", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], {horizontal: [[e2], [e3]]}]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e2], {horizontal: [[e1], [e3]]}]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e3], {horizontal: [[e1], [e2]]}]})
        })
      })

      describe("very-bottom", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e2], [e3]]}, [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e1], [e3]]}, [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e1], [e2]]}, [e3]]})
        })
      })

      describe("very-left", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e2], [e1], [e3]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e3], [e1], [e2]]})
        })
      })

      describe("very-right", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e2], [e3], [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e1], [e3], [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        })
      })

      describe("complex operation", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], {horizontal: [[e2], [e3]]}]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e2], [e3]]}, [e1]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e2], [e3], [e1]]})
        })
      })
    })

    describe("all vertical", () => {
      let e1, e2, e3, p1, p2, p3
      beforeEach(async () => {
        e1 = await atom.workspace.open("file1")
        e2 = await atom.workspace.open("file2", {split: "down"})
        e3 = await atom.workspace.open("file3", {split: "down"})
        const panes = atom.workspace.getCenter().getPanes()
        expect(panes).toHaveLength(3)
        ;[p1, p2, p3] = panes
        ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        expect(atom.workspace.getActivePane()).toBe(p3)
      })

      describe("very-top", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e2], [e1], [e3]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e3], [e1], [e2]]})
        })
      })

      describe("very-bottom", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e2], [e3], [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e1], [e3], [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        })
      })

      describe("very-left", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], {vertical: [[e2], [e3]]}]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e2], {vertical: [[e1], [e3]]}]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e3], {vertical: [[e1], [e2]]}]})
        })
      })

      describe("very-right", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e2], [e3]]}, [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e1], [e3]]}, [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e1], [e2]]}, [e3]]})
        })
      })

      describe("complex operation", () =>
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], {vertical: [[e2], [e3]]}]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e2], [e3], [e1]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e2], [e3]]}, [e1]]})
        }))
    })
  })

  describe("exchange-pane", () => {
    let p1, p2, p3, items
    beforeEach(async () => {
      const e1 = await atom.workspace.open("file1")
      const e2 = await atom.workspace.open("file2", {split: "right"})
      const e3 = await atom.workspace.open("file3")
      const e4 = await atom.workspace.open("file4", {split: "down"})
      const panes = atom.workspace.getCenter().getPanes()
      expect(panes).toHaveLength(3)
      ;[p1, p2, p3] = panes
      items = {
        p1: p1.getItems(),
        p2: p2.getItems(),
        p3: p3.getItems(),
      }
      expect(items).toEqual({
        p1: [e1],
        p2: [e2, e3],
        p3: [e4],
      })

      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p3)
    })

    it("[adjacent is pane]: exchange pane and and stay active pane", () => {
      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p3, items.p2]}]})
      expect(atom.workspace.getActivePane()).toBe(p2)

      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p3)
    })

    it("[adjacent is paneAxis]: Do nothing when adjacent was paneAxis", () => {
      p1.activate()
      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p1)
    })
  })
})
<commit_msg>unfocus<commit_after>"use babel"

const {Range} = require("atom")
const {
  it,
  fit,
  ffit,
  fffit,
  emitterEventPromise,
  beforeEach,
  afterEach,
} = require("./async-spec-helpers")

function dispatchCommand(commandName) {
  atom.commands.dispatch(atom.workspace.getElement(), commandName)
}

function ensurePaneLayout(layout) {
  const root = atom.workspace.getActivePane().getContainer().getRoot()
  expect(paneLayoutFor(root)).toEqual(layout)
}

function paneLayoutFor(root) {
  const layout = {}
  layout[root.getOrientation()] = root.getChildren().map(child => {
    switch (child.constructor.name) {
      case "Pane":
      return child.getItems()
      case "PaneAxis":
      return paneLayoutFor(child)
    }
  })
  return layout
}

describe("pane manipulation commands", () => {
  beforeEach(() => {
    // `destroyEmptyPanes` is default true, but atom's spec-helper reset to `false`
    // So set it to `true` again here to test with default value.
    atom.config.set("core.destroyEmptyPanes", true)
    jasmine.attachToDOM(atom.workspace.getElement())

    return atom.packages.activatePackage('vim-mode-plus')
  })

  describe("moveToVery direction", () => {
    describe("all horizontal", () => {
      let e1, e2, e3, p1, p2, p3
      beforeEach(async () => {
        e1 = await atom.workspace.open("file1")
        e2 = await atom.workspace.open("file2", {split: "right"})
        e3 = await atom.workspace.open("file3", {split: "right"})
        const panes = atom.workspace.getCenter().getPanes()
        expect(panes).toHaveLength(3)
        ;[p1, p2, p3] = panes
        ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        expect(atom.workspace.getActivePane()).toBe(p3)
      })

      describe("very-top", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], {horizontal: [[e2], [e3]]}]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e2], {horizontal: [[e1], [e3]]}]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e3], {horizontal: [[e1], [e2]]}]})
        })
      })

      describe("very-bottom", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e2], [e3]]}, [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e1], [e3]]}, [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e1], [e2]]}, [e3]]})
        })
      })

      describe("very-left", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e2], [e1], [e3]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e3], [e1], [e2]]})
        })
      })

      describe("very-right", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e2], [e3], [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e1], [e3], [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
        })
      })

      describe("complex operation", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], {horizontal: [[e2], [e3]]}]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], [e2], [e3]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [{horizontal: [[e2], [e3]]}, [e1]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [[e2], [e3], [e1]]})
        })
      })
    })

    describe("all vertical", () => {
      let e1, e2, e3, p1, p2, p3
      beforeEach(async () => {
        e1 = await atom.workspace.open("file1")
        e2 = await atom.workspace.open("file2", {split: "down"})
        e3 = await atom.workspace.open("file3", {split: "down"})
        const panes = atom.workspace.getCenter().getPanes()
        expect(panes).toHaveLength(3)
        ;[p1, p2, p3] = panes
        ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        expect(atom.workspace.getActivePane()).toBe(p3)
      })

      describe("very-top", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e2], [e1], [e3]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e3], [e1], [e2]]})
        })
      })

      describe("very-bottom", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e2], [e3], [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e1], [e3], [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
        })
      })

      describe("very-left", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], {vertical: [[e2], [e3]]}]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e2], {vertical: [[e1], [e3]]}]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e3], {vertical: [[e1], [e2]]}]})
        })
      })

      describe("very-right", () => {
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e2], [e3]]}, [e1]]})
        })
        it("case 2", () => {
          p2.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e1], [e3]]}, [e2]]})
        })
        it("case 3", () => {
          p3.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e1], [e2]]}, [e3]]})
        })
      })

      describe("complex operation", () =>
        it("case 1", () => {
          p1.activate()
          dispatchCommand("vim-mode-plus:move-pane-to-very-top")
          ensurePaneLayout({vertical: [[e1], [e2], [e3]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-left")
          ensurePaneLayout({horizontal: [[e1], {vertical: [[e2], [e3]]}]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-bottom")
          ensurePaneLayout({vertical: [[e2], [e3], [e1]]})
          dispatchCommand("vim-mode-plus:move-pane-to-very-right")
          ensurePaneLayout({horizontal: [{vertical: [[e2], [e3]]}, [e1]]})
        }))
    })
  })

  describe("exchange-pane", () => {
    let p1, p2, p3, items
    beforeEach(async () => {
      const e1 = await atom.workspace.open("file1")
      const e2 = await atom.workspace.open("file2", {split: "right"})
      const e3 = await atom.workspace.open("file3")
      const e4 = await atom.workspace.open("file4", {split: "down"})
      const panes = atom.workspace.getCenter().getPanes()
      expect(panes).toHaveLength(3)
      ;[p1, p2, p3] = panes
      items = {
        p1: p1.getItems(),
        p2: p2.getItems(),
        p3: p3.getItems(),
      }
      expect(items).toEqual({
        p1: [e1],
        p2: [e2, e3],
        p3: [e4],
      })

      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p3)
    })

    it("[adjacent is pane]: exchange pane and and stay active pane", () => {
      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p3, items.p2]}]})
      expect(atom.workspace.getActivePane()).toBe(p2)

      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p3)
    })

    it("[adjacent is paneAxis]: Do nothing when adjacent was paneAxis", () => {
      p1.activate()
      dispatchCommand("vim-mode-plus:exchange-pane")
      ensurePaneLayout({horizontal: [items.p1, {vertical: [items.p2, items.p3]}]})
      expect(atom.workspace.getActivePane()).toBe(p1)
    })
  })
})
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare",
	"dojo/_base/array",
	"dojo/_base/connect",
	"dojo/_base/lang",
	"dojo/_base/sniff",
	"dojo/_base/event",
	"dojo/_base/html",
	"dojo/_base/window",
	"dojo/cache",
	"dojo/query",
	"dijit/_Widget",
	"dijit/_TemplatedMixin",
	"dijit/_WidgetsInTemplateMixin",
	"dojo/fx",
	"dojo/_base/fx",
	"dojo/string",
	"dijit/focus"
], function(declare, array, connect, lang, has, event, html, win, cache, query, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, fx, baseFx, string, dijitFocus){

var _focusClass = "dojoxGridFBarHover",
	_filteredClass = "dojoxGridFBarFiltered",
	_stopEvent = function(evt){
		try{
			if(evt && evt.preventDefault){
				event.stop(evt);
			}
		}catch(e){}
	};

return declare("dojox.grid.enhanced.plugins.filter.FilterBar", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],{
	// summary:
	//		The filter bar UI.
	templateString: cache("dojox.grid","enhanced/templates/FilterBar.html"),

	widgetsInTemplate: true,

	_timeout_statusTooltip: 300,

	_handle_statusTooltip: null,

	_curColIdx: -1,

	plugin: null,

	postMixInProperties: function(){
		var plugin = this.plugin;
		var nls = plugin.nls;
		this._filterBarDefBtnLabel = nls["filterBarDefButton"];
		this._filterBarClearBtnLabel = nls["filterBarClearButton"];
		this._closeFilterBarBtnLabel = nls["closeFilterBarBtn"];
		var itemsName = plugin.args.itemsName || nls["defaultItemsName"];
		this._noFilterMsg = string.substitute(nls["filterBarMsgNoFilterTemplate"], ["", itemsName]);

		var t = this.plugin.args.statusTipTimeout;
		if(typeof t == 'number'){
			this._timeout_statusTooltip = t;
		}

		var g = plugin.grid;
		g.showFilterBar = lang.hitch(this, "showFilterBar");
		g.toggleFilterBar = lang.hitch(this, "toggleFilterBar");
		g.isFilterBarShown = lang.hitch(this, "isFilterBarShown");
	},
	postCreate: function(){
		this.inherited(arguments);
		if(!this.plugin.args.closeFilterbarButton){
			html.style(this.closeFilterBarButton.domNode, "display", "none");
		}
		var _this = this,
			g = this.plugin.grid,
			old_func = this.oldGetHeaderHeight = lang.hitch(g,g._getHeaderHeight);

		this.placeAt(g.viewsHeaderNode, "after");
		this.connect(this.plugin.filterDefDialog, "showDialog", "_onShowFilterDefDialog");
		this.connect(this.plugin.filterDefDialog, "closeDialog", "_onCloseFilterDefDialog");
		this.connect(g.layer("filter"), "onFiltered", this._onFiltered);

		this.defineFilterButton.domNode.title = this.plugin.nls["filterBarDefButton"];
		if(html.hasClass(win.body(), "dijit_a11y")){
			this.defineFilterButton.set("label", this.plugin.nls["a11yFilterBarDefButton"]);
		}
		this.connect(this.defineFilterButton.domNode, "click", _stopEvent);
		this.connect(this.clearFilterButton.domNode, "click", _stopEvent);
		this.connect(this.closeFilterBarButton.domNode, "click", _stopEvent);

		this.toggleClearFilterBtn(true);
		this._initAriaInfo();

		//Hack the header height to include filter bar height;
		g._getHeaderHeight = function(){
			return old_func() + html.marginBox(_this.domNode).h;
		};
		//Define an area to make focusManager handle all the navigation stuff
		g.focus.addArea({
			name: "filterbar",
			onFocus: lang.hitch(this, this._onFocusFilterBar, false),
			onBlur: lang.hitch(this, this._onBlurFilterBar)
		});
		g.focus.placeArea("filterbar","after","header");
	},
	uninitialize: function(){
		var g = this.plugin.grid;
		g._getHeaderHeight = this.oldGetHeaderHeight;
		g.focus.removeArea("filterbar");
		this.plugin = null;
	},
	isFilterBarShown: function(){
		return html.style(this.domNode, "display") != "none";
	},
	showFilterBar: function(toShow, useAnim, animArgs){
		var g = this.plugin.grid;
		if(useAnim){
			if(Boolean(toShow) == this.isFilterBarShown()){ return; }
			animArgs = animArgs || {};
			var anims = [], defaultDuration = 500;
			anims.push(fx[toShow ? "wipeIn" : "wipeOut"](lang.mixin({
				"node": this.domNode,
				"duration": defaultDuration
			}, animArgs)));
			var curHeight = g.views.views[0].domNode.offsetHeight;
			var prop = {
				"duration": defaultDuration,
				"properties": {
					"height": {
						"end": lang.hitch(this, function(){
							var barHeight = this.domNode.scrollHeight;
							if(has('ff')){
								barHeight -= 2;
							}
							return toShow ? (curHeight - barHeight) : (curHeight + barHeight);
						})
					}
				}
			};
			array.forEach(g.views.views, function(view){
				anims.push(baseFx.animateProperty(lang.mixin({
					"node": view.domNode
				}, prop, animArgs)), baseFx.animateProperty(lang.mixin({
					"node": view.scrollboxNode
				}, prop, animArgs)));
			});
			anims.push(baseFx.animateProperty(lang.mixin({
				"node": g.viewsNode
			}, prop, animArgs)));
			fx.combine(anims).play();
		}else{
			html.style(this.domNode, "display", toShow ? "" : "none");
			g.update();
		}
	},
	toggleFilterBar: function(useAnim, animArgs){
		this.showFilterBar(!this.isFilterBarShown(), useAnim, animArgs);
	},
	getColumnIdx: function(/* int */coordX){
		var headers = query("[role='columnheader']", this.plugin.grid.viewsHeaderNode);
		var idx = -1;
		for(var i = headers.length - 1; i >= 0; --i){
			var coord = html.position(headers[i]);
			if(coordX >= coord.x && coordX < coord.x + coord.w){
				idx = i;
				break;
			}
		}
		if(idx >= 0 && this.plugin.grid.layout.cells[idx].filterable !== false){
			return idx; //Integer
		}else{
			return -1; //Integer
		}
	},
	toggleClearFilterBtn: function(toHide){
		html.style(this.clearFilterButton.domNode, "display", toHide ? "none" : "");
	},
	_closeFilterBar: function(e){
		_stopEvent(e);
		var rulesCnt = this.plugin.filterDefDialog.getCriteria();
		if(rulesCnt){
			var handle = connect.connect(this.plugin.filterDefDialog, "clearFilter", this, function(){
				this.showFilterBar(false, true);
				connect.disconnect(handle);
			});
			this._clearFilterDefDialog(e);
		}else{
			this.showFilterBar(false, true);
		}
	},

	_showFilterDefDialog: function(e){
		_stopEvent(e);
		this.plugin.filterDefDialog.showDialog(this._curColIdx);
		this.plugin.grid.focus.focusArea("filterbar");
	},
	_clearFilterDefDialog: function(e){
		_stopEvent(e);
		this.plugin.filterDefDialog.onClearFilter();
		this.plugin.grid.focus.focusArea("filterbar");
	},
	_onEnterButton: function(e){
		//If mouse is hovering the btn, which means the user is about to click,
		//we should not show status tip on the btn!
		this._onBlurFilterBar();
		_stopEvent(e);
	},
	_onMoveButton: function(e){
		this._onBlurFilterBar();
	},
	_onLeaveButton: function(e){
		this._leavingBtn = true;
	},
	_onShowFilterDefDialog: function(/* Integer */colIdx){
		if(typeof colIdx == "number"){
			this._curColIdx = colIdx;
		}
		this._defPaneIsShown = true;
	},
	_onCloseFilterDefDialog: function(){
		this._defPaneIsShown = false;
		//Do not remember what column are we on, so clicking the btn will show 'any column'
		this._curColIdx = -1;
		dijitFocus.focus(this.defineFilterButton.domNode);
	},
	_onClickFilterBar: function(/* event */e){
		_stopEvent(e);
		this._clearStatusTipTimeout();
		this.plugin.grid.focus.focusArea("filterbar");
		this.plugin.filterDefDialog.showDialog(this.getColumnIdx(e.clientX));
	},
	_onMouseEnter: function(/* event */e){
		this._onFocusFilterBar(true, null);
		this._updateTipPosition(e);
		this._setStatusTipTimeout();
	},
	_onMouseMove: function(/* event */e){
		if(this._leavingBtn){
			this._onFocusFilterBar(true, null);
			this._leavingBtn = false;
		}
		if(this._isFocused){
			this._setStatusTipTimeout();
			this._highlightHeader(this.getColumnIdx(e.clientX));
			if(this._handle_statusTooltip){
				this._updateTipPosition(e);
			}
		}
	},
	_onMouseLeave: function(e){
		this._onBlurFilterBar();
	},
	_updateTipPosition: function(evt){
		this._tippos = {
			x: evt.pageX,
			y: evt.pageY
		};
	},
	_onFocusFilterBar: function(highlightOnly, evt, step){
		if(!this.isFilterBarShown()){
			return false;
		}
		this._isFocused = true;
		html.addClass(this.domNode,_focusClass);
		if(!highlightOnly){
			var hasFilter = html.style(this.clearFilterButton.domNode, "display") !== "none";
			var hasCloseButton = html.style(this.closeFilterBarButton.domNode, "display") !== "none";
			if(typeof this._focusPos == "undefined"){
				if(step > 0){
					this._focusPos = 0;
				}else{
					if(hasCloseButton){
						this._focusPos = 1;
					}else{
						this._focusPos = 0;
					}
					if(hasFilter){
						++this._focusPos;
					}
				}
			}
			if(this._focusPos === 0){
				dijitFocus.focus(this.defineFilterButton.focusNode);
			}else if(this._focusPos === 1 && hasFilter){
				dijitFocus.focus(this.clearFilterButton.focusNode);
			}else{
				dijitFocus.focus(this.closeFilterBarButton.focusNode);
			}
		}
		_stopEvent(evt);
		return true;
	},
	_onBlurFilterBar: function(evt, step){
		if(this._isFocused){
			this._isFocused = false;
			html.removeClass(this.domNode,_focusClass);
			this._clearStatusTipTimeout();
			this._clearHeaderHighlight();
		}
		var toBlur = true;
		if(step){
			var buttonCount = 3;
			if(html.style(this.closeFilterBarButton.domNode, "display") === "none"){
				--buttonCount;
			}
			if(html.style(this.clearFilterButton.domNode, "display") === "none"){
				--buttonCount;
			}
			if(buttonCount == 1){
				delete this._focusPos;
			}else{
				var current = this._focusPos;
				for(var next = current + step; next < 0; next += buttonCount){}
				next %= buttonCount;
				if((step > 0 && next < current) || (step < 0 && next > current)){
					delete this._focusPos;
				}else{
					this._focusPos = next;
					toBlur = false;
				}
			}
		}
		return toBlur;
	},
	_onFiltered: function(/* int */filteredSize,/* int */originSize){
		var p = this.plugin,
			itemsName = p.args.itemsName || p.nls["defaultItemsName"],
			msg = "", g = p.grid,
			filterLayer = g.layer("filter");
		if(filterLayer.filterDef()){
			msg = string.substitute(p.nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]);
			html.addClass(this.domNode, _filteredClass);
		}else{
			msg = string.substitute(p.nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]);
			html.removeClass(this.domNode, _filteredClass);
		}
		this.statusBarNode.innerHTML = msg;
		this._focusPos = 0;
	},
	_initAriaInfo: function(){
		this.defineFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarDefButton"]);
		this.clearFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarClearButton"]);
	},
	_isInColumn: function(/* int */mousePos_x, /* domNode */headerNode, /* int */colIndex){
		var coord = html.position(headerNode);
		return mousePos_x >= coord.x && mousePos_x < coord.x + coord.w;
	},
	_setStatusTipTimeout: function(){
		this._clearStatusTipTimeout();
		if(!this._defPaneIsShown){
			this._handle_statusTooltip = setTimeout(lang.hitch(this,this._showStatusTooltip),this._timeout_statusTooltip);
		}
	},
	_clearStatusTipTimeout: function(){
		clearTimeout(this._handle_statusTooltip);
		this._handle_statusTooltip = null;
	},
	_showStatusTooltip: function(){
		this._handle_statusTooltip = null;
		this.plugin.filterStatusTip.showDialog(this._tippos.x, this._tippos.y, this.getColumnIdx(this._tippos.x));
	},
	_highlightHeader: function(/* int */colIdx){
		if(colIdx != this._previousHeaderIdx){
			var g = this.plugin.grid,
			cell = g.getCell(this._previousHeaderIdx);
			if(cell){
				html.removeClass(cell.getHeaderNode(), "dojoxGridCellOver");
			}
			cell = g.getCell(colIdx);
			if(cell){
				html.addClass(cell.getHeaderNode(), "dojoxGridCellOver");
			}
			this._previousHeaderIdx = colIdx;
		}
	},
	_clearHeaderHighlight: function(){
		if(typeof this._previousHeaderIdx != "undefined"){
			var g = this.plugin.grid,
			cell = g.getCell(this._previousHeaderIdx);
			if(cell){
				g.onHeaderCellMouseOut({
					cellNode: cell.getHeaderNode()
				});
			}
			delete this._previousHeaderIdx;
		}
	}
});
});
<commit_msg>Fixes #15109 !strict, by adding a safe check, thanks for lzboron's patch<commit_after>define([
	"dojo/_base/declare",
	"dojo/_base/array",
	"dojo/_base/connect",
	"dojo/_base/lang",
	"dojo/_base/sniff",
	"dojo/_base/event",
	"dojo/_base/html",
	"dojo/_base/window",
	"dojo/cache",
	"dojo/query",
	"dijit/_Widget",
	"dijit/_TemplatedMixin",
	"dijit/_WidgetsInTemplateMixin",
	"dojo/fx",
	"dojo/_base/fx",
	"dojo/string",
	"dijit/focus"
], function(declare, array, connect, lang, has, event, html, win, cache, query, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, fx, baseFx, string, dijitFocus){

var _focusClass = "dojoxGridFBarHover",
	_filteredClass = "dojoxGridFBarFiltered",
	_stopEvent = function(evt){
		try{
			if(evt && evt.preventDefault){
				event.stop(evt);
			}
		}catch(e){}
	};

return declare("dojox.grid.enhanced.plugins.filter.FilterBar", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],{
	// summary:
	//		The filter bar UI.
	templateString: cache("dojox.grid","enhanced/templates/FilterBar.html"),

	widgetsInTemplate: true,

	_timeout_statusTooltip: 300,

	_handle_statusTooltip: null,

	_curColIdx: -1,

	plugin: null,

	postMixInProperties: function(){
		var plugin = this.plugin;
		var nls = plugin.nls;
		this._filterBarDefBtnLabel = nls["filterBarDefButton"];
		this._filterBarClearBtnLabel = nls["filterBarClearButton"];
		this._closeFilterBarBtnLabel = nls["closeFilterBarBtn"];
		var itemsName = plugin.args.itemsName || nls["defaultItemsName"];
		this._noFilterMsg = string.substitute(nls["filterBarMsgNoFilterTemplate"], ["", itemsName]);

		var t = this.plugin.args.statusTipTimeout;
		if(typeof t == 'number'){
			this._timeout_statusTooltip = t;
		}

		var g = plugin.grid;
		g.showFilterBar = lang.hitch(this, "showFilterBar");
		g.toggleFilterBar = lang.hitch(this, "toggleFilterBar");
		g.isFilterBarShown = lang.hitch(this, "isFilterBarShown");
	},
	postCreate: function(){
		this.inherited(arguments);
		if(!this.plugin.args.closeFilterbarButton){
			html.style(this.closeFilterBarButton.domNode, "display", "none");
		}
		var _this = this,
			g = this.plugin.grid,
			old_func = this.oldGetHeaderHeight = lang.hitch(g,g._getHeaderHeight);

		this.placeAt(g.viewsHeaderNode, "after");
		this.connect(this.plugin.filterDefDialog, "showDialog", "_onShowFilterDefDialog");
		this.connect(this.plugin.filterDefDialog, "closeDialog", "_onCloseFilterDefDialog");
		this.connect(g.layer("filter"), "onFiltered", this._onFiltered);

		this.defineFilterButton.domNode.title = this.plugin.nls["filterBarDefButton"];
		if(html.hasClass(win.body(), "dijit_a11y")){
			this.defineFilterButton.set("label", this.plugin.nls["a11yFilterBarDefButton"]);
		}
		this.connect(this.defineFilterButton.domNode, "click", _stopEvent);
		this.connect(this.clearFilterButton.domNode, "click", _stopEvent);
		this.connect(this.closeFilterBarButton.domNode, "click", _stopEvent);

		this.toggleClearFilterBtn(true);
		this._initAriaInfo();

		//Hack the header height to include filter bar height;
		g._getHeaderHeight = function(){
			return old_func() + html.marginBox(_this.domNode).h;
		};
		//Define an area to make focusManager handle all the navigation stuff
		g.focus.addArea({
			name: "filterbar",
			onFocus: lang.hitch(this, this._onFocusFilterBar, false),
			onBlur: lang.hitch(this, this._onBlurFilterBar)
		});
		g.focus.placeArea("filterbar","after","header");
	},
	uninitialize: function(){
		var g = this.plugin.grid;
		g._getHeaderHeight = this.oldGetHeaderHeight;
		g.focus.removeArea("filterbar");
		this.plugin = null;
	},
	isFilterBarShown: function(){
		return html.style(this.domNode, "display") != "none";
	},
	showFilterBar: function(toShow, useAnim, animArgs){
		var g = this.plugin.grid;
		if(useAnim){
			if(Boolean(toShow) == this.isFilterBarShown()){ return; }
			animArgs = animArgs || {};
			var anims = [], defaultDuration = 500;
			anims.push(fx[toShow ? "wipeIn" : "wipeOut"](lang.mixin({
				"node": this.domNode,
				"duration": defaultDuration
			}, animArgs)));
			var curHeight = g.views.views[0].domNode.offsetHeight;
			var prop = {
				"duration": defaultDuration,
				"properties": {
					"height": {
						"end": lang.hitch(this, function(){
							var barHeight = this.domNode.scrollHeight;
							if(has('ff')){
								barHeight -= 2;
							}
							return toShow ? (curHeight - barHeight) : (curHeight + barHeight);
						})
					}
				}
			};
			array.forEach(g.views.views, function(view){
				anims.push(baseFx.animateProperty(lang.mixin({
					"node": view.domNode
				}, prop, animArgs)), baseFx.animateProperty(lang.mixin({
					"node": view.scrollboxNode
				}, prop, animArgs)));
			});
			anims.push(baseFx.animateProperty(lang.mixin({
				"node": g.viewsNode
			}, prop, animArgs)));
			fx.combine(anims).play();
		}else{
			html.style(this.domNode, "display", toShow ? "" : "none");
			g.update();
		}
	},
	toggleFilterBar: function(useAnim, animArgs){
		this.showFilterBar(!this.isFilterBarShown(), useAnim, animArgs);
	},
	getColumnIdx: function(/* int */coordX){
		var headers = query("[role='columnheader']", this.plugin.grid.viewsHeaderNode);
		var idx = -1;
		for(var i = headers.length - 1; i >= 0; --i){
			var coord = html.position(headers[i]);
			if(coordX >= coord.x && coordX < coord.x + coord.w){
				idx = i;
				break;
			}
		}
		if(idx >= 0 && this.plugin.grid.layout.cells[idx].filterable !== false){
			return idx; //Integer
		}else{
			return -1; //Integer
		}
	},
	toggleClearFilterBtn: function(toHide){
		html.style(this.clearFilterButton.domNode, "display", toHide ? "none" : "");
	},
	_closeFilterBar: function(e){
		_stopEvent(e);
		var rulesCnt = this.plugin.filterDefDialog.getCriteria();
		if(rulesCnt){
			var handle = connect.connect(this.plugin.filterDefDialog, "clearFilter", this, function(){
				this.showFilterBar(false, true);
				connect.disconnect(handle);
			});
			this._clearFilterDefDialog(e);
		}else{
			this.showFilterBar(false, true);
		}
	},

	_showFilterDefDialog: function(e){
		_stopEvent(e);
		this.plugin.filterDefDialog.showDialog(this._curColIdx);
		this.plugin.grid.focus.focusArea("filterbar");
	},
	_clearFilterDefDialog: function(e){
		_stopEvent(e);
		this.plugin.filterDefDialog.onClearFilter();
		this.plugin.grid.focus.focusArea("filterbar");
	},
	_onEnterButton: function(e){
		//If mouse is hovering the btn, which means the user is about to click,
		//we should not show status tip on the btn!
		this._onBlurFilterBar();
		_stopEvent(e);
	},
	_onMoveButton: function(e){
		this._onBlurFilterBar();
	},
	_onLeaveButton: function(e){
		this._leavingBtn = true;
	},
	_onShowFilterDefDialog: function(/* Integer */colIdx){
		if(typeof colIdx == "number"){
			this._curColIdx = colIdx;
		}
		this._defPaneIsShown = true;
	},
	_onCloseFilterDefDialog: function(){
		this._defPaneIsShown = false;
		//Do not remember what column are we on, so clicking the btn will show 'any column'
		this._curColIdx = -1;
		dijitFocus.focus(this.defineFilterButton.domNode);
	},
	_onClickFilterBar: function(/* event */e){
		_stopEvent(e);
		this._clearStatusTipTimeout();
		this.plugin.grid.focus.focusArea("filterbar");
		this.plugin.filterDefDialog.showDialog(this.getColumnIdx(e.clientX));
	},
	_onMouseEnter: function(/* event */e){
		this._onFocusFilterBar(true, null);
		this._updateTipPosition(e);
		this._setStatusTipTimeout();
	},
	_onMouseMove: function(/* event */e){
		if(this._leavingBtn){
			this._onFocusFilterBar(true, null);
			this._leavingBtn = false;
		}
		if(this._isFocused){
			this._setStatusTipTimeout();
			this._highlightHeader(this.getColumnIdx(e.clientX));
			if(this._handle_statusTooltip){
				this._updateTipPosition(e);
			}
		}
	},
	_onMouseLeave: function(e){
		this._onBlurFilterBar();
	},
	_updateTipPosition: function(evt){
		this._tippos = {
			x: evt.pageX,
			y: evt.pageY
		};
	},
	_onFocusFilterBar: function(highlightOnly, evt, step){
		if(!this.isFilterBarShown()){
			return false;
		}
		this._isFocused = true;
		html.addClass(this.domNode,_focusClass);
		if(!highlightOnly){
			var hasFilter = html.style(this.clearFilterButton.domNode, "display") !== "none";
			var hasCloseButton = html.style(this.closeFilterBarButton.domNode, "display") !== "none";
			if(typeof this._focusPos == "undefined"){
				if(step > 0){
					this._focusPos = 0;
				}else{
					if(hasCloseButton){
						this._focusPos = 1;
					}else{
						this._focusPos = 0;
					}
					if(hasFilter){
						++this._focusPos;
					}
				}
			}
			if(this._focusPos === 0){
				dijitFocus.focus(this.defineFilterButton.focusNode);
			}else if(this._focusPos === 1 && hasFilter){
				dijitFocus.focus(this.clearFilterButton.focusNode);
			}else{
				dijitFocus.focus(this.closeFilterBarButton.focusNode);
			}
		}
		_stopEvent(evt);
		return true;
	},
	_onBlurFilterBar: function(evt, step){
		if(this._isFocused){
			this._isFocused = false;
			html.removeClass(this.domNode,_focusClass);
			this._clearStatusTipTimeout();
			this._clearHeaderHighlight();
		}
		var toBlur = true;
		if(step){
			var buttonCount = 3;
			if(html.style(this.closeFilterBarButton.domNode, "display") === "none"){
				--buttonCount;
			}
			if(html.style(this.clearFilterButton.domNode, "display") === "none"){
				--buttonCount;
			}
			if(buttonCount == 1){
				delete this._focusPos;
			}else{
				var current = this._focusPos;
				for(var next = current + step; next < 0; next += buttonCount){}
				next %= buttonCount;
				if((step > 0 && next < current) || (step < 0 && next > current)){
					delete this._focusPos;
				}else{
					this._focusPos = next;
					toBlur = false;
				}
			}
		}
		return toBlur;
	},
	_onFiltered: function(/* int */filteredSize,/* int */originSize){
		var p = this.plugin,
			itemsName = p.args.itemsName || p.nls["defaultItemsName"],
			msg = "", g = p.grid,
			filterLayer = g.layer("filter");
		if(filterLayer.filterDef()){
			msg = string.substitute(p.nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]);
			html.addClass(this.domNode, _filteredClass);
		}else{
			msg = string.substitute(p.nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]);
			html.removeClass(this.domNode, _filteredClass);
		}
		this.statusBarNode.innerHTML = msg;
		this._focusPos = 0;
	},
	_initAriaInfo: function(){
		this.defineFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarDefButton"]);
		this.clearFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarClearButton"]);
	},
	_isInColumn: function(/* int */mousePos_x, /* domNode */headerNode, /* int */colIndex){
		var coord = html.position(headerNode);
		return mousePos_x >= coord.x && mousePos_x < coord.x + coord.w;
	},
	_setStatusTipTimeout: function(){
		this._clearStatusTipTimeout();
		if(!this._defPaneIsShown){
			this._handle_statusTooltip = setTimeout(lang.hitch(this,this._showStatusTooltip),this._timeout_statusTooltip);
		}
	},
	_clearStatusTipTimeout: function(){
		clearTimeout(this._handle_statusTooltip);
		this._handle_statusTooltip = null;
	},
	_showStatusTooltip: function(){
		this._handle_statusTooltip = null;
		if(this.plugin){
			this.plugin.filterStatusTip.showDialog(this._tippos.x, this._tippos.y, this.getColumnIdx(this._tippos.x));
		}
	},
	_highlightHeader: function(/* int */colIdx){
		if(colIdx != this._previousHeaderIdx){
			var g = this.plugin.grid,
			cell = g.getCell(this._previousHeaderIdx);
			if(cell){
				html.removeClass(cell.getHeaderNode(), "dojoxGridCellOver");
			}
			cell = g.getCell(colIdx);
			if(cell){
				html.addClass(cell.getHeaderNode(), "dojoxGridCellOver");
			}
			this._previousHeaderIdx = colIdx;
		}
	},
	_clearHeaderHighlight: function(){
		if(typeof this._previousHeaderIdx != "undefined"){
			var g = this.plugin.grid,
			cell = g.getCell(this._previousHeaderIdx);
			if(cell){
				g.onHeaderCellMouseOut({
					cellNode: cell.getHeaderNode()
				});
			}
			delete this._previousHeaderIdx;
		}
	}
});
});
<|endoftext|>


<commit_before>// ***********************************************
// WINE LIFE
// DISCOVER WINDOW - DiscoverWindow.js
//
// MEN+1
// Programmer: Matthew Johnson
// ***********************************************

function DiscoverWindow(title) {

	var global = require('ui/common/globals');
	var dropdown = require('ui/common/elements/dropdown');
	var self = global.createWindow(title);
	self.barImage='images/iPhone_Nav_Bar_With_Bkgrd.png';
	var TU = require ('/TitanUp/TitanUp');

	// This view holds the wine list
	var view = Ti.UI.createView({
		top:'40%',
		left:0,
		width:'100%',
		height:'55%',
		layout: 'vertical'
	});

	var label_title = Ti.UI.createLabel({
		color: global.colors.dark,
		text:"Today's Featured Wines",
		font:{
            fontFamily:'Helvetica Neue',
            fontSize:18,
            fontWeight:'Medium'
           }
	});
//***********************************************************************************
//  This original list in the future will display advertised wines / picks of the day
//***********************************************************************************
	self.addEventListener('open', function(e){
		global.api.search_with_filter("Zinfandel", '124', function(search_results){
            table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
			});
		   view.add(label_title);
           view.add(table);
      });
	});

	self.add(view);

//************************************************************************
// Arrays with wines for picker menu's
//************************************************************************

 var allwines = ['Type', 'Amarone', 'Barolo', 'Blanc', 'Bordeaux', 'Cabernet', 'Carmenere', 'Chenin',
  'Chianti', 'Grand', 'Grenache', 'Grigio', 'Gris', 'Merlot', 'Murray', 'Muscat', 'Pinot Noir', 'Riesling',
 'Rose', 'Sangiovese', 'Shiraz', 'Syrah', 'Traminer', 'Verdicchio', 'Zinfandel'];

 var redwines =  ['Type','Amarone', 'Barolo', 'Cabernet', 'Carmenere',
  'Chianti', 'Grand', 'Grenache', 'Merlot', 'Pinot Noir',
  'Sangiovese', 'Shiraz', 'Syrah', 'Zinfandel'];

 var whitewines = ['Type','Blanc','Bordeaux', 'Chenin',
  'Grigio', 'Gris', 'Murray', 'Muscat', 'Riesling',
 'Rose', 'Traminer', 'Verdicchio'];

// Drop down view
	var view_discover = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			layout: 'vertical',
			left: 10,
			right: 10,
		});

	var wine_review = null;
	var table = null;

	// Dropdown menu components
	var search_bar = Ti.UI.createTextField({
		top:0,
		width:'90%',
		left:'5%',
		hintText:' Discover Wine...',
		borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	});

	var picker_color = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Color",
		values: ['Color','Red', 'White']
	});

	var picker_allwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: allwines
	});

	var picker_redwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: redwines
	});

	var picker_whitewines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: whitewines
	});

	// These variables store picker selected values
	var winecolor = null; // this is for color id to refine search
	var wineColor = null;  // this is for actual wine color
	var winetype = null;

//*****************************************************************
//  Associative array used for server query filtering
//*****************************************************************

	var wines = new Object;
	wines['Amarone'] = '145';
	wines['Australian'] = '145';
	wines['Barolo'] = '170';
	wines['Blanc'] = '144';
	wines['Bordeaux'] = '160';
	wines['Cabernet'] = '139';
	wines['Carmenere'] = '10081';
	wines['Chenin'] = '165';
	wines['Chile'] = '10081';
	wines['Chianti'] = '152';
	wines['Grand'] = '10082';
	wines['Grenache'] = '10080';
	wines['Grigio'] = '194';
	wines['Gris'] = '194';
	wines['Merlot'] = '138';
	wines['Murray'] = '162';
	wines['Muscat'] = '173';
	wines['Pinot Noir'] = '143';
	wines['Riesling'] = '153';
	wines['Rose'] = '147';
	wines['Sangiovese'] = '163';
	wines['Shiraz'] = '146';
	wines['Syrah'] = '146';
	wines['Traminer'] = '148';
	wines['Verdicchio'] = '148';
	wines['Zinfandel'] = '141';

//******************************************************************************
// Event listener for wine color picker.  This function adds and removes views
// based off of what is selected in the picker.
//******************************************************************************
	picker_color.addEventListener ('TUchange', function (e) {
		if(e.value == 'Red'){
			winecolor = '124';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_whitewines);
			view_discover.add(picker_redwines);

		picker_redwines.addEventListener ('TUchange', function (e) {
		winetype =  e.value;
		});

		}
		else if(e.value == "White"){
			winecolor = '125';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_whitewines);

			picker_whitewines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}
		else{
			winecolor = null;
			wineColor = null;
			view_discover.remove(picker_whitewines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_allwines);

			picker_allwines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}

	});

	picker_allwines.addEventListener ('TUchange', function (e) {
	winetype =  e.value;
	});

	view_discover.add(search_bar);
	view_discover.add(picker_color);
	view_discover.add(picker_allwines);

//***********************************************************************************
// Dropdown menu area
// This function controls the dropdown menu and the logic for the pickers and
// search bar.
//***********************************************************************************
	dropdown(view_discover, self, "Find", "Browse", "down", function(){

		view.setTop('10%');
		view.setHeight('90%');
		view.remove(table);
		view.remove(label_title);
		self.remove(view);
		label_title.setText("Search Results");
		view.add(label_title);

		if(search_bar.value != null && search_bar.value != ""){

		if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(search_bar.value, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else
			{
				global.api.search(search_bar.value, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}

        self.add(view);

     }
     else{
     //	if nothing entered in textfield do these
     	if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(winetype, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(winetype, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(wineColor, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else if(winecolor == null && winetype == null)
			{
				alert('Please Enter a Wine or Select a Filter to Search');
			}

     	self.add(view);
     }
	});

global.outputHook(self);
return self;
};

module.exports = DiscoverWindow;<commit_msg>removed broken filters<commit_after>// ***********************************************
// WINE LIFE
// DISCOVER WINDOW - DiscoverWindow.js
//
// MEN+1
// Programmer: Matthew Johnson
// ***********************************************

function DiscoverWindow(title) {

	var global = require('ui/common/globals');
	var dropdown = require('ui/common/elements/dropdown');
	var self = global.createWindow(title);
	self.barImage='images/iPhone_Nav_Bar_With_Bkgrd.png';
	var TU = require ('/TitanUp/TitanUp');

	// This view holds the wine list
	var view = Ti.UI.createView({
		top:'40%',
		left:0,
		width:'100%',
		height:'60%',
		layout: 'vertical'
	});

	var label_title = Ti.UI.createLabel({
		color: global.colors.dark,
		text:"Today's Featured Wines",
		font:{
            fontFamily:'Helvetica Neue',
            fontSize:18,
            fontWeight:'Medium'
           }
	});
//***********************************************************************************
//  This original list in the future will display advertised wines / picks of the day
//***********************************************************************************
	self.addEventListener('open', function(e){
		global.api.search_with_filter("Zinfandel", '124', function(search_results){
            table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
			});
		   view.add(label_title);
           view.add(table);
      });
	});

	self.add(view);

//************************************************************************
// Arrays with wines for picker menu's
//************************************************************************

 var allwines = ['Type', 'Amarone', 'Blanc', 'Cabernet', 'Chenin',
 'Grand', 'Grenache', 'Grigio', 'Gris', 'Merlot', 'Murray', 'Muscat', 'Pinot Noir', 'Riesling',
  'Sangiovese', 'Shiraz', 'Syrah', 'Traminer', 'Verdicchio', 'Zinfandel'];

 var redwines =  ['Type','Amarone', 'Cabernet',
   'Grand', 'Grenache', 'Merlot', 'Pinot Noir',
  'Sangiovese', 'Shiraz', 'Syrah', 'Zinfandel'];

 var whitewines = ['Type','Blanc', 'Chenin',
  'Grigio', 'Gris', 'Murray', 'Muscat', 'Riesling',
  'Traminer', 'Verdicchio'];

// wines with filters not working
//  'Barolo', 'Carmenere', 'Chianti', 'Bordeaux',

// Drop down view
	var view_discover = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			layout: 'vertical',
			left: 10,
			right: 10,
		});

	var wine_review = null;
	var table = null;

	// Dropdown menu components
	var search_bar = Ti.UI.createTextField({
		top:0,
		width:'90%',
		left:'5%',
		hintText:' Discover Wine...',
		borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	});

	var picker_color = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Color",
		values: ['Color','Red', 'White']
	});

	var picker_allwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: allwines
	});

	var picker_redwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: redwines
	});

	var picker_whitewines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: whitewines
	});

	// These variables store picker selected values
	var winecolor = null; // this is for color id to refine search
	var wineColor = null;  // this is for actual wine color
	var winetype = null;

//*****************************************************************
//  Associative array used for server query filtering
//*****************************************************************

	var wines = new Object;
	wines['Amarone'] = '145';
	wines['Australian'] = '145';
	wines['Barolo'] = '170';
	wines['Blanc'] = '144';
	wines['Bordeaux'] = '160';
	wines['Cabernet'] = '139';
	wines['Carmenere'] = '10081';
	wines['Chenin'] = '165';
	wines['Chile'] = '10081';
	wines['Chianti'] = '152';
	wines['Grand'] = '10082';
	wines['Grenache'] = '10080';
	wines['Grigio'] = '194';
	wines['Gris'] = '194';
	wines['Merlot'] = '138';
	wines['Murray'] = '162';
	wines['Muscat'] = '173';
	wines['Pinot Noir'] = '143';
	wines['Riesling'] = '153';
	wines['Rose'] = '147';
	wines['Sangiovese'] = '163';
	wines['Shiraz'] = '146';
	wines['Syrah'] = '146';
	wines['Traminer'] = '148';
	wines['Verdicchio'] = '148';
	wines['Zinfandel'] = '141';

//******************************************************************************
// Event listener for wine color picker.  This function adds and removes views
// based off of what is selected in the picker.
//******************************************************************************
	picker_color.addEventListener ('TUchange', function (e) {
		if(e.value == 'Red'){
			winecolor = '124';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_whitewines);
			view_discover.add(picker_redwines);

		picker_redwines.addEventListener ('TUchange', function (e) {
		winetype =  e.value;
		});

		}
		else if(e.value == "White"){
			winecolor = '125';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_whitewines);

			picker_whitewines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}
		else{
			winecolor = null;
			wineColor = null;
			view_discover.remove(picker_whitewines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_allwines);

			picker_allwines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}

	});

	picker_allwines.addEventListener ('TUchange', function (e) {
	winetype =  e.value;
	});

	view_discover.add(search_bar);
	view_discover.add(picker_color);
	view_discover.add(picker_allwines);

//***********************************************************************************
// Dropdown menu area
// This function controls the dropdown menu and the logic for the pickers and
// search bar.
//***********************************************************************************
	dropdown(view_discover, self, "Find", "Browse", "down", function(){

		view.setTop('10%');
		view.setHeight('90%');
		view.remove(table);
		view.remove(label_title);
		self.remove(view);
		label_title.setText("Search Results");
		view.add(label_title);

		if(search_bar.value != null && search_bar.value != ""){

		if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(search_bar.value, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else
			{
				global.api.search(search_bar.value, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}

        self.add(view);

     }
     else{
     //	if nothing entered in textfield do these
     	if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(winetype, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(winetype, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(wineColor, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else if(winecolor == null && winetype == null)
			{
				//alert('Please Enter a Wine or Select a Filter to Search');
			}

     	self.add(view);
     }
	});

global.outputHook(self);
return self;
};

module.exports = DiscoverWindow;<|endoftext|>