<commit_before>'use strict'

var create_plane = function(width, height, position, rotation) {
    var material = new THREE.MeshBasicMaterial({
        color: 0x000000,
        opacity: 0.0,
        side: THREE.DoubleSide
    })
    var geometry = new THREE.PlaneGeometry(width, height)
    var mesh = new THREE.Mesh(geometry, material)
    mesh.position.x = position.x
    mesh.position.y = position.y
    mesh.position.z = position.z
    mesh.rotation.x = rotation.x
    mesh.rotation.y = rotation.y
    mesh.rotation.z = rotation.z
    return mesh
}

var create_css_page = function(width, height, position, rotation, text) {
    // Create the CSS object.
    var html = '

' + text + '

'
    var div = document.createElement('div')
    div.innerHTML = html
    var css_object = new THREE.CSS3DObject(div)
    css_object.position.x = position.x
    css_object.position.y = position.y
    css_object.position.z = position.z
    css_object.rotation.x = rotation.x
    css_object.rotation.y = rotation.y
    css_object.rotation.z = rotation.z

    return css_object
}

var renderer_api  = new RendererAPI()
if (renderer_api.is_webgl_enabled() === false) {
    console.log('WebGL is not enabled!')
    throw new Error('WebGL is not enabled!')
}
var stats_api = new StatsAPI()
var scene = new THREE.Scene()
var camera   = new THREE.PerspectiveCamera(renderer_api.field_of_view, renderer_api.aspect_ratio, renderer_api.near_clipping, renderer_api.far_clipping)
renderer_api.set_camera(camera)

// Going to try to create a plane here.
var plane_geometry = new THREE.PlaneGeometry(2000, 2000, 100, 100)
plane_geometry.applyMatrix(new THREE.Matrix4().makeRotationX(- Math.PI / 2))
//var plane_material = new THREE.MeshBasicMaterial({color: 0x0000ff})
var plane_material = new THREE.MeshLambertMaterial({color: 0xccffcc, side: THREE.FrontSide, wireframe: false})
var plane_mesh     = new THREE.Mesh(plane_geometry, plane_material)
scene.add(plane_mesh)

var fps_controls = new FPSControls(camera)
scene.add(fps_controls.get_object())

var pointer_lock_api = new PointerLockAPI(fps_controls)

var geometry = new THREE.BoxGeometry(20, 20, 20)
//var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
var material = new THREE.MeshLambertMaterial({ color: 0x00ff00 })
var cube 	 = new THREE.Mesh(geometry, material)
cube.position.y = 30
scene.add(cube)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//var css_renderer_api = new CSSRendererAPI()

//var cssScene = new THREE.Scene()

var math_formulas = document.getElementById('math_formulas')

var element = document.createElement('div')
element.innerHTML = 'Plain text inside a div.'
element.className = 'three-div'

// Create a test plane.
var p_width = 100
var p_height = 100
var p_position = new THREE.Vector3(20, 30, -30)
var p_rotation = new THREE.Vector3(0, 0, 0)
var test_plane = create_plane(p_width, p_height, p_position, p_rotation)
//scene.add(test_plane)
//var test_css_plane = create_css_page(p_width, p_height, p_position, p_rotation, '`b^x=c^(xlog_cb)`')
//cssScene.add(test_css_plane)

// Second test plane.
var p_width2 = 200
var p_height2 = 200
var p_position2 = new THREE.Vector3(20, 30, -60)
var p_rotation2 = new THREE.Vector3(0, 0, 0)
var test_plane2 = create_plane(p_width2, p_height2, p_position2, p_rotation2)
//scene.add(test_plane2)
//var test_css_plane2 = create_css_page(p_width2, p_height2, p_position2, p_rotation2, '`log_bx=(log_cx)/(log_cb)`')
//cssScene.add(test_css_plane2)

//var light4 = new THREE.HemisphereLight(0xffbf67, 0x15c6ff, .3)
//scene.add(light4)

//scene.add(css_object)
//cssScene.add(css_object)

// @@@@
//css_renderer_api.renderer.domElement.appendChild(renderer_api.renderer.domElement)
//document.body.appendChild(css_renderer_api.renderer.domElement)
// @@@@
document.body.appendChild(renderer_api.renderer.domElement)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

// Add lights.
var ambiColor = '#cbe7ff'
var color1 = '#ffffbb'
var color2 = '#090920'
//var ambientLight = new THREE.AmbientLight(ambiColor, .2)
var lightt = new THREE.HemisphereLight( color1, color2, .1 )
scene.add( lightt )
//scene.add(ambientLight)
/*
var light = new THREE.DirectionalLight( 0xffffff, 1.5 )
light.position.set(1, 1, 1 )
scene.add(light)s

var light2 = new THREE.DirectionalLight( 0xffffff, 0.75 )
light2.position.set(-1, - 0.5, -1)
scene.add(light2)
*/

var data_display = new DataDisplay(fps_controls)

var light3 = new THREE.PointLight(0xccffcc, 1, 1000)
light3.position.set(5, 15, 5)
scene.add(light3)

//var shader_api = new ShaderAPI(renderer_api, scene, camera)

//

// TODO : Temporary commented out to make other debugging quicker.
//var world  = new World(scene)
//var client = new Client(world)

// Information that gets sent to the server.
// TODO : Only send information if position updates have been made.
/*
setInterval(function() {
    var data = fps_controls.get_position().x + '|' + fps_controls.get_position().y + '|' + fps_controls.get_position().z + '|' + fps_controls.get_x_rotation() + '|' + fps_controls.get_object().rotation.y + '|' + fps_controls.get_object().rotation.z
    client.send_data(data)
}, 100)
*/

var loader = new THREE.FontLoader()
loader.load('/home/git_repos/quasar_source/quasar_source_code/quasar_site_django/static/font/helvetiker_regular.typeface.json', function(tex){
    var  textGeo = new THREE.TextGeometry('Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday', {
        size: 80,
        height: 4,
        curveSegments: 2,
        font: tex
    })
    var  color = new THREE.Color()
    color.setRGB(50, 50, 50)
    var  textMaterial = new THREE.MeshLambertMaterial({ color: color })
    var  text = new THREE.Mesh(textGeo, textMaterial)
    scene.add(text)
})
//

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

var text_position = new THREE.Vector3(40, 40, 40)
var text_rotation = new THREE.Vector3(0, 0, 0)
var text_plane = new PlaneAPI(200, 50, text_position, text_rotation)
text_plane.create_dynamic_text('Hello Worlddddddddddd', scene, renderer_api.renderer)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

var previous_time = performance.now()

var animate = function () {
    //shader_api.render()

    requestAnimationFrame(animate)

    stats_api.pre_render()

    var cube_rotation = fps_controls.get_direction()
    cube.rotation.x = cube_rotation.x
    cube.rotation.y = cube_rotation.y
    cube.rotation.z = cube_rotation.z

    var time = performance.now()
    var delta = (time - previous_time) / 1000

    fps_controls.physics(delta)
    data_display.update()

    renderer_api.renderer.render(scene, camera)
    //css_renderer_api.renderer.render(cssScene, camera)

    stats_api.post_render()

    previous_time = time
}

animate()

<commit_msg>Misc adjustments 16<commit_after>'use strict'

var create_plane = function(width, height, position, rotation) {
    var material = new THREE.MeshBasicMaterial({
        color: 0x000000,
        opacity: 0.0,
        side: THREE.DoubleSide
    })
    var geometry = new THREE.PlaneGeometry(width, height)
    var mesh = new THREE.Mesh(geometry, material)
    mesh.position.x = position.x
    mesh.position.y = position.y
    mesh.position.z = position.z
    mesh.rotation.x = rotation.x
    mesh.rotation.y = rotation.y
    mesh.rotation.z = rotation.z
    return mesh
}

var create_css_page = function(width, height, position, rotation, text) {
    // Create the CSS object.
    var html = '

' + text + '

'
    var div = document.createElement('div')
    div.innerHTML = html
    var css_object = new THREE.CSS3DObject(div)
    css_object.position.x = position.x
    css_object.position.y = position.y
    css_object.position.z = position.z
    css_object.rotation.x = rotation.x
    css_object.rotation.y = rotation.y
    css_object.rotation.z = rotation.z

    return css_object
}

var renderer_api  = new RendererAPI()
if (renderer_api.is_webgl_enabled() === false) {
    console.log('WebGL is not enabled!')
    throw new Error('WebGL is not enabled!')
}
var stats_api = new StatsAPI()
var scene = new THREE.Scene()
var camera   = new THREE.PerspectiveCamera(renderer_api.field_of_view, renderer_api.aspect_ratio, renderer_api.near_clipping, renderer_api.far_clipping)
renderer_api.set_camera(camera)

// Going to try to create a plane here.
var plane_geometry = new THREE.PlaneGeometry(2000, 2000, 100, 100)
plane_geometry.applyMatrix(new THREE.Matrix4().makeRotationX(- Math.PI / 2))
//var plane_material = new THREE.MeshBasicMaterial({color: 0x0000ff})
var plane_material = new THREE.MeshLambertMaterial({color: 0xccffcc, side: THREE.FrontSide, wireframe: false})
var plane_mesh     = new THREE.Mesh(plane_geometry, plane_material)
scene.add(plane_mesh)

var fps_controls = new FPSControls(camera)
scene.add(fps_controls.get_object())

var pointer_lock_api = new PointerLockAPI(fps_controls)

var geometry = new THREE.BoxGeometry(20, 20, 20)
//var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
var material = new THREE.MeshLambertMaterial({ color: 0x00ff00 })
var cube 	 = new THREE.Mesh(geometry, material)
cube.position.y = 30
scene.add(cube)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//var css_renderer_api = new CSSRendererAPI()

//var cssScene = new THREE.Scene()

var math_formulas = document.getElementById('math_formulas')

var element = document.createElement('div')
element.innerHTML = 'Plain text inside a div.'
element.className = 'three-div'

// Create a test plane.
var p_width = 100
var p_height = 100
var p_position = new THREE.Vector3(20, 30, -30)
var p_rotation = new THREE.Vector3(0, 0, 0)
var test_plane = create_plane(p_width, p_height, p_position, p_rotation)
//scene.add(test_plane)
//var test_css_plane = create_css_page(p_width, p_height, p_position, p_rotation, '`b^x=c^(xlog_cb)`')
//cssScene.add(test_css_plane)

// Second test plane.
var p_width2 = 200
var p_height2 = 200
var p_position2 = new THREE.Vector3(20, 30, -60)
var p_rotation2 = new THREE.Vector3(0, 0, 0)
var test_plane2 = create_plane(p_width2, p_height2, p_position2, p_rotation2)
//scene.add(test_plane2)
//var test_css_plane2 = create_css_page(p_width2, p_height2, p_position2, p_rotation2, '`log_bx=(log_cx)/(log_cb)`')
//cssScene.add(test_css_plane2)

//var light4 = new THREE.HemisphereLight(0xffbf67, 0x15c6ff, .3)
//scene.add(light4)

//scene.add(css_object)
//cssScene.add(css_object)

// @@@@
//css_renderer_api.renderer.domElement.appendChild(renderer_api.renderer.domElement)
//document.body.appendChild(css_renderer_api.renderer.domElement)
// @@@@
document.body.appendChild(renderer_api.renderer.domElement)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

// Add lights.
var ambiColor = '#cbe7ff'
var color1 = '#ffffbb'
var color2 = '#090920'
//var ambientLight = new THREE.AmbientLight(ambiColor, .2)
var lightt = new THREE.HemisphereLight( color1, color2, .1 )
scene.add( lightt )
//scene.add(ambientLight)
/*
var light = new THREE.DirectionalLight( 0xffffff, 1.5 )
light.position.set(1, 1, 1 )
scene.add(light)s

var light2 = new THREE.DirectionalLight( 0xffffff, 0.75 )
light2.position.set(-1, - 0.5, -1)
scene.add(light2)
*/

var data_display = new DataDisplay(fps_controls)

var light3 = new THREE.PointLight(0xccffcc, 1, 10)
light3.position.set(5, 15, 5)
scene.add(light3)

//var shader_api = new ShaderAPI(renderer_api, scene, camera)

//

// TODO : Temporary commented out to make other debugging quicker.
//var world  = new World(scene)
//var client = new Client(world)

// Information that gets sent to the server.
// TODO : Only send information if position updates have been made.
/*
setInterval(function() {
    var data = fps_controls.get_position().x + '|' + fps_controls.get_position().y + '|' + fps_controls.get_position().z + '|' + fps_controls.get_x_rotation() + '|' + fps_controls.get_object().rotation.y + '|' + fps_controls.get_object().rotation.z
    client.send_data(data)
}, 100)
*/

var loader = new THREE.FontLoader()
loader.load('/home/git_repos/quasar_source/quasar_source_code/quasar_site_django/static/font/helvetiker_regular.typeface.json', function(tex){
    var  textGeo = new THREE.TextGeometry('Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday', {
        size: 80,
        height: 4,
        curveSegments: 2,
        font: tex
    })
    var  color = new THREE.Color()
    color.setRGB(100, 100, 100)
    var  textMaterial = new THREE.MeshLambertMaterial({ color: color })
    var  text = new THREE.Mesh(textGeo, textMaterial)
    scene.add(text)
})
//

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

var text_position = new THREE.Vector3(40, 40, 40)
var text_rotation = new THREE.Vector3(0, 0, 0)
var text_plane = new PlaneAPI(200, 50, text_position, text_rotation)
text_plane.create_dynamic_text('Hello Worlddddddddddd', scene, renderer_api.renderer)

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

var previous_time = performance.now()

var animate = function () {
    //shader_api.render()

    requestAnimationFrame(animate)

    stats_api.pre_render()

    var cube_rotation = fps_controls.get_direction()
    cube.rotation.x = cube_rotation.x
    cube.rotation.y = cube_rotation.y
    cube.rotation.z = cube_rotation.z

    var time = performance.now()
    var delta = (time - previous_time) / 1000

    fps_controls.physics(delta)
    data_display.update()

    renderer_api.renderer.render(scene, camera)
    //css_renderer_api.renderer.render(cssScene, camera)

    stats_api.post_render()

    previous_time = time
}

animate()

<|endoftext|>


<commit_before>import { computed } from '@ember/object';
import Service, { inject as service } from '@ember/service';

/**
 * A static dictionary of the supported units with its
 * conversion factors and default decimal places.
 * @const
 * @type {Object}
 */
const UNITS = {
  // Length
  m: [1, 0],
  ft: [3.28084, 0],
  km: [1 / 1000.0, 0],
  NM: [1 / 1852.0, 0],
  mi: [1 / 1609.34, 0],

  // Speed
  'm/s': [1, 1],
  'km/h': [3.6, 1],
  kt: [1.94384449, 1],
  mph: [2.23693629, 1],
  'ft/min': [196.850394, 0],
};

export const PRESETS = {
  european: {
    distance: 'km',
    speed: 'km/h',
    lift: 'm/s',
    altitude: 'm',
  },

  british: {
    distance: 'km',
    speed: 'kt',
    lift: 'kt',
    altitude: 'ft',
  },

  australian: {
    distance: 'km',
    speed: 'km/h',
    lift: 'kt',
    altitude: 'ft',
  },

  american: {
    distance: 'mi',
    speed: 'kt',
    lift: 'kt',
    altitude: 'ft',
  },
};

const DISTANCE_UNITS = ['m', 'km', 'NM', 'mi'];
const SPEED_UNITS = ['m/s', 'km/h', 'kt', 'mph'];
const LIFT_UNITS = ['m/s', 'kt', 'ft/min'];
const ALTITUDE_UNITS = ['m', 'ft'];

export default Service.extend({
  intl: service(),

  distanceUnitIndex: 1,
  speedUnitIndex: 1,
  liftUnitIndex: 0,
  altitudeUnitIndex: 0,

  distanceUnit: computedUnit('distanceUnits', 'distanceUnitIndex'),
  speedUnit: computedUnit('speedUnits', 'speedUnitIndex'),
  liftUnit: computedUnit('liftUnits', 'liftUnitIndex'),
  altitudeUnit: computedUnit('altitudeUnits', 'altitudeUnitIndex'),

  distanceUnits: DISTANCE_UNITS,
  speedUnits: SPEED_UNITS,
  liftUnits: LIFT_UNITS,
  altitudeUnits: ALTITUDE_UNITS,

  /**
   * Formats a number to a string with a given number of decimal places
   *
   * @param  {Number} value A number that should be formatted.
   * @param  {Number} decimals
   *   The number of decimal places that should be kept.
   * @return {String} The formatted value as a string.
   */
  formatDecimal(value, decimals) {
    return this.intl.formatNumber(value, {
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    });
  },

  formatDistance(value, options) {
    value = this.convertDistance(value);
    return this.addDistanceUnit(value, options);
  },

  convertDistance(value) {
    return value * UNITS[this.distanceUnit][0];
  },

  addDistanceUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.distanceUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.distanceUnit}` : value;
  },

  formatSpeed(value, options) {
    value = this.convertSpeed(value);
    return this.addSpeedUnit(value, options);
  },

  convertSpeed(value) {
    return value * UNITS[this.speedUnit][0];
  },

  addSpeedUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.speedUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.speedUnit}` : value;
  },

  formatLift(value, options) {
    value = this.convertLift(value);
    return this.addLiftUnit(value, options);
  },

  convertLift(value) {
    return value * UNITS[this.liftUnit][0];
  },

  addLiftUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.liftUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.liftUnit}` : value;
  },

  formatAltitude(value, options) {
    value = this.convertAltitude(value);
    return this.addAltitudeUnit(value, options);
  },

  convertAltitude(value) {
    return value * UNITS[this.altitudeUnit][0];
  },

  addAltitudeUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.altitudeUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.altitudeUnit}` : value;
  },
});

function computedUnit(unitsKey, indexKey) {
  return computed(indexKey, {
    get() {
      return this.get(unitsKey)[this.get(indexKey)];
    },
    set(key, value) {
      this.set(indexKey, this.get(unitsKey).indexOf(value));
      return value;
    },
  });
}
<commit_msg>services/units: Convert to ES6 class<commit_after>import { computed } from '@ember/object';
import Service, { inject as service } from '@ember/service';

/**
 * A static dictionary of the supported units with its
 * conversion factors and default decimal places.
 * @const
 * @type {Object}
 */
const UNITS = {
  // Length
  m: [1, 0],
  ft: [3.28084, 0],
  km: [1 / 1000.0, 0],
  NM: [1 / 1852.0, 0],
  mi: [1 / 1609.34, 0],

  // Speed
  'm/s': [1, 1],
  'km/h': [3.6, 1],
  kt: [1.94384449, 1],
  mph: [2.23693629, 1],
  'ft/min': [196.850394, 0],
};

export const PRESETS = {
  european: {
    distance: 'km',
    speed: 'km/h',
    lift: 'm/s',
    altitude: 'm',
  },

  british: {
    distance: 'km',
    speed: 'kt',
    lift: 'kt',
    altitude: 'ft',
  },

  australian: {
    distance: 'km',
    speed: 'km/h',
    lift: 'kt',
    altitude: 'ft',
  },

  american: {
    distance: 'mi',
    speed: 'kt',
    lift: 'kt',
    altitude: 'ft',
  },
};

const DISTANCE_UNITS = ['m', 'km', 'NM', 'mi'];
const SPEED_UNITS = ['m/s', 'km/h', 'kt', 'mph'];
const LIFT_UNITS = ['m/s', 'kt', 'ft/min'];
const ALTITUDE_UNITS = ['m', 'ft'];

export default class UnitsService extends Service {
  @service intl;

  distanceUnitIndex = 1;
  speedUnitIndex = 1;
  liftUnitIndex = 0;
  altitudeUnitIndex = 0;

  @computedUnit('distanceUnits', 'distanceUnitIndex') distanceUnit;
  @computedUnit('speedUnits', 'speedUnitIndex') speedUnit;
  @computedUnit('liftUnits', 'liftUnitIndex') liftUnit;
  @computedUnit('altitudeUnits', 'altitudeUnitIndex') altitudeUnit;

  distanceUnits = DISTANCE_UNITS;
  speedUnits = SPEED_UNITS;
  liftUnits = LIFT_UNITS;
  altitudeUnits = ALTITUDE_UNITS;

  /**
   * Formats a number to a string with a given number of decimal places
   *
   * @param  {Number} value A number that should be formatted.
   * @param  {Number} decimals
   *   The number of decimal places that should be kept.
   * @return {String} The formatted value as a string.
   */
  formatDecimal(value, decimals) {
    return this.intl.formatNumber(value, {
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    });
  }

  formatDistance(value, options) {
    value = this.convertDistance(value);
    return this.addDistanceUnit(value, options);
  }

  convertDistance(value) {
    return value * UNITS[this.distanceUnit][0];
  }

  addDistanceUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.distanceUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.distanceUnit}` : value;
  }

  formatSpeed(value, options) {
    value = this.convertSpeed(value);
    return this.addSpeedUnit(value, options);
  }

  convertSpeed(value) {
    return value * UNITS[this.speedUnit][0];
  }

  addSpeedUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.speedUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.speedUnit}` : value;
  }

  formatLift(value, options) {
    value = this.convertLift(value);
    return this.addLiftUnit(value, options);
  }

  convertLift(value) {
    return value * UNITS[this.liftUnit][0];
  }

  addLiftUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.liftUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.liftUnit}` : value;
  }

  formatAltitude(value, options) {
    value = this.convertAltitude(value);
    return this.addAltitudeUnit(value, options);
  }

  convertAltitude(value) {
    return value * UNITS[this.altitudeUnit][0];
  }

  addAltitudeUnit(value, options = {}) {
    let decimals = options.decimals !== undefined ? options.decimals : UNITS[this.altitudeUnit][1];
    value = this.formatDecimal(value, decimals);
    return options.withUnit !== false ? `${value} ${this.altitudeUnit}` : value;
  }
}

function computedUnit(unitsKey, indexKey) {
  return computed(indexKey, {
    get() {
      return this.get(unitsKey)[this.get(indexKey)];
    },
    set(key, value) {
      this.set(indexKey, this.get(unitsKey).indexOf(value));
      return value;
    },
  });
}
<|endoftext|>


<commit_before>var Class = require('../../utils/Class');
var File = require('../File');
var GetFastValue = require('../../utils/object/GetFastValue');
var GetURL = require('../GetURL');

//  Phaser.Loader.FileTypes.HTML5AudioFile

var HTML5AudioFile = new Class({

    Extends: File,

    initialize:

        function HTML5AudioFile (key, url, path, config)
        {
            var fileConfig = {
                type: 'audio',
                extension: GetFastValue(url, 'type', ''),
                key: key,
                url: GetFastValue(url, 'uri', url),
                path: path,
                config: config
            };

            File.call(this, fileConfig);
        },

    //  Called by the Loader, starts the actual file downloading
    load: function (callback, baseURL)
    {
        this.callback = callback;

        this.data = [];

        var instances = (this.config && this.config.instances) || 1;

        for(var i = 0; i < instances; i++)
        {
            var audio = new Audio();
            audio.name = this.key;
            audio.preload = 'auto';
            audio.src = GetURL(this, baseURL || '');
            audio.load();

            this.data.push(audio);
        }
    }

});

module.exports = HTML5AudioFile;
<commit_msg>Added onLoad and onError methods to HTML5AudioFile class<commit_after>var Class = require('../../utils/Class');
var File = require('../File');
var GetFastValue = require('../../utils/object/GetFastValue');
var GetURL = require('../GetURL');

//  Phaser.Loader.FileTypes.HTML5AudioFile

var HTML5AudioFile = new Class({

    Extends: File,

    initialize:

        function HTML5AudioFile (key, url, path, config)
        {
            var fileConfig = {
                type: 'audio',
                extension: GetFastValue(url, 'type', ''),
                key: key,
                url: GetFastValue(url, 'uri', url),
                path: path,
                config: config
            };

            File.call(this, fileConfig);
        },

    onLoad: function ()
    {
        this.callback(this, true);
    },

    onError: function (event)
    {
        this.callback(this, false);
    },

    //  Called by the Loader, starts the actual file downloading
    load: function (callback, baseURL)
    {
        this.callback = callback;

        this.data = [];

        var instances = (this.config && this.config.instances) || 1;

        for(var i = 0; i < instances; i++)
        {
            var audio = new Audio();
            audio.name = this.key;
            audio.preload = 'auto';
            audio.src = GetURL(this, baseURL || '');
            audio.load();

            this.data.push(audio);
        }
    }

});

module.exports = HTML5AudioFile;
<|endoftext|>


<commit_before>'use strict';

describe('Main View', function() {
  var page;

  beforeEach(function() {
    browser.get('/');
    page = require('./main.po');
  });

  it('should have video iframe and empty comment form', function() {
    expect(page.iFrame.getAttribute('src')).toBe('http://www.youtube.com/embed/DcJFdCmN98s');
    expect(page.submitBtn.getText()).toBe('Post');
    expect((page.commentBox.getText())).toBe('');
  });

  it('should at leat have a comment placeholder', function() {

    expect(page.commentList.count()).not.toBeLessThan(4);
  });

  it('should should add a new comment', function() {
     var old = page.commentList.count();
     page.commentBox.sendKeys('Some text from protactor');
     page.submitBtn.click();

     var newcount = page.commentList.count();
     expect(old).toBeLessThan(newcount);
  });

  it('should edit previously added comment', function() {
      expect(page.editLink).toBeTruthy();
      page.editLink.click();

      expect(page.commentBox).not.toBe('');

      page.commentBox.sendKeys(' some new edits');
      page.submitBtn.click();

      var old = page.commentList.count();
      expect(page.commentList.count()).toBe(old);
  });

});

<commit_msg>Added e2e test : delete comment<commit_after>'use strict';

describe('Main View', function() {
  var page;

  beforeEach(function() {
    browser.get('/');
    page = require('./main.po');
  });

  it('should have video iframe and empty comment form', function() {
    expect(page.iFrame.getAttribute('src')).toBe('http://www.youtube.com/embed/DcJFdCmN98s');
    expect(page.submitBtn.getText()).toBe('Post');
    expect((page.commentBox.getText())).toBe('');
  });

  it('should at leat have a comment placeholder', function() {

    expect(page.commentList.count()).not.toBeLessThan(4);
  });

  it('should should add a new comment', function() {
     var old = page.commentList.count();
     page.commentBox.sendKeys('Some text from protactor');
     page.submitBtn.click();

     var newcount = page.commentList.count();
     expect(old).toBeLessThan(newcount);
  });

  it('should edit previously added comment', function() {
      expect(page.editLink.getText()).toBeTruthy();
      page.editLink.click();

      expect(page.commentBox).not.toBe('');

      page.commentBox.sendKeys(' some new edits');
      page.submitBtn.click();

      var old = page.commentList.count();
      expect(page.commentList.count()).toBe(old);
  });

  it('should edit previously added comment', function() {
    expect(page.deleteLink.getText()).toBeTruthy();

    var old = page.commentList.count();
    page.deleteLink.click();

    expect(page.commentList.count()).toBeLessThan(old);
  });

});

<|endoftext|>


<commit_before>var TogglButton = {
  $apiUrl: "https://www.toggl.com/api/v7",
  $newApiUrl: "https://new.toggl.com/api/v8",
  $triedAlternative: false,
  $api_token: null,
  $default_wid: null,
  $clientMap: {},
  $projectMap: {},
  $curEntryId: null,

  fetchUser: function (apiUrl, callback) {
    var timeNow = new Date().getTime(),
      timeAuth = GM_getValue('_authenticated', 0);
    if ((timeNow - timeAuth) < (6*60*60*1000)) {
      this.$api_token   = GM_getValue('_api_token', false);
      this.$default_wid = GM_getValue('_default_wid', 0);
      this.$clientMap   = JSON.parse(GM_getValue('_clientMap', {}));
      this.$projectMap  = JSON.parse(GM_getValue('_projectMap', {}));
      callback();
      return;
    }
    GM_xmlhttpRequest({
      method: "GET",
      url: apiUrl + "/me?with_related_data=true",
      onload: function(result) {
        if (result.status === 200) {
          var resp = JSON.parse(result.responseText);
          TogglButton.$clientMap[0] = 'No Client';
          if (resp.data.clients) {
            resp.data.clients.forEach(function (client) {
              TogglButton.$clientMap[client.id] = client.name;
            });
          }
          if (resp.data.projects) {
            resp.data.projects.forEach(function (project) {
              if (TogglButton.$clientMap[project.cid] == undefined) {
                project.cid = 0;
              }
              if (project.active) {
                TogglButton.$projectMap[project.id] = {
                  id: project.id,
                  cid: project.cid,
                  name: project.name
                };
              }
            });
          }
          GM_setValue('_authenticated', new Date().getTime());
          GM_setValue('_api_token', resp.data.api_token);
          GM_setValue('_default_wid', resp.data.default_wid);
          GM_setValue('_clientMap', JSON.stringify(TogglButton.$clientMap));
          GM_setValue('_projectMap', JSON.stringify(TogglButton.$projectMap));
          TogglButton.$api_token = resp.data.api_token;
          TogglButton.$default_wid = resp.data.default_wid;
          callback();
        } else if (!TogglButton.$triedAlternative) {
          TogglButton.$triedAlternative = true;
          if (apiUrl === TogglButton.$apiUrl) {
            TogglButton.fetchUser(TogglButton.$newApiUrl, callback);
          } else if (apiUrl === TogglButton.$newApiUrl) {
            TogglButton.fetchUser(TogglButton.$apiUrl, callback);
          }
        }
      }
    });
  },

  createTimeEntry: function (timeEntry) {
    var start = new Date(),
      entry = {
        time_entry: {
          start: start.toISOString(),
          description: timeEntry.description,
          wid: TogglButton.$default_wid,
          pid: timeEntry.projectId || null,
          billable: timeEntry.billable || false,
          duration: -(start.getTime() / 1000),
          created_with: timeEntry.createdWith || 'GM TogglButton'
        }
      };
    GM_xmlhttpRequest({
      method: "POST",
      url: TogglButton.$newApiUrl + "/time_entries",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      },
      data: JSON.stringify(entry),
      onload: function(res) {
        var responseData, entryId;
        responseData = JSON.parse(res.responseText);
        entryId = responseData && responseData.data && responseData.data.id;
        TogglButton.$curEntryId = entryId;
      }
    });
  },

  checkCurrentTimeEntry: function (params) {
    GM_xmlhttpRequest({
      method: "GET",
      url: TogglButton.$newApiUrl + "/time_entries/current",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      },
      onload: function(result) {
        if (result.status === 200) {
          var resp = JSON.parse(result.responseText);
          if (resp == null) {
            return;
          }
          if (params.description === resp.data.description) {
            TogglButton.$curEntryId = resp.data.id;
            togglbutton.isStarted = false;
            updateLink();
          }
        }
      }
    });
  },

  stopTimeEntry: function (entryId) {
    entryId = entryId || TogglButton.$curEntryId;
    if (!entryId) {
      return;
    }
    GM_xmlhttpRequest({
      method: "PUT",
      url: TogglButton.$newApiUrl + "/time_entries/" + entryId + "/stop",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      }
    });
  },

  newMessage: function (request) {
    if (request.type === 'activate') {
      // TODO: Can we show something in the main window or the URL bar?
      return (TogglButton.$user !== null);
    } else if (request.type === 'timeEntry') {
      TogglButton.createTimeEntry(request);
    } else if (request.type === 'stop') {
      TogglButton.stopTimeEntry();
    } else if (request.type === 'checkCurrentTimeEntry') {
      TogglButton.checkCurrentTimeEntry(request);
    }
  }

};

function $(s, elem) {
  elem = elem || document;
  return elem.querySelector(s);
}

function createTag(name, className, innerHTML) {
  var tag = document.createElement(name);
  tag.className = className;

  if (innerHTML) {
    tag.innerHTML = innerHTML;
  }

  return tag;
}

function createLink(className, tagName, linkHref) {
  var link;

  // Param defaults
  tagName  = tagName  || 'a';
  linkHref = linkHref || '#';
  link     = createTag(tagName, className);

  if (tagName === 'a') {
    link.href = linkHref;
  }

  link.appendChild(document.createTextNode('Start timer'));
  return link;
}

function updateLink() {
  var linkText, color = '';

  if (togglbutton.isStarted) {
    togglbutton.link.classList.remove('active');
    linkText = 'Start timer';
  } else {
    togglbutton.link.classList.add('active');
    color = '#1ab351';
    linkText = 'Stop timer';
  }
  togglbutton.isStarted = !togglbutton.isStarted;
  togglbutton.link.style.color = color;
  if (!togglbutton.buttonTypeMinimal) {
    togglbutton.link.innerHTML = linkText;
  }
}

function invokeIfFunction(trial) {
  if (trial instanceof Function) {
    return trial();
  }
  return trial;
}

var togglbutton = {
  isStarted: false,
  link: null,
  buttonTypeMinimal: false,
  projectSelector: window.location.host,
  projectId: 0,
  render: function (selector, opts, renderer) {
    if (TogglButton.newMessage({type: 'activate'})) {
      togglbutton.renderTo(selector, renderer);
    }
  },

  renderTo: function (selector, renderer) {
    var i, len, elems = document.querySelectorAll(selector);
    for (i = 0, len = elems.length; i < len; i += 1) {
      elems[i].classList.add('toggl');
    }
    for (i = 0, len = elems.length; i < len; i += 1) {
      renderer(elems[i]);
    }
  },

  createTimerLink: function (params) {
    if (params.projectIds !== undefined) {
      this.projectSelector += '-' + params.projectIds.join('-');
    }
    this.projectId = GM_getValue(this.projectSelector, 0);
    GM_addStyle(GM_getResourceText('togglStyle'));
    this.link = createLink('toggl-button');
    this.link.classList.add(params.className);

    if (params.buttonType === 'minimal') {
      this.link.classList.add('min');
      this.link.removeChild(this.link.firstChild);
      this.buttonTypeMinimal = true;
    }

    this.link.addEventListener('click', function (e) {
      var opts = '';
      e.preventDefault();
      if (togglbutton.isStarted) {
        opts = {type: 'stop'};
      } else {
        opts = {
          type: 'timeEntry',
          projectId: togglbutton.projectId,
          description: invokeIfFunction(params.description),
          createdWith: 'GM TogglButton - ' + params.className
        };
      }
      TogglButton.newMessage(opts);
      updateLink();

      return false;
    });

    // new button created - reset state
    this.isStarted = false;

    // check if our link is the current time entry and set the state if it is
    var opts = {
      type: 'checkCurrentTimeEntry',
      projectId: togglbutton.projectId,
      description: invokeIfFunction(params.description)
    };
    TogglButton.newMessage(opts);

    $(params.targetSelectors.link).appendChild(this.link);
    $(params.targetSelectors.projectSelect).appendChild(createProjectSelect());

    return this.link;
  }
};

function createProjectSelect() {
  var pid,
    wrapper = createTag('div', 'toggl-button-project-select'),
    select = createTag('select'),
    resetOption = document.createElement('option');

  for (pid in TogglButton.$projectMap) {
    var optgroup, project = TogglButton.$projectMap[pid];
    if (typeof TogglButton.$clientMap[project.cid] === 'string') {
      optgroup = createTag('optgroup');
      optgroup.label = TogglButton.$clientMap[project.cid];
      TogglButton.$clientMap[project.cid] = optgroup;
      select.appendChild(optgroup);
    } else {
      optgroup = TogglButton.$clientMap[project.cid];
    }
    var option = document.createElement('option');
    option.setAttribute('value', project.id);
    option.text = project.name;
    optgroup.appendChild(option);
  }
  resetOption.setAttribute('value', 'RESET');
  resetOption.text = 'Reload settings';
  select.appendChild(resetOption);

  select.addEventListener('change', function (e) {
    if (select.value == 'RESET') {
      GM_setValue('_authenticated', 0);
      return;
    }
    togglbutton.projectId = select.value;
    GM_setValue(togglbutton.projectSelector, togglbutton.projectId);

  });

  select.value = togglbutton.projectId;

  wrapper.appendChild(select);
  return wrapper;
}
<commit_msg>#3 Reload automatically when settings get reset<commit_after>var TogglButton = {
  $apiUrl: "https://www.toggl.com/api/v7",
  $newApiUrl: "https://new.toggl.com/api/v8",
  $triedAlternative: false,
  $api_token: null,
  $default_wid: null,
  $clientMap: {},
  $projectMap: {},
  $curEntryId: null,

  fetchUser: function (apiUrl, callback) {
    var timeNow = new Date().getTime(),
      timeAuth = GM_getValue('_authenticated', 0);
    if ((timeNow - timeAuth) < (6*60*60*1000)) {
      this.$api_token   = GM_getValue('_api_token', false);
      this.$default_wid = GM_getValue('_default_wid', 0);
      this.$clientMap   = JSON.parse(GM_getValue('_clientMap', {}));
      this.$projectMap  = JSON.parse(GM_getValue('_projectMap', {}));
      callback();
      return;
    }
    GM_xmlhttpRequest({
      method: "GET",
      url: apiUrl + "/me?with_related_data=true",
      onload: function(result) {
        if (result.status === 200) {
          var resp = JSON.parse(result.responseText);
          TogglButton.$clientMap[0] = 'No Client';
          if (resp.data.clients) {
            resp.data.clients.forEach(function (client) {
              TogglButton.$clientMap[client.id] = client.name;
            });
          }
          if (resp.data.projects) {
            resp.data.projects.forEach(function (project) {
              if (TogglButton.$clientMap[project.cid] == undefined) {
                project.cid = 0;
              }
              if (project.active) {
                TogglButton.$projectMap[project.id] = {
                  id: project.id,
                  cid: project.cid,
                  name: project.name
                };
              }
            });
          }
          GM_setValue('_authenticated', new Date().getTime());
          GM_setValue('_api_token', resp.data.api_token);
          GM_setValue('_default_wid', resp.data.default_wid);
          GM_setValue('_clientMap', JSON.stringify(TogglButton.$clientMap));
          GM_setValue('_projectMap', JSON.stringify(TogglButton.$projectMap));
          TogglButton.$api_token = resp.data.api_token;
          TogglButton.$default_wid = resp.data.default_wid;
          callback();
        } else if (!TogglButton.$triedAlternative) {
          TogglButton.$triedAlternative = true;
          if (apiUrl === TogglButton.$apiUrl) {
            TogglButton.fetchUser(TogglButton.$newApiUrl, callback);
          } else if (apiUrl === TogglButton.$newApiUrl) {
            TogglButton.fetchUser(TogglButton.$apiUrl, callback);
          }
        }
      }
    });
  },

  createTimeEntry: function (timeEntry) {
    var start = new Date(),
      entry = {
        time_entry: {
          start: start.toISOString(),
          description: timeEntry.description,
          wid: TogglButton.$default_wid,
          pid: timeEntry.projectId || null,
          billable: timeEntry.billable || false,
          duration: -(start.getTime() / 1000),
          created_with: timeEntry.createdWith || 'GM TogglButton'
        }
      };
    GM_xmlhttpRequest({
      method: "POST",
      url: TogglButton.$newApiUrl + "/time_entries",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      },
      data: JSON.stringify(entry),
      onload: function(res) {
        var responseData, entryId;
        responseData = JSON.parse(res.responseText);
        entryId = responseData && responseData.data && responseData.data.id;
        TogglButton.$curEntryId = entryId;
      }
    });
  },

  checkCurrentTimeEntry: function (params) {
    GM_xmlhttpRequest({
      method: "GET",
      url: TogglButton.$newApiUrl + "/time_entries/current",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      },
      onload: function(result) {
        if (result.status === 200) {
          var resp = JSON.parse(result.responseText);
          if (resp == null) {
            return;
          }
          if (params.description === resp.data.description) {
            TogglButton.$curEntryId = resp.data.id;
            togglbutton.isStarted = false;
            updateLink();
          }
        }
      }
    });
  },

  stopTimeEntry: function (entryId) {
    entryId = entryId || TogglButton.$curEntryId;
    if (!entryId) {
      return;
    }
    GM_xmlhttpRequest({
      method: "PUT",
      url: TogglButton.$newApiUrl + "/time_entries/" + entryId + "/stop",
      headers: {
        "Authorization": "Basic " + btoa(TogglButton.$api_token + ':api_token')
      }
    });
  },

  newMessage: function (request) {
    if (request.type === 'activate') {
      // TODO: Can we show something in the main window or the URL bar?
      return (TogglButton.$user !== null);
    } else if (request.type === 'timeEntry') {
      TogglButton.createTimeEntry(request);
    } else if (request.type === 'stop') {
      TogglButton.stopTimeEntry();
    } else if (request.type === 'checkCurrentTimeEntry') {
      TogglButton.checkCurrentTimeEntry(request);
    }
  }

};

function $(s, elem) {
  elem = elem || document;
  return elem.querySelector(s);
}

function createTag(name, className, innerHTML) {
  var tag = document.createElement(name);
  tag.className = className;

  if (innerHTML) {
    tag.innerHTML = innerHTML;
  }

  return tag;
}

function createLink(className, tagName, linkHref) {
  var link;

  // Param defaults
  tagName  = tagName  || 'a';
  linkHref = linkHref || '#';
  link     = createTag(tagName, className);

  if (tagName === 'a') {
    link.href = linkHref;
  }

  link.appendChild(document.createTextNode('Start timer'));
  return link;
}

function updateLink() {
  var linkText, color = '';

  if (togglbutton.isStarted) {
    togglbutton.link.classList.remove('active');
    linkText = 'Start timer';
  } else {
    togglbutton.link.classList.add('active');
    color = '#1ab351';
    linkText = 'Stop timer';
  }
  togglbutton.isStarted = !togglbutton.isStarted;
  togglbutton.link.style.color = color;
  if (!togglbutton.buttonTypeMinimal) {
    togglbutton.link.innerHTML = linkText;
  }
}

function invokeIfFunction(trial) {
  if (trial instanceof Function) {
    return trial();
  }
  return trial;
}

var togglbutton = {
  isStarted: false,
  link: null,
  buttonTypeMinimal: false,
  projectSelector: window.location.host,
  projectId: 0,
  render: function (selector, opts, renderer) {
    if (TogglButton.newMessage({type: 'activate'})) {
      togglbutton.renderTo(selector, renderer);
    }
  },

  renderTo: function (selector, renderer) {
    var i, len, elems = document.querySelectorAll(selector);
    for (i = 0, len = elems.length; i < len; i += 1) {
      elems[i].classList.add('toggl');
    }
    for (i = 0, len = elems.length; i < len; i += 1) {
      renderer(elems[i]);
    }
  },

  createTimerLink: function (params) {
    if (params.projectIds !== undefined) {
      this.projectSelector += '-' + params.projectIds.join('-');
    }
    this.projectId = GM_getValue(this.projectSelector, 0);
    GM_addStyle(GM_getResourceText('togglStyle'));
    this.link = createLink('toggl-button');
    this.link.classList.add(params.className);

    if (params.buttonType === 'minimal') {
      this.link.classList.add('min');
      this.link.removeChild(this.link.firstChild);
      this.buttonTypeMinimal = true;
    }

    this.link.addEventListener('click', function (e) {
      var opts = '';
      e.preventDefault();
      if (togglbutton.isStarted) {
        opts = {type: 'stop'};
      } else {
        opts = {
          type: 'timeEntry',
          projectId: togglbutton.projectId,
          description: invokeIfFunction(params.description),
          createdWith: 'GM TogglButton - ' + params.className
        };
      }
      TogglButton.newMessage(opts);
      updateLink();

      return false;
    });

    // new button created - reset state
    this.isStarted = false;

    // check if our link is the current time entry and set the state if it is
    var opts = {
      type: 'checkCurrentTimeEntry',
      projectId: togglbutton.projectId,
      description: invokeIfFunction(params.description)
    };
    TogglButton.newMessage(opts);

    $(params.targetSelectors.link).appendChild(this.link);
    $(params.targetSelectors.projectSelect).appendChild(createProjectSelect());

    return this.link;
  }
};

function createProjectSelect() {
  var pid,
    wrapper = createTag('div', 'toggl-button-project-select'),
    select = createTag('select'),
    resetOption = document.createElement('option');

  for (pid in TogglButton.$projectMap) {
    var optgroup, project = TogglButton.$projectMap[pid];
    if (typeof TogglButton.$clientMap[project.cid] === 'string') {
      optgroup = createTag('optgroup');
      optgroup.label = TogglButton.$clientMap[project.cid];
      TogglButton.$clientMap[project.cid] = optgroup;
      select.appendChild(optgroup);
    } else {
      optgroup = TogglButton.$clientMap[project.cid];
    }
    var option = document.createElement('option');
    option.setAttribute('value', project.id);
    option.text = project.name;
    optgroup.appendChild(option);
  }
  resetOption.setAttribute('value', 'RESET');
  resetOption.text = 'Reload settings';
  select.appendChild(resetOption);

  select.addEventListener('change', function (e) {
    if (select.value == 'RESET') {
      GM_setValue('_authenticated', 0);
      window.location.reload();
      return;
    }
    togglbutton.projectId = select.value;
    GM_setValue(togglbutton.projectSelector, togglbutton.projectId);

  });

  select.value = togglbutton.projectId;

  wrapper.appendChild(select);
  return wrapper;
}
<|endoftext|>


<commit_before>/**
 * @author: Yura Knoxville
 * @version: v1.1.0
 */

let initBodyCaller

const groupBy = (array, f) => {
  const tmpGroups = {}
  array.forEach(o => {
    const groups = f(o)
    tmpGroups[groups] = tmpGroups[groups] || []
    tmpGroups[groups].push(o)
  })

  return tmpGroups
}

$.extend($.fn.bootstrapTable.defaults.icons, {
  collapseGroup: {
    bootstrap3: 'glyphicon-chevron-up',
    materialize: 'arrow_drop_down'
  }[$.fn.bootstrapTable.theme] || 'fa-angle-up',
  expandGroup: {
    bootstrap3: 'glyphicon-chevron-down',
    materialize: 'arrow_drop_up'
  }[$.fn.bootstrapTable.theme] || 'fa-angle-down'
})

$.extend($.fn.bootstrapTable.defaults, {
  groupBy: false,
  groupByField: '',
  groupByFormatter: undefined,
  groupByToggle: false,
  groupByShowToggleIcon: false
})

const Utils = $.fn.bootstrapTable.utils
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initSort = BootstrapTable.prototype.initSort
const _initBody = BootstrapTable.prototype.initBody
const _updateSelected = BootstrapTable.prototype.updateSelected

BootstrapTable.prototype.initSort = function (...args) {
  _initSort.apply(this, Array.prototype.slice.apply(args))

  const that = this
  this.tableGroups = []

  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
    if ((this.options.sortName !== this.options.groupByField)) {
      if (this.options.customSort) {
        Utils.calculateObjectValue(this.options, this.options.customSort, [
          this.options.sortName,
          this.options.sortOrder,
          this.data
        ])
      } else {
        this.data.sort((a, b) => {
          const groupByFields = this.getGroupByFields()
          const fieldValuesA = []
          const fieldValuesB = []

          $.each(groupByFields, (i, field) => {
            fieldValuesA.push(a[field])
            fieldValuesB.push(b[field])
          })

          a = fieldValuesA.join()
          b = fieldValuesB.join()
          return a.localeCompare(b, undefined, {numeric: true})
        })
      }
    }

    const groups = groupBy(that.data, (item) => {
      const groupByFields = this.getGroupByFields()
      const groupValues = []
      $.each(groupByFields, (i, field) => {
        groupValues.push(item[field])
      })

      return groupValues.join(', ')
    })

    let index = 0
    $.each(groups, (key, value) => {
      this.tableGroups.push({
        id: index,
        name: key,
        data: value
      })

      value.forEach(item => {
        if (!item._data) {
          item._data = {}
        }

        item._data['parent-index'] = index
      })

      index++
    })
  }
}

BootstrapTable.prototype.initBody = function (...args) {
  initBodyCaller = true
  _initBody.apply(this, Array.prototype.slice.apply(args))

  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
    const that = this
    let checkBox = false
    let visibleColumns = 0

    this.columns.forEach(column => {
      if (column.checkbox) {
        checkBox = true
      } else {
        if (column.visible) {
          visibleColumns += 1
        }
      }
    })

    if (this.options.detailView && !this.options.cardView) {
      visibleColumns += 1
    }

    this.tableGroups.forEach(item => {
      const html = []

      html.push(Utils.sprintf('
', this.options.groupByToggle ? 'expanded' : '', item.id))
      if (that.options.detailView && !that.options.cardView) {
        html.push('	')
      }

      if (checkBox) {
        html.push('',
          '<input name="btSelectGroup" type="checkbox" />',
          '	'
        )
      }

      let formattedValue = item.name
      if (typeof (that.options.groupByFormatter) === 'function') {
        formattedValue = that.options.groupByFormatter(item.name, item.id, item.data)
      }
      html.push('', formattedValue
      )

      if (this.options.groupByToggle && this.options.groupByShowToggleIcon) {
        html.push(`<span class="float-right ${this.options.iconsPrefix} ${this.options.icons.collapseGroup}"></span>`)
      }

      html.push('
')
      that.$body.find(`tr[data-parent-index=${item.id}]:first`).before($(html.join('')))
    })

    this.$selectGroup = []
    this.$body.find('[name="btSelectGroup"]').each(function () {
      const self = $(this)

      that.$selectGroup.push({
        group: self,
        item: that.$selectItem.filter(function () {
          return ($(this).closest('tr').data('parent-index') ===
            self.closest('tr').data('group-index'))
        })
      })
    })

    if (this.options.groupByToggle) {
      this.$container.off('click', '.groupBy')
        .on('click', '.groupBy', function () {
          $(this).toggleClass('expanded collapsed')
          $(this).find('span').toggleClass(`${that.options.icons.collapseGroup} ${that.options.icons.expandGroup}`)
          that.$body.find(`tr[data-parent-index=${$(this).closest('tr').data('group-index')}]`).toggleClass('hidden')
        })
    }

    this.$container.off('click', '[name="btSelectGroup"]')
      .on('click', '[name="btSelectGroup"]', function (event) {
        event.stopImmediatePropagation()

        const self = $(this)
        const checked = self.prop('checked')
        that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'))
      })
  }

  initBodyCaller = false
  this.updateSelected()
}

BootstrapTable.prototype.updateSelected = function (...args) {
  if (!initBodyCaller) {
    _updateSelected.apply(this, Array.prototype.slice.apply(args))

    if ((this.options.groupBy) && (this.options.groupByField !== '')) {
      this.$selectGroup.forEach(item => {
        const checkGroup = item.item.filter(':enabled').length ===
          item.item.filter(':enabled').filter(':checked').length

        item.group.prop('checked', checkGroup)
      })
    }
  }
}

BootstrapTable.prototype.checkGroup = function (index) {
  this.checkGroup_(index, true)
}

BootstrapTable.prototype.uncheckGroup = function (index) {
  this.checkGroup_(index, false)
}

BootstrapTable.prototype.checkGroup_ = function (index, checked) {
  const rowsBefore = this.getSelections()
  let rows
  const filter = function () {
    return ($(this).closest('tr').data('parent-index') === index)
  }

  this.$selectItem.filter(filter).prop('checked', checked)

  this.updateRows()
  this.updateSelected()
  const rowsAfter = this.getSelections()
  if (checked) {
    this.trigger('check-all', rowsAfter, rowsBefore)
    return
  }

  this.trigger('uncheck-all', rowsAfter, rowsBefore)
}

BootstrapTable.prototype.getGroupByFields = function () {
  let groupByFields = this.options.groupByField
  if (!$.isArray(this.options.groupByField)) {
    groupByFields = [this.options.groupByField]
  }

  return groupByFields
}

$.BootstrapTable = class extends $.BootstrapTable {
  scrollTo (params) {
    if (this.options.groupBy) {
      let options = {unit: 'px', value: 0}
      if (typeof params === 'object') {
        options = Object.assign(options, params)
      }

      if (options.unit === 'rows') {
        let scrollTo = 0
        this.$body.find(`> tr:lt(${options.value})`).each((i, el) => {
          scrollTo += $(el).outerHeight(true)
        })

        const $targetColumn = this.$body.find(`> tr:not(.groupBy):eq(${options.value})`)
        $targetColumn.prevAll('.groupBy').each((i, el) => {
          scrollTo += $(el).outerHeight(true)
        })

        this.$tableBody.scrollTop(scrollTo)
        return
      }
    }

    super.scrollTo(params)
  }
}<commit_msg>exclude the groupBy columns<commit_after>/**
 * @author: Yura Knoxville
 * @version: v1.1.0
 */

let initBodyCaller

const groupBy = (array, f) => {
  const tmpGroups = {}
  array.forEach(o => {
    const groups = f(o)
    tmpGroups[groups] = tmpGroups[groups] || []
    tmpGroups[groups].push(o)
  })

  return tmpGroups
}

$.extend($.fn.bootstrapTable.defaults.icons, {
  collapseGroup: {
    bootstrap3: 'glyphicon-chevron-up',
    materialize: 'arrow_drop_down'
  }[$.fn.bootstrapTable.theme] || 'fa-angle-up',
  expandGroup: {
    bootstrap3: 'glyphicon-chevron-down',
    materialize: 'arrow_drop_up'
  }[$.fn.bootstrapTable.theme] || 'fa-angle-down'
})

$.extend($.fn.bootstrapTable.defaults, {
  groupBy: false,
  groupByField: '',
  groupByFormatter: undefined,
  groupByToggle: false,
  groupByShowToggleIcon: false
})

const Utils = $.fn.bootstrapTable.utils
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initSort = BootstrapTable.prototype.initSort
const _initBody = BootstrapTable.prototype.initBody
const _updateSelected = BootstrapTable.prototype.updateSelected

BootstrapTable.prototype.initSort = function (...args) {
  _initSort.apply(this, Array.prototype.slice.apply(args))

  const that = this
  this.tableGroups = []

  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
    if ((this.options.sortName !== this.options.groupByField)) {
      if (this.options.customSort) {
        Utils.calculateObjectValue(this.options, this.options.customSort, [
          this.options.sortName,
          this.options.sortOrder,
          this.data
        ])
      } else {
        this.data.sort((a, b) => {
          const groupByFields = this.getGroupByFields()
          const fieldValuesA = []
          const fieldValuesB = []

          $.each(groupByFields, (i, field) => {
            fieldValuesA.push(a[field])
            fieldValuesB.push(b[field])
          })

          a = fieldValuesA.join()
          b = fieldValuesB.join()
          return a.localeCompare(b, undefined, {numeric: true})
        })
      }
    }

    const groups = groupBy(that.data, (item) => {
      const groupByFields = this.getGroupByFields()
      const groupValues = []
      $.each(groupByFields, (i, field) => {
        groupValues.push(item[field])
      })

      return groupValues.join(', ')
    })

    let index = 0
    $.each(groups, (key, value) => {
      this.tableGroups.push({
        id: index,
        name: key,
        data: value
      })

      value.forEach(item => {
        if (!item._data) {
          item._data = {}
        }

        item._data['parent-index'] = index
      })

      index++
    })
  }
}

BootstrapTable.prototype.initBody = function (...args) {
  initBodyCaller = true
  _initBody.apply(this, Array.prototype.slice.apply(args))

  if ((this.options.groupBy) && (this.options.groupByField !== '')) {
    const that = this
    let checkBox = false
    let visibleColumns = 0

    this.columns.forEach(column => {
      if (column.checkbox) {
        checkBox = true
      } else {
        if (column.visible) {
          visibleColumns += 1
        }
      }
    })

    if (this.options.detailView && !this.options.cardView) {
      visibleColumns += 1
    }

    this.tableGroups.forEach(item => {
      const html = []

      html.push(Utils.sprintf('
', this.options.groupByToggle ? 'expanded' : '', item.id))
      if (that.options.detailView && !that.options.cardView) {
        html.push('	')
      }

      if (checkBox) {
        html.push('',
          '<input name="btSelectGroup" type="checkbox" />',
          '	'
        )
      }

      let formattedValue = item.name
      if (typeof (that.options.groupByFormatter) === 'function') {
        formattedValue = that.options.groupByFormatter(item.name, item.id, item.data)
      }
      html.push('', formattedValue
      )

      if (this.options.groupByToggle && this.options.groupByShowToggleIcon) {
        html.push(`<span class="float-right ${this.options.iconsPrefix} ${this.options.icons.collapseGroup}"></span>`)
      }

      html.push('
')
      that.$body.find(`tr[data-parent-index=${item.id}]:first`).before($(html.join('')))
    })

    this.$selectGroup = []
    this.$body.find('[name="btSelectGroup"]').each(function () {
      const self = $(this)

      that.$selectGroup.push({
        group: self,
        item: that.$selectItem.filter(function () {
          return ($(this).closest('tr').data('parent-index') ===
            self.closest('tr').data('group-index'))
        })
      })
    })

    if (this.options.groupByToggle) {
      this.$container.off('click', '.groupBy')
        .on('click', '.groupBy', function () {
          $(this).toggleClass('expanded collapsed')
          $(this).find('span').toggleClass(`${that.options.icons.collapseGroup} ${that.options.icons.expandGroup}`)
          that.$body.find(`tr[data-parent-index=${$(this).closest('tr').data('group-index')}]`).toggleClass('hidden')
        })
    }

    this.$container.off('click', '[name="btSelectGroup"]')
      .on('click', '[name="btSelectGroup"]', function (event) {
        event.stopImmediatePropagation()

        const self = $(this)
        const checked = self.prop('checked')
        that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'))
      })
  }

  initBodyCaller = false
  this.updateSelected()
}

BootstrapTable.prototype.updateSelected = function (...args) {
  if (!initBodyCaller) {
    _updateSelected.apply(this, Array.prototype.slice.apply(args))

    if ((this.options.groupBy) && (this.options.groupByField !== '')) {
      this.$selectGroup.forEach(item => {
        const checkGroup = item.item.filter(':enabled').length ===
          item.item.filter(':enabled').filter(':checked').length

        item.group.prop('checked', checkGroup)
      })
    }
  }
}

BootstrapTable.prototype.checkGroup = function (index) {
  this.checkGroup_(index, true)
}

BootstrapTable.prototype.uncheckGroup = function (index) {
  this.checkGroup_(index, false)
}

BootstrapTable.prototype.checkGroup_ = function (index, checked) {
  const rowsBefore = this.getSelections()
  let rows
  const filter = function () {
    return ($(this).closest('tr').data('parent-index') === index)
  }

  this.$selectItem.filter(filter).prop('checked', checked)

  this.updateRows()
  this.updateSelected()
  const rowsAfter = this.getSelections()
  if (checked) {
    this.trigger('check-all', rowsAfter, rowsBefore)
    return
  }

  this.trigger('uncheck-all', rowsAfter, rowsBefore)
}

BootstrapTable.prototype.getGroupByFields = function () {
  let groupByFields = this.options.groupByField
  if (!$.isArray(this.options.groupByField)) {
    groupByFields = [this.options.groupByField]
  }

  return groupByFields
}

$.BootstrapTable = class extends $.BootstrapTable {
  scrollTo (params) {
    if (this.options.groupBy) {
      let options = {unit: 'px', value: 0}
      if (typeof params === 'object') {
        options = Object.assign(options, params)
      }

      if (options.unit === 'rows') {
        let scrollTo = 0
        this.$body.find(`> tr:not(.groupBy):lt(${options.value})`).each((i, el) => {
          scrollTo += $(el).outerHeight(true)
        })

        const $targetColumn = this.$body.find(`> tr:not(.groupBy):eq(${options.value})`)
        $targetColumn.prevAll('.groupBy').each((i, el) => {
          scrollTo += $(el).outerHeight(true)
        })

        this.$tableBody.scrollTop(scrollTo)
        return
      }
    }

    super.scrollTo(params)
  }
}<|endoftext|>


<commit_before>import * as React from 'react'
import PropTypes from 'prop-types'

import { SnackbarProvider } from 'notistack'
import { makeStyles } from '@material-ui/core/styles'

const useStyles = makeStyles(({ palette }) => ({
  variantSuccess: {
    backgroundColor: `${palette.success.main} !important`,
    color: palette.success.contrastText
  },
  variantError: {
    backgroundColor: `${palette.error.main} !important`,
    color: palette.error.contrastText
  },
  variantInfo: {
    backgroundColor: `${palette.debug.main} !important`,
    color: palette.debug.contrastText
  },
  variantWarning: {
    backgroundColor: `${palette.warning.main} !important`,
    color: palette.warning.contrastText
  }
}))

const NotistackProvider = ({ children }) => {
  const classes = useStyles()
  return (
    <SnackbarProvider
      hideIconVariant
      classes={classes}
      anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
    >
      {children}
    </SnackbarProvider>
  )
}

NotistackProvider.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.node,
    PropTypes.arrayOf(PropTypes.node)
  ])
}

NotistackProvider.defaultProps = {
  children: undefined
}

export default NotistackProvider
<commit_msg>M #~: Fix styles for notification with long text (#1046)<commit_after>import * as React from 'react'
import PropTypes from 'prop-types'

import { SnackbarProvider } from 'notistack'
import { makeStyles } from '@material-ui/core/styles'

const useStyles = makeStyles(({ palette }) => ({
  containerRoot: {
    marginLeft: 20,
    wordBreak: 'break-all'
  },
  variantSuccess: {
    backgroundColor: `${palette.success.main} !important`,
    color: palette.success.contrastText
  },
  variantError: {
    backgroundColor: `${palette.error.main} !important`,
    color: palette.error.contrastText
  },
  variantInfo: {
    backgroundColor: `${palette.debug.main} !important`,
    color: palette.debug.contrastText
  },
  variantWarning: {
    backgroundColor: `${palette.warning.main} !important`,
    color: palette.warning.contrastText
  }
}))

const NotistackProvider = ({ children }) => {
  const classes = useStyles()

  return (
    <SnackbarProvider
      hideIconVariant
      classes={classes}
      anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
    >
      {children}
    </SnackbarProvider>
  )
}

NotistackProvider.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.node,
    PropTypes.arrayOf(PropTypes.node)
  ])
}

NotistackProvider.defaultProps = {
  children: undefined
}

export default NotistackProvider
<|endoftext|>


<commit_before>/**
 * Created by itayk on 7/26/15.
 */
( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'pipBtn', mw.KBaseComponent.extend({

			defaultConfig: {
				'parent': 'controlsContainer',
				'accessibleControls': false,
				'order': 53,
				'showTooltip': true,
				'align': "right",
				'smartContainer': 'morePlugins',
				'title': gM( 'mwe-embedplayer-pip' ),
				"displayImportance": "medium"
			},

			isDisabled: true,
			pipTitle: gM( 'mwe-embedplayer-pip' ),
			setup: function() {
				var _this = this;
				this.bind("playerReady",function(){
					_this.onDisable();
				});
				this.bind("firstPlay",function(){
					 _this.onEnable();
				});
			},
			isSafeEnviornment: function(){
				return mw.isIOS9() && mw.isIpad() && !mw.isIpad2() ;
			},
			getComponent: function() {
				var _this = this;
				if( !this.$el ) {
					this.$el  = $( '<button />' )
						.attr( 'title', this.pipTitle )
						.addClass( "btn icon-new-tab pull-right" + this.getCssClass() )
						.click( function() {
							if( mw.getConfig("EmbedPlayer.ForceNativeComponent") ) {
								_this.embedPlayer.togglePictureInPicture();
							} else {
								_this.embedPlayer.playerElement.webkitSetPresentationMode(_this.embedPlayer.playerElement.webkitPresentationMode === "picture-in-picture" ? "inline" : "picture-in-picture");
							}
						});

				}
				return this.$el;
			},

			getBtn: function(){
				return this.getComponent().find( '.btn' );
			}
		})
	);

} )( window.mw, window.jQuery );
<commit_msg>FEC-4308 #comment add smartContainerCloseEvent to pipBtn plugin<commit_after>/**
 * Created by itayk on 7/26/15.
 */
( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'pipBtn', mw.KBaseComponent.extend({

			defaultConfig: {
				'parent': 'controlsContainer',
				'accessibleControls': false,
				'order': 53,
				'showTooltip': true,
				'align': "right",
				'smartContainer': 'morePlugins',
				'smartContainerCloseEvent': 'pipEvent',
				'title': gM( 'mwe-embedplayer-pip' ),
				"displayImportance": "medium"
			},

			isDisabled: true,
			pipTitle: gM( 'mwe-embedplayer-pip' ),
			setup: function() {
				var _this = this;
				this.bind("playerReady",function(){
					_this.onDisable();
				});
				this.bind("firstPlay",function(){
					 _this.onEnable();
				});
			},
			isSafeEnviornment: function(){
				return mw.isIOS9() && mw.isIpad() && !mw.isIpad2() ;
			},
			getComponent: function() {
				var _this = this;
				if( !this.$el ) {
					this.$el  = $( '<button />' )
						.attr( 'title', this.pipTitle )
						.addClass( "btn icon-new-tab pull-right" + this.getCssClass() )
						.click( function() {
							if( mw.getConfig("EmbedPlayer.ForceNativeComponent") ) {
								_this.embedPlayer.togglePictureInPicture();
							} else {
								_this.embedPlayer.playerElement.webkitSetPresentationMode(_this.embedPlayer.playerElement.webkitPresentationMode === "picture-in-picture" ? "inline" : "picture-in-picture");
							}
							_this.embedPlayer.triggerHelper("pipEvent");
						});

				}
				return this.$el;
			},

			getBtn: function(){
				return this.getComponent().find( '.btn' );
			}
		})
	);

} )( window.mw, window.jQuery );
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: felix@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {
    var Transform = require('famous/core/Transform');
    var Transitionable = require('famous/transitions/Transitionable');
    var RenderNode = require('famous/core/RenderNode');
    var OptionsManager = require('famous/core/OptionsManager');

    /**
     * Allows you to link two renderables as front and back sides that can be
     *  'flipped' back and forth along a chosen axis. Rendering optimizations are
     *  automatically handled.
     *
     * @class Flipper
     * @constructor
     * @param {Options} [options] An object of options.
     * @param {Transition} [options.transition=true] The transition executed when flipping your Flipper instance.
     */
    function Flipper(options) {
        this.options = Object.create(Flipper.DEFAULT_OPTIONS);
        this._optionsManager = new OptionsManager(this.options);
        if (options) this.setOptions(options);

        this.state = new Transitionable(0);

        this.frontNode = new RenderNode();
        this.backNode = new RenderNode();

        this.flipped = false;
    }

    Flipper.DIRECTION_X = 0;
    Flipper.DIRECTION_Y = 1;

    var SEPERATION_LENGTH = 1;

    Flipper.DEFAULT_OPTIONS = {
        transition: true,
        direction: Flipper.DIRECTION_X
    };

    /**
     * Flips from the current side to the opposite one with the Flipper instance's default transition.
     *
     * @method flip
     * @param {Number} side Can be either one or zero (one represents the back, zero represents the front).
     *   Defaults to the default transition (true).
     * @param {function} [callback] Executes after transitioning to the toggled state.
     */
    Flipper.prototype.rotate = function rotate(angle, transition, callback) {
        if (angle === undefined) {
            angle = this.flipped ? this.state.get() - Math.PI : this.state.get() + Math.PI;
            this.flipped = !this.flipped;
        } else {
            this.flipped = false;
        }
        if (transition === undefined) transition = this.options.transition;
        this.state.halt();
        this.state.set(angle, transition, callback);
    };

    /**
     * Patches the Flipper instance's options with the passed-in ones.
     *
     * @method setOptions
     * @param {Options} options An object of configurable options for the Flipper instance.
     */
    Flipper.prototype.setOptions = function setOptions(options) {
        return this._optionsManager.setOptions(options);
    };

    /**
     * Adds the passed-in renderable to the view associated with the 'front' of the Flipper instance.
     *
     * @method setFront
     * @chainable
     * @param {Object} obj The renderable you want to add to the front.
     */
    Flipper.prototype.setFront = function setFront(obj) {
        return this.frontNode.set(obj);
    };

    /**
     * Adds the passed-in renderable to the view associated with the 'back' of the Flipper instance.
     *
     * @method setBack
     * @chainable
     * @param {Object} obj The renderable you want to add to the back.
     */
    Flipper.prototype.setBack = function setBack(obj) {
        return this.backNode.set(obj);
    };

    /**
     * Generate a render spec from the contents of this component.
     *
     * @private
     * @method render
     * @return {Number} Render spec for this component
     */
    Flipper.prototype.render = function render() {
        var angle = this.state.get();

        var frontTransform;
        var backTransform;

        if (this.options.direction === Flipper.DIRECTION_X) {
            frontTransform = Transform.rotateY(angle);
            backTransform = Transform.rotateY(angle + Math.PI);
        }
        else {
            frontTransform = Transform.rotateX(angle);
            backTransform = Transform.rotateX(angle + Math.PI);
        }

        return [
            {
                transform: frontTransform,
                target: this.frontNode.render()
            },
            {
                transform: Transform.moveThen([0, 0, SEPERATION_LENGTH], backTransform),
                target: this.backNode.render()
            }
        ];
    };

    module.exports = Flipper;
});
<commit_msg>Update Flipper to include flip method, code cleanup<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Owner: felix@famo.us
 * @license MPL 2.0
 * @copyright Famous Industries, Inc. 2014
 */

define(function(require, exports, module) {
    var Transform = require('famous/core/Transform');
    var Transitionable = require('famous/transitions/Transitionable');
    var RenderNode = require('famous/core/RenderNode');
    var OptionsManager = require('famous/core/OptionsManager');

    /**
     * Allows you to link two renderables as front and back sides that can be
     *  'flipped' back and forth along a chosen axis. Rendering optimizations are
     *  automatically handled.
     *
     * @class Flipper
     * @constructor
     * @param {Options} [options] An object of options.
     * @param {Transition} [options.transition=true] The transition executed when flipping your Flipper instance.
     */
    function Flipper(options) {
        this.options = Object.create(Flipper.DEFAULT_OPTIONS);
        this._optionsManager = new OptionsManager(this.options);
        if (options) this.setOptions(options);

        this.angle = new Transitionable(0);

        this.frontNode = undefined;
        this.backNode = undefined;

        this.flipped = false;
    }

    Flipper.DIRECTION_X = 0;
    Flipper.DIRECTION_Y = 1;

    var SEPERATION_LENGTH = 1;

    Flipper.DEFAULT_OPTIONS = {
        transition: true,
        direction: Flipper.DIRECTION_X
    };

    /**
     * Toggles the rotation between the front and back renderables
     *
     * @method flip
     * @param {Object} [transition] Transition definition
     * @param {Function} [callback] Callback
     */
    Flipper.prototype.flip = function flip(transition, callback){
        var angle = this.flipped ? 0 : Math.PI;
        this.setAngle(angle, transition, callback);
        this.flipped = !this.flipped;
    };

    /**
     * Basic setter to the angle
     *
     * @method setAngle
     * @param {Number} angle
     * @param {Object} [transition] Transition definition
     * @param {Function} [callback] Callback
     */
    Flipper.prototype.setAngle = function setAngle(angle, transition, callback) {
        if (transition === undefined) transition = this.options.transition;
        if (this.angle.isActive()) this.angle.halt();
        this.angle.set(angle, transition, callback);
    };

    /**
     * Patches the Flipper instance's options with the passed-in ones.
     *
     * @method setOptions
     * @param {Options} options An object of configurable options for the Flipper instance.
     */
    Flipper.prototype.setOptions = function setOptions(options) {
        return this._optionsManager.setOptions(options);
    };

    /**
     * Adds the passed-in renderable to the view associated with the 'front' of the Flipper instance.
     *
     * @method setFront
     * @chainable
     * @param {Object} node The renderable you want to add to the front.
     */
    Flipper.prototype.setFront = function setFront(node) {
        this.frontNode = node;
    };

    /**
     * Adds the passed-in renderable to the view associated with the 'back' of the Flipper instance.
     *
     * @method setBack
     * @chainable
     * @param {Object} node The renderable you want to add to the back.
     */
    Flipper.prototype.setBack = function setBack(node) {
        this.backNode = node;
    };

    /**
     * Generate a render spec from the contents of this component.
     *
     * @private
     * @method render
     * @return {Number} Render spec for this component
     */
    Flipper.prototype.render = function render() {
        var angle = this.angle.get();

        var frontTransform;
        var backTransform;

        if (this.options.direction === Flipper.DIRECTION_X) {
            frontTransform = Transform.rotateY(angle);
            backTransform = Transform.rotateY(angle + Math.PI);
        }
        else {
            frontTransform = Transform.rotateX(angle);
            backTransform = Transform.rotateX(angle + Math.PI);
        }

        var result = [];
        if (this.frontNode){
            result.push({
                transform: frontTransform,
                target: this.frontNode.render()
            });
        }

        if (this.backNode){
            result.push({
                transform: Transform.moveThen([0, 0, SEPERATION_LENGTH], backTransform),
                target: this.backNode.render()
            });
        }

        return result;
    };

    module.exports = Flipper;
});
<|endoftext|>


<commit_before>import {Button} from 'widget/button'
import {msg} from 'translate'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'

const {Provider, Consumer} = React.createContext()

export class Pageable extends React.Component {
    state = {
        itemCount: null,
        pageCount: null,
        pageNumber: 1
    }

    componentDidUpdate(prevProps) {
        if (!_.isEqual(prevProps, this.props)) {
            const {items, limit} = this.props
            const itemCount = items.length
            const pageCount = Math.ceil(itemCount / limit)
            this.setState(prevState => ({
                ...prevState,
                pageCount,
                itemCount,
                pageNumber: 1
            }))
        }
    }

    firstPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: 1
        }))
    }

    lastPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: prevState.pageCount
        }))
    }

    prevPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: Math.max(prevState.pageNumber - 1, 1)
        }))
    }

    nextPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: Math.min(prevState.pageNumber + 1, prevState.pageCount)
        }))
    }

    getPageItems() {
        const {items, limit} = this.props
        const {pageNumber} = this.state
        return items.slice((pageNumber - 1) * limit, pageNumber * limit)
    }

    render() {
        return (
            <Provider value={{
                itemCount: this.state.itemCount,
                pageCount: this.state.pageCount,
                pageNumber: this.state.pageNumber,
                isFirstPage: this.state.pageNumber === 1,
                isLastPage: this.state.pageNumber === this.state.pageCount,
                pageItems: this.getPageItems(),
                firstPage: () => this.firstPage(),
                lastPage: () => this.lastPage(),
                prevPage: () => this.prevPage(),
                nextPage: () => this.nextPage()
            }}>
                {this.props.children}
            </Provider>
        )
    }
}

Pageable.propTypes = {
    children: PropTypes.array.isRequired,
    items: PropTypes.array.isRequired,
    limit: PropTypes.number.isRequired
}

export const PageData = (props) =>
    <Consumer>
        {pageable =>
            <React.Fragment>
                {pageable.pageItems.map(item => props.children(item))}
            </React.Fragment>
        }
    </Consumer>

PageData.propTypes = {
    children: PropTypes.func.isRequired
}

export const PageControls = (props) => {
    const renderDefaultControls = (pageable) =>

            <Button icon='fast-backward' onClick={() => pageable.firstPage()} disabled={pageable.isFirstPage}/>
            <Button icon='backward' onClick={() => pageable.prevPage()} disabled={pageable.isFirstPage}/>
            <Button icon='forward' onClick={() => pageable.nextPage()} disabled={pageable.isLastPage}/>
            <Button icon='fast-forward' onClick={() => pageable.lastPage()} disabled={pageable.isLastPage}/>

    const renderCustomControls = ({isFirstPage, isLastPage, firstPage, lastPage, prevPage, nextPage}) =>
        <React.Fragment>
            {props.children({isFirstPage, isLastPage, firstPage, lastPage, prevPage, nextPage})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomControls(pageable)
                : renderDefaultControls(pageable)
            }
        </Consumer>
    )
}

PageControls.propTypes = {
    children: PropTypes.func
}

export const PageInfo = (props) => {
    const renderDefaultInfo = ({pageNumber, pageCount, itemCount}) =>

            {msg('pagination.info', {pageNumber, pageCount, itemCount})}

    const renderCustomInfo = ({pageNumber, pageCount, itemCount}) =>
        <React.Fragment>
            {props.children({pageNumber, pageCount, itemCount})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomInfo(pageable)
                : renderDefaultInfo(pageable)
            }
        </Consumer>
    )
}

PageInfo.propTypes = {
    children: PropTypes.func
}
<commit_msg>Cleanup.<commit_after>import {Button} from 'widget/button'
import {msg} from 'translate'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'

const {Provider, Consumer} = React.createContext()

export class Pageable extends React.Component {
    state = {
        itemCount: null,
        pageCount: null,
        pageNumber: 1
    }

    componentDidUpdate(prevProps) {
        if (!_.isEqual(prevProps, this.props)) {
            const {items, limit} = this.props
            const itemCount = items.length
            const pageCount = Math.ceil(itemCount / limit)
            this.setState(prevState => ({
                ...prevState,
                pageCount,
                itemCount,
                pageNumber: 1
            }))
        }
    }

    firstPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: 1
        }))
    }

    lastPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: prevState.pageCount
        }))
    }

    prevPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: Math.max(prevState.pageNumber - 1, 1)
        }))
    }

    nextPage() {
        this.setState(prevState => ({
            ...prevState,
            pageNumber: Math.min(prevState.pageNumber + 1, prevState.pageCount)
        }))
    }

    getPageItems() {
        const {items, limit} = this.props
        const {pageNumber} = this.state
        return items.slice((pageNumber - 1) * limit, pageNumber * limit)
    }

    render() {
        return (
            <Provider value={{
                itemCount: this.state.itemCount,
                pageCount: this.state.pageCount,
                pageNumber: this.state.pageNumber,
                isFirstPage: this.state.pageNumber === 1,
                isLastPage: this.state.pageNumber === this.state.pageCount,
                pageItems: this.getPageItems(),
                firstPage: () => this.firstPage(),
                lastPage: () => this.lastPage(),
                prevPage: () => this.prevPage(),
                nextPage: () => this.nextPage()
            }}>
                {this.props.children}
            </Provider>
        )
    }
}

Pageable.propTypes = {
    children: PropTypes.array.isRequired,
    items: PropTypes.array.isRequired,
    limit: PropTypes.number.isRequired
}

export const PageData = (props) =>
    <Consumer>
        {pageable =>
            <React.Fragment>
                {pageable.pageItems.map(item => props.children(item))}
            </React.Fragment>
        }
    </Consumer>

PageData.propTypes = {
    children: PropTypes.func.isRequired
}

export const PageControls = (props) => {
    const renderDefaultControls = (pageable) =>

            <Button icon='fast-backward'
                onClick={() => pageable.firstPage()}
                disabled={pageable.isFirstPage}/>
            <Button icon='backward'
                onClick={() => pageable.prevPage()}
                disabled={pageable.isFirstPage}/>
            <Button icon='forward'
                onClick={() => pageable.nextPage()}
                disabled={pageable.isLastPage}/>
            <Button icon='fast-forward'
                onClick={() => pageable.lastPage()}
                disabled={pageable.isLastPage}/>

    const renderCustomControls = ({isFirstPage, isLastPage, firstPage, lastPage, prevPage, nextPage}) =>
        <React.Fragment>
            {props.children({isFirstPage, isLastPage, firstPage, lastPage, prevPage, nextPage})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomControls(pageable)
                : renderDefaultControls(pageable)
            }
        </Consumer>
    )
}

PageControls.propTypes = {
    children: PropTypes.func
}

export const PageInfo = (props) => {
    const renderDefaultInfo = ({pageNumber, pageCount, itemCount}) =>

            {msg('pagination.info', {pageNumber, pageCount, itemCount})}

    const renderCustomInfo = ({pageNumber, pageCount, itemCount}) =>
        <React.Fragment>
            {props.children({pageNumber, pageCount, itemCount})}
        </React.Fragment>

    return (
        <Consumer>
            {pageable => props.children
                ? renderCustomInfo(pageable)
                : renderDefaultInfo(pageable)
            }
        </Consumer>
    )
}

PageInfo.propTypes = {
    children: PropTypes.func
}
<|endoftext|>