<commit_before>/* jshint expr: true */
'use strict';

var expect    = require('chai').expect,
    fs        = require('fs'),
    path      = require('path'),
    uncss     = require('./../lib/uncss.js'),
    inspect = require('util').inspect;

/* Read file sync sugar. */
var rfs = function (file) {
    return fs.readFileSync(path.join(__dirname, file), 'utf-8').toString();
};

describe('PhantomJS', function () {

    it('Should process CSS', function (done) {
        uncss(['tests/phantomjs/basic.html'], function (err, output) {
            expect(output).to.include('.evaluated');
            done();
        });
    });

    it('Should exit only when JS evaluation has finished', function (done) {
        this.timeout(5000);
        uncss(['tests/phantomjs/long_wait.html'], function (err, output) {
            expect(output).to.include('.long-wait');
            done();
        });
    });

    it('Should not wait for timeouts by default', function (done) {
        uncss(['tests/phantomjs/timeout.html'], function (err, output) {
            expect(output).to.not.include('.timeout');
            done();
        });
    });

    it('Should respect options.timeout', function (done) {
        this.timeout(10000);
        uncss(['tests/phantomjs/timeout.html'], { timeout : 5000 }, function (err, output) {
            expect(output).to.include('.timeout');
            done();
        });
    });
});
<commit_msg>Fix timeout for Travis<commit_after>/* jshint expr: true */
'use strict';

var expect    = require('chai').expect,
    fs        = require('fs'),
    path      = require('path'),
    uncss     = require('./../lib/uncss.js'),
    inspect = require('util').inspect;

/* Read file sync sugar. */
var rfs = function (file) {
    return fs.readFileSync(path.join(__dirname, file), 'utf-8').toString();
};

describe('PhantomJS', function () {

    it('Should process CSS', function (done) {
        uncss(['tests/phantomjs/basic.html'], function (err, output) {
            expect(output).to.include('.evaluated');
            done();
        });
    });

    it('Should exit only when JS evaluation has finished', function (done) {
        this.timeout(20000);
        uncss(['tests/phantomjs/long_wait.html'], function (err, output) {
            expect(output).to.include('.long-wait');
            done();
        });
    });

    it('Should not wait for timeouts by default', function (done) {
        uncss(['tests/phantomjs/timeout.html'], function (err, output) {
            expect(output).to.not.include('.timeout');
            done();
        });
    });

    it('Should respect options.timeout', function (done) {
        this.timeout(10000);
        uncss(['tests/phantomjs/timeout.html'], { timeout : 5000 }, function (err, output) {
            expect(output).to.include('.timeout');
            done();
        });
    });
});
<|endoftext|>


<commit_before>var nijs = require('../../lib/nijs.js');

exports.pkg = function(args) {
  return args.stdenv().mkDerivation({
    name : "wget-1.13.4",

    src : args.fetchurl({
      url : new nijs.NixURL("mirror://gnu/wget/wget-1.13.4.tar.gz"),
      sha256 : "1kadjg63x1mm741dxdidwsn1rz0f7dkzbq59v0iww87jr45p3ir4"
    }),

    configureFlags : "--with-ssl=openssl",

    buildInputs : [ args.openssl() ],

    meta : {
      description : "GNU Wget, a tool for retrieving files using HTTP, HTTPS, and FTP",
      license : "GPLv3+",
      homepage : new nijs.NixURL("http://www.gnu.org/software/wget")
    }
  });
};
<commit_msg>Updated wget test package to version 1.14<commit_after>var nijs = require('../../lib/nijs.js');

exports.pkg = function(args) {
  return args.stdenv().mkDerivation({
    name : "wget-1.14",

    src : args.fetchurl({
      url : new nijs.NixURL("mirror://gnu/wget/wget-1.14.tar.gz"),
      sha256 : "0sf26vlklxx20fjnj30fx6rijpcyvdl6cjmh6m2bjnvn7a78k9pk"
    }),

    configureFlags : "--with-ssl=openssl",

    buildInputs : [ args.openssl() ],

    meta : {
      description : "GNU Wget, a tool for retrieving files using HTTP, HTTPS, and FTP",
      license : "GPLv3+",
      homepage : new nijs.NixURL("http://www.gnu.org/software/wget")
    }
  });
};
<|endoftext|>


<commit_before>
/**
 * Convenience properties and methods for QUnit testing within two.js
 */

(function() {

  var root = this;
  var QU = root.QUnit || {};
  var TEMP = document.createElement('div');

  var Utils = root.Utils = QU.Utils = {

    /**
     * Add a DOM Element to your current unit test.
     */
    addElemToTest: function(test, elem) {

      var domElement = document.createElement('li');

      if (_.isArray(elem)) {
        _.each(elem, function(el) {
          domElement.appendChild(el);
        });
      } else {
        domElement.appendChild(elem);
      }

      _.delay(function() {
        document.querySelector('#' + test.id + ' ol').appendChild(domElement);
      }, 100);

    },

    /**
     * Add an instance of Two.js to your current unit test.
     */
    addInstanceToTest: function(test, two) {

      var elem;

      if (_.isArray(two)) {
        elem = _.map(two, function(t) {
          return t.renderer.domElement;
        });
      } else {
        elem = two.renderer.domElement;
      }

      Utils.addElemToTest(test, elem);

    },

    get: function(path, callback) {

      var xhr = new XMLHttpRequest();

      xhr.onreadystatechange = function(e) {

        if (xhr.readyState != 4 || xhr.status != 200) {
          return;
        }

        callback(xhr.response);

      };

      xhr.open('GET', path, true);
      xhr.send();

    },

    /**
     * Ajax get request to get blob.
     */
    getImageBlob: function(path, callback) {

      var xhr = new XMLHttpRequest();

      if (window.URL) {
        xhr.responseType = 'blob';
      } else {
        xhr.responseType = 'arraybuffer';
      }

      xhr.onreadystatechange = function(e) {

        if (xhr.readyState != 4 || xhr.status != 200) {
          return;
        }

        if (window.URL) {

          callback(this.response);

        } else {

          // Safari doesn't support responseType blob,
          // so create a blob from arraybuffer
          callback(new Blob([this.response], { "type" : 'image/png' }));

        }

      };

      xhr.open('GET', path, true);
      xhr.send();

    },

    /**
     * Compare a specific instance of two to an image in the context of a
     * specific test.
     */
    compare: function(path, renderer, message, callback) {

      var _this = this;

      QUnit.Utils.getImageBlob(path, function(reference) {

        var data = renderer.domElement.toDataURL('image/png');
        resemble(reference).compareTo(data).onComplete(function(data) {

          var pct = parseFloat(data.misMatchPercentage);

          ok(pct <= 1, message);
          start();

          var img = document.createElement('img');
          img.src = path;
          img.title = 'Reference Image';
          img.width = img.height = 400;

          var domElement = document.createElement('li');
          renderer.domElement.title = 'Computed Image';

          domElement.appendChild(img);
          domElement.appendChild(renderer.domElement);

          _.delay(function() {
            document.querySelector('#' + _this.id + ' ol').appendChild(domElement);
          }, 100);

        });

      });

    },

    textToDOM: function(str) {

      TEMP.innerHTML = str;
      return _.map(TEMP.children, function(child) {
        return child;
      });

    },

    /**
     * Deep equality between an answer, a, and an object in question, q.
     */
    shapeEquals: function(a, q) {

      for (var i in a) {

        var check;

        if (_.isArray(a[i])) {
          check = Utils.shapeEquals(a[i], _.toArray(q[i]));
        } else if (_.isObject(a[i])) {
          check = Utils.shapeEquals(a[i], q[i]);
        } else {
          check = q[i] === a[i];
        }

        if (!check) {
          return false;
        }

      }

      return true;

    }

  };

})();<commit_msg>updated tests to reflect rounding errors<commit_after>
/**
 * Convenience properties and methods for QUnit testing within two.js
 */

(function() {

  var root = this;
  var QU = root.QUnit || {};
  var TEMP = document.createElement('div');
  var Tolerance = 0.001;

  var Utils = root.Utils = QU.Utils = {

    /**
     * Add a DOM Element to your current unit test.
     */
    addElemToTest: function(test, elem) {

      var domElement = document.createElement('li');

      if (_.isArray(elem)) {
        _.each(elem, function(el) {
          domElement.appendChild(el);
        });
      } else {
        domElement.appendChild(elem);
      }

      _.delay(function() {
        document.querySelector('#' + test.id + ' ol').appendChild(domElement);
      }, 100);

    },

    /**
     * Add an instance of Two.js to your current unit test.
     */
    addInstanceToTest: function(test, two) {

      var elem;

      if (_.isArray(two)) {
        elem = _.map(two, function(t) {
          return t.renderer.domElement;
        });
      } else {
        elem = two.renderer.domElement;
      }

      Utils.addElemToTest(test, elem);

    },

    get: function(path, callback) {

      var xhr = new XMLHttpRequest();

      xhr.onreadystatechange = function(e) {

        if (xhr.readyState != 4 || xhr.status != 200) {
          return;
        }

        callback(xhr.response);

      };

      xhr.open('GET', path, true);
      xhr.send();

    },

    /**
     * Ajax get request to get blob.
     */
    getImageBlob: function(path, callback) {

      var xhr = new XMLHttpRequest();

      if (window.URL) {
        xhr.responseType = 'blob';
      } else {
        xhr.responseType = 'arraybuffer';
      }

      xhr.onreadystatechange = function(e) {

        if (xhr.readyState != 4 || xhr.status != 200) {
          return;
        }

        if (window.URL) {

          callback(this.response);

        } else {

          // Safari doesn't support responseType blob,
          // so create a blob from arraybuffer
          callback(new Blob([this.response], { "type" : 'image/png' }));

        }

      };

      xhr.open('GET', path, true);
      xhr.send();

    },

    /**
     * Compare a specific instance of two to an image in the context of a
     * specific test.
     */
    compare: function(path, renderer, message, callback) {

      var _this = this;

      QUnit.Utils.getImageBlob(path, function(reference) {

        var data = renderer.domElement.toDataURL('image/png');
        resemble(reference).compareTo(data).onComplete(function(data) {

          var pct = parseFloat(data.misMatchPercentage);

          ok(pct <= 1, message);
          start();

          var img = document.createElement('img');
          img.src = path;
          img.title = 'Reference Image';
          img.width = img.height = 400;

          var domElement = document.createElement('li');
          renderer.domElement.title = 'Computed Image';

          domElement.appendChild(img);
          domElement.appendChild(renderer.domElement);

          _.delay(function() {
            document.querySelector('#' + _this.id + ' ol').appendChild(domElement);
          }, 100);

        });

      });

    },

    textToDOM: function(str) {

      TEMP.innerHTML = str;
      return _.map(TEMP.children, function(child) {
        return child;
      });

    },

    /**
     * Deep equality between an answer, a, and an object in question, q.
     */
    shapeEquals: function(a, q) {

      for (var i in a) {

        var check, isElse = false;

        if (_.isArray(a[i])) {
          check = Utils.shapeEquals(a[i], _.toArray(q[i]));
        } else if (_.isObject(a[i])) {
          check = Utils.shapeEquals(a[i], q[i]);
        } else if (_.isNumber(a[i])) {
          check = Math.abs(a[i] - q[i]) <= Tolerance; // Fuzzy checking
        } else {
          check = q[i] === a[i];
        }

        if (!check) {
          return false;
        }

      }

      return true;

    }

  };

})();<|endoftext|>


<commit_before>/* Copyright (c) Royal Holloway, University of London | Contact Blake Loring (blake@parsed.uk), Duncan Mitchell (Duncan.Mitchell.2015@rhul.ac.uk), or Johannes Kinder (johannes.kinder@rhul.ac.uk) for details or support | LICENSE.md for license details */

function buildTestList() {
    var testList = [];

    function buildTest(file, expectPaths, expectErrors) {
        testList.push({
            path: file,
            expectPaths: expectPaths,
            expectErrors: expectErrors
        });
    }

    //Core Javascript, no symbex / annotations
    buildTest('core/bools.js', 1, 0);
    buildTest('core/recursion.js', 1, 0);
    buildTest('core/lamda.js', 1, 0);

    //Booleans
    buildTest('bool/hello.js', 2, 0);
    buildTest('bool/basic.js', 4, 1);

    //Pure Symbols
    buildTest('pure/pure_symbol.js', 8, 0)

    //Integers
    buildTest('integers/hello.js', 2, 0);
    buildTest('integers/lt.js', 3, 0);
    buildTest('integers/coerce.js', 2, 0);
    buildTest('integers/mul.js', 2, 0);
    buildTest('integers/breaker.js', 1, 0);
    buildTest('integers/infoflow.js', 17, 0);

    //Fractions
    buildTest('fractions/fraction_one.js', 3, 0);

    buildTest('assert/assert.js', 6, 0);

    buildTest('assumes/basic.js', 2, 0);
    buildTest('assumes/wrapped_assume.js', 2, 0);

    //Loops
    buildTest('loops/loop_alot.js', 12, 0);

    //Named methods
    buildTest('named_method/simple.js', 1, 0);

    //Strings
    buildTest('strings/hello_strings.js', 2, 0);
    buildTest('strings/hello_strings2.js', 3, 0);
    buildTest('strings/hello_strings_concat.js', 2, 0);
    buildTest('strings/hello_strings_concat2.js', 1, 0);
    buildTest('strings/hello_strings_len.js', 2, 0);
    buildTest('strings/strings_concat.js', 2, 0);
    buildTest('strings/warning.js', 4, 0);

    buildTest('regex/test/alternatives/simple.js', 4, 4);
    buildTest('regex/test/alternatives/many.js', 4, 4);
    buildTest('regex/test/alternatives/words.js', 4, 4);
    buildTest('regex/test/alternatives/exhaustive_simple.js', 5, 5);
    buildTest('regex/test/alternatives/multiple_related.js', 7, 7);

    buildTest('regex/test/atoms/simple_one.js', 2, 1);
    buildTest('regex/test/atoms/simple_two.js', 2, 1);
    buildTest('regex/test/atoms/long_example.js', 2, 2);
    buildTest('regex/test/atoms/empty_example.js', 2, 2);
    buildTest('regex/test/atoms/mixed_escaped.js', 3, 3); //TODO: Should this be 2
    buildTest('regex/test/atoms/non_alpha.js', 2, 2);
    buildTest('regex/test/atoms/multiple.js', 6, 6);

    buildTest('regex/test/escaping/hex.js', 5, 4);
    buildTest('regex/test/escaping/unicode.js', 6, 5);
    buildTest('regex/test/escaping/unicode_mode.js', 3, 2);
    buildTest('regex/test/escaping/ranges.js', 8, 8);
    buildTest('regex/test/escaping/negative_ranges.js', 2, 3);
    buildTest('regex/test/escaping/space_class.js', 8, 7);
    buildTest('regex/test/escaping/word.js', 3, 2);
    buildTest('regex/test/escaping/digit.js', 3, 2);

    buildTest('regex/test/star/star.js', 7, 7);
    buildTest('regex/test/star/online.js', 12, 11);
    buildTest('regex/test/star/lazy.js', 7, 7);
    buildTest('regex/test/star/multiple.js', 5, 5);

    buildTest('regex/test/plus/plus.js', 12, 11);
    buildTest('regex/test/plus/lazy.js', 12, 11);
    buildTest('regex/test/plus/online.js', 11, 10);
    buildTest('regex/test/plus/multiple.js', 4, 4);

    buildTest('regex/test/anchors/left.js', 3, 3);
    buildTest('regex/test/anchors/right.js', 3, 3); //TODO: An extra query is generated
    buildTest('regex/test/anchors/none.js', 4, 4);
    buildTest('regex/test/anchors/both.js', 2, 1);

    buildTest('regex/test/assertions/arbitrary_ahead.js', 3, 3);

    buildTest('regex/test/backreferences/closed.js', 2, 2);

    buildTest('regex/search/simple.js', 2, 2);
    buildTest('regex/search/alt.js', 3, 3);
    buildTest('regex/search/not_at_start.js', 3, 3);
    buildTest('regex/search/test_at_start.js', 5, 5);

    /*
    //Regex
    buildTest('regex/primatives/anchors_one.js', 3, 1);
    buildTest('regex/primatives/anchors_two.js', 5, 2);

    buildTest('regex/primatives/simple_one.js', 2, 0);
    buildTest('regex/primatives/simple_two.js', 2, 1);

    buildTest('regex/primatives/klene_plus_one.js', 3, 1);
    buildTest('regex/primatives/klene_plus_two.js', 3, 1);
    buildTest('regex/primatives/klene_plus_three.js', 2, 0);

    buildTest('regex/primatives/kleene_star_two.js', 3, 2);
    buildTest('regex/primatives/kleene_star_three.js', 2, 1);

    buildTest('regex/primatives/primative_rw_github.js', 2, 1);

    //buildTest('regex/test_three_deep.js', 7, 3);

    buildTest('regex/replace_and_length.js', 5, 0);
    buildTest('regex/replace_and_length.js', 3, 0);
    */

    //Async
    buildTest('async/settimeout.js', 3, 1);

    return testList;
}

exports["default"] = buildTestList();
module.exports = exports["default"];
<commit_msg>Wrong way around in test_list<commit_after>/* Copyright (c) Royal Holloway, University of London | Contact Blake Loring (blake@parsed.uk), Duncan Mitchell (Duncan.Mitchell.2015@rhul.ac.uk), or Johannes Kinder (johannes.kinder@rhul.ac.uk) for details or support | LICENSE.md for license details */

function buildTestList() {
    var testList = [];

    function buildTest(file, expectPaths, expectErrors) {
        testList.push({
            path: file,
            expectPaths: expectPaths,
            expectErrors: expectErrors
        });
    }

    //Core Javascript, no symbex / annotations
    buildTest('core/bools.js', 1, 0);
    buildTest('core/recursion.js', 1, 0);
    buildTest('core/lamda.js', 1, 0);

    //Booleans
    buildTest('bool/hello.js', 2, 0);
    buildTest('bool/basic.js', 4, 1);

    //Pure Symbols
    buildTest('pure/pure_symbol.js', 8, 0)

    //Integers
    buildTest('integers/hello.js', 2, 0);
    buildTest('integers/lt.js', 3, 0);
    buildTest('integers/coerce.js', 2, 0);
    buildTest('integers/mul.js', 2, 0);
    buildTest('integers/breaker.js', 1, 0);
    buildTest('integers/infoflow.js', 17, 0);

    //Fractions
    buildTest('fractions/fraction_one.js', 3, 0);

    buildTest('assert/assert.js', 6, 0);

    buildTest('assumes/basic.js', 2, 0);
    buildTest('assumes/wrapped_assume.js', 2, 0);

    //Loops
    buildTest('loops/loop_alot.js', 12, 0);

    //Named methods
    buildTest('named_method/simple.js', 1, 0);

    //Strings
    buildTest('strings/hello_strings.js', 2, 0);
    buildTest('strings/hello_strings2.js', 3, 0);
    buildTest('strings/hello_strings_concat.js', 2, 0);
    buildTest('strings/hello_strings_concat2.js', 1, 0);
    buildTest('strings/hello_strings_len.js', 2, 0);
    buildTest('strings/strings_concat.js', 2, 0);
    buildTest('strings/warning.js', 4, 0);

    buildTest('regex/test/alternatives/simple.js', 4, 4);
    buildTest('regex/test/alternatives/many.js', 4, 4);
    buildTest('regex/test/alternatives/words.js', 4, 4);
    buildTest('regex/test/alternatives/exhaustive_simple.js', 5, 5);
    buildTest('regex/test/alternatives/multiple_related.js', 7, 7);

    buildTest('regex/test/atoms/simple_one.js', 2, 1);
    buildTest('regex/test/atoms/simple_two.js', 2, 1);
    buildTest('regex/test/atoms/long_example.js', 2, 2);
    buildTest('regex/test/atoms/empty_example.js', 2, 2);
    buildTest('regex/test/atoms/mixed_escaped.js', 3, 3); //TODO: Should this be 2
    buildTest('regex/test/atoms/non_alpha.js', 2, 2);
    buildTest('regex/test/atoms/multiple.js', 6, 6);

    buildTest('regex/test/escaping/hex.js', 5, 4);
    buildTest('regex/test/escaping/unicode.js', 6, 5);
    buildTest('regex/test/escaping/unicode_mode.js', 3, 2);
    buildTest('regex/test/escaping/ranges.js', 8, 8);
    buildTest('regex/test/escaping/negative_ranges.js', 3, 2);
    buildTest('regex/test/escaping/space_class.js', 8, 7);
    buildTest('regex/test/escaping/word.js', 3, 2);
    buildTest('regex/test/escaping/digit.js', 3, 2);

    buildTest('regex/test/star/star.js', 7, 7);
    buildTest('regex/test/star/online.js', 12, 11);
    buildTest('regex/test/star/lazy.js', 7, 7);
    buildTest('regex/test/star/multiple.js', 5, 5);

    buildTest('regex/test/plus/plus.js', 12, 11);
    buildTest('regex/test/plus/lazy.js', 12, 11);
    buildTest('regex/test/plus/online.js', 11, 10);
    buildTest('regex/test/plus/multiple.js', 4, 4);

    buildTest('regex/test/anchors/left.js', 3, 3);
    buildTest('regex/test/anchors/right.js', 3, 3); //TODO: An extra query is generated
    buildTest('regex/test/anchors/none.js', 4, 4);
    buildTest('regex/test/anchors/both.js', 2, 1);

    buildTest('regex/test/assertions/arbitrary_ahead.js', 3, 3);

    buildTest('regex/test/backreferences/closed.js', 2, 2);

    buildTest('regex/search/simple.js', 2, 2);
    buildTest('regex/search/alt.js', 3, 3);
    buildTest('regex/search/not_at_start.js', 3, 3);
    buildTest('regex/search/test_at_start.js', 5, 5);

    /*
    //Regex
    buildTest('regex/primatives/anchors_one.js', 3, 1);
    buildTest('regex/primatives/anchors_two.js', 5, 2);

    buildTest('regex/primatives/simple_one.js', 2, 0);
    buildTest('regex/primatives/simple_two.js', 2, 1);

    buildTest('regex/primatives/klene_plus_one.js', 3, 1);
    buildTest('regex/primatives/klene_plus_two.js', 3, 1);
    buildTest('regex/primatives/klene_plus_three.js', 2, 0);

    buildTest('regex/primatives/kleene_star_two.js', 3, 2);
    buildTest('regex/primatives/kleene_star_three.js', 2, 1);

    buildTest('regex/primatives/primative_rw_github.js', 2, 1);

    //buildTest('regex/test_three_deep.js', 7, 3);

    buildTest('regex/replace_and_length.js', 5, 0);
    buildTest('regex/replace_and_length.js', 3, 0);
    */

    //Async
    buildTest('async/settimeout.js', 3, 1);

    return testList;
}

exports["default"] = buildTestList();
module.exports = exports["default"];
<|endoftext|>


<commit_before>const test     = require('ava')
    , { type } = require('../dist/fp-standard')

test('properly reports its arity (is unary)', (t) => {
  t.is(type.length, 1)
})

test('returns "Nil" for undefined', (t) => {
  t.is(type(undefined), 'Nil')
})

test('returns "Nil" for null', (t) => {
  t.is(type(null), 'Nil')
})

test('returns "Boolean" for boolean literals', (t) => {
  t.is(type(true), 'Boolean')
})

test('returns "Boolean" for instances of Boolean', (t) => {
  t.is(type(new Boolean()), 'Boolean') // eslint-disable-line
})

test('returns "String" for string literals', (t) => {
  t.is(type(''), 'String')
})

test('returns "String" for instances of String', (t) => {
  t.is(type(new String()), 'String') // eslint-disable-line
})

test('returns "Number" for number literals', (t) => {
  t.is(type(1), 'Number')
})

test('returns "Number" for instances of Number', (t) => {
  t.is(type(new Number()), 'Number') // eslint-disable-line
})

test('returns "Array" for array literals', (t) => {
  t.is(type([]), 'Array')
})

test('returns "Array" for instances of Array', (t) => {
  t.is(type(new Array()), 'Array') // eslint-disable-line
})

test('returns "Function" for function literals', (t) => {
  t.is(type(() => {}), 'Function')
})

test('returns "Function" for instances of Function', (t) => {
  t.is(type(new Function()), 'Function') // eslint-disable-line
})

test('returns "Function" for function literals', (t) => {
  t.is(type(() => {}), 'Function')
})

test('returns "Object" for object literals', (t) => {
  t.is(type({}), 'Object')
})

test('returns "Object" for instances of Object', (t) => {
  t.is(type(new Object()), 'Object') // eslint-disable-line
})

test('returns "Promise" for instances of Promise', (t) => {
  t.is(type(new Promise(res => res())), 'Promise') // eslint-disable-line
})

<commit_msg>chore(type): remove duplicate function test<commit_after>const test     = require('ava')
    , { type } = require('../dist/fp-standard')

test('properly reports its arity (is unary)', (t) => {
  t.is(type.length, 1)
})

test('returns "Nil" for undefined', (t) => {
  t.is(type(undefined), 'Nil')
})

test('returns "Nil" for null', (t) => {
  t.is(type(null), 'Nil')
})

test('returns "Boolean" for boolean literals', (t) => {
  t.is(type(true), 'Boolean')
})

test('returns "Boolean" for instances of Boolean', (t) => {
  t.is(type(new Boolean()), 'Boolean') // eslint-disable-line
})

test('returns "String" for string literals', (t) => {
  t.is(type(''), 'String')
})

test('returns "String" for instances of String', (t) => {
  t.is(type(new String()), 'String') // eslint-disable-line
})

test('returns "Number" for number literals', (t) => {
  t.is(type(1), 'Number')
})

test('returns "Number" for instances of Number', (t) => {
  t.is(type(new Number()), 'Number') // eslint-disable-line
})

test('returns "Array" for array literals', (t) => {
  t.is(type([]), 'Array')
})

test('returns "Array" for instances of Array', (t) => {
  t.is(type(new Array()), 'Array') // eslint-disable-line
})

test('returns "Function" for function literals', (t) => {
  t.is(type(() => {}), 'Function')
})

test('returns "Function" for instances of Function', (t) => {
  t.is(type(new Function()), 'Function') // eslint-disable-line
})

test('returns "Object" for object literals', (t) => {
  t.is(type({}), 'Object')
})

test('returns "Object" for instances of Object', (t) => {
  t.is(type(new Object()), 'Object') // eslint-disable-line
})

test('returns "Promise" for instances of Promise', (t) => {
  t.is(type(new Promise(res => res())), 'Promise') // eslint-disable-line
})

<|endoftext|>


<commit_before>describe('Xcon', function () {

	"use strict";

	it('should namespace .out and .run methods to console or fall back to xcon', function () {
		var itWorked = (!!window.console.run && !!window.console.out) ||
						(!!window.xcon.run && !!window.xcon.out);
		expect(itWorked).toEqual(true);
	});

});

describe('condition()', function () {

	"use strict";

	// keep this up-to-date with function in source code
	function condition (text) {
        var type = typeof text;
        switch (type) {
            case 'number' || 'boolean' || 'function':
                text = text.toString();
                break;
            case 'object':
                type = text instanceof Array ? 'array' : 'object';
                type = text !== null ? type : 'null';
                text = JSON.stringify(text);
                break;
            case 'undefined':
                text = 'undefined';
                break;
        }
        type = type + ':';
        return {
            "type": type,
            "text": text
        };
    }

	it('should return .text and .type', function () {
		var foundType = condition(Math.PI);
		expect(foundType.type).toEqual('number:');
		expect(foundType.text).toEqual('3.141592653589793');
	});

	it('should stringify objects, arrays, and null values', function () {
		var obj = condition({"hello":"goodbye"}).text,
			arr = condition([1, 2, 3]).text,
			nl = condition(null).text;
		expect(obj).toEqual('{"hello":"goodbye"}');
		expect(arr).toEqual('[1,2,3]');
		expect(nl).toEqual('null');
	});

	it('should correctly identify numbers', function () {
		expect(condition(4).type).toEqual('number:');
		expect(condition(NaN).type).toEqual('number:');
		expect(condition("4").type).not.toEqual('number:');
	});

	it('should correctly identify booleans', function () {
		expect(condition(false).type).toEqual('boolean:');
		expect(condition(true).type).toEqual('boolean:');
		expect(condition('true').type).not.toEqual('boolean:');
	});

	it('should correctly identify strings', function () {
		expect(condition('Steve Perry').type).toEqual('string:');
		expect(condition(['Steve', 123][1]).type).not.toEqual('string:');
	});

	it('should be able to identify undefined', function () {
		expect(condition(undefined).type).toEqual('undefined:');
		expect(condition('undefined').type).not.toEqual('undefined:');
	});

	it('should correctly identify objects', function () {
		expect(condition({"name": "value"}).type).toEqual('object:');
	});

	it('should correctly identify arrays', function () {
		expect(condition(["one", "two", 3]).type).toEqual('array:');
	});

	it('should be able to identify null', function () {
		expect(condition(null).type).toEqual('null:');
		expect(condition(undefined).type).not.toEqual('null:');
		expect(condition('null').type).not.toEqual('null:');
	});

	it('should differentiate between objects, arrays, and null', function () {
		expect(condition([1, 2, 3]).type).not.toEqual('object:');
		expect(condition({"an": "object"}).type).not.toEqual('array:');
		expect(condition(null).type).not.toEqual('object:');
	});

});

describe('console.out()', function () {

	"use strict";

	it('should log the type and output of a given JS statement in the browser console (open console to check output).',
	function () {
		console.out(2);
		console.out('two');
		console.out([1, 1]);
		console.out({"one":"one"});
		console.out(NaN);
		console.out(undefined);
		console.out(null);
		console.out(true);
		expect(console.out('placeholder')).not.toBeDefined();
	});

	it('should log using the user-specified color given any valid css declaration (open console to check output)',
	function () {
		console.out("hex 3-digit: this should be invisible", {"color":"#fff"});
		console.out("color string: this should be blue", {"color":"blue"});
		console.out("hex 6-digit: this should be orange", {"color":"#ff9900"});
		console.out("rgb: this should be pink", {"color":"rgb(255,20,147)"});
		console.out("rgba: this should be really light pink", {"color":"rgba(255,20,147,0.2)"});
		console.out("hsl: this should be green", {"color":"hsl(120, 96%, 34%)"});
		console.out("hsla: this should be really light green", {"color":"hsla(120, 96%, 34%, 0.2)"});
		expect(console.out('placeholder')).not.toBeDefined();
	});

	it('should log function name, function arguments, and error status if given those parameters (open console to check output)',
	function () {
		console.out('error message', {
            "color": 'red',
            "fnName": 'someFunction',
            "fnArgs": '1, 2, 3',
            "error": true
        });
        console.out('success message', {
            "color": 'darkgreen',
            "fnName": 'anotherFunction',
            "fnArgs": '1, 2, 3'
        });
        expect(console.out('error message')).not.toBeDefined();
	});

});

describe('console.run()', function () {

	"use strict";

	var ex;

	beforeEach(function () {
		ex = {
			"example": function (one, two, three) {
				return one + two + three;
			},
			"notAFunction": {
				"not": "function"
			},
			"fakeConstructor": function () {
				this.something = "something";
				return this;
			}
		};
	});

	afterEach(function () {
		ex = null;
	});

	it('should run the given function', function () {
		spyOn(ex, 'example');
		console.run(ex.example);
		expect(ex.example).toHaveBeenCalled();
	});

	it('should call console.out() to print function output', function () {
		spyOn(console, 'out');
		console.run(ex.example);
		expect(console.out).toHaveBeenCalled();
	});

	it('should call console.out() for non-functions as well', function () {
		spyOn(console, 'out');
		console.run(ex.notAFunction);
		expect(console.out).toHaveBeenCalled();
	});

	it('should accept function arguments and run the function with those arguments', function () {
		expect(console.run(ex.example, [1, 1, 1])).toEqual(3);
	});

	it('should accept a context as the third argument and run the function with that context', function () {
		var fakeObj = {};
		fakeObj = console.run(ex.fakeConstructor, [], fakeObj);
		expect(fakeObj.something).toEqual("something");
	});

});<commit_msg>update spec to drop the trailing ":" from condition()<commit_after>describe('Xcon', function () {

	"use strict";

	it('should namespace .out and .run methods to console or fall back to xcon', function () {
		var itWorked = (!!window.console.run && !!window.console.out) ||
						(!!window.xcon.run && !!window.xcon.out);
		expect(itWorked).toEqual(true);
	});

});

describe('condition()', function () {

	"use strict";

	// keep this up-to-date with function in source code
	function condition (text) {
        var type = typeof text;
        switch (type) {
            case 'number' || 'boolean' || 'function':
                text = text.toString();
                break;
            case 'object':
                type = text instanceof Array ? 'array' : 'object';
                type = text !== null ? type : 'null';
                text = JSON.stringify(text);
                break;
            case 'undefined':
                text = 'undefined';
                break;
        }
        type = type;
        return {
            "type": type,
            "text": text
        };
    }

	it('should return .text and .type', function () {
		var foundType = condition(Math.PI);
		expect(foundType.type).toEqual('number');
		expect(foundType.text).toEqual('3.141592653589793');
	});

	it('should stringify objects, arrays, and null values', function () {
		var obj = condition({"hello":"goodbye"}).text,
			arr = condition([1, 2, 3]).text,
			nl = condition(null).text;
		expect(obj).toEqual('{"hello":"goodbye"}');
		expect(arr).toEqual('[1,2,3]');
		expect(nl).toEqual('null');
	});

	it('should correctly identify numbers', function () {
		expect(condition(4).type).toEqual('number');
		expect(condition(NaN).type).toEqual('number');
		expect(condition("4").type).not.toEqual('number');
	});

	it('should correctly identify booleans', function () {
		expect(condition(false).type).toEqual('boolean');
		expect(condition(true).type).toEqual('boolean');
		expect(condition('true').type).not.toEqual('boolean');
	});

	it('should correctly identify strings', function () {
		expect(condition('Steve Perry').type).toEqual('string');
		expect(condition(['Steve', 123][1]).type).not.toEqual('string');
	});

	it('should be able to identify undefined', function () {
		expect(condition(undefined).type).toEqual('undefined');
		expect(condition('undefined').type).not.toEqual('undefined');
	});

	it('should correctly identify objects', function () {
		expect(condition({"name": "value"}).type).toEqual('object');
	});

	it('should correctly identify arrays', function () {
		expect(condition(["one", "two", 3]).type).toEqual('array');
	});

	it('should be able to identify null', function () {
		expect(condition(null).type).toEqual('null');
		expect(condition(undefined).type).not.toEqual('null');
		expect(condition('null').type).not.toEqual('null');
	});

	it('should differentiate between objects, arrays, and null', function () {
		expect(condition([1, 2, 3]).type).not.toEqual('object');
		expect(condition({"an": "object"}).type).not.toEqual('array');
		expect(condition(null).type).not.toEqual('object');
	});

});

describe('console.out()', function () {

	"use strict";

	it('should log the type and output of a given JS statement in the browser console (open console to check output).',
	function () {
		console.out(2);
		console.out('two');
		console.out([1, 1]);
		console.out({"one":"one"});
		console.out(NaN);
		console.out(undefined);
		console.out(null);
		console.out(true);
		expect(console.out('placeholder')).not.toBeDefined();
	});

	it('should log using the user-specified color given any valid css declaration (open console to check output)',
	function () {
		console.out("hex 3-digit: this should be invisible", {"color":"#fff"});
		console.out("color string: this should be blue", {"color":"blue"});
		console.out("hex 6-digit: this should be orange", {"color":"#ff9900"});
		console.out("rgb: this should be pink", {"color":"rgb(255,20,147)"});
		console.out("rgba: this should be really light pink", {"color":"rgba(255,20,147,0.2)"});
		console.out("hsl: this should be green", {"color":"hsl(120, 96%, 34%)"});
		console.out("hsla: this should be really light green", {"color":"hsla(120, 96%, 34%, 0.2)"});
		expect(console.out('placeholder')).not.toBeDefined();
	});

	it('should log function name, function arguments, and error status if given those parameters (open console to check output)',
	function () {
		console.out('error message', {
            "color": 'red',
            "fnName": 'someFunction',
            "fnArgs": '1, 2, 3',
            "error": true
        });
        console.out('success message', {
            "color": 'darkgreen',
            "fnName": 'anotherFunction',
            "fnArgs": '1, 2, 3'
        });
        expect(console.out('error message')).not.toBeDefined();
	});

});

describe('console.run()', function () {

	"use strict";

	var ex;

	beforeEach(function () {
		ex = {
			"example": function (one, two, three) {
				return one + two + three;
			},
			"notAFunction": {
				"not": "function"
			},
			"fakeConstructor": function () {
				this.something = "something";
				return this;
			}
		};
	});

	afterEach(function () {
		ex = null;
	});

	it('should run the given function', function () {
		spyOn(ex, 'example');
		console.run(ex.example);
		expect(ex.example).toHaveBeenCalled();
	});

	it('should call console.out() to print function output', function () {
		spyOn(console, 'out');
		console.run(ex.example);
		expect(console.out).toHaveBeenCalled();
	});

	it('should call console.out() for non-functions as well', function () {
		spyOn(console, 'out');
		console.run(ex.notAFunction);
		expect(console.out).toHaveBeenCalled();
	});

	it('should accept function arguments and run the function with those arguments', function () {
		expect(console.run(ex.example, [1, 1, 1])).toEqual(3);
	});

	it('should accept a context as the third argument and run the function with that context', function () {
		var fakeObj = {};
		fakeObj = console.run(ex.fakeConstructor, [], fakeObj);
		expect(fakeObj.something).toEqual("something");
	});

});<|endoftext|>


<commit_before>
var theRemix = {
	load: function(a) {
	 setInterval( function(){document.body.style.fontSize=window.innerWidth+"px"}, 10)
	 document.getElementsByClassName('header')[0].innerHTML =
	 'The RemixBetter Than Fire' + //The Name
	 'Home' + //Home Page
	 'Music' + //Music Page
	 'Settings' //Settings Page
	 if (a == 2) {
	 document.getElementById('pausePlay').onclick = function() {
	  if (this.attributes.paused.value == 'true') { // If the player is paused (not playing)
	    this.attributes.paused.value = 'false';
		this.src = 'images/stop.png';
	    document.getElementById('audio').play();
	   } else { //If the player is not paused (playing)
	    this.attributes.paused.value = 'true';
		this.src = 'images/play.png';
	    document.getElementById('audio').pause();
	   }
	  }
	  for (i = 0; i < document.getElementsByClassName('track').length; i++) {
	   document.getElementsByClassName('track')[i].id = 'track#' + Number(i + 1);
	   document.getElementsByClassName('track')[i].onclick = function() {
	    document.getElementById('audio').src = 'music/' + this.attributes.url.value;
		document.getElementById('pausePlay').src = 'images/stop.png';
		document.getElementById('pausePlay').attributes.paused.value = 'false';
	   }
	   document.getElementById('trackNumber').innerHTML = i + 1;
	  }
	 }
	},
}<commit_msg>Update tRemix.js<commit_after>
var theRemix = {
	load: function(a) {
	 setInterval( function(){document.body.style.fontSize=window.innerWidth+"px"}, 10)
	 document.getElementsByClassName('header')[0].innerHTML =
	 'The RemixBetter Than Fire' + //The Name
	 'Home' + //Home Page
	 'Music' + //Music Page
	 'Settings' //Settings Page
	 if (a == 2) {
	 document.getElementById('pausePlay').onclick = function() {
	  if (this.attributes.paused.value == 'true') { // If the player is paused (not playing)
	    this.attributes.paused.value = 'false';
		this.src = 'images/stop.png';
	    document.getElementById('audio').play();
	   } else { //If the player is not paused (playing)
	    this.attributes.paused.value = 'true';
		this.src = 'images/play.png';
	    document.getElementById('audio').pause();
	   }
	  }
	  for (i = 0; i < document.getElementsByClassName('track').length; i++) {
	   document.getElementsByClassName('track')[i].id = 'track#' + Number(i + 1);
	   document.getElementsByClassName('track')[i].onclick = function() {
	    document.getElementById('audio').src = 'music/' + this.attributes.url.value;
		document.getElementById('pausePlay').src = 'images/stop.png';
		document.getElementById('pausePlay').attributes.paused.value = 'false';
	   }
	   document.getElementById('trackNumber').innerHTML = i + 1;
	  }
	 }
	},
}
<|endoftext|>


<commit_before>import path from 'path';
import crypto from 'crypto';
import Promise from 'bluebird';

// Copied from html-webpack-plugin
function resolvePublicPath(compilation, filename, publicPath) {
  let resolvedPublicPath;
  if (typeof publicPath === 'undefined') {
    /* istanbul ignore else */
    resolvedPublicPath = typeof compilation.options.output.publicPath !== 'undefined'
      ? compilation.options.output.publicPath
      : path.relative(path.dirname(filename), '.'); // TODO: How to test this? I haven't written this logic, unsure what it does
  } else {
    resolvedPublicPath = publicPath;
  }

  if (resolvedPublicPath.length && resolvedPublicPath.substr(-1, 1) !== '/') {
    resolvedPublicPath = `${resolvedPublicPath}/`;
  }
  return resolvedPublicPath;
}

function addFileToAssets(compilation, htmlPluginData, { filepath, typeOfAsset = 'js', includeSourcemap = true, hash = false, publicPath }) {
  if (!filepath) {
    const error = new Error('No filename defined');
    compilation.errors.push(error);
    return Promise.reject(error);
  }

  return htmlPluginData.plugin.addFileToAssets(filepath, compilation)
    .then(addedFilename => {
      let suffix = '';
      if (hash) {
        const md5 = crypto.createHash('md5');
        md5.update(compilation.assets[addedFilename].source());
        suffix = `?${md5.digest('hex').substr(0, 20)}`;
      }

      // TODO: No need to call this if `publicPath` is provided
      const resolvedPublicPath = resolvePublicPath(compilation, addedFilename, publicPath);
      const resolvedPath = `${resolvedPublicPath}${addedFilename}${suffix}`;

      htmlPluginData.assets[typeOfAsset].unshift(resolvedPath);

      return resolvedPath;
    })
    .then(() => {
      if (includeSourcemap) {
        return htmlPluginData.plugin.addFileToAssets(`${filepath}.map`, compilation);
      }
      return null;
    });
}

// Visible for testing
export function addAllAssetsToCompilation(assets, compilation, htmlPluginData, callback) {
  return Promise.mapSeries(assets, asset => addFileToAssets(compilation, htmlPluginData, asset))
    .then(() => callback(null, htmlPluginData))
    .catch(e => callback(e, htmlPluginData));
}

export default class AddAssetHtmlPlugin {
  constructor(assets = []) {
    this.assets = Array.isArray(assets) ? assets.slice().reverse() : [assets];
  }

  /* istanbul ignore next: this would be integration tests */
  apply(compiler) {
    compiler.plugin('compilation', compilation => {
      compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, callback) => {
        addAllAssetsToCompilation(this.assets, compilation, htmlPluginData, callback);
      });
    });
  }
}
<commit_msg>Don't call `resolvePublicPath` if `publicPath` is provided<commit_after>import path from 'path';
import crypto from 'crypto';
import Promise from 'bluebird';

function ensureTrailingSlash(string) {
  if (string.length && string.substr(-1, 1) !== '/') {
    return `${string}/`;
  }

  return string;
}

// Copied from html-webpack-plugin
function resolvePublicPath(compilation, filename) {
  /* istanbul ignore else */
  const publicPath = typeof compilation.options.output.publicPath !== 'undefined'
      ? compilation.options.output.publicPath
      : path.relative(path.dirname(filename), '.'); // TODO: How to test this? I haven't written this logic, unsure what it does

  return ensureTrailingSlash(publicPath);
}

function addFileToAssets(compilation, htmlPluginData, { filepath, typeOfAsset = 'js', includeSourcemap = true, hash = false, publicPath }) {
  if (!filepath) {
    const error = new Error('No filename defined');
    compilation.errors.push(error);
    return Promise.reject(error);
  }

  return htmlPluginData.plugin.addFileToAssets(filepath, compilation)
    .then(addedFilename => {
      let suffix = '';
      if (hash) {
        const md5 = crypto.createHash('md5');
        md5.update(compilation.assets[addedFilename].source());
        suffix = `?${md5.digest('hex').substr(0, 20)}`;
      }

      const resolvedPublicPath = typeof publicPath === 'undefined' ?
        resolvePublicPath(compilation, addedFilename) :
        ensureTrailingSlash(publicPath);
      const resolvedPath = `${resolvedPublicPath}${addedFilename}${suffix}`;

      htmlPluginData.assets[typeOfAsset].unshift(resolvedPath);

      return resolvedPath;
    })
    .then(() => {
      if (includeSourcemap) {
        return htmlPluginData.plugin.addFileToAssets(`${filepath}.map`, compilation);
      }
      return null;
    });
}

// Visible for testing
export function addAllAssetsToCompilation(assets, compilation, htmlPluginData, callback) {
  return Promise.mapSeries(assets, asset => addFileToAssets(compilation, htmlPluginData, asset))
    .then(() => callback(null, htmlPluginData))
    .catch(e => callback(e, htmlPluginData));
}

export default class AddAssetHtmlPlugin {
  constructor(assets = []) {
    this.assets = Array.isArray(assets) ? assets.slice().reverse() : [assets];
  }

  /* istanbul ignore next: this would be integration tests */
  apply(compiler) {
    compiler.plugin('compilation', compilation => {
      compilation.plugin('html-webpack-plugin-before-html-generation', (htmlPluginData, callback) => {
        addAllAssetsToCompilation(this.assets, compilation, htmlPluginData, callback);
      });
    });
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import { elem, mod } from 'ember-cli-bem/mixins/bem';

const {
  HTMLBars: { makeBoundHelper },
} = Ember;

export default makeBoundHelper(function(params, hash) {
  const { blockName } = hash
  const [ elemName ] = params;

  if (!blockName) {
    throw Error(`blockName is required for 'elem' helper`);
  }

  const elemClassName = elem(blockName, elemName);

  const modNames = Object.keys(hash).filter((key) => key !== 'blockName');
  const modClassNames = modNames.map((modName) => {
    const modValue = hash[modName];
    return mod(elemClassName, { modName, modValue });
  });

  return [elemClassName, ...modClassNames].filter(Boolean).join(' ');
});
<commit_msg>Added a variable for blockName key in elem helper.<commit_after>import Ember from 'ember';
import { elem, mod } from 'ember-cli-bem/mixins/bem';

const {
  HTMLBars: { makeBoundHelper },
} = Ember;

const BLOCK_KEY = 'blockName';

export default makeBoundHelper(function(params, hash) {
  const blockName = hash[BLOCK_KEY];
  const [ elemName ] = params;

  if (!blockName) {
    throw Error(`${BLOCK_KEY} is required for 'elem' helper`);
  }

  const elemClassName = elem(blockName, elemName);

  const modNames = Object.keys(hash).filter((key) => key !== BLOCK_KEY);
  const modClassNames = modNames.map((modName) => {
    const modValue = hash[modName];
    return mod(elemClassName, { modName, modValue });
  });

  return [elemClassName, ...modClassNames].filter(Boolean).join(' ');
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import createFormatCache from '../format-cache/memoizer';

var forEach   = Ember.EnumerableUtils.forEach;
var alias     = Ember.computed.alias;
var makeArray = Ember.makeArray;
var get       = Ember.get;

function assertIsDate (date, errMsg) {
	Ember.assert(errMsg, isFinite(date));
}

export default Ember.Controller.extend(Ember.Evented, {
	locales:           null,
	defaultLocales:    null,
	getDateTimeFormat: null,
	getRelativeFormat: null,
	getMessageFormat:  null,
	getNumberFormat:   null,

	setupMemoizers: Ember.on('init', function () {
		this.setProperties({
			getDateTimeFormat: createFormatCache(Intl.DateTimeFormat),
			getRelativeFormat: createFormatCache(IntlRelativeFormat),
			getNumberFormat:   createFormatCache(Intl.NumberFormat),
			getMessageFormat:  createFormatCache(IntlMessageFormat)
		});
	}),

	current: Ember.computed('locales', 'defaultLocales', function () {
		var locales         = makeArray(get(this, 'locales'));
		var defaultLocales  = makeArray(get(this, 'defaultLocales'));

		defaultLocales = defaultLocales.filter(function (locale) {
			return !locales.contains(locale);
		});

		return locales.concat(defaultLocales);
	}).readOnly(),

	formats: Ember.computed(function () {
		var formats = this.container.resolver('formats:main');

		if (!formats) {
			Ember.Logger.warn('No `formats:main` module found.  Did you forget to export it?');
			return {};
		}

		return formats;
	}).readOnly(),

	messages: Ember.computed('current', function () {
		var locales  = get(this, 'current');
		var messages = {};

		if (!Ember.isEmpty(locales)) {
			locales.forEach(function (localeKey) {
				var locale = this.lookupMessage(localeKey) || this.lookupMessage(localeKey.split('-')[0]);

				for (var key in locale) {
					if (locale.hasOwnProperty(key) && !messages.hasOwnProperty(key)) {
						messages[key] = Ember.$.extend(true, messages[key], locale[key]);
					}
				}
			}, this);
		}

		return messages;
	}).readOnly(),

	localeChanged: Ember.observer('current', function () {
		Ember.run.once(this, this.notifyLocaleChanged);
	}),

	notifyLocaleChanged: function () {
		this.trigger('localesChanged');
	},

	lookupMessage: function (localeName) {
		Ember.assert('The locale name specific to lookupMessage must be a string.', typeof localeName === 'string');

		localeName = localeName.toLowerCase();

		var locale = this.container.resolver('locale:' + localeName);

		if (locale) {
			return locale.messages || {};
		}

		return {};
	},

	formatRelative: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatRelative()');

		return this._format('relative', date, options);
	},

	formatMessage: function (message, values, options) {
		// When `message` is a function, assume it's an IntlMessageFormat
		// instance's `format()` method passed by reference, and call it. This
		// is possible because its `this` will be pre-bound to the instance.
		if (typeof message === 'function') {
			return message(values);
		}

		options = options || {};

		var locales = makeArray(options.locales);

		var formats = options.formats || get(this, 'formats');

		if (Ember.isEmpty(locales)) {
			locales = get(this, 'current');
		}

		if (typeof message === 'string') {
			message = this.getMessageFormat(message, locales, formats);
		}

		return message.format(values);
	},

	formatTime: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatTime()');

		return this._format('time', date, options);
	},

	formatDate: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatDate()');

	  return this._format('date', date, options);
	},

	formatNumber: function (num, options) {
		return this._format('number', num, options);
	},

	_format: function (type, value, options) {
		options = options || {};

		var locales = makeArray(options.locales);
		var formats = get(this, 'formats');

		if (Ember.isEmpty(locales)) {
			locales = get(this, 'current');
		}

		if (typeof options.formats === 'string') {
			options = get(this, 'formats.' + type + '.' + options.formats);
		} else if (typeof options.formats === 'object') {
			options = options.formats;
		}

		if (typeof options === 'string') {
			try {
				options = formats[type][options];
			} catch (e) {
				options = undefined;
			} finally {
				if (options === undefined) {
					throw new ReferenceError('No ' + type + ' format named: ' + options);
				}
			}
		}

		switch (type) {
			case 'date':
			case 'time':
				return this.getDateTimeFormat(locales, options).format(value);
			case 'number':
				return this.getNumberFormat(locales, options).format(value);
			case 'relative':
				return this.getRelativeFormat(locales, options).format(value);
			default:
				throw new Error('Unrecognized simple format type: ' + type);
		}
	}
});
<commit_msg>Removing unused variables<commit_after>import Ember from 'ember';
import createFormatCache from '../format-cache/memoizer';

var makeArray = Ember.makeArray;
var get       = Ember.get;

function assertIsDate (date, errMsg) {
	Ember.assert(errMsg, isFinite(date));
}

export default Ember.Controller.extend(Ember.Evented, {
	locales:           null,
	defaultLocales:    null,
	getDateTimeFormat: null,
	getRelativeFormat: null,
	getMessageFormat:  null,
	getNumberFormat:   null,

	setupMemoizers: Ember.on('init', function () {
		this.setProperties({
			getDateTimeFormat: createFormatCache(Intl.DateTimeFormat),
			getRelativeFormat: createFormatCache(IntlRelativeFormat),
			getNumberFormat:   createFormatCache(Intl.NumberFormat),
			getMessageFormat:  createFormatCache(IntlMessageFormat)
		});
	}),

	current: Ember.computed('locales', 'defaultLocales', function () {
		var locales         = makeArray(get(this, 'locales'));
		var defaultLocales  = makeArray(get(this, 'defaultLocales'));

		defaultLocales = defaultLocales.filter(function (locale) {
			return !locales.contains(locale);
		});

		return locales.concat(defaultLocales);
	}).readOnly(),

	formats: Ember.computed(function () {
		var formats = this.container.resolver('formats:main');

		if (!formats) {
			Ember.Logger.warn('No `formats:main` module found.  Did you forget to export it?');
			return {};
		}

		return formats;
	}).readOnly(),

	messages: Ember.computed('current', function () {
		var locales  = get(this, 'current');
		var messages = {};

		if (!Ember.isEmpty(locales)) {
			locales.forEach(function (localeKey) {
				var locale = this.lookupMessage(localeKey) || this.lookupMessage(localeKey.split('-')[0]);

				for (var key in locale) {
					if (locale.hasOwnProperty(key) && !messages.hasOwnProperty(key)) {
						messages[key] = Ember.$.extend(true, messages[key], locale[key]);
					}
				}
			}, this);
		}

		return messages;
	}).readOnly(),

	localeChanged: Ember.observer('current', function () {
		Ember.run.once(this, this.notifyLocaleChanged);
	}),

	notifyLocaleChanged: function () {
		this.trigger('localesChanged');
	},

	lookupMessage: function (localeName) {
		Ember.assert('The locale name specific to lookupMessage must be a string.', typeof localeName === 'string');

		localeName = localeName.toLowerCase();

		var locale = this.container.resolver('locale:' + localeName);

		if (locale) {
			return locale.messages || {};
		}

		return {};
	},

	formatRelative: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatRelative()');

		return this._format('relative', date, options);
	},

	formatMessage: function (message, values, options) {
		// When `message` is a function, assume it's an IntlMessageFormat
		// instance's `format()` method passed by reference, and call it. This
		// is possible because its `this` will be pre-bound to the instance.
		if (typeof message === 'function') {
			return message(values);
		}

		options = options || {};

		var locales = makeArray(options.locales);

		var formats = options.formats || get(this, 'formats');

		if (Ember.isEmpty(locales)) {
			locales = get(this, 'current');
		}

		if (typeof message === 'string') {
			message = this.getMessageFormat(message, locales, formats);
		}

		return message.format(values);
	},

	formatTime: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatTime()');

		return this._format('time', date, options);
	},

	formatDate: function (date, options) {
		date = new Date(date);
		assertIsDate(date, 'A date or timestamp must be provided to formatDate()');

	  return this._format('date', date, options);
	},

	formatNumber: function (num, options) {
		return this._format('number', num, options);
	},

	_format: function (type, value, options) {
		options = options || {};

		var locales = makeArray(options.locales);
		var formats = get(this, 'formats');

		if (Ember.isEmpty(locales)) {
			locales = get(this, 'current');
		}

		if (typeof options.formats === 'string') {
			options = get(this, 'formats.' + type + '.' + options.formats);
		} else if (typeof options.formats === 'object') {
			options = options.formats;
		}

		if (typeof options === 'string') {
			try {
				options = formats[type][options];
			} catch (e) {
				options = undefined;
			} finally {
				if (options === undefined) {
					throw new ReferenceError('No ' + type + ' format named: ' + options);
				}
			}
		}

		switch (type) {
			case 'date':
			case 'time':
				return this.getDateTimeFormat(locales, options).format(value);
			case 'number':
				return this.getNumberFormat(locales, options).format(value);
			case 'relative':
				return this.getRelativeFormat(locales, options).format(value);
			default:
				throw new Error('Unrecognized simple format type: ' + type);
		}
	}
});
<|endoftext|>


<commit_before>var MODES = {
    normal: Symbol('normal'),
    insert: Symbol('insert'),
};
var mode = MODES.normal;

let emit = x => self.port.emit('fvim:event', x);

var CMDS = {
    scrollTop: () => window.scrollTo(0, 0),
    scrollBottom: () => window.scrollTo(0, window.scrollMaxY),
    scrollDown: () => window.scrollByLines(1),
    scrollUp: () => window.scrollByLines(-1),
    scrollLeft: () => window.scollBy(-10, 0),
    scrollRight: () => window.scollBy(10, 0),
    yankUrl: () => emit({ cmd: 'yankUrl', param: window.location.href }),
    newTab: () => emit({ cmd: 'newTab' }),
    openInNewTab: () => emit({ cmd: 'openInNewTab' }),
    setInsertMode: () => mode = MODES.insert,
};
let fG = (ev) => {
    if (mode === MODES.insert) {
        if (ev.key === "Escape") {
            mode = MODES.normal;
        } else {
            return;
        }
    }
    ev.preventDefault();
    ev.stopPropagation();
    switch (ev.key) {
    case 'g': CMDS.scrollTop();
        break;
    case 'G': CMDS.scrollBottom();
        break;
    case 'j': CMDS.scrollDown();
        break;
    case 'k': CMDS.scrollUp();
        break;
    case 'h': CMDS.scrollLeft();
        break;
    case 'l': CMDS.scrollRight();
        break;
    case 'y': CMDS.yankUrl();
        break;
    case 't': CMDS.newTab();
        break;
    case 'P': CMDS.openInNewTab();
        break;
    case 'i': CMDS.setInsertMode();
        break;
    }
};
addEventListener('keydown', fG, true);
<commit_msg>add atuo mode with some insert detection<commit_after>var MODES = {
    normal: Symbol('normal'),
    insert: Symbol('insert'),
    auto: Symbol('auto'),
};
var mode = MODES.auto;

let emit = x => self.port.emit('fvim:event', x);

let editable = x =>
    x.tagName === 'INPUT' ||
    x.tagName === 'TEXTAREA' ||
    x.getAttribute('g_editable') === 'true';

var CMDS = {
    scrollTop: () => window.scrollTo(0, 0),
    scrollBottom: () => window.scrollTo(0, window.scrollMaxY),
    scrollDown: () => window.scrollByLines(1),
    scrollUp: () => window.scrollByLines(-1),
    scrollLeft: () => window.scollBy(-10, 0),
    scrollRight: () => window.scollBy(10, 0),
    yankUrl: () => emit({ cmd: 'yankUrl', param: window.location.href }),
    newTab: () => emit({ cmd: 'newTab' }),
    openInNewTab: () => emit({ cmd: 'openInNewTab' }),
    setInsertMode: () => mode = MODES.insert,
};
let fG = (ev) => {
    if (ev.key === "Escape") {
        mode = mode === MODES.insert ? MODES.normal : MODES.auto;
    }
    switch (mode) {
    case MODES.insert: return;
    case MODES.auto: if (editable(ev.target)) return;
    }
    ev.preventDefault();
    ev.stopPropagation();
    switch (ev.key) {
    case 'g': CMDS.scrollTop();
        break;
    case 'G': CMDS.scrollBottom();
        break;
    case 'j': CMDS.scrollDown();
        break;
    case 'k': CMDS.scrollUp();
        break;
    case 'h': CMDS.scrollLeft();
        break;
    case 'l': CMDS.scrollRight();
        break;
    case 'y': CMDS.yankUrl();
        break;
    case 't': CMDS.newTab();
        break;
    case 'P': CMDS.openInNewTab();
        break;
    case 'i': CMDS.setInsertMode();
        break;
    }
};
addEventListener('keydown', fG, true);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* jshint moz: true */
// Graph Visualization (one of 3 views: graph, clock, and list). This is way
// too heavyweight for mobile right now.

// Visualization of tracking data interconnections

(function (visualizations, global) {
"use strict";

// Bunch of utilities related to UI elements.
const graphNodeRadius = {
  "graph": 12
};

// The graph is an emitter with a default size.
var graph = new Emitter();
visualizations.graph = graph;
graph.name = "graph";
var width = 750,
  height = 750;
var force, vis;
var edges, nodes;

// There are three phases for a visualization life-cycle:
// init does initialization and receives the existing set of connections
// connection notifies of a new connection that matches existing filter
// remove lets the visualization know it is about to be switched out so it can clean up
graph.on('init', onInit);
// graph.on('connection', onConnection);
graph.on('remove', onRemove);
graph.on('reset', onReset);

/* for Highlighting and Colouring -------------------- */

var highlight = {
  visited: true,
  neverVisited: true,
  connections: true,
  cookies: true,
  watched: true,
  blocked: true
};

// Restart the simulation. This is only called when there's a new connection we
// haven't seen before.
function onUpdate() {
  // new nodes, reheat graph simulation
  if (force) {
    // console.log('restarting graph due to update');
    force.stop();
    force.nodes(filteredAggregate.nodes);
    force.links(filteredAggregate.edges);
    force.start();
    updateGraph();
    colourHighlightNodes(highlight);
  } else {
    console.log('the force is not with us');
  }
}

function onInit() {
  // console.log('graph::onInit()');
  // console.log('initializing graph from %s connections', filteredAggregate.nodes.length);
  // Handles all of the panning and scaling.
  vis = d3.select(vizcanvas);
  // A D3 visualization has a two main components, data-shaping, and setting up the D3 callbacks
  // This binds our data to the D3 visualization and sets up the callbacks
  initGraph();
  aggregate.on('update', onUpdate);
  // Differenct visualizations may have different viewBoxes, so make sure we use the right one
  vizcanvas.setAttribute('viewBox', [0, 0, width, height].join(' '));
  // console.log('graph::onInit end');
  document.querySelector(".filter-display").classList.remove("hidden");
}

function onRemove() {
  // var startTime = Date.now();
  if (force) {
    force.stop();
    force = null;
  }
  resetCanvas();
  document.querySelector(".filter-display").classList.add("hidden");
  // console.log('it took %s ms to remove graph view', Date.now() - startTime);
}

function onReset() {
  onRemove();
  aggregate.emit('load', global.allConnections);
}

// UTILITIES FOR CREATING POLYGONS

function point(angle, size) {
  return [Math.round(Math.cos(angle) * size), -Math.round(Math.sin(angle) * size)];
}

function polygon(points, size, debug) {
  var increment = Math.PI * 2 / points;
  var angles = [],
    i;
  for (i = 0; i < points; i++) {
    angles.push(i * increment + Math.PI / 2); // add 90 degrees so first point is up
  }
  return angles.map(function (angle) {
    return point(angle, size);
  });
}

function polygonAsString(points, size) {
  var poly = polygon(points, size);
  return poly.map(function (pair) {
    return pair.join(',');
  }).join(' ');
}

// ACCESSOR FUNCTIONS

// function scaleNode(node){ return 'translate(' + node.x + ',' + node.y + ') scale(' + (1 + .05 * node.weight) + ')'; }
function visited(node) {
  return node.nodeType === 'site' || node.nodeType === 'both';
}

function notVisited(node) {
  return node.nodeType === 'thirdparty';
}
// function timestamp(node){ return node.lastAccess.toISOString(); }
// function nodeHighlight(node){ return ( node.visitedCount > 0 ) ? highlight.highlightVisited : highlight.highlightNeverVisited; }
// function sourceX(edge){ return edge.source.x; }
// function sourceY(edge){ return edge.source.y; }
// function targetX(edge){ return edge.target.x; }
// function targetY(edge){ return edge.target.y; }
// function edgeCookie(edge){ return edge.cookieCount > 0; }
// function edgeHighlight(edge){ return highlight.connections; }
// function edgeColoured(edge){ return edge.cookieCount > 0 && highlight.cookies; }
function nodeName(node) {
  if (node) {
    return node.name;
  }
  return undefined;
}

function siteHasPref(site, pref) {
  return (userSettings.hasOwnProperty(site) &&
    userSettings[site].contains(pref));
}

function watchSite(node) {
  return siteHasPref(node.name, "watch");
}

function blockSite(node) {
  return siteHasPref(node.name, "block");
}

// SET UP D3 HANDLERS

var ticking = false;

function charge(d) {
  return -(500 + d.weight * 25);
}

function colourHighlightNodes(highlight) {
  var i;
  var watchedSites = document.querySelectorAll(".watched");
  var blockedSites = document.querySelectorAll(".blocked");
  if (highlight.watched) {
    for (i = 0; i < watchedSites.length; i++) {
      watchedSites[i].classList.add("watchedSites");
    }
  } else {
    for (i = 0; i < watchedSites.length; i++) {
      watchedSites[i].classList.remove("watchedSites");
    }
  }
  if (highlight.blocked) {
    for (i = 0; i < blockedSites.length; i++) {
      blockedSites[i].classList.add("blockedSites");
    }
  } else {
    for (i = 0; i < blockedSites.length; i++) {
      blockedSites[i].classList.remove("blockedSites");
    }
  }
}

function initGraph() {
  // Initialize D3 layout and bind data
  // console.log('initGraph()');
  force = d3.layout.force()
    .nodes(filteredAggregate.nodes)
    .links(filteredAggregate.edges)
    .charge(charge)
    .size([width, height])
    .start();
  updateGraph();
  colourHighlightNodes(highlight);

  // update method
  var lastUpdate, lastTick;
  lastUpdate = lastTick = Date.now();
  var draws = [];
  var ticks = 0;
  const second = 1000;
  const minute = 60 * second;
  force.on('tick', function ontick(evt) {
    // find a way to report how often tick() is called, and how long it takes to run
    // without trying to console.log() every 5 milliseconds...
    if (ticking) {
      console.log('overlapping tick!');
      return;
    }
    ticking = true;
    var nextTick = Date.now();
    ticks++;
    lastTick = nextTick;
    if ((lastTick - lastUpdate) > second) {
      // console.log('%s ticks per second, each draw takes %s milliseconds', ticks, Math.floor(d3.mean(draws)));
      lastUpdate = lastTick;
      draws = [];
      ticks = 0;
    }
    edges.each(function (d, i) {
      // `this` is the DOM node
      this.setAttribute('x1', d.source.x);
      this.setAttribute('y1', d.source.y);
      this.setAttribute('x2', d.target.x);
      this.setAttribute('y2', d.target.y);
      if (d.cookieCount) {
        this.classList.add('cookieYes');
      } else {
        this.classList.remove('cookieYes');
      }
      if (highlight.connections) {
        this.classList.add('highlighted');
      } else {
        this.classList.remove('highlighted');
      }
      if (d.cookieCount && highlight.cookies) {
        this.classList.add('coloured');
      } else {
        this.classList.remove('coloured');
      }
    });
    nodes.each(function (d, i) {
      // `this` is the DOM node
      this.setAttribute('transform', 'translate(' + d.x + ',' + d.y + ') scale(' + (1 + 0.05 * d.weight) + ')');
      this.setAttribute('data-timestamp', d.lastAccess.toISOString());
      if (d.nodeType === 'site' || d.nodeType === 'both') {
        this.classList.add('visitedYes');
        this.classList.remove('visitedNo');
      } else {
        this.classList.add('visitedNo');
        this.classList.remove('visitedYes');
      }
      if ((d.nodeType === 'site' || d.nodeType === 'both') && highlight.visited) {
        this.classList.add('highlighted');
      } else if ((d.nodeType === 'thirdparty') && highlight.neverVisited) {
        this.classList.add('highlighted');
      } else {
        this.classList.remove('highlighted');
      }
    });
    var endDraw = Date.now();
    draws.push(endDraw - lastTick);
    nodes.call(force.drag);

    ticking = false;
  });
}

function updateGraph() {
  // console.log('updateGraph()');
  // Data binding for links
  edges = vis.selectAll('.edge')
    .data(filteredAggregate.edges, nodeName);

  edges.enter().insert('line', ':first-child')
    .classed('edge', true);

  edges.exit()
    .remove();

  nodes = vis.selectAll('.node')
    .data(filteredAggregate.nodes, nodeName);

  nodes.enter().append('g')
    .classed('visitedYes', visited)
    .classed('visitedNo', notVisited)
    .classed("watched", watchSite)
    .classed("blocked", blockSite)
    .call(addShape)
    .attr('data-name', nodeName)
    .on('mouseenter', tooltip.show)
    .on('mouseleave', tooltip.hide)
    .classed('node', true);

  nodes.exit()
    .remove();

}

function addFavicon(selection) {
  selection.append("svg:image")
    .attr("class", "favicon")
    .attr("width", "16") // move these to the favicon class in css
  .attr("height", "16")
    .attr("x", "-8") // offset to make 16x16 favicon appear centered
  .attr("y", "-8")
    .attr("xlink:href", function (node) {
      return 'http://' + node.name + '/favicon.ico';
    });
}

function addCircle(selection) {
  selection
    .append('circle')
    .attr('cx', 0)
    .attr('cy', 0)
    .attr('r', graphNodeRadius.graph)
    .classed('site', true);
}

function addShape(selection) {
  selection.filter('.visitedYes').call(addCircle).call(addFavicon);
  selection.filter('.visitedNo').call(addTriangle).call(addFavicon);
}

function addTriangle(selection) {
  selection
    .append('polygon')
    .attr('points', polygonAsString(3, 20))
    .attr('data-name', function (node) {
      return node.name;
    });
}

// FIXME: Move this out of visualization so multiple visualizations can use it.
function resetCanvas() {
  // You will still need to remove timer events
  var parent = vizcanvas.parentNode;
  var newcanvas = vizcanvas.cloneNode(false);
  var vizcanvasDefs = document.querySelector(".vizcanvas defs").cloneNode(true);
  newcanvas.appendChild(vizcanvasDefs);
  parent.replaceChild(newcanvas, vizcanvas);
  vizcanvas = newcanvas;
  aggregate.off('update', onUpdate);
}

var graphLegend = document.querySelector(".graph-footer");

function legendBtnClickHandler(legendElm) {
  legendElm.querySelector(".legend-controls").addEventListener("click", function (event) {
    if (event.target.mozMatchesSelector(".btn, .btn *")) {
      var btn = event.target;
      while (btn.mozMatchesSelector('.btn *')) {
        btn = btn.parentElement;
      }
      btn.classList.toggle("active");
    }
  });
}

legendBtnClickHandler(graphLegend);

graphLegend.querySelector(".legend-toggle-visited").addEventListener("click", function (event) {
  var visited = document.querySelectorAll(".visitedYes");
  toggleVizElements(visited, "highlighted");
  highlight.visited = !highlight.visited;
});

graphLegend.querySelector(".legend-toggle-never-visited").addEventListener("click", function (event) {
  var neverVisited = document.querySelectorAll(".visitedNo");
  toggleVizElements(neverVisited, "highlighted");
  highlight.neverVisited = !highlight.neverVisited;
});

graphLegend.querySelector(".legend-toggle-connections").addEventListener("click", function (event) {
  var cookiesConnections = document.querySelectorAll(".edge");
  toggleVizElements(cookiesConnections, "highlighted");
  highlight.connections = !highlight.connections;
});

graphLegend.querySelector(".legend-toggle-cookies").addEventListener("click", function (event) {
  var cookiesConnections = document.querySelectorAll(".cookieYes");
  toggleVizElements(cookiesConnections, "coloured");
  highlight.cookies = !highlight.cookies;
});

graphLegend.querySelector(".legend-toggle-watched").addEventListener("click", function (event) {
  highlight.watched = !highlight.watched;
  colourHighlightNodes(highlight);
});

graphLegend.querySelector(".legend-toggle-blocked").addEventListener("click", function (event) {
  highlight.blocked = !highlight.blocked;
  colourHighlightNodes(highlight);
});

graphLegend.querySelector(".legend-toggle").addEventListener("click", function (event) {
  toggleLegendSection(event.target, graphLegend);
});

})(visualizations, this);
<commit_msg>Fix broken graph update (fix #586)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* jshint moz: true */
// Graph Visualization (one of 3 views: graph, clock, and list). This is way
// too heavyweight for mobile right now.

// Visualization of tracking data interconnections

(function (visualizations, global) {
"use strict";

// Bunch of utilities related to UI elements.
const graphNodeRadius = {
  "graph": 12
};

// The graph is an emitter with a default size.
var graph = new Emitter();
visualizations.graph = graph;
graph.name = "graph";
var width = 750,
  height = 750;
var force, vis;
var edges, nodes;

// There are three phases for a visualization life-cycle:
// init does initialization and receives the existing set of connections
// connection notifies of a new connection that matches existing filter
// remove lets the visualization know it is about to be switched out so it can clean up
graph.on('init', onInit);
// graph.on('connection', onConnection);
graph.on('remove', onRemove);
graph.on('reset', onReset);

/* for Highlighting and Colouring -------------------- */

var highlight = {
  visited: true,
  neverVisited: true,
  connections: true,
  cookies: true,
  watched: true,
  blocked: true
};

// Restart the simulation. This is only called when there's a new connection we
// haven't seen before.
function onUpdate() {
  // new nodes, reheat graph simulation
  if (force) {
    // console.log('restarting graph due to update');
    force.stop();
    force.nodes(filteredAggregate.nodes);
    force.links(filteredAggregate.edges);
    force.start();
    updateGraph();
    colourHighlightNodes(highlight);
  } else {
    console.log('the force is not with us');
  }
}

function onInit() {
  // console.log('graph::onInit()');
  // console.log('initializing graph from %s connections', filteredAggregate.nodes.length);
  // Handles all of the panning and scaling.
  vis = d3.select(vizcanvas);
  // A D3 visualization has a two main components, data-shaping, and setting up the D3 callbacks
  // This binds our data to the D3 visualization and sets up the callbacks
  initGraph();
  aggregate.on('update', onUpdate);
  // Differenct visualizations may have different viewBoxes, so make sure we use the right one
  vizcanvas.setAttribute('viewBox', [0, 0, width, height].join(' '));
  // console.log('graph::onInit end');
  document.querySelector(".filter-display").classList.remove("hidden");
}

function onRemove() {
  // var startTime = Date.now();
  if (force) {
    force.stop();
    force = null;
  }
  resetCanvas();
  document.querySelector(".filter-display").classList.add("hidden");
  // console.log('it took %s ms to remove graph view', Date.now() - startTime);
}

function onReset() {
  onRemove();
  aggregate.emit('load', global.allConnections);
}

// UTILITIES FOR CREATING POLYGONS

function point(angle, size) {
  return [Math.round(Math.cos(angle) * size), -Math.round(Math.sin(angle) * size)];
}

function polygon(points, size, debug) {
  var increment = Math.PI * 2 / points;
  var angles = [],
    i;
  for (i = 0; i < points; i++) {
    angles.push(i * increment + Math.PI / 2); // add 90 degrees so first point is up
  }
  return angles.map(function (angle) {
    return point(angle, size);
  });
}

function polygonAsString(points, size) {
  var poly = polygon(points, size);
  return poly.map(function (pair) {
    return pair.join(',');
  }).join(' ');
}

// ACCESSOR FUNCTIONS

// function scaleNode(node){ return 'translate(' + node.x + ',' + node.y + ') scale(' + (1 + .05 * node.weight) + ')'; }
function visited(node) {
  return node.nodeType === 'site' || node.nodeType === 'both';
}

function notVisited(node) {
  return node.nodeType === 'thirdparty';
}
// function timestamp(node){ return node.lastAccess.toISOString(); }
// function nodeHighlight(node){ return ( node.visitedCount > 0 ) ? highlight.highlightVisited : highlight.highlightNeverVisited; }
// function sourceX(edge){ return edge.source.x; }
// function sourceY(edge){ return edge.source.y; }
// function targetX(edge){ return edge.target.x; }
// function targetY(edge){ return edge.target.y; }
// function edgeCookie(edge){ return edge.cookieCount > 0; }
// function edgeHighlight(edge){ return highlight.connections; }
// function edgeColoured(edge){ return edge.cookieCount > 0 && highlight.cookies; }
function nodeName(node) {
  if (node) {
    return node.name;
  }
  return undefined;
}

function siteHasPref(site, pref) {
  return (userSettings.hasOwnProperty(site) &&
    userSettings[site].contains(pref));
}

function watchSite(node) {
  return siteHasPref(node.name, "watch");
}

function blockSite(node) {
  return siteHasPref(node.name, "block");
}

// SET UP D3 HANDLERS

var ticking = false;

function charge(d) {
  return -(500 + d.weight * 25);
}

function colourHighlightNodes(highlight) {
  var i;
  var watchedSites = document.querySelectorAll(".watched");
  var blockedSites = document.querySelectorAll(".blocked");
  if (highlight.watched) {
    for (i = 0; i < watchedSites.length; i++) {
      watchedSites[i].classList.add("watchedSites");
    }
  } else {
    for (i = 0; i < watchedSites.length; i++) {
      watchedSites[i].classList.remove("watchedSites");
    }
  }
  if (highlight.blocked) {
    for (i = 0; i < blockedSites.length; i++) {
      blockedSites[i].classList.add("blockedSites");
    }
  } else {
    for (i = 0; i < blockedSites.length; i++) {
      blockedSites[i].classList.remove("blockedSites");
    }
  }
}

function initGraph() {
  // Initialize D3 layout and bind data
  // console.log('initGraph()');
  force = d3.layout.force()
    .nodes(filteredAggregate.nodes)
    .links(filteredAggregate.edges)
    .charge(charge)
    .size([width, height])
    .start();
  updateGraph();
  colourHighlightNodes(highlight);

  // update method
  var lastUpdate, lastTick;
  lastUpdate = lastTick = Date.now();
  var draws = [];
  var ticks = 0;
  const second = 1000;
  const minute = 60 * second;
  force.on('tick', function ontick(evt) {
    // find a way to report how often tick() is called, and how long it takes to run
    // without trying to console.log() every 5 milliseconds...
    if (ticking) {
      console.log('overlapping tick!');
      return;
    }
    ticking = true;
    var nextTick = Date.now();
    ticks++;
    lastTick = nextTick;
    if ((lastTick - lastUpdate) > second) {
      // console.log('%s ticks per second, each draw takes %s milliseconds', ticks, Math.floor(d3.mean(draws)));
      lastUpdate = lastTick;
      draws = [];
      ticks = 0;
    }
    edges.each(function (d, i) {
      // `this` is the DOM node
      this.setAttribute('x1', d.source.x);
      this.setAttribute('y1', d.source.y);
      this.setAttribute('x2', d.target.x);
      this.setAttribute('y2', d.target.y);
      if (d.cookieCount) {
        this.classList.add('cookieYes');
      } else {
        this.classList.remove('cookieYes');
      }
      if (highlight.connections) {
        this.classList.add('highlighted');
      } else {
        this.classList.remove('highlighted');
      }
      if (d.cookieCount && highlight.cookies) {
        this.classList.add('coloured');
      } else {
        this.classList.remove('coloured');
      }
    });
    nodes.each(function (d, i) {
      // `this` is the DOM node
      this.setAttribute('transform', 'translate(' + d.x + ',' + d.y + ') scale(' + (1 + 0.05 * d.weight) + ')');
      this.setAttribute('data-timestamp', d.lastAccess.toISOString());
      if (d.nodeType === 'site' || d.nodeType === 'both') {
        this.classList.add('visitedYes');
        this.classList.remove('visitedNo');
      } else {
        this.classList.add('visitedNo');
        this.classList.remove('visitedYes');
      }
      if ((d.nodeType === 'site' || d.nodeType === 'both') && highlight.visited) {
        this.classList.add('highlighted');
      } else if ((d.nodeType === 'thirdparty') && highlight.neverVisited) {
        this.classList.add('highlighted');
      } else {
        this.classList.remove('highlighted');
      }
    });
    var endDraw = Date.now();
    draws.push(endDraw - lastTick);
    if (force) {
      nodes.call(force.drag);
    }

    ticking = false;
  });
}

function updateGraph() {
  // console.log('updateGraph()');
  // Data binding for links
  edges = vis.selectAll('.edge')
    .data(filteredAggregate.edges, nodeName);

  edges.enter().insert('line', ':first-child')
    .classed('edge', true);

  edges.exit()
    .remove();

  nodes = vis.selectAll('.node')
    .data(filteredAggregate.nodes, nodeName);

  nodes.enter().append('g')
    .classed('visitedYes', visited)
    .classed('visitedNo', notVisited)
    .classed("watched", watchSite)
    .classed("blocked", blockSite)
    .call(addShape)
    .attr('data-name', nodeName)
    .on('mouseenter', tooltip.show)
    .on('mouseleave', tooltip.hide)
    .classed('node', true);

  nodes.exit()
    .remove();

}

function addFavicon(selection) {
  selection.append("svg:image")
    .attr("class", "favicon")
    .attr("width", "16") // move these to the favicon class in css
  .attr("height", "16")
    .attr("x", "-8") // offset to make 16x16 favicon appear centered
  .attr("y", "-8")
    .attr("xlink:href", function (node) {
      return 'http://' + node.name + '/favicon.ico';
    });
}

function addCircle(selection) {
  selection
    .append('circle')
    .attr('cx', 0)
    .attr('cy', 0)
    .attr('r', graphNodeRadius.graph)
    .classed('site', true);
}

function addShape(selection) {
  selection.filter('.visitedYes').call(addCircle).call(addFavicon);
  selection.filter('.visitedNo').call(addTriangle).call(addFavicon);
}

function addTriangle(selection) {
  selection
    .append('polygon')
    .attr('points', polygonAsString(3, 20))
    .attr('data-name', function (node) {
      return node.name;
    });
}

// FIXME: Move this out of visualization so multiple visualizations can use it.
function resetCanvas() {
  // You will still need to remove timer events
  var parent = vizcanvas.parentNode;
  var newcanvas = vizcanvas.cloneNode(false);
  var vizcanvasDefs = document.querySelector(".vizcanvas defs").cloneNode(true);
  newcanvas.appendChild(vizcanvasDefs);
  parent.replaceChild(newcanvas, vizcanvas);
  vizcanvas = newcanvas;
  aggregate.off('update', onUpdate);
}

var graphLegend = document.querySelector(".graph-footer");

function legendBtnClickHandler(legendElm) {
  legendElm.querySelector(".legend-controls").addEventListener("click", function (event) {
    if (event.target.mozMatchesSelector(".btn, .btn *")) {
      var btn = event.target;
      while (btn.mozMatchesSelector('.btn *')) {
        btn = btn.parentElement;
      }
      btn.classList.toggle("active");
    }
  });
}

legendBtnClickHandler(graphLegend);

graphLegend.querySelector(".legend-toggle-visited").addEventListener("click", function (event) {
  var visited = document.querySelectorAll(".visitedYes");
  toggleVizElements(visited, "highlighted");
  highlight.visited = !highlight.visited;
});

graphLegend.querySelector(".legend-toggle-never-visited").addEventListener("click", function (event) {
  var neverVisited = document.querySelectorAll(".visitedNo");
  toggleVizElements(neverVisited, "highlighted");
  highlight.neverVisited = !highlight.neverVisited;
});

graphLegend.querySelector(".legend-toggle-connections").addEventListener("click", function (event) {
  var cookiesConnections = document.querySelectorAll(".edge");
  toggleVizElements(cookiesConnections, "highlighted");
  highlight.connections = !highlight.connections;
});

graphLegend.querySelector(".legend-toggle-cookies").addEventListener("click", function (event) {
  var cookiesConnections = document.querySelectorAll(".cookieYes");
  toggleVizElements(cookiesConnections, "coloured");
  highlight.cookies = !highlight.cookies;
});

graphLegend.querySelector(".legend-toggle-watched").addEventListener("click", function (event) {
  highlight.watched = !highlight.watched;
  colourHighlightNodes(highlight);
});

graphLegend.querySelector(".legend-toggle-blocked").addEventListener("click", function (event) {
  highlight.blocked = !highlight.blocked;
  colourHighlightNodes(highlight);
});

graphLegend.querySelector(".legend-toggle").addEventListener("click", function (event) {
  toggleLegendSection(event.target, graphLegend);
});

})(visualizations, this);
<|endoftext|>


<commit_before>'use strict'

module.exports = [
  {
    user: '@michal.brasna',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@jan.pavlovsky',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@ottokovarik',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@radim',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@tomas.pokorny',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@radek.carda',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@zdenek.cejka',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@mafo',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  }
]
<commit_msg>Add few more people<commit_after>'use strict'

module.exports = [
  {
    user: '@michal.brasna',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@jan.pavlovsky',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@ottokovarik',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@radim',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@tomas.pokorny',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@radek.carda',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@zdenek.cejka',
    services: ['peters', 'pub', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@mafo',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@martin.kadlec',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  },
  {
    user: '@adamsobotka',
    services: ['pub', 'tankovna', 'lokal-hamburk']
  }
]
<|endoftext|>


<commit_before>//
// Renato Mangini
// http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
// http://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers
//

function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
<commit_msg>using Uint8Array instead of Uint16Array<commit_after>//
// Renato Mangini
// http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
// http://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers
//
// Edited by Rodolphe Breard
//  - Using Uint8Array instead of Uint16Array
//

function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint8Array(buf));
}

function str2ab(str) {
    var buf = new ArrayBuffer(str.length);
    var bufView = new Uint8Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
<|endoftext|>


<commit_before>"use strict";

function $(loc) {
	loc = String(loc);
	var els = document.querySelectorAll(loc);
	return els.length > 0 ? els : els[0];
}

window.addEventListener("load", addStructure);
window.addEventListener("load", addAnchors);
window.addEventListener("load", addToc);
window.addEventListener("load", paginate);
window.addEventListener("load", insertHeader);
window.addEventListener("load", insertFooter);
window.addEventListener("load", populateHeaderYs);
window.addEventListener("load", populateTocEls);
window.addEventListener("scroll", trackHeaders);
window.addEventListener("scroll", moveToc);

function addStructure() {}

/**
 * Function that parses through the current page, and adds
 * anchors on the h1-h6 tags for TOC navigation
 */
function addAnchors() {
	var whitelist = "abcdefghijklmnopqrstuvwxyz0123456789 ";
	function sanitise(s) {
		if (!s)
			return;
		s = s.trim().toLowerCase();
		s = Array.prototype.filter.call(s, function(c) { return whitelist.indexOf(c) >= 0 }).join("");
		return s.replace(/\s/g, "_")
	}
	var hs = $("h1, h2, h3, h4, h5, h6");
	for (var i=0; i< hs.length; i++) {
		hs[i].id = sanitise(hs[i].textContent);
	}
}

/**
 * Add the table of contents to the DOM.
 */
function addToc() {
	var toc = document.createElement("nav");
	toc.id = "toc";
	toc.innerHTML = "
Table of Contents
";
	var hs = $("h1, h2, h3, h4, h5, h6");
	for (var i=0; i< hs.length; i++) {
		var level = hs[i].tagName.substring(1);
		if (level == 1)
			continue;
		toc.innerHTML += "" + hs[i].textContent + ""
	}
	document.body.insertBefore(toc, document.body.firstChild);
}

/**
 * Retrieve the current page, without an extension
 * @returns string "index" | "intro" | etc.
 */
function getCurrentPage() {
  var paths = location.href.split('/');
  return paths[paths.length-1].split('.')[0];
}

/**
 * Adds a pagination nav to the page
 */
function paginate() {
	var prev = document.querySelector("link[rel=prev]");
	var next = document.querySelector("link[rel=next]");
	var nav = document.createElement("nav");
	nav.id = "pagination";
	if (prev)
		nav.innerHTML = "" + prev.title + "";
	if (next)
		nav.innerHTML += "" + next.title + "";
	if (prev || next)
		document.body.appendChild(nav);
}

/**
 * Listener function that will put the header into the DOM as the first child in
 */
function insertHeader() {
	var header = document.createElement("header");
	header.innerHTML = "
Selenium Documentation
";

  if (getCurrentPage() != 'index')
    header.innerHTML += "back to index";

	document.body.insertBefore(header, document.body.firstChild);
}

/**
 * Listener function that will put the footer into the DOM as the last child in
 */
// TODO(ato): Warning, this is unsafe.
function insertFooter() {
	var footer = document.createElement("footer");
	var path = window.location.pathname;
	if (path === "/docs" || path === "/docs/")
		path = "/docs/index.html";
	var file = path.substring(path.lastIndexOf("/") + 1);

	footer.innerHTML = "
" +
		"
" +
		"
" +
		"
© 2013-" + new Date().getFullYear() + ", Software Freedom Conservancy." +
		"
Last updated " + document.lastModified +
		"
" +
		"
" +
		"
Report a bug" +
		"
Edit" +
		"
" +
		"
";

	document.body.appendChild(footer);
}

var hs = [];
var headerYs = {};
var curHeader = null;
var tocEls = {};

/**
 * Function that stores the `y` coords of each html header
 */
function populateHeaderYs() {
	var hdrs = $("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]");
	for (var i=0; i< hdrs.length; i++) {
		hs.push(hdrs[i]);
		headerYs[hdrs[i].offsetTop] = hdrs[i].id;
	};
}

/**
 * Function that populates the elements within the Table of Contents floaty
 */
function populateTocEls() {
	var els = $("nav#toc > a");
	for (var i=0; i< els.length; i++) {
		var anchor = els[i].href.substring(els[i].href.indexOf("#"));
		tocEls[anchor] = els[i];
	}
}

/**
 * Listener function that observes the html headers, and will determine whether they have disappeared
 * @param ev the scroll event
 */
function trackHeaders(ev) {
	var pageY = ev.pageY;
	var cur = hs[0].id;
	var gone = Object.keys(headerYs).filter(function(y, h) { return y <= pageY });
	if (gone.length > 0) {
		var curY = gone[gone.length - 1];
		cur = headerYs[curY];
	}
	updateToc(cur);
}

/**
 * Update the table of contents with where the user is on the page
 * @param id the id of the header element
 */
function updateToc(id) {
	if (curHeader == id) {
		return;
	}
	Object.keys(tocEls).map(function(id) { tocEls[id].classList.remove("current") });
	var sel = "#" + id;
	if (!(sel in tocEls))
		return;
	curHeader = tocEls[sel];
	curHeader.classList.add("current");
}

/**
 * Listener event that moves the table of contents with the user's viewport
 * @param ev the scroll event
 */
function moveToc(ev) {
	var toc = $("nav#toc")[0];
	var firstEl = $("nav + h1")[0];
	var firstElSt = firstEl.getBoundingClientRect();
	var offset = document.body.classList.contains("front") ? 300 : 200;

	var firstElRealTop = firstElSt.bottom - (firstElSt.height - offset);
	if (firstElRealTop - 50 < 0) {
		toc.style.top = "50px";
	} else {
		toc.style.top = firstElSt.y + offset + "px";
	}
}
<commit_msg>Added logo<commit_after>"use strict";

function $(loc) {
	loc = String(loc);
	var els = document.querySelectorAll(loc);
	return els.length > 0 ? els : els[0];
}

window.addEventListener("load", addStructure);
window.addEventListener("load", addAnchors);
window.addEventListener("load", addToc);
window.addEventListener("load", paginate);
window.addEventListener("load", insertHeader);
window.addEventListener("load", insertFooter);
window.addEventListener("load", populateHeaderYs);
window.addEventListener("load", populateTocEls);
window.addEventListener("scroll", trackHeaders);
window.addEventListener("scroll", moveToc);

function addStructure() {}

/**
 * Function that parses through the current page, and adds
 * anchors on the h1-h6 tags for TOC navigation
 */
function addAnchors() {
	var whitelist = "abcdefghijklmnopqrstuvwxyz0123456789 ";
	function sanitise(s) {
		if (!s)
			return;
		s = s.trim().toLowerCase();
		s = Array.prototype.filter.call(s, function(c) { return whitelist.indexOf(c) >= 0 }).join("");
		return s.replace(/\s/g, "_")
	}
	var hs = $("h1, h2, h3, h4, h5, h6");
	for (var i=0; i< hs.length; i++) {
		hs[i].id = sanitise(hs[i].textContent);
	}
}

/**
 * Add the table of contents to the DOM.
 */
function addToc() {
	var toc = document.createElement("nav");
	toc.id = "toc";
	toc.innerHTML = "
Table of Contents
";
	var hs = $("h1, h2, h3, h4, h5, h6");
	for (var i=0; i< hs.length; i++) {
		var level = hs[i].tagName.substring(1);
		if (level == 1)
			continue;
		toc.innerHTML += "" + hs[i].textContent + ""
	}
	document.body.insertBefore(toc, document.body.firstChild);
}

/**
 * Retrieve the current page, without an extension
 * @returns string "index" | "intro" | etc.
 */
function getCurrentPage() {
  var paths = location.href.split('/');
  return paths[paths.length-1].split('.')[0];
}

/**
 * Adds a pagination nav to the page
 */
function paginate() {
	var prev = document.querySelector("link[rel=prev]");
	var next = document.querySelector("link[rel=next]");
	var nav = document.createElement("nav");
	nav.id = "pagination";
	if (prev)
		nav.innerHTML = "" + prev.title + "";
	if (next)
		nav.innerHTML += "" + next.title + "";
	if (prev || next)
		document.body.appendChild(nav);
}

/**
 * Listener function that will put the header into the DOM as the first child in
 */
function insertHeader() {
	var header = document.createElement("header");
	header.innerHTML = "
Selenium Documentation
";

  if (getCurrentPage() != 'index')
    header.innerHTML += "back to index";

	document.body.insertBefore(header, document.body.firstChild);
}

/**
 * Listener function that will put the footer into the DOM as the last child in
 */
// TODO(ato): Warning, this is unsafe.
function insertFooter() {
	var footer = document.createElement("footer");
	var path = window.location.pathname;
	if (path === "/docs" || path === "/docs/")
		path = "/docs/index.html";
	var file = path.substring(path.lastIndexOf("/") + 1);

	footer.innerHTML = "
" +
		"
" +
		"
" +
		"
© 2013-" + new Date().getFullYear() + ", Software Freedom Conservancy." +
		"
Last updated " + document.lastModified +
		"
" +
		"
" +
		"
Report a bug" +
		"
Edit" +
		"
" +
		"
";

	document.body.appendChild(footer);
}

var hs = [];
var headerYs = {};
var curHeader = null;
var tocEls = {};

/**
 * Function that stores the `y` coords of each html header
 */
function populateHeaderYs() {
	var hdrs = $("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]");
	for (var i=0; i< hdrs.length; i++) {
		hs.push(hdrs[i]);
		headerYs[hdrs[i].offsetTop] = hdrs[i].id;
	};
}

/**
 * Function that populates the elements within the Table of Contents floaty
 */
function populateTocEls() {
	var els = $("nav#toc > a");
	for (var i=0; i< els.length; i++) {
		var anchor = els[i].href.substring(els[i].href.indexOf("#"));
		tocEls[anchor] = els[i];
	}
}

/**
 * Listener function that observes the html headers, and will determine whether they have disappeared
 * @param ev the scroll event
 */
function trackHeaders(ev) {
	var pageY = ev.pageY;
	var cur = hs[0].id;
	var gone = Object.keys(headerYs).filter(function(y, h) { return y <= pageY });
	if (gone.length > 0) {
		var curY = gone[gone.length - 1];
		cur = headerYs[curY];
	}
	updateToc(cur);
}

/**
 * Update the table of contents with where the user is on the page
 * @param id the id of the header element
 */
function updateToc(id) {
	if (curHeader == id) {
		return;
	}
	Object.keys(tocEls).map(function(id) { tocEls[id].classList.remove("current") });
	var sel = "#" + id;
	if (!(sel in tocEls))
		return;
	curHeader = tocEls[sel];
	curHeader.classList.add("current");
}

/**
 * Listener event that moves the table of contents with the user's viewport
 * @param ev the scroll event
 */
function moveToc(ev) {
	var toc = $("nav#toc")[0];
	var firstEl = $("nav + h1")[0];
	var firstElSt = firstEl.getBoundingClientRect();
	var offset = document.body.classList.contains("front") ? 300 : 200;

	var firstElRealTop = firstElSt.bottom - (firstElSt.height - offset);
	if (firstElRealTop - 50 < 0) {
		toc.style.top = "50px";
	} else {
		toc.style.top = firstElSt.y + offset + "px";
	}
}
<|endoftext|>