<commit_before>import React, { PropTypes } from 'react'
import { View, StyleSheet, TouchableHighlight, Image, Platform } from 'react-native'
import Icon from '../icons/Icon'
import Text from '../text/Text'
import colors from '../config/colors'
import fonts from '../config/fonts'
import normalize from '../helpers/normalizeText'

let styles

const ListItem = ({
  onPress,
  title,
  leftIcon,
  rightIcon,
  avatar,
  avatarStyle,
  underlayColor,
  subtitle,
  subtitleStyle,
  containerStyle,
  wrapperStyle,
  titleStyle,
  hideChevron,
  chevronColor,
  roundAvatar,
  component,
  fontFamily,
  rightTitle,
  rightTitleContainerStyle,
  rightTitleStyle,
  subtitleContainerStyle,
}) => {
  let Component = onPress ? TouchableHighlight : View
  if (component) {
    Component = component
  }
  if (typeof avatar === 'string') {
    avatar = {uri: avatar}
  }
  return (
    <Component
      onPress={onPress}
      underlayColor={underlayColor}
      style={[styles.container, containerStyle && containerStyle]}>
      <View style={[styles.wrapper, wrapperStyle && wrapperStyle]}>
        {
          leftIcon && leftIcon.name && (
            <Icon
              type={leftIcon.type}
              iconStyle={[styles.icon, leftIcon.style && leftIcon.style]}
              name={leftIcon.name}
              color={leftIcon.color || colors.grey4}
            />
          )
        }
        {
          avatar && (
            <Image
              style={[
                styles.avatar,
                roundAvatar && {borderRadius: 17},
                avatarStyle && avatarStyle]}
              source={avatar}
              />
          )
        }
        <View style={styles.titleContainer}>
          <Text
            style={[
              styles.title,
              titleStyle && titleStyle,
              !leftIcon && {marginLeft: 10},
              fontFamily && {fontFamily}
            ]}>{title}</Text>
          {subtitle && (
            <View style={subtitleContainerStyle}>
              <Text
                style={[
                  styles.subtitle,
                  !leftIcon && {marginLeft: 10},
                  subtitleStyle && subtitleStyle,
                  fontFamily && {fontFamily}
                ]}>{subtitle}</Text>
            </View>
          )}
        </View>
        {
          !hideChevron && !rightTitle && (
            <View style={styles.chevronContainer}>
              <Icon
                type={rightIcon.type}
                style={styles.chevron}
                size={28}
                name={rightIcon.name}
                color={rightIcon.color || chevronColor} />
            </View>
          )
        }
        {
          rightTitle && (
            <View style={[styles.rightTitleContainer, rightTitleContainerStyle]}>
              <Text style={[styles.rightTitleStyle, rightTitleStyle]}>{rightTitle}</Text>
            </View>
          )
        }
      </View>
    </Component>
  )
}

ListItem.defaultProps = {
  underlayColor: 'white',
  chevronColor: colors.grey4,
  rightIcon: {name: 'chevron-right'},
  hideChevron: false,
  roundAvatar: false
}

ListItem.propTypes = {
  title: PropTypes.string,
  avatar: PropTypes.any,
  icon: PropTypes.any,
  onPress: PropTypes.func,
  rightIcon: PropTypes.object,
  underlayColor: PropTypes.string,
  subtitle: PropTypes.string,
  subtitleStyle: PropTypes.any,
  containerStyle: PropTypes.any,
  wrapperStyle: PropTypes.any,
  titleStyle: PropTypes.any,
  hideChevron: PropTypes.bool,
  chevronColor: PropTypes.string,
  roundAvatar: PropTypes.bool
}

styles = StyleSheet.create({
  avatar: {
    width: 34,
    height: 34
  },
  container: {
    padding: 10,
    borderBottomColor: '#ededed',
    borderBottomWidth: 1,
    backgroundColor: 'white'
  },
  wrapper: {
    flexDirection: 'row'
  },
  icon: {
    marginRight: 8
  },
  title: {
    fontSize: normalize(14),
    color: colors.grey1
  },
  subtitle: {
    color: colors.grey3,
    fontSize: normalize(12),
    marginTop: 1,
    ...Platform.select({
      ios: {
        fontWeight: '600'
      },
      android: {
        fontFamily: fonts.android.bold
      }
    })
  },
  titleContainer: {
    justifyContent: 'center',
    flex: 1,
  },
  chevronContainer: {
    flex: 0.15,
    alignItems: 'flex-end',
    justifyContent: 'center'
  },
  rightTitleContainer: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'center'
  },
  rightTitleStyle: {
    marginRight: 5,
    color: colors.grey4
  },
  chevron: {
  }
})

export default ListItem
<commit_msg>Allow list item title and subtitle to accept object proptype as well as string proptype<commit_after>import React, { PropTypes } from 'react'
import { View, StyleSheet, TouchableHighlight, Image, Platform } from 'react-native'
import Icon from '../icons/Icon'
import Text from '../text/Text'
import colors from '../config/colors'
import fonts from '../config/fonts'
import normalize from '../helpers/normalizeText'

let styles

const ListItem = ({
  onPress,
  title,
  leftIcon,
  rightIcon,
  avatar,
  avatarStyle,
  underlayColor,
  subtitle,
  subtitleStyle,
  containerStyle,
  wrapperStyle,
  titleStyle,
  hideChevron,
  chevronColor,
  roundAvatar,
  component,
  fontFamily,
  rightTitle,
  rightTitleContainerStyle,
  rightTitleStyle,
  subtitleContainerStyle,
}) => {
  let Component = onPress ? TouchableHighlight : View
  if (component) {
    Component = component
  }
  if (typeof avatar === 'string') {
    avatar = {uri: avatar}
  }
  return (
    <Component
      onPress={onPress}
      underlayColor={underlayColor}
      style={[styles.container, containerStyle && containerStyle]}>
      <View style={[styles.wrapper, wrapperStyle && wrapperStyle]}>
        {
          leftIcon && leftIcon.name && (
            <Icon
              type={leftIcon.type}
              iconStyle={[styles.icon, leftIcon.style && leftIcon.style]}
              name={leftIcon.name}
              color={leftIcon.color || colors.grey4}
            />
          )
        }
        {
          avatar && (
            <Image
              style={[
                styles.avatar,
                roundAvatar && {borderRadius: 17},
                avatarStyle && avatarStyle]}
              source={avatar}
              />
          )
        }
        <View style={styles.titleContainer}>
          <Text
            style={[
              styles.title,
              titleStyle && titleStyle,
              !leftIcon && {marginLeft: 10},
              fontFamily && {fontFamily}
            ]}>{title}</Text>
          {subtitle && (
            <View style={subtitleContainerStyle}>
              <Text
                style={[
                  styles.subtitle,
                  !leftIcon && {marginLeft: 10},
                  subtitleStyle && subtitleStyle,
                  fontFamily && {fontFamily}
                ]}>{subtitle}</Text>
            </View>
          )}
        </View>
        {
          !hideChevron && !rightTitle && (
            <View style={styles.chevronContainer}>
              <Icon
                type={rightIcon.type}
                style={styles.chevron}
                size={28}
                name={rightIcon.name}
                color={rightIcon.color || chevronColor} />
            </View>
          )
        }
        {
          rightTitle && (
            <View style={[styles.rightTitleContainer, rightTitleContainerStyle]}>
              <Text style={[styles.rightTitleStyle, rightTitleStyle]}>{rightTitle}</Text>
            </View>
          )
        }
      </View>
    </Component>
  )
}

ListItem.defaultProps = {
  underlayColor: 'white',
  chevronColor: colors.grey4,
  rightIcon: {name: 'chevron-right'},
  hideChevron: false,
  roundAvatar: false
}

ListItem.propTypes = {
  title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  avatar: PropTypes.any,
  icon: PropTypes.any,
  onPress: PropTypes.func,
  rightIcon: PropTypes.object,
  underlayColor: PropTypes.string,
  subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  subtitleStyle: PropTypes.any,
  containerStyle: PropTypes.any,
  wrapperStyle: PropTypes.any,
  titleStyle: PropTypes.any,
  hideChevron: PropTypes.bool,
  chevronColor: PropTypes.string,
  roundAvatar: PropTypes.bool
}

styles = StyleSheet.create({
  avatar: {
    width: 34,
    height: 34
  },
  container: {
    padding: 10,
    borderBottomColor: '#ededed',
    borderBottomWidth: 1,
    backgroundColor: 'white'
  },
  wrapper: {
    flexDirection: 'row'
  },
  icon: {
    marginRight: 8
  },
  title: {
    fontSize: normalize(14),
    color: colors.grey1
  },
  subtitle: {
    color: colors.grey3,
    fontSize: normalize(12),
    marginTop: 1,
    ...Platform.select({
      ios: {
        fontWeight: '600'
      },
      android: {
        fontFamily: fonts.android.bold
      }
    })
  },
  titleContainer: {
    justifyContent: 'center',
    flex: 1,
  },
  chevronContainer: {
    flex: 0.15,
    alignItems: 'flex-end',
    justifyContent: 'center'
  },
  rightTitleContainer: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'center'
  },
  rightTitleStyle: {
    marginRight: 5,
    color: colors.grey4
  },
  chevron: {
  }
})

export default ListItem
<|endoftext|>


<commit_before>(function($) {
  $(Screw).bind("before", function(){
    $('.it')
      .bind('passed', function(){
        java.lang.System.out.print(".");

        BlueRidge.CommandLine.passed++;
      })
      .bind('failed', function(e, reason){
        BlueRidge.CommandLine.failed++;

        BlueRidge.CommandLine.messages.push(BlueRidge.CommandLine.exampleName(this)
                                + '\n'
                                + reason
                                + '\n'
                                + 'in ' + BlueRidge.CommandLine.specFile
                                + '\n'
                                + (reason.rhinoException ? reason.rhinoException.scriptStackTrace + "\n" : "")
        );
      });
  });
})(jQuery);
<commit_msg>Mark failing JS specs with 'F' on the console report<commit_after>(function($) {
  $(Screw).bind("before", function(){
    $('.it')
      .bind('passed', function(){
        java.lang.System.out.print(".");

        BlueRidge.CommandLine.passed++;
      })
      .bind('failed', function(e, reason){
        java.lang.System.out.print("F");

        BlueRidge.CommandLine.failed++;

        BlueRidge.CommandLine.messages.push(BlueRidge.CommandLine.exampleName(this)
                                + '\n'
                                + reason
                                + '\n'
                                + 'in ' + BlueRidge.CommandLine.specFile
                                + '\n'
                                + (reason.rhinoException ? reason.rhinoException.scriptStackTrace + "\n" : "")
        );
      });
  });
})(jQuery);
<|endoftext|>


<commit_before>/**
 * @fileOverview The base Controller Class.
 */
var __  = require('lodash');
var crude = require('crude');

var tplHelpers = require('./tpl-helpers.js');

/**
 * Extend and augment the crude controller.
 *
 * @extends {crude.CrudeBaseCtrl}
 * @constructor
 */
var Controller = module.exports = crude.extend(function() {
  // define CRUD handlers
  this.create.unshift(this._prepResponse.bind(this));
  this.createView.unshift(this._prepResponse.bind(this));
  this.readOne.unshift(this._prepResponse.bind(this));
  this.update.unshift(this._prepResponse.bind(this));
  this.updateView.unshift(this._prepResponse.bind(this));
});

/** @define {string} The view key in which the output will be available.  */
Controller.VIEW_OUTPUT_KEY = 'crudView';

/**
 * Check if an error was passed through session flash.
 *
 * @param {Object} req The request Object.
 * @param {express.Result} res Express response object.
 */
Controller.prototype.checkFlashError = function(req, res) {
  res.locals.error =  !!req.flash('error').shift();
  if (res.locals.error) {
    var errObj = req.flash('errorObj').shift();
    if (!(errObj instanceof Object)) {
      errObj = {};
    }
    res.locals.errorMsg = req.flash('errorMsg').shift();
    res.locals.errorObj = errObj;
  }
};

/**
 * Check if an success message was passed through session flash.
 *
 * @param {Object} req The request Object.
 * @param {express.Result} res Express response object.
 */
Controller.prototype.checkFlashSuccess = function(req, res) {
  res.locals.success =  !!req.flash('success').shift();
  if (res.locals.success) {
    var successObj = req.flash('successObj').shift();
    if (!(successObj instanceof Object)) {
      successObj = {};
    }
    res.locals.successObj = successObj;
  }
};

/**
 * Add an Error instance to the view params.
 *
 * @param {express.Result} res Express response object.
 * @param {Error} err an instance or child of Error.
 */
Controller.prototype.addError = function(res, err) {
  res.locals.error =  true;
  res.locals.errorMsg = err.message;
  res.locals.errorObj = err;
};

/**
 * Add success message to the view params.
 *
 * @param {express.Result} res Express response object.
 * @param {Object=} obj Any Object.
 */
Controller.prototype.addSuccess = function(res, optObj) {
  res.locals.success =  true;
  res.locals.successObj = optObj || {};
};

/**
 * Add the error to the session flash.
 *
 * @param {Object} req The request Object.
 * @param {Error} err an instance or child of Error.
 */
Controller.prototype.addFlashError = function(req, err) {
  req.flash('error', true);
  req.flash('errorMsg', err.message);
  req.flash('errorObj', err);
};

/**
 * Add the success message / object to the session flash.
 *
 * @param {Object} req The request Object.
 * @param {Object=} obj Any Object.
 */
Controller.prototype.addFlashSuccess = function(req, obj) {
  req.flash('success', true);
  req.flash('successObj', obj);
};

/**
 * Prepare the response object for each request, an internal middleware.
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Function} next callback.
 * @protected
 */
Controller.prototype._prepResponse = function(req, res, next) {
  res.locals.opts = Object.create(this.opts);
  res.locals.opts.renderedBaseUrl = this.getBaseUrl(req);
  res.locals.schema = this.entity.getSchema();
  res.locals.currentUser = req.user;
  // all template functions
  res.locals.fn = {};
  __.extend(res.locals.fn, tplHelpers);
  next();
};

/**
 * Handle a successful outcome by either rendering or JSONing.
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Object} doc The document item.
 * @private
 */
Controller.prototype._handleSuccess = function(req, res, doc) {
  // assign the item to the tpl vars.
  res.locals.item = doc;
  // construct the item's url
  // var itemUrl = path.join(this.getBaseUrl(req, true), doc[this.opts.urlField]);
  // res.locals.item.itemUrl = path.normalize(itemUrl) + '/';

  this.checkFlashSuccess(req, res);

  if (this.opts.itemView) {
    return res.render(this.opts.itemView);
  }

  // render the template and store in response locals.
  res.locals[Controller.VIEW_OUTPUT_KEY] = this.compiled.view(res.locals);

  var status = 200;
  if (!doc) {
    status = 404;
  }
  if (this.opts.layoutView) {
    res.status(status).render(this.opts.layoutView);
  } else {
    res.status(status).send(res.locals[Controller.VIEW_OUTPUT_KEY]);
  }
};

/**
 * Handle an success outcome properly depending on request Content-Type
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Object} doc A document.
 * @private
 */
Controller.prototype._handleSuccessRedirect = function(req, res, doc) {
  res.status(200).json(this._sanitizeResult(doc));
  res.redirect(this.getBaseUrl(req, true) + '/' + doc[this.opts.urlField]);
};

/**
 * Handle an error properly depending on request Content-Type
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {string} redirectUrl Define a redirect url.
 * @param {Error} err Error.
 * @protected
 */
Controller.prototype._handleErrorRedirect = function(req, res, redirectUrl, err) {
  this.addFlashError(req, err);
  res.redirect(redirectUrl);
};
<commit_msg>more...<commit_after>/**
 * @fileOverview The base Controller Class.
 */
var __  = require('lodash');
var crude = require('crude');

var tplHelpers = require('./tpl-helpers.js');

/**
 * Extend and augment the crude controller.
 *
 * @extends {crude.CrudeBaseCtrl}
 * @constructor
 */
var Controller = module.exports = crude.extend(function() {
  // define CRUD handlers
  this.create.unshift(this._prepResponse.bind(this));
  this.readOne.unshift(this._prepResponse.bind(this));
  this.update.unshift(this._prepResponse.bind(this));

  this.createView = [
    this._prepResponse.bind(this),
    this.createOp.createView.bind(this.createOp),
  ];
  this.updateView = [
    this._prepResponse.bind(this),
    this.updateOp.updateView.bind(this.updateOp),
  ];
});

/** @define {string} The view key in which the output will be available.  */
Controller.VIEW_OUTPUT_KEY = 'crudView';

/**
 * Check if an error was passed through session flash.
 *
 * @param {Object} req The request Object.
 * @param {express.Result} res Express response object.
 */
Controller.prototype.checkFlashError = function(req, res) {
  res.locals.error =  !!req.flash('error').shift();
  if (res.locals.error) {
    var errObj = req.flash('errorObj').shift();
    if (!(errObj instanceof Object)) {
      errObj = {};
    }
    res.locals.errorMsg = req.flash('errorMsg').shift();
    res.locals.errorObj = errObj;
  }
};

/**
 * Check if an success message was passed through session flash.
 *
 * @param {Object} req The request Object.
 * @param {express.Result} res Express response object.
 */
Controller.prototype.checkFlashSuccess = function(req, res) {
  res.locals.success =  !!req.flash('success').shift();
  if (res.locals.success) {
    var successObj = req.flash('successObj').shift();
    if (!(successObj instanceof Object)) {
      successObj = {};
    }
    res.locals.successObj = successObj;
  }
};

/**
 * Add an Error instance to the view params.
 *
 * @param {express.Result} res Express response object.
 * @param {Error} err an instance or child of Error.
 */
Controller.prototype.addError = function(res, err) {
  res.locals.error =  true;
  res.locals.errorMsg = err.message;
  res.locals.errorObj = err;
};

/**
 * Add success message to the view params.
 *
 * @param {express.Result} res Express response object.
 * @param {Object=} obj Any Object.
 */
Controller.prototype.addSuccess = function(res, optObj) {
  res.locals.success =  true;
  res.locals.successObj = optObj || {};
};

/**
 * Add the error to the session flash.
 *
 * @param {Object} req The request Object.
 * @param {Error} err an instance or child of Error.
 */
Controller.prototype.addFlashError = function(req, err) {
  req.flash('error', true);
  req.flash('errorMsg', err.message);
  req.flash('errorObj', err);
};

/**
 * Add the success message / object to the session flash.
 *
 * @param {Object} req The request Object.
 * @param {Object=} obj Any Object.
 */
Controller.prototype.addFlashSuccess = function(req, obj) {
  req.flash('success', true);
  req.flash('successObj', obj);
};

/**
 * Prepare the response object for each request, an internal middleware.
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Function} next callback.
 * @protected
 */
Controller.prototype._prepResponse = function(req, res, next) {
  res.locals.opts = Object.create(this.opts);
  res.locals.opts.renderedBaseUrl = this.getBaseUrl(req);
  res.locals.schema = this.entity.getSchema();
  res.locals.currentUser = req.user;
  // all template functions
  res.locals.fn = {};
  __.extend(res.locals.fn, tplHelpers);
  next();
};

/**
 * Handle a successful outcome by either rendering or JSONing.
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Object} doc The document item.
 * @private
 */
Controller.prototype._handleSuccess = function(req, res, doc) {
  // assign the item to the tpl vars.
  res.locals.item = doc;
  // construct the item's url
  // var itemUrl = path.join(this.getBaseUrl(req, true), doc[this.opts.urlField]);
  // res.locals.item.itemUrl = path.normalize(itemUrl) + '/';

  this.checkFlashSuccess(req, res);

  if (this.opts.itemView) {
    return res.render(this.opts.itemView);
  }

  // render the template and store in response locals.
  res.locals[Controller.VIEW_OUTPUT_KEY] = this.compiled.view(res.locals);

  var status = 200;
  if (!doc) {
    status = 404;
  }
  if (this.opts.layoutView) {
    res.status(status).render(this.opts.layoutView);
  } else {
    res.status(status).send(res.locals[Controller.VIEW_OUTPUT_KEY]);
  }
};

/**
 * Handle an success outcome properly depending on request Content-Type
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {Object} doc A document.
 * @private
 */
Controller.prototype._handleSuccessRedirect = function(req, res, doc) {
  res.status(200).json(this._sanitizeResult(doc));
  res.redirect(this.getBaseUrl(req, true) + '/' + doc[this.opts.urlField]);
};

/**
 * Handle an error properly depending on request Content-Type
 *
 * @param {Object} req The request Object.
 * @param {Object} res The response Object.
 * @param {string} redirectUrl Define a redirect url.
 * @param {Error} err Error.
 * @protected
 */
Controller.prototype._handleErrorRedirect = function(req, res, redirectUrl, err) {
  this.addFlashError(req, err);
  res.redirect(redirectUrl);
};
<|endoftext|>


<commit_before>'use strict';

var asmCrypto = require('asmcrypto.js');
var subtle = global.crypto ? global.crypto.subtle || global.crypto.webkitSubtle : null;

var maxRoundsPreIteration = 10000;
var aesBlockSize = 16;
var credentialSize = 32;
var maxBufferSize = aesBlockSize * maxRoundsPreIteration;

function encrypt(credentials, key, rounds, callback) {
    var result = Promise.resolve();
    if (!subtle) {
        result = Promise.reject("No subtle crypto");
    } else {
        result = result
            .then(function() {
                return subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['encrypt']);
            })
            .then(function(encKey) {
                var resolvers = [];
                for (var idx=0; idx<credentialSize; idx += aesBlockSize) {
                    resolvers.push(encryptBlock(
                        credentials.subarray(idx, aesBlockSize), encKey, rounds));
                }
                return Promise.all(resolvers)
            })
            .then(function(results) {
                var concat = new Uint8Array(credentialSize);

                results.forEach(function(result, idx) {
                    var base = idx * aesBlockSize;
                    for (var i=0; i<aesBlockSize; ++i) {
                        concat[i + base] = result[i];
                    }
                });

                return concat;
            });
    }

    result.then(callback, function(err) {
        fallbackEncrypt(credentials, key, rounds, callback);
    });
}

function encryptBlock(iv, encKey, rounds, buffer) {
    if (!subtle) {
        return Promise.reject("No subtle crypto");
    }

    var actualRounds = rounds;
    var roundCap = buffer && buffer.length >= aesBlockSize ?
        Math.floor(buffer.length / aesBlockSize) : maxRoundsPreIteration;

    var result = Promise.resolve(iv);

    for (var roundsLeft = rounds; roundsLeft > 0; roundsLeft -= roundCap) {
        var actualRounds = Math.max(roundsLeft, roundsCap);
        var dataLen = actualRounds * aesBlockSize;
        if (!buffer) {
            buffer = new Uint8Array(dataLen);
        }
        var zeroData = buffer.length === dataLen ? buffer : buffer.subarray(0, dataLen);
        result = result
            .then(function (iv) {
                return subtle.encrypt({name: 'AES-CBC', iv: iv}, encKey, zeroData);
            }).then(function (data) {
                return new Uint8Array(data, (actualRounds - 1) * aesBlockSize, aesBlockSize);
            });
    }

    return result;
}

function fallbackEncrypt(credentials, key, rounds, callback) {
    return Promise.resolve(asmCrypto.AES_ECB.encrypt(credentials, key, false, rounds));
}

module.exports.encrypt = encrypt;
module.exports.fallbackEncrypt = fallbackEncrypt;
<commit_msg>Use promises only if crypto.subtle exists<commit_after>'use strict';

var asmCrypto = require('asmcrypto.js');
var subtle = global.crypto ? global.crypto.subtle || global.crypto.webkitSubtle : null;

var maxRoundsPreIteration = 10000;
var aesBlockSize = 16;
var credentialSize = 32;
var maxBufferSize = aesBlockSize * maxRoundsPreIteration;

function encrypt(credentials, key, rounds, callback) {
    if (!subtle) {
        fallbackEncrypt(credentials, key, rounds, callback);
        return;
    } else {
        Promise.resolve()
            .then(function() {
                return subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['encrypt']);
            })
            .then(function(encKey) {
                var resolvers = [];
                for (var idx=0; idx<credentialSize; idx += aesBlockSize) {
                    resolvers.push(encryptBlock(
                        credentials.subarray(idx, aesBlockSize), encKey, rounds));
                }
                return Promise.all(resolvers)
            })
            .then(function(results) {
                var concat = new Uint8Array(credentialSize);

                results.forEach(function(result, idx) {
                    var base = idx * aesBlockSize;
                    for (var i=0; i<aesBlockSize; ++i) {
                        concat[i + base] = result[i];
                    }
                });

                return concat;
            })
            .then(callback, function(err) {
                fallbackEncrypt(credentials, key, rounds, callback);
            });
    }
}

function encryptBlock(iv, encKey, rounds, buffer) {
    if (!subtle) {
        return Promise.reject("No subtle crypto");
    }

    var actualRounds = rounds;
    var roundCap = buffer && buffer.length >= aesBlockSize ?
        Math.floor(buffer.length / aesBlockSize) : maxRoundsPreIteration;

    var result = Promise.resolve(iv);

    for (var roundsLeft = rounds; roundsLeft > 0; roundsLeft -= roundCap) {
        var actualRounds = Math.max(roundsLeft, roundsCap);
        var dataLen = actualRounds * aesBlockSize;
        if (!buffer) {
            buffer = new Uint8Array(dataLen);
        }
        var zeroData = buffer.length === dataLen ? buffer : buffer.subarray(0, dataLen);
        result = result
            .then(function (iv) {
                return subtle.encrypt({name: 'AES-CBC', iv: iv}, encKey, zeroData);
            }).then(function (data) {
                return new Uint8Array(data, (actualRounds - 1) * aesBlockSize, aesBlockSize);
            });
    }

    return result;
}

function fallbackEncrypt(credentials, key, rounds, callback) {
    callback(asmCrypto.AES_ECB.encrypt(credentials, key, false, rounds));
}

module.exports.encrypt = encrypt;
module.exports.fallbackEncrypt = fallbackEncrypt;
<|endoftext|>


<commit_before>define(function(require) {

  var React = require('react/addons'),
    moment = require('moment'),
    RefreshComponent = require('components/projects/resources/instance/details/sections/metrics/RefreshComponent.react'),
    stores = require('stores');

  return React.createClass({

    getInitialState: function(){
      // start fetching the relevant models before the component is rendered
      stores.ImageRequestStore.fetchFirstPageWhere({new_machine_owner__username: stores.ProfileStore.get().id});
      return {};
    },

    onEditImage: function(requestId){
      modals.ImageModals.edit(stores.ImageRequestStore.get(requestId));
    },

    refreshHistory: function(){
      stores.ImageRequestStore.fetchFirstPageWhere({new_machine_owner__username: stores.ProfileStore.get().id});
      stores.ImageRequestStore.lastUpdated = Date.now();
      this.forceUpdate();
    },

    renderRefreshButton: function(){
      return (

            <RefreshComponent onRefreshClick = {this.refreshHistory} timestamp = {stores.ImageRequestStore.lastUpdated} delay = {1000 * 30} />

      );
    },

    render: function() {
      var username = stores.ProfileStore.get().id,
          imagingDocsUrl = "https://pods.iplantcollaborative.org/wiki/display/atmman/Requesting+an+Image+of+an+Instance";

      if(username == null){
        return

      }

      var requests = stores.ImageRequestStore.getAll();

      if(requests == null){
        return

;
      }

      if(!requests.models[0]){
        return (

              {"Looking for more information about the imaging process? Check out the "}
              documention on imaging.

You have not made any imaging requests.

        );
      }

      var displayRequests = requests.map(function(request){

        // set the color of the row based on the status of the request
        var trClass;
        switch(request.get('status').name){
          case "approved":
            trClass = "success";
            break;
          case "failed":
            trClass = "warning"
            break;
          default:
            trClass = "active"
            break;
        }

        var newMachineId = !!request.get('new_machine') ? request.get('new_machine').id : "N/A";

        return

                    {moment(request.get('start_date')).format("MMM D, YYYY")}
                    #{request.get('instance').id} - {request.get('instance').name}
                    {request.get('status').name}
                    {request.get('old_status')}
                    {newMachineId}

      }.bind(this));

      return (

            {"Looking for more information about the imaging process? Check out the "}
            documention on imaging.

          {this.renderRefreshButton()}

Date requested

Base instance

Status

Machine State

New Machine ID

              {displayRequests}

      );
    }

  });

});
<commit_msg>add css class to my image page refresh button<commit_after>define(function(require) {

  var React = require('react/addons'),
    moment = require('moment'),
    RefreshComponent = require('components/projects/resources/instance/details/sections/metrics/RefreshComponent.react'),
    stores = require('stores');

  return React.createClass({

    getInitialState: function(){
      // start fetching the relevant models before the component is rendered
      stores.ImageRequestStore.fetchFirstPageWhere({new_machine_owner__username: stores.ProfileStore.get().id});
      return {};
    },

    onEditImage: function(requestId){
      modals.ImageModals.edit(stores.ImageRequestStore.get(requestId));
    },

    refreshHistory: function(){
      stores.ImageRequestStore.fetchFirstPageWhere({new_machine_owner__username: stores.ProfileStore.get().id});
      stores.ImageRequestStore.lastUpdated = Date.now();
      this.forceUpdate();
    },

    renderRefreshButton: function(){
      return (

            <RefreshComponent onRefreshClick = {this.refreshHistory} timestamp = {stores.ImageRequestStore.lastUpdated} delay = {1000 * 30} />

      );
    },

    render: function() {
      var username = stores.ProfileStore.get().id,
          imagingDocsUrl = "https://pods.iplantcollaborative.org/wiki/display/atmman/Requesting+an+Image+of+an+Instance";

      if(username == null){
        return

      }

      var requests = stores.ImageRequestStore.getAll();

      if(requests == null){
        return

;
      }

      if(!requests.models[0]){
        return (

              {"Looking for more information about the imaging process? Check out the "}
              documention on imaging.

You have not made any imaging requests.

        );
      }

      var displayRequests = requests.map(function(request){

        // set the color of the row based on the status of the request
        var trClass;
        switch(request.get('status').name){
          case "approved":
            trClass = "success";
            break;
          case "failed":
            trClass = "warning"
            break;
          default:
            trClass = "active"
            break;
        }

        var newMachineId = !!request.get('new_machine') ? request.get('new_machine').id : "N/A";

        return

                    {moment(request.get('start_date')).format("MMM D, YYYY")}
                    #{request.get('instance').id} - {request.get('instance').name}
                    {request.get('status').name}
                    {request.get('old_status')}
                    {newMachineId}

      }.bind(this));

      return (

            {"Looking for more information about the imaging process? Check out the "}
            documention on imaging.

          {this.renderRefreshButton()}

Date requested

Base instance

Status

Machine State

New Machine ID

              {displayRequests}

      );
    }

  });

});
<|endoftext|>


<commit_before>/**
 * A Validation Menu to be appended to a Card for validation purposes.
 *
 * @param uiCardImage The html element to append the validation menu to.
 * @param cardProperties Properties of the label the validation menu is being appended to
 * @returns {ValidationMenu}
 * @constructor
 */
function ValidationMenu(uiCardImage, cardProperties, isCard) {
    const resultOptions = {
        "Agree": 1,
        "Disagree": 2,
        "NotSure": 3
    };

    let self = this;

    let currentCardProperties = cardProperties;

    let referenceCard = null;

    // A kind of wack way to do this, explore better options.
    const classToValidationOption = {
        "validate-agree": "Agree",
        "validate-disagree": "Disagree",
        "validate-not-sure": "NotSure"
    };
    const validationOptionToClass = {
        "Agree": "validate-agree",
        "Disagree": "validate-disagree",
        "NotSure": "validate-not-sure"
    };

    let currSelected = null;

    const overlayHTML = `

            <button id="gallery-card-agree-button" class="validation-button">${i18next.t('gallery:agree')}</button>
            <button id="gallery-card-disagree-button" class="validation-button">${i18next.t('gallery:disagree')}</button>
            <button id="gallery-card-not-sure-button" class="validation-button">${i18next.t('gallery:not-sure')}</button>

    `;
    let overlay = $(overlayHTML);

    let validationButtons = {
        "validate-agree": overlay.find("#gallery-card-agree-button"),
        "validate-disagree": overlay.find("#gallery-card-disagree-button"),
        "validate-not-sure": overlay.find("#gallery-card-not-sure-button")
    };

    // This is a regular DOM element, not jquery.
    let galleryCard = uiCardImage.parentElement;

    // Adds onClick functions for the validation buttons.
    function _init() {
        if (!isCard) {
            validationButtons["validate-agree"] = $(uiCardImage).find("#gallery-modal-agree");
            validationButtons["validate-disagree"] = $(uiCardImage).find("#gallery-modal-disagree");
            validationButtons["validate-not-sure"] = $(uiCardImage).find("#gallery-modal-not-sure");
            galleryCard = document.getElementsByClassName('gallery-modal').item(0);
        }
        for (const [valKey, button] of Object.entries(validationButtons)) {
            button.click(function() {
                _showValidated(classToValidationOption[valKey]);
                validateLabel(classToValidationOption[valKey]);
            });
        }
        // If the signed in user had already validated this label before loading the page, style the card to show that.
        if (currentCardProperties !== null && currentCardProperties.user_validation) {
            _showValidated(currentCardProperties.user_validation);
        }
        if (isCard) {
            uiCardImage.append(overlay[0]);
        }
    }

    // Sets the look of the card to show that the label has been validated.
    function _showValidated(validationOption) {
        const validationClass = validationOptionToClass[validationOption];

        // If the label had already been validated differently, remove the visual effects from the older validation.
        if (currSelected && currSelected !== validationClass) {
            if (isCard) {
                validationButtons[currSelected].attr('class', 'validation-button');
            }
            if (galleryCard.classList.contains(currSelected)) {
                galleryCard.classList.remove(currSelected);
            }
        }

        // Add the visual effects from the new validation.
        currSelected = validationClass;
        galleryCard.classList.add(validationClass);
        if (isCard) {
            validationButtons[validationClass].attr('class', 'validation-button-selected');
            referenceCard.setProperty('user_validation', validationOption);
        } else {
            referenceCard.validationMenu._showValidated(validationOption);
            referenceCard.updateValidationStatus(validationOption);
        }
    }

    /**
     * Consolidate data on the validation and submit as a POST request.
     *
     * @param action Validation result.
     * @private
     */
    function validateLabel(action) {
        console.log("validate method called");

        // TODO: do we need this log?
        sg.tracker.push("Validate_MenuClick=" + action);
        let validationTimestamp = new Date().getTime();

        let data = {
            label_id: currentCardProperties.label_id,
            label_type: currentCardProperties.label_type,
            validation_result: resultOptions[action],
            canvas_x: currentCardProperties.canvas_x,
            canvas_y: currentCardProperties.canvas_y,
            heading: currentCardProperties.heading,
            pitch: currentCardProperties.pitch,
            zoom: currentCardProperties.zoom,
            canvas_height: currentCardProperties.canvas_height,
            canvas_width: currentCardProperties.canvas_width,
            start_timestamp: validationTimestamp,
            end_timestamp: validationTimestamp,
            is_mobile: false
        };

        // Submit the validation via POST request.
        $.ajax({
            async: true,
            contentType: 'application/json; charset=utf-8',
            url: "/labelmap/validate",
            type: 'post',
            data: JSON.stringify(data),
            dataType: 'json',
            success: function (result) {
                showConfirmation(action);
            },
            error: function (result) {
                console.error(result);
            }
        });
    }

    /**
     * Confirm successful submit of validation.
     * TODO: Probably want to remove for prod or show confirmation through something else.
     *
     * @param {*} action Validation result.
     */
    function showConfirmation(action) {
        console.log(action + ": validation submitted successfully :)");
    }

    /**
     * Updates the card properties neccesary for validation.
     * @param {*} newProperties The properties to update to.
     */
    function updateCardProperties(newProperties) {
        currentCardProperties = newProperties;
    }

    /**
     * When using the ValidationMenu as a part of the Modal, the card the Modal is expanding is updated.
     *
     * @param {Card} newCard The new card the Modal references.
     */
    function updateReferenceCard(newCard) {
        referenceCard = newCard;
        galleryCard.classList.remove(validationOptionToClass["Agree"], validationOptionToClass["Disagree"], validationOptionToClass["NotSure"])
        _init();
    }

    self.updateCardProperties = updateCardProperties;
    self.updateReferenceCard = updateReferenceCard;
    self._showValidated = _showValidated;
    _init();
    return self;
}
<commit_msg>removed duplicate onclick binding to buttons<commit_after>/**
 * A Validation Menu to be appended to a Card for validation purposes.
 *
 * @param uiCardImage The html element to append the validation menu to.
 * @param cardProperties Properties of the label the validation menu is being appended to
 * @returns {ValidationMenu}
 * @constructor
 */
function ValidationMenu(uiCardImage, cardProperties, isCard) {
    const resultOptions = {
        "Agree": 1,
        "Disagree": 2,
        "NotSure": 3
    };

    let self = this;

    let currentCardProperties = cardProperties;

    let referenceCard = null;

    // A kind of wack way to do this, explore better options.
    const classToValidationOption = {
        "validate-agree": "Agree",
        "validate-disagree": "Disagree",
        "validate-not-sure": "NotSure"
    };
    const validationOptionToClass = {
        "Agree": "validate-agree",
        "Disagree": "validate-disagree",
        "NotSure": "validate-not-sure"
    };

    let currSelected = null;

    const overlayHTML = `

            <button id="gallery-card-agree-button" class="validation-button">${i18next.t('gallery:agree')}</button>
            <button id="gallery-card-disagree-button" class="validation-button">${i18next.t('gallery:disagree')}</button>
            <button id="gallery-card-not-sure-button" class="validation-button">${i18next.t('gallery:not-sure')}</button>

    `;
    let overlay = $(overlayHTML);

    let validationButtons = {
        "validate-agree": overlay.find("#gallery-card-agree-button"),
        "validate-disagree": overlay.find("#gallery-card-disagree-button"),
        "validate-not-sure": overlay.find("#gallery-card-not-sure-button")
    };

    // This is a regular DOM element, not jquery.
    let galleryCard = uiCardImage.parentElement;

    // Adds onClick functions for the validation buttons.
    function _init() {
        if (!isCard) {
            validationButtons["validate-agree"] = $(uiCardImage).find("#gallery-modal-agree");
            validationButtons["validate-disagree"] = $(uiCardImage).find("#gallery-modal-disagree");
            validationButtons["validate-not-sure"] = $(uiCardImage).find("#gallery-modal-not-sure");
            galleryCard = document.getElementsByClassName('gallery-modal').item(0);
        }
        for (const [valKey, button] of Object.entries(validationButtons)) {
            button.click(function() {
                _showValidated(classToValidationOption[valKey]);
                validateLabel(classToValidationOption[valKey]);
            });
        }
        // If the signed in user had already validated this label before loading the page, style the card to show that.
        if (currentCardProperties !== null && currentCardProperties.user_validation) {
            _showValidated(currentCardProperties.user_validation);
        }
        if (isCard) {
            uiCardImage.append(overlay[0]);
        }
    }

    // Sets the look of the card to show that the label has been validated.
    function _showValidated(validationOption) {
        const validationClass = validationOptionToClass[validationOption];

        // If the label had already been validated differently, remove the visual effects from the older validation.
        if (currSelected && currSelected !== validationClass) {
            if (isCard) {
                validationButtons[currSelected].attr('class', 'validation-button');
            }
            if (galleryCard.classList.contains(currSelected)) {
                galleryCard.classList.remove(currSelected);
            }
        }

        // Add the visual effects from the new validation.
        currSelected = validationClass;
        galleryCard.classList.add(validationClass);
        if (isCard) {
            validationButtons[validationClass].attr('class', 'validation-button-selected');
            referenceCard.setProperty('user_validation', validationOption);
        } else {
            referenceCard.validationMenu._showValidated(validationOption);
            referenceCard.setProperty('user_validation', validationOption);
        }
    }

    /**
     * Consolidate data on the validation and submit as a POST request.
     *
     * @param action Validation result.
     * @private
     */
    function validateLabel(action) {
        console.log("validate method called");

        // TODO: do we need this log?
        sg.tracker.push("Validate_MenuClick=" + action);
        let validationTimestamp = new Date().getTime();

        let data = {
            label_id: currentCardProperties.label_id,
            label_type: currentCardProperties.label_type,
            validation_result: resultOptions[action],
            canvas_x: currentCardProperties.canvas_x,
            canvas_y: currentCardProperties.canvas_y,
            heading: currentCardProperties.heading,
            pitch: currentCardProperties.pitch,
            zoom: currentCardProperties.zoom,
            canvas_height: currentCardProperties.canvas_height,
            canvas_width: currentCardProperties.canvas_width,
            start_timestamp: validationTimestamp,
            end_timestamp: validationTimestamp,
            is_mobile: false
        };

        // Submit the validation via POST request.
        $.ajax({
            async: true,
            contentType: 'application/json; charset=utf-8',
            url: "/labelmap/validate",
            type: 'post',
            data: JSON.stringify(data),
            dataType: 'json',
            success: function (result) {
                showConfirmation(action);
            },
            error: function (result) {
                console.error(result);
            }
        });
    }

    /**
     * Confirm successful submit of validation.
     * TODO: Probably want to remove for prod or show confirmation through something else.
     *
     * @param {*} action Validation result.
     */
    function showConfirmation(action) {
        console.log(action + ": validation submitted successfully :)");
    }

    /**
     * Updates the card properties neccesary for validation.
     * @param {*} newProperties The properties to update to.
     */
    function updateCardProperties(newProperties) {
        currentCardProperties = newProperties;
    }

    /**
     * When using the ValidationMenu as a part of the Modal, the card the Modal is expanding is updated.
     *
     * @param {Card} newCard The new card the Modal references.
     */
    function updateReferenceCard(newCard) {
        referenceCard = newCard;
        galleryCard.classList.remove(validationOptionToClass["Agree"], validationOptionToClass["Disagree"], validationOptionToClass["NotSure"])
        if (currentCardProperties !== null && currentCardProperties.user_validation) {
            _showValidated(currentCardProperties.user_validation);
        }
    }

    self.updateCardProperties = updateCardProperties;
    self.updateReferenceCard = updateReferenceCard;
    self._showValidated = _showValidated;
    _init();
    return self;
}
<|endoftext|>


<commit_before>/**
 * A Keyboard module.
 *

 * @returns {{className: string}}
 * @constructor
 */
function Keyboard (svl, canvas, contextMenu, ribbon, zoomControl) {
    var self = this;
    var status = {
        focusOnTextField: false,
        isOnboarding: false,
        shiftDown: false
    };

    // Move in the direction of a link closest to a given angle.
    // Todo: Get rid of dependency to svl.panorama. Inject a streetViewMap into this module and use its interface.
    // Todo. Make the method name more descriptive.
    this._movePano = function (angle) {
        // take the cosine of the difference for each link to the current heading in radians and stores them to an array
        var cosines = svl.panorama.links.map(function(link) {
            var headingAngleOffset = util.math.toRadians(svl.panorama.pov.heading + angle) - util.math.toRadians(link.heading);
            return Math.cos(headingAngleOffset);
        });
        var maxVal = Math.max.apply(null, cosines);
        var maxIndex = cosines.indexOf(maxVal);
        if(cosines[maxIndex] > 0.5){
            svl.panorama.setPano(svl.panorama.links[maxIndex].pano);
        }
    };

    this._moveForward = function (){
        this._movePano(0);
    };

    this._moveBackward = function (){
        this._movePano(180);
    };

    /**
     * Change the heading of the current panorama point of view by a particular degree value
     * Todo. Change the method name so it is more descriptive.
     * @param degree
     */
    this._rotatePov = function (degree){
        var heading =  svl.panorama.pov.heading;
        var pitch = svl.panorama.pov.pitch;
        var zoom = svl.panorama.pov.zoom;
        heading = (heading + degree + 360) % 360;
        svl.panorama.setPov({heading: heading, pitch: pitch, zoom: zoom});
    };

    /**
     * This is a callback for a key down event
     * @param {object} e An event object
     * @private
     */
    this._documentKeyDown = function (e) {
        // The callback method that is triggered with a keyUp event.
        if (contextMenu.isOpen()) {
            return;
        } else if (!status.focusOnTextField) {
            // lock scrolling in response to key pressing
            switch (e.keyCode) {
                case 16:  // "Shift"
                    status.shiftDown = true;
                    break;
                case 37:  // "Left"
                    self._rotatePov(-2);
                    break;
                case 39:  // "Right"
                    self._rotatePov(2);
                    break;
                case 38:
                    self._moveForward();
                    break;
                case 40:  // "down"
                    self._moveBackward();
                    break;
            }

            if([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
                e.preventDefault();
            }
        }
    };

    /**
     * This is a callback for a key up event.
     * @param {object} e An event object
     * @private
     */
    this._documentKeyUp = function (e) {
        if (svl.isOnboarding()) {
            // Don't allow users to use keyboard shortcut during the onboarding.
            return;
        }

        /*
         This is a callback method that is triggered when a keyDown
         event occurs and focus is not on ContextMenu's textbox.
         */
        if (!status.focusOnTextField) {
            var label;
            switch (e.keyCode) {
                case 16:
                    // "Shift"
                    status.shiftDown = false;
                    break;
                case 49:  // "1"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(1);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 1);
                        }
                    }
                    else{
                        ribbon.modeSwitchClick("CurbRamp");
                        break;
                    }
                    break;
                case 50:  // "2"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(2);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 2);
                        }
                    } else {
                        ribbon.modeSwitchClick("NoCurbRamp");
                    }
                    break;
                case 51:  // "3"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(3);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 3);
                        }
                    } else {
                        ribbon.modeSwitchClick("Obstacle");
                    }
                    break;
                case 52:  // "4"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(4);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 4);
                        }
                    } else {
                        ribbon.modeSwitchClick("SurfaceProblem");
                    }
                    break;
                case 53:  // "5"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(5);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 5);
                        }
                    }
                    break;
                case 66:
                    // "b" for a blocked view
                    ribbon.modeSwitch("Occlusion");
                    break;
                case 67:
                    // "c" for CurbRamp. Switch the mode to the CurbRamp labeling mode.
                    ribbon.modeSwitch("CurbRamp");
                    break;
                case 69:
                    // "e" for Explore. Switch the mode to Walk (camera) mode.
                    ribbon.modeSwitch("Walk");
                    break;
                case 77:
                    // "m" for MissingCurbRamp. Switch the mode to the MissingCurbRamp labeling mode.
                    ribbon.modeSwitch("NoCurbRamp");
                    break;
                case 78:
                    ribbon.modeSwitch("NoSidewalk");
                    break;
                case 79:
                    // "o" for Obstacle
                    ribbon.modeSwitch("Obstacle");
                    break;
                case 83:
                    ribbon.modeSwitch("SurfaceProblem");
                    break;
                case 90:
                    // "z" for zoom. By default, it will zoom in. If "shift" is down, it will zoom out.
                    if (status.shiftDown) {
                        // Zoom out
                        zoomControl.zoomOut();
                    } else {
                        // Zoom in
                        zoomControl.zoomIn();
                    }
            }
        }

        /*
         This is a callback method that is triggered when a keyDown
         event occurs. It is not relevant to ContextMenu's textbox focus.
         */
        switch (e.keyCode) {
            case 13:
                // "Enter"
                if (contextMenu.isOpen()) {
                    contextMenu.hide();
                }
                break;
            case 27:
                // "Escape"
                if (canvas.getStatus('drawing')) {
                    canvas.cancelDrawing();
                } else {
                    ribbon.backToWalk();
                }
                break;
        }

        contextMenu.updateRadioButtonImages();
    };

    /**
     * Get status
     * @param {string} key Field name
     * @returns {*}
     */
    this.getStatus = function  (key) {
        if (!(key in status)) {
            console.warn("You have passed an invalid key for status.")
        }
        return status[key];
    };

    /**
     * This method returns whether a shift key is currently pressed or not.
     * @returns {boolean}
     */
    this.isShiftDown = function () {
        return status.shiftDown;
    };

    /**
     * Set status
     * @param key Field name
     * @param value Field value
     * @returns {setStatus}
     */
    this.setStatus = function (key, value) {
        if (key in status) {
            status[key] = value;
        }
    };

    $(document).bind('keyup', this._documentKeyUp);
    $(document).bind('keydown', this._documentKeyDown);
}
<commit_msg>Update comments<commit_after>/**
 * A Keyboard module.
 *

 * @returns {{className: string}}
 * @constructor
 */
function Keyboard (svl, canvas, contextMenu, ribbon, zoomControl) {
    var self = this;
    var status = {
        focusOnTextField: false,
        isOnboarding: false,
        shiftDown: false
    };

    // Move in the direction of a link closest to a given angle.
    // Todo: Get rid of dependency to svl.panorama. Inject a streetViewMap into this module and use its interface.
    // Todo. Make the method name more descriptive.
    this._movePano = function (angle) {
        // take the cosine of the difference for each link to the current heading in radians and stores them to an array
        var cosines = svl.panorama.links.map(function(link) {
            var headingAngleOffset = util.math.toRadians(svl.panorama.pov.heading + angle) - util.math.toRadians(link.heading);
            return Math.cos(headingAngleOffset);
        });
        var maxVal = Math.max.apply(null, cosines);
        var maxIndex = cosines.indexOf(maxVal);
        if(cosines[maxIndex] > 0.5){
            svl.panorama.setPano(svl.panorama.links[maxIndex].pano);
        }
    };

    this._moveForward = function (){
        this._movePano(0);
    };

    this._moveBackward = function (){
        this._movePano(180);
    };

    /**
     * Change the heading of the current panorama point of view by a particular degree value
     * Todo. Change the method name so it is more descriptive.
     * @param degree
     */
    this._rotatePov = function (degree){
        var heading =  svl.panorama.pov.heading;
        var pitch = svl.panorama.pov.pitch;
        var zoom = svl.panorama.pov.zoom;
        heading = (heading + degree + 360) % 360;
        svl.panorama.setPov({heading: heading, pitch: pitch, zoom: zoom});
    };

    /**
     * This is a callback for a key down event
     * @param {object} e An event object
     * @private
     */
    this._documentKeyDown = function (e) {
        // The callback method that is triggered with a keyUp event.
        if (contextMenu.isOpen()) {
            return;
        } else if (!status.focusOnTextField) {
            // lock scrolling in response to key pressing
            switch (e.keyCode) {
                case 16:  // "Shift"
                    status.shiftDown = true;
                    break;
                case 37:  // "Left"
                    self._rotatePov(-2);
                    break;
                case 39:  // "Right"
                    self._rotatePov(2);
                    break;
                case 38:
                    self._moveForward();
                    break;
                case 40:  // "down"
                    self._moveBackward();
                    break;
            }

            if([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
                e.preventDefault();
            }
        }
    };

    /**
     * This is a callback for a key up event.
     * @param {object} e An event object
     * @private
     */
    this._documentKeyUp = function (e) {
        if (svl.isOnboarding()) {
            // Don't allow users to use keyboard shortcut during the onboarding.
            return;
        }

        /*
         This is a callback method that is triggered when a keyUp
         event occurs and focus is not on ContextMenu's textbox.
         */
        if (!status.focusOnTextField) {
            var label;
            switch (e.keyCode) {
                case 16:
                    // "Shift"
                    status.shiftDown = false;
                    break;
                case 49:  // "1"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(1);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 1);
                        }
                    }
                    else{
                        ribbon.modeSwitchClick("CurbRamp");
                        break;
                    }
                    break;
                case 50:  // "2"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(2);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 2);
                        }
                    } else {
                        ribbon.modeSwitchClick("NoCurbRamp");
                    }
                    break;
                case 51:  // "3"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(3);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 3);
                        }
                    } else {
                        ribbon.modeSwitchClick("Obstacle");
                    }
                    break;
                case 52:  // "4"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(4);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 4);
                        }
                    } else {
                        ribbon.modeSwitchClick("SurfaceProblem");
                    }
                    break;
                case 53:  // "5"
                    if (contextMenu.isOpen()) {
                        contextMenu.checkRadioButton(5);
                        label = contextMenu.getTargetLabel();
                        if (label) {
                            label.setProperty('severity', 5);
                        }
                    }
                    break;
                case 66:
                    // "b" for a blocked view
                    ribbon.modeSwitch("Occlusion");
                    break;
                case 67:
                    // "c" for CurbRamp. Switch the mode to the CurbRamp labeling mode.
                    ribbon.modeSwitch("CurbRamp");
                    break;
                case 69:
                    // "e" for Explore. Switch the mode to Walk (camera) mode.
                    ribbon.modeSwitch("Walk");
                    break;
                case 77:
                    // "m" for MissingCurbRamp. Switch the mode to the MissingCurbRamp labeling mode.
                    ribbon.modeSwitch("NoCurbRamp");
                    break;
                case 78:
                    ribbon.modeSwitch("NoSidewalk");
                    break;
                case 79:
                    // "o" for Obstacle
                    ribbon.modeSwitch("Obstacle");
                    break;
                case 83:
                    ribbon.modeSwitch("SurfaceProblem");
                    break;
                case 90:
                    // "z" for zoom. By default, it will zoom in. If "shift" is down, it will zoom out.
                    if (status.shiftDown) {
                        // Zoom out
                        zoomControl.zoomOut();
                    } else {
                        // Zoom in
                        zoomControl.zoomIn();
                    }
            }
        }

        /*
         This is a callback method that is triggered when a keyUp
         event occurs. It is not relevant to ContextMenu's textbox focus.
         */
        switch (e.keyCode) {
            case 13:
                // "Enter"
                if (contextMenu.isOpen()) {
                    contextMenu.hide();
                }
                break;
            case 27:
                // "Escape"
                if (canvas.getStatus('drawing')) {
                    canvas.cancelDrawing();
                } else {
                    ribbon.backToWalk();
                }
                break;
        }

        contextMenu.updateRadioButtonImages();
    };

    /**
     * Get status
     * @param {string} key Field name
     * @returns {*}
     */
    this.getStatus = function  (key) {
        if (!(key in status)) {
            console.warn("You have passed an invalid key for status.")
        }
        return status[key];
    };

    /**
     * This method returns whether a shift key is currently pressed or not.
     * @returns {boolean}
     */
    this.isShiftDown = function () {
        return status.shiftDown;
    };

    /**
     * Set status
     * @param key Field name
     * @param value Field value
     * @returns {setStatus}
     */
    this.setStatus = function (key, value) {
        if (key in status) {
            status[key] = value;
        }
    };

    $(document).bind('keyup', this._documentKeyUp);
    $(document).bind('keydown', this._documentKeyDown);
}
<|endoftext|>


<commit_before>'use strict';

// Posts controller
angular.module('posts').controller('PostsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Posts','$http',
	function($scope, $stateParams, $location, Authentication, Posts,$http) {
		$scope.authentication = Authentication;

		// Create new Post
		$scope.create = function() {
            $http.post('/posts', $scope.fields).success(function(response) {
                // And redirect to the index page
                //$location.path('/posts'+response);
                console.log(response);
            }).error(function(response) {
                $scope.error = response.message;
            });
        };

		// Remove existing Post
		$scope.remove = function(post) {
			if ( post ) {
				post.$remove();

				for (var i in $scope.posts) {
					if ($scope.posts [i] === post) {
						$scope.posts.splice(i, 1);
					}
				}
			} else {
				$scope.post.$remove(function() {
					$location.path('posts');
				});
			}
		};

		// Update existing Post
		$scope.update = function() {
			var post = $scope.post;

			post.$update(function() {
				$location.path('posts/' + post._id);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		// Find a list of Posts
		$scope.find = function() {
			$scope.posts = Posts.query();
		};

		// Find existing Post
		$scope.findOne = function() {
			$scope.post = Posts.get({
				postId: $stateParams.postId
			});
		};
	}
]);
<commit_msg>Update post client router<commit_after>'use strict';

// Posts controller
angular.module('posts').controller('PostsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Posts','$http',
	function($scope, $stateParams, $location, Authentication, Posts,$http) {
		$scope.authentication = Authentication;

		// Create new Post
		$scope.create = function() {
            $http.post('/posts', $scope.fields).success(function(response) {
                // And redirect to the index page
                $location.path('/posts/'+response);
            }).error(function(response) {
                $scope.error = response.message;
            });
        };

		// Remove existing Post
		$scope.remove = function(post) {
			if ( post ) {
				post.$remove();

				for (var i in $scope.posts) {
					if ($scope.posts [i] === post) {
						$scope.posts.splice(i, 1);
					}
				}
			} else {
				$scope.post.$remove(function() {
					$location.path('posts');
				});
			}
		};

		// Update existing Post
		$scope.update = function() {
			var post = $scope.post;

			post.$update(function() {
				$location.path('posts/' + post._id);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		// Find a list of Posts
		$scope.find = function() {
			$scope.posts = Posts.query();
		};

		// Find existing Post
		$scope.findOne = function() {
			$scope.post = Posts.get({
				postId: $stateParams.postId
			});
		};
	}
]);
<|endoftext|>


<commit_before>'use strict';

var Contacts = {
  _loaded: false,
  get view() {
    delete this.view;
    return this.view = document.getElementById('contacts-view-scrollable');
  },

  setup: function contactsSetup() {
    document.getElementById('contacts').addEventListener('change',
      (function contactTabChanged(evt) {
        // loading contacts the first time the view appears
        this.load();

        ContactDetails.hide();
      }).bind(this));
  },

  load: function contactsLoad() {
    if (this._loaded) {
      return;
    }

    this.find(this.show.bind(this));
  },

  reload: function contactsReload() {
    this._loaded = false;
    this.load();
  },

  find: function contactsFind(callback) {
    // Ideally I would like to choose the ordering
    var request = window.navigator.mozContacts.find({});
    request.onsuccess = function findCallback() {
      var contacts = request.result;
      contacts.sort(function contactsSort(a, b) {
        return a.familyName[0].toUpperCase() > b.familyName[0].toUpperCase();
      });
      callback(contacts);
    };
  },

  findByNumber: function findByNumber(number, callback) {
    var options = {
      filterBy: ['tel'],
      filterOp: 'contains',
      filterValue: number
    };
    var request = window.navigator.mozContacts.find(options);
    request.onsuccess = function findCallback() {
      if (request.result.length == 0)
        return;

      var contacts = request.result;
      callback(contacts[0]);
    };
  },

  show: function contactsShow(contacts) {
    var content = '';
    var currentLetter = '';

    var count = contacts.length;
    for (var i = 0; i < count; i++) {
      var contact = contacts[i];

      var name = contact.familyName[0];
      var letter = name ? name[0].toUpperCase() : '';
      if (currentLetter != letter) {
        currentLetter = letter;

        content += '
' +
                   '' +
                      currentLetter +
                   '
';
      }

      content += '
';
      content += '' + contact.givenName + ' ';
      content += '' + contact.familyName + '';
      content += '
';
    }

    var contactsContainer = document.getElementById('contacts-container');
    contactsContainer.innerHTML = content;
    this.filter();

    this._loaded = true;
  },

  filter: function contactsFilter(value) {
    var pattern = new RegExp(value, 'i');
    var container = document.getElementById('contacts-container');
    var contacts = container.children;

    var count = contacts.length;
    for (var i = 0; i < count; i++) {
      var contact = contacts[i];
      if (contact.className == 'contact-header')
        continue;

      contact.hidden = !pattern.test(contact.textContent);
    }

    // If there is 0 childs for a particular letter, hide it.
    var enabledLetters = [];
    for (var i = 0; i < count; i++) {
      var contactHeader = contacts[i];
      if (contactHeader.className != 'contact-header')
        continue;

      var nextSibling = contactHeader.nextSibling;
      while (nextSibling && nextSibling.className == 'contact') {
        if (!nextSibling.hidden) {
          enabledLetters.push(contactHeader.id);
          break;
        }
        nextSibling = nextSibling.nextSibling;
      }
    }

    // Reflect the change in the shortcut letter
    var shortcuts = document.getElementById('contacts-shortcuts').children;
    for (var j = 0; j < shortcuts.length; j++) {
      var shortcut = shortcuts[j];
      var targetId = shortcut.name;
      var header = document.getElementById(targetId);

      var disabled = (enabledLetters.indexOf(targetId) == -1);
      if (header && disabled) {
        shortcut.setAttribute('data-disabled', 'true');
        header.hidden = true;
      } else if (disabled) {
        shortcut.setAttribute('data-disabled', 'true');
      } else {
        shortcut.removeAttribute('data-disabled');
        header.hidden = false;
      }
    }
  },

  anchor: function contactsAnchor(targetId) {
    var target = document.getElementById(targetId);
    if (!target)
      return;

    var top = target.getBoundingClientRect().top;
    var scrollable = document.getElementById('contacts-view-scrollable');
    var scrollableTop = scrollable.getBoundingClientRect().top;
    scrollable.scrollTop = (top - scrollableTop) + scrollable.scrollTop;
  },

  showDetails: function contactsShowDetails(evt) {
    var contactId = evt.target.id;

    var options = {
      filterBy: ['id'],
      filterOp: 'equals',
      filterValue: contactId
    };
    var request = window.navigator.mozContacts.find(options);
    request.onsuccess = function findCallback() {
      if (request.result == 0)
        return;

      var contacts = request.result;
      ContactDetails.show(contacts[0]);
    };
  },

  create: function contactsCreate() {
    // creating an empty contact
    var contact = new mozContact();
    contact.init({tel: '', email: ''});

    ContactDetails.show(contact);
  }
};

var ShortcutsHandler = {
  setup: function sh_setup() {
    ['touchstart', 'touchmove', 'touchend'].forEach((function(evt) {
      this.shortcutsBar.addEventListener(evt, this, true);
    }).bind(this));
  },

  get shortcutsBar() {
    delete this.shortcutsBar;
    return this.shortcutsBar = document.getElementById('contacts-shortcuts');
  },

  get shortcutsBackground() {
    delete this.shortcutsBackground;
    var id = 'contacts-shortcuts-background';
    return this.shortcutsBackground = document.getElementById(id);
  },

  handleEvent: function sh_handleEvent(evt) {
    // preventing the events from bubbling to the contacts list
    evt.preventDefault();

    switch (evt.type) {
      case 'touchstart':
        this.startTracking();
      case 'touchmove': // fall through
        this.anchorForPosition(evt.targetTouches[0].clientY);
        break;

      case 'touchend':
        this.stopTracking();
        break;
    }
  },

  startTracking: function sh_startTracking() {
    this.shortcutsBackground.classList.add('tracking');

    // we keep a reference to the horizontal center of the zone
    // it allows us to keep anchoring correctly if the user gets
    // out of the zone while swiping
    var rect = this.shortcutsBar.getBoundingClientRect();
    this._positionX = rect.left + (rect.width / 2);
  },
  stopTracking: function sh_stopTracking() {
    this.shortcutsBackground.classList.remove('tracking');
    delete this._positionX;
  },
  anchorForPosition: function sh_anchorForPosition(positionY) {
    // only inspecting the vertical point of the touch
    var target = document.elementFromPoint(this._positionX, positionY).name;
    Contacts.anchor(target);
  }
};

var ContactDetails = {
  _editing: false,
  _lastFocusedInput: null,

  setup: function cd_setup() {
    window.addEventListener('keyup', this, true);

    // Binding to properly handle the return key
    var inputs = this.container.querySelectorAll('input');
    for (var i = 0; i < inputs.length; i++) {
      inputs[i].onkeypress = (function cd_inputKeyPress(event) {
        if (event.keyCode == event.DOM_VK_RETURN) {
          this.focusNextField();
          return false;
        }
      }).bind(this);
    }

    // click outside details container to close
    this.overlay.addEventListener('click', function(evt) {
      ContactDetails.hide();
    });
    this.container.addEventListener('click', function(evt) {
      evt.stopPropagation();
    });
  },
  get overlay() {
    delete this.overlay;
    return this.overlay = document.getElementById('contacts-overlay');
  },
  get container() {
    delete this.container;
    return this.container =
      document.getElementById('contact-details-container');
  },
  get view() {
    delete this.view;
    return this.view = document.getElementById('contact-details-view');
  },

  get contactName() {
    delete this.contactName;
    return this.contactName = document.getElementById('contact-name');
  },
  get contactGivenNameField() {
    delete this.contactGivenNameField;
    var id = 'contact-given-name-field';
    return this.contactGivenNameField = document.getElementById(id);
  },
  get contactFamilyNameField() {
    delete this.contactFamilyNameField;
    var id = 'contact-family-name-field';
    return this.contactFamilyNameField = document.getElementById(id);
  },

  get contactPhone() {
    delete this.contactPhone;
    return this.contactPhone = document.getElementById('contact-phone');
  },
  get contactPhoneField() {
    delete this.contactPhoneField;
    var id = 'contact-phone-field';
    return this.contactPhoneField = document.getElementById(id);
  },

  get contactEmail() {
    delete this.contactEmail;
    return this.contactEmail = document.getElementById('contact-email');
  },
  get contactEmailField() {
    delete this.contactEmailField;
    var id = 'contact-email-field';
    return this.contactEmailField = document.getElementById(id);
  },

  set contact(contact) {
    delete this._contact;
    this._contact = contact;
    this.render();
  },

  execute: function cd_execute(evt) {
    var action = evt.currentTarget.dataset.action;
    if (!this[action]) {
      this.hide();
      return;
    }

    this[action](evt);
  },

  show: function cd_show(contact) {
    if (typeof contact != 'undefined') {
      this.contact = contact;
    }

    var overlay = this.overlay;
    overlay.classList.add('displayed');

    // directly entering the edit mode if this is a new contact
    var self = this;
    if (this._contact.id == 'undefined') {
      overlay.addEventListener('transitionend', function trWait() {
        overlay.removeEventListener('transitionend', trWait);
        self.edit();
      });
    }
  },

  hide: function cd_hide() {
    if (!this.overlay.classList.contains('displayed')) {
      return false;
    }

    var overlay = this.overlay;
    overlay.classList.add('hidden');
    overlay.addEventListener('transitionend', function fadeWait() {
      overlay.removeEventListener('transitionend', fadeWait);

      overlay.classList.remove('hidden');
      overlay.classList.remove('displayed');
    });

    this.endEditing();
    return true;
  },

  edit: function cd_edit() {
    if (this._editing) {
      return;
    }
    this._editing = true;

    this.view.classList.add('editing');

    // setting a min-height in preparation for the keyboard appearance
    var minHeight = this.container.getBoundingClientRect().height;
    this.container.style.minHeight = minHeight + 'px';
  },

  save: function cd_save(form) {
    if (form.checkValidity()) {
      var contact = this._contact;

      contact.givenName = this.contactGivenNameField.value;
      contact.familyName = this.contactFamilyNameField.value;
      contact.name = contact.givenName + ' ' + contact.familyName;

      if (this.contactPhoneField.value.length)
        contact.tel = [this.contactPhoneField.value];
      if (this.contactEmailField.value.length)
        contact.email = [this.contactEmailField.value];

      var req = navigator.mozContacts.save(contact);
      req.onsuccess = (function() {
        this.render();
        this.endEditing();
        Contacts.reload();
      }.bind(this));
    }
  },

  destroy: function cd_destroy(evt) {

    var req = navigator.mozContacts.remove(this._contact);
    req.onsuccess = (function() {
      this.render();
      this.hide();
      Contacts.reload();
    }.bind(this));

    evt.preventDefault();
  },

  call: function cd_call(evt) {
    if (this._editing) {
      return;
    }

    var number = evt.target.dataset.number;
    if (number) {
      CallHandler.call(number);
    }
  },

  endEditing: function cd_endEditing() {
    if (!this._editing) {
      return false;
    }
    this._editing = false;

    this.view.classList.remove('editing');
    return true;
  },

  // scrolling to the right position when one of the fields
  // takes focus
  autoscroll: function cd_autoscroll(event) {
    this._lastFocusedInput = event.currentTarget;
    var element = this.nextField(event.currentTarget);
    var self = this;

    var scrollInPlace = function cd_autoscrollMove() {
      element.scrollIntoView(false);
    };
    scrollInPlace();

    //also listening to the next resize for keyboard handling
    window.addEventListener('resize', function cd_afterResize() {
      window.removeEventListener('resize', cd_afterResize);

      scrollInPlace();
    });
  },

  focusNextField: function cd_focusNextField() {
    if (!this._editing)
      return;

    if (this._lastFocusedInput)
      this.nextField(this._lastFocusedInput).focus();
  },

  nextField: function cd_nextField(element) {
    // selecting the next input or the save button
    var nextGroup = element.parentNode.nextElementSibling;
    var nextElement = nextGroup.querySelector('input');
    if (nextElement) {
      element = nextElement;
    }

    return element;
  },

  // back button handling
  handleEvent: function cd_handleEvent(evt) {
    if (evt.type !== 'keyup' || evt.keyCode != evt.DOM_VK_ESCAPE) {
      return;
    }

    if (this.endEditing() || this.hide()) {
      evt.preventDefault();
    }
  },

  render: function cd_render() {
    var contact = this._contact;

    var names = '';
    names += contact.givenName || '';
    names += ' ' + (contact.familyName || '');
    this.contactName.innerHTML = names;

    this.contactGivenNameField.value =
      contact.givenName;
    this.contactFamilyNameField.value =
      contact.familyName;

    document.getElementById('contact-photo').innerHTML =
      profilePictureForNumber(contact.id);

    if (contact.tel) {
      this.contactPhone.querySelector('.value').innerHTML =
        contact.tel[0];
      this.contactPhone.dataset.number = contact.tel[0];

      this.contactPhoneField.value = contact.tel[0];
    }

    if (this._contact.email) {
      this.contactEmail.querySelector('.value').innerHTML =
        contact.email[0];

      this.contactEmailField.value = contact.email[0];
    }
  }
};

window.addEventListener('load', function contactSetup(evt) {
  window.removeEventListener('load', contactSetup);
  Contacts.setup();
  ShortcutsHandler.setup();
  ContactDetails.setup();
});
<commit_msg>Bugfix for #774<commit_after>'use strict';

var Contacts = {
  _loaded: false,
  get view() {
    delete this.view;
    return this.view = document.getElementById('contacts-view-scrollable');
  },

  setup: function contactsSetup() {
    document.getElementById('contacts').addEventListener('change',
      (function contactTabChanged(evt) {
        // loading contacts the first time the view appears
        this.load();

        ContactDetails.hide();
      }).bind(this));
  },

  load: function contactsLoad() {
    if (this._loaded) {
      return;
    }

    this.find(this.show.bind(this));
  },

  reload: function contactsReload() {
    this._loaded = false;
    this.load();
  },

  find: function contactsFind(callback) {
    // Ideally I would like to choose the ordering
    var request = window.navigator.mozContacts.find({});
    request.onsuccess = function findCallback() {
      var contacts = request.result;
      contacts.sort(function contactsSort(a, b) {
        return a.familyName[0].toUpperCase() > b.familyName[0].toUpperCase();
      });
      callback(contacts);
    };
  },

  findByNumber: function findByNumber(number, callback) {
    var options = {
      filterBy: ['tel'],
      filterOp: 'contains',
      filterValue: number
    };
    var request = window.navigator.mozContacts.find(options);
    request.onsuccess = function findCallback() {
      if (request.result.length == 0)
        return;

      var contacts = request.result;
      callback(contacts[0]);
    };
  },

  show: function contactsShow(contacts) {
    var content = '';
    var currentLetter = '';

    var count = contacts.length;
    for (var i = 0; i < count; i++) {
      var contact = contacts[i];

      var name = contact.familyName[0];
      var letter = name ? name[0].toUpperCase() : '';
      if (currentLetter != letter) {
        currentLetter = letter;

        content += '
' +
                   '' +
                      currentLetter +
                   '
';
      }

      content += '
';
      content += '' + contact.givenName + ' ';
      content += '' + contact.familyName + '';
      content += '
';
    }

    var contactsContainer = document.getElementById('contacts-container');
    contactsContainer.innerHTML = content;
    this.filter();

    this._loaded = true;
  },

  filter: function contactsFilter(value) {
    var pattern = new RegExp(value, 'i');
    var container = document.getElementById('contacts-container');
    var contacts = container.children;

    var count = contacts.length;
    for (var i = 0; i < count; i++) {
      var contact = contacts[i];
      if (contact.className == 'contact-header')
        continue;

      contact.hidden = !pattern.test(contact.textContent);
    }

    // If there is 0 childs for a particular letter, hide it.
    var enabledLetters = [];
    for (var i = 0; i < count; i++) {
      var contactHeader = contacts[i];
      if (contactHeader.className != 'contact-header')
        continue;

      var nextSibling = contactHeader.nextSibling;
      while (nextSibling && nextSibling.className == 'contact') {
        if (!nextSibling.hidden) {
          enabledLetters.push(contactHeader.id);
          break;
        }
        nextSibling = nextSibling.nextSibling;
      }
    }

    // Reflect the change in the shortcut letter
    var shortcuts = document.getElementById('contacts-shortcuts').children;
    for (var j = 0; j < shortcuts.length; j++) {
      var shortcut = shortcuts[j];
      var targetId = shortcut.name;
      var header = document.getElementById(targetId);

      var disabled = (enabledLetters.indexOf(targetId) == -1);
      if (header && disabled) {
        shortcut.setAttribute('data-disabled', 'true');
        header.hidden = true;
      } else if (disabled) {
        shortcut.setAttribute('data-disabled', 'true');
      } else {
        shortcut.removeAttribute('data-disabled');
        header.hidden = false;
      }
    }
  },

  anchor: function contactsAnchor(targetId) {
    var target = document.getElementById(targetId);
    if (!target)
      return;

    var top = target.getBoundingClientRect().top;
    var scrollable = document.getElementById('contacts-view-scrollable');
    var scrollableTop = scrollable.getBoundingClientRect().top;
    scrollable.scrollTop = (top - scrollableTop) + scrollable.scrollTop;
  },

  showDetails: function contactsShowDetails(evt) {
    var contactId = evt.target.id;

    var options = {
      filterBy: ['id'],
      filterOp: 'equals',
      filterValue: contactId
    };
    var request = window.navigator.mozContacts.find(options);
    request.onsuccess = function findCallback() {
      if (request.result == 0)
        return;

      var contacts = request.result;
      ContactDetails.show(contacts[0]);
    };
  },

  create: function contactsCreate() {
    // creating an empty contact
    var contact = new mozContact();
    contact.init({tel: '', email: ''});

    ContactDetails.show(contact);
  }
};

var ShortcutsHandler = {
  setup: function sh_setup() {
    ['touchstart', 'touchmove', 'touchend'].forEach((function(evt) {
      this.shortcutsBar.addEventListener(evt, this, true);
    }).bind(this));
  },

  get shortcutsBar() {
    delete this.shortcutsBar;
    return this.shortcutsBar = document.getElementById('contacts-shortcuts');
  },

  get shortcutsBackground() {
    delete this.shortcutsBackground;
    var id = 'contacts-shortcuts-background';
    return this.shortcutsBackground = document.getElementById(id);
  },

  handleEvent: function sh_handleEvent(evt) {
    // preventing the events from bubbling to the contacts list
    evt.preventDefault();

    switch (evt.type) {
      case 'touchstart':
        this.startTracking();
      case 'touchmove': // fall through
        this.anchorForPosition(evt.targetTouches[0].clientY);
        break;

      case 'touchend':
        this.stopTracking();
        break;
    }
  },

  startTracking: function sh_startTracking() {
    this.shortcutsBackground.classList.add('tracking');

    // we keep a reference to the horizontal center of the zone
    // it allows us to keep anchoring correctly if the user gets
    // out of the zone while swiping
    var rect = this.shortcutsBar.getBoundingClientRect();
    this._positionX = rect.left + (rect.width / 2);
  },
  stopTracking: function sh_stopTracking() {
    this.shortcutsBackground.classList.remove('tracking');
    delete this._positionX;
  },
  anchorForPosition: function sh_anchorForPosition(positionY) {
    // only inspecting the vertical point of the touch
    var target = document.elementFromPoint(this._positionX, positionY).name;
    Contacts.anchor(target);
  }
};

var ContactDetails = {
  _editing: false,
  _lastFocusedInput: null,
  _keyboardDisplayed: false,

  setup: function cd_setup() {
    window.addEventListener('keyup', this, true);
    window.addEventListener('resize', this, true);

    // Binding to properly handle the return key
    var inputs = this.container.querySelectorAll('input');
    for (var i = 0; i < inputs.length; i++) {
      inputs[i].onkeypress = (function cd_inputKeyPress(event) {
        if (event.keyCode == event.DOM_VK_RETURN) {
          this.focusNextField();
          return false;
        }
      }).bind(this);
    }

    // click outside details container to close
    this.overlay.addEventListener('click', function(evt) {
      ContactDetails.hide();
    });
    this.container.addEventListener('click', function(evt) {
      evt.stopPropagation();
    });
  },
  get overlay() {
    delete this.overlay;
    return this.overlay = document.getElementById('contacts-overlay');
  },
  get container() {
    delete this.container;
    return this.container =
      document.getElementById('contact-details-container');
  },
  get view() {
    delete this.view;
    return this.view = document.getElementById('contact-details-view');
  },

  get contactName() {
    delete this.contactName;
    return this.contactName = document.getElementById('contact-name');
  },
  get contactGivenNameField() {
    delete this.contactGivenNameField;
    var id = 'contact-given-name-field';
    return this.contactGivenNameField = document.getElementById(id);
  },
  get contactFamilyNameField() {
    delete this.contactFamilyNameField;
    var id = 'contact-family-name-field';
    return this.contactFamilyNameField = document.getElementById(id);
  },

  get contactPhone() {
    delete this.contactPhone;
    return this.contactPhone = document.getElementById('contact-phone');
  },
  get contactPhoneField() {
    delete this.contactPhoneField;
    var id = 'contact-phone-field';
    return this.contactPhoneField = document.getElementById(id);
  },

  get contactEmail() {
    delete this.contactEmail;
    return this.contactEmail = document.getElementById('contact-email');
  },
  get contactEmailField() {
    delete this.contactEmailField;
    var id = 'contact-email-field';
    return this.contactEmailField = document.getElementById(id);
  },

  set contact(contact) {
    delete this._contact;
    this._contact = contact;
    this.render();
  },

  execute: function cd_execute(evt) {
    var action = evt.currentTarget.dataset.action;
    if (!this[action]) {
      this.hide();
      return;
    }

    this[action](evt);
  },

  show: function cd_show(contact) {
    if (typeof contact != 'undefined') {
      this.contact = contact;
    }

    var overlay = this.overlay;
    overlay.classList.add('displayed');

    // directly entering the edit mode if this is a new contact
    var self = this;
    if (this._contact.id == 'undefined') {
      overlay.addEventListener('transitionend', function trWait() {
        overlay.removeEventListener('transitionend', trWait);
        self.edit();
      });
    }
  },

  hide: function cd_hide() {
    if (!this.overlay.classList.contains('displayed')) {
      return false;
    }

    var overlay = this.overlay;
    overlay.classList.add('hidden');
    overlay.addEventListener('transitionend', function fadeWait() {
      overlay.removeEventListener('transitionend', fadeWait);

      overlay.classList.remove('hidden');
      overlay.classList.remove('displayed');
    });

    this.endEditing();
    return true;
  },

  edit: function cd_edit() {
    if (this._editing) {
      return;
    }
    this._editing = true;

    this.view.classList.add('editing');

    // setting a min-height in preparation for the keyboard appearance
    var minHeight = this.container.getBoundingClientRect().height;
    this.container.style.minHeight = minHeight + 'px';
  },

  save: function cd_save(form) {
    if (form.checkValidity()) {
      var contact = this._contact;

      contact.givenName = this.contactGivenNameField.value;
      contact.familyName = this.contactFamilyNameField.value;
      contact.name = contact.givenName + ' ' + contact.familyName;

      if (this.contactPhoneField.value.length)
        contact.tel = [this.contactPhoneField.value];
      if (this.contactEmailField.value.length)
        contact.email = [this.contactEmailField.value];

      var req = navigator.mozContacts.save(contact);
      req.onsuccess = (function() {
        this.render();
        this.endEditing();
        Contacts.reload();
      }.bind(this));
    }
  },

  destroy: function cd_destroy(evt) {

    var req = navigator.mozContacts.remove(this._contact);
    req.onsuccess = (function() {
      this.render();
      this.hide();
      Contacts.reload();
    }.bind(this));

    evt.preventDefault();
  },

  call: function cd_call(evt) {
    if (this._editing) {
      return;
    }

    var number = evt.target.dataset.number;
    if (number) {
      CallHandler.call(number);
    }
  },

  endEditing: function cd_endEditing() {
    if (!this._editing) {
      return false;
    }
    this._editing = false;

    this.view.classList.remove('editing');
    return true;
  },

  // scrolling to the right position when one of the fields
  // takes focus
  autoscroll: function cd_autoscroll(event) {
    this._lastFocusedInput = event.currentTarget;
    var element = this.nextField(event.currentTarget);
    var self = this;

    var scrollInPlace = function cd_autoscrollMove() {
      element.scrollIntoView(false);
    };
    scrollInPlace();

    //also listening to the next resize for keyboard handling
    window.addEventListener('resize', function cd_afterResize() {
      window.removeEventListener('resize', cd_afterResize);

      scrollInPlace();
    });
  },

  focusNextField: function cd_focusNextField() {
    if (!this._editing)
      return;

    if (this._lastFocusedInput)
      this.nextField(this._lastFocusedInput).focus();
  },

  nextField: function cd_nextField(element) {
    // selecting the next input or the save button
    var nextGroup = element.parentNode.nextElementSibling;
    var nextElement = nextGroup.querySelector('input');
    if (nextElement) {
      element = nextElement;
    }

    return element;
  },

  // back button handling
  handleEvent: function cd_handleEvent(evt) {
    if (evt.type == 'resize') {
      //XXX: the keyboard resizes the frame before we get the ESCAPE
      // event. So the frame is always full-height when we get it
      // if we don't add this timeout
      setTimeout((function() {
        this._keyboardDisplayed = !this._keyboardDisplayed;
      }).bind(this), 300);
      return;
    }

    if (evt.type !== 'keyup' || evt.keyCode != evt.DOM_VK_ESCAPE) {
      return;
    }

    // If the user escaped just to remove the keyboard we stay
    // in edit mode
    if (this._keyboardDisplayed) {
      evt.preventDefault();
      return;
    }

    if (this.endEditing() || this.hide()) {
      evt.preventDefault();
    }
  },

  render: function cd_render() {
    var contact = this._contact;

    var names = '';
    names += contact.givenName || '';
    names += ' ' + (contact.familyName || '');
    this.contactName.innerHTML = names;

    this.contactGivenNameField.value =
      contact.givenName;
    this.contactFamilyNameField.value =
      contact.familyName;

    document.getElementById('contact-photo').innerHTML =
      profilePictureForNumber(contact.id);

    if (contact.tel) {
      this.contactPhone.querySelector('.value').innerHTML =
        contact.tel[0];
      this.contactPhone.dataset.number = contact.tel[0];

      this.contactPhoneField.value = contact.tel[0];
    }

    if (this._contact.email) {
      this.contactEmail.querySelector('.value').innerHTML =
        contact.email[0];

      this.contactEmailField.value = contact.email[0];
    }
  }
};

window.addEventListener('load', function contactSetup(evt) {
  window.removeEventListener('load', contactSetup);
  Contacts.setup();
  ShortcutsHandler.setup();
  ContactDetails.setup();
});
<|endoftext|>


<commit_before>let Cacher = function(file) {
    if (!file) {
        throw new Error('Missing file parameter!');
    }
    let fs = require('fs');
    this.file = file;

    this.setData = function(str) {
        return new Promise((resolve, reject) => {
            fs.writeFile(this.file, str, {encoding: 'utf8'}, (err) => {
                if (err) {
                    reject(new Error(err));
                }
                resolve();
            });
        });
    };

    this.getData = function() {
        return new Promise((resolve, reject) => {
            fs.stat(this.file, (err) => {
                if (err) {
                    resolve(false);
                }
            });
            fs.readFile(this.file, {encoding: 'utf8'}, (err, data) => {
                if (err) {
                    reject(new Error(err));
                }
                resolve(data);
            });
        });
    };
};

module.exports = Cacher;
<commit_msg>return undefined if cache file hasn't been created<commit_after>let Cacher = function(file) {
    if (!file) {
        throw new Error('Missing file parameter!');
    }
    let fs = require('fs');
    this.file = file;

    this.setData = function(str) {
        return new Promise((resolve, reject) => {
            fs.writeFile(this.file, str, {encoding: 'utf8'}, (err) => {
                if (err) {
                    reject(new Error(err));
                }
                resolve();
            });
        });
    };

    this.getData = function() {
        return new Promise((resolve, reject) => {
            fs.stat(this.file, (err) => {
                if (err) {
                    resolve(undefined);
                }
            });
            fs.readFile(this.file, {encoding: 'utf8'}, (err, data) => {
                if (err) {
                    reject(new Error(err));
                }
                resolve(data);
            });
        });
    };
};

module.exports = Cacher;
<|endoftext|>


<commit_before>function degats(nain, arme) {
    var competence = (arme.portee > 0) ? nain.precision : nain.force,
        dommages = arme.dommages,
        baseDegats = (competence + 80) * dommages;

    return {
        minimum: Math.round(baseDegats / 105),
        maximum: Math.round(baseDegats / 95)
        //critiqueMin: Math.round(dommages * (1 + competence/105) * 4.75),
        //critiqueMax: Math.round(dommages * (1 + competence/95) * 4.75)
    };
}

module.exports = {
    degats: degats
};<commit_msg>Improved degats calculation<commit_after>function degats(nain, arme) {
    var competence = (arme.portee > 0) ? nain.precision : nain.force,
        dommages = arme.dommages,
        baseDegats = (competence + 80) * dommages / 100;

    return {
        minimum: Math.round(baseDegats * 0.95),  // -5%
        maximum: Math.round(baseDegats * 1.05)  // +5%
        //critiqueMin: Math.round(dommages * (1 + competence/105) * 4.75),
        //critiqueMax: Math.round(dommages * (1 + competence/95) * 4.75)
    };
}

module.exports = {
    degats: degats
};<|endoftext|>