<commit_before>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.MainMenu');

/**
 *
 * @param {boolean} isSubtitled
 * @param {Array.<Object<string, string>>=} Optional array of
 *     json translation languages, where each language
 *     has a code and name.
 */
mirosubs.MainMenu = function(videoID, nullWidget,
                             isSubtitled, opt_translationLanguages) {
    goog.ui.PopupMenu.call(this);
    // FIXME: is there a better way to do this rather than setting globals?
    goog.ui.MenuRenderer.CSS_CLASS = 'mirosubs-langmenu';
    goog.ui.MenuItemRenderer.CSS_CLASS = goog.getCssName('mirosubs-langmenuitem');
    goog.ui.MenuSeparatorRenderer.CSS_CLASS = goog.getCssName('mirosubs-langmenusep');
    this.videoID_ = videoID;
    this.nullWidget_ = nullWidget;
    this.isSubtitled_ = isSubtitled;
    this.translationLanguages_ = opt_translationLanguages || [];
    this.currentLangCode_ = null;
    this.showingSubs_ = false;
    this.setToggleMode(true);
};
goog.inherits(mirosubs.MainMenu, goog.ui.PopupMenu);
mirosubs.MainMenu.MenuValues_ = {
    ADD_SUBTITLES: 'addsubs',
    EDIT_SUBTITLES: 'editsubs',
    ORIGINAL_LANG: 'originallang',
    NEW_LANG: 'newlang',
    LOGIN: 'login',
    CREATE_ACCOUNT: 'createaccount',
    LOGOUT: 'logout',
    SHARETHIS: 'sharethis',
    TURNOFFSUBS: 'turnoffsubs'
};
mirosubs.MainMenu.EventType = {
    ADD_SUBTITLES: 'addsubs',
    EDIT_SUBTITLES: 'editsubs',
    LANGUAGE_SELECTED: 'langselected',
    ADD_NEW_LANGUAGE: 'newlanguage',
    TURN_OFF_SUBS: 'turnoffsubs'
};
/**
 * Sets current language code -- used to add SRT download link to menu.
 * @param {?langCode} The current language code selected, or null to indicate
 *     original language.
 */
mirosubs.MainMenu.prototype.setCurrentLangCode = function(langCode) {
    this.currentLangCode_ = langCode;
};
mirosubs.MainMenu.prototype.setShowingSubs = function(show) {
    this.showingSubs_ = show;
};
mirosubs.MainMenu.prototype.onActionTaken_ = function(event) {
    var selectedValue = event.target.getModel();
    var mv = mirosubs.MainMenu.MenuValues_;
    var et = mirosubs.MainMenu.EventType;
    if (selectedValue == mv.ADD_SUBTITLES)
        this.dispatchEvent(et.ADD_SUBTITLES);
    else if (selectedValue == mv.EDIT_SUBTITLES)
        this.dispatchEvent(et.EDIT_SUBTITLES);
    else if (selectedValue == mv.ORIGINAL_LANG)
        this.dispatchEvent(
            new mirosubs.MainMenu
                .LanguageSelectedEvent());
    else if (selectedValue == mv.NEW_LANG)
        this.dispatchEvent(et.ADD_NEW_LANGUAGE);
    else if (selectedValue == mv.LOGIN)
        mirosubs.login();
    else if (selectedValue == mv.CREATE_ACCOUNT)
        mirosubs.createAccount();
    else if (selectedValue == mv.LOGOUT)
        mirosubs.logout();
    else if (selectedValue == mv.SHARETHIS)
        alert('not yet implemented');
    else if (selectedValue == mv.TURNOFFSUBS)
        this.dispatchEvent(et.TURN_OFF_SUBS);
    else
        this.dispatchEvent(
            new mirosubs.MainMenu
                .LanguageSelectedEvent(selectedValue));
};
mirosubs.MainMenu.prototype.setTranslationLanguages = function(langs) {
    this.translationLanguages_ = langs;
};
mirosubs.MainMenu.prototype.setSubtitled = function() {
    this.isSubtitled_ = true;
};
mirosubs.MainMenu.prototype.enterDocument = function() {
    mirosubs.MainMenu.superClass_.enterDocument.call(this);
    this.getHandler().listen(
        this, goog.ui.Component.EventType.ACTION, this.onActionTaken_);
};
mirosubs.MainMenu.prototype.showMenu = function(target, x, y) {
    if (!this.isVisible() && !this.wasRecentlyHidden())
        this.setMenuItems_();
    mirosubs.MainMenu.superClass_.showMenu.call(this, target, x, y);
};
mirosubs.MainMenu.prototype.setMenuItems_ = function() {
    this.removeChildren(true);
    var mv = mirosubs.MainMenu.MenuValues_;
    if (this.showingSubs_) {
        this.addChild(new goog.ui.MenuItem(
            'Edit subs', mv.EDIT_SUBTITLES), true);
        this.addChild(new goog.ui.MenuItem(
            'Turn off subs', mv.TURNOFFSUBS), true);
        this.addChild(new goog.ui.MenuSeparator(), true);
    }
    if (this.isSubtitled_) {
        this.addChild(new goog.ui.MenuItem('Original',
            mv.ORIGINAL_LANG), true);
        var that = this;
        goog.array.forEach(this.translationLanguages_, function(lang) {
            that.addChild(new goog.ui.MenuItem(
                lang['name'], lang['code']), true);
        });
        this.addChild(new goog.ui.MenuItem(
            'Add new', mv.NEW_LANG), true);
    }
    else {
        this.addChild(new goog.ui.MenuItem('Add Subtitles',
                                           mv.ADD_SUBTITLES), true);
    }
    this.addChild(new goog.ui.MenuSeparator(), true);
    if (mirosubs.currentUsername == null) {
        this.addChild(new goog.ui.MenuItem('Login', mv.LOGIN), true);
        this.addChild(new goog.ui.MenuItem('Create Account',
                                           mv.CREATE_ACCOUNT), true);
    }
    else
        this.addChild(new goog.ui.MenuItem('Logout',
                                           mv.LOGOUT), true);
    this.addChild(new goog.ui.MenuSeparator(), true);
    this.addChild(new goog.ui.MenuItem('Share this',
                                       mv.SHARETHIS), true);
    if (this.showingSubs_) {
        this.addChild(new goog.ui.MenuSeparator(), true);
        this.addChild(this.createDownloadSRTLink_(), true);
    }
};
mirosubs.MainMenu.prototype.createDownloadSRTLink_ = function() {
    var url = [mirosubs.BASE_URL,
               "/widget/download_",
               (this.nullWidget_ ? "null_" : ""),
               "srt/?video_id=",
               '' + this.videoID_].join('');
    if (this.currentLangCode_)
        url += ['&lang_code=', this.currentLangCode_].join('')
    var $d = goog.bind(this.getDomHelper().createDom,
                       this.getDomHelper());
    var menuItem = new goog.ui.MenuItem(
        $d('a', {'href':url}, 'Download SRT'));
    menuItem.setSelectable(false);
    menuItem.setEnabled(false);
    return menuItem;
};
mirosubs.MainMenu.LanguageSelectedEvent = function(opt_languageCode) {
    this.type = mirosubs.MainMenu.EventType.LANGUAGE_SELECTED;
    /**
     * The language code selected, or null to signify original
     * language.
     * @type {?string}
     */
    this.languageCode = opt_languageCode;
};<commit_msg>13420: removed share link from main menu<commit_after>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.MainMenu');

/**
 *
 * @param {boolean} isSubtitled
 * @param {Array.<Object<string, string>>=} Optional array of
 *     json translation languages, where each language
 *     has a code and name.
 */
mirosubs.MainMenu = function(videoID, nullWidget,
                             isSubtitled, opt_translationLanguages) {
    goog.ui.PopupMenu.call(this);
    // FIXME: is there a better way to do this rather than setting globals?
    goog.ui.MenuRenderer.CSS_CLASS = 'mirosubs-langmenu';
    goog.ui.MenuItemRenderer.CSS_CLASS = goog.getCssName('mirosubs-langmenuitem');
    goog.ui.MenuSeparatorRenderer.CSS_CLASS = goog.getCssName('mirosubs-langmenusep');
    this.videoID_ = videoID;
    this.nullWidget_ = nullWidget;
    this.isSubtitled_ = isSubtitled;
    this.translationLanguages_ = opt_translationLanguages || [];
    this.currentLangCode_ = null;
    this.showingSubs_ = false;
    this.setToggleMode(true);
};
goog.inherits(mirosubs.MainMenu, goog.ui.PopupMenu);
mirosubs.MainMenu.MenuValues_ = {
    ADD_SUBTITLES: 'addsubs',
    EDIT_SUBTITLES: 'editsubs',
    ORIGINAL_LANG: 'originallang',
    NEW_LANG: 'newlang',
    LOGIN: 'login',
    CREATE_ACCOUNT: 'createaccount',
    LOGOUT: 'logout',
    TURNOFFSUBS: 'turnoffsubs'
};
mirosubs.MainMenu.EventType = {
    ADD_SUBTITLES: 'addsubs',
    EDIT_SUBTITLES: 'editsubs',
    LANGUAGE_SELECTED: 'langselected',
    ADD_NEW_LANGUAGE: 'newlanguage',
    TURN_OFF_SUBS: 'turnoffsubs'
};
/**
 * Sets current language code -- used to add SRT download link to menu.
 * @param {?langCode} The current language code selected, or null to indicate
 *     original language.
 */
mirosubs.MainMenu.prototype.setCurrentLangCode = function(langCode) {
    this.currentLangCode_ = langCode;
};
mirosubs.MainMenu.prototype.setShowingSubs = function(show) {
    this.showingSubs_ = show;
};
mirosubs.MainMenu.prototype.onActionTaken_ = function(event) {
    var selectedValue = event.target.getModel();
    var mv = mirosubs.MainMenu.MenuValues_;
    var et = mirosubs.MainMenu.EventType;
    if (selectedValue == mv.ADD_SUBTITLES)
        this.dispatchEvent(et.ADD_SUBTITLES);
    else if (selectedValue == mv.EDIT_SUBTITLES)
        this.dispatchEvent(et.EDIT_SUBTITLES);
    else if (selectedValue == mv.ORIGINAL_LANG)
        this.dispatchEvent(
            new mirosubs.MainMenu
                .LanguageSelectedEvent());
    else if (selectedValue == mv.NEW_LANG)
        this.dispatchEvent(et.ADD_NEW_LANGUAGE);
    else if (selectedValue == mv.LOGIN)
        mirosubs.login();
    else if (selectedValue == mv.CREATE_ACCOUNT)
        mirosubs.createAccount();
    else if (selectedValue == mv.LOGOUT)
        mirosubs.logout();
    else if (selectedValue == mv.TURNOFFSUBS)
        this.dispatchEvent(et.TURN_OFF_SUBS);
    else
        this.dispatchEvent(
            new mirosubs.MainMenu
                .LanguageSelectedEvent(selectedValue));
};
mirosubs.MainMenu.prototype.setTranslationLanguages = function(langs) {
    this.translationLanguages_ = langs;
};
mirosubs.MainMenu.prototype.setSubtitled = function() {
    this.isSubtitled_ = true;
};
mirosubs.MainMenu.prototype.enterDocument = function() {
    mirosubs.MainMenu.superClass_.enterDocument.call(this);
    this.getHandler().listen(
        this, goog.ui.Component.EventType.ACTION, this.onActionTaken_);
};
mirosubs.MainMenu.prototype.showMenu = function(target, x, y) {
    if (!this.isVisible() && !this.wasRecentlyHidden())
        this.setMenuItems_();
    mirosubs.MainMenu.superClass_.showMenu.call(this, target, x, y);
};
mirosubs.MainMenu.prototype.setMenuItems_ = function() {
    this.removeChildren(true);
    var mv = mirosubs.MainMenu.MenuValues_;
    if (this.showingSubs_) {
        this.addChild(new goog.ui.MenuItem(
            'Edit subs', mv.EDIT_SUBTITLES), true);
        this.addChild(new goog.ui.MenuItem(
            'Turn off subs', mv.TURNOFFSUBS), true);
        this.addChild(new goog.ui.MenuSeparator(), true);
    }
    if (this.isSubtitled_) {
        this.addChild(new goog.ui.MenuItem('Original',
            mv.ORIGINAL_LANG), true);
        var that = this;
        goog.array.forEach(this.translationLanguages_, function(lang) {
            that.addChild(new goog.ui.MenuItem(
                lang['name'], lang['code']), true);
        });
        this.addChild(new goog.ui.MenuItem(
            'Add new', mv.NEW_LANG), true);
    }
    else {
        this.addChild(new goog.ui.MenuItem('Add Subtitles',
                                           mv.ADD_SUBTITLES), true);
    }
    this.addChild(new goog.ui.MenuSeparator(), true);
    if (mirosubs.currentUsername == null) {
        this.addChild(new goog.ui.MenuItem('Login', mv.LOGIN), true);
        this.addChild(new goog.ui.MenuItem('Create Account',
                                           mv.CREATE_ACCOUNT), true);
    }
    else
        this.addChild(new goog.ui.MenuItem('Logout',
                                           mv.LOGOUT), true);
    this.addChild(new goog.ui.MenuSeparator(), true);
    if (this.showingSubs_) {
        this.addChild(new goog.ui.MenuSeparator(), true);
        this.addChild(this.createDownloadSRTLink_(), true);
    }
};
mirosubs.MainMenu.prototype.createDownloadSRTLink_ = function() {
    var url = [mirosubs.BASE_URL,
               "/widget/download_",
               (this.nullWidget_ ? "null_" : ""),
               "srt/?video_id=",
               '' + this.videoID_].join('');
    if (this.currentLangCode_)
        url += ['&lang_code=', this.currentLangCode_].join('')
    var $d = goog.bind(this.getDomHelper().createDom,
                       this.getDomHelper());
    var menuItem = new goog.ui.MenuItem(
        $d('a', {'href':url}, 'Download SRT'));
    menuItem.setSelectable(false);
    menuItem.setEnabled(false);
    return menuItem;
};
mirosubs.MainMenu.LanguageSelectedEvent = function(opt_languageCode) {
    this.type = mirosubs.MainMenu.EventType.LANGUAGE_SELECTED;
    /**
     * The language code selected, or null to signify original
     * language.
     * @type {?string}
     */
    this.languageCode = opt_languageCode;
};<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 */

CLASS({
  package: 'com.google.sweeper',
  name: 'Board',
  extends: 'foam.u2.Element',

  requires: [ 'com.google.sweeper.Cell' ],
  exports: [ 'as board' ],

  properties: [
    [ 'width', 14 ],
    [ 'height', 14 ],
    {
      name: 'cells',
      lazyFactory: function() {
        var cells = [];
        for ( var row = 0 ; row < this.height ; row++ ) {
          cells[row] = [];
          for ( var col = 0 ; col < this.width ; col++ ) {
            var cell = this.Cell.create({x: col, y: row});
            cells[row][col] = cell;
            cell.covered$.addListener(this.cellUncovered);
          }
        }
        return cells;
      }
    }
  ],

  methods: {
    getMineCount: function(cell) {
      var c = 0;
      for ( var row = Math.max(0, cell.y-1) ; row < Math.min(this.height, cell.y+2) ; row++ ) {
        for ( var col = Math.max(0, cell.x-1) ; col < Math.min(this.width, cell.x+2) ; col++ ) {
          if ( this.cells[row][col].mined ) c++;
        }
      }
      return c;
    }
  },

  templates: [
    function CSS() {/*
      $ {
        border: 1px solid gray;
        display: inline-block;
        margin: 24px;
      }
    */},
    function initE() {/*#U2

        (( for ( var col = 0 ; col < this.width ; col++ ) { ))
          {{this.cells[row][col]}}
        (( } ))

    */}
  ],

  listeners: [
    function cellUncovered(cell) {
      if ( cell.mineCount ) return;
      this.X.setTimeout(function() {
        for ( var x = -1 ; x <= 1 ; x++ ) {
          for ( var y = -1 ; y <= 1 ; y++ ) {
            try {
              var c = this.cells[cell.y+y][cell.x+x];
              if ( ! c.mined ) c.covered = false;
            } catch(x) {}
          }
        }}.bind(this), 32);
    }
  ]
});
<commit_msg>Sweeper: refactoring<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 */

CLASS({
  package: 'com.google.sweeper',
  name: 'Board',
  extends: 'foam.u2.Element',

  requires: [ 'com.google.sweeper.Cell' ],
  exports: [ 'as board' ],

  properties: [
    [ 'width', 14 ],
    [ 'height', 14 ],
    {
      name: 'cells',
      lazyFactory: function() {
        var cells = [];
        for ( var row = 0 ; row < this.height ; row++ ) {
          cells[row] = [];
          for ( var col = 0 ; col < this.width ; col++ ) {
            var cell = this.Cell.create({x: col, y: row});
            cells[row][col] = cell;
            cell.covered$.addListener(this.cellUncovered);
          }
        }
        return cells;
      }
    }
  ],

  methods: [
    function forEachNeighbour(cell, f) {
      for ( var row = Math.max(0, cell.y-1) ; row < Math.min(this.height, cell.y+2) ; row++ )
        for ( var col = Math.max(0, cell.x-1) ; col < Math.min(this.width, cell.x+2) ; col++ )
          f(this.cells[row][col]);
    },
    function getMineCount(cell) {
      var count = 0;
      this.forEachNeighbour(cell, function(c) { if ( c.mined ) count++; });
      return count;
    }
  ],

  templates: [
    function CSS() {/*
      $ {
        border: 1px solid gray;
        display: inline-block;
        margin: 24px;
      }
    */},
    function initE() {/*#U2

        (( for ( var col = 0 ; col < this.width ; col++ ) { ))
          {{this.cells[row][col]}}
        (( } ))

    */}
  ],

  listeners: [
    function cellUncovered(cell) {
      if ( cell.mineCount ) return;
      this.X.setTimeout(this.forEachNeighbour.bind(this, cell, function(c) { if ( ! c.mined ) c.covered = false; }), 32);
    }
  ]
});
<|endoftext|>


<commit_before>import React, { Component, Suspense, lazy } from 'react'
import merge from 'deepmerge'
import memoize from 'memoize-one'
import isEqual from 'react-fast-compare'

import { propTypes, defaultProps } from './props'
import { omit } from './utils'
import players from './players'
import Player from './Player'

const Preview = lazy(() => import('./Preview'))

const SUPPORTED_PROPS = Object.keys(propTypes)
const customPlayers = []

export default class ReactPlayer extends Component {
  static displayName = 'ReactPlayer'
  static propTypes = propTypes
  static defaultProps = defaultProps
  static addCustomPlayer = player => { customPlayers.push(player) }
  static removeCustomPlayers = () => { customPlayers.length = 0 }

  static canPlay = url => {
    for (const Player of [...customPlayers, ...players]) {
      if (Player.canPlay(url)) {
        return true
      }
    }
    return false
  }

  static canEnablePIP = url => {
    for (const Player of [...customPlayers, ...players]) {
      if (Player.canEnablePIP && Player.canEnablePIP(url)) {
        return true
      }
    }
    return false
  }

  state = {
    showPreview: !!this.props.light
  }

  // Use references, as refs is used by React
  references = {
    wrapper: wrapper => { this.wrapper = wrapper },
    player: player => { this.player = player }
  }

  shouldComponentUpdate (nextProps, nextState) {
    return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState)
  }

  componentDidUpdate (prevProps) {
    const { light } = this.props
    if (!prevProps.light && light) {
      this.setState({ showPreview: true })
    }
    if (prevProps.light && !light) {
      this.setState({ showPreview: false })
    }
  }

  handleClickPreview = () => {
    this.setState({ showPreview: false })
  }

  showPreview = () => {
    this.setState({ showPreview: true })
  }

  getDuration = () => {
    if (!this.player) return null
    return this.player.getDuration()
  }

  getCurrentTime = () => {
    if (!this.player) return null
    return this.player.getCurrentTime()
  }

  getSecondsLoaded = () => {
    if (!this.player) return null
    return this.player.getSecondsLoaded()
  }

  getInternalPlayer = (key = 'player') => {
    if (!this.player) return null
    return this.player.getInternalPlayer(key)
  }

  seekTo = (fraction, type) => {
    if (!this.player) return null
    this.player.seekTo(fraction, type)
  }

  handleReady = () => {
    this.props.onReady(this)
  }

  getActivePlayer = memoize(url => {
    for (const player of [...customPlayers, ...players]) {
      if (player.canPlay(url)) {
        return player
      }
    }
    // Fall back to FilePlayer if nothing else can play the URL
    return players[players.length - 1]
  })

  getConfig = memoize((url, key) => {
    const { config } = this.props
    return merge.all([
      defaultProps.config,
      defaultProps.config[key] || {},
      config,
      config[key] || {}
    ])
  })

  getAttributes = memoize(url => {
    return omit(this.props, SUPPORTED_PROPS)
  })

  renderPreview (url) {
    if (!url) return null
    const { light, playIcon } = this.props
    return (
      <Preview
        url={url}
        light={light}
        playIcon={playIcon}
        onClick={this.handleClickPreview}
      />
    )
  }

  renderActivePlayer = url => {
    if (!url) return null
    const player = this.getActivePlayer(url)
    const config = this.getConfig(url, player.key)
    return (
      <Player
        {...this.props}
        key={player.key}
        ref={this.references.player}
        config={config}
        activePlayer={player.lazyPlayer || player}
        onReady={this.handleReady}
      />
    )
  }

  render () {
    const { url, style, width, height, wrapper: Wrapper } = this.props
    const { showPreview } = this.state
    const attributes = this.getAttributes(url)
    return (
      <Wrapper ref={this.references.wrapper} style={{ ...style, width, height }} {...attributes}>
        <Suspense fallback={null}>
          {showPreview
            ? this.renderPreview(url)
            : this.renderActivePlayer(url)}
        </Suspense>
      </Wrapper>
    )
  }
}
<commit_msg>Prevent Suspense being rendering during SSR<commit_after>import React, { Component, Suspense, lazy } from 'react'
import merge from 'deepmerge'
import memoize from 'memoize-one'
import isEqual from 'react-fast-compare'

import { propTypes, defaultProps } from './props'
import { omit } from './utils'
import players from './players'
import Player from './Player'

const Preview = lazy(() => import('./Preview'))

const IS_BROWSER = typeof window !== 'undefined' && window.document
const SUPPORTED_PROPS = Object.keys(propTypes)

// Return null when rendering on the server
// as Suspense is not supported yet
const UniversalSuspense = IS_BROWSER ? Suspense : () => null

const customPlayers = []

export default class ReactPlayer extends Component {
  static displayName = 'ReactPlayer'
  static propTypes = propTypes
  static defaultProps = defaultProps
  static addCustomPlayer = player => { customPlayers.push(player) }
  static removeCustomPlayers = () => { customPlayers.length = 0 }

  static canPlay = url => {
    for (const Player of [...customPlayers, ...players]) {
      if (Player.canPlay(url)) {
        return true
      }
    }
    return false
  }

  static canEnablePIP = url => {
    for (const Player of [...customPlayers, ...players]) {
      if (Player.canEnablePIP && Player.canEnablePIP(url)) {
        return true
      }
    }
    return false
  }

  state = {
    showPreview: !!this.props.light
  }

  // Use references, as refs is used by React
  references = {
    wrapper: wrapper => { this.wrapper = wrapper },
    player: player => { this.player = player }
  }

  shouldComponentUpdate (nextProps, nextState) {
    return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState)
  }

  componentDidUpdate (prevProps) {
    const { light } = this.props
    if (!prevProps.light && light) {
      this.setState({ showPreview: true })
    }
    if (prevProps.light && !light) {
      this.setState({ showPreview: false })
    }
  }

  handleClickPreview = () => {
    this.setState({ showPreview: false })
  }

  showPreview = () => {
    this.setState({ showPreview: true })
  }

  getDuration = () => {
    if (!this.player) return null
    return this.player.getDuration()
  }

  getCurrentTime = () => {
    if (!this.player) return null
    return this.player.getCurrentTime()
  }

  getSecondsLoaded = () => {
    if (!this.player) return null
    return this.player.getSecondsLoaded()
  }

  getInternalPlayer = (key = 'player') => {
    if (!this.player) return null
    return this.player.getInternalPlayer(key)
  }

  seekTo = (fraction, type) => {
    if (!this.player) return null
    this.player.seekTo(fraction, type)
  }

  handleReady = () => {
    this.props.onReady(this)
  }

  getActivePlayer = memoize(url => {
    for (const player of [...customPlayers, ...players]) {
      if (player.canPlay(url)) {
        return player
      }
    }
    // Fall back to FilePlayer if nothing else can play the URL
    return players[players.length - 1]
  })

  getConfig = memoize((url, key) => {
    const { config } = this.props
    return merge.all([
      defaultProps.config,
      defaultProps.config[key] || {},
      config,
      config[key] || {}
    ])
  })

  getAttributes = memoize(url => {
    return omit(this.props, SUPPORTED_PROPS)
  })

  renderPreview (url) {
    if (!url) return null
    const { light, playIcon } = this.props
    return (
      <Preview
        url={url}
        light={light}
        playIcon={playIcon}
        onClick={this.handleClickPreview}
      />
    )
  }

  renderActivePlayer = url => {
    if (!url) return null
    const player = this.getActivePlayer(url)
    const config = this.getConfig(url, player.key)
    return (
      <Player
        {...this.props}
        key={player.key}
        ref={this.references.player}
        config={config}
        activePlayer={player.lazyPlayer || player}
        onReady={this.handleReady}
      />
    )
  }

  render () {
    const { url, style, width, height, wrapper: Wrapper } = this.props
    const { showPreview } = this.state
    const attributes = this.getAttributes(url)
    return (
      <Wrapper ref={this.references.wrapper} style={{ ...style, width, height }} {...attributes}>
        <UniversalSuspense fallback={null}>
          {showPreview
            ? this.renderPreview(url)
            : this.renderActivePlayer(url)}
        </UniversalSuspense>
      </Wrapper>
    )
  }
}
<|endoftext|>


<commit_before>'use strict';

var blessed = require('blessed');
const logger = require('../util/Logger.js');
const clipboard = require('../util/Clipboard.js');
const CheckboxListDialog = require('./CheckboxListDialog.js');
const MessageDialog = require('./MessageDialog.js');
const tagConfig = require('../util/TagConfig.js');
const Filters = require('./Filters.js');
const util = require('util');
const TagDialog = require('./TagDialog.js');

class TracksView{

  constructor(screen, style, player, playlistManager){
    this._screen = screen;
    this._style = style;
    this._player = player;
    this._trackList = undefined;
    this._filteredTrackList = undefined;
    this._activeFilters = new Set();
    this._playlistManager = playlistManager;
    let self = this;

    this._list = blessed.list({
      parent: screen,
      tags: true,
      draggable: false,
      top: 0,
      right: 0,
      width: '40%',
      height: `100%-${style.outputView.height}`,
      keys: true,
      vi: true,
      mouse: false,
      border: 'line',
      scrollbar: {
        ch: ' ',
        track: {
          bg: 'cyan'
        },
        style: {
          inverse: true
        }
      },
      style: JSON.parse(JSON.stringify(style.box)), //deep copy style
      search: function(callback) {
        self._prompt.input('{white-fg}Search track:{/white-fg}', '', function(err, value) {
          if (err) return;
          return callback(null, value);
        });
      }
    });
    this._prompt = blessed.prompt({
      parent: screen,
      top: 'center',
      left: 'center',
      height: 'shrink',
      width: 'shrink',
      keys: true,
      vi: true,
      mouse: false,
      tags: true,
      border: 'line',
      hidden: true,
      style: JSON.parse(JSON.stringify(style.box)) //deep copy style
    });

    this._list.on('focus', this.onFocused.bind(this));
    this._list.on('blur', this.onUnFocused.bind(this));
    this._updateTitle();
  }

  showList(list){
    this._trackList = list;
    this._update();
  }

  show(){
    this._list.focus();
    this._list.enterSelected(0);
    this._list.show();
    this._screen.render();
  }

  hide(){
    this._list.hide();
    this._screen.render();
  }

  focus(){
    this._list.focus();
  }

  onPlay(){
    let track = this._selectedTrack();
    logger.debug('play ' + track.getName());

    this._player.play(this._filteredTrackList, this._list.selected);
  }

  onFocused(){
    this._updateTitle();
    this._screen.key('p', this.onPlay.bind(this));
    this._screen.key('C-c', this.copyToClipboard.bind(this));
    this._screen.key('f', this.filter.bind(this));
    this._screen.key('t', this.tagEntry.bind(this));
    this._screen.key('i', this.showInfo.bind(this));
  }

  onUnFocused(){
    this._updateTitle();
    this._screen.removeKeyAll('p');
    this._screen.removeKeyAll('C-c');
    this._screen.removeKeyAll('f');
    this._screen.removeKeyAll('t');
    this._screen.removeKeyAll('i');
  }

  copyToClipboard(){
    let track = this._selectedTrack();
    if (!track){
      return; //nothing selected
    }

    logger.verbose('copy ' + track.getName());

    clipboard.set(track, (clipboard, playlist, selectedPlaylistEntry)=>{
      playlist.addTrack(clipboard.content(), selectedPlaylistEntry);
    });
  }

  filter(){
    let dialog = new CheckboxListDialog(this._screen, this._style, 'f');
    let availableTags = tagConfig.getQualifiedTags();
    const UNTAGGED_OPTION = '[untagged]';
    availableTags.push(UNTAGGED_OPTION);

    let usedTags = [...this._activeFilters].map((filter)=>filter.getName());

    dialog.ask('Filter by tags', availableTags, usedTags, (addedElements, removedElements, selectedTags)=>{
      if (!selectedTags){
        return; //user pressed esc
      }

      this._activeFilters.clear();

      selectedTags.forEach((tagName)=>{
        this._activeFilters.add(
          tagName === UNTAGGED_OPTION
            ? new Filters.FilterUntagged(UNTAGGED_OPTION)
            : new Filters.FilterByTag(tagName)
        );
      });

      this._update();
    });
  }

  tagEntry(){
    let track = this._selectedTrack();
    if (!track){
      return; //nothing selected
    }

    let usedTags = track.tagsAsString();

    let dialog = new TagDialog(this._screen, this._style, 't', 'Select tags');
    dialog.ask(usedTags, (addedElements, removedElements)=>{
      addedElements.forEach((tagName)=>{
        this._playlistManager.addTrackToTag(track, tagName);
      });
      removedElements.forEach((tagName)=>{
        this._playlistManager.removeTrackFromTag(track, tagName);
      });
    });
  }

  showInfo(){
    let track = this._selectedTrack();
    if (!track){
      return; //nothing selected
    }

    let view = new MessageDialog(this._screen, this._style, 'i', 'Info: ' + track.getName(), util.inspect(track._track));
    view.show();
  }

  _selectedTrack(){
    return this._filteredTrackList[this._list.selected];
  }

  _updateTitle(){
    let template = this._list.focused ? this._style.title.focused : this._style.title.unfocused;
    let filters = this._activeFilters.size == 0
      ? 'none'
      : [...this._activeFilters].map((f)=>f.getName()).join(',');
    let nrOfEntries = this._filteredTrackList ? this._filteredTrackList.length : 0;
    this._list.setLabel(template.replace('${title}','All tracks (' +  nrOfEntries + ')[filters=' + filters + ']'));

    this._screen.render();
  }

  _update(){
    let trackStyle = this._style.track;
    let allTracks = this._trackList.getTracks();
    this._filteredTrackList = allTracks;

    if (this._activeFilters.size > 0){
      this._filteredTrackList = allTracks.filter((t) => {
        return [...this._activeFilters].filter(f=>f.matches(t)).length > 0;
      });
    }

    let items = this._filteredTrackList.map( (element) => {
      let str = trackStyle
        .replace('${artist}',element.getArtist())
        .replace('${title}',element.getTitle());
      return str;
    } );

    this._list.setItems(items || ['<empty>']);

    this._updateTitle();
  }

}

module.exports = TracksView;<commit_msg>moved "untagged" to the bginning of the filter dialog<commit_after>'use strict';

var blessed = require('blessed');
const logger = require('../util/Logger.js');
const clipboard = require('../util/Clipboard.js');
const CheckboxListDialog = require('./CheckboxListDialog.js');
const MessageDialog = require('./MessageDialog.js');
const tagConfig = require('../util/TagConfig.js');
const Filters = require('./Filters.js');
const util = require('util');
const TagDialog = require('./TagDialog.js');

class TracksView {

  constructor(screen, style, player, playlistManager) {
    this._screen = screen;
    this._style = style;
    this._player = player;
    this._trackList = undefined;
    this._filteredTrackList = undefined;
    this._activeFilters = new Set();
    this._playlistManager = playlistManager;
    let self = this;

    this._list = blessed.list({
      parent: screen,
      tags: true,
      draggable: false,
      top: 0,
      right: 0,
      width: '40%',
      height: `100%-${style.outputView.height}`,
      keys: true,
      vi: true,
      mouse: false,
      border: 'line',
      scrollbar: {
        ch: ' ',
        track: {
          bg: 'cyan'
        },
        style: {
          inverse: true
        }
      },
      style: JSON.parse(JSON.stringify(style.box)), //deep copy style
      search: function (callback) {
        self._prompt.input('{white-fg}Search track:{/white-fg}', '', function (err, value) {
          if (err) return;
          return callback(null, value);
        });
      }
    });
    this._prompt = blessed.prompt({
      parent: screen,
      top: 'center',
      left: 'center',
      height: 'shrink',
      width: 'shrink',
      keys: true,
      vi: true,
      mouse: false,
      tags: true,
      border: 'line',
      hidden: true,
      style: JSON.parse(JSON.stringify(style.box)) //deep copy style
    });

    this._list.on('focus', this.onFocused.bind(this));
    this._list.on('blur', this.onUnFocused.bind(this));
    this._updateTitle();
  }

  showList(list) {
    this._trackList = list;
    this._update();
  }

  show() {
    this._list.focus();
    this._list.enterSelected(0);
    this._list.show();
    this._screen.render();
  }

  hide() {
    this._list.hide();
    this._screen.render();
  }

  focus() {
    this._list.focus();
  }

  onPlay() {
    let track = this._selectedTrack();
    logger.debug('play ' + track.getName());

    this._player.play(this._filteredTrackList, this._list.selected);
  }

  onFocused() {
    this._updateTitle();
    this._screen.key('p', this.onPlay.bind(this));
    this._screen.key('C-c', this.copyToClipboard.bind(this));
    this._screen.key('f', this.filter.bind(this));
    this._screen.key('t', this.tagEntry.bind(this));
    this._screen.key('i', this.showInfo.bind(this));
  }

  onUnFocused() {
    this._updateTitle();
    this._screen.removeKeyAll('p');
    this._screen.removeKeyAll('C-c');
    this._screen.removeKeyAll('f');
    this._screen.removeKeyAll('t');
    this._screen.removeKeyAll('i');
  }

  copyToClipboard() {
    let track = this._selectedTrack();
    if (!track) {
      return; //nothing selected
    }

    logger.verbose('copy ' + track.getName());

    clipboard.set(track, (clipboard, playlist, selectedPlaylistEntry) => {
      playlist.addTrack(clipboard.content(), selectedPlaylistEntry);
    });
  }

  filter() {
    let dialog = new CheckboxListDialog(this._screen, this._style, 'f');
    let availableTags = tagConfig.getQualifiedTags();
    const UNTAGGED_OPTION = '[untagged]';
    availableTags.unshift(UNTAGGED_OPTION);

    let usedTags = [...this._activeFilters].map((filter) => filter.getName());

    dialog.ask('Filter by tags', availableTags, usedTags, (addedElements, removedElements, selectedTags) => {
      if (!selectedTags) {
        return; //user pressed esc
      }

      this._activeFilters.clear();

      selectedTags.forEach((tagName) => {
        this._activeFilters.add(
          tagName === UNTAGGED_OPTION
            ? new Filters.FilterUntagged(UNTAGGED_OPTION)
            : new Filters.FilterByTag(tagName)
        );
      });

      this._update();
    });
  }

  tagEntry() {
    let track = this._selectedTrack();
    if (!track) {
      return; //nothing selected
    }

    let usedTags = track.tagsAsString();

    let dialog = new TagDialog(this._screen, this._style, 't', 'Select tags');
    dialog.ask(usedTags, (addedElements, removedElements) => {
      addedElements.forEach((tagName) => {
        this._playlistManager.addTrackToTag(track, tagName);
      });
      removedElements.forEach((tagName) => {
        this._playlistManager.removeTrackFromTag(track, tagName);
      });
    });
  }

  showInfo() {
    let track = this._selectedTrack();
    if (!track) {
      return; //nothing selected
    }

    let view = new MessageDialog(this._screen, this._style, 'i', 'Info: ' + track.getName(), util.inspect(track._track));
    view.show();
  }

  _selectedTrack() {
    return this._filteredTrackList[this._list.selected];
  }

  _updateTitle() {
    let template = this._list.focused ? this._style.title.focused : this._style.title.unfocused;
    let filters = this._activeFilters.size == 0
      ? 'none'
      : [...this._activeFilters].map((f) => f.getName()).join(',');
    let nrOfEntries = this._filteredTrackList ? this._filteredTrackList.length : 0;
    this._list.setLabel(template.replace('${title}', 'All tracks (' + nrOfEntries + ')[filters=' + filters + ']'));

    this._screen.render();
  }

  _update() {
    let trackStyle = this._style.track;
    let allTracks = this._trackList.getTracks();
    this._filteredTrackList = allTracks;

    if (this._activeFilters.size > 0) {
      this._filteredTrackList = allTracks.filter((t) => {
        return [...this._activeFilters].filter(f => f.matches(t)).length > 0;
      });
    }

    let items = this._filteredTrackList.map((element) => {
      let str = trackStyle
        .replace('${artist}', element.getArtist())
        .replace('${title}', element.getTitle());
      return str;
    });

    this._list.setItems(items || ['<empty>']);

    this._updateTitle();
  }

}

module.exports = TracksView;<|endoftext|>


<commit_before>// www module, served on /

// happner defaults for this module

module.exports.$happner = {
  config: {
    component: {
      startMethod: 'start',
      stopMethod: 'stop',
      schema: {
        exclusive: true,
        methods: {
          'start': {},
          'stop': {},
          'exampleExchangeMethod': {
            alias: 'example' // called from client in client.exchange.www.example()
          }
        }
      },
      web: {
        routes: {
          static: 'static'
        }
      }
    }
  }
}

module.exports.exampleExchangeMethod = function($happn, arg, callback) {

  callback(null, arg.true);

}

module.exports.start = function($happn, callback) {
  // $happn.log.info('Starting www component.');

  var terminal, address, url;

  address = $happn.info.datalayer.address;
  url = 'http://'+address.address+':'+address.port;

  // If present, add 'www' command to terminal.

  if (terminal = $happn.exchange.terminal) {                   // TODO: for various browsers: open in same/existing tab
    terminal.register('www', {                                //
      description: '(osx) Open browser to the www module.',  //
      run: function(args, callback) {                       //
        require('child_process').exec('open ' + url, function(e) {
          callback(e);
        });
      }
    });
  }

  var seq1 = 0;
  setInterval(function() {
    seq1++
    $happn.emit('ping', {seq: seq1});
  }, 100);

  var seq2 = 0;
  setInterval(function() {
    seq2++;
    $happn.emit('wildcard/' + seq2, {seq: seq2});
  }, 100);

  callback(null);
}

module.exports.stop = function($happn, callback) {
  // $happn.log.info('Stopping www component.');
  callback(null);
}

<commit_msg>commit<commit_after>// www module, served on /

// happner defaults for this module

module.exports.$happner = {
  config: {
    component: {
      startMethod: 'start',
      stopMethod: 'stop',
      schema: {
        exclusive: true,
        methods: {
          'start': {},
          'stop': {},
          'exampleExchangeMethod': {
            alias: 'example' // called from client in client.exchange.www.example()
          }
        }
      },
      web: {
        routes: {
          static: 'static'
        }
      },
      events: {
        ping: {},
        'wildcard/*': {}
      },
      data: {
        'storage/*': {}
      }
    }
  }
}

module.exports.exampleExchangeMethod = function($happn, arg, callback) {

  callback(null, arg.true);

}

module.exports.start = function($happn, callback) {
  // $happn.log.info('Starting www component.');

  var terminal, address, url;

  address = $happn.info.datalayer.address;
  url = 'http://'+address.address+':'+address.port;

  // If present, add 'www' command to terminal.

  if (terminal = $happn.exchange.terminal) {                   // TODO: for various browsers: open in same/existing tab
    terminal.register('www', {                                //
      description: '(osx) Open browser to the www module.',  //
      run: function(args, callback) {                       //
        require('child_process').exec('open ' + url, function(e) {
          callback(e);
        });
      }
    });
  }

  var seq1 = 0;
  setInterval(function() {
    seq1++
    $happn.emit('ping', {seq: seq1});
  }, 100);

  var seq2 = 0;
  setInterval(function() {
    seq2++;
    $happn.emit('wildcard/' + seq2, {seq: seq2});
  }, 100);

  callback(null);
}

module.exports.stop = function($happn, callback) {
  // $happn.log.info('Stopping www component.');
  callback(null);
}

<|endoftext|>


<commit_before>/*jslint indent: 2,
         nomen: true,
         maxlen: 80 */
/*global require,
    db,
    assertEqual, assertTrue,
    ArangoCollection */

////////////////////////////////////////////////////////////////////////////////
/// @brief test the index
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler, Lucas Dohmen
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");
var internal = require("internal");
var console = require("console");
var errors = internal.errors;

// -----------------------------------------------------------------------------
// --SECTION--                                                     basic methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: basics
////////////////////////////////////////////////////////////////////////////////

function indexSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._create(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      // we need try...catch here because at least one test drops the collection itself!
      try {
        collection.unload();
        collection.drop();
      }
      catch (err) {
      }
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get indexes
////////////////////////////////////////////////////////////////////////////////

    testGetIndexes : function () {
      var res = collection.getIndexes();

      assertEqual(1, res.length);

      collection.ensureGeoIndex("a");
      collection.ensureGeoIndex("a", "b");

      res = collection.getIndexes();

      assertEqual(3, res.length);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get index
////////////////////////////////////////////////////////////////////////////////

    testIndex : function () {
      var id = collection.ensureGeoIndex("a");

      var idx = collection.index(id.id);
      assertEqual(id.id, idx.id);

      idx = collection.index(id);
      assertEqual(id.id, idx.id);

      idx = internal.db._index(id.id);
      assertEqual(id.id, idx.id);

      idx = internal.db._index(id);
      assertEqual(id.id, idx.id);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief drop index
////////////////////////////////////////////////////////////////////////////////

    testDropIndex : function () {
      var id = collection.ensureGeoIndex("a");
      var res = collection.dropIndex(id.id);
      assertEqual(true, res);

      res = collection.dropIndex(id.id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a");
      res = collection.dropIndex(id);
      assertEqual(true, res);

      res = collection.dropIndex(id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a");
      res = internal.db._dropIndex(id);
      assertEqual(true, res);

      res = internal.db._dropIndex(id);
      assertEqual(false, res);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief drop index by id string
////////////////////////////////////////////////////////////////////////////////

    testDropIndexString : function () {
      // pick up the numeric part (starts after the slash)
      var id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      var res = collection.dropIndex(collection.name() + "/" + id);
      assertEqual(true, res);

      res = collection.dropIndex(collection.name() + "/" + id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      res = collection.dropIndex(parseInt(id, 10));
      assertEqual(true, res);

      res = collection.dropIndex(parseInt(id, 10));
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      res = internal.db._dropIndex(collection.name() + "/" + id);
      assertEqual(true, res);

      res = internal.db._dropIndex(collection.name() + "/" + id);
      assertEqual(false, res);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access a non-existing index
////////////////////////////////////////////////////////////////////////////////

    testGetNonExistingIndexes : function () {
      tests = [ "2444334000000", "9999999999999" ].forEach(function (id) {
        try {
          var idx = collection.index(id);
          fail();
        }
        catch (err) {
          assertEqual(errors.ERROR_ARANGO_INDEX_NOT_FOUND.code, err.errorNum);
        }
      });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access an existing index of an unloaded collection
////////////////////////////////////////////////////////////////////////////////

    testGetIndexUnloaded : function () {
      var idx = collection.ensureHashIndex("test");

      collection.unload();
      internal.wait(4);

      assertEqual(idx.id, collection.index(idx.id).id);
      assertEqual(idx.id, collection.getIndexes()[1].id);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access an existing index of a dropped collection
////////////////////////////////////////////////////////////////////////////////

    testGetIndexDropped : function () {
      var idx = collection.ensureHashIndex("test");

      collection.drop();

      try {
        collection.index(idx.id).id;
        fail();
      }
      catch (e1) {
        assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e1.errorNum);
      }

      try {
        collection.getIndexes();
        fail();
      }
      catch (e2) {
        assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e2.errorNum);
      }
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                        getIndexes
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: return value of getIndexes
////////////////////////////////////////////////////////////////////////////////

function getIndexesSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._create(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      collection.drop();
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get primary
////////////////////////////////////////////////////////////////////////////////

    testGetPrimary : function () {
      var res = collection.getIndexes();

      assertEqual(1, res.length);
      var idx = res[0];

      assertEqual("primary", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "_id" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique1 : function () {
      collection.ensureUniqueConstraint("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique2 : function () {
      collection.ensureUniqueConstraint("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashNonUnique1 : function () {
      collection.ensureHashIndex("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashNonUnique2 : function () {
      collection.ensureHashIndex("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique1 : function () {
      collection.ensureUniqueSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique2 : function () {
      collection.ensureUniqueSkiplist("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistNonUnique1 : function () {
      collection.ensureSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistNonUnique2 : function () {
      collection.ensureSkiplist("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get bitarray index
////////////////////////////////////////////////////////////////////////////////

    testGetBitarray: function () {
      collection.ensureBitarray("value", [ "one", "two", "three" ]);
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("bitarray", idx.type);
      assertEqual(false, idx.unique);
      assertEqual(false, idx["undefined"]);
      assertEqual([ [ "value", [ "one", "two", "three" ] ] ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get fulltext index
////////////////////////////////////////////////////////////////////////////////

    testGetFulltext: function () {
      collection.ensureFulltextIndex("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("fulltext", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                              getIndexes for edges
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: return value of getIndexes for an edge collection
////////////////////////////////////////////////////////////////////////////////

function getIndexesEdgesSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._createEdgeCollection(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      collection.drop();
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get primary
////////////////////////////////////////////////////////////////////////////////

    testGetPrimary : function () {
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[0];

      assertEqual("primary", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "_id" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get edge
////////////////////////////////////////////////////////////////////////////////

    testGetEdge : function () {
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("edge", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "_from", "_to" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique1 : function () {
      collection.ensureUniqueConstraint("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique1 : function () {
      collection.ensureUniqueSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get bitarray index
////////////////////////////////////////////////////////////////////////////////

    testGetBitarray: function () {
      collection.ensureBitarray("value", [ "one", "two", "three" ]);
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("bitarray", idx.type);
      assertEqual(false, idx.unique);
      assertEqual(false, idx["undefined"]);
      assertEqual([ [ "value", [ "one", "two", "three" ] ] ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get fulltext index
////////////////////////////////////////////////////////////////////////////////

    testGetFulltext: function () {
      collection.ensureFulltextIndex("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("fulltext", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////

jsunity.run(indexSuite);
jsunity.run(getIndexesSuite);
jsunity.run(getIndexesEdgesSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:
<commit_msg>do not pollute global namespace<commit_after>/*jslint indent: 2,
         nomen: true,
         maxlen: 80 */
/*global require,
    db,
    assertEqual, assertTrue,
    ArangoCollection */

////////////////////////////////////////////////////////////////////////////////
/// @brief test the index
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler, Lucas Dohmen
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");
var internal = require("internal");
var console = require("console");
var errors = internal.errors;

// -----------------------------------------------------------------------------
// --SECTION--                                                     basic methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: basics
////////////////////////////////////////////////////////////////////////////////

function indexSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._create(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      // we need try...catch here because at least one test drops the collection itself!
      try {
        collection.unload();
        collection.drop();
      }
      catch (err) {
      }
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get indexes
////////////////////////////////////////////////////////////////////////////////

    testGetIndexes : function () {
      var res = collection.getIndexes();

      assertEqual(1, res.length);

      collection.ensureGeoIndex("a");
      collection.ensureGeoIndex("a", "b");

      res = collection.getIndexes();

      assertEqual(3, res.length);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get index
////////////////////////////////////////////////////////////////////////////////

    testIndex : function () {
      var id = collection.ensureGeoIndex("a");

      var idx = collection.index(id.id);
      assertEqual(id.id, idx.id);

      idx = collection.index(id);
      assertEqual(id.id, idx.id);

      idx = internal.db._index(id.id);
      assertEqual(id.id, idx.id);

      idx = internal.db._index(id);
      assertEqual(id.id, idx.id);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief drop index
////////////////////////////////////////////////////////////////////////////////

    testDropIndex : function () {
      var id = collection.ensureGeoIndex("a");
      var res = collection.dropIndex(id.id);
      assertEqual(true, res);

      res = collection.dropIndex(id.id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a");
      res = collection.dropIndex(id);
      assertEqual(true, res);

      res = collection.dropIndex(id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a");
      res = internal.db._dropIndex(id);
      assertEqual(true, res);

      res = internal.db._dropIndex(id);
      assertEqual(false, res);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief drop index by id string
////////////////////////////////////////////////////////////////////////////////

    testDropIndexString : function () {
      // pick up the numeric part (starts after the slash)
      var id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      var res = collection.dropIndex(collection.name() + "/" + id);
      assertEqual(true, res);

      res = collection.dropIndex(collection.name() + "/" + id);
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      res = collection.dropIndex(parseInt(id, 10));
      assertEqual(true, res);

      res = collection.dropIndex(parseInt(id, 10));
      assertEqual(false, res);

      id = collection.ensureGeoIndex("a").id.substr(cn.length + 1);
      res = internal.db._dropIndex(collection.name() + "/" + id);
      assertEqual(true, res);

      res = internal.db._dropIndex(collection.name() + "/" + id);
      assertEqual(false, res);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access a non-existing index
////////////////////////////////////////////////////////////////////////////////

    testGetNonExistingIndexes : function () {
      [ "2444334000000", "9999999999999" ].forEach(function (id) {
        try {
          var idx = collection.index(id);
          fail();
        }
        catch (err) {
          assertEqual(errors.ERROR_ARANGO_INDEX_NOT_FOUND.code, err.errorNum);
        }
      });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access an existing index of an unloaded collection
////////////////////////////////////////////////////////////////////////////////

    testGetIndexUnloaded : function () {
      var idx = collection.ensureHashIndex("test");

      collection.unload();
      internal.wait(4);

      assertEqual(idx.id, collection.index(idx.id).id);
      assertEqual(idx.id, collection.getIndexes()[1].id);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief access an existing index of a dropped collection
////////////////////////////////////////////////////////////////////////////////

    testGetIndexDropped : function () {
      var idx = collection.ensureHashIndex("test");

      collection.drop();

      try {
        collection.index(idx.id).id;
        fail();
      }
      catch (e1) {
        assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e1.errorNum);
      }

      try {
        collection.getIndexes();
        fail();
      }
      catch (e2) {
        assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e2.errorNum);
      }
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                        getIndexes
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: return value of getIndexes
////////////////////////////////////////////////////////////////////////////////

function getIndexesSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._create(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      collection.drop();
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get primary
////////////////////////////////////////////////////////////////////////////////

    testGetPrimary : function () {
      var res = collection.getIndexes();

      assertEqual(1, res.length);
      var idx = res[0];

      assertEqual("primary", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "_id" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique1 : function () {
      collection.ensureUniqueConstraint("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique2 : function () {
      collection.ensureUniqueConstraint("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashNonUnique1 : function () {
      collection.ensureHashIndex("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashNonUnique2 : function () {
      collection.ensureHashIndex("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("hash", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique1 : function () {
      collection.ensureUniqueSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique2 : function () {
      collection.ensureUniqueSkiplist("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistNonUnique1 : function () {
      collection.ensureSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get non-unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistNonUnique2 : function () {
      collection.ensureSkiplist("value1", "value2");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("skiplist", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value1", "value2" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get bitarray index
////////////////////////////////////////////////////////////////////////////////

    testGetBitarray: function () {
      collection.ensureBitarray("value", [ "one", "two", "three" ]);
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("bitarray", idx.type);
      assertEqual(false, idx.unique);
      assertEqual(false, idx["undefined"]);
      assertEqual([ [ "value", [ "one", "two", "three" ] ] ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get fulltext index
////////////////////////////////////////////////////////////////////////////////

    testGetFulltext: function () {
      collection.ensureFulltextIndex("value");
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("fulltext", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                              getIndexes for edges
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: return value of getIndexes for an edge collection
////////////////////////////////////////////////////////////////////////////////

function getIndexesEdgesSuite() {
  var cn = "UnitTestsCollectionIdx";
  var collection = null;

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      internal.db._drop(cn);
      collection = internal.db._createEdgeCollection(cn, { waitForSync : false });
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      collection.drop();
      collection = null;
      internal.wait(0.0);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get primary
////////////////////////////////////////////////////////////////////////////////

    testGetPrimary : function () {
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[0];

      assertEqual("primary", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "_id" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get edge
////////////////////////////////////////////////////////////////////////////////

    testGetEdge : function () {
      var res = collection.getIndexes();

      assertEqual(2, res.length);
      var idx = res[1];

      assertEqual("edge", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "_from", "_to" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique hash index
////////////////////////////////////////////////////////////////////////////////

    testGetHashUnique1 : function () {
      collection.ensureUniqueConstraint("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("hash", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get unique skiplist index
////////////////////////////////////////////////////////////////////////////////

    testGetSkiplistUnique1 : function () {
      collection.ensureUniqueSkiplist("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("skiplist", idx.type);
      assertEqual(true, idx.unique);
      assertEqual([ "value" ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get bitarray index
////////////////////////////////////////////////////////////////////////////////

    testGetBitarray: function () {
      collection.ensureBitarray("value", [ "one", "two", "three" ]);
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("bitarray", idx.type);
      assertEqual(false, idx.unique);
      assertEqual(false, idx["undefined"]);
      assertEqual([ [ "value", [ "one", "two", "three" ] ] ], idx.fields);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test: get fulltext index
////////////////////////////////////////////////////////////////////////////////

    testGetFulltext: function () {
      collection.ensureFulltextIndex("value");
      var res = collection.getIndexes();

      assertEqual(3, res.length);
      var idx = res[2];

      assertEqual("fulltext", idx.type);
      assertEqual(false, idx.unique);
      assertEqual([ "value" ], idx.fields);
    }

  };
}

// -----------------------------------------------------------------------------
// --SECTION--                                                              main
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////

jsunity.run(indexSuite);
jsunity.run(getIndexesSuite);
jsunity.run(getIndexesEdgesSuite);

return jsunity.done();

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { RoutingContext as DefaultRoutingContext } from 'react-router';
import routerStateEquals from './routerStateEquals';
import { ROUTER_STATE_SELECTOR } from './constants';
import { initRoutes, replaceRoutes } from './actionCreators';

function memoizeRouterStateSelector(selector) {
  let previousRouterState = null;

  return state => {
    const nextRouterState = selector(state);
    if (routerStateEquals(previousRouterState, nextRouterState)) {
      return previousRouterState;
    }
    previousRouterState = nextRouterState;
    return nextRouterState;
  };
}

function getRoutesFromProps(props) {
  return props.routes || props.children;
}

class ReduxRouter extends Component {
  static propTypes = {
    children: PropTypes.node
  }

  static contextTypes = {
    store: PropTypes.object
  }

  constructor(props, context) {
    super(props, context);
    context.store.dispatch(initRoutes(getRoutesFromProps(props)));
  }

  componentWillReceiveProps(nextProps) {
    this.receiveRoutes(getRoutesFromProps(nextProps));
  }

  receiveRoutes(routes) {
    if (!routes) return;

    const { store } = this.context;
    store.dispatch(replaceRoutes(routes));
  }

  render() {
    const { store } = this.context;

    if (!store) {
      throw new Error(
        'Redux store missing from context of <ReduxRouter>. Make sure you\'re '
      + 'using a <Provider>'
      );
    }

    const {
      history,
      [ROUTER_STATE_SELECTOR]: routerStateSelector
    } = store;

    if (!history || !routerStateSelector) {
      throw new Error(
        'Redux store not configured properly for <ReduxRouter>. Make sure '
      + 'you\'re using the reduxReactRouter() store enhancer.'
    );
    }

    return (
      <ReduxRouterContext
        history={history}
        routerStateSelector={memoizeRouterStateSelector(routerStateSelector)}
        {...this.props}
      />
    );
  }
}

@connect(
  (state, { routerStateSelector }) => routerStateSelector(state) || {}
)
class ReduxRouterContext extends Component {
  render() {
    const {location} = this.props;

    if (location === null || location === undefined)
      return null; // Async matching

    const RoutingContext = this.props.RoutingContext || DefaultRoutingContext;

    return <RoutingContext {...this.props} />;
  }
}

export default ReduxRouter;
<commit_msg>Fix linter warnings<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { RoutingContext as DefaultRoutingContext } from 'react-router';
import routerStateEquals from './routerStateEquals';
import { ROUTER_STATE_SELECTOR } from './constants';
import { initRoutes, replaceRoutes } from './actionCreators';

function memoizeRouterStateSelector(selector) {
  let previousRouterState = null;

  return state => {
    const nextRouterState = selector(state);
    if (routerStateEquals(previousRouterState, nextRouterState)) {
      return previousRouterState;
    }
    previousRouterState = nextRouterState;
    return nextRouterState;
  };
}

function getRoutesFromProps(props) {
  return props.routes || props.children;
}

class ReduxRouter extends Component {
  static propTypes = {
    children: PropTypes.node
  }

  static contextTypes = {
    store: PropTypes.object
  }

  constructor(props, context) {
    super(props, context);
    context.store.dispatch(initRoutes(getRoutesFromProps(props)));
  }

  componentWillReceiveProps(nextProps) {
    this.receiveRoutes(getRoutesFromProps(nextProps));
  }

  receiveRoutes(routes) {
    if (!routes) return;

    const { store } = this.context;
    store.dispatch(replaceRoutes(routes));
  }

  render() {
    const { store } = this.context;

    if (!store) {
      throw new Error(
        'Redux store missing from context of <ReduxRouter>. Make sure you\'re '
      + 'using a <Provider>'
      );
    }

    const {
      history,
      [ROUTER_STATE_SELECTOR]: routerStateSelector
    } = store;

    if (!history || !routerStateSelector) {
      throw new Error(
        'Redux store not configured properly for <ReduxRouter>. Make sure '
      + 'you\'re using the reduxReactRouter() store enhancer.'
    );
    }

    return (
      <ReduxRouterContext
        history={history}
        routerStateSelector={memoizeRouterStateSelector(routerStateSelector)}
        {...this.props}
      />
    );
  }
}

@connect(
  (state, { routerStateSelector }) => routerStateSelector(state) || {}
)
class ReduxRouterContext extends Component {
  static propTypes = {
    location: PropTypes.object,
    RoutingContext: PropTypes.element,
  }

  render() {
    const {location} = this.props;

    if (location === null || location === undefined) {
      return null; // Async matching
    }

    const RoutingContext = this.props.RoutingContext || DefaultRoutingContext;

    return <RoutingContext {...this.props} />;
  }
}

export default ReduxRouter;
<|endoftext|>


<commit_before>import {createStore} from 'redux';
import {DependencyError} from './errors';

/**
 * @class ModuleManager
 * @category core
 * @param {Object} object handler
 * @description  Solves modules dependencies
 * @memberof module:core
 */
export class ModuleManager {
  constructor(object) {
    this.handler = object;
    this.currentModule = null;

    this.store = createStore((state = [{}, ''], action) => {
      state[0][action.key] = action.data;
      state[1] = action.key;

      return state;
    });

    this.modules = {};
  }

  /**
   * @method active
   * @instance
   * @description Sets .currentModule to provided module.
   * @param {Object} module the module to make current
   * @memberof module:core.ModuleManager
   */
  active(module) {
    this.currentModule = module;
  }

  /**
   * @method reset
   * @instance
   * @description Set's .currentModule to null.
   * @memberof module:core.ModuleManager
   */
  reset() {
    this.currentModule = null;
  }

  /**
   * @method define
   * @instance
   * @description Define the module in manager
   * @param name The module name
   * @memberof module:core.ModuleManager
   */
  define(name) {
    this.modules[name] = this.currentModule;
  }

  /**
   * @method use
   * @instance
   * @description Get the defined module from manager
   * @param name The module name
   * @memberof module:core.ModuleManager
   */
  use(name) {
    return this.modules[name];
  }

  /**
   * @method set
   * @instance
   * @description An alias for .add()

   * Use this method if you know that you will overwrite existing dependency.

   * Use it in your app, but not in module that you provide to other people.
   * @param {String} key the key of the dependency
   * @param {Object} data the value of the dependency
   * @memberof module:core.ModuleManager
   */
  set(key, data) {
    this.store.dispatch({
      type: 'ADD',
      key,
      data
    });
  }

  /**
   * @method get
   * @instance
   * @description Returns dependency in store object, by key.
   * @param {String} key the key of the dependency
   * @memberof module:core.ModuleManager
   * @return {Object|Module}
   * @throws {DependencyError} if dependency is not in the store
   * @example
Get the 'hello' dependency

   * manager.get('hello'); // -> {world: true}
   */
  get(key) {
    if (!this.store.getState()[0][key]) {
      throw new DependencyError(
        'ModuleManager',
        `Module requires '${key}' dependency`,
        this.currentModule
      );
    }

    return this.store.getState()[0][key];
  }

  /**
   * @method has
   * @instance
   * @description Returns whether manager has a dependency with the given key
   * @param {String} key the key of the dependency
   * @memberof module:core.ModuleManager
   * @return {Boolean} Promise that is resolved when all promises completed.
   * @example
Check whether the store has the 'hello' dependency

   * manager.has('hello'); // -> true
   */
  has(key) {
    return Boolean(this.store.getState()[0][key]);
  }

  /**
   * @method update
   * @instance
   * @description Updates deps
   * @param {Object} [depsMap={}]
   * @memberof module:core.ModuleManager
   */
  update(depsMap = {}) {
    this.store.subscribe(() => {
      const [data, changedKey] = this.store.getState();
      const callback = depsMap[changedKey];

      if (callback) callback(data[changedKey]);
    });
  }

  /**
   * @method add
   * @alias module:core.ModuleManager#set
   */
  add(...data) {
    console.warn('.add() method is deprecated. Use .set() instead');
    return this.set(...data);
  }

  require(name, moduleExecutor) {
    if (this.use(name) === undefined) this.handler.applyModule(moduleExecutor());
  }
}
<commit_msg>Document manager.require<commit_after>import {createStore} from 'redux';
import {DependencyError} from './errors';

/**
 * @class ModuleManager
 * @category core
 * @param {Object} object handler
 * @description  Solves modules dependencies
 * @memberof module:core
 */
export class ModuleManager {
  constructor(object) {
    this.handler = object;
    this.currentModule = null;

    this.store = createStore((state = [{}, ''], action) => {
      state[0][action.key] = action.data;
      state[1] = action.key;

      return state;
    });

    this.modules = {};
  }

  /**
   * @method active
   * @instance
   * @description Sets .currentModule to provided module.
   * @param {Object} module the module to make current
   * @memberof module:core.ModuleManager
   */
  active(module) {
    this.currentModule = module;
  }

  /**
   * @method reset
   * @instance
   * @description Set's .currentModule to null.
   * @memberof module:core.ModuleManager
   */
  reset() {
    this.currentModule = null;
  }

  /**
   * @method define
   * @instance
   * @description Define the module in manager
   * @param name The module name
   * @memberof module:core.ModuleManager
   */
  define(name) {
    this.modules[name] = this.currentModule;
  }

  /**
   * @method use
   * @instance
   * @description Get the defined module from manager
   * @param name The module name
   * @memberof module:core.ModuleManager
   */
  use(name) {
    return this.modules[name];
  }

  /**
   * @method set
   * @instance
   * @description An alias for .add()

   * Use this method if you know that you will overwrite existing dependency.

   * Use it in your app, but not in module that you provide to other people.
   * @param {String} key the key of the dependency
   * @param {Object} data the value of the dependency
   * @memberof module:core.ModuleManager
   */
  set(key, data) {
    this.store.dispatch({
      type: 'ADD',
      key,
      data
    });
  }

  /**
   * @method get
   * @instance
   * @description Returns dependency in store object, by key.
   * @param {String} key the key of the dependency
   * @memberof module:core.ModuleManager
   * @return {Object|Module}
   * @throws {DependencyError} if dependency is not in the store
   * @example
Get the 'hello' dependency

   * manager.get('hello'); // -> {world: true}
   */
  get(key) {
    if (!this.store.getState()[0][key]) {
      throw new DependencyError(
        'ModuleManager',
        `Module requires '${key}' dependency`,
        this.currentModule
      );
    }

    return this.store.getState()[0][key];
  }

  /**
   * @method has
   * @instance
   * @description Returns whether manager has a dependency with the given key
   * @param {String} key the key of the dependency
   * @memberof module:core.ModuleManager
   * @return {Boolean} Promise that is resolved when all promises completed.
   * @example
Check whether the store has the 'hello' dependency

   * manager.has('hello'); // -> true
   */
  has(key) {
    return Boolean(this.store.getState()[0][key]);
  }

  /**
   * @method update
   * @instance
   * @description Updates deps
   * @param {Object} [depsMap={}]
   * @memberof module:core.ModuleManager
   */
  update(depsMap = {}) {
    this.store.subscribe(() => {
      const [data, changedKey] = this.store.getState();
      const callback = depsMap[changedKey];

      if (callback) callback(data[changedKey]);
    });
  }

  /**
   * @method add
   * @alias module:core.ModuleManager#set
   * @memberof module:core.ModuleManager
   */
  add(...data) {
    console.warn('.add() method is deprecated. Use .set() instead');
    return this.set(...data);
  }

  /**
   * @method require
   * @instance
   * @description Require module
   * @param {String} name Defined name
   * @param {Function} moduleExecutor Function that returns applied module
   * @memberof module:core.ModuleManager
   */
  require(name, moduleExecutor) {
    if (this.use(name) === undefined) this.handler.applyModule(moduleExecutor());
  }
}
<|endoftext|>


<commit_before>define(["js/core/Component", "js/html/HtmlElement"], function (Component, HtmlElement) {

    return Component.inherit('js.core.Component', {

        defaults: {
            /**
             * The duration in seconds
             *
             * @type Number
             */
            duration: 3,
            /**
             * The css class for the container, which contains the notifications
             *
             * @type String
             */
            containerClass: "notifications"
        },

        ctor: function () {
            this.$notifications = [];

            this.callBase();
        },
        /**
         * Shows a notification with the given template.
         * The templates need to be defined in the NotificationManager instance via XAML.
         *
         * @param {String} templateName - the name of the Template for the Notification
         * @param {Object} [attributes] - attributes for the template
         * @param {Object} [options] - options for
         * @returns {js.core.DomElement} - the created notification instance
         */
        showNotification: function (templateName, attributes, options) {
            if (!this.$container) {
                this.$container = this.createComponent(HtmlElement, {"class": this.$.containerClass, tagName: "div"});
                this.$stage.addChild(this.$container);
            }

            if (!this.$templates[templateName]) {
                console.warn("Couldn't find template " + templateName);
                return null;
            }

            options = options || {};

            var duration = options.duration || this.$.duration;

            var notification = this.$templates[templateName].createInstance(attributes || {});

            notification.bind('remove:dom', function () {
                notification.destroy();
            });

            this.$container.addChild(notification);

            var self = this;
            notification.close = function () {
                self.closeNotification(this);
            };
            this.$notifications.push(notification);

            setTimeout(function () {
                self.closeNotification(notification);
            }, duration * 1000);

            return notification;
        },
        /**
         * Closes a notification instance.
         *
         * @param {js.core.DomElement} notification - the instance returned by showNotification
         */
        closeNotification: function (notification) {
            this.$notifications.splice(this.$notifications.indexOf(notification), 1);
            this.$container.removeChild(notification);
        }

    });
});<commit_msg>fixed Notification fqClassName<commit_after>define(["js/core/Component", "js/html/HtmlElement"], function (Component, HtmlElement) {

    return Component.inherit('js.core.NotificationManager', {

        defaults: {
            /**
             * The duration in seconds
             *
             * @type Number
             */
            duration: 3,
            /**
             * The css class for the container, which contains the notifications
             *
             * @type String
             */
            containerClass: "notifications"
        },

        ctor: function () {
            this.$notifications = [];

            this.callBase();
        },
        /**
         * Shows a notification with the given template.
         * The templates need to be defined in the NotificationManager instance via XAML.
         *
         * @param {String} templateName - the name of the Template for the Notification
         * @param {Object} [attributes] - attributes for the template
         * @param {Object} [options] - options for
         * @returns {js.core.DomElement} - the created notification instance
         */
        showNotification: function (templateName, attributes, options) {
            if (!this.$container) {
                this.$container = this.createComponent(HtmlElement, {"class": this.$.containerClass, tagName: "div"});
                this.$stage.addChild(this.$container);
            }

            if (!this.$templates[templateName]) {
                console.warn("Couldn't find template " + templateName);
                return null;
            }

            options = options || {};

            var duration = options.duration || this.$.duration;

            var notification = this.$templates[templateName].createInstance(attributes || {});

            notification.bind('remove:dom', function () {
                notification.destroy();
            });

            this.$container.addChild(notification);

            var self = this;
            notification.close = function () {
                self.closeNotification(this);
            };
            this.$notifications.push(notification);

            setTimeout(function () {
                self.closeNotification(notification);
            }, duration * 1000);

            return notification;
        },
        /**
         * Closes a notification instance.
         *
         * @param {js.core.DomElement} notification - the instance returned by showNotification
         */
        closeNotification: function (notification) {
            this.$notifications.splice(this.$notifications.indexOf(notification), 1);
            this.$container.removeChild(notification);
        }

    });
});<|endoftext|>