<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe('two');
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>completed 'should understand array length'<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe('two');
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe(FILL_ME_IN); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(FILL_ME_IN);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(FILL_ME_IN);
    expect(multiTypeArray[2]).toBe(FILL_ME_IN);
    expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
    expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
    expect(multiTypeArray[4]["value2"]).toBe(FILL_ME_IN);
    expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>update About Arrays<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe("object"); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>define.class("$server/composition",function(require, $ui$, screen, view) {
	this.render = function() {
		return [screen(
			view({
				flex:1,
				init:function(){
					console.log('here')
				},
				bgcolor:'red',
				hardrect:{
					color:function(){
						return mix('brown',pal.pal1(mesh.depth/14),mesh.depth/12)*sin(mesh.pos.y*PI)
					},
					mesh:define.struct({
						pos:vec2,
						path:float,
						depth:float
					}).array(),
					position:function(){

						// lets walk
						var path = mesh.path
						var pos = vec2(0,0)
						var scale = vec2(1,1)
						var dir = vec2(0,-1)
						var depth = int(mesh.depth)
						for(var i = 0; i < 32; i++){
							if(i >= depth) break
							var right = mod(path, 2.)
						    if(right>0.){
						    	dir = math.rotate2d(dir, 30.*math.DEG*sin(view.time))
						    }
						    else{
						    	dir = math.rotate2d(dir, -30.*math.DEG*sin(1.2*view.time+0.1*mesh.depth))
						    }
						    pos += (dir * scale)*1.8
						    scale = scale * vec2(0.9,0.9)
							path = floor(path / 2.)
						}
						// alright we found a pos and dir

						var p = (math.rotate2d(mesh.pos*scale, atan(dir.y,dir.x)) + pos)  * vec2(30,30) + vec2(300,600)

						return vec4(p, 0, 1) * view.totalmatrix * view.viewmatrix
					},
					update:function(){
						var mesh = this.mesh = this.mesh.struct.array()

						// first triangle
						function recur(path, depth){

							mesh.pushQuad(
								-1,-1, path, depth,
								1,-1, path, depth,
								-1,1, path, depth,
								1,1, path, depth
							)
							if(depth>14)return

							recur(path, depth+1)
							recur(path + Math.pow(2, depth), depth+1)
						}
						recur(0,0)

						10101101

					}
				}
			})
		)]
	}
})
<commit_msg>tree art better<commit_after>define.class("$server/composition",function(require, $ui$, screen, view) {
	this.render = function() {
		return [screen(
			view({
				flex:1,
				init:function(){
					console.log('here')
				},
				bgcolor:'red',
				hardrect:{
					color:function(){
						return mix('brown',pal.pal1(mesh.depth/14+0.1*view.time),mesh.depth/12)*sin(mesh.pos.y*PI)*pow(sin(mesh.pos.x*PI),0.2)
					},
					mesh:define.struct({
						pos:vec2,
						path:float,
						depth:float
					}).array(),
					position:function(){

						// lets walk
						var path = mesh.path
						var pos = vec2(0,0)
						var scale = vec2(1,1)
						var dir = vec2(0,-1)
						var depth = int(mesh.depth)
						for(var i = 0; i < 32; i++){
							if(i >= depth) break
							var right = mod(path, 2.)
						    if(right>0.){
						    	dir = math.rotate2d(dir, 30.*math.DEG*sin(view.time))
						    }
						    else{
						    	dir = math.rotate2d(dir, -30.*math.DEG*sin(1.2*view.time+0.1*mesh.depth))
						    }
						    pos += (dir * scale)*1.8
						    scale = scale * vec2(0.9,0.9)
							path = floor(path / 2.)
						}
						// alright we found a pos and dir

						var p = (math.rotate2d(mesh.pos*scale, atan(dir.y,dir.x)) + pos)  * vec2(30,30) + vec2(300,600)

						return vec4(p, 0, 1) * view.totalmatrix * view.viewmatrix
					},
					update:function(){
						var mesh = this.mesh = this.mesh.struct.array()

						// first triangle
						function recur(path, depth){

							mesh.pushQuad(
								-1,-1, path, depth,
								1,-1, path, depth,
								-1,1, path, depth,
								1,1, path, depth
							)
							if(depth>13)return

							recur(path, depth+1)
							recur(path + Math.pow(2, depth), depth+1)
						}
						recur(0,0)

						10101101

					}
				}
			})
		)]
	}
})
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe("object"); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1,2,3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Solved third AboutArrays koan - array length<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe("object"); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1,2,3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>import { ProjectDashboard } from './index';
import * as ProjectHelpers from '../../utils/ProjectHelpers';

describe('ProjectDashboard', () => {
  describe('scrollThroughProjects', () => {
    let projectDashboard;
    let getSisterProject;
    let setState;
    let setActiveProject;

    before(() => {
      projectDashboard = new ProjectDashboard();
      projectDashboard.state = { currentlyChanging: false };

      projectDashboard.props = {
        projects: new List([]),
        project: new Map(),
        setActiveProject: () => {
          return;
        }
      };
    });
  });
});
<commit_msg>added tests and linted<commit_after>import { ProjectDashboard } from './index';
import * as ProjectHelpers from '../../utils/ProjectHelpers';

describe('ProjectDashboard', () => {
  describe('swipe', () => {
    let projectDashboard;
    let getSisterProject;
    let setActiveProject;
    let direction;

    before(() => {
      projectDashboard = new ProjectDashboard();
      projectDashboard.props = {
        projects: new List([]),
        project: new Map(),
        setActiveProject: () => {
          return;
        }
      };
      direction = 1;
    });

    beforeEach(() => {
      getSisterProject = spy(ProjectHelpers, 'getSisterProject');
      setActiveProject = spy(projectDashboard.props, 'setActiveProject');
      projectDashboard.swipe(direction);
    });

    it('calls getSisterProject', () => {
      expect(getSisterProject.calledWith(direction)).to.be.true;
    });

    it('calls setActiveProject', () => {
      expect(setActiveProject.calledOnce).to.be.true;
    });

    afterEach(() => {
      getSisterProject.restore();
      setActiveProject.restore();
    });
  });
});
<|endoftext|>


<commit_before>import Polymer from '../../polymer';
import {
  moreInfoActions,
  serviceActions,
} from '../../util/home-assistant-js-instance';
import domainIcon from '../../util/domain-icon';
import canToggle from '../../util/can-toggle';

require('../../components/ha-label-badge');

export default new Polymer({
  is: 'ha-state-label-badge',

  properties: {
    state: {
      type: Object,
      observer: 'stateChanged',
    },
  },

  listeners: {
    'click': 'badgeTap',
  },

  badgeTap(ev) {
    ev.stopPropagation();
    if (!canToggle(this.state.entityId)) {
      this.async(() => moreInfoActions.selectEntity(this.state.entityId), 1);
      return;
    }
    if (this.state.domain === 'scene') {
      serviceActions.callTurnOn(this.state.entityId);
    } else if (this.state.state === 'off') {
      serviceActions.callTurnOn(this.state.entityId);
    } else {
      serviceActions.callTurnOff(this.state.entityId);
    }
  },

  computeClasses(state) {
    switch (state.domain) {
    case 'scene':
      return 'green';
    case 'script':
      return state.state === 'on' ? 'blue' : 'grey';
    case 'updater':
      return 'blue';
    default:
      return '';
    }
  },

  computeValue(state) {
    switch (state.domain) {
    case 'device_tracker':
    case 'updater':
    case 'sun':
    case 'scene':
    case 'script':
    case 'alarm_control_panel':
      return undefined;
    case 'sensor':
      return state.state;
    default:
      return state.state;
    }
  },

  computeIcon(state) {
    switch (state.domain) {
    case 'alarm_control_panel':
      if (state.state === 'pending') {
        return 'mdi:clock-fast';
      } else if (state.state === 'armed_away') {
        return 'mdi:nature';
      } else if (state.state === 'armed_home') {
        return 'mdi:home-variant';
      }
      // state == 'disarmed'
      return 'mdi:lock-open';
    case 'device_tracker':
    case 'scene':
    case 'script':
      return domainIcon(state.domain, state.state);
    case 'updater':
      return domainIcon(state.domain);
    case 'sun':
      return state.state === 'above_horizon' ?
        domainIcon(state.domain) : 'mdi:brightness-3';
    default:
      return undefined;
    }
  },

  computeImage(state) {
    return state.attributes.entity_picture;
  },

  computeLabel(state) {
    switch (state.domain) {
    case 'scene':
    case 'script':
      return state.domain;
    case 'device_tracker':
      return state.state === 'not_home' ? 'Away' : state.state;
    case 'alarm_control_panel':
      if (state.state === 'pending') {
        return 'pend';
      } else if (state.state === 'armed_away' || state.state === 'armed_home') {
        return 'armed';
      }
      // state == 'disarmed'
      return 'disarm';
    default:
      return state.attributes.unit_of_measurement;
    }
  },

  computeDescription(state) {
    return state.entityDisplay;
  },

  stateChanged() {
    this.updateStyles();
  },
});
<commit_msg>Add binary sensor<commit_after>import Polymer from '../../polymer';
import {
  moreInfoActions,
  serviceActions,
} from '../../util/home-assistant-js-instance';
import domainIcon from '../../util/domain-icon';
import canToggle from '../../util/can-toggle';

require('../../components/ha-label-badge');

export default new Polymer({
  is: 'ha-state-label-badge',

  properties: {
    state: {
      type: Object,
      observer: 'stateChanged',
    },
  },

  listeners: {
    'click': 'badgeTap',
  },

  badgeTap(ev) {
    ev.stopPropagation();
    if (!canToggle(this.state.entityId)) {
      this.async(() => moreInfoActions.selectEntity(this.state.entityId), 1);
      return;
    }
    if (this.state.domain === 'scene') {
      serviceActions.callTurnOn(this.state.entityId);
    } else if (this.state.state === 'off') {
      serviceActions.callTurnOn(this.state.entityId);
    } else {
      serviceActions.callTurnOff(this.state.entityId);
    }
  },

  computeClasses(state) {
    switch (state.domain) {
    case 'binary_sensor':
      return state.state === 'on' ? 'green' : 'red';
    case 'scene':
      return 'green';
    case 'script':
      return state.state === 'on' ? 'blue' : 'grey';
    case 'updater':
      return 'blue';
    default:
      return '';
    }
  },

  computeValue(state) {
    switch (state.domain) {
    case 'binary_sensor':
    case 'device_tracker':
    case 'updater':
    case 'sun':
    case 'scene':
    case 'script':
    case 'alarm_control_panel':
      return undefined;
    case 'sensor':
      return state.state;
    default:
      return state.state;
    }
  },

  computeIcon(state) {
    switch (state.domain) {
    case 'alarm_control_panel':
      if (state.state === 'pending') {
        return 'mdi:clock-fast';
      } else if (state.state === 'armed_away') {
        return 'mdi:nature';
      } else if (state.state === 'armed_home') {
        return 'mdi:home-variant';
      }
      // state == 'disarmed'
      return 'mdi:lock-open';
    case 'binary_sensor':
      if (state.state === 'on') {
        return 'mdi:radiobox-marked';
      }
      // state == 'off'
      return 'mdi:radiobox-blank';
    case 'device_tracker':
    case 'scene':
    case 'script':
      return domainIcon(state.domain, state.state);
    case 'updater':
      return domainIcon(state.domain);
    case 'sun':
      return state.state === 'above_horizon' ?
        domainIcon(state.domain) : 'mdi:brightness-3';
    default:
      return undefined;
    }
  },

  computeImage(state) {
    return state.attributes.entity_picture;
  },

  computeLabel(state) {
    switch (state.domain) {
    case 'scene':
    case 'script':
      return state.domain;
    case 'device_tracker':
      return state.state === 'not_home' ? 'Away' : state.state;
    case 'alarm_control_panel':
      if (state.state === 'pending') {
        return 'pend';
      } else if (state.state === 'armed_away' || state.state === 'armed_home') {
        return 'armed';
      }
      // state == 'disarmed'
      return 'disarm';
    default:
      return state.attributes.unit_of_measurement;
    }
  },

  computeDescription(state) {
    return state.entityDisplay;
  },

  stateChanged() {
    this.updateStyles();
  },
});
<|endoftext|>


<commit_before>import $ from 'dom7';
import Utils from '../../utils/utils';
import Framework7Class from '../../utils/class';

class ListIndex extends Framework7Class {
  constructor(app, params = {}) {
    super(params, [app]);
    const index = this;

    const defaults = {
      el: null, // where to render indexes
      listEl: null, // list el to generate indexes
      indexes: 'auto', // or array of indexes
      iosItemHeight: 14,
      mdItemHeight: 14,
      scrollList: true,
      label: false,
      // eslint-disable-next-line
      renderItem(itemContent, itemIndex) {
        return `

${itemContent}

        `.trim();
      },
      renderSkipPlaceholder() {
        return '

';
      },
      on: {},
    };

    // Extend defaults with modules params
    index.useModulesParams(defaults);

    index.params = Utils.extend(defaults, params);

    let $el;
    let $listEl;
    let $pageContentEl;
    let $ul;

    if (index.params.el) {
      $el = $(index.params.el);
    } else {
      return index;
    }

    $ul = $el.find('ul');
    if ($ul.length === 0) {
      $ul = $('

');
      $el.append($ul);
    }

    if (index.params.listEl) {
      $listEl = $(index.params.listEl);
    }

    if (index.params.indexes === 'auto' && !$listEl) {
      return index;
    }

    if ($listEl) {
      $pageContentEl = $listEl.parents('.page-content').eq(0);
    } else {
      $pageContentEl = $el.siblings('.page-content').eq(0);
      if ($pageContentEl.length === 0) {
        $pageContentEl = $el.parents('.page').eq(0).find('.page-content').eq(0);
      }
    }

    $el[0].f7ListIndex = index;

    Utils.extend(index, {
      app,
      $el,
      el: $el && $el[0],
      $ul,
      ul: $ul && $ul[0],
      $listEl,
      listEl: $listEl && $listEl[0],
      $pageContentEl,
      pageContentEl: $pageContentEl && $pageContentEl[0],
      indexes: params.indexes,
      height: 0,
      skipRate: 0,
    });

    // Install Modules
    index.useModules();

    // Attach events
    function handleResize() {
      const height = { index };
      index.calcSize();
      if (height !== index.height) {
        index.render();
      }
    }

    function handleClick(e) {
      const $clickedLi = $(e.target).closest('li');
      if (!$clickedLi.length) return;

      let itemIndex = $clickedLi.index();
      if (index.skipRate > 0) {
        const percentage = itemIndex / ($clickedLi.siblings('li').length - 1);
        itemIndex = Math.round((index.indexes.length - 1) * percentage);
      }
      const itemContent = index.indexes[itemIndex];

      index.$el.trigger('listindex:click', itemContent, itemIndex);
      index.emit('local::click listIndexClick', index, itemContent, itemIndex);
      index.$el.trigger('listindex:select', itemContent, itemIndex);
      index.emit('local::select listIndexSelect', index, itemContent, itemIndex);

      if (index.$listEl && index.params.scrollList) {
        index.scrollListToIndex(itemContent, itemIndex);
      }
    }

    const touchesStart = {};
    let isTouched;
    let isMoved;
    let topPoint;
    let bottomPoint;
    let $labelEl;
    let previousIndex = null;
    function handleTouchStart(e) {
      const $children = $ul.children();
      if (!$children.length) return;
      topPoint = $children[0].getBoundingClientRect().top;
      bottomPoint = $children[$children.length - 1].getBoundingClientRect().top + $children[0].offsetHeight;

      touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
      touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
      isTouched = true;
      isMoved = false;
      previousIndex = null;
    }
    function handleTouchMove(e) {
      if (!isTouched) return;
      if (!isMoved && index.params.label) {
        $labelEl = $('');
        $el.append($labelEl);
      }
      isMoved = true;
      const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
      e.preventDefault();

      let percentage = (pageY - topPoint) / (bottomPoint - topPoint);
      percentage = Math.min(Math.max(percentage, 0), 1);

      const itemIndex = Math.round((index.indexes.length - 1) * percentage);
      const itemContent = index.indexes[itemIndex];

      const ulHeight = bottomPoint - topPoint;
      const bubbleBottom = ((index.height - ulHeight) / 2) + ((1 - percentage) * ulHeight);

      if (itemIndex !== previousIndex) {
        if (index.params.label) {
          $labelEl.html(itemContent).transform(`translateY(-${bubbleBottom}px)`);
        }

        if (index.$listEl && index.params.scrollList) {
          index.scrollListToIndex(itemContent, itemIndex);
        }
      }

      previousIndex = itemIndex;

      index.$el.trigger('listindex:select', index);
      index.emit('local::select listIndexSelect', index, itemContent, itemIndex);
    }
    function handleTouchEnd() {
      if (!isTouched) return;
      isTouched = false;
      isMoved = false;
      if (index.params.label) {
        if ($labelEl) $labelEl.remove();
        $labelEl = undefined;
      }
    }
    const passiveListener = app.support.passiveListener ? { passive: true } : false;
    index.attachEvents = function attachEvents() {
      $el.parents('.tab').on('tab:show', handleResize);
      $el.parents('.page').on('page:reinit', handleResize);
      $el.parents('.panel').on('panel:open', handleResize);
      $el
        .parents('.sheet-modal, .actions-modal, .popup, .popover, .login-screen, .dialog, .toast')
        .on('modal:open', handleResize);
      app.on('resize', handleResize);

      $el.on('click', handleClick);
      $el.on(app.touchEvents.start, handleTouchStart, passiveListener);
      app.on('touchmove:active', handleTouchMove);
      app.on('touchend:passive', handleTouchEnd);
    };
    index.detachEvents = function attachEvents() {
      $el.parents('.tab').off('tab:show', handleResize);
      $el.parents('.page').off('page:reinit', handleResize);
      $el.parents('.panel').off('panel:open', handleResize);
      $el
        .parents('.sheet-modal, .actions-modal, .popup, .popover, .login-screen, .dialog, .toast')
        .off('modal:open', handleResize);
      app.off('resize', handleResize);

      $el.off('click', handleClick);
      $el.off(app.touchEvents.start, handleTouchStart, passiveListener);
      app.off('touchmove:active', handleTouchMove);
      app.off('touchend:passive', handleTouchEnd);
    };
    // Init
    index.init();

    return index;
  }
  // eslint-disable-next-line
  scrollListToIndex(itemContent, itemIndex) {
    const index = this;
    const { $listEl, $pageContentEl } = index;
    if (!$listEl || !$pageContentEl || $pageContentEl.length === 0) return index;

    let $scrollToEl;
    $listEl.find('.list-group-title, .item-divider').each((elIndex, el) => {
      if ($scrollToEl) return;
      const $el = $(el);
      if ($el.text() === itemContent) {
        $scrollToEl = $el;
      }
    });
    if (!$scrollToEl || $scrollToEl.length === 0) return index;

    const parentTop = $scrollToEl.parent().offset().top;
    const paddingTop = parseInt($pageContentEl.css('padding-top'), 10);

    if (parentTop <= paddingTop) {
      $pageContentEl.scrollTop(($scrollToEl.parent().offset().top + $pageContentEl[0].scrollTop) - parseInt($pageContentEl.css('padding-top'), 10));
    } else {
      $pageContentEl.scrollTop(($scrollToEl.offset().top + $pageContentEl[0].scrollTop) - parseInt($pageContentEl.css('padding-top'), 10));
    }
    return index;
  }
  renderSkipPlaceholder() {
    const index = this;
    return index.params.renderSkipPlaceholder.call(index);
  }
  renderItem(itemContent, itemIndex) {
    const index = this;
    return index.params.renderItem.call(index, itemContent, itemIndex);
  }
  render() {
    const index = this;
    const { $ul, indexes, skipRate } = index;
    let wasSkipped;

    const html = indexes.map((itemContent, itemIndex) => {
      if (itemIndex % skipRate !== 0 && skipRate > 0) {
        wasSkipped = true;
        return '';
      }
      let itemHtml = index.renderItem(itemContent, itemIndex);
      if (wasSkipped) {
        itemHtml = index.renderSkipPlaceholder() + itemHtml;
      }
      wasSkipped = false;
      return itemHtml;
    }).join('');

    $ul.html(html);

    return index;
  }
  calcSize() {
    const index = this;
    const { app, params, el, indexes } = index;
    const height = el.offsetHeight;
    const itemHeight = app.theme === 'ios' ? params.iosItemHeight : params.mdItemHeight;
    const maxItems = Math.floor(height / itemHeight);
    const items = indexes.length;
    let skipRate = 0;
    if (items > maxItems) {
      skipRate = Math.ceil(((items * 2) - 1) / maxItems);
    }

    index.height = height;
    index.skipRate = skipRate;

    return index;
  }
  calcIndexes() {
    const index = this;
    if (index.params.indexes === 'auto') {
      index.indexes = [];

      index.$listEl.find('.list-group-title, .item-divider').each((elIndex, el) => {
        const elContent = $(el).text();
        if (index.indexes.indexOf(elContent) < 0) {
          index.indexes.push(elContent);
        }
      });
    } else {
      index.indexes = index.params.indexes;
    }
    return index;
  }
  update() {
    const index = this;
    index.calcIndexes();
    index.calcSize();
    index.render();

    return index;
  }
  init() {
    const index = this;
    index.calcIndexes();
    index.calcSize();
    index.render();
    index.attachEvents();
  }
  destroy() {
    let index = this;
    index.$el.trigger('listindex:beforedestroy', index);
    index.emit('local::beforeDestroy listIndexBeforeDestroy', index);
    index.detachEvents();
    index.$el[0].f7ListIndex = null;
    delete index.$el[0].f7ListIndex;
    Utils.deleteProps(index);
    index = null;
  }
}

export default ListIndex;
<commit_msg>Update list-index-class.js<commit_after>import $ from 'dom7';
import Utils from '../../utils/utils';
import Framework7Class from '../../utils/class';

class ListIndex extends Framework7Class {
  constructor(app, params = {}) {
    super(params, [app]);
    const index = this;

    const defaults = {
      el: null, // where to render indexes
      listEl: null, // list el to generate indexes
      indexes: 'auto', // or array of indexes
      iosItemHeight: 14,
      mdItemHeight: 14,
      scrollList: true,
      label: false,
      // eslint-disable-next-line
      renderItem(itemContent, itemIndex) {
        return `

${itemContent}

        `.trim();
      },
      renderSkipPlaceholder() {
        return '

';
      },
      on: {},
    };

    // Extend defaults with modules params
    index.useModulesParams(defaults);

    index.params = Utils.extend(defaults, params);

    let $el;
    let $listEl;
    let $pageContentEl;
    let $ul;

    if (index.params.el) {
      $el = $(index.params.el);
    } else {
      return index;
    }

    $ul = $el.find('ul');
    if ($ul.length === 0) {
      $ul = $('

');
      $el.append($ul);
    }

    if (index.params.listEl) {
      $listEl = $(index.params.listEl);
    }

    if (index.params.indexes === 'auto' && !$listEl) {
      return index;
    }

    if ($listEl) {
      $pageContentEl = $listEl.parents('.page-content').eq(0);
    } else {
      $pageContentEl = $el.siblings('.page-content').eq(0);
      if ($pageContentEl.length === 0) {
        $pageContentEl = $el.parents('.page').eq(0).find('.page-content').eq(0);
      }
    }

    $el[0].f7ListIndex = index;

    Utils.extend(index, {
      app,
      $el,
      el: $el && $el[0],
      $ul,
      ul: $ul && $ul[0],
      $listEl,
      listEl: $listEl && $listEl[0],
      $pageContentEl,
      pageContentEl: $pageContentEl && $pageContentEl[0],
      indexes: params.indexes,
      height: 0,
      skipRate: 0,
    });

    // Install Modules
    index.useModules();

    // Attach events
    function handleResize() {
      const height = { index };
      index.calcSize();
      if (height !== index.height) {
        index.render();
      }
    }

    function handleClick(e) {
      const $clickedLi = $(e.target).closest('li');
      if (!$clickedLi.length) return;

      let itemIndex = $clickedLi.index();
      if (index.skipRate > 0) {
        const percentage = itemIndex / ($clickedLi.siblings('li').length - 1);
        itemIndex = Math.round((index.indexes.length - 1) * percentage);
      }
      const itemContent = index.indexes[itemIndex];

      index.$el.trigger('listindex:click', itemContent, itemIndex);
      index.emit('local::click listIndexClick', index, itemContent, itemIndex);
      index.$el.trigger('listindex:select', itemContent, itemIndex);
      index.emit('local::select listIndexSelect', index, itemContent, itemIndex);

      if (index.$listEl && index.params.scrollList) {
        index.scrollListToIndex(itemContent, itemIndex);
      }
    }

    const touchesStart = {};
    let isTouched;
    let isMoved;
    let topPoint;
    let bottomPoint;
    let $labelEl;
    let previousIndex = null;
    function handleTouchStart(e) {
      const $children = $ul.children();
      if (!$children.length) return;
      topPoint = $children[0].getBoundingClientRect().top;
      bottomPoint = $children[$children.length - 1].getBoundingClientRect().top + $children[0].offsetHeight;

      touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
      touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
      isTouched = true;
      isMoved = false;
      previousIndex = null;
    }
    function handleTouchMove(e) {
      if (!isTouched) return;
      if (!isMoved && index.params.label) {
        $labelEl = $('');
        $el.append($labelEl);
      }
      isMoved = true;
      const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
      e.preventDefault();

      let percentage = (pageY - topPoint) / (bottomPoint - topPoint);
      percentage = Math.min(Math.max(percentage, 0), 1);

      const itemIndex = Math.round((index.indexes.length - 1) * percentage);
      const itemContent = index.indexes[itemIndex];

      const ulHeight = bottomPoint - topPoint;
      const bubbleBottom = ((index.height - ulHeight) / 2) + ((1 - percentage) * ulHeight);

      if (itemIndex !== previousIndex) {
        if (index.params.label) {
          $labelEl.html(itemContent).transform(`translateY(-${bubbleBottom}px)`);
        }

        if (index.$listEl && index.params.scrollList) {
          index.scrollListToIndex(itemContent, itemIndex);
        }
      }

      previousIndex = itemIndex;

      index.$el.trigger('listindex:select', index);
      index.emit('local::select listIndexSelect', index, itemContent, itemIndex);
    }
    function handleTouchEnd() {
      if (!isTouched) return;
      isTouched = false;
      isMoved = false;
      if (index.params.label) {
        if ($labelEl) $labelEl.remove();
        $labelEl = undefined;
      }
    }
    const passiveListener = app.support.passiveListener ? { passive: true } : false;
    index.attachEvents = function attachEvents() {
      $el.parents('.tab').on('tab:show', handleResize);
      $el.parents('.page').on('page:reinit', handleResize);
      $el.parents('.panel').on('panel:open', handleResize);
      $el
        .parents('.sheet-modal, .actions-modal, .popup, .popover, .login-screen, .dialog, .toast')
        .on('modal:open', handleResize);
      app.on('resize', handleResize);

      $el.on('click', handleClick);
      $el.on(app.touchEvents.start, handleTouchStart, passiveListener);
      app.on('touchmove:active', handleTouchMove);
      app.on('touchend:passive', handleTouchEnd);
    };
    index.detachEvents = function attachEvents() {
      $el.parents('.tab').off('tab:show', handleResize);
      $el.parents('.page').off('page:reinit', handleResize);
      $el.parents('.panel').off('panel:open', handleResize);
      $el
        .parents('.sheet-modal, .actions-modal, .popup, .popover, .login-screen, .dialog, .toast')
        .off('modal:open', handleResize);
      app.off('resize', handleResize);

      $el.off('click', handleClick);
      $el.off(app.touchEvents.start, handleTouchStart, passiveListener);
      app.off('touchmove:active', handleTouchMove);
      app.off('touchend:passive', handleTouchEnd);
    };
    // Init
    index.init();

    return index;
  }
  // eslint-disable-next-line
  scrollListToIndex(itemContent, itemIndex) {
    const index = this;
    const { $listEl, $pageContentEl } = index;
    if (!$listEl || !$pageContentEl || $pageContentEl.length === 0) return index;

    let $scrollToEl;
    $listEl.find('.list-group-title, .item-divider').each((elIndex, el) => {
      if ($scrollToEl) return;
      const $el = $(el);
      if ($el.text() === itemContent) {
        $scrollToEl = $el;
      }
    });
    if (!$scrollToEl || $scrollToEl.length === 0) return index;

    const parentTop = $scrollToEl.parent().offset().top;
    const paddingTop = parseInt($pageContentEl.css('padding-top'), 10);
    const scrollTop = $pageContentEl[0].scrollTop;
    const scrollToElTop = $scrollToEl.offset().top;

    if (parentTop <= paddingTop) {
      $pageContentEl.scrollTop((parentTop + scrollTop) - paddingTop);
    } else {
      $pageContentEl.scrollTop((scrollToElTop + scrollTop) - paddingTop);
    }
    return index;
  }
  renderSkipPlaceholder() {
    const index = this;
    return index.params.renderSkipPlaceholder.call(index);
  }
  renderItem(itemContent, itemIndex) {
    const index = this;
    return index.params.renderItem.call(index, itemContent, itemIndex);
  }
  render() {
    const index = this;
    const { $ul, indexes, skipRate } = index;
    let wasSkipped;

    const html = indexes.map((itemContent, itemIndex) => {
      if (itemIndex % skipRate !== 0 && skipRate > 0) {
        wasSkipped = true;
        return '';
      }
      let itemHtml = index.renderItem(itemContent, itemIndex);
      if (wasSkipped) {
        itemHtml = index.renderSkipPlaceholder() + itemHtml;
      }
      wasSkipped = false;
      return itemHtml;
    }).join('');

    $ul.html(html);

    return index;
  }
  calcSize() {
    const index = this;
    const { app, params, el, indexes } = index;
    const height = el.offsetHeight;
    const itemHeight = app.theme === 'ios' ? params.iosItemHeight : params.mdItemHeight;
    const maxItems = Math.floor(height / itemHeight);
    const items = indexes.length;
    let skipRate = 0;
    if (items > maxItems) {
      skipRate = Math.ceil(((items * 2) - 1) / maxItems);
    }

    index.height = height;
    index.skipRate = skipRate;

    return index;
  }
  calcIndexes() {
    const index = this;
    if (index.params.indexes === 'auto') {
      index.indexes = [];

      index.$listEl.find('.list-group-title, .item-divider').each((elIndex, el) => {
        const elContent = $(el).text();
        if (index.indexes.indexOf(elContent) < 0) {
          index.indexes.push(elContent);
        }
      });
    } else {
      index.indexes = index.params.indexes;
    }
    return index;
  }
  update() {
    const index = this;
    index.calcIndexes();
    index.calcSize();
    index.render();

    return index;
  }
  init() {
    const index = this;
    index.calcIndexes();
    index.calcSize();
    index.render();
    index.attachEvents();
  }
  destroy() {
    let index = this;
    index.$el.trigger('listindex:beforedestroy', index);
    index.emit('local::beforeDestroy listIndexBeforeDestroy', index);
    index.detachEvents();
    index.$el[0].f7ListIndex = null;
    delete index.$el[0].f7ListIndex;
    Utils.deleteProps(index);
    index = null;
  }
}

export default ListIndex;
<|endoftext|>


<commit_before>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * The MediaControl is responsible for displaying the Player controls.
 */

var _ = require('underscore')
var $ = require('jquery')
var JST = require('../../base/jst')
var Styler = require('../../base/styler')
var UIObject = require('../../base/ui_object')
var Utils = require('../../base/utils')

class MediaControl extends UIObject {
  get name() { return 'MediaControl' }

  get attributes() {
    return {
      class: 'media-control',
      'data-media-control': ''
    }
  }

  get events() {
    return {
      'click [data-play]': 'play',
      'click [data-pause]': 'pause',
      'click [data-playpause]': 'togglePlayPause',
      'click [data-stop]': 'stop',
      'click [data-playstop]': 'togglePlayStop',
      'click [data-fullscreen]': 'toggleFullscreen',
      'click [data-seekbar]': 'seek',
      'click .bar-background[data-volume]': 'volume',
      'click .drawer-icon[data-volume]': 'toggleMute',
      'mouseover .drawer-container[data-volume]': 'showVolumeBar',
      'mouseover [data-volume]': 'keepVolumeBar',
      'mouseleave .drawer-container[data-volume]': 'hideVolumeBar',
      'mousedown .bar-scrubber[data-seekbar]': 'startSeekDrag',
      'mousedown .bar-scrubber[data-volume]': 'startVolumeDrag',
      'mouseenter .media-control-layer[data-controls]': 'setKeepVisible',
      'mouseleave .media-control-layer[data-controls]': 'resetKeepVisible'
    }
  }

  get template() { return JST.media_control }

  initialize(params) {
    this.params = params
    this.container = params.container
    this.keepVisible = false
    this.addEventListeners()
    this.defaultSettings = {
      left: ['play', 'stop', 'pause'],
      right: ['volume'],
      default: ['position', 'seekbar', 'duration']
    }
    this.disabled = false
    if (this.container.mediaControlDisabled || this.params.chromeless)
      this.disable()
    this.currentVolume = 100
    $(document).bind('mouseup', (event) => this.stopDrag(event))
    $(document).bind('mousemove', (event) => this.updateDrag(event))
  }

  addEventListeners() {
    this.listenTo(this.container, 'container:play', this.changeTogglePlay)
    this.listenTo(this.container, 'container:playing', this.changeTogglePlay)
    this.listenTo(this.container, 'container:timeupdate', this.updateSeekBar)
    this.listenTo(this.container, 'container:progress', this.updateProgressBar)
    this.listenTo(this.container, 'container:settingsupdate', this.settingsUpdate)
    this.listenTo(this.container, 'container:highdefinitionupdate', this.highDefinitionUpdate)
    this.listenTo(this.container, 'container:mediacontrol:disable', this.disable)
    this.listenTo(this.container, 'container:mediacontrol:enable', this.enable)
    this.listenTo(this.container, 'container:ended', this.ended)
  }

  disable() {
    this.disabled = true
    this.hide()
  }

  enable() {
    if (this.params.chromeless) return
    this.disabled = false
    this.show()
  }

  play() {
    this.container.play()
  }

  pause() {
    this.container.pause()
  }

  stop() {
    this.container.stop()
  }

  changeTogglePlay() {
    if (this.container.isPlaying()) {
      this.$playPauseToggle.removeClass('paused').addClass('playing')
      this.$playStopToggle.removeClass('stopped').addClass('playing')
    } else {
      this.$playPauseToggle.removeClass('playing').addClass('paused')
      this.$playStopToggle.removeClass('playing').addClass('stopped')
    }
  }

  togglePlayPause() {
    if (this.container.isPlaying()) {
      this.container.pause()
    } else {
      this.container.play()
    }
    this.changeTogglePlay()
  }

  togglePlayStop() {
    if (this.container.isPlaying()) {
      this.container.stop()
    } else {
      this.container.play()
    }
    this.changeTogglePlay()
  }

  startSeekDrag(event) {
    this.draggingSeekBar = true
    if (event) {
      event.preventDefault()
    }
  }

  startVolumeDrag(event) {
    this.draggingVolumeBar = true
    if (event) {
      event.preventDefault()
    }
  }

  stopDrag(event) {
    if (this.draggingSeekBar) {
      this.seek(event)
    }
    this.draggingSeekBar = false
    this.draggingVolumeBar = false
  }

  updateDrag(event) {
    if (event) {
      event.preventDefault()
    }
    if (this.draggingSeekBar) {
      var offsetX = event.pageX - this.$seekBarContainer.offset().left
      var pos = offsetX / this.$seekBarContainer.width() * 100
      pos = Math.min(100, Math.max(pos, 0))
      this.setSeekPercentage(pos)
    } else if (this.draggingVolumeBar) {
      this.volume(event)
    }
  }

  volume(event) {
    var offsetY = event.pageY - this.$volumeBarContainer.offset().top
    this.currentVolume = (1 - (offsetY / this.$volumeBarContainer.height())) * 100
    this.currentVolume = Math.min(100, Math.max(this.currentVolume, 0))
    this.container.setVolume(this.currentVolume)
    this.setVolumeLevel(this.currentVolume)
  }

  toggleMute() {
    if (!!this.mute) {
      this.container.setVolume(this.currentVolume)
      this.setVolumeLevel(this.currentVolume)
      this.mute = false
    } else {
      this.container.setVolume(0)
      this.setVolumeLevel(0)
      this.mute = true
    }
  }

  toggleFullscreen() {
    this.trigger('mediacontrol:fullscreen', this.name)
  }

  setContainer(container) {
    this.stopListening(this.container)
    this.container = container
    this.changeTogglePlay()
    this.addEventListeners()
    this.settingsUpdate()
    this.container.volume(this.currentVolume)
    if (this.container.mediaControlDisabled)
      this.disable()
  }

  showVolumeBar() {
    if (this.hideVolumeId) {
      clearTimeout(this.hideVolumeId)
    }
    this.$volumeBarContainer.show()
    this.$volumeBarContainer.removeClass('volume-bar-hide')
  }

  hideVolumeBar() {
    if (!this.$volumeBarContainer) return
    if (this.hideVolumeId) {
      clearTimeout(this.hideVolumeId)
    }
    this.$volumeBarContainer.one(
      'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',
      () => this.$volumeBarContainer.hide()
    )
    this.hideVolumeId = setTimeout(
      () => this.$volumeBarContainer.addClass('volume-bar-hide'),
      750
    )
  }

  keepVolumeBar() {
    if(this.hideVolumeId) {
      clearTimeout(this.hideVolumeId)
    }
  }

  ended() {
    this.changeTogglePlay()
  }

  updateProgressBar(startPosition, endPosition, duration) {
    var loadedStart = startPosition / duration * 100
    var loadedEnd = endPosition / duration * 100
    this.$seekBarLoaded.css({ left: loadedStart + '%', width: (loadedEnd - loadedStart) + '%' })
  }

  updateSeekBar(position, duration) {
    if (this.draggingSeekBar) return
    var seekbarValue = (100 / duration) * position
    this.setSeekPercentage(seekbarValue)
    this.$('[data-position]').html(Utils.formatTime(position))
    this.$('[data-duration]').html(Utils.formatTime(duration))
  }

  seek(event) {
    var offsetX = event.pageX - this.$seekBarContainer.offset().left
    var pos = offsetX / this.$seekBarContainer.width() * 100
    pos = Math.min(100, Math.max(pos, 0))
    this.container.setCurrentTime(pos)
  }

  setKeepVisible() {
    this.keepVisible = true
  }

  resetKeepVisible() {
    this.keepVisible = false
  }

  show(event) {
    if (this.disabled) return
    var timeout = 2000
    if (!event || (event.clientX !== this.lastMouseX && event.clientY !== this.lastMouseY) || navigator.userAgent.match(/firefox/i)) {
      if (this.hideId) {
        clearTimeout(this.hideId)
      }
      this.trigger('mediacontrol:show', this.name)
      this.$el.removeClass('media-control-hide')
      this.hideId = setTimeout(() => this.hide(), timeout)
      if (event) {
        this.lastMouseX = event.clientX
        this.lastMouseY = event.clientY
      }
    }
  }

  hide() {
    var timeout = 2000
    if (this.hideId) {
      clearTimeout(this.hideId)
    }
    if (this.keepVisible || this.draggingVolumeBar || this.draggingSeekBar) {
      this.hideId = setTimeout(() => this.hide(), timeout)
    } else {
      if (this.$volumeBarContainer) {
        this.$volumeBarContainer.hide()
        this.hideVolumeBar()
      }
      this.trigger('mediacontrol:hide', this.name)
      this.$el.addClass('media-control-hide')
    }
  }

  settingsUpdate() {
    this.render()
  }

  highDefinitionUpdate() {
    var $element = this.$el.find('button[data-hd]')
    $element.removeClass('enabled')
    if (this.container.isHighDefinitionInUse()) {
      $element.addClass('enabled')
    }
  }

  createCachedElements() {
    this.$playPauseToggle = this.$el.find('button.media-control-button[data-playpause]')
    this.$playStopToggle = this.$el.find('button.media-control-button[data-playstop]')
    this.$seekBarContainer = this.$el.find('.bar-container[data-seekbar]')
    this.$seekBarLoaded = this.$el.find('.bar-fill-1[data-seekbar]')
    this.$seekBarPosition = this.$el.find('.bar-fill-2[data-seekbar]')
    this.$seekBarScrubber = this.$el.find('.bar-scrubber[data-seekbar]')
    this.$volumeBarContainer = this.$el.find('.bar-container[data-volume]')
    this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]')
    this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]')
    this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]')
    this.$volumeIcon = this.$el.find('.drawer-icon[data-volume]')
  }

  setVolumeLevel(value) {
    var containerHeight = this.$volumeBarContainer.height()
    var barHeight = this.$volumeBarBackground.height()
    var offset = (containerHeight - barHeight) / 2.0
    var pos = barHeight * value / 100.0 - this.$volumeBarScrubber.height() / 2.0 + offset
    this.$volumeBarFill.css({ height: value + '%' })
    this.$volumeBarScrubber.css({ bottom: pos })
    if (value > 0) {
      this.$volumeIcon.removeClass('muted')
    } else {
      this.$volumeIcon.addClass('muted')
    }
  }

  setSeekPercentage(value) {
    var pos = this.$seekBarContainer.width() * value / 100.0 - this.$seekBarScrubber.width() / 2.0
    this.$seekBarPosition.css({ width: value + '%' })
    this.$seekBarScrubber.css({ left: pos })
  }

  render() {
    var timeout = 1000
    var style = Styler.getStyleFor('media_control')
    var settings = this.container.settings || this.defaultSettings
    this.$el.html(this.template({ settings: settings }))
    this.$el.append(style)
    this.createCachedElements()
    this.$playPauseToggle.addClass('paused')
    this.$playStopToggle.addClass('stopped')
    this.currentVolume = this.currentVolume || 100

    this.$volumeBarContainer.hide()
    this.hideVolumeBar()

    if (this.params.autoPlay) {
      this.togglePlayPause()
      this.togglePlayStop()
    }
    this.changeTogglePlay()
    this.hideId = setTimeout(() => this.hide(), timeout)
    if (this.disabled)
      this.hide()

    this.$el.ready(() => {
      this.setVolumeLevel(this.currentVolume)
      this.setSeekPercentage(0)
    })

    return this
  }
}

module.exports = MediaControl
<commit_msg>media control: fix volume bar blinking issue<commit_after>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * The MediaControl is responsible for displaying the Player controls.
 */

var _ = require('underscore')
var $ = require('jquery')
var JST = require('../../base/jst')
var Styler = require('../../base/styler')
var UIObject = require('../../base/ui_object')
var Utils = require('../../base/utils')

class MediaControl extends UIObject {
  get name() { return 'MediaControl' }

  get attributes() {
    return {
      class: 'media-control',
      'data-media-control': ''
    }
  }

  get events() {
    return {
      'click [data-play]': 'play',
      'click [data-pause]': 'pause',
      'click [data-playpause]': 'togglePlayPause',
      'click [data-stop]': 'stop',
      'click [data-playstop]': 'togglePlayStop',
      'click [data-fullscreen]': 'toggleFullscreen',
      'click [data-seekbar]': 'seek',
      'click .bar-background[data-volume]': 'volume',
      'click .drawer-icon[data-volume]': 'toggleMute',
      'mouseover .drawer-container[data-volume]': 'showVolumeBar',
      'mouseleave .drawer-container[data-volume]': 'hideVolumeBar',
      'mousedown .bar-scrubber[data-seekbar]': 'startSeekDrag',
      'mousedown .bar-scrubber[data-volume]': 'startVolumeDrag',
      'mouseenter .media-control-layer[data-controls]': 'setKeepVisible',
      'mouseleave .media-control-layer[data-controls]': 'resetKeepVisible'
    }
  }

  get template() { return JST.media_control }

  initialize(params) {
    this.params = params
    this.container = params.container
    this.keepVisible = false
    this.addEventListeners()
    this.defaultSettings = {
      left: ['play', 'stop', 'pause'],
      right: ['volume'],
      default: ['position', 'seekbar', 'duration']
    }
    this.disabled = false
    if (this.container.mediaControlDisabled || this.params.chromeless)
      this.disable()
    this.currentVolume = 100
    $(document).bind('mouseup', (event) => this.stopDrag(event))
    $(document).bind('mousemove', (event) => this.updateDrag(event))
  }

  addEventListeners() {
    this.listenTo(this.container, 'container:play', this.changeTogglePlay)
    this.listenTo(this.container, 'container:playing', this.changeTogglePlay)
    this.listenTo(this.container, 'container:timeupdate', this.updateSeekBar)
    this.listenTo(this.container, 'container:progress', this.updateProgressBar)
    this.listenTo(this.container, 'container:settingsupdate', this.settingsUpdate)
    this.listenTo(this.container, 'container:highdefinitionupdate', this.highDefinitionUpdate)
    this.listenTo(this.container, 'container:mediacontrol:disable', this.disable)
    this.listenTo(this.container, 'container:mediacontrol:enable', this.enable)
    this.listenTo(this.container, 'container:ended', this.ended)
  }

  disable() {
    this.disabled = true
    this.hide()
  }

  enable() {
    if (this.params.chromeless) return
    this.disabled = false
    this.show()
  }

  play() {
    this.container.play()
  }

  pause() {
    this.container.pause()
  }

  stop() {
    this.container.stop()
  }

  changeTogglePlay() {
    if (this.container.isPlaying()) {
      this.$playPauseToggle.removeClass('paused').addClass('playing')
      this.$playStopToggle.removeClass('stopped').addClass('playing')
    } else {
      this.$playPauseToggle.removeClass('playing').addClass('paused')
      this.$playStopToggle.removeClass('playing').addClass('stopped')
    }
  }

  togglePlayPause() {
    if (this.container.isPlaying()) {
      this.container.pause()
    } else {
      this.container.play()
    }
    this.changeTogglePlay()
  }

  togglePlayStop() {
    if (this.container.isPlaying()) {
      this.container.stop()
    } else {
      this.container.play()
    }
    this.changeTogglePlay()
  }

  startSeekDrag(event) {
    this.draggingSeekBar = true
    if (event) {
      event.preventDefault()
    }
  }

  startVolumeDrag(event) {
    this.draggingVolumeBar = true
    if (event) {
      event.preventDefault()
    }
  }

  stopDrag(event) {
    if (this.draggingSeekBar) {
      this.seek(event)
    }
    this.draggingSeekBar = false
    this.draggingVolumeBar = false
  }

  updateDrag(event) {
    if (event) {
      event.preventDefault()
    }
    if (this.draggingSeekBar) {
      var offsetX = event.pageX - this.$seekBarContainer.offset().left
      var pos = offsetX / this.$seekBarContainer.width() * 100
      pos = Math.min(100, Math.max(pos, 0))
      this.setSeekPercentage(pos)
    } else if (this.draggingVolumeBar) {
      this.volume(event)
    }
  }

  volume(event) {
    var offsetY = event.pageY - this.$volumeBarContainer.offset().top
    this.currentVolume = (1 - (offsetY / this.$volumeBarContainer.height())) * 100
    this.currentVolume = Math.min(100, Math.max(this.currentVolume, 0))
    this.container.setVolume(this.currentVolume)
    this.setVolumeLevel(this.currentVolume)
  }

  toggleMute() {
    if (!!this.mute) {
      this.container.setVolume(this.currentVolume)
      this.setVolumeLevel(this.currentVolume)
      this.mute = false
    } else {
      this.container.setVolume(0)
      this.setVolumeLevel(0)
      this.mute = true
    }
  }

  toggleFullscreen() {
    this.trigger('mediacontrol:fullscreen', this.name)
  }

  setContainer(container) {
    this.stopListening(this.container)
    this.container = container
    this.changeTogglePlay()
    this.addEventListeners()
    this.settingsUpdate()
    this.container.volume(this.currentVolume)
    if (this.container.mediaControlDisabled)
      this.disable()
  }

  showVolumeBar() {
    if (this.hideVolumeId) {
      clearTimeout(this.hideVolumeId)
    }
    this.$volumeBarContainer.show()
    this.$volumeBarContainer.removeClass('volume-bar-hide')
  }

  hideVolumeBar() {
    if (!this.$volumeBarContainer) return
    if (this.hideVolumeId) {
      clearTimeout(this.hideVolumeId)
    }
    this.hideVolumeId = setTimeout(
      () => {
        this.$volumeBarContainer.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', () => {
          this.$volumeBarContainer.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend')
          this.$volumeBarContainer.hide()
        })
        this.$volumeBarContainer.addClass('volume-bar-hide')
      }, 750)
  }

  ended() {
    this.changeTogglePlay()
  }

  updateProgressBar(startPosition, endPosition, duration) {
    var loadedStart = startPosition / duration * 100
    var loadedEnd = endPosition / duration * 100
    this.$seekBarLoaded.css({ left: loadedStart + '%', width: (loadedEnd - loadedStart) + '%' })
  }

  updateSeekBar(position, duration) {
    if (this.draggingSeekBar) return
    var seekbarValue = (100 / duration) * position
    this.setSeekPercentage(seekbarValue)
    this.$('[data-position]').html(Utils.formatTime(position))
    this.$('[data-duration]').html(Utils.formatTime(duration))
  }

  seek(event) {
    var offsetX = event.pageX - this.$seekBarContainer.offset().left
    var pos = offsetX / this.$seekBarContainer.width() * 100
    pos = Math.min(100, Math.max(pos, 0))
    this.container.setCurrentTime(pos)
  }

  setKeepVisible() {
    this.keepVisible = true
  }

  resetKeepVisible() {
    this.keepVisible = false
  }

  show(event) {
    if (this.disabled) return
    var timeout = 2000
    if (!event || (event.clientX !== this.lastMouseX && event.clientY !== this.lastMouseY) || navigator.userAgent.match(/firefox/i)) {
      if (this.hideId) {
        clearTimeout(this.hideId)
      }
      this.trigger('mediacontrol:show', this.name)
      this.$el.removeClass('media-control-hide')
      this.hideId = setTimeout(() => this.hide(), timeout)
      if (event) {
        this.lastMouseX = event.clientX
        this.lastMouseY = event.clientY
      }
    }
  }

  hide() {
    var timeout = 2000
    if (this.hideId) {
      clearTimeout(this.hideId)
    }
    if (this.keepVisible || this.draggingVolumeBar || this.draggingSeekBar) {
      this.hideId = setTimeout(() => this.hide(), timeout)
    } else {
      if (this.$volumeBarContainer) {
        this.$volumeBarContainer.hide()
      }
      this.trigger('mediacontrol:hide', this.name)
      this.$el.addClass('media-control-hide')
    }
  }

  settingsUpdate() {
    this.render()
  }

  highDefinitionUpdate() {
    var $element = this.$el.find('button[data-hd]')
    $element.removeClass('enabled')
    if (this.container.isHighDefinitionInUse()) {
      $element.addClass('enabled')
    }
  }

  createCachedElements() {
    this.$playPauseToggle = this.$el.find('button.media-control-button[data-playpause]')
    this.$playStopToggle = this.$el.find('button.media-control-button[data-playstop]')
    this.$seekBarContainer = this.$el.find('.bar-container[data-seekbar]')
    this.$seekBarLoaded = this.$el.find('.bar-fill-1[data-seekbar]')
    this.$seekBarPosition = this.$el.find('.bar-fill-2[data-seekbar]')
    this.$seekBarScrubber = this.$el.find('.bar-scrubber[data-seekbar]')
    this.$volumeBarContainer = this.$el.find('.bar-container[data-volume]')
    this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]')
    this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]')
    this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]')
    this.$volumeIcon = this.$el.find('.drawer-icon[data-volume]')
  }

  setVolumeLevel(value) {
    var containerHeight = this.$volumeBarContainer.height()
    var barHeight = this.$volumeBarBackground.height()
    var offset = (containerHeight - barHeight) / 2.0
    var pos = barHeight * value / 100.0 - this.$volumeBarScrubber.height() / 2.0 + offset
    this.$volumeBarFill.css({ height: value + '%' })
    this.$volumeBarScrubber.css({ bottom: pos })
    if (value > 0) {
      this.$volumeIcon.removeClass('muted')
    } else {
      this.$volumeIcon.addClass('muted')
    }
  }

  setSeekPercentage(value) {
    var pos = this.$seekBarContainer.width() * value / 100.0 - this.$seekBarScrubber.width() / 2.0
    this.$seekBarPosition.css({ width: value + '%' })
    this.$seekBarScrubber.css({ left: pos })
  }

  render() {
    var timeout = 1000
    var style = Styler.getStyleFor('media_control')
    var settings = this.container.settings || this.defaultSettings
    this.$el.html(this.template({ settings: settings }))
    this.$el.append(style)
    this.createCachedElements()
    this.$playPauseToggle.addClass('paused')
    this.$playStopToggle.addClass('stopped')
    this.currentVolume = this.currentVolume || 100

    this.$volumeBarContainer.hide()

    if (this.params.autoPlay) {
      this.togglePlayPause()
      this.togglePlayStop()
    }
    this.changeTogglePlay()
    this.hideId = setTimeout(() => this.hide(), timeout)
    if (this.disabled)
      this.hide()

    this.$el.ready(() => {
      this.setVolumeLevel(this.currentVolume)
      this.setSeekPercentage(0)
    })

    return this
  }
}

module.exports = MediaControl
<|endoftext|>


<commit_before>import $ from 'dom7';
import Utils from '../../utils/utils';
import Framework7Class from '../../utils/class';

class Messagebar extends Framework7Class {
  constructor(app, params = {}) {
    super(params, [app]);

    const messagebar = this;

    const defaults = {
      top: false,
      topOffset: 0,
      bottomOffset: 0,
      attachments: [],
      renderAttachments: undefined,
      renderAttachment: undefined,
      maxHeight: null,
      resizePage: true,
    };

    // Extend defaults with modules params
    messagebar.useModulesParams(defaults);

    messagebar.params = Utils.extend(defaults, params);

    // El
    const $el = $(messagebar.params.el);
    if ($el.length === 0) return messagebar;

    $el[0].f7Messagebar = messagebar;

    // Page and PageContent
    const $pageEl = $el.parents('.page').eq(0);
    const $pageContentEl = $pageEl.find('.page-content').eq(0);

    // Area
    const $areaEl = $el.find('.messagebar-area');

    // Textarea
    let $textareaEl;
    if (messagebar.params.textareaEl) {
      $textareaEl = $(messagebar.params.textareaEl);
    } else {
      $textareaEl = $el.find('textarea');
    }

    // Attachments & Library
    const $attachmentsEl = $el.find('.messagebar-attachments');
    const $sheetEl = $el.find('.messagebar-sheet');

    if (messagebar.params.top) {
      $el.addClass('messagebar-top');
    }

    Utils.extend(messagebar, {
      $el,
      el: $el[0],
      $areaEl,
      areaEl: $areaEl[0],
      $textareaEl,
      textareaEl: $textareaEl[0],
      $attachmentsEl,
      attachmentsEl: $attachmentsEl[0],
      attachmentsVisible: $attachmentsEl.hasClass('messagebar-attachments-visible'),
      $sheetEl,
      sheetEl: $sheetEl[0],
      sheetVisible: $sheetEl.hasClass('messagebar-sheet-visible'),
      $pageEl,
      pageEl: $pageEl[0],
      $pageContentEl,
      pageContentEl: $pageContentEl,
      top: $el.hasClass('messagebar-top') || messagebar.params.top,
      attachments: [],
    });

    // Events
    function onAppResize() {
      if (messagebar.params.resizePage) {
        messagebar.resizePage();
      }
    }
    function onSubmit(e) {
      e.preventDefault();
    }
    function onAttachmentClick(e) {
      const index = $(this).index();
      if ($(e.target).closest('.messagebar-attachment-delete').length) {
        $(this).trigger('messagebar:attachmentdelete', index);
        messagebar.emit('local::attachmentDelete messagebarAttachmentDelete', messagebar, this, index);
      } else {
        $(this).trigger('messagebar:attachmentclick', index);
        messagebar.emit('local::attachmentClick messagebarAttachmentClick', messagebar, this, index);
      }
    }
    function onTextareaChange() {
      messagebar.checkEmptyState();
      messagebar.$el.trigger('messagebar:change');
      messagebar.emit('local::change messagebarChange', messagebar);
    }
    function onTextareaFocus() {
      messagebar.sheetHide();
      messagebar.$el.trigger('messagebar:focus');
      messagebar.emit('local::focus messagebarFocus', messagebar);
    }
    function onTextareaBlur() {
      messagebar.$el.trigger('messagebar:blur');
      messagebar.emit('local::blur messagebarBlur', messagebar);
    }

    messagebar.attachEvents = function attachEvents() {
      $el.on('textarea:resize', onAppResize);
      $el.on('submit', onSubmit);
      $el.on('click', '.messagebar-attachment', onAttachmentClick);
      $textareaEl.on('change input', onTextareaChange);
      $textareaEl.on('focus', onTextareaFocus);
      $textareaEl.on('blur', onTextareaBlur);
      app.on('resize', onAppResize);
    };
    messagebar.detachEvents = function detachEvents() {
      $el.off('textarea:resize', onAppResize);
      $el.off('submit', onSubmit);
      $el.off('click', '.messagebar-attachment', onAttachmentClick);
      $textareaEl.off('change input', onTextareaChange);
      $textareaEl.off('focus', onTextareaFocus);
      $textareaEl.off('blur', onTextareaBlur);
      app.off('resize', onAppResize);
    };

    // Install Modules
    messagebar.useModules();

    // Init
    messagebar.init();

    return messagebar;
  }
  focus() {
    const messagebar = this;
    messagebar.$textareaEl.focus();
    return messagebar;
  }
  blur() {
    const messagebar = this;
    messagebar.$textareaEl.blur();
    return messagebar;
  }
  clear() {
    const messagebar = this;
    messagebar.$textareaEl.val('').trigger('change');
    return messagebar;
  }
  getValue() {
    const messagebar = this;
    return messagebar.$textareaEl.val().trim();
  }
  setValue(value) {
    const messagebar = this;
    messagebar.$textareaEl.val(value).trigger('change');
    return messagebar;
  }
  setPlaceholder(placeholder) {
    const messagebar = this;
    messagebar.$textareaEl.attr('placeholder', placeholder);
    return messagebar;
  }
  resizePage() {
    const messagebar = this;
    const {
      params,
      $el,
      top,
      $pageEl,
      $pageContentEl,
      $areaEl,
      $textareaEl,
      $sheetEl,
      $attachmentsEl,
    } = messagebar;
    const elHeight = $el[0].offsetHeight;
    let maxHeight = params.maxHeight;
    if (top) {
      /*
      Disable at the moment
      const requiredPaddingTop = elHeight + params.topOffset;
      const currentPaddingTop = parseInt($pageContentEl.css('padding-top'), 10);
      if (requiredPaddingTop !== currentPaddingTop) {
        if (!maxHeight) {
          maxHeight = $pageEl[0].offsetHeight - currentPaddingTop - $sheetEl.outerHeight() - $attachmentsEl.outerHeight() - parseInt($areaEl.css('margin-top'), 10) - parseInt($areaEl.css('margin-bottom'), 10);
        }
        $textareaEl.css('max-height', `${maxHeight}px`);
        $pageContentEl.css('padding-top', `${requiredPaddingTop}px`);
        $el.trigger('messagebar:resizePage');
        messagebar.emit('local::resizepage messagebarResizePage');
      }
      */
    } else {
      const currentPaddingBottom = parseInt($pageContentEl.css('padding-bottom'), 10);
      const requiredPaddingBottom = elHeight + params.bottomOffset;
      if (requiredPaddingBottom !== currentPaddingBottom && $pageContentEl.length) {
        const currentPaddingTop = parseInt($pageContentEl.css('padding-top'), 10);
        const pageScrollHeight = $pageContentEl[0].scrollHeight;
        const pageOffsetHeight = $pageContentEl[0].offsetHeight;
        const pageScrollTop = $pageContentEl[0].scrollTop;
        const scrollOnBottom = (pageScrollTop === pageScrollHeight - pageOffsetHeight);
        if (!maxHeight) {
          maxHeight = $pageEl[0].offsetHeight - currentPaddingTop - $sheetEl.outerHeight() - $attachmentsEl.outerHeight() - parseInt($areaEl.css('margin-top'), 10) - parseInt($areaEl.css('margin-bottom'), 10);
        }
        $textareaEl.css('max-height', `${maxHeight}px`);
        $pageContentEl.css('padding-bottom', `${requiredPaddingBottom}px`);
        if (scrollOnBottom) {
          $pageContentEl.scrollTop($pageContentEl[0].scrollHeight - pageOffsetHeight);
        }
        $el.trigger('messagebar:resizepage');
        messagebar.emit('local::resizePage messagebarResizePage', messagebar);
      }
    }
  }
  checkEmptyState() {
    const messagebar = this;
    const { $el, $textareaEl } = messagebar;
    const value = $textareaEl.val().trim();
    if (value && value.length) {
      $el.addClass('messagebar-with-value');
    } else {
      $el.removeClass('messagebar-with-value');
    }
  }
  attachmentsCreate(innerHTML = '') {
    const messagebar = this;
    const $attachmentsEl = $(`<div class="messagebar-attachments">${innerHTML}</div>`);
    $attachmentsEl.insertBefore(messagebar.$textareaEl);
    Utils.extend(messagebar, {
      $attachmentsEl,
      attachmentsEl: $attachmentsEl[0],
    });
    return messagebar;
  }
  attachmentsShow(innerHTML = '') {
    const messagebar = this;
    messagebar.$attachmentsEl = messagebar.$el.find('.messagebar-attachments');
    if (messagebar.$attachmentsEl.length === 0) {
      messagebar.attachmentsCreate(innerHTML);
    }
    messagebar.$el.addClass('messagebar-attachments-visible');
    messagebar.attachmentsVisible = true;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  attachmentsHide() {
    const messagebar = this;
    messagebar.$el.removeClass('messagebar-attachments-visible');
    messagebar.attachmentsVisible = false;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  attachmentsToggle() {
    const messagebar = this;
    if (messagebar.attachmentsVisible) {
      messagebar.attachmentsHide();
    } else {
      messagebar.attachmentsShow();
    }
    return messagebar;
  }
  renderAttachment(attachment) {
    const messagebar = this;
    if (messagebar.params.renderAttachment) {
      return messagebar.params.renderAttachment.call(messagebar, attachment);
    }
    return `

    `;
  }
  renderAttachments() {
    const messagebar = this;
    let html;
    if (messagebar.params.renderAttachments) {
      html = messagebar.params.renderAttachments.call(messagebar, messagebar.attachments);
    } else {
      html = `${messagebar.attachments.map(attachment => messagebar.renderAttachment(attachment)).join('')}`;
    }
    if (messagebar.$attachmentsEl.length === 0) {
      messagebar.attachmentsCreate(html);
    } else {
      messagebar.$attachmentsEl.html(html);
    }
  }
  sheetCreate(innerHTML = '') {
    const messagebar = this;
    const $sheetEl = $(`<div class="messagebar-sheet">${innerHTML}</div>`);
    messagebar.$el.append($sheetEl);
    Utils.extend(messagebar, {
      $sheetEl,
      sheetEl: $sheetEl[0],
    });
    return messagebar;
  }
  sheetShow(innerHTML = '') {
    const messagebar = this;
    messagebar.$sheetEl = messagebar.$el.find('.messagebar-sheet');
    if (messagebar.$sheetEl.length === 0) {
      messagebar.sheetCreate(innerHTML);
    }
    messagebar.$el.addClass('messagebar-sheet-visible');
    messagebar.sheetVisible = true;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  sheetHide() {
    const messagebar = this;
    messagebar.$el.removeClass('messagebar-sheet-visible');
    messagebar.sheetVisible = false;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  sheetToggle() {
    const messagebar = this;
    if (messagebar.sheetVisible) {
      messagebar.sheetHide();
    } else {
      messagebar.sheetShow();
    }
    return messagebar;
  }
  init() {
    const messagebar = this;
    messagebar.attachEvents();
    messagebar.checkEmptyState();
    return messagebar;
  }
  destroy() {
    const messagebar = this;
    messagebar.emit('local::beforeDestroy messagebarBeforeDestroy', messagebar);
    messagebar.$el.trigger('messagebar:beforedestroy', messagebar);
    messagebar.detachEvents();
    messagebar.$el[0].f7Messagebar = null;
    delete messagebar.$el[0].f7Messagebar;
    Utils.deleteProps(messagebar);
  }
}

export default Messagebar;
<commit_msg>messagebar-focused class<commit_after>import $ from 'dom7';
import Utils from '../../utils/utils';
import Framework7Class from '../../utils/class';

class Messagebar extends Framework7Class {
  constructor(app, params = {}) {
    super(params, [app]);

    const messagebar = this;

    const defaults = {
      top: false,
      topOffset: 0,
      bottomOffset: 0,
      attachments: [],
      renderAttachments: undefined,
      renderAttachment: undefined,
      maxHeight: null,
      resizePage: true,
    };

    // Extend defaults with modules params
    messagebar.useModulesParams(defaults);

    messagebar.params = Utils.extend(defaults, params);

    // El
    const $el = $(messagebar.params.el);
    if ($el.length === 0) return messagebar;

    $el[0].f7Messagebar = messagebar;

    // Page and PageContent
    const $pageEl = $el.parents('.page').eq(0);
    const $pageContentEl = $pageEl.find('.page-content').eq(0);

    // Area
    const $areaEl = $el.find('.messagebar-area');

    // Textarea
    let $textareaEl;
    if (messagebar.params.textareaEl) {
      $textareaEl = $(messagebar.params.textareaEl);
    } else {
      $textareaEl = $el.find('textarea');
    }

    // Attachments & Library
    const $attachmentsEl = $el.find('.messagebar-attachments');
    const $sheetEl = $el.find('.messagebar-sheet');

    if (messagebar.params.top) {
      $el.addClass('messagebar-top');
    }

    Utils.extend(messagebar, {
      $el,
      el: $el[0],
      $areaEl,
      areaEl: $areaEl[0],
      $textareaEl,
      textareaEl: $textareaEl[0],
      $attachmentsEl,
      attachmentsEl: $attachmentsEl[0],
      attachmentsVisible: $attachmentsEl.hasClass('messagebar-attachments-visible'),
      $sheetEl,
      sheetEl: $sheetEl[0],
      sheetVisible: $sheetEl.hasClass('messagebar-sheet-visible'),
      $pageEl,
      pageEl: $pageEl[0],
      $pageContentEl,
      pageContentEl: $pageContentEl,
      top: $el.hasClass('messagebar-top') || messagebar.params.top,
      attachments: [],
    });

    // Events
    function onAppResize() {
      if (messagebar.params.resizePage) {
        messagebar.resizePage();
      }
    }
    function onSubmit(e) {
      e.preventDefault();
    }
    function onAttachmentClick(e) {
      const index = $(this).index();
      if ($(e.target).closest('.messagebar-attachment-delete').length) {
        $(this).trigger('messagebar:attachmentdelete', index);
        messagebar.emit('local::attachmentDelete messagebarAttachmentDelete', messagebar, this, index);
      } else {
        $(this).trigger('messagebar:attachmentclick', index);
        messagebar.emit('local::attachmentClick messagebarAttachmentClick', messagebar, this, index);
      }
    }
    function onTextareaChange() {
      messagebar.checkEmptyState();
      messagebar.$el.trigger('messagebar:change');
      messagebar.emit('local::change messagebarChange', messagebar);
    }
    function onTextareaFocus() {
      messagebar.sheetHide();
      messagebar.$el.addClass('messagebar-focused');
      messagebar.$el.trigger('messagebar:focus');
      messagebar.emit('local::focus messagebarFocus', messagebar);
    }
    function onTextareaBlur() {
      messagebar.$el.removeClass('messagebar-focused');
      messagebar.$el.trigger('messagebar:blur');
      messagebar.emit('local::blur messagebarBlur', messagebar);
    }

    messagebar.attachEvents = function attachEvents() {
      $el.on('textarea:resize', onAppResize);
      $el.on('submit', onSubmit);
      $el.on('click', '.messagebar-attachment', onAttachmentClick);
      $textareaEl.on('change input', onTextareaChange);
      $textareaEl.on('focus', onTextareaFocus);
      $textareaEl.on('blur', onTextareaBlur);
      app.on('resize', onAppResize);
    };
    messagebar.detachEvents = function detachEvents() {
      $el.off('textarea:resize', onAppResize);
      $el.off('submit', onSubmit);
      $el.off('click', '.messagebar-attachment', onAttachmentClick);
      $textareaEl.off('change input', onTextareaChange);
      $textareaEl.off('focus', onTextareaFocus);
      $textareaEl.off('blur', onTextareaBlur);
      app.off('resize', onAppResize);
    };

    // Install Modules
    messagebar.useModules();

    // Init
    messagebar.init();

    return messagebar;
  }
  focus() {
    const messagebar = this;
    messagebar.$textareaEl.focus();
    return messagebar;
  }
  blur() {
    const messagebar = this;
    messagebar.$textareaEl.blur();
    return messagebar;
  }
  clear() {
    const messagebar = this;
    messagebar.$textareaEl.val('').trigger('change');
    return messagebar;
  }
  getValue() {
    const messagebar = this;
    return messagebar.$textareaEl.val().trim();
  }
  setValue(value) {
    const messagebar = this;
    messagebar.$textareaEl.val(value).trigger('change');
    return messagebar;
  }
  setPlaceholder(placeholder) {
    const messagebar = this;
    messagebar.$textareaEl.attr('placeholder', placeholder);
    return messagebar;
  }
  resizePage() {
    const messagebar = this;
    const {
      params,
      $el,
      top,
      $pageEl,
      $pageContentEl,
      $areaEl,
      $textareaEl,
      $sheetEl,
      $attachmentsEl,
    } = messagebar;
    const elHeight = $el[0].offsetHeight;
    let maxHeight = params.maxHeight;
    if (top) {
      /*
      Disable at the moment
      const requiredPaddingTop = elHeight + params.topOffset;
      const currentPaddingTop = parseInt($pageContentEl.css('padding-top'), 10);
      if (requiredPaddingTop !== currentPaddingTop) {
        if (!maxHeight) {
          maxHeight = $pageEl[0].offsetHeight - currentPaddingTop - $sheetEl.outerHeight() - $attachmentsEl.outerHeight() - parseInt($areaEl.css('margin-top'), 10) - parseInt($areaEl.css('margin-bottom'), 10);
        }
        $textareaEl.css('max-height', `${maxHeight}px`);
        $pageContentEl.css('padding-top', `${requiredPaddingTop}px`);
        $el.trigger('messagebar:resizePage');
        messagebar.emit('local::resizepage messagebarResizePage');
      }
      */
    } else {
      const currentPaddingBottom = parseInt($pageContentEl.css('padding-bottom'), 10);
      const requiredPaddingBottom = elHeight + params.bottomOffset;
      if (requiredPaddingBottom !== currentPaddingBottom && $pageContentEl.length) {
        const currentPaddingTop = parseInt($pageContentEl.css('padding-top'), 10);
        const pageScrollHeight = $pageContentEl[0].scrollHeight;
        const pageOffsetHeight = $pageContentEl[0].offsetHeight;
        const pageScrollTop = $pageContentEl[0].scrollTop;
        const scrollOnBottom = (pageScrollTop === pageScrollHeight - pageOffsetHeight);
        if (!maxHeight) {
          maxHeight = $pageEl[0].offsetHeight - currentPaddingTop - $sheetEl.outerHeight() - $attachmentsEl.outerHeight() - parseInt($areaEl.css('margin-top'), 10) - parseInt($areaEl.css('margin-bottom'), 10);
        }
        $textareaEl.css('max-height', `${maxHeight}px`);
        $pageContentEl.css('padding-bottom', `${requiredPaddingBottom}px`);
        if (scrollOnBottom) {
          $pageContentEl.scrollTop($pageContentEl[0].scrollHeight - pageOffsetHeight);
        }
        $el.trigger('messagebar:resizepage');
        messagebar.emit('local::resizePage messagebarResizePage', messagebar);
      }
    }
  }
  checkEmptyState() {
    const messagebar = this;
    const { $el, $textareaEl } = messagebar;
    const value = $textareaEl.val().trim();
    if (value && value.length) {
      $el.addClass('messagebar-with-value');
    } else {
      $el.removeClass('messagebar-with-value');
    }
  }
  attachmentsCreate(innerHTML = '') {
    const messagebar = this;
    const $attachmentsEl = $(`<div class="messagebar-attachments">${innerHTML}</div>`);
    $attachmentsEl.insertBefore(messagebar.$textareaEl);
    Utils.extend(messagebar, {
      $attachmentsEl,
      attachmentsEl: $attachmentsEl[0],
    });
    return messagebar;
  }
  attachmentsShow(innerHTML = '') {
    const messagebar = this;
    messagebar.$attachmentsEl = messagebar.$el.find('.messagebar-attachments');
    if (messagebar.$attachmentsEl.length === 0) {
      messagebar.attachmentsCreate(innerHTML);
    }
    messagebar.$el.addClass('messagebar-attachments-visible');
    messagebar.attachmentsVisible = true;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  attachmentsHide() {
    const messagebar = this;
    messagebar.$el.removeClass('messagebar-attachments-visible');
    messagebar.attachmentsVisible = false;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  attachmentsToggle() {
    const messagebar = this;
    if (messagebar.attachmentsVisible) {
      messagebar.attachmentsHide();
    } else {
      messagebar.attachmentsShow();
    }
    return messagebar;
  }
  renderAttachment(attachment) {
    const messagebar = this;
    if (messagebar.params.renderAttachment) {
      return messagebar.params.renderAttachment.call(messagebar, attachment);
    }
    return `

    `;
  }
  renderAttachments() {
    const messagebar = this;
    let html;
    if (messagebar.params.renderAttachments) {
      html = messagebar.params.renderAttachments.call(messagebar, messagebar.attachments);
    } else {
      html = `${messagebar.attachments.map(attachment => messagebar.renderAttachment(attachment)).join('')}`;
    }
    if (messagebar.$attachmentsEl.length === 0) {
      messagebar.attachmentsCreate(html);
    } else {
      messagebar.$attachmentsEl.html(html);
    }
  }
  sheetCreate(innerHTML = '') {
    const messagebar = this;
    const $sheetEl = $(`<div class="messagebar-sheet">${innerHTML}</div>`);
    messagebar.$el.append($sheetEl);
    Utils.extend(messagebar, {
      $sheetEl,
      sheetEl: $sheetEl[0],
    });
    return messagebar;
  }
  sheetShow(innerHTML = '') {
    const messagebar = this;
    messagebar.$sheetEl = messagebar.$el.find('.messagebar-sheet');
    if (messagebar.$sheetEl.length === 0) {
      messagebar.sheetCreate(innerHTML);
    }
    messagebar.$el.addClass('messagebar-sheet-visible');
    messagebar.sheetVisible = true;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  sheetHide() {
    const messagebar = this;
    messagebar.$el.removeClass('messagebar-sheet-visible');
    messagebar.sheetVisible = false;
    if (messagebar.params.resizePage) {
      messagebar.resizePage();
    }
    return messagebar;
  }
  sheetToggle() {
    const messagebar = this;
    if (messagebar.sheetVisible) {
      messagebar.sheetHide();
    } else {
      messagebar.sheetShow();
    }
    return messagebar;
  }
  init() {
    const messagebar = this;
    messagebar.attachEvents();
    messagebar.checkEmptyState();
    return messagebar;
  }
  destroy() {
    const messagebar = this;
    messagebar.emit('local::beforeDestroy messagebarBeforeDestroy', messagebar);
    messagebar.$el.trigger('messagebar:beforedestroy', messagebar);
    messagebar.detachEvents();
    messagebar.$el[0].f7Messagebar = null;
    delete messagebar.$el[0].f7Messagebar;
    Utils.deleteProps(messagebar);
  }
}

export default Messagebar;
<|endoftext|>