<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @fileoverview Provides tools for loading an HTML import file into D8.
 */
(function(global) {
  var isNode = global.process && global.process.versions.node;

  var fs;
  if (isNode)
    fs = require('fs');

  var pathUtils = undefined;
  function setPathUtils(newPathUtils) {
    if (pathUtils !== undefined)
      throw new Error('Already set');
    pathUtils = newPathUtils;
  }

  function readFileContents(fileName) {
    if (!isNode)
      return read(fileName);
    return fs.readFileSync(fileName, 'utf8');
  }

  /**
   * Strips the starting '/' in file_path if |file_path| is meant to be a
   * relative path.
   *
   * @param {string} file_path path to some file, can be relative or absolute
   * path.
   * @return {string} the file_path with starting '/' removed if |file_path|
   * does not exist or the original |file_path| otherwise.
   */
  function _stripStartingSlashIfNeeded(file_path) {
    if (file_path.substring(0, 1) !== '/') {
      return file_path;
    }
    if (pathUtils.exists(file_path))
      return file_path;
    return file_path.substring(1);
  }

  var sourcePaths = [];

  function addArrayToSourcePath(paths) {
    for (var i = 0; i < paths.length; i++) {
      if (sourcePaths.indexOf(paths[i]) !== -1)
        continue;
      sourcePaths.push(paths[i]);
    }
  }

  function hrefToAbsolutePath(href) {
    var pathPart;
    if (!pathUtils.isAbs(href)) {
      throw new Error('Found a non absolute import and thats not supported: ' +
                      href);
    } else {
      pathPart = href.substring(1);
    }

    var candidates = [];
    for (var i = 0; i < sourcePaths.length; i++) {
      var candidate = pathUtils.join(sourcePaths[i], pathPart);
      if (pathUtils.exists(candidate))
        candidates.push(candidate);
    }
    if (candidates.length > 1) {
      throw new Error('Multiple candidates found for ' + href + ': ' +
          candidates + '\nSource paths:\n' + sourcePaths.join(',\n'));
    }
    if (candidates.length === 0) {
      throw new Error(href + ' not found!' +
          '\nSource paths:\n' + sourcePaths.join(',\n'));
    }
    return candidates[0];
  }

  var loadedModulesByFilePath = {};

  /**
   * Load a HTML file, which absolute path or path relative to <%search-path%>.
   * Unlike the native load() method of d8, variables declared in |file_path|
   * will not be hoisted to the caller environment. For example:
   *
   * a.html:
   * <script>
   *   var x = 1;
   * </script>
   *
   * test.js:
   * loadHTML("a.html");
   * print(x);  // <- ReferenceError is thrown because x is not defined.
   *
   * @param {string} file_path path to the HTML file to be loaded.
   */
  function loadHTML(href) {
    var absPath = hrefToAbsolutePath(href);
    loadHTMLFile.call(global, absPath, href);
  };

  function loadScript(href) {
    var absPath = hrefToAbsolutePath(href);
    loadFile.call(global, absPath, href);
  };

  function loadHTMLFile(absPath, opt_href) {
    var href = opt_href || absPath;
    if (loadedModulesByFilePath[absPath])
      return;
    loadedModulesByFilePath[absPath] = true;
    try {
      var html_content = readFileContents(absPath);
    } catch (err) {
      throw new Error('Error in loading html file ' + href +
          ': File does not exist');
    }

    try {
      var stripped_js = generateJsFromHTML(html_content);
    } catch (err) {
      throw new Error('Error in loading html file ' + href + ': ' + err);
    }

    // If there is blank line at the beginning of generated js, we add
    // "//@ sourceURL=|file_path|" to the beginning of generated source so
    // the stack trace show the source file even in case of syntax error.
    // If not, we add it to the end of generated source to preserve the line
    // number.
    if (stripped_js.startsWith('\n')) {
      stripped_js = '//@ sourceURL=' + href + stripped_js;
    } else {
      stripped_js = stripped_js + '\n//@ sourceURL=' + href;
    }
    eval(stripped_js);
  };

  function loadFile(absPath, opt_href) {
    var href = opt_href || absPath;
    var relPath = pathUtils.relPath(absPath);
    try {
      if (!isNode) {
        load(relPath);
      } else {
        var contents = readFileContents(relPath);
        eval(contents);
      }
    } catch (err) {
      throw new Error('Error in loading script file ' + href + ': ' + err);
    }
  };

  global.HTMLImportsLoader = {
    setPathUtils: setPathUtils,
    sourcePaths: sourcePaths,
    addArrayToSourcePath: addArrayToSourcePath,
    hrefToAbsolutePath: hrefToAbsolutePath,
    loadHTML: loadHTML,
    loadScript: loadScript,
    loadHTMLFile: loadHTMLFile,
    loadFile: loadFile
  };
})(this);<commit_msg>[vinn] Switch loadScript to use abs path when running under d8<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @fileoverview Provides tools for loading an HTML import file into D8.
 */
(function(global) {
  var isNode = global.process && global.process.versions.node;

  var fs;
  if (isNode)
    fs = require('fs');

  var pathUtils = undefined;
  function setPathUtils(newPathUtils) {
    if (pathUtils !== undefined)
      throw new Error('Already set');
    pathUtils = newPathUtils;
  }

  function readFileContents(fileName) {
    if (!isNode)
      return read(fileName);
    return fs.readFileSync(fileName, 'utf8');
  }

  /**
   * Strips the starting '/' in file_path if |file_path| is meant to be a
   * relative path.
   *
   * @param {string} file_path path to some file, can be relative or absolute
   * path.
   * @return {string} the file_path with starting '/' removed if |file_path|
   * does not exist or the original |file_path| otherwise.
   */
  function _stripStartingSlashIfNeeded(file_path) {
    if (file_path.substring(0, 1) !== '/') {
      return file_path;
    }
    if (pathUtils.exists(file_path))
      return file_path;
    return file_path.substring(1);
  }

  var sourcePaths = [];

  function addArrayToSourcePath(paths) {
    for (var i = 0; i < paths.length; i++) {
      if (sourcePaths.indexOf(paths[i]) !== -1)
        continue;
      sourcePaths.push(paths[i]);
    }
  }

  function hrefToAbsolutePath(href) {
    var pathPart;
    if (!pathUtils.isAbs(href)) {
      throw new Error('Found a non absolute import and thats not supported: ' +
                      href);
    } else {
      pathPart = href.substring(1);
    }

    var candidates = [];
    for (var i = 0; i < sourcePaths.length; i++) {
      var candidate = pathUtils.join(sourcePaths[i], pathPart);
      if (pathUtils.exists(candidate))
        candidates.push(candidate);
    }
    if (candidates.length > 1) {
      throw new Error('Multiple candidates found for ' + href + ': ' +
          candidates + '\nSource paths:\n' + sourcePaths.join(',\n'));
    }
    if (candidates.length === 0) {
      throw new Error(href + ' not found!' +
          '\nSource paths:\n' + sourcePaths.join(',\n'));
    }
    return candidates[0];
  }

  var loadedModulesByFilePath = {};

  /**
   * Load a HTML file, which absolute path or path relative to <%search-path%>.
   * Unlike the native load() method of d8, variables declared in |file_path|
   * will not be hoisted to the caller environment. For example:
   *
   * a.html:
   * <script>
   *   var x = 1;
   * </script>
   *
   * test.js:
   * loadHTML("a.html");
   * print(x);  // <- ReferenceError is thrown because x is not defined.
   *
   * @param {string} file_path path to the HTML file to be loaded.
   */
  function loadHTML(href) {
    var absPath = hrefToAbsolutePath(href);
    loadHTMLFile.call(global, absPath, href);
  };

  function loadScript(href) {
    var absPath = hrefToAbsolutePath(href);
    loadFile.call(global, absPath, href);
  };

  function loadHTMLFile(absPath, opt_href) {
    var href = opt_href || absPath;
    if (loadedModulesByFilePath[absPath])
      return;
    loadedModulesByFilePath[absPath] = true;
    try {
      var html_content = readFileContents(absPath);
    } catch (err) {
      throw new Error('Error in loading html file ' + href +
          ': File does not exist');
    }

    try {
      var stripped_js = generateJsFromHTML(html_content);
    } catch (err) {
      throw new Error('Error in loading html file ' + href + ': ' + err);
    }

    // If there is blank line at the beginning of generated js, we add
    // "//@ sourceURL=|file_path|" to the beginning of generated source so
    // the stack trace show the source file even in case of syntax error.
    // If not, we add it to the end of generated source to preserve the line
    // number.
    if (stripped_js.startsWith('\n')) {
      stripped_js = '//@ sourceURL=' + href + stripped_js;
    } else {
      stripped_js = stripped_js + '\n//@ sourceURL=' + href;
    }
    eval(stripped_js);
  };

  function loadFile(absPath, opt_href) {
    var href = opt_href || absPath;
    try {
      if (!isNode) {
        load(absPath);
      } else {
        var relPath = pathUtils.relPath(absPath);
        var contents = readFileContents(relPath);
        eval(contents);
      }
    } catch (err) {
      throw new Error('Error in loading script file ' + href + ': ' + err);
    }
  };

  global.HTMLImportsLoader = {
    setPathUtils: setPathUtils,
    sourcePaths: sourcePaths,
    addArrayToSourcePath: addArrayToSourcePath,
    hrefToAbsolutePath: hrefToAbsolutePath,
    loadHTML: loadHTML,
    loadScript: loadScript,
    loadHTMLFile: loadHTMLFile,
    loadFile: loadFile
  };
})(this);
<|endoftext|>


<commit_before>'use strict';

import React, {
  Component,
  Dimensions,
  Image,
  StyleSheet,
  Text,
  ToolbarAndroid,
  TouchableOpacity,
  View,
} from 'react-native';

import { Surface } from 'gl-react-native';
var ImagePickerManager = require('NativeModules').ImagePickerManager;

import PostDetails from './post-details';
import Saturation from '../components/saturation';
import Vignette from '../components/vignette';
import Instagram from '../components/instagram';

var length = Dimensions.get('window').width;

class Camera extends Component {
  constructor(props) {
    super(props);
    this.state = {
      avatarSource: null,
      test: 'help',
      length: length,
      filter: null
    };
  }

  openCamera() {
    ImagePickerManager.showImagePicker(options, (response) => {
      console.log('Response = ', response);

      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePickerManager Error: ', response.error);
      } else {
        // You can display the image using either data:
        const source = {uri: 'data:image/jpeg;base64,' + response.data, isStatic: true};
        this.setState({
          avatarSource: source
        });
      }
    });
  }

  renderImage() {
    var filter;
    switch (this.state.filter) {
      case "sat":
        filter = this.monoImage();
        break;
      case "vign":
        filter = this.vignetteImage();
        break;
      case "hefe":
        filter = this.hefeImage();
        break;
      default:
        filter = this.ogImage();
        break;
    }
    return (
      <View>
        <ToolbarAndroid
          title = 'Create a Post'
          style = {styles.toolbar}
          actions = {[
            {title: 'Details', show: 'always'},
            {title: 'Camera', show: 'always'}
          ]}
          onActionSelected = {this.onActionSelected.bind(this)}
        />

        <Surface width = {this.state.length} height = {this.state.length} >
        {filter}
        </Surface>

        <View style = {{flex: 1, flexDirection: 'row', flexWrap: 'wrap' }}>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Original
        </Text>

        <TouchableOpacity onPress ={()=> this.setState({filter: null})} style = {{flex: 1}}>
          <Surface width = {40} height = {40}>
            {this.ogImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Monochrome
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'sat'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.monoImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Vignette
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'vign'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.vignetteImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Hefe
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'hefe'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.hefeImage()}
          </Surface>
        </TouchableOpacity>

        </View>
        </View>

    );
  }

  ogImage() {
    return(
      <Image source = {this.state.avatarSource}
      style = {{flex: 1}}/>
    );
  }

  monoImage() {
    return(<Saturation
      factor = {0}
      image = {this.state.avatarSource}
      style = {{flex: 1}}
    />);
  }

  vignetteImage() {
    var secondSource = this.state.avatarSource;
    return (<Vignette
      time = {0.2}
      texture = {secondSource}
      style = {{flex: 1}}
    />
    );
  }
  hefeImage() {
    var thirdSource = this.state.avatarSource;
    return (<Instagram
      brightness = {1}
      saturation = {1}
      contrast = {1}
      hue = {0}
      sepia = {1}
      gray = {0}
      mixFactor = {0}
      tex = {thirdSource}
      />
    );
  }
  renderBars() {
    return(
      <View>
        <ToolbarAndroid
          title = 'Create a Post'
          style = {styles.toolbar}
          actions ={[
            {title: 'Details', show: 'always'},
            {title: 'Camera', show: 'always'}
          ]}

          onActionSelected = {this.onActionSelected.bind(this)}
        />
      </View>
    );
  }

  onActionSelected(position) {
    if (position == 0) {
      this.props.navigator.push({component: PostDetails});
    } else if (position == 1) {
      this.openCamera();
    }
  }

  render() {
    if ( this.state.avatarSource)
      {return this.renderImage();}
    else
      {return this.renderBars();}
  }

}

const styles = StyleSheet.create({
  toolbar: {
    height: 56,
    backgroundColor: '#4682b4',
  }
});

var options = {
  title: 'Select Avatar', // specify null or empty string to remove the title
  cancelButtonTitle: 'Cancel',
  takePhotoButtonTitle: 'Take Photo...', // specify null or empty string to remove this button
  chooseFromLibraryButtonTitle: 'Choose from Library...', // specify null or empty string to remove this button
  cameraType: 'back', // 'front' or 'back'
  mediaType: 'photo', // 'photo' or 'video'
  videoQuality: 'high', // 'low', 'medium', or 'high'
  durationLimit: 10, // video recording max time in seconds
  maxWidth: 370, // photos only
  maxHeight: 370, // photos only
  aspectX: 2, // android only - aspectX:aspectY, the cropping image's ratio of width to height
  aspectY: 1, // android only - aspectX:aspectY, the cropping image's ratio of width to height
  quality: 1, // 0 to 1, photos only
  angle: 0, // android only, photos only
  allowsEditing: false, // Built in functionality to resize, reposition the image after selection
  noData: false, // photos only - disables the base64 `data` field from being generated (greatly improves performance on large photos)
};

module.exports = Camera;
<commit_msg>added instagram functions, but camera won't open<commit_after>'use strict';

import React, {
  Component,
  Dimensions,
  Image,
  StyleSheet,
  Text,
  ToolbarAndroid,
  TouchableOpacity,
  View,
} from 'react-native';

import { Surface } from 'gl-react-native';
var ImagePickerManager = require('NativeModules').ImagePickerManager;

import PostDetails from './post-details';
import Saturation from '../components/saturation';
import Vignette from '../components/vignette';
import Instagram from '../components/instagram';

var length = Dimensions.get('window').width;

class Camera extends Component {
  constructor(props) {
    super(props);
    this.state = {
      avatarSource: null,
      test: 'help',
      length: length,
      filter: null
    };
  }

  openCamera() {
    ImagePickerManager.showImagePicker(options, (response) => {
      console.log('Response = ', response);

      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePickerManager Error: ', response.error);
      } else {
        // You can display the image using either data:
        const source = {uri: 'data:image/jpeg;base64,' + response.data, isStatic: true};
        this.setState({
          avatarSource: source
        });
      }
    });
  }

  renderImage() {
    var filter;
    switch (this.state.filter) {
      case "sat":
        filter = this.monoImage();
        break;
      case "vign":
        filter = this.vignetteImage();
        break;
      case "ig":
        filter = this.igImage();
        break;
      default:
        filter = this.ogImage();
        break;
    }
    return (
      <View>
        <ToolbarAndroid
          title = 'Create a Post'
          style = {styles.toolbar}
          actions = {[
            {title: 'Details', show: 'always'},
            {title: 'Camera', show: 'always'}
          ]}
          onActionSelected = {this.onActionSelected.bind(this)}
        />

        <Surface width = {this.state.length} height = {this.state.length} >
        {filter}
        </Surface>

        <View style = {{flex: 1, flexDirection: 'row', flexWrap: 'wrap' }}>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Original
        </Text>

        <TouchableOpacity onPress ={()=> this.setState({filter: null})} style = {{flex: 1}}>
          <Surface width = {40} height = {40}>
            {this.ogImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Monochrome
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'sat'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.monoImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Vignette
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'vign'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.vignetteImage()}
          </Surface>
        </TouchableOpacity>

        <Text
          style = {{color: 'black', marginTop: 10, flex: 1}}>
          Anything Goes
        </Text>

        <TouchableOpacity onPress = {()=> this.setState({filter: 'ig'})} style = {{flex: 1}}>
          <Surface width = {40} height = {40} >
            {this.igImage()}
          </Surface>
        </TouchableOpacity>

        </View>
        </View>

    );
  }

  ogImage() {
    return(
      <Image source = {this.state.avatarSource}
      style = {{flex: 1}}/>
    );
  }

  monoImage() {
    return(<Saturation
      factor = {0}
      image = {this.state.avatarSource}
      style = {{flex: 1}}
    />);
  }

  vignetteImage() {
    var secondSource = this.state.avatarSource;
    return (<Vignette
      time = {0.2}
      texture = {secondSource}
      style = {{flex: 1}}
    />
    );
  }

  igImage() {
    var thirdSource = this.state.avatarSource;
    return (<Instagram
      brightness = {1}
      saturation = {1}
      contrast = {1}
      hue = {0}
      sepia = {1}
      gray = {0}
      mixFactor = {0}
      tex = {thirdSource}
      />
    );
  }
  renderBars() {
    return(
      <View>
        <ToolbarAndroid
          title = 'Create a Post'
          style = {styles.toolbar}
          actions ={[
            {title: 'Details', show: 'always'},
            {title: 'Camera', show: 'always'}
          ]}

          onActionSelected = {this.onActionSelected.bind(this)}
        />
      </View>
    );
  }

  onActionSelected(position) {
    if (position == 0) {
      this.props.navigator.push({component: PostDetails});
    } else if (position == 1) {
      this.openCamera();
    }
  }

  render() {
    if ( this.state.avatarSource)
      {return this.renderImage();}
    else
      {return this.renderBars();}
  }

}

const styles = StyleSheet.create({
  toolbar: {
    height: 56,
    backgroundColor: '#4682b4',
  }
});

var options = {
  title: 'Select Avatar', // specify null or empty string to remove the title
  cancelButtonTitle: 'Cancel',
  takePhotoButtonTitle: 'Take Photo...', // specify null or empty string to remove this button
  chooseFromLibraryButtonTitle: 'Choose from Library...', // specify null or empty string to remove this button
  cameraType: 'back', // 'front' or 'back'
  mediaType: 'photo', // 'photo' or 'video'
  videoQuality: 'high', // 'low', 'medium', or 'high'
  durationLimit: 10, // video recording max time in seconds
  maxWidth: 370, // photos only
  maxHeight: 370, // photos only
  aspectX: 2, // android only - aspectX:aspectY, the cropping image's ratio of width to height
  aspectY: 1, // android only - aspectX:aspectY, the cropping image's ratio of width to height
  quality: 1, // 0 to 1, photos only
  angle: 0, // android only, photos only
  allowsEditing: false, // Built in functionality to resize, reposition the image after selection
  noData: false, // photos only - disables the base64 `data` field from being generated (greatly improves performance on large photos)
};

module.exports = Camera;
<|endoftext|>


<commit_before>import moment from 'moment';

export class WeekCalcer {
  constructor(matches, currentWeek, includeFreeMatches = false) {
    this.includeFreeMatches = includeFreeMatches;
    this.matches = matches.sort((a, b) => a.date - b.date);
    this.setCurrentWeeks(currentWeek);
  }

  getMatches() {
    const week = this.getWeek();
    // TODO: the includeFreeMatches is broken because this.weeks needs a weekSorta and weekVttl prop...
    const matchFilter = match => match.date.isBetween(week.start, week.end) || (this.includeFreeMatches && match.week === this.currentWeek);
    return this.matches.filter(matchFilter);
  }

  getWeek() {
    return this.weeks[this.currentWeek - 1];
  }

  setCurrentWeeks(currentWeek) {
    this.currentWeek = currentWeek;
    if (!this.matches.size) {
      this.firstWeek = 1;
      this.currentWeek = 1;
      this.lastWeek = 22;
      this.weeks = [{start: moment().startOf('week'), end: moment().endOf('week')}];
      return;
    }
    this.weeks = this.matches.reduce((acc, next) => {
      const date = next.date.clone().startOf('week');
      if (!acc.length || !acc[acc.length -1].start.isSame(date, 'day')) {
        acc.push({start: date, end: next.date.clone().endOf('week')});
      }
      return acc;
    }, []);

    //console.log('weekz', this.weeks.map(x => x.start.toString() + " -> " + x.end.toString()));

    this.firstWeek = 1;
    this.lastWeek = this.weeks.length;

    if (!this.currentWeek) {
      let testWeek = moment().startOf('week');
      const indexFinder = w => w.start.isSame(testWeek, 'day');
      while (!this.currentWeek) {
        this.currentWeek = this.weeks.findIndex(indexFinder) + 1;
        testWeek = testWeek.add(1, 'week');
        if (testWeek.isAfter(this.weeks[this.weeks.length - 1].end)) {
          this.currentWeek = this.lastWeek;
          break;
        }
      }
    }
  }
}
<commit_msg>MatchesWeek: edit mode bugfix<commit_after>import moment from 'moment';

export class WeekCalcer {
  constructor(matches, currentWeek, includeFreeMatches = false) {
    this.includeFreeMatches = includeFreeMatches;
    this.matches = matches.sort((a, b) => a.date - b.date);
    this.setCurrentWeeks(currentWeek);
  }

  getMatches() {
    const week = this.getWeek();
    // TODO: the includeFreeMatches is broken because this.weeks needs a weekSorta and weekVttl prop...
    // const matchFilter = match => match.date.isBetween(week.start, week.end) || (this.includeFreeMatches && match.week === this.currentWeek);
    const matchFilter = match => match.date.isBetween(week.start, week.end);
    return this.matches.filter(matchFilter);
  }

  getWeek() {
    return this.weeks[this.currentWeek - 1];
  }

  setCurrentWeeks(currentWeek) {
    this.currentWeek = currentWeek;
    if (!this.matches.size) {
      this.firstWeek = 1;
      this.currentWeek = 1;
      this.lastWeek = 22;
      this.weeks = [{start: moment().startOf('week'), end: moment().endOf('week')}];
      return;
    }
    this.weeks = this.matches.reduce((acc, next) => {
      const date = next.date.clone().startOf('week');
      if (!acc.length || !acc[acc.length -1].start.isSame(date, 'day')) {
        acc.push({start: date, end: next.date.clone().endOf('week')});
      }
      return acc;
    }, []);

    //console.log('weekz', this.weeks.map(x => x.start.toString() + " -> " + x.end.toString()));

    this.firstWeek = 1;
    this.lastWeek = this.weeks.length;

    if (!this.currentWeek) {
      let testWeek = moment().startOf('week');
      const indexFinder = w => w.start.isSame(testWeek, 'day');
      while (!this.currentWeek) {
        this.currentWeek = this.weeks.findIndex(indexFinder) + 1;
        testWeek = testWeek.add(1, 'week');
        if (testWeek.isAfter(this.weeks[this.weeks.length - 1].end)) {
          this.currentWeek = this.lastWeek;
          break;
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>define(function() {

	'use strict';

	var MIN_GAP = 500;

	function PiecemealDownload(url, ranges) {
		this.url = url;
		for (var i = ranges.length-2; i >= 0; i--) {
			if (isNaN(ranges[i].length)) {
				ranges.splice(i + 1, ranges.length - (i + 1));
			}
			else {
				if (ranges[i].offset <= ranges[i + 1].offset
						&& (ranges[i].offset + ranges[i].length + MIN_GAP) >= ranges[i + 1].offset) {
					if (isNaN(ranges[i + 1].length)) {
						delete ranges[i].length;
						ranges.splice(i + 1, ranges.length - (i + 1));
					}
					else {
						ranges[i].length = (ranges[i+1].offset + ranges[i+1].length) - ranges[i].offset;
						ranges.splice(i + 1, 1);
					}
				}
			}
		}
		this.ranges = ranges;
	}
	PiecemealDownload.prototype = {
		getRangeHeader: function() {
			var ranges = this.ranges;
			return 'bytes=' + ranges.map(function(range) {
				return range.offset + '-' +
					(isNaN(range.length) ? '' : (range.offset + range.length - 1));
			}).join(',');
		},
		onPiece: function(){},
		onTotalLength: function(){},
		onRawPiece: null,
		initMonolithic: function(offset) {
			this.onRawPiece = this.onRawPiece || function(piece) {
				this.onPiece(offset, piece);
				offset += piece.length;
			};
		},
		initMultipart: function(boundary) {
			var self = this;
			var lineBuf = [];
			var offset, length = 0;
			var onLine;
			var partHeaders;
			function onLine_PartBoundary(line) {
				if (!boundary) {
					if (/^--/.test(line)) {
						boundary = line.substr(2);
						partHeaders = {};
						onLine = onLine_PartHeader;
					}
					else if (line !== '') {
						self.cancel();
						throw new Error('Invalid multipart data');
					}
				}
				else if (line === '--' + boundary) {
					partHeaders = {};
					onLine = onLine_PartHeader;
				}
				else if (line === '--' + boundary + '--') {
					// end of data
					// (not actually reached because there's no final CRLF)
				}
				else if (line !== '') { // optional CRLFs before the first part
					self.cancel();
					throw new Error('Invalid multipart data');
				}
			}
			function onLine_PartHeader(line) {
				if (line === '') {
					var range = partHeaders['content-range'];
					if (!range) {
						self.cancel();
						throw new Error('Invalid multipart data: no Content-Range part header found');
					}
					var matched = range.match(/^bytes (\d+)\-(\d+)\/(\d+)$/);
					if (!matched) {
						self.cancel();
						throw new Error('Invalid multipart Content-Range: ' + range);
					}
					offset = +matched[1];
					length = +matched[2] + 1 - offset;
					onLine = onLine_PartBoundary;
				}
				else {
					var header = line.match(/^\s*([^:\s]*)\s*:\s*(.*?)\s*$/);
					if (!header) {
						self.cancel();
						throw new Error('Invalid multipart data');
					}
					var headerName = header[1].toLowerCase();
					var headerValue = header[2];
					partHeaders[headerName] = headerValue;
				}
			}
			onLine = onLine_PartBoundary;
			this.onRawPiece = function(piece) {
				var pos = 0;
				if (length > 0) {
					var pieceLength = Math.min(length, piece.length);
					this.onPiece(offset, piece.subarray(0, pieceLength));
					offset += pieceLength;
					pos += pieceLength;
					length -= pieceLength;
				}
				while (pos < piece.length) {
					var byte = piece[pos++];
					if (byte === 10) {
						onLine(String.fromCharCode.apply(null, lineBuf));
						lineBuf.length = 0;
						var pieceLength = Math.min(length, piece.length - pos);
						if (pieceLength > 0) {
							this.onPiece(offset, piece.subarray(pos, pos + pieceLength));
							offset += pieceLength;
							pos += pieceLength;
							length -= pieceLength;
						}
					}
					else if (byte !== 13) {
						if (byte < 32 && byte !== 9) {
							this.cancel();
							throw new Error('Unexpected control character: ' + byte);
						}
						lineBuf.push(byte);
					}
				}
			};
		},
		onDone: function(){},
		startDownload: null,
		initContentHeaders: function(contentType, contentRange) {
			contentType = contentType.split(/\s*;\s*/g);
			if (/^multipart\//i.test(contentType[0])) {
				for (var i = 1; i < contentType.length; i++) {
					var param = contentType[i].match(/^\s*([^=\s]+)\s*=("(.*)"|(.*))$/);
					if (!param) {
						this.cancel();
						throw new Error('Invalid Content-Type: ' + contentType.join('; '));
					}
					if (param[1].toLowerCase() === 'boundary') {
						return this.initMultipart(param[3] || param[4]);
					}
				}
				this.cancel();
				throw new Error('Invalid Content-Type: ' + contentType);
			}
			if (!contentRange) {
				return this.initMonolithic(0);
			}
			var matched = contentRange.match(/^bytes (\d+)\-(\d+)\/(\d+)$/);
			if (!matched) {
				this.cancel();
				throw new Error('Invalid Content-Range: ' + contentRange);
			}
			this.onTotalLength(+matched[3]);
			this.initMonolithic(+matched[1]);
		},
		openXHR: function(forceMultipart) {
			var xhr = new XMLHttpRequest;
			xhr.open('GET', this.url, true);
			xhr.setRequestHeader('Range', this.getRangeHeader());
			var self = this;
			xhr.addEventListener('readystatechange', function() {
				if (this.readyState === 2) {
					if (forceMultipart) {
						self.initMultipart(null);
					}
					else {
						self.initContentHeaders(
							this.getResponseHeader('Content-Type'),
							this.getResponseHeader('Content-Range'));
					}
				}
			});
			xhr.addEventListener('load', function() {
				self.onDone();
				delete self.xhr;
			});
			return this.xhr = xhr;
		},
		cancel: function() {
			if ('xhr' in this) {
				this.xhr.abort();
				delete this.xhr;
			}
			else if ('reader' in this) {
				if ('cancel' in this.reader) {
					this.reader.cancel();
				}
				else {
					this.reader.abort();
				}
				delete this.reader;
			}
			this.cancelled = true;
		},
		listenToReader: function(reader) {
			var self = this;
			var pos = 0;
			reader.addEventListener('progress', function() {
				var arraybuffer = this.result;
				if (pos < arraybuffer.byteLength) {
					self.onRawPiece(new Uint8Array(arraybuffer, pos));
					pos = arraybuffer.byteLength;
				}
			});
			reader.addEventListener('load', function() {
				delete self.reader;
			});
			this.reader = reader;
		},
	};

	function tryResponseType(responseType) {
		if (!('responseType' in XMLHttpRequest.prototype)) {
			return false;
		}
		var xhr = new XMLHttpRequest;
		xhr.open('GET', '/', true);
		xhr.responseType = responseType;
		return xhr.responseType === responseType;
	}

	if ('fetch' in window && 'Response' in window && 'body' in Response.prototype) {
		PiecemealDownload.prototype.startDownload = startDownload_FetchResponseBody;
		PiecemealDownload.mode = 'chunked';
	}
	else if (tryResponseType('moz-chunked-arraybuffer')) {
		PiecemealDownload.prototype.startDownload = startDownload_MozChunked;
		PiecemealDownload.mode = 'chunked';
	}
	else if ('MSStreamReader' in window && tryResponseType('ms-stream')) {
		PiecemealDownload.prototype.startDownload = startDownload_MSStream;
		PiecemealDownload.mode = 'buffered';
	}
	else if ('overrideMimeType' in XMLHttpRequest.prototype) {
		PiecemealDownload.prototype.startDownload = startDownload_BinaryString;
		PiecemealDownload.mode = 'buffered';
	}
	else {
		PiecemealDownload.prototype.startDownload = startDownload_ManuallyChunked;
		PiecemealDownload.mode = 'simulated';
	}

	// using Streams API via fetch()
	function startDownload_FetchResponseBody() {
		var self = this;
		fetch(this.url, {headers: {Range: this.getRangeHeader()}, cache:'force-cache'})
			.then(function(response) {
				self.initContentHeaders(
					response.headers.get('Content-Type'),
					response.headers.get('Content-Range'));
				var reader = response.body.getReader();
				self.reader = reader;
				function onPiece(piece) {
					if (piece.done) {
						if (!self.cancelled) {
							self.onDone();
						}
					}
					else {
						self.onRawPiece(piece.value);
						reader.read().then(onPiece);
					}
				}
				reader.read().then(onPiece);
			});
	}

	// using Mozilla's moz-chunked-arraybuffer responseType
	function startDownload_MozChunked() {
		var xhr = this.openXHR();
		xhr.responseType = 'moz-chunked-arraybuffer';
		var self = this;
		xhr.addEventListener('progress', function() {
			self.onRawPiece(new Uint8Array(this.response));
		});
		xhr.send();
	}

	// using Microsoft's ms-stream responseType
	function startDownload_MSStream() {
		var xhr = this.openXHR();
		xhr.responseType = 'ms-stream';
		var self = this;
		xhr.addEventListener('readystatechange', function() {
			switch (this.readyState) {
				case 3: // LOADING
					var reader = new MSStreamReader;
					self.listenToReader(reader);
					reader.readAsArrayBuffer(this.response);
					break;
			}
		});
		xhr.send();
	}

	// using binary string responseText
	// TODO: limit to blocks of 1mb?
	var getStringBytes;
	function startDownload_BinaryString() {
		var xhr = this.openXHR(this.ranges.length > 1);
		xhr.overrideMimeType('text/plain; charset=ISO-8859-1');
		var pos = 0;
		var self = this;
		xhr.addEventListener('progress', function() {
			if (pos < this.responseText.length) {
				self.onRawPiece(getStringBytes(this.responseText.slice(pos)));
				pos = this.responseText.length;
			}
		});
		xhr.send();
	}

	// TextEncoder only works with UTF, not ISO-8859-1
	function getStringBytes(str) {
		var a = new Array(str.length);
		for (var i = 0; i < str.length; i++) {
			a[i] = str.charCodeAt(i);
		}
		return new Uint8Array(a);
	}

	// no true streaming available?
	// make a series of small individual downloads instead
	var MANUAL_CHUNK_SIZE = 1024 * 10;
	function startDownload_ManuallyChunked() {
		var self = this;
		var ranges = this.ranges.slice();
		function nextRange() {
			if (ranges.length === 0) {
				self.onDone();
			}
			else {
				var range = ranges.splice(0, 1)[0];
				nextChunk(range.offset, range.length);
			}
		}
		function nextChunk(offset, length) {
			var xhr = new XMLHttpRequest;
			xhr.open('GET', self.url, true);
			xhr.responseType = 'arraybuffer';
			var chunkLength = isNaN(length) || length > MANUAL_CHUNK_SIZE ? MANUAL_CHUNK_SIZE : length;
			xhr.setRequestHeader('Range', 'bytes=' + offset + '-' + (offset + chunkLength - 1));
			xhr.addEventListener('readystatechange', function() {
				if (this.readyState === 2) {
					if (xhr.status < 200 && xhr.status > 299) {
						xhr.abort();
						throw new Error('Server returned status ' + xhr.status);
					}
					if (isNaN(length)) {
						var range = xhr.getResponseHeader('Content-Range');
						if (!range) {
							xhr.abort();
							throw new Error('Server returned no Content-Range');
						}
						var match = range.match(/\/(\d+)/);
						if (!match) {
							xhr.abort();
							throw new Error('Content-Range: ' + range);
						}
						length = +match[1] - offset;
					}
				}
			});
			xhr.addEventListener('load', function() {
				self.onPiece(offset, new Uint8Array(xhr.response));
				var responseLength = xhr.response.byteLength;
				if (responseLength === length || responseLength < MANUAL_CHUNK_SIZE) {
					nextRange();
				}
				else {
					nextChunk(
						offset + xhr.response.byteLength,
						length - xhr.response.byteLength);
				}
			});
			self.xhr = xhr;
			xhr.send();
		}
		nextRange();
	}

	return PiecemealDownload;

});
<commit_msg>Treat Infinity the same as NaN for length values<commit_after>define(function() {

	'use strict';

	var MIN_GAP = 500;

	function isNafN(v) {
		return isNaN(v) || !isFinite(v);
	}

	function PiecemealDownload(url, ranges) {
		this.url = url;
		for (var i = ranges.length-2; i >= 0; i--) {
			if (isNafN(ranges[i].length)) {
				ranges.splice(i + 1, ranges.length - (i + 1));
			}
			else {
				if (ranges[i].offset <= ranges[i + 1].offset
						&& (ranges[i].offset + ranges[i].length + MIN_GAP) >= ranges[i + 1].offset) {
					if (isNafN(ranges[i + 1].length)) {
						delete ranges[i].length;
						ranges.splice(i + 1, ranges.length - (i + 1));
					}
					else {
						ranges[i].length = (ranges[i+1].offset + ranges[i+1].length) - ranges[i].offset;
						ranges.splice(i + 1, 1);
					}
				}
			}
		}
		this.ranges = ranges;
	}
	PiecemealDownload.prototype = {
		getRangeHeader: function() {
			var ranges = this.ranges;
			return 'bytes=' + ranges.map(function(range) {
				return range.offset + '-' +
					(isNafN(range.length) ? '' : (range.offset + range.length - 1));
			}).join(',');
		},
		onPiece: function(){},
		onTotalLength: function(){},
		onRawPiece: null,
		initMonolithic: function(offset) {
			this.onRawPiece = this.onRawPiece || function(piece) {
				this.onPiece(offset, piece);
				offset += piece.length;
			};
		},
		initMultipart: function(boundary) {
			var self = this;
			var lineBuf = [];
			var offset, length = 0;
			var onLine;
			var partHeaders;
			function onLine_PartBoundary(line) {
				if (!boundary) {
					if (/^--/.test(line)) {
						boundary = line.substr(2);
						partHeaders = {};
						onLine = onLine_PartHeader;
					}
					else if (line !== '') {
						self.cancel();
						throw new Error('Invalid multipart data');
					}
				}
				else if (line === '--' + boundary) {
					partHeaders = {};
					onLine = onLine_PartHeader;
				}
				else if (line === '--' + boundary + '--') {
					// end of data
					// (not actually reached because there's no final CRLF)
				}
				else if (line !== '') { // optional CRLFs before the first part
					self.cancel();
					throw new Error('Invalid multipart data');
				}
			}
			function onLine_PartHeader(line) {
				if (line === '') {
					var range = partHeaders['content-range'];
					if (!range) {
						self.cancel();
						throw new Error('Invalid multipart data: no Content-Range part header found');
					}
					var matched = range.match(/^bytes (\d+)\-(\d+)\/(\d+)$/);
					if (!matched) {
						self.cancel();
						throw new Error('Invalid multipart Content-Range: ' + range);
					}
					offset = +matched[1];
					length = +matched[2] + 1 - offset;
					onLine = onLine_PartBoundary;
				}
				else {
					var header = line.match(/^\s*([^:\s]*)\s*:\s*(.*?)\s*$/);
					if (!header) {
						self.cancel();
						throw new Error('Invalid multipart data');
					}
					var headerName = header[1].toLowerCase();
					var headerValue = header[2];
					partHeaders[headerName] = headerValue;
				}
			}
			onLine = onLine_PartBoundary;
			this.onRawPiece = function(piece) {
				var pos = 0;
				if (length > 0) {
					var pieceLength = Math.min(length, piece.length);
					this.onPiece(offset, piece.subarray(0, pieceLength));
					offset += pieceLength;
					pos += pieceLength;
					length -= pieceLength;
				}
				while (pos < piece.length) {
					var byte = piece[pos++];
					if (byte === 10) {
						onLine(String.fromCharCode.apply(null, lineBuf));
						lineBuf.length = 0;
						var pieceLength = Math.min(length, piece.length - pos);
						if (pieceLength > 0) {
							this.onPiece(offset, piece.subarray(pos, pos + pieceLength));
							offset += pieceLength;
							pos += pieceLength;
							length -= pieceLength;
						}
					}
					else if (byte !== 13) {
						if (byte < 32 && byte !== 9) {
							this.cancel();
							throw new Error('Unexpected control character: ' + byte);
						}
						lineBuf.push(byte);
					}
				}
			};
		},
		onDone: function(){},
		startDownload: null,
		initContentHeaders: function(contentType, contentRange) {
			contentType = contentType.split(/\s*;\s*/g);
			if (/^multipart\//i.test(contentType[0])) {
				for (var i = 1; i < contentType.length; i++) {
					var param = contentType[i].match(/^\s*([^=\s]+)\s*=("(.*)"|(.*))$/);
					if (!param) {
						this.cancel();
						throw new Error('Invalid Content-Type: ' + contentType.join('; '));
					}
					if (param[1].toLowerCase() === 'boundary') {
						return this.initMultipart(param[3] || param[4]);
					}
				}
				this.cancel();
				throw new Error('Invalid Content-Type: ' + contentType);
			}
			if (!contentRange) {
				return this.initMonolithic(0);
			}
			var matched = contentRange.match(/^bytes (\d+)\-(\d+)\/(\d+)$/);
			if (!matched) {
				this.cancel();
				throw new Error('Invalid Content-Range: ' + contentRange);
			}
			this.onTotalLength(+matched[3]);
			this.initMonolithic(+matched[1]);
		},
		openXHR: function(forceMultipart) {
			var xhr = new XMLHttpRequest;
			xhr.open('GET', this.url, true);
			xhr.setRequestHeader('Range', this.getRangeHeader());
			var self = this;
			xhr.addEventListener('readystatechange', function() {
				if (this.readyState === 2) {
					if (forceMultipart) {
						self.initMultipart(null);
					}
					else {
						self.initContentHeaders(
							this.getResponseHeader('Content-Type'),
							this.getResponseHeader('Content-Range'));
					}
				}
			});
			xhr.addEventListener('load', function() {
				self.onDone();
				delete self.xhr;
			});
			return this.xhr = xhr;
		},
		cancel: function() {
			if ('xhr' in this) {
				this.xhr.abort();
				delete this.xhr;
			}
			else if ('reader' in this) {
				if ('cancel' in this.reader) {
					this.reader.cancel();
				}
				else {
					this.reader.abort();
				}
				delete this.reader;
			}
			this.cancelled = true;
		},
		listenToReader: function(reader) {
			var self = this;
			var pos = 0;
			reader.addEventListener('progress', function() {
				var arraybuffer = this.result;
				if (pos < arraybuffer.byteLength) {
					self.onRawPiece(new Uint8Array(arraybuffer, pos));
					pos = arraybuffer.byteLength;
				}
			});
			reader.addEventListener('load', function() {
				delete self.reader;
			});
			this.reader = reader;
		},
	};

	function tryResponseType(responseType) {
		if (!('responseType' in XMLHttpRequest.prototype)) {
			return false;
		}
		var xhr = new XMLHttpRequest;
		xhr.open('GET', '/', true);
		xhr.responseType = responseType;
		return xhr.responseType === responseType;
	}

	if ('fetch' in window && 'Response' in window && 'body' in Response.prototype) {
		PiecemealDownload.prototype.startDownload = startDownload_FetchResponseBody;
		PiecemealDownload.mode = 'chunked';
	}
	else if (tryResponseType('moz-chunked-arraybuffer')) {
		PiecemealDownload.prototype.startDownload = startDownload_MozChunked;
		PiecemealDownload.mode = 'chunked';
	}
	else if ('MSStreamReader' in window && tryResponseType('ms-stream')) {
		PiecemealDownload.prototype.startDownload = startDownload_MSStream;
		PiecemealDownload.mode = 'buffered';
	}
	else if ('overrideMimeType' in XMLHttpRequest.prototype) {
		PiecemealDownload.prototype.startDownload = startDownload_BinaryString;
		PiecemealDownload.mode = 'buffered';
	}
	else {
		PiecemealDownload.prototype.startDownload = startDownload_ManuallyChunked;
		PiecemealDownload.mode = 'simulated';
	}

	// using Streams API via fetch()
	function startDownload_FetchResponseBody() {
		var self = this;
		fetch(this.url, {headers: {Range: this.getRangeHeader()}, cache:'force-cache'})
			.then(function(response) {
				self.initContentHeaders(
					response.headers.get('Content-Type'),
					response.headers.get('Content-Range'));
				var reader = response.body.getReader();
				self.reader = reader;
				function onPiece(piece) {
					if (piece.done) {
						if (!self.cancelled) {
							self.onDone();
						}
					}
					else {
						self.onRawPiece(piece.value);
						reader.read().then(onPiece);
					}
				}
				reader.read().then(onPiece);
			});
	}

	// using Mozilla's moz-chunked-arraybuffer responseType
	function startDownload_MozChunked() {
		var xhr = this.openXHR();
		xhr.responseType = 'moz-chunked-arraybuffer';
		var self = this;
		xhr.addEventListener('progress', function() {
			self.onRawPiece(new Uint8Array(this.response));
		});
		xhr.send();
	}

	// using Microsoft's ms-stream responseType
	function startDownload_MSStream() {
		var xhr = this.openXHR();
		xhr.responseType = 'ms-stream';
		var self = this;
		xhr.addEventListener('readystatechange', function() {
			switch (this.readyState) {
				case 3: // LOADING
					var reader = new MSStreamReader;
					self.listenToReader(reader);
					reader.readAsArrayBuffer(this.response);
					break;
			}
		});
		xhr.send();
	}

	// using binary string responseText
	// TODO: limit to blocks of 1mb?
	var getStringBytes;
	function startDownload_BinaryString() {
		var xhr = this.openXHR(this.ranges.length > 1);
		xhr.overrideMimeType('text/plain; charset=ISO-8859-1');
		var pos = 0;
		var self = this;
		xhr.addEventListener('progress', function() {
			if (pos < this.responseText.length) {
				self.onRawPiece(getStringBytes(this.responseText.slice(pos)));
				pos = this.responseText.length;
			}
		});
		xhr.send();
	}

	// TextEncoder only works with UTF, not ISO-8859-1
	function getStringBytes(str) {
		var a = new Array(str.length);
		for (var i = 0; i < str.length; i++) {
			a[i] = str.charCodeAt(i);
		}
		return new Uint8Array(a);
	}

	// no true streaming available?
	// make a series of small individual downloads instead
	var MANUAL_CHUNK_SIZE = 1024 * 10;
	function startDownload_ManuallyChunked() {
		var self = this;
		var ranges = this.ranges.slice();
		function nextRange() {
			if (ranges.length === 0) {
				self.onDone();
			}
			else {
				var range = ranges.splice(0, 1)[0];
				nextChunk(range.offset, range.length);
			}
		}
		function nextChunk(offset, length) {
			var xhr = new XMLHttpRequest;
			xhr.open('GET', self.url, true);
			xhr.responseType = 'arraybuffer';
			var chunkLength = isNafN(length) || length > MANUAL_CHUNK_SIZE ? MANUAL_CHUNK_SIZE : length;
			xhr.setRequestHeader('Range', 'bytes=' + offset + '-' + (offset + chunkLength - 1));
			xhr.addEventListener('readystatechange', function() {
				if (this.readyState === 2) {
					if (xhr.status < 200 && xhr.status > 299) {
						xhr.abort();
						throw new Error('Server returned status ' + xhr.status);
					}
					if (isNafN(length)) {
						var range = xhr.getResponseHeader('Content-Range');
						if (!range) {
							xhr.abort();
							throw new Error('Server returned no Content-Range');
						}
						var match = range.match(/\/(\d+)/);
						if (!match) {
							xhr.abort();
							throw new Error('Content-Range: ' + range);
						}
						length = +match[1] - offset;
					}
				}
			});
			xhr.addEventListener('load', function() {
				self.onPiece(offset, new Uint8Array(xhr.response));
				var responseLength = xhr.response.byteLength;
				if (responseLength === length || responseLength < MANUAL_CHUNK_SIZE) {
					nextRange();
				}
				else {
					nextChunk(
						offset + xhr.response.byteLength,
						length - xhr.response.byteLength);
				}
			});
			self.xhr = xhr;
			xhr.send();
		}
		nextRange();
	}

	return PiecemealDownload;

});
<|endoftext|>


<commit_before>export const typeFormatChoices = [
  {
    'key': 'int32',
    'label': '32-bit integer',
    'conditions': {
      '../type': 'integer'
    }
  },
  {
    'key': 'int64',
    'label': '64-bit integer',
    'conditions': {
      '../type': 'integer'
    }
  },
  {
    'key': 'float',
    'label': '32-bit floating point',
    'conditions': {
      '../type': 'number'
    }
  },
  {
    'key': 'double',
    'label': '64-bit floating point',
    'conditions': {
      '../type': 'number'
    }
  },
  {
    'key': '',
    'label': 'String',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'byte',
    'label': 'Byte (Base64)',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'binary',
    'label': 'Binary (octet sequence)',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'date',
    'label': 'Date',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'date-time',
    'label': 'Date and Time',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'password',
    'label': 'Password',
    'conditions': {
      '../type': 'string'
    }
  }
];

export const types = {
  'type': 'array',
  'format': 'map',
  'keyField': 'name',
  'showValueInParent': false,
  'addIndexToChildLabel': false,
  'collapseManagement': true,
  'newItemText': 'New Type',
  'item': {
    'type': 'object',
    'label': 'Type #$index: ${#/name}',
    'legendChildren': {
      'type': {
        'type': 'option',
        'columns': '4',
        'placeholder': 'Type name',
        'format': 'dropdown',
        'choices': ['string', 'integer', 'boolean', 'number', 'array', 'object', 'reference', 'null']
      },
      'name': {
        'type': 'text',
        'columns': '4',
        'label': 'Enter key...'
      }
    },
    'children': {
      '$ref': {
        'type': 'option',
        'format': 'dropdown',
        'label': 'Target',
        'hideIfNoChoices': false,
        'dataSources': [{
          'source': '/global-definitions/types',
          'key': '#/definitions/${#/name}',
          'label': 'Type ${#/name}'
        }],
        'conditions': {
          '../type': 'reference'
        }
      },
      'title': {
        'type': 'text',
        'conditions': {
          '../type': ['string', 'integer', 'number', 'array', 'object', 'null']
        }
      },
      'description': {
        'type': 'textarea',
        'conditions': {
          '../type': ['string', 'integer', 'number', 'array', 'object', 'null']
        }
      },
      'format': {
        'type': 'option',
        'format': 'dropdown',
        'choices': typeFormatChoices
      },
      'items': {
        'type': 'lazylink',
        'target': '/global-definitions/types/:item',
        'overrides': {
          'labelFormat': 'Array item',
          'legendChildren/name': null,
          'legendChildren/type/columns': 8
        },
        'conditions': {
          '../type': 'array'
        }
      },
      'properties': {
        'type': 'lazylink',
        'target': '/global-definitions/types',
        'overrides': {
          'labelFormat': 'Properties',
          '#/:item;labelFormat': 'Property #$index: ${#/name}'
        },
        'conditions': {
          '../type': 'object'
        }
      },
      'required': {
        'type': 'array',
        'item': {
          'type': 'option',
          'format': 'dropdown',
          'dataSources': [{
            'source': '../../properties/:child',
            'key': '${#/name}',
            'label': 'Field ${#/name}'
          }],
          'label': 'Required subfield'
        },
        'conditions': {
          '../type': 'object'
        }
      }
    }
  }
};
<commit_msg>Improve types<commit_after>export const typeFormatChoices = [
  {
    'key': 'int32',
    'label': '32-bit integer',
    'conditions': {
      '../type': 'integer'
    }
  },
  {
    'key': 'int64',
    'label': '64-bit integer',
    'conditions': {
      '../type': 'integer'
    }
  },
  {
    'key': 'float',
    'label': '32-bit floating point',
    'conditions': {
      '../type': 'number'
    }
  },
  {
    'key': 'double',
    'label': '64-bit floating point',
    'conditions': {
      '../type': 'number'
    }
  },
  {
    'key': '',
    'label': 'String',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'byte',
    'label': 'Byte (Base64)',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'binary',
    'label': 'Binary (octet sequence)',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'date',
    'label': 'Date',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'date-time',
    'label': 'Date and Time',
    'conditions': {
      '../type': 'string'
    }
  },
  {
    'key': 'password',
    'label': 'Password',
    'conditions': {
      '../type': 'string'
    }
  }
];

export const types = {
  'type': 'array',
  'format': 'map',
  'keyField': 'name',
  'showValueInParent': false,
  'addIndexToChildLabel': false,
  'collapseManagement': true,
  'newItemText': 'New Type',
  'item': {
    'type': 'object',
    'label': 'Type #$index: ${#/name}',
    'legendChildren': {
      'type': {
        'type': 'option',
        'columns': '4',
        'placeholder': 'Type name',
        'format': 'dropdown',
        'choices': ['', 'string', 'integer', 'boolean', 'number', 'array', 'object', 'reference', 'null']
      },
      'name': {
        'type': 'text',
        'columns': '4',
        'label': 'Enter key...'
      }
    },
    'children': {
      '$ref': {
        'type': 'option',
        'format': 'dropdown',
        'label': 'Target',
        'hideIfNoChoices': false,
        'dataSources': [{
          'source': '/global-definitions/types',
          'key': '#/definitions/${#/name}',
          'label': 'Type ${#/name}'
        }],
        'conditions': {
          '../type': 'reference'
        }
      },
      'title': {
        'type': 'text',
        'conditions': {
          '../type': ['string', 'integer', 'number', 'array', 'object', 'null']
        }
      },
      'description': {
        'type': 'textarea',
        'conditions': {
          '../type': ['string', 'integer', 'number', 'array', 'object', 'null']
        }
      },
      'format': {
        'type': 'option',
        'format': 'dropdown',
        'choices': typeFormatChoices
      },
      'items': {
        'type': 'lazylink',
        'target': '/global-definitions/types/:item',
        'overrides': {
          'labelFormat': 'Array item',
          'legendChildren/name': null,
          'legendChildren/type/columns': 8
        },
        'conditions': {
          '../type': 'array'
        }
      },
      'properties': {
        'type': 'lazylink',
        'target': '/global-definitions/types',
        'overrides': {
          'labelFormat': 'Properties',
          '#/:item;labelFormat': 'Property #$index: ${#/name}'
        },
        'conditions': {
          '../type': 'object'
        }
      },
      'required': {
        'label': 'Required subfields',
        'type': 'array',
        'item': {
          'type': 'option',
          'format': 'dropdown',
          'dataSources': [{
            'source': '../../properties/:child',
            'key': '${#/name}',
            'label': 'Field ${#/name}'
          }],
          'label': 'Required subfield'
        },
        'conditions': {
          '../type': 'object'
        }
      }
    }
  }
};
<|endoftext|>


<commit_before>/*
 Copyright 2016 Jani Mustonen

 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.
 */

import React from 'react';

/**
 * AccessibleButton is a generic wrapper for any element that should be treated
 * as a button.  Identifies the element as a button, setting proper tab
 * indexing and keyboard activation behavior.
 *
 * @param {Object} props  react element properties
 * @returns {Object} rendered react
 */
export default function AccessibleButton(props) {
    const {element, onClick, children, ...restProps} = props;
    restProps.onClick = onClick;
    restProps.onKeyUp = function(e) {
        if (e.keyCode == 13 || e.keyCode == 32) return onClick(e);
    };
    restProps.tabIndex = restProps.tabIndex || "0";
    restProps.role = "button";
    restProps.className = (restProps.className ? restProps.className + " " : "") +
                          "mx_AccessibleButton";
    return React.createElement(element, restProps, children);
}

/**
 * children: React's magic prop. Represents all children given to the element.
 * element:  (optional) The base element type. "div" by default.
 * onClick:  (required) Event handler for button activation. Should be
 *           implemented exactly like a normal onClick handler.
 */
AccessibleButton.propTypes = {
    children: React.PropTypes.node,
    element: React.PropTypes.string,
    onClick: React.PropTypes.func.isRequired,
};

AccessibleButton.defaultProps = {
    element: 'div',
};

AccessibleButton.displayName = "AccessibleButton";
<commit_msg>Fixed an issue where pressing enter key to activate the AccessibleButton was also activating normal button that might just have received the system focus as a result of the key press and the other way round. The most obvious occurence of this issue is that dialogs were reappearing when dismissed by pressing the enter key.<commit_after>/*
 Copyright 2016 Jani Mustonen

 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.
 */

import React from 'react';

/**
 * AccessibleButton is a generic wrapper for any element that should be treated
 * as a button.  Identifies the element as a button, setting proper tab
 * indexing and keyboard activation behavior.
 *
 * @param {Object} props  react element properties
 * @returns {Object} rendered react
 */
export default function AccessibleButton(props) {
    const {element, onClick, children, ...restProps} = props;
    restProps.onClick = onClick;
    restProps.onKeyDown = function(e) {
        if (e.keyCode == 13 || e.keyCode == 32) {
            e.stopPropagation();
            e.preventDefault();
            return onClick(e);
        }
    };
    restProps.tabIndex = restProps.tabIndex || "0";
    restProps.role = "button";
    restProps.className = (restProps.className ? restProps.className + " " : "") +
                          "mx_AccessibleButton";
    return React.createElement(element, restProps, children);
}

/**
 * children: React's magic prop. Represents all children given to the element.
 * element:  (optional) The base element type. "div" by default.
 * onClick:  (required) Event handler for button activation. Should be
 *           implemented exactly like a normal onClick handler.
 */
AccessibleButton.propTypes = {
    children: React.PropTypes.node,
    element: React.PropTypes.string,
    onClick: React.PropTypes.func.isRequired,
};

AccessibleButton.defaultProps = {
    element: 'div',
};

AccessibleButton.displayName = "AccessibleButton";
<|endoftext|>


<commit_before>import ButtonCounter from '../../ButtonCounter';
import IconImage from '../../IconImage';
import Icon from '../../Icon';
import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import styles from './styles.css';

const ICON_WIDTH = 24;
const OVERLAP = 7;
const SPACE = 40;

class ActionItemSummaryComposit extends React.Component {
    constructor(props) {
        super(props);
        this.renderIcons = this.renderIcons.bind(this);
    }

    componentDidMount() {
        const icons = this.renderIcons();

        ReactDOM.render(
{icons}
, this.container);
    }

    handleRef = (component) => {
        this.container = component;
    };

    renderIcons() {
        let lastLeft = 0;
        const width = ReactDOM.findDOMNode(this.container).offsetWidth;
        const number = Math.floor((width - SPACE) / (ICON_WIDTH - OVERLAP));
        const iconsMap = this.props.icons.slice(0, number).map((icon, key) => {
            lastLeft = key * (ICON_WIDTH - OVERLAP);
            return (
                <IconImage
                    className={styles.icon}
                    icon={icon}
                    key={key}
                    size={"small"}
                    style={{left: key * (ICON_WIDTH - OVERLAP)}}
                />
            );
        });
        const numberLeft = this.props.icons.length - number;

        return [iconsMap,
            numberLeft > 0
                ? <ButtonCounter
                    className={styles.cb}
                    key={"bc"}
                    number={numberLeft}
                    prefix={'+'}
                    size={'small'}
                    style={{position: "absolute", left: lastLeft + ICON_WIDTH - OVERLAP}}
                  /> : null,
            <Icon
                className={classNames(styles.arrow, {[styles.expanded]: this.props.expanded})}
                icon={"icon-keyboard_arrow_down"}
                key={"icon"}
                onClick={this.props.onClick}
                size={"standard"}
            />
        ];
    }

    render() {
        return (

        );
    }
}

ActionItemSummaryComposit.propTypes = {
    className: React.PropTypes.string,
    expanded: React.PropTypes.bool,
    icons: React.PropTypes.arrayOf(React.PropTypes.string),
    onClick: React.PropTypes.func
};

export default ActionItemSummaryComposit;
<commit_msg>Fixed bug where icons would not update<commit_after>import ButtonCounter from '../../ButtonCounter';
import IconImage from '../../IconImage';
import Icon from '../../Icon';
import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import styles from './styles.css';

const ICON_WIDTH = 24;
const OVERLAP = 7;
const SPACE = 40;

class ActionItemSummaryComposit extends React.Component {
    constructor(props) {
        super(props);
        this.renderIcons = this.renderIcons.bind(this);
    }

    componentDidMount() {
        const icons = this.renderIcons();

        ReactDOM.render(
{icons}
, this.container);
    }

    componentDidUpdate() {
        const icons = this.renderIcons();

        ReactDOM.render(
{icons}
, this.container);
    }

    handleRef = (component) => {
        this.container = component;
    };

    renderIcons() {
        let lastLeft = 0;
        const width = ReactDOM.findDOMNode(this.container).offsetWidth;
        const number = Math.floor((width - SPACE) / (ICON_WIDTH - OVERLAP));
        const iconsMap = this.props.icons.slice(0, number).map((icon, key) => {
            lastLeft = key * (ICON_WIDTH - OVERLAP);
            return (
                <IconImage
                    className={styles.icon}
                    icon={icon}
                    key={`${key}_${Math.random()}`}
                    size={"small"}
                    style={{left: key * (ICON_WIDTH - OVERLAP)}}
                />
            );
        });
        const numberLeft = this.props.icons.length - number;

        return [iconsMap,
            numberLeft > 0
                ? <ButtonCounter
                    className={styles.cb}
                    key={"bc"}
                    number={numberLeft}
                    prefix={'+'}
                    size={'small'}
                    style={{position: "absolute", left: lastLeft + ICON_WIDTH - OVERLAP}}
                  /> : null,
            <Icon
                className={classNames(styles.arrow, {[styles.expanded]: this.props.expanded})}
                icon={"icon-keyboard_arrow_down"}
                key={"icon"}
                onClick={this.props.onClick}
                size={"standard"}
            />
        ];
    }

    render() {
        return (

        );
    }
}

ActionItemSummaryComposit.propTypes = {
    className: React.PropTypes.string,
    expanded: React.PropTypes.bool,
    icons: React.PropTypes.arrayOf(React.PropTypes.string),
    onClick: React.PropTypes.func
};

export default ActionItemSummaryComposit;
<|endoftext|>


<commit_before>document.body.onload = main;

function main() {
  var canvas = document.getElementById('scene');
  var ctx = canvas.getContext('2d');

  var plot = ctx.getImageData(0, 0, canvas.offsetWidth, canvas.offsetHeight);

  var width = plot.width;
  var height = plot.height;

  var fromX = -10, toX = 10, fromY = -10, toY = 10;
  var mathWidth = toX - fromX;
  var mathHeight = toY - fromY;

  var step = (toX - fromX)/(20 * width);

  for (var x = fromX; x < toX; x += step) {
    var y = Math.sin(x);

    var screenX = (x - fromX) * width / mathWidth;
    var screenY = (y - fromY) * height / mathHeight;

    pixel(screenX, screenY, 0, 255, 0);
  }

  ctx.putImageData(plot, 0, 0);

  function pixel(x, y, r, g, b) {
    x = Math.floor(x);
    y = Math.floor(y);
    var idx = (x + width * y) * 4;
    plot.data[idx] = r;
    plot.data[idx + 1] = g;
    plot.data[idx + 2] = b;
    plot.data[idx + 3] = 255;
  }
}

<commit_msg>Rotate sin function<commit_after>document.body.onload = main;

function main() {
  var canvas = document.getElementById('scene');
  var ctx = canvas.getContext('2d');

  var plot = ctx.getImageData(0, 0, canvas.offsetWidth, canvas.offsetHeight);

  var width = plot.width;
  var height = plot.height;

  var fromX = -10, toX = 10, fromY = -10, toY = 10;
  var mathWidth = toX - fromX;
  var mathHeight = toY - fromY;

  var step = (toX - fromX)/(20 * width);

  for (var x = fromX; x < toX; x += step) {
    var y = Math.sin(x);

    var angle = Math.PI/2;
    var rotX = x * Math.cos(angle) - y * Math.sin(angle);
    var rotY = x * Math.sin(angle) + y * Math.cos(angle);

    var screenX = (rotX - fromX) * width / mathWidth;
    var screenY = (rotY - fromY) * height / mathHeight;

    pixel(screenX, screenY, 0, 255, 0);
  }

  ctx.putImageData(plot, 0, 0);

  function pixel(x, y, r, g, b) {
    x = Math.floor(x);
    y = Math.floor(y);
    var idx = (x + width * y) * 4;
    plot.data[idx] = r;
    plot.data[idx + 1] = g;
    plot.data[idx + 2] = b;
    plot.data[idx + 3] = 255;
  }
}

<|endoftext|>


<commit_before>'use strict';

var $overlay = $('#ruler-overlay');
// If the overlay doesn't exist, create it.
if ($overlay.length === 0) {
  $overlay = $('<div>');

  $overlay.attr('id', 'ruler-overlay');
  $overlay.attr('class', 'ruler-overlay');
}

// TODO figure out why insertCSS wasn't working.
$overlay.css('position', 'fixed');
$overlay.css('top', 0);
$overlay.css('right', 0);
$overlay.css('bottom', 0);
$overlay.css('left', 0);

// Let's just make sure we're above everything else.
$overlay.css('z-index', 10000);

$overlay.css('background-color', '#000');
$overlay.css('opacity', '0.8');

$('body').append($overlay);

var Rect = function() {
  this.$rect = $('<div>');

  this.$rect.attr('id', 'ruler-rect');
  this.$rect.attr('class', 'ruler-rect');

  this.$rect.css('background-color', 'green');
};

Rect.prototype.setDimensions = function(point) {
  var width = Math.abs(this.origin.left - point.left);
  var height = Math.abs(this.origin.top - point.top);

  var origin = {
    left: Math.min(this.origin.left, point.left),
    top: Math.min(this.origin.top, point.top)
  };

  if (origin.left !== this.origin.left || origin.top !== this.origin.top) {
    this.$rect.offset(origin);
  }

  this.$rect.width(width);
  this.$rect.height(height);
};

Rect.prototype.setOrigin = function(event) {
  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.origin = point;

  this.$rect.offset(point);

  this.$rect.width(0);
  this.$rect.height(0);

  if (this.$rect.parents().length === 0) {
    $overlay.append(this.$rect);
  }

  $overlay.on('mousemove', $.proxy(this.followMouse, this));
  $overlay.one('click', $.proxy(this.stopFollowingMouse, this));
};

Rect.prototype.followMouse = function(event) {
  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.setDimensions(point);
};

Rect.prototype.stopFollowingMouse = function(event) {
  $overlay.off('mousemove', this.followMouse);

  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.setDimensions(point);

  $overlay.one('click', $.proxy(this.setOrigin, this));
};

var rect = new Rect();
$overlay.one('click', $.proxy(rect.setOrigin, rect));
<commit_msg>fixed initial origin always being 0, 0<commit_after>'use strict';

var $overlay = $('#ruler-overlay');
// If the overlay doesn't exist, create it.
if ($overlay.length === 0) {
  $overlay = $('<div>');

  $overlay.attr('id', 'ruler-overlay');
  $overlay.attr('class', 'ruler-overlay');
}

// TODO figure out why insertCSS wasn't working.
$overlay.css('position', 'fixed');
$overlay.css('top', 0);
$overlay.css('right', 0);
$overlay.css('bottom', 0);
$overlay.css('left', 0);

// Let's just make sure we're above everything else.
$overlay.css('z-index', 10000);

$overlay.css('background-color', '#000');
$overlay.css('opacity', '0.8');

$('body').append($overlay);

var Rect = function() {
  this.$rect = $('<div>');

  this.$rect.attr('id', 'ruler-rect');
  this.$rect.attr('class', 'ruler-rect');

  this.$rect.css('background-color', 'green');
};

Rect.prototype.setDimensions = function(point) {
  var width = Math.abs(this.origin.left - point.left);
  var height = Math.abs(this.origin.top - point.top);

  var origin = {
    left: Math.min(this.origin.left, point.left),
    top: Math.min(this.origin.top, point.top)
  };

  if (origin.left !== this.origin.left || origin.top !== this.origin.top) {
    this.$rect.offset(origin);
  }

  this.$rect.width(width);
  this.$rect.height(height);
};

Rect.prototype.setOrigin = function(event) {
  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.origin = point;

  if (this.$rect.parents().length === 0) {
    $overlay.append(this.$rect);
  }

  this.$rect.offset(point);

  this.$rect.width(0);
  this.$rect.height(0);

  $overlay.on('mousemove', $.proxy(this.followMouse, this));
  $overlay.one('click', $.proxy(this.stopFollowingMouse, this));
};

Rect.prototype.followMouse = function(event) {
  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.setDimensions(point);
};

Rect.prototype.stopFollowingMouse = function(event) {
  $overlay.off('mousemove', this.followMouse);

  var point = {
    left: event.clientX,
    top: event.clientY
  };

  this.setDimensions(point);

  $overlay.one('click', $.proxy(this.setOrigin, this));
};

var rect = new Rect();
$overlay.one('click', $.proxy(rect.setOrigin, rect));
<|endoftext|>


<commit_before>/*global declare, it, describe, beforeEach, afterEach, before, after*/
import { morph,  World, MorphicEnv } from "../index.js";
import { Tree, TreeData } from "../tree.js";
import { expect } from "mocha-es6";
import { pt, rect, Color, Rectangle, Transform } from "lively.graphics";
import { arr } from "lively.lang";
import { dummyFontMetric as fontMetric } from "./test-helpers.js";
import { createDOMEnvironment } from "../rendering/dom-helper.js";

function testTreeData() {
  class TestTreeData extends TreeData {
    display(node) { return node.morph || node.name }
    isCollapsed(node) { return node.isCollapsed }
    collapse(node, bool) { node.isCollapsed = bool; }
    getChildren(node) { return node.isLeaf ? null : node.isCollapsed ? [] : node.children }
    isLeaf(node) { return node.isLeaf }
  }

  return new TestTreeData({
    name: "root",
    isCollapsed: false,
    isLeaf: false,
    children: [
      {name: "child 1", isLeaf: true},
      {name: "child 2", isLeaf: false, isCollapsed: true, children: [{name: "child 2 - 1", isLeaf: true}]},
      {name: "child 3", isLeaf: false,
       isCollapsed: false,
       children: [
         {name: "child 3 - 1", isLeaf: true},
         {name: "child 3 - 2", isLeaf: true}
       ]},
      {name: "child 4", isLeaf: true},
    ]
  });
}

var tree;
function createTree(props) {
  return tree = new Tree({
    extent: pt(200,200), fill: Color.white, border: {color: Color.gray, width: 1},
    padding: Rectangle.inset(0), treeData: testTreeData(), ...props
  })
}

var env;
async function createMorphicEnv() {
  env = new MorphicEnv(await createDOMEnvironment());
  env.domEnv.document.body.style = "margin: 0";
  env.fontMetric = fontMetric;
  MorphicEnv.pushDefault(env);
  await env.setWorld(new World({extent: pt(400,300)}));
}
async function destroyMorphicEnv() { MorphicEnv.popDefault().uninstall(); }

describe("tree", function() {

  this.timeout(10000);

  beforeEach(async () => {
    await createMorphicEnv();
    createTree({env});
  });
  afterEach(() => destroyMorphicEnv());

  it("renders visible items without root", () => {
    expect(arr.pluck(tree.nodeMorphs, "labelString"))
      .equals(["child 1", "child 2", "child 3", "child 3 - 1", "child 3 - 2", "child 4"]);
    var h = tree.lineBounds(1).height;
    tree.height = h*3;
    tree.scroll = pt(0, 2*h-3);
    tree.update();
    expect(arr.pluck(tree.nodeMorphs, "labelString"))
      .equals(["child 2", "child 3", "child 3 - 1", "child 3 - 2"]);
  });

  it("selects", () => {
    expect(tree.selectedIndex).equals(-1);
    expect(tree.selection).equals(null)
    tree.selection = tree.treeData.root.children[1];
    expect(tree.selectedIndex).equals(2);
    expect(tree.selection).containSubset({isCollapsed: true, name: "child 2"});
  })

  it("descends along path and returns node", async () => {
    var path = ["root", "child 3", "child 3 - 2"],
        td = tree.treeData,
        found = await td.followPath(path,
          (pathPart, node) => td.display(node) === pathPart);
    expect(td.root.children[2].children[1]).equals(found);
  });

  describe("morphs as tree nodes", () => {

    it("inserts morph when node specifies one in display()", async () => {
      var m = morph({extent: pt(50,50), fill: Color.red});
      tree.treeData.root.children[1].morph = m;
      // tree.openInWorld()
      // tree.remove()
      tree.update();

      expect(tree.nodeMorphs[1].submorphs[1]).equals(m, "morph not rendered in display node morph");
      await tree.onNodeCollapseChanged({node: tree.treeData.root.children[1], isCollapsed: false})
      expect(tree.nodes[3].name).equals("child 2 - 1", "node not uncollapsed");
      expect(tree.nodeMorphs[2].top).gte(tree.nodeMorphs[1].bottom, "vertical layout wrong");
    });

  });

  describe("view state", () => {

    it("can be externalized and applied", async () => {
      var tree1 = tree,
          tree2 = createTree();
      // env.world.addMorph(tree1); // env.world.addMorph(tree2);
      // tree2.moveBy(pt(300,0))
      // tree1.remove(); tree2.remove();

      tree2.nodes.forEach((n) => tree2.treeData.collapse(n, true));
      tree2.update();

      expect(tree2.nodes).equals([tree2.treeData.root]);
      expect(tree2.treeData.root).not.equals(tree1.treeData.root);

      var viewState = tree1.buildViewState((n) => n.name);
      await tree2.applyViewState(viewState, (n) => n.name);

      expect(arr.pluck(tree2.nodes, "name"))
        .equals(["root", "child 1", "child 2", "child 3", "child 3 - 1", "child 3 - 2", "child 4"]);
    });

  });
});
<commit_msg>fix tree test<commit_after>/*global declare, it, describe, beforeEach, afterEach, before, after*/
import { morph,  World, MorphicEnv } from "../index.js";
import { Tree, TreeData } from "../tree.js";
import { expect } from "mocha-es6";
import { pt, rect, Color, Rectangle, Transform } from "lively.graphics";
import { arr } from "lively.lang";
import { dummyFontMetric as fontMetric } from "./test-helpers.js";
import { createDOMEnvironment } from "../rendering/dom-helper.js";

function testTreeData() {
  class TestTreeData extends TreeData {
    display(node) { return node.morph || node.name }
    isCollapsed(node) { return node.isCollapsed }
    collapse(node, bool) { node.isCollapsed = bool; }
    getChildren(node) { return node.isLeaf ? null : node.isCollapsed ? [] : node.children }
    isLeaf(node) { return node.isLeaf }
  }

  return new TestTreeData({
    name: "root",
    isCollapsed: false,
    isLeaf: false,
    children: [
      {name: "child 1", isLeaf: true},
      {name: "child 2", isLeaf: false, isCollapsed: true, children: [{name: "child 2 - 1", isLeaf: true}]},
      {name: "child 3", isLeaf: false,
       isCollapsed: false,
       children: [
         {name: "child 3 - 1", isLeaf: true},
         {name: "child 3 - 2", isLeaf: true}
       ]},
      {name: "child 4", isLeaf: true},
    ]
  });
}

var tree;
function createTree(props) {
  return tree = new Tree({
    extent: pt(200,200), fill: Color.white, border: {color: Color.gray, width: 1},
    padding: Rectangle.inset(0), treeData: testTreeData(), ...props
  })
}

var env;
async function createMorphicEnv() {
  env = new MorphicEnv(await createDOMEnvironment());
  env.domEnv.document.body.style = "margin: 0";
  env.fontMetric = fontMetric;
  MorphicEnv.pushDefault(env);
  await env.setWorld(new World({extent: pt(400,300)}));
}
async function destroyMorphicEnv() { MorphicEnv.popDefault().uninstall(); }

describe("tree", function() {

  this.timeout(10000);

  beforeEach(async () => {
    await createMorphicEnv();
    createTree({env});
  });
  afterEach(() => destroyMorphicEnv());

  it("renders visible items without root", () => {
    expect(arr.pluck(tree.nodeMorphs, "labelValue"))
      .equals(["child 1", "child 2", "child 3", "child 3 - 1", "child 3 - 2", "child 4"]);
    var h = tree.lineBounds(1).height;
    tree.height = h*3;
    tree.scroll = pt(0, 2*h-3);
    tree.update();
    expect(arr.pluck(tree.nodeMorphs, "labelValue"))
      .equals(["child 2", "child 3", "child 3 - 1", "child 3 - 2"]);
  });

  it("selects", () => {
    expect(tree.selectedIndex).equals(-1);
    expect(tree.selection).equals(null)
    tree.selection = tree.treeData.root.children[1];
    expect(tree.selectedIndex).equals(2);
    expect(tree.selection).containSubset({isCollapsed: true, name: "child 2"});
  })

  it("descends along path and returns node", async () => {
    var path = ["root", "child 3", "child 3 - 2"],
        td = tree.treeData,
        found = await td.followPath(path,
          (pathPart, node) => td.display(node) === pathPart);
    expect(td.root.children[2].children[1]).equals(found);
  });

  describe("morphs as tree nodes", () => {

    it("inserts morph when node specifies one in display()", async () => {
      var m = morph({extent: pt(50,50), fill: Color.red});
      tree.treeData.root.children[1].morph = m;
      // tree.openInWorld()
      // tree.remove()
      tree.update();

      expect(tree.nodeMorphs[1].submorphs[1]).equals(m, "morph not rendered in display node morph");
      await tree.onNodeCollapseChanged({node: tree.treeData.root.children[1], isCollapsed: false})
      expect(tree.nodes[3].name).equals("child 2 - 1", "node not uncollapsed");
      expect(tree.nodeMorphs[2].top).gte(tree.nodeMorphs[1].bottom, "vertical layout wrong");
    });

  });

  describe("view state", () => {

    it("can be externalized and applied", async () => {
      var tree1 = tree,
          tree2 = createTree();
      // env.world.addMorph(tree1); // env.world.addMorph(tree2);
      // tree2.moveBy(pt(300,0))
      // tree1.remove(); tree2.remove();

      tree2.nodes.forEach((n) => tree2.treeData.collapse(n, true));
      tree2.update();

      expect(tree2.nodes).equals([tree2.treeData.root]);
      expect(tree2.treeData.root).not.equals(tree1.treeData.root);

      var viewState = tree1.buildViewState((n) => n.name);
      await tree2.applyViewState(viewState, (n) => n.name);

      expect(arr.pluck(tree2.nodes, "name"))
        .equals(["root", "child 1", "child 2", "child 3", "child 3 - 1", "child 3 - 2", "child 4"]);
    });

  });
});
<|endoftext|>


<commit_before>function createTreeMap(json, elementId, amountLabel) {
    var get = function(id){
        return document.getElementById(id);
    };
    var infovis = get(elementId);
    var w = infovis.offsetWidth, h = infovis.offsetHeight;
    infovis.style.width = w + 'px';
    infovis.style.height = h + 'px';

    //init tm
    var tm = new TM.Squarified({
        //The id of the treemap container
        rootId: elementId,
        //Set the max. depth to be shown for a subtree
        levelsToShow: 1,

        //Add click handlers for
        //zooming the Treemap in and out
        addLeftClickHandler: true,
        addRightClickHandler: true,

        //When hovering a node highlight the nodes
        //between the root node and the hovered node. This
        //is done by adding the 'in-path' CSS class to each node.
        selectPathOnHover: true,

        titleHeight: 20,

        Color: {
            //Allow coloring
            allow: true,
            //Set min value and max value constraints
            //for the *$color* property value.
            //Default's to -100 and 100.
            minValue: 0,
            maxValue: 50,
            //Set color range. Default's to reddish and greenish.
            //It takes an array of three
            //integers as R, G and B values.
            minColorValue: [168, 69, 66],
            // maxColorValue: [68, 68, 68]
            maxColorValue: [0, 0, 0]
        },

        //Allow tips
        Tips: {
          allow: true,
          //add positioning offsets
          offsetX: 20,
          offsetY: 20,
          //implement the onShow method to
          //add content to the tooltip when a node
          //is hovered
          onShow: function(tip, node, isLeaf, domElement) {
              tip.innerHTML = "
" + node.name + "
" +
                "
" + this.makeHTMLFromData(node.data) + "
";
          },

          //Aux method: Build the tooltip inner html by using the data property
          makeHTMLFromData: function(data){
              var html = '';
              html += amountLabel + ': ' + data.$area + '
';
              return html;
          }
        },

        //Implement this method for retrieving a requested
        //subtree that has as root a node with id = nodeId,
        //and level as depth. This method could also make a server-side
        //call for the requested subtree. When completed, the onComplete
        //callback method should be called.
        request: function(nodeId, level, onComplete){
            var tree = eval('(' + json + ')');
            var subtree = TreeUtil.getSubtree(tree, nodeId);
            TreeUtil.prune(subtree, 1);
            onComplete.onComplete(nodeId, subtree);
        },

        //Remove all events for the element before destroying it.
        onDestroyElement: function(content, tree, isLeaf, leaf){
            if(leaf.clearAttributes) leaf.clearAttributes();
        }
    });

    var pjson = eval('(' + json + ')');
    TreeUtil.prune(pjson, 1);
    tm.loadJSON(pjson);
    //end
}

//
function makeSeries(tabular, firstColumnName, secondColumnName, thirdColumnName, dashedValue) {
    var idx1 = tabular.header.indexOf(firstColumnName);
    var idx2 = tabular.header.indexOf(secondColumnName);
    var idx3;
    if(thirdColumnName && dashedValue){
	// special handling of values that should be drawn dashed
	// assumption is that series of values always take form normal...dashed
	// hence n--n--n--n- d- d- d
	// issue: last value is not drawn, only mid point between last and last but 1 point
	idx3 = tabular.header.indexOf(thirdColumnName);
    }
    var series = [];
    var rep = /^([\d\.\-]+)$/;
    var last_r;
    var last_v;
    $.each(tabular.data, function(i,row) {
	var v=row[idx2];
	if(rep.test(v)){
	    var r=row[idx1];
	    if(idx3){
		// dashed marking mode
		if(row[idx3] == dashedValue){
		    // this is a dashed value
		    if(rep.test(last_v)){
			// there was a last value
			var r1=parseFloat(r)*1/4+parseFloat(last_r)*3/4;
			var r2=parseFloat(r)*1/2+parseFloat(last_r)*1/2;
			var r3=parseFloat(r)*3/4+parseFloat(last_r)*1/4;
			var v1=parseFloat(v)*1/4+parseFloat(last_v)*3/4;
			var v2=parseFloat(v)*1/2+parseFloat(last_v)*1/2;
			var v3=parseFloat(v)*3/4+parseFloat(last_v)*1/4;
			debug('dashed:'+r2+','+v2);
			series.push([r1,v1]);
			series.push(null);
			series.push([r2,v2]);
			series.push([r3,v3]);
			series.push(null);
		    }
		}
		last_r=r;
		last_v=v;
	    }
	    debug('normal:'+r+','+v+' l:'+last_r+','+last_v);
	    series.push([r, v]);
	}else{
	    last_r='';
	    last_v='';
	}
    });
    return series;
}

function setupFlot(all_datasets, flotChart, options, flotGroup0) {
    /*
      Plot a set of datasets using flot.

      :param all_datasets: list of datasets. Should look like:

      "series-1": {
      label: "Label 1",
      data: [[1988, 483994], [1989, 479060]]
      },
      "series-2": {
      label: "Label 2",
      data: [[1988, 218000], [1989, 203000]]
      }
    */
    // hard-code color indices to prevent them from shifting as
    // series are turned on/off
    var i = 0;
    $.each(all_datasets, function(key, val) {
	if(val.setid){
	    val.color=(val.setid-1);
	}else{
	    val.color = i;
	    ++i;
	}
    });

    // setup checkboxes
    var seriesList = flotChart.find(".flot-select-series");
    if(flotGroup0){
	var groups=[];
	for (var datasetKey in all_datasets) {
	    var group=all_datasets[datasetKey].group;
	    if(!groups[group]){
		groups[group]=1;
		var input = $('<input type="radio"></input>');
		input.attr('name', 'flot-radio');
		input.attr('value', group);
		input.attr('checked', 'checked');
		seriesList.append(input);
		seriesList.append(DisplayNames[group]);
	    }
	}
    }else{
	for (var datasetKey in all_datasets) {
	    var input = $('<input type="checkbox"></input>');
	    input.attr('name', datasetKey);
	    input.attr('value', datasetKey);
	    input.attr('checked', 'checked');
	    seriesList.append(input);
	    seriesList.append(all_datasets[datasetKey].label);
	}
    }

    flotChart.find('.flot-chart-controls').find('input').live('click', function() {
	doFlotPlot(all_datasets, flotChart, options, flotGroup0);
    });

    // setup charttype
    var chartType = "lines";
    var x = flotChart.find(".flot-chart-type").find("input[value="+chartType+"]");
    x.attr("checked", true);
}

function doFlotPlot(all_datasets, flotChart, options, flotGroup0) {
    /*
      :param options: optional set of options to be passed to flot plot.
    */
    if (!options) {
	options = {};
    }

    // select datesets according to current state
    var datasets_to_plot = []
    var percent_flag=0;
    flotChart.find(".flot-select-series").find("input:checked").each(function () {
	var key = $(this).attr("value");
	if (key) {
	    if(flotGroup0){
		// percentage on yaxis1
                if(ColDisplayTypes[key]){
	     	    percent_flag=1;
		}
		var flotSet=flotGroup0[key];
		$.each(flotSet, function(i, keys) {
		    if (all_datasets[keys]) {
			datasets_to_plot.push(all_datasets[keys]);
		    }
		});
	    }else{
		// percentage on yaxis2
                if(ColDisplayTypes[key]){
	     	    percent_flag=2;
		}
		if (all_datasets[key]) {
		    datasets_to_plot.push(all_datasets[key]);
		}
	    }
	}
    });

    // yaxis percentage options
    if(percent_flag==1){
	options['yaxis'] = {
	    tickFormatter: percentFormatter
	};
	options['y2axis'] = {};
    }else if(percent_flag==2){
	options['yaxis'] = {};
	options['y2axis'] = {
	    tickFormatter: percentFormatter
	};
    }else{
	options['yaxis'] = {};
	options['y2axis'] = {};
    }

    // select plot type according to current state
    flotChart.find(".flot-chart-type").find("input:checked").each(function() {
	var value = $(this).attr("value");
	options[value] = { show: true };
    });

    // select range according to current state
    flotChart.find(".flot-select-range").find("input:checked").each(function() {
        var key=$(this).attr("value");
        if(key=='plusminusfive'){
            options['xaxis'] = { min: 2005, max: 2015 };
        }else{
	    options['xaxis'] = {};
	}
    });
    var chartDiv = flotChart.find('.flot-chart')[0];
    $.plot(chartDiv, datasets_to_plot, options);
}

  function percentFormatter(val, axis) {
      return (val * 100).toFixed(1) + " %";
  }
<commit_msg>[scripts/wdmmg.js][xs]: tabify spaces.<commit_after>function createTreeMap(json, elementId, amountLabel) {
	var get = function(id){
		return document.getElementById(id);
	};
	var infovis = get(elementId);
	var w = infovis.offsetWidth, h = infovis.offsetHeight;
	infovis.style.width = w + 'px';
	infovis.style.height = h + 'px';

	//init tm
	var tm = new TM.Squarified({
		//The id of the treemap container
		rootId: elementId,
		//Set the max. depth to be shown for a subtree
		levelsToShow: 1,

		//Add click handlers for
		//zooming the Treemap in and out
		addLeftClickHandler: true,
		addRightClickHandler: true,

		//When hovering a node highlight the nodes
		//between the root node and the hovered node. This
		//is done by adding the 'in-path' CSS class to each node.
		selectPathOnHover: true,

		titleHeight: 20,

		Color: {
			//Allow coloring
			allow: true,
			//Set min value and max value constraints
			//for the *$color* property value.
			//Default's to -100 and 100.
			minValue: 0,
			maxValue: 50,
			//Set color range. Default's to reddish and greenish.
			//It takes an array of three
			//integers as R, G and B values.
			minColorValue: [168, 69, 66],
			// maxColorValue: [68, 68, 68]
			maxColorValue: [0, 0, 0]
		},

		//Allow tips
		Tips: {
		  allow: true,
		  //add positioning offsets
		  offsetX: 20,
		  offsetY: 20,
		  //implement the onShow method to
		  //add content to the tooltip when a node
		  //is hovered
		  onShow: function(tip, node, isLeaf, domElement) {
			  tip.innerHTML = "
" + node.name + "
" +
				"
" + this.makeHTMLFromData(node.data) + "
";
		  },

		  //Aux method: Build the tooltip inner html by using the data property
		  makeHTMLFromData: function(data){
			  var html = '';
			  html += amountLabel + ': ' + data.$area + '
';
			  return html;
		  }
		},

		//Implement this method for retrieving a requested
		//subtree that has as root a node with id = nodeId,
		//and level as depth. This method could also make a server-side
		//call for the requested subtree. When completed, the onComplete
		//callback method should be called.
		request: function(nodeId, level, onComplete){
			var tree = eval('(' + json + ')');
			var subtree = TreeUtil.getSubtree(tree, nodeId);
			TreeUtil.prune(subtree, 1);
			onComplete.onComplete(nodeId, subtree);
		},

		//Remove all events for the element before destroying it.
		onDestroyElement: function(content, tree, isLeaf, leaf){
			if(leaf.clearAttributes) leaf.clearAttributes();
		}
	});

	var pjson = eval('(' + json + ')');
	TreeUtil.prune(pjson, 1);
	tm.loadJSON(pjson);
	//end
}

//
function makeSeries(tabular, firstColumnName, secondColumnName, thirdColumnName, dashedValue) {
	var idx1 = tabular.header.indexOf(firstColumnName);
	var idx2 = tabular.header.indexOf(secondColumnName);
	var idx3;
	if(thirdColumnName && dashedValue){
	// special handling of values that should be drawn dashed
	// assumption is that series of values always take form normal...dashed
	// hence n--n--n--n- d- d- d
	// issue: last value is not drawn, only mid point between last and last but 1 point
	idx3 = tabular.header.indexOf(thirdColumnName);
	}
	var series = [];
	var rep = /^([\d\.\-]+)$/;
	var last_r;
	var last_v;
	$.each(tabular.data, function(i,row) {
	var v=row[idx2];
	if(rep.test(v)){
		var r=row[idx1];
		if(idx3){
		// dashed marking mode
		if(row[idx3] == dashedValue){
			// this is a dashed value
			if(rep.test(last_v)){
			// there was a last value
			var r1=parseFloat(r)*1/4+parseFloat(last_r)*3/4;
			var r2=parseFloat(r)*1/2+parseFloat(last_r)*1/2;
			var r3=parseFloat(r)*3/4+parseFloat(last_r)*1/4;
			var v1=parseFloat(v)*1/4+parseFloat(last_v)*3/4;
			var v2=parseFloat(v)*1/2+parseFloat(last_v)*1/2;
			var v3=parseFloat(v)*3/4+parseFloat(last_v)*1/4;
			debug('dashed:'+r2+','+v2);
			series.push([r1,v1]);
			series.push(null);
			series.push([r2,v2]);
			series.push([r3,v3]);
			series.push(null);
			}
		}
		last_r=r;
		last_v=v;
		}
		debug('normal:'+r+','+v+' l:'+last_r+','+last_v);
		series.push([r, v]);
	}else{
		last_r='';
		last_v='';
	}
	});
	return series;
}

function setupFlot(all_datasets, flotChart, options, flotGroup0) {
	/*
	  Plot a set of datasets using flot.

	  :param all_datasets: list of datasets. Should look like:

	  "series-1": {
	  label: "Label 1",
	  data: [[1988, 483994], [1989, 479060]]
	  },
	  "series-2": {
	  label: "Label 2",
	  data: [[1988, 218000], [1989, 203000]]
	  }
	*/
	// hard-code color indices to prevent them from shifting as
	// series are turned on/off
	var i = 0;
	$.each(all_datasets, function(key, val) {
	if(val.setid){
		val.color=(val.setid-1);
	}else{
		val.color = i;
		++i;
	}
	});

	// setup checkboxes
	var seriesList = flotChart.find(".flot-select-series");
	if(flotGroup0){
	var groups=[];
	for (var datasetKey in all_datasets) {
		var group=all_datasets[datasetKey].group;
		if(!groups[group]){
		groups[group]=1;
		var input = $('<input type="radio"></input>');
		input.attr('name', 'flot-radio');
		input.attr('value', group);
		input.attr('checked', 'checked');
		seriesList.append(input);
		seriesList.append(DisplayNames[group]);
		}
	}
	}else{
	for (var datasetKey in all_datasets) {
		var input = $('<input type="checkbox"></input>');
		input.attr('name', datasetKey);
		input.attr('value', datasetKey);
		input.attr('checked', 'checked');
		seriesList.append(input);
		seriesList.append(all_datasets[datasetKey].label);
	}
	}

	flotChart.find('.flot-chart-controls').find('input').live('click', function() {
	doFlotPlot(all_datasets, flotChart, options, flotGroup0);
	});

	// setup charttype
	var chartType = "lines";
	var x = flotChart.find(".flot-chart-type").find("input[value="+chartType+"]");
	x.attr("checked", true);
}

function doFlotPlot(all_datasets, flotChart, options, flotGroup0) {
	/*
	  :param options: optional set of options to be passed to flot plot.
	*/
	if (!options) {
	options = {};
	}

	// select datesets according to current state
	var datasets_to_plot = []
	var percent_flag=0;
	flotChart.find(".flot-select-series").find("input:checked").each(function () {
	var key = $(this).attr("value");
	if (key) {
		if(flotGroup0){
		// percentage on yaxis1
				if(ColDisplayTypes[key]){
		 		percent_flag=1;
		}
		var flotSet=flotGroup0[key];
		$.each(flotSet, function(i, keys) {
			if (all_datasets[keys]) {
			datasets_to_plot.push(all_datasets[keys]);
			}
		});
		}else{
		// percentage on yaxis2
				if(ColDisplayTypes[key]){
		 		percent_flag=2;
		}
		if (all_datasets[key]) {
			datasets_to_plot.push(all_datasets[key]);
		}
		}
	}
	});

	// yaxis percentage options
	if(percent_flag==1){
	options['yaxis'] = {
		tickFormatter: percentFormatter
	};
	options['y2axis'] = {};
	}else if(percent_flag==2){
	options['yaxis'] = {};
	options['y2axis'] = {
		tickFormatter: percentFormatter
	};
	}else{
	options['yaxis'] = {};
	options['y2axis'] = {};
	}

	// select plot type according to current state
	flotChart.find(".flot-chart-type").find("input:checked").each(function() {
	var value = $(this).attr("value");
	options[value] = { show: true };
	});

	// select range according to current state
	flotChart.find(".flot-select-range").find("input:checked").each(function() {
		var key=$(this).attr("value");
		if(key=='plusminusfive'){
			options['xaxis'] = { min: 2005, max: 2015 };
		}else{
		options['xaxis'] = {};
	}
	});
	var chartDiv = flotChart.find('.flot-chart')[0];
	$.plot(chartDiv, datasets_to_plot, options);
}

  function percentFormatter(val, axis) {
	  return (val * 100).toFixed(1) + " %";
  }
<|endoftext|>