<commit_before>
var paginate = require('../index');
var util = require('util');
var url = require('url');

describe('paginate', function() {

  describe('.href(req)', function() {

    beforeEach(function() {
      this.req = {
        originalUrl: 'http://niftylettuce.com/',
        query: {
          page: 3
        }
      };
    });

    it('should return function', function() {
      paginate.href(this.req).should.be.a('function');
    });

    describe('the returned function', function() {

      it('should return the next page when invoked with no arguments', function() {
        paginate.href(this.req)().should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the next page when invoked with `false` as the first argument', function() {
        paginate.href(this.req)().should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the previous page href when invoked with `true` as the first argument', function() {
        paginate.href(this.req)(true).should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page - 1));
      });

      it('should return the previous page href and sorted by title when invoked with `true` and a `params` object', function() {
        paginate.href(this.req)(true, { sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page - 1));
      });

      it('should return the next page href and sorted by title when invoked with `false` and a `params` object', function() {
        paginate.href(this.req)(false, { sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the current page sorted by title when invoked with just a `params` object as the first argument', function() {
        paginate.href(this.req)({ sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page));
      });

    });

  });

  describe('.hasNextPages(req)', function() {

    beforeEach(function() {
      this.req = {
        query: {
          page: 3
        }
      };
    });

    it('should return function', function() {
      paginate.hasNextPages(this.req).should.be.a('function');
    });

    describe('the returned function', function() {

      it('should return true when there are more pages', function() {
        paginate.hasNextPages(this.req)(4).should.be.true;
      });

      it('should return false when there are no more pages', function() {
        paginate.hasNextPages(this.req)(3).should.be.false;
      });

      it('should throw an error when pageCount is not a number', function(){
        (function(){
          paginate.hasNextPages(this.req)('');
        }).should.throw(/not a number/);
      });

      it('should throw an error when pageCount is less than zero', function() {
        (function(){
          paginate.hasNextPages(this.req)('');
        }).should.throw(/\> 0/);
      });

    });

  });

});
<commit_msg>Fixed tests<commit_after>
var paginate = require('../index');
var util = require('util');
var url = require('url');

describe('paginate', function() {

  describe('.href(req)', function() {

    beforeEach(function() {
      this.req = {
        originalUrl: 'http://niftylettuce.com/',
        query: {
          page: 3
        }
      };
    });

    it('should return function', function() {
      paginate.href(this.req).should.be.a('function');
    });

    describe('the returned function', function() {

      it('should return the next page when invoked with no arguments', function() {
        paginate.href(this.req)().should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the next page when invoked with `false` as the first argument', function() {
        paginate.href(this.req)().should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the previous page href when invoked with `true` as the first argument', function() {
        paginate.href(this.req)(true).should.equal(util.format('%s?page=%d', url.parse(this.req.originalUrl).pathname, this.req.query.page - 1));
      });

      it('should return the previous page href and sorted by title when invoked with `true` and a `params` object', function() {
        paginate.href(this.req)(true, { sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page - 1));
      });

      it('should return the next page href and sorted by title when invoked with `false` and a `params` object', function() {
        paginate.href(this.req)(false, { sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page + 1));
      });

      it('should return the current page sorted by title when invoked with just a `params` object as the first argument', function() {
        paginate.href(this.req)({ sort: 'title' }).should.equal(util.format('%s?page=%d&sort=title', url.parse(this.req.originalUrl).pathname, this.req.query.page));
      });

    });

  });

  describe('.hasNextPages(req)', function() {

    beforeEach(function() {
      this.req = {
        query: {
          page: 3
        }
      };
    });

    it('should return function', function() {
      paginate.hasNextPages(this.req).should.be.a('function');
    });

    describe('the returned function', function() {

      it('should return true when there are more pages', function() {
        paginate.hasNextPages(this.req)(4).should.be.true;
      });

      it('should return false when there are no more pages', function() {
        paginate.hasNextPages(this.req)(3).should.be.false;
      });

      it('should throw an error when pageCount is not a number', function(){
        (function(){
          paginate.hasNextPages(this.req)('');
        }).should.throw(/not a number/);
      });

      it('should throw an error when pageCount is less than zero', function() {
        (function(){
          paginate.hasNextPages(this.req)('');
        }).should.throw(/\>= 0/);
      });

    });

  });

});
<|endoftext|>


<commit_before>'use strict';

// Tests suite
const chai = require('chai');
chai.should();
const expect = chai.expect;

// The star of the show
JSON.truncate = require('../');

// Helper
const createDeep = levels => {

    const createALevel = (obj, level) => {
        obj.bool = true;
        obj.num = 10;
        obj.str = `You are on level ${level}`;
        obj.arr = [true, 1, 'hi'];
        obj.sub = {};
        return obj;
    };

    let rootobj = {};
    let levelsCopy = levels;

    let refobj = rootobj;
    while (levelsCopy > 0) {
        levelsCopy--;
        createALevel(refobj, levels - levelsCopy);
        if (levelsCopy > 0) {
            refobj = refobj.sub;
        } else {
            refobj.sub = undefined;
            refobj.arr = undefined;
        }
    }

    //refobj.sub = undefined;
    return rootobj;
};

describe('JSONtruncate', () => {

    describe('defaults', () => {

        it('should truncate to 1', () => {
            JSON.truncate(createDeep(3), 1).should.deep.equal(createDeep(1));
        });

        it('should truncate to default (10)', () => {
            JSON.truncate(createDeep(15)).should.deep.equal(createDeep(10));
        });

        it('should truncate arrays and nested objects', () => {
            JSON.truncate([createDeep(3)], 2).should.deep.equal([createDeep(1)]);
        });

        it('should return flat objects', () => {
            [5, true, false, "hello"].map(val => {
              JSON.truncate(val, 5).should.equal(val);
            });
        });

        it('should return an empty with anything not jsonable', () => {
          JSON.truncate(function(){}, 5).should.deep.equal({});
        });

        it('should return an empty object with a bad maxDepth value', () => {
          expect(JSON.truncate({test: true}, {bad:true})).to.be.undefied;
        });

        it('should resolve recursive objects', () => {
            // setting up a recursive object
            const recursive = {
              test: true
            };
            Object.defineProperty(recursive, 'sub', {
              value: recursive,
              enumerable: true
            });

            JSON.truncate(recursive, 2).should.deep.equal({test: true, sub: {test: true, sub: undefined}});
        });

    });

});
<commit_msg>fix(): Adding a fix to the tests on older versions of node (iojs-3 - 0.10).<commit_after>'use strict';

// Tests suite
const chai = require('chai');
chai.should();
const expect = chai.expect;

// The star of the show
JSON.truncate = require('../');

// Helper
const createDeep = function(levels) {

    const createALevel = (obj, level) => {
        obj.bool = true;
        obj.num = 10;
        obj.str = `You are on level ${level}`;
        obj.arr = [true, 1, 'hi'];
        obj.sub = {};
        return obj;
    };

    let rootobj = {};
    let levelsCopy = levels;

    let refobj = rootobj;
    while (levelsCopy > 0) {
        levelsCopy--;
        createALevel(refobj, levels - levelsCopy);
        if (levelsCopy > 0) {
            refobj = refobj.sub;
        } else {
            refobj.sub = undefined;
            refobj.arr = undefined;
        }
    }

    //refobj.sub = undefined;
    return rootobj;
};

describe('JSONtruncate', () => {

    describe('defaults', () => {

        it('should truncate to 1', () => {
            JSON.truncate(createDeep(3), 1).should.deep.equal(createDeep(1));
        });

        it('should truncate to default (10)', () => {
            JSON.truncate(createDeep(15)).should.deep.equal(createDeep(10));
        });

        it('should truncate arrays and nested objects', () => {
            JSON.truncate([createDeep(3)], 2).should.deep.equal([createDeep(1)]);
        });

        it('should return flat objects', () => {
            [5, true, false, "hello"].map(val => {
              JSON.truncate(val, 5).should.equal(val);
            });
        });

        it('should return an empty with anything not jsonable', () => {
          JSON.truncate(function(){}, 5).should.deep.equal({});
        });

        it('should return an empty object with a bad maxDepth value', () => {
          expect(JSON.truncate({test: true}, {bad:true})).to.be.undefied;
        });

        it('should resolve recursive objects', () => {
            // setting up a recursive object
            const recursive = {
              test: true
            };
            Object.defineProperty(recursive, 'sub', {
              value: recursive,
              enumerable: true
            });

            JSON.truncate(recursive, 2).should.deep.equal({test: true, sub: {test: true, sub: undefined}});
        });

    });

});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Controller.extend({
  didValidate: false,

  onSuccess() {
    this.transitionToRoute('dashboard');
  },

  onFailure() {
    this.set(
      'errorMessage',
      'Huh? Something bad happened. Please contact support if it continues.');
  },

  actions: {
    create() {
      this.get('model').validate().then(({model, validations}) => {
        if (validations.get('isValid')) {
          model.save()
            .then(this.onSuccess.bind(this))
            .catch(this.onFailure.bind(this));
        } else {
          // TODO: There needs to be some kind of reset when leaving login.
          // Clear any previous submission to the server.
          this.set('errorMessage', 'Oops. Something is out of whack.');
        }
        this.set('didValidate', true);
      });
    }
  }
});
<commit_msg>Handle errors for /students/new.<commit_after>import Ember from 'ember';

export default Ember.Controller.extend({
  didValidate: false,

  onSuccess() {
    this.transitionToRoute('dashboard');
  },

  onFailure() {
    this.set(
      'errorMessage',
      'Huh? Something bad happened. Please contact support if it continues.');
  },

  actions: {
    create() {
      this.get('model').validate().then(({model, validations}) => {
        if (validations.get('isValid')) {
          model.save()
            .then(this.onSuccess.bind(this))
            .catch(this.onFailure.bind(this));
        } else {
          this.set('errorMessage', 'Oops. Something is out of whack.');
        }
        this.set('didValidate', true);
      });
    }
  }
});
<|endoftext|>


<commit_before>/*jslint browser: true, plusplus: false*/
/*global $, Snap, console*/

function AirResContext(canvas, dom) {
    'use strict';

    this.context = canvas;
    this.domContext = dom;

    this.config = {
        grid: {
            margin: 60,
            stroke: '#EEE',
            darkStroke: '#000',
            strokeWidth: 2
        },
        path: {
            stroke: '#444',
            strokeWidth: 2
        }
    };

    this.horizontalSegments = 0;
    this.verticalSegments = 0;

    this.boundings = {
        x: {
            min: 0,
            max: 1
        },
        y: {
            min: 0,
            max: 1
        }
    };

    return this;
}

AirResContext.prototype.setBoundings = function (xMin, xMax, yMin, yMax) {
    'use strict';

    // Save the boundings
    this.boundings = {
        x: {
            min: xMin,
            max: xMax
        },
        y: {
            min: yMin,
            max: yMax
        }
    };
};

AirResContext.prototype.drawGrid = function (hSegments, vSegments) {
    'use strict';

    // If either the horizontal or the vertical segments are undefined, throw an error
    if (!hSegments || !vSegments) {
        throw new Error('The amount of segments cannot be 0');
    }

    // Save the amount of segments
    this.horizontalSegments = hSegments;
    this.verticalSegments = vSegments;

    // Create new group for the grid
    this.grid = this.context.g();

    // Save the height and width of the DOM object of the canvas
    var height = this.domContext.height() - 2 * this.config.grid.margin,
        width = this.domContext.width() - 2 * this.config.grid.margin,
        gridHeight = height / vSegments,
        gridWidth = width / hSegments;

    for (var i = 0; i <= vSegments; i++) {

        // Calculate the points for horizontal grid
        var x1 = this.config.grid.margin - this.config.grid.strokeWidth / 2,
            y1 = this.config.grid.margin + i * gridHeight,
            x2 = this.config.grid.margin + width + this.config.grid.strokeWidth / 2,
            y2 = this.config.grid.margin + i * gridHeight;

        // Draw a horizontal line
        var horizontalLine = this.context.line(x1, y1, x2, y2);

        // If it's the last horizontal line, it's the axis, so make it darker
        if (i === vSegments) {
            horizontalLine.attr({
                stroke: this.config.grid.darkStroke
            });
        }

        // Add the horizontal line to the grid
        this.grid.add(horizontalLine);
    }

    for (var i = 0; i <= hSegments; i++) {

        // Calculate the points for vertical grid
        var x1 = this.config.grid.margin + i * gridWidth,
            y1 = this.config.grid.margin - this.config.grid.strokeWidth / 2,
            x2 = this.config.grid.margin + i * gridWidth,
            y2 = this.config.grid.margin + height + this.config.grid.strokeWidth / 2;

        // Draw vertical line
        var verticalLine = this.context.line(x1, y1, x2, y2);

        // If it's the first vertical line, it's the axis, so make it darker
        if (i === 0) {
            verticalLine.attr({
                stroke: this.config.grid.darkStroke
            });
        }

        // Add the vertical line to the grid
        this.grid.add(verticalLine);
    }

    // Set the attributes for the grid
    this.grid.attr({
        stroke: this.config.grid.stroke,
        strokeWidth: this.config.grid.strokeWidth
    });

    return this.grid;
};

AirResContext.prototype.drawData = function (xData, yData) {

    // If the datapoints for x and y does not match, throw an error
    if (xData.length != yData.length) {
        throw new Error('Amount of datapoints for x- and y-axis must match');
    }

    // Calculate the height and width of the diagram
    var height = this.domContext.height() - 2 * this.config.grid.margin,
        width = this.domContext.width() - 2 * this.config.grid.margin;

    // Initialize the path
    var path = '';

    for (var i = 0; i < xData.length; i++) {

        // Calculate the x- and y-coordinate for the next datapoint
        var xCoordinate = ((xData[i] - this.boundings.x.min) / (this.boundings.x.max - this.boundings.x.min)) * width + this.config.grid.margin,
            yCoordinate = height - ((yData[i] - this.boundings.y.min) / (this.boundings.y.max - this.boundings.y.min)) * height + this.config.grid.margin;

        // If it's the first datapoint, move the path to it using 'M'
        if (i === 0) {
            path += 'M';
        } else {
            path += 'L';
        }

        // Append the datapoint to the path
        path += xCoordinate + ',' + yCoordinate;
    }

    // Draw the generated path
    var graph = this.context.path(path);

    // Set attributes for the drawn path
    graph.attr({
        stroke: this.config.path.stroke,
        strokeWidth: this.config.path.strokeWidth,
        'fill-opacity': 0
    });

    return graph;
};

$(function () {
    'use strict';

    // Get the DOM-Object for the diagram, read the width of the parent and calculate the height
    var domContext = $('#diagram'),
        totalWidth = domContext.closest('div').width(),
        totalHeight = (totalWidth / 16) * 9;

    // Add the width and height to the diagram
    domContext.attr('width', totalWidth);
    domContext.attr('height', totalHeight);

    // Create a new Snap.svg context
    var sCanvas = new Snap('#diagram'),
        context = new AirResContext(sCanvas, domContext);

    // Draw the grid
    context.drawGrid(15, 10);

    // Initialize a place to store all the paths
    var paths = [];

    // Read configuration from the <form>'s
    var readConfiguration = function() {
        return {
            requestID: Math.random(),
            terrain: {
                angle: parseFloat($('input[name=angle]').val()),
                gravitation: parseFloat($('input[name=gravitation]').val()),
                length: parseFloat($('input[name=length]').val()),
            },
            subject: {
                weight: parseFloat($('input[name=weight]').val()),
                area: parseFloat($('input[name=area]').val()),
                cw: parseFloat($('input[name=cw]').val()),
                init_velo: parseFloat($('input[name=init_velo]').val()),
                force: parseFloat($('input[name=force]').val()),
            },
            resistance: {
                stationary: parseFloat($('input[name=stationary]').val()),
                underway: 0,
            },
            fluid: {
                density: parseFloat($('input[name=density]').val()),
            },
            points: {
                max: 1000,
                steps: 0.5,
            }
        };
    },
        redraw = function() {

            // Remove all paths on redraw
            paths.forEach(function(path) {
                path.remove();
            });

            // Read input and analyze it
            var input = readConfiguration(),
                result = analyze(input);

            // Read which properties should be shown
            var properties = $('input[name=diagram]:checked').val().split('|'),
                xProperty = properties[1],
                yProperty = properties[0];

            // Initialize min- and max-values
            var xMin = 0,
                xMax = 0,
                yMin = 0,
                yMax = 0;

            // Draw a path for each activated graph
            $('input[name=graphs]').each(function() {

                // Map the x-coordinates according to the diagram-type
                var xData = (result[$(this).val()] || []).map(function(obj) {
                    return obj[xProperty];
                });

                // Map the y-coordinates according to the diagram-type
                var yData = (result[$(this).val()] || []).map(function(obj) {
                    return obj[yProperty];
                });

                // Calculate the max-values for the data of the current graph
                var xTempMax = Math.max.apply(null, xData),
                    yTempMax = Math.max.apply(null, yData);

                // If the calculated max-values are bigger than the ones before, save them
                if (xTempMax > xMax) xMax = xTempMax;
                if (yTempMax > yMax) yMax = yTempMax;
            });

            // Set the boundings (i.e. min- and max-values)
            context.setBoundings(xMin, xMax, yMin, yMax);

            // If the min- and max-values are not the same, we can draw it
            if (xMin != xMax && yMin != yMax) {
                $('input[name=graphs]:checked').each(function() {

                    // Read the current graph type
                    var graphType = $(this).val();

                    // Map the x-coordinates of the current graphtype using the required property
                    var xData = (result[graphType] || []).map(function(obj) {
                        return obj[xProperty];
                    });

                    // Map the y-coordinates of the current graphtype using the required property
                    var yData = (result[graphType] || []).map(function(obj) {
                        return obj[yProperty];
                    });

                    // Draw the path and push it to the paths-array, so we can remove it on redraw
                    paths.push(context.drawData(xData, yData));
                });
            }
        };

    // If different graphs are required or the diagram type changes, redraw it
    $('input[name=graphs]').change(redraw);
    $('input[name=diagram]').change(redraw);

    // If the values change, redraw, too
    $('.form-group input').keyup(redraw);
    $('.pre-defined').change(redraw);

    // Redraw the saved configurations
    var showConfigurations = function() {

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read, add examples
        catch(e) {
            savedConfigurations = [{
                name: 'Schlittschuhfahrer auf leichtem Gefälle',
                config: {
                    "terrain": {
                        "angle": 10,
                        "gravitation": 9.798,
                        "length": 1000
                    },
                    "subject": {
                        "weight": 80,
                        "area": 0.66,
                        "cw": 0.78,
                        "init_velo": 0,
                        "force": 0
                    },
                    "resistance": {
                        "stationary": 0.027,
                        "underway": 0
                    },
                    "fluid": {
                        "density": 1.204
                    }
                }
            }];

            // Save the example configurations to the localStorage
            localStorage.configurations = JSON.stringify(savedConfigurations);
        }

        // Remove all options from the configuration-select
        $('select[name=configuration]').empty();

        // For all found configurations create an option
        for (var i = 0; i < savedConfigurations.length; i++) {
            var option = $('<option></option>');
            option.val(i);
            option.text(savedConfigurations[i].name);
            option.appendTo($('select[name=configuration]'));
        }
    };

    // Show configuration on .ready()
    showConfigurations();

    // Save configuration clicked
    $('#save').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}

        // Push the configuration along its name
        savedConfigurations.push({
            name: $('input[name=configuration]').val(),
            config: readConfiguration()
        });

        // Save the configurations to the localStorage
        localStorage.configurations = JSON.stringify(savedConfigurations);

        // Hooray, we added a configuration, so reload them to make it visible
        showConfigurations();
    });

    // Load configuration clicked
    $('#load').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);

            // Read the selected configuration
            var loadedConfiguration = savedConfigurations[$('select[name=configuration]').val()].config;

            // Fill the <form> with the loaded configuration
            for (var section in loadedConfiguration) {
                if (typeof loadedConfiguration[section] === 'object') {
                    for (var name in loadedConfiguration[section]) {
                        $('input[name=' + name + ']').val(loadedConfiguration[section][name]).keyup();
                    }
                }
            }
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}
    });

    // Load configuration clicked
    $('#delete').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}

        // Splice the selected configuration out of the the array
        savedConfigurations.splice($('select[name=configuration]').val(), 1);

        // Save the configurations to the localStorage
        localStorage.configurations = JSON.stringify(savedConfigurations);

        // Boohoo, we removed a configuration, so reload them to make it invisible
        showConfigurations();
    });
});
<commit_msg>Add labels to the axis<commit_after>/*jslint browser: true, plusplus: false*/
/*global $, Snap, console*/

function AirResContext(canvas, dom) {
    'use strict';

    this.context = canvas;
    this.domContext = dom;

    this.config = {
        grid: {
            margin: 60,
            stroke: '#EEE',
            darkStroke: '#000',
            strokeWidth: 2
        },
        path: {
            stroke: '#444',
            strokeWidth: 2
        }
    };

    this.horizontalSegments = 0;
    this.verticalSegments = 0;

    this.boundings = {
        x: {
            min: 0,
            max: 1
        },
        y: {
            min: 0,
            max: 1
        }
    };

    return this;
}

AirResContext.prototype.setBoundings = function (xMin, xMax, yMin, yMax) {
    'use strict';

    // Save the boundings
    this.boundings = {
        x: {
            min: xMin,
            max: xMax
        },
        y: {
            min: yMin,
            max: yMax
        }
    };

    // If the axis are already drawn, remove them
    if (this.axis) {
        this.axis.remove();
    }

    // Create a group for both axis
    this.axis = this.context.g();

    // Create a group for both the x- and the y-axis
    var xAxis = this.context.g(),
        yAxis = this.context.g();

    // Calculate the range for the axis
    var xRange = xMax - xMin,
        yRange = yMax - yMin;

    // Save the height and width of the DOM object of the canvas
    var height = this.domContext.height() - 2 * this.config.grid.margin,
        width = this.domContext.width() - 2 * this.config.grid.margin,
        gridHeight = height / this.verticalSegments,
        gridWidth = width / this.horizontalSegments;

    for (var i = 0; i < this.verticalSegments; i++) {
        // Calculate the value for the next axis step
        var value = ((xRange / this.verticalSegments) * (this.verticalSegments - i)).toFixed(1);

        // Calculate the points for vertical grid
        var x = this.config.grid.margin - this.config.grid.strokeWidth / 2,
            y = this.config.grid.margin + i * gridHeight;

        // Draw the value text
        var valueText = this.context.text(x, y, value),
            valueTextBox = valueText.getBBox();

        // Transform value text to be left from the axis
        valueText.transform('T' + -valueTextBox.width + ',' + (valueTextBox.height / 2));

        // Add the value text to the x-axis group
        xAxis.add(valueText);
    }

    for (var i = 0; i <= this.horizontalSegments; i++) {
        // Calculate the value for the next axis step
        var value = ((yRange / this.horizontalSegments) * i).toFixed(1);

        // Calculate the points for vertical grid
        var x = this.config.grid.margin + i * gridWidth,
            y = this.config.grid.margin + height + this.config.grid.strokeWidth / 2;

        // Draw the value text
        var valueText = this.context.text(x, y, value),
            valueTextBox = valueText.getBBox();

        // Transform value text to be left from the axis
        valueText.transform('T' + -(valueTextBox.width / 2) + ',' + valueTextBox.height);

        // Add the value text to the x-axis group
        yAxis.add(valueText);
    }

    // Add the x- and the y-axis to the axis-group
    this.axis.add(xAxis);
    this.axis.add(yAxis);
};

AirResContext.prototype.drawGrid = function (hSegments, vSegments) {
    'use strict';

    // If either the horizontal or the vertical segments are undefined, throw an error
    if (!hSegments || !vSegments) {
        throw new Error('The amount of segments cannot be 0');
    }

    // Save the amount of segments
    this.horizontalSegments = hSegments;
    this.verticalSegments = vSegments;

    // Create new group for the grid
    this.grid = this.context.g();

    // Save the height and width of the DOM object of the canvas
    var height = this.domContext.height() - 2 * this.config.grid.margin,
        width = this.domContext.width() - 2 * this.config.grid.margin,
        gridHeight = height / vSegments,
        gridWidth = width / hSegments;

    for (var i = 0; i <= vSegments; i++) {

        // Calculate the points for horizontal grid
        var x1 = this.config.grid.margin - this.config.grid.strokeWidth / 2,
            y1 = this.config.grid.margin + i * gridHeight,
            x2 = this.config.grid.margin + width + this.config.grid.strokeWidth / 2,
            y2 = this.config.grid.margin + i * gridHeight;

        // Draw a horizontal line
        var horizontalLine = this.context.line(x1, y1, x2, y2);

        // If it's the last horizontal line, it's the axis, so make it darker
        if (i === vSegments) {
            horizontalLine.attr({
                stroke: this.config.grid.darkStroke
            });
        }

        // Add the horizontal line to the grid
        this.grid.add(horizontalLine);
    }

    for (var i = 0; i <= hSegments; i++) {

        // Calculate the points for vertical grid
        var x1 = this.config.grid.margin + i * gridWidth,
            y1 = this.config.grid.margin - this.config.grid.strokeWidth / 2,
            x2 = this.config.grid.margin + i * gridWidth,
            y2 = this.config.grid.margin + height + this.config.grid.strokeWidth / 2;

        // Draw vertical line
        var verticalLine = this.context.line(x1, y1, x2, y2);

        // If it's the first vertical line, it's the axis, so make it darker
        if (i === 0) {
            verticalLine.attr({
                stroke: this.config.grid.darkStroke
            });
        }

        // Add the vertical line to the grid
        this.grid.add(verticalLine);
    }

    // Set the attributes for the grid
    this.grid.attr({
        stroke: this.config.grid.stroke,
        strokeWidth: this.config.grid.strokeWidth
    });

    return this.grid;
};

AirResContext.prototype.drawData = function (xData, yData) {

    // If the datapoints for x and y does not match, throw an error
    if (xData.length != yData.length) {
        throw new Error('Amount of datapoints for x- and y-axis must match');
    }

    // Calculate the height and width of the diagram
    var height = this.domContext.height() - 2 * this.config.grid.margin,
        width = this.domContext.width() - 2 * this.config.grid.margin;

    // Initialize the path
    var path = '';

    for (var i = 0; i < xData.length; i++) {

        // Calculate the x- and y-coordinate for the next datapoint
        var xCoordinate = ((xData[i] - this.boundings.x.min) / (this.boundings.x.max - this.boundings.x.min)) * width + this.config.grid.margin,
            yCoordinate = height - ((yData[i] - this.boundings.y.min) / (this.boundings.y.max - this.boundings.y.min)) * height + this.config.grid.margin;

        // If it's the first datapoint, move the path to it using 'M'
        if (i === 0) {
            path += 'M';
        } else {
            path += 'L';
        }

        // Append the datapoint to the path
        path += xCoordinate + ',' + yCoordinate;
    }

    // Draw the generated path
    var graph = this.context.path(path);

    // Set attributes for the drawn path
    graph.attr({
        stroke: this.config.path.stroke,
        strokeWidth: this.config.path.strokeWidth,
        'fill-opacity': 0
    });

    return graph;
};

$(function () {
    'use strict';

    // Get the DOM-Object for the diagram, read the width of the parent and calculate the height
    var domContext = $('#diagram'),
        totalWidth = domContext.closest('div').width(),
        totalHeight = (totalWidth / 16) * 9;

    // Add the width and height to the diagram
    domContext.attr('width', totalWidth);
    domContext.attr('height', totalHeight);

    // Create a new Snap.svg context
    var sCanvas = new Snap('#diagram'),
        context = new AirResContext(sCanvas, domContext);

    // Draw the grid
    context.drawGrid(15, 10);

    // Initialize a place to store all the paths
    var paths = [];

    // Read configuration from the <form>'s
    var readConfiguration = function() {
        return {
            requestID: Math.random(),
            terrain: {
                angle: parseFloat($('input[name=angle]').val()),
                gravitation: parseFloat($('input[name=gravitation]').val()),
                length: parseFloat($('input[name=length]').val()),
            },
            subject: {
                weight: parseFloat($('input[name=weight]').val()),
                area: parseFloat($('input[name=area]').val()),
                cw: parseFloat($('input[name=cw]').val()),
                init_velo: parseFloat($('input[name=init_velo]').val()),
                force: parseFloat($('input[name=force]').val()),
            },
            resistance: {
                stationary: parseFloat($('input[name=stationary]').val()),
                underway: 0,
            },
            fluid: {
                density: parseFloat($('input[name=density]').val()),
            },
            points: {
                max: 1000,
                steps: 0.5,
            }
        };
    },
        redraw = function() {

            // Remove all paths on redraw
            paths.forEach(function(path) {
                path.remove();
            });

            // Read input and analyze it
            var input = readConfiguration(),
                result = analyze(input);

            // Read which properties should be shown
            var properties = $('input[name=diagram]:checked').val().split('|'),
                xProperty = properties[1],
                yProperty = properties[0];

            // Initialize min- and max-values
            var xMin = 0,
                xMax = 0,
                yMin = 0,
                yMax = 0;

            // Draw a path for each activated graph
            $('input[name=graphs]').each(function() {

                // Map the x-coordinates according to the diagram-type
                var xData = (result[$(this).val()] || []).map(function(obj) {
                    return obj[xProperty];
                });

                // Map the y-coordinates according to the diagram-type
                var yData = (result[$(this).val()] || []).map(function(obj) {
                    return obj[yProperty];
                });

                // Calculate the max-values for the data of the current graph
                var xTempMax = Math.max.apply(null, xData),
                    yTempMax = Math.max.apply(null, yData);

                // If the calculated max-values are bigger than the ones before, save them
                if (xTempMax > xMax) xMax = xTempMax;
                if (yTempMax > yMax) yMax = yTempMax;
            });

            // Set the boundings (i.e. min- and max-values)
            context.setBoundings(xMin, xMax, yMin, yMax);

            // If the min- and max-values are not the same, we can draw it
            if (xMin != xMax && yMin != yMax) {
                $('input[name=graphs]:checked').each(function() {

                    // Read the current graph type
                    var graphType = $(this).val();

                    // Map the x-coordinates of the current graphtype using the required property
                    var xData = (result[graphType] || []).map(function(obj) {
                        return obj[xProperty];
                    });

                    // Map the y-coordinates of the current graphtype using the required property
                    var yData = (result[graphType] || []).map(function(obj) {
                        return obj[yProperty];
                    });

                    // Draw the path and push it to the paths-array, so we can remove it on redraw
                    paths.push(context.drawData(xData, yData));
                });
            }
        };

    // If different graphs are required or the diagram type changes, redraw it
    $('input[name=graphs]').change(redraw);
    $('input[name=diagram]').change(redraw);

    // If the values change, redraw, too
    $('.form-group input').keyup(redraw);
    $('.pre-defined').change(redraw);

    // Redraw the saved configurations
    var showConfigurations = function() {

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read, add examples
        catch(e) {
            savedConfigurations = [{
                name: 'Schlittschuhfahrer auf leichtem Gefälle',
                config: {
                    "terrain": {
                        "angle": 10,
                        "gravitation": 9.798,
                        "length": 1000
                    },
                    "subject": {
                        "weight": 80,
                        "area": 0.66,
                        "cw": 0.78,
                        "init_velo": 0,
                        "force": 0
                    },
                    "resistance": {
                        "stationary": 0.027,
                        "underway": 0
                    },
                    "fluid": {
                        "density": 1.204
                    }
                }
            }];

            // Save the example configurations to the localStorage
            localStorage.configurations = JSON.stringify(savedConfigurations);
        }

        // Remove all options from the configuration-select
        $('select[name=configuration]').empty();

        // For all found configurations create an option
        for (var i = 0; i < savedConfigurations.length; i++) {
            var option = $('<option></option>');
            option.val(i);
            option.text(savedConfigurations[i].name);
            option.appendTo($('select[name=configuration]'));
        }
    };

    // Show configuration on .ready()
    showConfigurations();

    // Save configuration clicked
    $('#save').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}

        // Push the configuration along its name
        savedConfigurations.push({
            name: $('input[name=configuration]').val(),
            config: readConfiguration()
        });

        // Save the configurations to the localStorage
        localStorage.configurations = JSON.stringify(savedConfigurations);

        // Hooray, we added a configuration, so reload them to make it visible
        showConfigurations();
    });

    // Load configuration clicked
    $('#load').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);

            // Read the selected configuration
            var loadedConfiguration = savedConfigurations[$('select[name=configuration]').val()].config;

            // Fill the <form> with the loaded configuration
            for (var section in loadedConfiguration) {
                if (typeof loadedConfiguration[section] === 'object') {
                    for (var name in loadedConfiguration[section]) {
                        $('input[name=' + name + ']').val(loadedConfiguration[section][name]).keyup();
                    }
                }
            }
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}
    });

    // Load configuration clicked
    $('#delete').click(function(e) {

        // Prevent the form from reloading the page
        e.preventDefault();

        // Initialize the saved configurations, we don't know yet if we can parse them
        var savedConfigurations = [];

        // Try to parse the saved configurations
        try {
            savedConfigurations = JSON.parse(localStorage.configurations);
        }

        // If the saved configurations couldn't be read... uhm... we'll ignore it
        catch(e) {}

        // Splice the selected configuration out of the the array
        savedConfigurations.splice($('select[name=configuration]').val(), 1);

        // Save the configurations to the localStorage
        localStorage.configurations = JSON.stringify(savedConfigurations);

        // Boohoo, we removed a configuration, so reload them to make it invisible
        showConfigurations();
    });
});
<|endoftext|>


<commit_before>$(function() {
	$('.edit-via-ajax a').click(function(e) {
		e.preventDefault();
		var father = $(this).parent();
		var child = father.children();
		child.toggle();
		father.find(".to-focus").focus();
		return false;
	});

	$('form.ajax').submit(function(e) {
		e.preventDefault();
		var self = $(this);
		if(!self.valid()) return false;

		var error = function() {
			console.log("error");
		};

		var success = function(response, status, jqhr) {
			var target = $("#" + self.data("ajax-result"));
			if(jqhr.status==201) {
				target.append("Sugestão enviada!");
			} else {
				var action = self.data("ajax-on-callback") || "replace-inner";
				if(action == "replace-inner") {
					target.html(response);
				} else if(action == "append") {
					target.append(response);
				} else if(action == "replace"){
					target.replaceWith(response);
				}
			}
			self.find("textarea").val("");
			var formParent = self.closest(".edit-via-ajax");
			formParent.children().toggle();
		};

		var uri = self.attr("action");
		$.ajax(uri, {
			success: success,
			error: error,
			dataType : 'html',
			data : self.serialize(),
			method: "POST"
		});
		return false;
	});
});<commit_msg>bind em elementos adicionados por ajax<commit_after>$(function() {
	$('body').on("click", ".edit-via-ajax a", function(e) {
		e.preventDefault();
		var father = $(this).parent();
		var child = father.children();
		child.toggle();
		father.find(".to-focus").focus();
		return false;
	});

	$('body').on("submit", "form.ajax", function(e) {
		e.preventDefault();
		var self = $(this);
		if(!self.valid()) return false;

		var error = function() {
			console.log("error");
		};

		var success = function(response, status, jqhr) {
			var target = $("#" + self.data("ajax-result"));
			if(jqhr.status==201) {
				target.append("Sugestão enviada!");
			} else {
				var action = self.data("ajax-on-callback") || "replace-inner";
				if(action == "replace-inner") {
					target.html(response);
				} else if(action == "append") {
					target.append(response);
				} else if(action == "replace"){
					target.replaceWith(response);
				}
			}
			self.find("textarea").val("");
			var formParent = self.closest(".edit-via-ajax");
			formParent.children().toggle();
		};

		var uri = self.attr("action");
		$.ajax(uri, {
			success: success,
			error: error,
			dataType : 'html',
			data : self.serialize(),
			method: "POST"
		});
		return false;
	});
});<|endoftext|>


<commit_before>// ==UserScript==
// @name         pinboard-youtube-alternates
// @version      1.0.1
// @description  Adds alternative links to YouTube videos on Pinboard.in
// @namespace    http://kafene.org
// @match        *://*.pinboard.in/*
// @run-at       document-start
// @grant        none
// @license      MIT <https://raw.githubusercontent.com/kafene/userscripts/mater/LICENSE>
// @require      https://raw.githubusercontent.com/ded/domready/master/src/ready.js
// @downloadURL  https://raw.githubusercontent.com/kafene/userscripts/master/pinboard-youtube-alternates.user.js
// @updateURL    https://raw.githubusercontent.com/kafene/userscripts/master/pinboard-youtube-alternates.user.js
// ==/UserScript==

domready(function () {
    var links = document.querySelectorAll('a.bookmark_title[href^="https://www.youtube.com/watch"]');
    var regex = /[?&]v=([^#&]+)/;

    [].forEach.call(links, function (a) {
        var v = regex.exec(a.href);
        if (!v || !v[1]) { return; }

        var description = a.parentNode.querySelector('.description');
        if (!description) {
            description = document.createElement('div');
            description.className = 'description';
            a.parentNode.insertBefore(description, a.nextSibling);
        }

        description.insertAdjacentHTML('AFTERBEGIN',
            '
Watch with: ' +
            'fixYT ‖ ' +
            'Toogles ‖ ' +
            'Accessible Interface to YouTube' +
            '
'
        );
    });
});
<commit_msg>add viewpure and quietube<commit_after>// ==UserScript==
// @name         pinboard-youtube-alternates
// @version      1.0.2
// @description  Adds alternative links to YouTube videos on Pinboard.in
// @namespace    http://kafene.org
// @match        *://*.pinboard.in/*
// @run-at       document-start
// @grant        none
// @license      MIT <https://raw.githubusercontent.com/kafene/userscripts/mater/LICENSE>
// @require      https://raw.githubusercontent.com/ded/domready/master/src/ready.js
// @downloadURL  https://raw.githubusercontent.com/kafene/userscripts/master/pinboard-youtube-alternates.user.js
// @updateURL    https://raw.githubusercontent.com/kafene/userscripts/master/pinboard-youtube-alternates.user.js
// ==/UserScript==

domready(function () {
    var links = document.querySelectorAll("a.bookmark_title[href^='https://www.youtube.com/watch']");
    var youtubeVideoIdRegex = /[?&]v=([^#&]+)/;

    [].forEach.call(links, function (link) {
        var matches = youtubeVideoIdRegex.exec(link.href);
        if (!matches || !matches[1]) { return; }
        var videoId = matches[1];

        var description = link.parentNode.querySelector('.description');
        if (!description) {
            description = document.createElement('div');
            description.className = 'description';
            link.parentNode.insertBefore(description, link.nextSibling);
        }

        description.insertAdjacentHTML("AFTERBEGIN",
            "
Watch with... " +
            "fixYT ‖ " +
            "Toogles ‖ " +
            "ViewPure ‖ " +
            "quietube ‖ " +
            "Accessible Interface to YouTube" +
            "
");
    });
});
<|endoftext|>


<commit_before>'use strict';

import React from 'react';

require('styles//Controls.scss');

class ControlsComponent extends React.Component {

  renderStopButton() {
    if (this.props.slides.isPlaying) {
      return <button id="stop">Stop</button>
    }

    return <button id="stop" style={{display: 'none'}} onClick={() => this.props.stop()}>Stop</button>

  }

  renderPlayButton() {
    if (this.props.slides.isPlaying) {
      return <button id="play" style={{display: 'none'}} onClick={() => this.props.play()}>Play</button>
    }

    return <button id="play">Play</button>
  }

  render() {
    return (

          <button id="previous" onClick={() => this.props.previous()}>Previous</button>
          {this.renderStopButton()}
          {this.renderPlayButton()}
          <button id="next" onClick={() => this.props.next()}>Next</button>

    );
  }
}

ControlsComponent.displayName = 'ControlsComponent';

ControlsComponent.propTypes = {
  slides :   React.PropTypes.object.isRequired,
  previous : React.PropTypes.func,
  stop :     React.PropTypes.func,
  play :     React.PropTypes.func,
  next :     React.PropTypes.func
};

export default ControlsComponent;
<commit_msg>Fixes the on click binding for play and stop<commit_after>'use strict';

import React from 'react';

require('styles//Controls.scss');

class ControlsComponent extends React.Component {

  renderStopButton() {
    if (this.props.slides.isPlaying) {
      return <button id="stop" onClick={() => this.props.stop()}>Stop</button>
    }

    return <button id="stop" style={{display: 'none'}} onClick={() => this.props.stop()}>Stop</button>

  }

  renderPlayButton() {
    if (this.props.slides.isPlaying) {
      return <button id="play" style={{display: 'none'}} onClick={() => this.props.play()}>Play</button>
    }

    return <button id="play" onClick={() => this.props.play()}>Play</button>
  }

  render() {
    return (

          <button id="previous" onClick={() => this.props.previous()}>Previous</button>
          {this.renderStopButton()}
          {this.renderPlayButton()}
          <button id="next" onClick={() => this.props.next()}>Next</button>

    );
  }
}

ControlsComponent.displayName = 'ControlsComponent';

ControlsComponent.propTypes = {
  slides :   React.PropTypes.object.isRequired,
  previous : React.PropTypes.func,
  stop :     React.PropTypes.func,
  play :     React.PropTypes.func,
  next :     React.PropTypes.func
};

export default ControlsComponent;
<|endoftext|>


<commit_before>import React from 'react';
import moment from 'moment';
import _ from 'lodash';
import ls from 'local-storage';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import {
    IconButton, Slider
}
from 'material-ui';
import {
    handleTime
}
from '../utils/time';
import PlayerStore from '../store';
import PlayerActions from '../actions';

export
default React.createClass({

    mixins: [PureRenderMixin],

    getInitialState() {

        var playerState = PlayerStore.getState();

        return {
            fullscreen: playerState.fullscreen,
            uiShown: playerState.uiShown || playerState.playlistOpen || playerState.settingsOpen,
            uiHidden: playerState.uiHidden,

            scrobbling: playerState.scrobbling,
            playing: playerState.playing,
            position: playerState.position,
            buffering: playerState.buffering,
            time: playerState.time,
            length: playerState.length,
            keepScrobble: playerState.keepScrobble,
            seekPerc: playerState.seekPerc,

            currentTime: playerState.currentTime,
            totalTime: playerState.totalTime,

            rippleEffects: playerState.rippleEffects,

            foundSubs: playerState.foundSubs,
            subtitlesOpen: playerState.subtitlesOpen,

            volume: ls('volume'),
            mute: playerState.muted,

            volumeDragging: false,
            volumePendingEffects: '',
            volumePendingRipples: '',

            forceTime: playerState.forceTime,
            overTime: playerState.overTime
        }
    },
    componentWillMount() {
        PlayerStore.listen(this.update);
    },
    componentDidMount() {
        window.addEventListener('mousemove', this.handleGlobalMouseMove);
        window.addEventListener('mouseup', this.handleGlobalMouseUp);

        // assign a class to the volume index pointer
        var volumeSlider = this.refs['volume-slider'][0].children[4].children[0].children[2];
        volumeSlider.className = 'volume-index volume-hover';
        volumeSlider.children[0].className = 'volume-ripple';
    },
    componentWillUnmount() {
        window.removeEventListener('mousemove', this.handleGlobalMouseMove);
        window.removeEventListener('mouseup', this.handleGlobalMouseUp);
        PlayerStore.unlisten(this.update);
    },
    update() {
        if (this.isMounted()) {

            var playerState = PlayerStore.getState();

            this.setState({
                fullscreen: playerState.fullscreen,
                uiShown: playerState.uiShown || playerState.playlistOpen || playerState.settingsOpen,
                uiHidden: playerState.uiHidden,

                playing: playerState.playing,
                position: playerState.position,
                buffering: playerState.buffering,
                seekable: playerState.seekable,
                time: playerState.time,
                length: playerState.length,
                scrobbling: playerState.scrobbling,
                seekPerc: playerState.seekPerc,

                currentTime: playerState.currentTime,
                totalTime: playerState.totalTime,

                rippleEffects: playerState.rippleEffects,

                foundSubs: playerState.foundSubs,
                subtitlesOpen: playerState.subtitlesOpen,

                volume: ls('volume'),
                mute: playerState.muted,

                forceTime: playerState.forceTime,
                overTime: playerState.overTime,

                keepScrobble: playerState.keepScrobble
            });
        }
    },
    delayScrobbleGUI() {
        _.delay(() => {
            PlayerActions.settingChange({
                keepScrobble: false
            })
        }, 1000)
    },
    handlePausePlay() {
        this.state.playing ? PlayerActions.pause() : PlayerActions.play();
    },
    handleNext() {
        PlayerActions.next();
    },
    handlePrev() {
        PlayerActions.prev();
    },
    handleFullscreen() {
        PlayerActions.toggleFullscreen(!this.state.fullscreen);
    },
    handleScrobblerHover(event) {

        var newState = {};

        var total_time = this.state.length;

        var percent_done = event.pageX / document.body.clientWidth;

        var newTime = total_time * percent_done;
        //        this.refs['scrobbler-handle'].style.left = (percent_done * 100) + '%';
        //console.log(total_time, percent_done + '%', newTime);
        if (this.state.time) {
            this.refs['scrobbler-tooltip'].style.display = 'inline-block';
            if (percent_done <= 0.5) {
                var realPos = Math.floor(window.innerWidth * percent_done) - this.state.tooltipHalf;
            } else {
                var realPos = Math.floor(window.innerWidth * percent_done) + this.state.tooltipHalf;
            }

            var seekTime = handleTime(percent_done * this.state.length, this.state.length);

            if (seekTime.length > 5)
                newState.tooltipHalf = 33;
            else
                newState.tooltipHalf = 24;

            if (realPos < 0) newState.tooltipLeft = newState.tooltipHalf + 'px';
            else if (realPos > window.innerWidth) newState.tooltipLeft = (window.innerWidth - newState.tooltipHalf) + 'px';
            else newState.tooltipLeft = (percent_done * 100) + '%';

            newState.humanTime = seekTime;
        }

        if (this.state.scrobbling) {
            PlayerActions.settingChange({
                seekPerc: percent_done < 0 ? 0 : percent_done > 1 ? 1 : percent_done
            });
        }

        if (Object.keys(newState).length) {
            this.setState(newState);
        }

    },
    handleScrobble(event) {
        if (!this.state.length || !this.state.seekable)
            return;

        PlayerActions.settingChange({
            keepScrobble: true,
            scrobbling: false
        });

        this.setState({
            position: this.state.seekPerc
        });

        this.refs['scrobbler-height'].className = this.refs['scrobbler-height'].className.replace(' scrobbling', '');
        this.delayScrobbleGUI();
        var percent_done = event.pageX / document.body.clientWidth;
        PlayerActions.scrobble(this.state.length * percent_done);
    },
    handleDragStart(event) {

        PlayerActions.scrobbleState(true);

        this.refs['scrobbler-height'].className = this.refs['scrobbler-height'].className + ' scrobbling';

        PlayerActions.settingChange({
            keepScrobble: true
        });
        var percent_done = event.pageX / document.body.clientWidth;
        PlayerActions.settingChange({
            seekPerc: percent_done
        });
        this.delayScrobbleGUI();
    },
    handleDragEnd() {
        this.refs['scrobbler-tooltip'].style.display = 'none';
    },
    handleGlobalMouseMove(event) {
        if (this.state.scrobbling) {
            this.handleScrobblerHover(event);
        }
    },
    handleGlobalMouseUp(event) {
        if (this.state.scrobbling) {
            this.handleScrobble(event);
            this.refs['scrobbler-tooltip'].style.display = 'none';
        }
    },
    handleVolume(event, t) {
        PlayerActions.volume(t);
    },
    handleMute(event) {
        PlayerActions.mute(!this.state.mute);
    },
    volumeIndexEffect(f, b, i) {
        if (i) {
            if (!this.state.volumeDragging) {
                var volumeIndex = document.querySelector('.volume-index');
                var volumeClass = volumeIndex.className.replace(' volume-hover', '');
                if (i.type == 'react-mouseenter') {
                    volumeIndex.className = volumeClass;
                } else if (i.type == 'react-mouseleave') {
                    volumeIndex.className = volumeClass + ' volume-hover';
                }
            } else if (i.type) {
                this.setState({
                    volumePendingEffects: i.type
                })
            }
        }
    },
    volumeRippleEffect(c, i, a) {
        if (a) {
            if (!this.state.volumeDragging) {
                var volumeRipple = document.querySelector('.volume-ripple');
                var volumeClass = volumeRipple.className.replace(' volume-ripple-hover', '');
                if (a.type == 'react-mouseenter') {
                    volumeRipple.className = volumeClass;
                } else if (a.type == 'react-mouseleave') {
                    volumeRipple.className = volumeClass + ' volume-ripple-hover';
                }
            } else if (a.type) {
                this.setState({
                    volumePendingRipples: a.type
                });
            }
        }
    },
    volumeDragStart() {
        this.setState({
            volumeDragging: true
        });
    },
    volumeDragStop() {
        this.setState({
            volumeDragging: false
        });
        if (this.state.volumePendingEffects) {
            this.volumeIndexEffect(null, null, {
                type: this.state.volumePendingEffects
            });
            this.setState({
                volumePendingEffects: ''
            });
        }
        if (this.state.volumePendingRipples) {
            this.volumeRippleEffect(null, null, {
                type: this.state.volumePendingRipples
            });
            this.setState({
                volumePendingRipples: ''
            });
        }
    },
    render() {
        var scrobblerStyles = {
            time: {
                width: this.state.scrobbling || this.state.keepScrobble ? this.state.seekPerc * 100 + '%' : this.state.position * 100 + '%'
            },
            tooltip: {
                marginLeft: '-' + this.state.tooltipHalf + 'px',
                left: this.state.tooltipLeft
            }
        };
        return (

{this.state.humanTime}

                        {
                            this.state.forceTime ? this.state.overTime : this.state.currentTime
                        } / {this.state.totalTime}

                <IconButton onClick={this.handlePausePlay} iconClassName="material-icons" iconStyle={{top: '-5px', left: '-1px'}} className={this.state.rippleEffects ? 'play-toggle' : 'play-toggle no-ripples'}>{this.state.playing ? 'pause' : 'play_arrow'}</IconButton>

                <IconButton onClick={this.handlePrev} iconClassName="material-icons" iconStyle={{top: '-6px'}} className={'prev-button'}>{'skip_previous'}</IconButton>

                <IconButton onClick={this.handleNext} iconClassName="material-icons" iconStyle={{top: '-6px'}} className={'next-button'}>{'skip_next'}</IconButton>

                <IconButton onClick={this.handleMute} iconClassName="material-icons" iconStyle={{color: '#e7e7e7'}} className="volume-button">{this.state.mute ? 'volume_off' : this.state.volume <= 0 ? 'volume_mute' : this.state.volume <= 120 ? 'volume_down' : 'volume_up' }</IconButton>
                <Slider name="volume-slider" ref="volume-slider" defaultValue={this.state.volume} step={1} min={0} max={200} onChange={this.handleVolume} value={this.state.mute ? 0 : this.state.volume} onMouseEnter={this.volumeRippleEffect} onMouseLeave={this.volumeRippleEffect} onDragStart={this.volumeDragStart} onDragStop={this.volumeDragStop} />
                <IconButton onClick={this.handleFullscreen} iconClassName="material-icons" iconStyle={{color: '#e7e7e7', fontSize: '30px', top: '-5px', left: '-1px'}} className="fullscreen-toggle">{this.state.fullscreen ? 'fullscreen_exit' : 'fullscreen'}</IconButton>
                <IconButton onClick={PlayerActions.toggleSubtitles} iconClassName="material-icons" iconStyle={{color: this.state.subtitlesOpen ? '#00acff' : '#e7e7e7', fontSize: '26px', top: '-5px', left: '-1px'}} className="subtitles-toggle" style={{display: 'inline-block'}}>closed_caption</IconButton>

        );
    }
});<commit_msg>Fix References to Volume Slider<commit_after>import React from 'react';
import moment from 'moment';
import _ from 'lodash';
import ls from 'local-storage';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import {
    IconButton, Slider
}
from 'material-ui';
import {
    handleTime
}
from '../utils/time';
import PlayerStore from '../store';
import PlayerActions from '../actions';

export
default React.createClass({

    mixins: [PureRenderMixin],

    getInitialState() {

        var playerState = PlayerStore.getState();

        return {
            fullscreen: playerState.fullscreen,
            uiShown: playerState.uiShown || playerState.playlistOpen || playerState.settingsOpen,
            uiHidden: playerState.uiHidden,

            scrobbling: playerState.scrobbling,
            playing: playerState.playing,
            position: playerState.position,
            buffering: playerState.buffering,
            time: playerState.time,
            length: playerState.length,
            keepScrobble: playerState.keepScrobble,
            seekPerc: playerState.seekPerc,

            currentTime: playerState.currentTime,
            totalTime: playerState.totalTime,

            rippleEffects: playerState.rippleEffects,

            foundSubs: playerState.foundSubs,
            subtitlesOpen: playerState.subtitlesOpen,

            volume: ls('volume'),
            mute: playerState.muted,

            volumeDragging: false,
            volumePendingEffects: '',
            volumePendingRipples: '',

            forceTime: playerState.forceTime,
            overTime: playerState.overTime
        }
    },
    componentWillMount() {
        PlayerStore.listen(this.update);
    },
    componentDidMount() {
        window.addEventListener('mousemove', this.handleGlobalMouseMove);
        window.addEventListener('mouseup', this.handleGlobalMouseUp);

        // assign a class to the volume index pointer
        var volumeIndex = this.refs['volume-slider'].refs['track'].lastChild;
        volumeIndex.className = 'volume-index volume-hover';
        volumeIndex.firstChild.className = 'volume-ripple';
    },
    componentWillUnmount() {
        window.removeEventListener('mousemove', this.handleGlobalMouseMove);
        window.removeEventListener('mouseup', this.handleGlobalMouseUp);
        PlayerStore.unlisten(this.update);
    },
    update() {
        if (this.isMounted()) {

            var playerState = PlayerStore.getState();

            this.setState({
                fullscreen: playerState.fullscreen,
                uiShown: playerState.uiShown || playerState.playlistOpen || playerState.settingsOpen,
                uiHidden: playerState.uiHidden,

                playing: playerState.playing,
                position: playerState.position,
                buffering: playerState.buffering,
                seekable: playerState.seekable,
                time: playerState.time,
                length: playerState.length,
                scrobbling: playerState.scrobbling,
                seekPerc: playerState.seekPerc,

                currentTime: playerState.currentTime,
                totalTime: playerState.totalTime,

                rippleEffects: playerState.rippleEffects,

                foundSubs: playerState.foundSubs,
                subtitlesOpen: playerState.subtitlesOpen,

                volume: ls('volume'),
                mute: playerState.muted,

                forceTime: playerState.forceTime,
                overTime: playerState.overTime,

                keepScrobble: playerState.keepScrobble
            });
        }
    },
    delayScrobbleGUI() {
        _.delay(() => {
            PlayerActions.settingChange({
                keepScrobble: false
            })
        }, 1000)
    },
    handlePausePlay() {
        this.state.playing ? PlayerActions.pause() : PlayerActions.play();
    },
    handleNext() {
        PlayerActions.next();
    },
    handlePrev() {
        PlayerActions.prev();
    },
    handleFullscreen() {
        PlayerActions.toggleFullscreen(!this.state.fullscreen);
    },
    handleScrobblerHover(event) {

        var newState = {};

        var total_time = this.state.length;

        var percent_done = event.pageX / document.body.clientWidth;

        var newTime = total_time * percent_done;
        //        this.refs['scrobbler-handle'].style.left = (percent_done * 100) + '%';
        //console.log(total_time, percent_done + '%', newTime);
        if (this.state.time) {
            this.refs['scrobbler-tooltip'].style.display = 'inline-block';
            if (percent_done <= 0.5) {
                var realPos = Math.floor(window.innerWidth * percent_done) - this.state.tooltipHalf;
            } else {
                var realPos = Math.floor(window.innerWidth * percent_done) + this.state.tooltipHalf;
            }

            var seekTime = handleTime(percent_done * this.state.length, this.state.length);

            if (seekTime.length > 5)
                newState.tooltipHalf = 33;
            else
                newState.tooltipHalf = 24;

            if (realPos < 0) newState.tooltipLeft = newState.tooltipHalf + 'px';
            else if (realPos > window.innerWidth) newState.tooltipLeft = (window.innerWidth - newState.tooltipHalf) + 'px';
            else newState.tooltipLeft = (percent_done * 100) + '%';

            newState.humanTime = seekTime;
        }

        if (this.state.scrobbling) {
            PlayerActions.settingChange({
                seekPerc: percent_done < 0 ? 0 : percent_done > 1 ? 1 : percent_done
            });
        }

        if (Object.keys(newState).length) {
            this.setState(newState);
        }

    },
    handleScrobble(event) {
        if (!this.state.length || !this.state.seekable)
            return;

        PlayerActions.settingChange({
            keepScrobble: true,
            scrobbling: false
        });

        this.setState({
            position: this.state.seekPerc
        });

        this.refs['scrobbler-height'].className = this.refs['scrobbler-height'].className.replace(' scrobbling', '');
        this.delayScrobbleGUI();
        var percent_done = event.pageX / document.body.clientWidth;
        PlayerActions.scrobble(this.state.length * percent_done);
    },
    handleDragStart(event) {

        PlayerActions.scrobbleState(true);

        this.refs['scrobbler-height'].className = this.refs['scrobbler-height'].className + ' scrobbling';

        PlayerActions.settingChange({
            keepScrobble: true
        });
        var percent_done = event.pageX / document.body.clientWidth;
        PlayerActions.settingChange({
            seekPerc: percent_done
        });
        this.delayScrobbleGUI();
    },
    handleDragEnd() {
        this.refs['scrobbler-tooltip'].style.display = 'none';
    },
    handleGlobalMouseMove(event) {
        if (this.state.scrobbling) {
            this.handleScrobblerHover(event);
        }
    },
    handleGlobalMouseUp(event) {
        if (this.state.scrobbling) {
            this.handleScrobble(event);
            this.refs['scrobbler-tooltip'].style.display = 'none';
        }
    },
    handleVolume(event, t) {
        PlayerActions.volume(t);
    },
    handleMute(event) {
        PlayerActions.mute(!this.state.mute);
    },
    volumeIndexEffect(f, b, i) {
        if (i) {
            if (!this.state.volumeDragging) {
                var volumeIndex = this.refs['volume-slider'].refs['track'].lastChild;
                var volumeClass = volumeIndex.className.replace(' volume-hover', '');
                if (i.type == 'react-mouseenter') {
                    volumeIndex.className = volumeClass;
                } else if (i.type == 'react-mouseleave') {
                    volumeIndex.className = volumeClass + ' volume-hover';
                }
            } else if (i.type) {
                this.setState({
                    volumePendingEffects: i.type
                })
            }
        }
    },
    volumeRippleEffect(c, i, a) {
        if (a) {
            if (!this.state.volumeDragging) {
                var volumeRipple = this.refs['volume-slider'].refs['track'].lastChild.firstChild;
                var volumeClass = volumeRipple.className.replace(' volume-ripple-hover', '');
                if (a.type == 'react-mouseenter') {
                    volumeRipple.className = volumeClass;
                } else if (a.type == 'react-mouseleave') {
                    volumeRipple.className = volumeClass + ' volume-ripple-hover';
                }
            } else if (a.type) {
                this.setState({
                    volumePendingRipples: a.type
                });
            }
        }
    },
    volumeDragStart() {
        this.setState({
            volumeDragging: true
        });
    },
    volumeDragStop() {
        this.setState({
            volumeDragging: false
        });
        if (this.state.volumePendingEffects) {
            this.volumeIndexEffect(null, null, {
                type: this.state.volumePendingEffects
            });
            this.setState({
                volumePendingEffects: ''
            });
        }
        if (this.state.volumePendingRipples) {
            this.volumeRippleEffect(null, null, {
                type: this.state.volumePendingRipples
            });
            this.setState({
                volumePendingRipples: ''
            });
        }
    },
    render() {
        var scrobblerStyles = {
            time: {
                width: this.state.scrobbling || this.state.keepScrobble ? this.state.seekPerc * 100 + '%' : this.state.position * 100 + '%'
            },
            tooltip: {
                marginLeft: '-' + this.state.tooltipHalf + 'px',
                left: this.state.tooltipLeft
            }
        };
        return (

{this.state.humanTime}

                        {
                            this.state.forceTime ? this.state.overTime : this.state.currentTime
                        } / {this.state.totalTime}

                <IconButton onClick={this.handlePausePlay} iconClassName="material-icons" iconStyle={{top: '-5px', left: '-1px'}} className={this.state.rippleEffects ? 'play-toggle' : 'play-toggle no-ripples'}>{this.state.playing ? 'pause' : 'play_arrow'}</IconButton>

                <IconButton onClick={this.handlePrev} iconClassName="material-icons" iconStyle={{top: '-6px'}} className={'prev-button'}>{'skip_previous'}</IconButton>

                <IconButton onClick={this.handleNext} iconClassName="material-icons" iconStyle={{top: '-6px'}} className={'next-button'}>{'skip_next'}</IconButton>

                <IconButton onClick={this.handleMute} iconClassName="material-icons" iconStyle={{color: '#e7e7e7'}} className="volume-button">{this.state.mute ? 'volume_off' : this.state.volume <= 0 ? 'volume_mute' : this.state.volume <= 120 ? 'volume_down' : 'volume_up' }</IconButton>
                <Slider name="volume-slider" ref="volume-slider" defaultValue={this.state.volume} step={1} min={0} max={200} onChange={this.handleVolume} value={this.state.mute ? 0 : this.state.volume} onMouseEnter={this.volumeRippleEffect} onMouseLeave={this.volumeRippleEffect} onDragStart={this.volumeDragStart} onDragStop={this.volumeDragStop} />
                <IconButton onClick={this.handleFullscreen} iconClassName="material-icons" iconStyle={{color: '#e7e7e7', fontSize: '30px', top: '-5px', left: '-1px'}} className="fullscreen-toggle">{this.state.fullscreen ? 'fullscreen_exit' : 'fullscreen'}</IconButton>
                <IconButton onClick={PlayerActions.toggleSubtitles} iconClassName="material-icons" iconStyle={{color: this.state.subtitlesOpen ? '#00acff' : '#e7e7e7', fontSize: '26px', top: '-5px', left: '-1px'}} className="subtitles-toggle" style={{display: 'inline-block'}}>closed_caption</IconButton>

        );
    }
});<|endoftext|>


<commit_before>var test = require('tape');

d3 = require("d3");
vistk = require("../build/vistk.js");

test('vistk version should be defined and defined as a string', function (t) {

    t.plan(1);
    t.equal(typeof vistk.version, 'string', vistk.version);

});

test('an empty configuration object returns an object with default values', function (t) {

    t.plan(1);
    var visualization = vistk.viz().params({});
    t.equal(typeof visualization.params(), 'object');

});

test('the same dataset is returned by VisTK', function (t) {

    t.plan(1);
    var data = ['A', 'B', 'C'];
    var visualization = vistk.viz().params({data: data});
    t.equal(visualization.params().new_data, data);

});

test('a dataset with no attribute is augmented with attributes', function (t) {

    t.plan(1);
    var data = ['A', 'B', 'C'];
    var visualization = vistk.viz().params({data: data});

    // Default ids
    t.equal(visualization.params().new_data[0].__id, 0);

});

test('if the dataset is temporal, then only items are returned', function (t) {

    t.plan(2);
    var data = [{id: 1, time: 0}, {id: 1, time: 1}];
    var visualization = vistk.viz().params({data: data});

    t.equal(visualization.params().new_data[0].length, 1);
    t.equal(visualization.params().new_data[0].values.length, 2);

});

test('check if selection and highlight classes are set', function (t) {

    t.plan(2);
    var data = ['A', 'B', 'C'];
    var selection = [data[0]],
    var highlight: [data[0], data[1]],

    var visualization = vistk.viz().params({
        data: data,
        selection: selection,
        highlight: highlight
    });

    // check if internal state of the toolkit matches the cfg
    t.equal(visualization.params().selection, selection);
    t.equal(visualization.params().highlight, highlight);

});

test('check if selection and highlight classes are set', function (t) {

    t.plan(2);
    var data = ['A', 'B', 'C'];

    var items_rect = [{
        marks: [{
          type: "rect";
        }]
    }];

    var items_circle = [{
        marks: [{
          type: "circle";
        }]
    }];

    var visualization = vistk.viz().params({data: data, items: items_rect});
    t.equal(d3.select(visualization.params().container).selectAll('rect')[0].length, data.length);

    visualization.params({data: data, items: items_rect});
    t.equal(d3.select(visualization.params().container).selectAll('circle')[0].length, data.length);

});
<commit_msg>Updating test<commit_after>var test = require('tape');

d3 = require("d3");
vistk = require("../build/vistk.js");

test('vistk version should be defined and defined as a string', function (t) {

    t.plan(1);
    t.equal(typeof vistk.version, 'string', vistk.version);

});

test('an empty configuration object returns an object with default values', function (t) {

    t.plan(1);
    var visualization = vistk.viz().params({});
    t.equal(typeof visualization.params(), 'object');

});

test('the same dataset is returned by VisTK', function (t) {

    t.plan(1);
    var data = ['A', 'B', 'C'];
    var visualization = vistk.viz().params({data: data});
    t.equal(visualization.params().new_data, data);

});

test('a dataset with no attribute is augmented with attributes', function (t) {

    t.plan(1);
    var data = ['A', 'B', 'C'];
    var visualization = vistk.viz().params({data: data});

    // Default ids
    t.equal(visualization.params().new_data[0].__id, 0);

});

test('if the dataset is temporal, then only items are returned', function (t) {

    t.plan(2);
    var data = [{id: 1, time: 0}, {id: 1, time: 1}];
    var visualization = vistk.viz().params({data: data});

    t.equal(visualization.params().new_data[0].length, 1);
    t.equal(visualization.params().new_data[0].values.length, 2);

});

test('check if selection and highlight classes are set', function (t) {

    t.plan(2);
    var data = ['A', 'B', 'C'];
    var selection = [data[0]];
    var highlight = [data[0], data[1]];

    var visualization = vistk.viz().params({
        data: data,
        selection: selection,
        highlight: highlight
    });

    // check if internal state of the toolkit matches the cfg
    t.equal(visualization.params().selection, selection);
    t.equal(visualization.params().highlight, highlight);

});

test('check if selection and highlight classes are set', function (t) {

    t.plan(4);
    var data = ['A', 'B', 'C'];

    var items_rect = [{
        marks: [{
          type: "rect"
        }]
    }];

    var items_circle = [{
        marks: [{
          type: "circle"
        }]
    }];

    // we draw rectangles first
    var visualization = vistk.viz().params({data: data, items: items_rect});
    t.equal(d3.select(visualization.params().container).selectAll('rect')[0].length, data.length);
    t.equal(d3.select(visualization.params().container).selectAll('circle')[0].length, 0);

    // then we replace them by circles
    visualization.params({data: data, items: items_rect});
    t.equal(d3.select(visualization.params().container).selectAll('rect')[0].length, 0);
    t.equal(d3.select(visualization.params().container).selectAll('circle')[0].length, data.length);

});
<|endoftext|>


<commit_before>'use strict';

module.exports = ['UserDetail', '$stateParams', '$mdMedia', 'ContactStatisticTypes', 'UserDetailContacts', 'UserDetailContactings', 'ToolbarService',
    function (UserDetail, $stateParams, $mdMedia, ContactStatisticTypes, UserDetailContacts, UserDetailContactings, ToolbarService) {
        var ctrl = this;

        ctrl.activeNext = {};
        ctrl.contactPreviewEvents = {};
        ctrl.contactingPreviewEvents = {};
        ctrl.$mdMedia = $mdMedia;
        ctrl.UserDetailContacts = UserDetailContacts;
        ctrl.UserDetailContactings = UserDetailContactings;

        ctrl.userDetail = UserDetail.get({userId: $stateParams.userId}, function () {
            ContactStatisticTypes.setStatistic(ctrl.userDetail.contactTypeStatistic);
            ctrl.numberOfGroups = ctrl.userDetail.contactTypeStatistic.length;
            ctrl.userName = ctrl.userDetail.user.forename;
            ToolbarService.setTitle(ctrl.userName);
        });

        ctrl.showContactOverview = function () {
            ctrl.showOverviewContact = true;
            ctrl.showOverviewContacting = false;
            ToolbarService.setTitle(ctrl.userName + "'s Kontakte");
            if (ctrl.contactingPreviewEvents.hasOwnProperty('detailClosed')) {
                ctrl.contactingPreviewEvents.detailClosed();
            }
        };

        ctrl.showContactingOverview = function () {
            ctrl.showOverviewContacting = true;
            ctrl.showOverviewContact = false;
            ToolbarService.setTitle(ctrl.userName + "'s Follower");
            if (ctrl.contactPreviewEvents.hasOwnProperty('detailClosed')) {
                ctrl.contactPreviewEvents.detailClosed();
            }
        };

        ctrl.close = function () {
            ctrl.showOverviewContact = false;
            ctrl.showOverviewContacting = false;
        };

    }];

<commit_msg>Bugfix: Removed contacts and follower description.<commit_after>'use strict';

module.exports = ['UserDetail', '$stateParams', '$mdMedia', 'ContactStatisticTypes', 'UserDetailContacts', 'UserDetailContactings', 'ToolbarService',
    function (UserDetail, $stateParams, $mdMedia, ContactStatisticTypes, UserDetailContacts, UserDetailContactings, ToolbarService) {
        var ctrl = this;

        ctrl.activeNext = {};
        ctrl.contactPreviewEvents = {};
        ctrl.contactingPreviewEvents = {};
        ctrl.$mdMedia = $mdMedia;
        ctrl.UserDetailContacts = UserDetailContacts;
        ctrl.UserDetailContactings = UserDetailContactings;

        ctrl.userDetail = UserDetail.get({userId: $stateParams.userId}, function () {
            ContactStatisticTypes.setStatistic(ctrl.userDetail.contactTypeStatistic);
            ctrl.numberOfGroups = ctrl.userDetail.contactTypeStatistic.length;
            ctrl.userName = ctrl.userDetail.user.forename;
            ToolbarService.setTitle(ctrl.userName);
        });

        ctrl.showContactOverview = function () {
            ctrl.showOverviewContact = true;
            ctrl.showOverviewContacting = false;
            if (ctrl.contactingPreviewEvents.hasOwnProperty('detailClosed')) {
                ctrl.contactingPreviewEvents.detailClosed();
            }
        };

        ctrl.showContactingOverview = function () {
            ctrl.showOverviewContacting = true;
            ctrl.showOverviewContact = false;
            if (ctrl.contactPreviewEvents.hasOwnProperty('detailClosed')) {
                ctrl.contactPreviewEvents.detailClosed();
            }
        };

        ctrl.close = function () {
            ctrl.showOverviewContact = false;
            ctrl.showOverviewContacting = false;
        };

    }];

<|endoftext|>