<commit_before>/*jslint unparam: true */
/*global $, document, window, request */
var CMS = {};

CMS.grid = function () {
	"use strict";
	var initGridFilter,
		initGridOrder,
		initGridOperation;

	initGridFilter = function () {

		var stoptyping;
		$('table.grid').on('keyup', "th > div.field > .field", function (event) {
			if (event.which === 27) {
				return;
			}
			var field = $(this);
			var fieldName = $(this).attr('name');
			clearTimeout(stoptyping);
			stoptyping = setTimeout(function () {
				field.change();
			}, 500);
		});

		$('table.grid').on('change', 'th > div.field > .field', function () {
			var field = $(this).attr('name'),
				value = $(this).val(),
				method =  $(this).attr('data-method'),
				fieldName = $(this).attr('name'),
				gridId = $(this).parent('div').parent('th').parent('tr').parent('tbody').parent('table').attr('id');
			$.post(window.location, {method: method, filter: field, value: value}, function (data) {
				$('#' + gridId).html(data);
				$('input[name=\'' + fieldName + '\']').focus().val($('input[name=\'' + fieldName + '\']').val());
			});
		});

	};

	initGridOrder = function () {
		//sortowanie grida
		$('table.grid').on('click', 'th > a.order', function () {
			var field = $(this).attr('href'),
				gridId = $(this).parent('th').parent('tr').parent('tbody').parent('table').attr('id'),
				method = $(this).attr('data-method');
			$.post(window.location, {order: field, method: method}, function (data) {
				$('#' + gridId).html(data);
			});
			return false;
		});
	};

	initGridOperation = function () {
		//zapytanie o kasowanie
		$('table.grid').on('click', 'td > a.confirm', function () {
			return window.confirm($(this).attr('title') + '?');
		});
		//zapytanie o kasowanie
		$('table.grid').on('change', 'td > div.checkbox > input.checkbox', function () {
			var id = $(this).attr('id').split('-');
			$.post(window.location, {id: id[1], name: id[0], value: $(this).val(), checked: $(this).is(':checked')}, function (data) {
				return;
			});
		});
	};

	initGridFilter();
	initGridOrder();
	initGridOperation();
};

$(document).ready(function () {
	"use strict";
	CMS.grid();
});
<commit_msg>Grid fix double request<commit_after>/*jslint unparam: true */
/*global $, document, window, request */
var CMS = {};

CMS.grid = function () {
	"use strict";
	var initGridFilter,
		initGridOrder,
		initGridOperation;

	initGridFilter = function () {

		var stoptyping;
		$('table.grid').on('keyup', "th > div.field > .field", function (event) {
			if (event.which === 27) {
				return;
			}
			var field = $(this);
			clearTimeout(stoptyping);
			stoptyping = setTimeout(function () {
				filter(field);
			}, 500);
		});

		function filter(field) {
			var filter = field.attr('name'),
				value = field.val(),
				fieldName = field.attr('name'),
				gridId = field.parent('div').parent('th').parent('tr').parent('tbody').parent('table').attr('id');
			$.post(window.location, {filter: filter, value: value}, function (data) {
				$('#' + gridId).html(data);
				$('input[name=\'' + fieldName + '\']').focus().val($('input[name=\'' + fieldName + '\']').val());
			});
		}

	};

	initGridOrder = function () {
		//sortowanie grida
		$('table.grid').on('click', 'th > a.order', function () {
			var field = $(this).attr('href'),
				gridId = $(this).parent('th').parent('tr').parent('tbody').parent('table').attr('id'),
				method = $(this).attr('data-method');
			$.post(window.location, {order: field, method: method}, function (data) {
				$('#' + gridId).html(data);
			});
			return false;
		});
	};

	initGridOperation = function () {
		//zapytanie o kasowanie
		$('table.grid').on('click', 'td > a.confirm', function () {
			return window.confirm($(this).attr('title') + '?');
		});
		//zapytanie o kasowanie
		$('table.grid').on('change', 'td > div.checkbox > input.checkbox', function () {
			var id = $(this).attr('id').split('-');
			$.post(window.location, {id: id[1], name: id[0], value: $(this).val(), checked: $(this).is(':checked')}, function (data) {
				return;
			});
		});
	};

	initGridFilter();
	initGridOrder();
	initGridOperation();
};

$(document).ready(function () {
	"use strict";
	CMS.grid();
});
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * TODO: Docs
 */
define( function( require ) {
  'use strict';

  var DownUpListener = require( 'SCENERY/input/DownUpListener' );
  var Property = require( 'AXON/Property' );
  var inherit = require( 'PHET_CORE/inherit' );

  /**
   * @param {Object} options
   * @constructor
   */
  function ButtonListener( buttonModel, options ) {
    this.buttonModel = buttonModel;
    var self = this;
    options = _.extend( {
      fireOnDown: false
    }, options );

    // Track the pointer the is currently interacting with this button, ignore others.
    this.overPointer = null;
    this.downPointer = null;

    DownUpListener.call( this, {
        down: function( event, trail ) {
          if ( self.downPointer === null ) {
            self.downPointer = event.pointer;
          }
          if ( buttonModel.enabled && event.pointer === self.downPointer ) {
            buttonModel.down = true;
          }
        },

        up: function( event, trail ) {
          if ( buttonModel.enabled ) {
            buttonModel.down = false;
          }
          if ( event.pointer === self.downPointer ) {
            self.downPointer = null;
          }
        }
      }
    );

  }

  return inherit( DownUpListener, ButtonListener, {
    enter: function( event, trail ) {
      if ( this.overPointer === null ) {
        this.overPointer = event.pointer;
      }
      if ( this.buttonModel.enabled ) {
        if ( this.overPointer === event.pointer ) {
          this.buttonModel.over = true;
        }
      }
    },

    exit: function( event, trail ) {
      if ( event.pointer === this.overPointer ) {
        this.overPointer = null;
        if ( this.buttonModel.enabled ) {
          this.buttonModel.over = false;
        }
      }
    }} );
} );<commit_msg>added docs<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * The ButtonListener is a scenery Input Listener that translates input events (down, up, enter, exit) into states in a ButtonModel.
 */
define( function( require ) {
  'use strict';

  var DownUpListener = require( 'SCENERY/input/DownUpListener' );
  var Property = require( 'AXON/Property' );
  var inherit = require( 'PHET_CORE/inherit' );

  /**
   * @param {Object} options
   * @constructor
   */
  function ButtonListener( buttonModel, options ) {
    this.buttonModel = buttonModel;
    var self = this;
    options = _.extend( {
      fireOnDown: false
    }, options );

    // Track the pointer the is currently interacting with this button, ignore others.
    this.overPointer = null;
    this.downPointer = null;

    DownUpListener.call( this, {
        down: function( event, trail ) {
          if ( self.downPointer === null ) {
            self.downPointer = event.pointer;
          }
          if ( buttonModel.enabled && event.pointer === self.downPointer ) {
            buttonModel.down = true;
          }
        },

        up: function( event, trail ) {
          if ( buttonModel.enabled ) {
            buttonModel.down = false;
          }
          if ( event.pointer === self.downPointer ) {
            self.downPointer = null;
          }
        }
      }
    );

  }

  return inherit( DownUpListener, ButtonListener, {
    enter: function( event, trail ) {
      if ( this.overPointer === null ) {
        this.overPointer = event.pointer;
      }
      if ( this.buttonModel.enabled ) {
        if ( this.overPointer === event.pointer ) {
          this.buttonModel.over = true;
        }
      }
    },

    exit: function( event, trail ) {
      if ( event.pointer === this.overPointer ) {
        this.overPointer = null;
        if ( this.buttonModel.enabled ) {
          this.buttonModel.over = false;
        }
      }
    }} );
} );<|endoftext|>


<commit_before>const XUnitReport = testResults => {
  let testCaseToXML = (suiteName, testName, testCase) => {
    var passed = testCase.expected == testCase.actual;
    var xml = '    <testcase classname="' + suiteName + '" name="' + testName + '"';

    if (passed) {
      xml += '/>\n';
    } else {
      xml +=
        '>\n      <failure message="Expected ' +
        testCase.expected +
        ' but got ' +
        testCase.actual +
        '">' +
        testCase.error +
        '</failure>\n';
      xml += '    </testcase>\n';
    }

    return xml;
  };

  let testSuiteToXML = (suiteName, suite) => {
    let xml = '  <testsuite tests="' + numTests.toString() + '">\n';
    let tests = Object.keys(suite);

    tests.forEach(test => {
      xml += testCaseToXML(suiteName, test, suite[test]);
    });

    for (var testName in suite) {
    }
    xml += '  </testsuite>\n';
    return xml;
  };

  let jsonToXUnit = results => {
    let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<testsuites>\n';
    let { suites } = results.tests;
    let suiteNames = Object.keys(suites);
    suiteNames &&
      suiteNames.forEach(suite => {
        xml += testSuiteToXML(suite, suites[suite]);
      });
    xml += '</testsuites>\n';
    return xml;
  };

  let xunit = jsonToXunit(testResults);
};

export const reporter = XUnitReport;

export const postTestResults = (testResultJSON, params) => {
  const headers = new Headers({
    ...params.headers
  });

  const body = {
    testResult: testResultJSON
  };

  const requestParams = {
    method: params.method,
    headers: headers || undefined,
    body: JSON.stringify(body)
  };

  return fetch(params.url, requestParams)
    .then(response => response.text())
    .then(responseData => {
      console.log('responseData', responseData);
    })
    .catch(failure => {
      console.warn(failure);
    });
};
<commit_msg>Reporter: fix capitalization<commit_after>const XUnitReport = testResults => {
  let testCaseToXML = (suiteName, testName, testCase) => {
    var passed = testCase.expected == testCase.actual;
    var xml = '    <testcase classname="' + suiteName + '" name="' + testName + '"';

    if (passed) {
      xml += '/>\n';
    } else {
      xml +=
        '>\n      <failure message="Expected ' +
        testCase.expected +
        ' but got ' +
        testCase.actual +
        '">' +
        testCase.error +
        '</failure>\n';
      xml += '    </testcase>\n';
    }

    return xml;
  };

  let testSuiteToXML = (suiteName, suite) => {
    let xml = '  <testsuite tests="' + numTests.toString() + '">\n';
    let tests = Object.keys(suite);

    tests.forEach(test => {
      xml += testCaseToXML(suiteName, test, suite[test]);
    });

    for (var testName in suite) {
    }
    xml += '  </testsuite>\n';
    return xml;
  };

  let jsonToXUnit = results => {
    let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<testsuites>\n';
    let { suites } = results.tests;
    let suiteNames = Object.keys(suites);
    suiteNames &&
      suiteNames.forEach(suite => {
        xml += testSuiteToXML(suite, suites[suite]);
      });
    xml += '</testsuites>\n';
    return xml;
  };

  let xunit = jsonToXUnit(testResults);
};

export const reporter = XUnitReport;

export const postTestResults = (testResultJSON, params) => {
  const headers = new Headers({
    ...params.headers
  });

  const body = {
    testResult: testResultJSON
  };

  const requestParams = {
    method: params.method,
    headers: headers || undefined,
    body: JSON.stringify(body)
  };

  return fetch(params.url, requestParams)
    .then(response => response.text())
    .then(responseData => {
      console.log('responseData', responseData);
    })
    .catch(failure => {
      console.warn(failure);
    });
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var del = require('del');
var inject = require('gulp-inject-string');
var htmlmin = require('gulp-htmlmin');
var runSequence = require('run-sequence');
var fs = require('fs');
var rename = require('gulp-rename');
var gulpStylelint = require('gulp-stylelint');
var imageResize = require('gulp-image-resize');
var imagemin = require('gulp-imagemin');
var connect = require('gulp-connect');
var uglify = require('gulp-uglify');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var s3 = require('gulp-s3-upload')({});
var cloudfront = require('gulp-cloudfront-invalidate');

gulp.task('build', function(callback) {
  return runSequence(
    'lint:scss',
    'clean',
    'copy:assets',
    'scss',
    'postcss',
    'js',
    'image:minify',
    'image:inject',
    'inject:html',
    'inject:js',
    'inject:css',
    'html:min',
    'inject:build-comment',
    'rename-index',
    callback
  );
});

gulp.task('clean', function() {
  return del([
    'build',
    'index.html'
  ])
});

// This task needs to be run when you update the photos
// that appear in the carousel. It cuts the small images
// from the large images and puts them in the small-photos folder
gulp.task('image:resize', function() {
  return gulp.src('assets/large-photos/**')
    .pipe(imageResize({
        height : 350,
        imageMagick: true
    }))
    .pipe(gulp.dest('assets/small-photos'));
});

gulp.task('image:minify', function() {
  return gulp.src('assets/**/*')
    .pipe(imagemin([
      imagemin.jpegtran({progressive: true})
    ]))
    .pipe(gulp.dest('assets'))
});

// This task adds the html for photos in the carousel. The order is based
// on the filename, so to change order change the first number in the filename.
gulp.task('image:inject', function() {
  var photoFilenames = fs.readdirSync('assets/large-photos');
  var sortedPhotoFilenames = photoFilenames.sort();
  var imageElementString = '';
  var imageElementTemplate = fs.readFileSync('src/photo-element-template.html').toString();
  // Add a cachebuster to the end of the file name to allow
  // for updating images with the same filename.
  var cacheBuster = Date.now();

  for (var index = 0; index < sortedPhotoFilenames.length; index++) {
    var filename = sortedPhotoFilenames[index];

    if (!filename || filename.startsWith('.')) {
      continue;
    }

    var cacheBustedfilename = filename + '?cb=' + cacheBuster;
    var imageElement = imageElementTemplate.replace(/filename/g, cacheBustedfilename);
    imageElementString += imageElement;
  }

  return gulp.src('src/main.html')
    .pipe(inject.replace('<!-- Inject Photos  -->', imageElementString))
    .pipe(gulp.dest('build'));
});

gulp.task('lint:scss', function() {
  return gulp
    .src('src/**/*.scss')
    .pipe(gulpStylelint({
        reporters: [{
            formatter: 'string',
            console: true
        }]
    }));
})

gulp.task('scss', function() {
  return gulp.src('src/**/*.scss')
    .pipe(sass({
        outputStyle: 'compressed'
    }).on('error', sass.logError))
    .pipe(gulp.dest('build'));
});

gulp.task('copy:assets', function() {
  return gulp.src('assets/**')
    .pipe(gulp.dest('build/assets'));
});

gulp.task('postcss', function() {
  return gulp.src('build/**/*.css')
    .pipe(postcss([ autoprefixer() ]))
    .pipe(gulp.dest('build'));
});

gulp.task('js', function() {
  return gulp.src('src/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('build'));
});

gulp.task('html:min', function() {
  return gulp.src('build/shell.html')
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeComments: true
    }))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:html', function() {
  return gulp.src('src/shell.html')
    .pipe(inject.after('<body>', fs.readFileSync('build/main.html').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:js', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.after('<script>', fs.readFileSync('build/main.js').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:css', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.after('<style>', fs.readFileSync('build/main.css').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:build-comment', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.prepend('<!-- Generated: ' + Date() + ' -->\n'))
    .pipe(gulp.dest('build'));
});

gulp.task('rename-index', function() {
  return gulp.src('build/shell.html')
    .pipe(rename('index.html'))
    .pipe(gulp.dest('build'));
});

gulp.task('watch', function() {
  return gulp.watch(['src/*'], function() {
    runSequence('build', 'reload');
  });
});

gulp.task('connect', function() {
  return connect.server({
    root: ['build'],
    livereload: true
  });
});

gulp.task('reload', function () {
  return gulp.src('src/**')
    .pipe(connect.reload());
});

gulp.task('develop', function() {
  return runSequence(
    'build',
    'watch',
    'connect'
  );
});

gulp.task('upload:s3', function() {
  return gulp.src('build/**')
    .pipe(s3({
      Bucket: 'creak-website',
      ACL: 'public-read'
    }));
});

gulp.task('deploy', function() {
  runSequence('build', 'upload:s3');
});<commit_msg>updated s3 bucket name<commit_after>var gulp = require('gulp');
var sass = require('gulp-sass');
var del = require('del');
var inject = require('gulp-inject-string');
var htmlmin = require('gulp-htmlmin');
var runSequence = require('run-sequence');
var fs = require('fs');
var rename = require('gulp-rename');
var gulpStylelint = require('gulp-stylelint');
var imageResize = require('gulp-image-resize');
var imagemin = require('gulp-imagemin');
var connect = require('gulp-connect');
var uglify = require('gulp-uglify');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var s3 = require('gulp-s3-upload')({});
var cloudfront = require('gulp-cloudfront-invalidate');

gulp.task('build', function(callback) {
  return runSequence(
    'lint:scss',
    'clean',
    'copy:assets',
    'scss',
    'postcss',
    'js',
    'image:minify',
    'image:inject',
    'inject:html',
    'inject:js',
    'inject:css',
    'html:min',
    'inject:build-comment',
    'rename-index',
    callback
  );
});

gulp.task('clean', function() {
  return del([
    'build',
    'index.html'
  ])
});

// This task needs to be run when you update the photos
// that appear in the carousel. It cuts the small images
// from the large images and puts them in the small-photos folder
gulp.task('image:resize', function() {
  return gulp.src('assets/large-photos/**')
    .pipe(imageResize({
        height : 350,
        imageMagick: true
    }))
    .pipe(gulp.dest('assets/small-photos'));
});

gulp.task('image:minify', function() {
  return gulp.src('assets/**/*')
    .pipe(imagemin([
      imagemin.jpegtran({progressive: true})
    ]))
    .pipe(gulp.dest('assets'))
});

// This task adds the html for photos in the carousel. The order is based
// on the filename, so to change order change the first number in the filename.
gulp.task('image:inject', function() {
  var photoFilenames = fs.readdirSync('assets/large-photos');
  var sortedPhotoFilenames = photoFilenames.sort();
  var imageElementString = '';
  var imageElementTemplate = fs.readFileSync('src/photo-element-template.html').toString();
  // Add a cachebuster to the end of the file name to allow
  // for updating images with the same filename.
  var cacheBuster = Date.now();

  for (var index = 0; index < sortedPhotoFilenames.length; index++) {
    var filename = sortedPhotoFilenames[index];

    if (!filename || filename.startsWith('.')) {
      continue;
    }

    var cacheBustedfilename = filename + '?cb=' + cacheBuster;
    var imageElement = imageElementTemplate.replace(/filename/g, cacheBustedfilename);
    imageElementString += imageElement;
  }

  return gulp.src('src/main.html')
    .pipe(inject.replace('<!-- Inject Photos  -->', imageElementString))
    .pipe(gulp.dest('build'));
});

gulp.task('lint:scss', function() {
  return gulp
    .src('src/**/*.scss')
    .pipe(gulpStylelint({
        reporters: [{
            formatter: 'string',
            console: true
        }]
    }));
})

gulp.task('scss', function() {
  return gulp.src('src/**/*.scss')
    .pipe(sass({
        outputStyle: 'compressed'
    }).on('error', sass.logError))
    .pipe(gulp.dest('build'));
});

gulp.task('copy:assets', function() {
  return gulp.src('assets/**')
    .pipe(gulp.dest('build/assets'));
});

gulp.task('postcss', function() {
  return gulp.src('build/**/*.css')
    .pipe(postcss([ autoprefixer() ]))
    .pipe(gulp.dest('build'));
});

gulp.task('js', function() {
  return gulp.src('src/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('build'));
});

gulp.task('html:min', function() {
  return gulp.src('build/shell.html')
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeComments: true
    }))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:html', function() {
  return gulp.src('src/shell.html')
    .pipe(inject.after('<body>', fs.readFileSync('build/main.html').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:js', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.after('<script>', fs.readFileSync('build/main.js').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:css', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.after('<style>', fs.readFileSync('build/main.css').toString()))
    .pipe(gulp.dest('build'));
});

gulp.task('inject:build-comment', function() {
  return gulp.src('build/shell.html')
    .pipe(inject.prepend('<!-- Generated: ' + Date() + ' -->\n'))
    .pipe(gulp.dest('build'));
});

gulp.task('rename-index', function() {
  return gulp.src('build/shell.html')
    .pipe(rename('index.html'))
    .pipe(gulp.dest('build'));
});

gulp.task('watch', function() {
  return gulp.watch(['src/*'], function() {
    runSequence('build', 'reload');
  });
});

gulp.task('connect', function() {
  return connect.server({
    root: ['build'],
    livereload: true
  });
});

gulp.task('reload', function () {
  return gulp.src('src/**')
    .pipe(connect.reload());
});

gulp.task('develop', function() {
  return runSequence(
    'build',
    'watch',
    'connect'
  );
});

gulp.task('upload:s3', function() {
  return gulp.src('build/**')
    .pipe(s3({
      Bucket: 'www.thecreak.net',
      ACL: 'public-read'
    }));
});

gulp.task('deploy', function() {
  runSequence('build', 'upload:s3');
});<|endoftext|>


<commit_before>/*
 * Copyright 2009-2013 European Molecular Biology Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

(function ($, undefined) {
    if ($ == undefined) {
        throw "jQuery not loaded";
    }

    $.fn.extend({

        aeLoginForm: function(options) {
            return this.each(function() {
			    new $.AELoginForm(this, options);
            });
        }
    });

    $.AELoginForm = function(loginWindow, options) {

        var $body = $("body");
        var $window = $(loginWindow);
        var $form = $window.find("form").first();
        var $user = $form.find("input[name='u']").first();
        var $pass = $form.find("input[name='p']").first();
        var $submit = $form.find("input[type='submit']").first();
        var $open = $(options.open).first();
        var $close = $(options.close).first();
        var $status = $(options.status).first();

        function verifyLoginValues() {
            var user = $user.val();
            var pass = $pass.val();

            $submit.attr("disabled", "true");

            if ("" == user) {
                $status.text("User name should not be empty.");
                $user.focus();
                $submit.removeAttr("disabled");
                return false;
            }

            if ("" == pass) {
                $status.text("Password should not be empty.");
                $pass.focus();
                $submit.removeAttr("disabled");
                return false;
            }

            $status.text();
            return true;
        }

        function isLoggedIn() {
            return (undefined != $.cookie("AeLoggedUser") && undefined != $.cookie("AeLoginToken"));
        }

        function clearCookies() {
            $.cookie("AeAuthMessage", null, {path: '/' });
            $.cookie("AeLoggedUser", null, {path: '/' });
            $.cookie("AeLoginToken", null, {path: '/' });
        }

        function doLogout() {
            clearCookies();
            doReload();
        }

        function doReload() {
            window.location.href = window.location.href;
        }

        function doOpenWindow() {
            $body.bind("click", doCloseWindow);
            $window.bind("click", onWindowClick);

            $submit.removeAttr("disabled");
            $window.show();
            $user.focus();
        }

        function doCloseWindow() {
            $window.unbind("click", onWindowClick);
            $body.unbind("click", doCloseWindow);
            $window.hide();
            $status.text("");
        }

        function onWindowClick(e) {
            e.stopPropagation();
        }

        $form.submit(function() {
            return verifyLoginValues();
        });

        $open.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (isLoggedIn()) {
                doLogout();
            } else {
                doOpenWindow();
            }
        });

        $close.click(function (e) {
            e.preventDefault();
            doCloseWindow();
        });

        $form.find("input").keydown(function (e) {
            if (27 == e.keyCode) {
                doCloseWindow();
            }
        });

        var message = $.cookie("AeAuthMessage");
        if (undefined != message) {
            var username = $.cookie("AeLoggedUser");
            clearCookies();
            $user.val(username);
            $status.html(message.replace(/^"?(.+[^"])"?$/g, "$1"));
            doOpenWindow();
        }
    };

    $.fn.extend({

        aeFeedbackForm: function(options) {
            return this.each(function() {
                new $.AEFeedbackForm(this, options);
            });
        }
    });

    $.AEFeedbackForm = function(feedbackWindow, options) {

        var $body = $("body");
        var $window = $(feedbackWindow);
        var $form = $window.find("form").first();
        var $message = $form.find("textarea[name='m']").first();
        var $email = $form.find("input[name='e']").first();
        var $page = $form.find("input[name='p']").first();
        var $ref = $form.find("input[name='r']").first();
        var $submit = $form.find("input[type='submit']").first();
        var $open = $(options.open).first();
        var $close = $(options.close).first();

        function doOpenWindow() {
            $body.bind("click", doCloseWindow);
            $window.bind("click", onWindowClick);

            $submit.removeAttr("disabled");
            $window.show();
            $message.val("").focus();
        }

        function doCloseWindow() {
            $window.unbind("click", onWindowClick);
            $body.unbind("click", doCloseWindow);
            $window.hide();
        }

        function onWindowClick(e) {
            e.stopPropagation();
        }

        $form.submit(function() {
            $submit.attr("disabled", "true");
            $.post( contextPath + "/feedback"
                , {m : $message.val(), e : $email.val(), p : $page.val(), r : $ref.val()}
            ).always(function() {
                doCloseWindow();
            });
        });

        $open.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            doOpenWindow();
        });

        $close.click(function (e) {
            e.preventDefault();
            doCloseWindow();
        });

        $form.find("input,textarea").keydown(function (e) {
            if (27 == e.keyCode) {
                doCloseWindow();
            }
        });
    };

    $.fn.extend({

        aeBrowseSorting: function(options) {
            return this.each(function() {
                new $.AEBrowseSorting(this, options);
            });
        }
    });

    $.AEBrowseSorting =  function(column, options) {
        if ($.query == undefined) {
            throw "jQuery.query not loaded";
        }

        var $column = $(column);

        var sortby = $.query.get("sortby") || options.defaultField;
        var sortorder = $.query.get("sortorder") || options.fields[options.defaultField].sort;

        var pageName = /\/?([^\/]*)$/.exec(decodeURI(window.location.pathname))[1];

        var colname = /col_(\w+)/.exec($column.attr("class"))[1];

        // so the idea is to set default sorting for all columns except the "current" one
        // (which will be inverted) against its current state
        var newOrder = (colname === sortby) ? ("ascending" === sortorder ? "descending" : "ascending"): options.fields[colname].sort;
        var queryString = $.query.set("sortby", colname).set("sortorder", newOrder).toString();

        $column.wrapInner("");
    };

    function updateTableHeaders() {
        $(".persist-area").each(function() {

            var el             = $(this),
                offset         = el.offset(),
                scrollTop      = $(window).scrollTop(),
                floatingHeader = $(".floating-header", this),
                width          = floatingHeader.prev().width();

            if ((scrollTop > offset.top) && (scrollTop < offset.top + el.height())) {
                floatingHeader.css({
                    "visibility": "visible",
                    "width": width
                });
            } else {
                floatingHeader.css({
                    "visibility": "hidden"
                });
            }
        });
    }

    function resizeTableHeaders() {
        $(".persist-area").each(function() {

            var floatingHeader = $(".floating-header", this),
                width          = floatingHeader.prev().width();

            if ("visible" == floatingHeader.css("visibility")) {
                floatingHeader.css({
                    "visibility": "visible",
                    "width": width
                });
            }
        });
    }

    function initPersistentHeaders()
    {
        var clonedHeaderRow;

        $(".persist-area").each(function() {
            clonedHeaderRow = $(".persist-header", this);
            clonedHeaderRow
                .before(clonedHeaderRow.clone())
                .addClass("floating-header");

        });

        $(window)
            .scroll(updateTableHeaders)
            .resize(resizeTableHeaders)
            .trigger("scroll");
    }

    $.aeFeedback = function(e) {
        e.preventDefault();
        e.stopPropagation();
        $("li.feedback a").click();
    };

    $(function() {
        initPersistentHeaders();
        $("#ae-login-window").aeLoginForm({
            open: "li.login a",
            close: "#ae-login-close",
            status: "#ae-login-status"
        });
        $("#ae-feedback-window").aeFeedbackForm({
            open: "li.feedback a",
            close: "#ae-feedback-close"
        });

        var autoCompleteFixSet = function() {
            $(this).attr('autocomplete', 'off');
        };
        var autoCompleteFixUnset = function() {
            $(this).removeAttr('autocomplete');
        };

        $("#local-searchbox").autocomplete(
            contextPath + "/keywords.txt"
            , { matchContains: false
                , selectFirst: false
                , scroll: true
                , max: 50
                , requestTreeUrl: contextPath + "/efotree.txt"
            }
        ).focus(autoCompleteFixSet).blur(autoCompleteFixUnset).removeAttr('autocomplete');

        // attach titles to highlight classes
        var $browse_data = $("#ae-browse").find("td");
        $browse_data.find(".text-hit").attr("title", "This is exact string matched for input query terms");
        $browse_data.find(".text-syn").attr("title", "This is synonym matched from Experimental Factor Ontology e.g. neoplasia for cancer");
        $browse_data.find(".text-efo").attr("title", "This is matched child term from Experimental Factor Ontology e.g. brain and subparts of brain");

    });

})(window.jQuery);
<commit_msg>- highlight help will work just about everywhere<commit_after>/*
 * Copyright 2009-2013 European Molecular Biology Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

(function ($, undefined) {
    if ($ == undefined) {
        throw "jQuery not loaded";
    }

    $.fn.extend({

        aeLoginForm: function(options) {
            return this.each(function() {
			    new $.AELoginForm(this, options);
            });
        }
    });

    $.AELoginForm = function(loginWindow, options) {

        var $body = $("body");
        var $window = $(loginWindow);
        var $form = $window.find("form").first();
        var $user = $form.find("input[name='u']").first();
        var $pass = $form.find("input[name='p']").first();
        var $submit = $form.find("input[type='submit']").first();
        var $open = $(options.open).first();
        var $close = $(options.close).first();
        var $status = $(options.status).first();

        function verifyLoginValues() {
            var user = $user.val();
            var pass = $pass.val();

            $submit.attr("disabled", "true");

            if ("" == user) {
                $status.text("User name should not be empty.");
                $user.focus();
                $submit.removeAttr("disabled");
                return false;
            }

            if ("" == pass) {
                $status.text("Password should not be empty.");
                $pass.focus();
                $submit.removeAttr("disabled");
                return false;
            }

            $status.text();
            return true;
        }

        function isLoggedIn() {
            return (undefined != $.cookie("AeLoggedUser") && undefined != $.cookie("AeLoginToken"));
        }

        function clearCookies() {
            $.cookie("AeAuthMessage", null, {path: '/' });
            $.cookie("AeLoggedUser", null, {path: '/' });
            $.cookie("AeLoginToken", null, {path: '/' });
        }

        function doLogout() {
            clearCookies();
            doReload();
        }

        function doReload() {
            window.location.href = window.location.href;
        }

        function doOpenWindow() {
            $body.bind("click", doCloseWindow);
            $window.bind("click", onWindowClick);

            $submit.removeAttr("disabled");
            $window.show();
            $user.focus();
        }

        function doCloseWindow() {
            $window.unbind("click", onWindowClick);
            $body.unbind("click", doCloseWindow);
            $window.hide();
            $status.text("");
        }

        function onWindowClick(e) {
            e.stopPropagation();
        }

        $form.submit(function() {
            return verifyLoginValues();
        });

        $open.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (isLoggedIn()) {
                doLogout();
            } else {
                doOpenWindow();
            }
        });

        $close.click(function (e) {
            e.preventDefault();
            doCloseWindow();
        });

        $form.find("input").keydown(function (e) {
            if (27 == e.keyCode) {
                doCloseWindow();
            }
        });

        var message = $.cookie("AeAuthMessage");
        if (undefined != message) {
            var username = $.cookie("AeLoggedUser");
            clearCookies();
            $user.val(username);
            $status.html(message.replace(/^"?(.+[^"])"?$/g, "$1"));
            doOpenWindow();
        }
    };

    $.fn.extend({

        aeFeedbackForm: function(options) {
            return this.each(function() {
                new $.AEFeedbackForm(this, options);
            });
        }
    });

    $.AEFeedbackForm = function(feedbackWindow, options) {

        var $body = $("body");
        var $window = $(feedbackWindow);
        var $form = $window.find("form").first();
        var $message = $form.find("textarea[name='m']").first();
        var $email = $form.find("input[name='e']").first();
        var $page = $form.find("input[name='p']").first();
        var $ref = $form.find("input[name='r']").first();
        var $submit = $form.find("input[type='submit']").first();
        var $open = $(options.open).first();
        var $close = $(options.close).first();

        function doOpenWindow() {
            $body.bind("click", doCloseWindow);
            $window.bind("click", onWindowClick);

            $submit.removeAttr("disabled");
            $window.show();
            $message.val("").focus();
        }

        function doCloseWindow() {
            $window.unbind("click", onWindowClick);
            $body.unbind("click", doCloseWindow);
            $window.hide();
        }

        function onWindowClick(e) {
            e.stopPropagation();
        }

        $form.submit(function() {
            $submit.attr("disabled", "true");
            $.post( contextPath + "/feedback"
                , {m : $message.val(), e : $email.val(), p : $page.val(), r : $ref.val()}
            ).always(function() {
                doCloseWindow();
            });
        });

        $open.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            doOpenWindow();
        });

        $close.click(function (e) {
            e.preventDefault();
            doCloseWindow();
        });

        $form.find("input,textarea").keydown(function (e) {
            if (27 == e.keyCode) {
                doCloseWindow();
            }
        });
    };

    $.fn.extend({

        aeBrowseSorting: function(options) {
            return this.each(function() {
                new $.AEBrowseSorting(this, options);
            });
        }
    });

    $.AEBrowseSorting =  function(column, options) {
        if ($.query == undefined) {
            throw "jQuery.query not loaded";
        }

        var $column = $(column);

        var sortby = $.query.get("sortby") || options.defaultField;
        var sortorder = $.query.get("sortorder") || options.fields[options.defaultField].sort;

        var pageName = /\/?([^\/]*)$/.exec(decodeURI(window.location.pathname))[1];

        var colname = /col_(\w+)/.exec($column.attr("class"))[1];

        // so the idea is to set default sorting for all columns except the "current" one
        // (which will be inverted) against its current state
        var newOrder = (colname === sortby) ? ("ascending" === sortorder ? "descending" : "ascending"): options.fields[colname].sort;
        var queryString = $.query.set("sortby", colname).set("sortorder", newOrder).toString();

        $column.wrapInner("");
    };

    function updateTableHeaders() {
        $(".persist-area").each(function() {

            var el             = $(this),
                offset         = el.offset(),
                scrollTop      = $(window).scrollTop(),
                floatingHeader = $(".floating-header", this),
                width          = floatingHeader.prev().width();

            if ((scrollTop > offset.top) && (scrollTop < offset.top + el.height())) {
                floatingHeader.css({
                    "visibility": "visible",
                    "width": width
                });
            } else {
                floatingHeader.css({
                    "visibility": "hidden"
                });
            }
        });
    }

    function resizeTableHeaders() {
        $(".persist-area").each(function() {

            var floatingHeader = $(".floating-header", this),
                width          = floatingHeader.prev().width();

            if ("visible" == floatingHeader.css("visibility")) {
                floatingHeader.css({
                    "visibility": "visible",
                    "width": width
                });
            }
        });
    }

    function initPersistentHeaders()
    {
        var clonedHeaderRow;

        $(".persist-area").each(function() {
            clonedHeaderRow = $(".persist-header", this);
            clonedHeaderRow
                .before(clonedHeaderRow.clone())
                .addClass("floating-header");

        });

        $(window)
            .scroll(updateTableHeaders)
            .resize(resizeTableHeaders)
            .trigger("scroll");
    }

    $.aeFeedback = function(e) {
        e.preventDefault();
        e.stopPropagation();
        $("li.feedback a").click();
    };

    $(function() {
        initPersistentHeaders();
        $("#ae-login-window").aeLoginForm({
            open: "li.login a",
            close: "#ae-login-close",
            status: "#ae-login-status"
        });
        $("#ae-feedback-window").aeFeedbackForm({
            open: "li.feedback a",
            close: "#ae-feedback-close"
        });

        var autoCompleteFixSet = function() {
            $(this).attr('autocomplete', 'off');
        };
        var autoCompleteFixUnset = function() {
            $(this).removeAttr('autocomplete');
        };

        $("#local-searchbox").autocomplete(
            contextPath + "/keywords.txt"
            , { matchContains: false
                , selectFirst: false
                , scroll: true
                , max: 50
                , requestTreeUrl: contextPath + "/efotree.txt"
            }
        ).focus(autoCompleteFixSet).blur(autoCompleteFixUnset).removeAttr('autocomplete');

        // attach titles to highlight classes
        var $data = $("#ae-content");
        $data.find(".text-hit").attr("title", "This is exact string matched for input query terms");
        $data.find(".text-syn").attr("title", "This is synonym matched from Experimental Factor Ontology e.g. neoplasia for cancer");
        $data.find(".text-efo").attr("title", "This is matched child term from Experimental Factor Ontology e.g. brain and subparts of brain");

    });

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


<commit_before>import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { c } from 'ttag';
import { ResetButton, PrimaryButton, Input, Label, Row } from 'react-components';

import Modal from './Modal';
import Footer from './Footer';
import Content from './Content';
import { generateUID } from '../../helpers/component';

/*
Good candidates:
- Gift code modal
- Orgnization name modal
- Password modal to unlock scope
- Black/White list modal
- OpenVPN modal
*/

const InputModal = ({ label, title, input: initialInput, show, onClose, onSubmit, cancel, submit, placeholder }) => {
    const [input, set] = useState(initialInput);
    const id = generateUID('input-modal');
    const handleChange = (event) => set(event.target.value);
    const handleSubmit = () => onSubmit(input);

    return (
        <Modal show={show} onClose={onClose} title={title} modalClassName="pm-modal--smaller">
            <Content onSubmit={handleSubmit} onReset={onClose}>
                <Row>
                    {label}
                    <Input
                        id={id}
                        value={input}
                        placeholder={placeholder}
                        onChange={handleChange}
                        autoFocus={true}
                        required
                    />
                </Row>

                    <ResetButton>{cancel}</ResetButton>
                    <PrimaryButton type="submit">{submit}</PrimaryButton>

            </Content>
        </Modal>
    );
};

InputModal.propTypes = {
    input: PropTypes.string,
    onClose: PropTypes.func,
    label: PropTypes.string.isRequired,
    onSubmit: PropTypes.func,
    title: PropTypes.string,
    cancel: PropTypes.string.isRequired,
    confirm: PropTypes.string.isRequired,
    show: PropTypes.bool.isRequired,
    placeholder: PropTypes.string,
    submit: PropTypes.string
};

InputModal.defaultProps = {
    show: false,
    input: '',
    label: '',
    cancel: c('Action').t`Cancel`,
    submit: c('Action').t`Submit`
};

export default InputModal;
<commit_msg>Hotfix InputModal: confirm not used and was required<commit_after>import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { c } from 'ttag';
import { ResetButton, PrimaryButton, Input, Label, Row } from 'react-components';

import Modal from './Modal';
import Footer from './Footer';
import Content from './Content';
import { generateUID } from '../../helpers/component';

/*
Good candidates:
- Gift code modal
- Orgnization name modal
- Password modal to unlock scope
- Black/White list modal
- OpenVPN modal
*/

const InputModal = ({ label, title, input: initialInput, show, onClose, onSubmit, cancel, submit, placeholder }) => {
    const [input, set] = useState(initialInput);
    const id = generateUID('input-modal');
    const handleChange = (event) => set(event.target.value);
    const handleSubmit = () => onSubmit(input);

    return (
        <Modal show={show} onClose={onClose} title={title} modalClassName="pm-modal--smaller">
            <Content onSubmit={handleSubmit} onReset={onClose}>
                <Row>
                    {label}
                    <Input
                        id={id}
                        value={input}
                        placeholder={placeholder}
                        onChange={handleChange}
                        autoFocus={true}
                        required
                    />
                </Row>

                    <ResetButton>{cancel}</ResetButton>
                    <PrimaryButton type="submit">{submit}</PrimaryButton>

            </Content>
        </Modal>
    );
};

InputModal.propTypes = {
    input: PropTypes.string,
    onClose: PropTypes.func,
    label: PropTypes.string.isRequired,
    onSubmit: PropTypes.func,
    title: PropTypes.string,
    cancel: PropTypes.string.isRequired,
    show: PropTypes.bool.isRequired,
    placeholder: PropTypes.string,
    submit: PropTypes.string
};

InputModal.defaultProps = {
    show: false,
    input: '',
    label: '',
    cancel: c('Action').t`Cancel`,
    submit: c('Action').t`Submit`
};

export default InputModal;
<|endoftext|>


<commit_before>import os from 'os'
import path from 'path'
import fs from 'fs'

import { ipcRenderer } from 'electron';
import React, { Component } from 'react';
import { Link, browserHistory } from 'react-router';
import { ScaleLoader } from 'halogen'

import request from 'request'
import requestProgress from 'request-progress'
import StreamZip from 'node-stream-zip'
import fsextra from 'fs-extra'
import async from 'async'

import config from '../../../config'

import section from '../../cssModules/section.scss'
import content from '../../cssModules/content.scss'

import styles from './index.css'

let SoundHax = React.createClass({
  getInitialState() {
    return {
      text: '',
      downloading: null,
      progress: 0,
      finished: false
    }
  },
  componentDidMount() {
    this.downloadSoundhax()
  },
  downloadFile (filename, url, done) {
    this.setState({
      ...this.state,
      progress: 0
    })
    console.log('downloading to', path.resolve(config.drive.mountPoint, filename))
    requestProgress(request(url))
      .on('progress', (state) => {
        this.setState({
          ...this.state,
          progress: (state.percent * 100).toFixed(0)
        })
      })
      .on('end', (err) => {
        if (err) {
          return done(err)
        }
        this.setState({
          ...this.state,
          progress: 100
        })
        return done()
      })
      .pipe(fs.createWriteStream(path.resolve(config.drive.mountPoint, filename)))
  },
  downloadSoundhax () {
    this.setState({
      ...this.state,
      downloading: 'Soundhax'
    })
    const url = `https://github.com/nedwill/soundhax/blob/master/soundhax-${config.region.toLowerCase()}-${config.model}.m4a?raw=true`
    this.downloadFile('soundhax.m4a', url, (err) => {
      if (err) {
        return console.error('Error downloading soundhax...', err)
      }
      this.downloadOtherapp()
    })
  },
  downloadOtherapp () {
    this.setState({
      ...this.state,
      downloading: 'otherapp.bin'
    })
    ipcRenderer.on('otherappURLReply', (event, url) => {
      this.downloadFile('otherapp.bin', url, (err) => {
        if (err) {
          return console.error('Error downloading otherapp.bin...', err)
        }
        this.downloadHBSK()
      })
    })
    ipcRenderer.send('otherappURL', JSON.stringify(config))
  },
  downloadHBSK () {
    this.setState({
      ...this.state,
      downloading: 'Homebrew Starter Kit'
    })
    const zipPath = path.resolve(config.drive.mountPoint, 'starter.zip')
    this.downloadFile(zipPath, 'http://smealum.github.io/ninjhax2/starter.zip', (err) => {
      if (err) {
        return console.error('Error downloading starter.zip...', err)
      }

      let zip = new StreamZip({
        file: zipPath,
        storeEntries: true
      })

      zip.on('error', console.error)

      zip.on('ready', () => {
        zip.extract(null, config.drive.mountPoint, (err) => {
          if (err) {
            return console.error(err)
          }
          return extracted()
        })
      })

      const extracted = () => {
        let files = []
        fsextra.walk(path.resolve(config.drive.mountPoint, 'starter'))
          .on('data', function (file) {
            files.push(file.path)
          })
          .on('end', () => {
            async.each(files, function (file, done) {
              fsextra.move(file, file.replace('starter/', ''), { mkdirp: true }, function (err) {
                if (err && err.code === 'EEXIST') {
                  // ignore
                } else if (err) {
                  return done(err)
                }
                done()
              })
            }, (err) => {
              if (err) {
                return console.error(err)
              }

              // remove previous zip + dir
              fsextra.remove(zipPath)
              fsextra.remove(path.resolve(config.drive.mountPoint, 'starter'))

              this.setState({
                ...this.state,
                finished: true
              })
            })
          })
      }
    })
  },
  getContent () {
    if (this.state.downloading === null) {
      return
Loading...

    } else if (this.state.finished === true) {
      return

        Finished... click next

    } else {
      return

        <ScaleLoader color="#000000" width="20px" height="120px" />

        Downloading {this.state.downloading} ({this.state.progress}%)

    }
  },
  next() {
    if (this.state.finished) {
      this.props.router.push('/decrypt9')
    } else {
      // do nothing if not finished...
    }
  },
  render() {
    return (

Soundhax Setup

        <div className={`${section.content} ${styles.center} ${styles.content}`}>
          {this.getContent()}

Back

          <div className={`${content.button} ${content.buttonNext} ${this.state.finished ? '' : content.buttonDisabled}`} onClick={this.next}>Next

    )
  }
})

export default SoundHax
<commit_msg>refactor soundhax loading<commit_after>import os from 'os'
import path from 'path'
import fs from 'fs'

import { ipcRenderer } from 'electron';
import React, { Component } from 'react';
import { Link, browserHistory } from 'react-router';
import { ScaleLoader } from 'halogen'

import request from 'request'
import requestProgress from 'request-progress'
import StreamZip from 'node-stream-zip'
import fsextra from 'fs-extra'
import async from 'async'

import config from '../../../config'

import section from '../../cssModules/section.scss'
import content from '../../cssModules/content.scss'

import styles from './index.css'

let SoundHax = React.createClass({
  getInitialState() {
    return {
      text: '',
      downloading: null,
      progress: 0,
      finished: false
    }
  },
  componentDidMount() {
    this.downloadSoundhax()
  },
  downloadFile (filename, url, done) {
    this.setState({
      ...this.state,
      progress: 0
    })
    console.log('downloading to', path.resolve(config.drive.mountPoint, filename))
    requestProgress(request(url))
      .on('progress', (state) => {
        this.setState({
          ...this.state,
          progress: (state.percent * 100).toFixed(0)
        })
      })
      .on('end', (err) => {
        if (err) {
          return done(err)
        }
        this.setState({
          ...this.state,
          progress: 100
        })
        return done()
      })
      .pipe(fs.createWriteStream(path.resolve(config.drive.mountPoint, filename)))
  },
  downloadSoundhax () {
    this.setState({
      ...this.state,
      downloading: 'Soundhax'
    }, () => {
      const url = `https://github.com/nedwill/soundhax/blob/master/soundhax-${config.region.toLowerCase()}-${config.model}.m4a?raw=true`
      this.downloadFile('soundhax.m4a', url, (err) => {
        if (err) {
          return console.error('Error downloading soundhax...', err)
        }
        this.downloadOtherapp()
      })
    })
  },
  downloadOtherapp () {
    this.setState({
      ...this.state,
      downloading: 'otherapp.bin'
    }, () => {
      ipcRenderer.send('otherappURL', JSON.stringify(config))
    })
    ipcRenderer.on('otherappURLReply', (event, url) => {
      this.downloadFile('otherapp.bin', url, (err) => {
        if (err) {
          return console.error('Error downloading otherapp.bin...', err)
        }
        this.downloadHBSK()
      })
    })
  },
  downloadHBSK () {
    const zipPath = path.resolve(config.drive.mountPoint, 'starter.zip')

    const download = () => {
      this.downloadFile(zipPath, 'http://smealum.github.io/ninjhax2/starter.zip', (err) => {
        if (err) {
          return console.error('Error downloading starter.zip...', err)
        }
        return extract()
      })
    }

    const extract = () => {
      let zip = new StreamZip({
        file: zipPath,
        storeEntries: true
      })

      zip.on('error', console.error)

      zip.on('ready', () => {
        zip.extract(null, config.drive.mountPoint, (err) => {
          if (err) {
            return console.error(err)
          }
          return extracted()
        })
      })
    }

    const extracted = () => {
      let files = []
      fsextra.walk(path.resolve(config.drive.mountPoint, 'starter'))
        .on('data', function (file) {
          files.push(file.path)
        })
        .on('end', () => {
          async.each(files, function (file, done) {
            fsextra.move(file, file.replace('starter/', ''), { mkdirp: true }, function (err) {
              if (err && err.code === 'EEXIST') {
                // ignore
              } else if (err) {
                return done(err)
              }
              done()
            })
          }, (err) => {
            if (err) {
              return console.error(err)
            }

            // remove previous zip + dir
            fsextra.remove(zipPath)
            fsextra.remove(path.resolve(config.drive.mountPoint, 'starter'))

            this.setState({
              ...this.state,
              finished: true
            })
          })
        })
    }

    this.setState({
      ...this.state,
      downloading: 'Homebrew Starter Kit'
    }, function () {
      download()
    })
  },
  getContent () {
    if (this.state.downloading === null) {
      return
Loading...

    } else if (this.state.finished === true) {
      return

        Finished... click next

    } else {
      return

        <ScaleLoader color="#000000" width="20px" height="120px" />

        Downloading {this.state.downloading} ({this.state.progress}%)

    }
  },
  next() {
    if (this.state.finished) {
      this.props.router.push('/decrypt9')
    } else {
      // do nothing if not finished...
    }
  },
  render() {
    return (

Soundhax Setup

        <div className={`${section.content} ${styles.center} ${styles.content}`}>
          {this.getContent()}

Back

          <div className={`${content.button} ${content.buttonNext} ${this.state.finished ? '' : content.buttonDisabled}`} onClick={this.next}>Next

    )
  }
})

export default SoundHax
<|endoftext|>


<commit_before>/**
 * Local dependencies
 */
const CryptoKey = require('./keys/CryptoKey')
const CryptoKeyPair = require('./keys/CryptoKeyPair')
const JsonWebKey = require('./keys/JsonWebKey')
const recognizedKeyUsages = require('./keys/recognizedKeyUsages')
const supportedAlgorithms = require('./algorithms')
const {InvalidAccessError, NotSupportedError} = require('./errors')
const {TextEncoder} = require('text-encoding')

/**
 * SubtleCrypto
 */
class SubtleCrypto {

  /**
   * encrypt
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  encrypt (algorithm, key, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('encrypt', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('encrypt')) {
        throw new InvalidAccessError('Key usages must include "encrypt"')
      }

      let ciphertext = normalizedAlgorithm.encrypt(algorithm,key, data)

      resolve(ciphertext)
    })
  }

  /**
   * decrypt
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  decrypt (algorithm, key, data) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('decrypt', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    data = data.slice()

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('decrypt')) {
        throw new InvalidAccessError('Key usages must include "decrypt"')
      }

      let plaintext = normalizedAlgorithm.decrypt(algorithm, key, data)
      resolve(plaintext)
    })
  }

  /**
   * sign
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  sign (algorithm, key, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('sign', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('sign')) {
        throw new InvalidAccessError('Key usages must include "sign"')
      }

      let result = normalizedAlgorithm.sign(key, data)

      resolve(result)
    })
  }

  /**
   * verify
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} signature
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  verify (alg, key, signature, data) {
    signature = signature.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('verify', alg)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    data = data.slice()

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('verify')) {
        throw new InvalidAccessError('Key usages must include "verify"')
      }

      let result = normalizedAlgorithm.verify(key, signature, data)
      resolve(result)
    })
  }

  /**
   * digest
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {BufferSource} data
   *
   * @returns {Promise.<ArrayBuffer>}
   */
  digest (algorithm, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('digest', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      try {
        let result = normalizedAlgorithm.digest(algorithm, data)
        return resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * generateKey
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  generateKey (algorithm, extractable, keyUsages) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('generateKey', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      try {
        let result = normalizedAlgorithm.generateKey(algorithm, extractable, keyUsages)

        if (result instanceof CryptoKey) {
          let {type,usages} = result
          let restricted = (type === 'secret' || type === 'private')
          let emptyUsages = (!usages || usages.length === 0)

          if (restricted && emptyUsages) {
            throw new SyntaxError()
          }
        }

        if (result instanceof CryptoKeyPair) {
          let {privateKey:{usages}} = result

          if (!usages || usages.length === 0) {
            throw new SyntaxError()
          }
        }

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * deriveKey
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} baseKey
   * @param {AlgorithmIdentifier} derivedKeyType
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   * @returns {Promise}
   */
  deriveKey (algorithm, baseKey, derivedKeyType, extractable, keyUsages) {
    return new Promise()
  }

  /**
   * deriveBits
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} baseKey
   * @param {number} length
   *
   * @returns {Promise}
   */
  deriveBits (algorithm, baseKey, length) {
    return new Promise()
  }

  /**
   * importKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {BufferSource|JWK} keyData
   * @param {AlgorithmIdentifier} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  importKey (format, keyData, algorithm, extractable, keyUsages) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('importKey', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (format === 'raw' || format === 'pkcs8' || format === 'spki') {
        if (keyData instanceof JsonWebKey) {
          throw new TypeError()
        }

        keyData = keyData.slice()
      }

      if (format === 'jwk') {
        keyData = new JsonWebKey(keyData)

        if (!(keyData instanceof JsonWebKey)) {
          throw new TypeError('key is not a JSON Web Key')
        }
      }

      try {
        let result = normalizedAlgorithm
          .importKey(format, keyData, algorithm, extractable, keyUsages)

        if (result.type === 'secret' || result.type === 'private') {
          if (!result.usages || result.usages.length === 0) {
            throw new SyntaxError()
          }
        }

        result.extractable = extractable
        result.usages = recognizedKeyUsages.normalize(keyUsages)

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * exportKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {CryptoKey} key
   *
   * @returns {Promise}
   */
  exportKey (format, key) {
    return new Promise((resolve, reject) => {
      try {
        let registeredAlgorithms = supportedAlgorithms['exportKey']

        if (!registeredAlgorithms[key.algorithm.name]) {
          throw new NotSupportedError(key.algorithm.name)
        }

        if (key.extractable === false) {
          throw new InvalidAccessError('Key is not extractable')
        }

        let result = key.algorithm.exportKey(format, key)

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * wrapKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {CryptoKey} key
   * @param {CryptoKey} wrappingKey
   * @param {AlgorithmIdentifier} wrapAlgorithm
   *
   * @returns {Promise}
   */
  wrapKey (format, key, wrappingKey, wrapAlgorithm) {
    // 1. Parameters
    // 2. Setup normalizedAlgorithm with op as 'unwrap'
    let normalizedAlgorithm = supportedAlgorithms.normalize('wrapKey', wrapAlgorithm)
    if (normalizedAlgorithm instanceof Error) {
      // 3. If failed, then try again with op as 'encrypt'
      normalizedAlgorithm = supportedAlgorithms.normalize('encrypt', wrapAlgorithm)
    }
    // 4. Otherwise reject outright
    if (normalizedAlgorithm instanceof Error)  {
      return Promise.reject(normalizedAlgorithm)
    }
    // 5-6. Setup and asynchronously return a new promise
    return new Promise((resolve, reject) => {
      // 7. Try catch the following step...
      // if anything goes wrong then reject the promise outright
      try {
          // 8. Validate normalizedAlgorithm name property
          if (normalizedAlgorithm.name !== wrappingKey.algorithm.name) {
            throw new InvalidAccessError('NormalizedAlgorthm name must be same as wrappingKey algorithm name')
          }

          // 9. Validate usages property contains wrap
          if (!wrappingKey.usages.includes('wrapKey')) {
            throw new InvalidAccessError('Wrapping key usages must include "wrapKey"')
          }

          // 10. Validate algorithm contains exportKey
          let exportKeyAlgorithms = supportedAlgorithms['exportKey']
          if (!exportKeyAlgorithms[key.algorithm.name]) {
            throw new NotSupportedError(key.algorithm.name)
          }

          // 11. Validate extractable property
          if (key.extractable === false) {
            throw new InvalidAccessError('Key is not extractable')
          }

          // 12. Generate extracted key
          return this.exportKey(format,key)
                .then(exportedKey => {
                  let bytes
                  // 13.1. If format is "raw", "pkcs8", or "spki":
                   if (["raw", "pkcs8","spki"].includes(format)) {
                    bytes = exportedKey
                  }
                  // 13.2. If format is "jwk"
                  else if (format === "jwk"){
                    let json = JSON.stringify(exportedKey)
                    bytes = new TextEncoder().encode(json)
                  }
                  // 14.1. If the normalizedAlgorithm supports wrapKey then use it
                  if (normalizedAlgorithm['wrapKey']){
                    return normalizedAlgorithm.wrapKey(wrapAlgorithm,wrappingKey,new Uint8Array(bytes))
                  }
                  // 14.2. Otherwise try with encrypt
                  else if (normalizedAlgorithm['encrypt']){
                    return normalizedAlgorithm.encrypt(wrapAlgorithm,wrappingKey,new Uint8Array(bytes))
                  }
                  // 14.3. Otherwise throw error
                  else {
                    return reject (new NotSupportedError(normalizedAlgorithm.name))
                  }
                })
                // 15 Return the resulting promise
                .then(resolve)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * unwrapKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {BufferSource} wrappedKey
   * @param {CryptoKey} unwrappingKey
   * @param {AlgorithmIdentifier} unwrapAlgorithm
   * @param {AlgorithmIdentifier} unwrappedKeyAlgorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  unwrapKey (format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, exractable, keyUsages) {
    return new Promise()
  }
}

/**
 * Export
 */
module.exports = SubtleCrypto

// const AES_GCM = require('./algorithms/AES-GCM')

// aes = new AES_GCM({ name: "AES-GCM", length: 256 })
// key = aes.importKey(
//     "jwk",
//     {
//         kty: "oct",
//         k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
//         alg: "A256GCM",
//         ext: true,
//     },
//     {
//         name: "AES-GCM",
//     },
//     true,
//     ["encrypt", "decrypt","wrapKey"]
// )
// let SC = new SubtleCrypto()
// let x = SC.wrapKey('jwk',key,key,{name:"AES-GCM",iv: new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])})
// x.then(result => console.log("is this working?",new Uint8Array(result)))

<commit_msg>wip(SubtleCrypto): completed unwrap function call<commit_after>/**
 * Local dependencies
 */
const CryptoKey = require('./keys/CryptoKey')
const CryptoKeyPair = require('./keys/CryptoKeyPair')
const JsonWebKey = require('./keys/JsonWebKey')
const recognizedKeyUsages = require('./keys/recognizedKeyUsages')
const supportedAlgorithms = require('./algorithms')
const {InvalidAccessError, NotSupportedError} = require('./errors')
const {TextEncoder,TextDecoder} = require('text-encoding')

/**
 * SubtleCrypto
 */
class SubtleCrypto {

  /**
   * encrypt
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  encrypt (algorithm, key, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('encrypt', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('encrypt')) {
        throw new InvalidAccessError('Key usages must include "encrypt"')
      }

      let ciphertext = normalizedAlgorithm.encrypt(algorithm,key, data)

      resolve(ciphertext)
    })
  }

  /**
   * decrypt
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  decrypt (algorithm, key, data) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('decrypt', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    data = data.slice()

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('decrypt')) {
        throw new InvalidAccessError('Key usages must include "decrypt"')
      }

      let plaintext = normalizedAlgorithm.decrypt(algorithm, key, data)
      resolve(plaintext)
    })
  }

  /**
   * sign
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  sign (algorithm, key, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('sign', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('sign')) {
        throw new InvalidAccessError('Key usages must include "sign"')
      }

      let result = normalizedAlgorithm.sign(key, data)

      resolve(result)
    })
  }

  /**
   * verify
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} key
   * @param {BufferSource} signature
   * @param {BufferSource} data
   *
   * @returns {Promise}
   */
  verify (alg, key, signature, data) {
    signature = signature.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('verify', alg)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    data = data.slice()

    return new Promise((resolve, reject) => {
      if (normalizedAlgorithm.name !== key.algorithm.name) {
        throw new InvalidAccessError('Algorithm does not match key')
      }

      if (!key.usages.includes('verify')) {
        throw new InvalidAccessError('Key usages must include "verify"')
      }

      let result = normalizedAlgorithm.verify(key, signature, data)
      resolve(result)
    })
  }

  /**
   * digest
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {BufferSource} data
   *
   * @returns {Promise.<ArrayBuffer>}
   */
  digest (algorithm, data) {
    data = data.slice()

    let normalizedAlgorithm = supportedAlgorithms.normalize('digest', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      try {
        let result = normalizedAlgorithm.digest(algorithm, data)
        return resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * generateKey
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  generateKey (algorithm, extractable, keyUsages) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('generateKey', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      try {
        let result = normalizedAlgorithm.generateKey(algorithm, extractable, keyUsages)

        if (result instanceof CryptoKey) {
          let {type,usages} = result
          let restricted = (type === 'secret' || type === 'private')
          let emptyUsages = (!usages || usages.length === 0)

          if (restricted && emptyUsages) {
            throw new SyntaxError()
          }
        }

        if (result instanceof CryptoKeyPair) {
          let {privateKey:{usages}} = result

          if (!usages || usages.length === 0) {
            throw new SyntaxError()
          }
        }

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * deriveKey
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} baseKey
   * @param {AlgorithmIdentifier} derivedKeyType
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   * @returns {Promise}
   */
  deriveKey (algorithm, baseKey, derivedKeyType, extractable, keyUsages) {
    return new Promise()
  }

  /**
   * deriveBits
   *
   * @description
   *
   * @param {AlgorithmIdentifier} algorithm
   * @param {CryptoKey} baseKey
   * @param {number} length
   *
   * @returns {Promise}
   */
  deriveBits (algorithm, baseKey, length) {
    return new Promise()
  }

  /**
   * importKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {BufferSource|JWK} keyData
   * @param {AlgorithmIdentifier} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  importKey (format, keyData, algorithm, extractable, keyUsages) {
    let normalizedAlgorithm = supportedAlgorithms.normalize('importKey', algorithm)

    if (normalizedAlgorithm instanceof Error) {
      return Promise.reject(normalizedAlgorithm)
    }

    return new Promise((resolve, reject) => {
      if (format === 'raw' || format === 'pkcs8' || format === 'spki') {
        if (keyData instanceof JsonWebKey) {
          throw new TypeError()
        }

        keyData = keyData.slice()
      }

      if (format === 'jwk') {
        keyData = new JsonWebKey(keyData)

        if (!(keyData instanceof JsonWebKey)) {
          throw new TypeError('key is not a JSON Web Key')
        }
      }

      try {
        let result = normalizedAlgorithm
          .importKey(format, keyData, algorithm, extractable, keyUsages)

        if (result.type === 'secret' || result.type === 'private') {
          if (!result.usages || result.usages.length === 0) {
            throw new SyntaxError()
          }
        }

        result.extractable = extractable
        result.usages = recognizedKeyUsages.normalize(keyUsages)

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * exportKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {CryptoKey} key
   *
   * @returns {Promise}
   */
  exportKey (format, key) {
    return new Promise((resolve, reject) => {
      try {
        let registeredAlgorithms = supportedAlgorithms['exportKey']

        if (!registeredAlgorithms[key.algorithm.name]) {
          throw new NotSupportedError(key.algorithm.name)
        }

        if (key.extractable === false) {
          throw new InvalidAccessError('Key is not extractable')
        }

        let result = key.algorithm.exportKey(format, key)

        resolve(result)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * wrapKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {CryptoKey} key
   * @param {CryptoKey} wrappingKey
   * @param {AlgorithmIdentifier} wrapAlgorithm
   *
   * @returns {Promise}
   */
  wrapKey (format, key, wrappingKey, wrapAlgorithm) {
    // 1. Parameters
    // 2. Setup normalizedAlgorithm with op as 'unwrap'
    let normalizedAlgorithm = supportedAlgorithms.normalize('wrapKey', wrapAlgorithm)
    if (normalizedAlgorithm instanceof Error) {
      // 3. If failed, then try again with op as 'encrypt'
      normalizedAlgorithm = supportedAlgorithms.normalize('encrypt', wrapAlgorithm)
    }
    // 4. Otherwise reject outright
    if (normalizedAlgorithm instanceof Error)  {
      return Promise.reject(normalizedAlgorithm)
    }
    // 5-6. Setup and asynchronously return a new promise
    return new Promise((resolve, reject) => {
      // 7. Try catch the following step...
      // if anything goes wrong then reject the promise outright
      try {
          // 8. Validate normalizedAlgorithm name property
          if (normalizedAlgorithm.name !== wrappingKey.algorithm.name) {
            throw new InvalidAccessError('NormalizedAlgorthm name must be same as wrappingKey algorithm name')
          }

          // 9. Validate usages property contains wrap
          if (!wrappingKey.usages.includes('wrapKey')) {
            throw new InvalidAccessError('Wrapping key usages must include "wrapKey"')
          }

          // 10. Validate algorithm contains exportKey
          let exportKeyAlgorithms = supportedAlgorithms['exportKey']
          if (!exportKeyAlgorithms[key.algorithm.name]) {
            throw new NotSupportedError(key.algorithm.name)
          }

          // 11. Validate extractable property
          if (key.extractable === false) {
            throw new InvalidAccessError('Key is not extractable')
          }

          // 12. Generate extracted key
          return this.exportKey(format,key)
                .then(exportedKey => {
                  let bytes
                  // 13.1. If format is "raw", "pkcs8", or "spki":
                   if (["raw", "pkcs8","spki"].includes(format)) {
                    bytes = exportedKey
                  }
                  // 13.2. If format is "jwk"
                  else if (format === "jwk"){
                    let json = JSON.stringify(exportedKey)
                    bytes = new TextEncoder().encode(json)
                  }
                  // 14.1. If the normalizedAlgorithm supports wrapKey then use it
                  if (normalizedAlgorithm['wrapKey']){
                    return normalizedAlgorithm.wrapKey(wrapAlgorithm,wrappingKey,new Uint8Array(bytes))
                  }
                  // 14.2. Otherwise try with encrypt
                  else if (normalizedAlgorithm['encrypt']){
                    return normalizedAlgorithm.encrypt(wrapAlgorithm,wrappingKey,new Uint8Array(bytes))
                  }
                  // 14.3. Otherwise throw error
                  else {
                    return reject (new NotSupportedError(normalizedAlgorithm.name))
                  }
                })
                // 15. Return the resulting promise
                .then(resolve)
      } catch (error) {
        return reject(error)
      }
    })
  }

  /**
   * unwrapKey
   *
   * @description
   *
   * @param {KeyFormat} format
   * @param {BufferSource} wrappedKey
   * @param {CryptoKey} unwrappingKey
   * @param {AlgorithmIdentifier} unwrapAlgorithm
   * @param {AlgorithmIdentifier} unwrappedKeyAlgorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {Promise}
   */
  unwrapKey (format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages) {
    // 1. Parameters
    // 2. ?

    // 3. Setup normalizedAlgorithm with op as 'unwrap'
    let normalizedAlgorithm = supportedAlgorithms.normalize('unwrapKey', unwrapAlgorithm)
    if (normalizedAlgorithm instanceof Error) {
    // 4. If failed, then try again with op as 'encrypt'
      normalizedAlgorithm = supportedAlgorithms.normalize('decrypt', unwrapAlgorithm)
    }

    // 5. Otherwise reject outright
    if (normalizedAlgorithm instanceof Error)  {
      return Promise.reject(normalizedAlgorithm)
    }

    // 6. Setup normalizedKeyAlgorithm
    let normalizedKeyAlgorithm = supportedAlgorithms.normalize('importKey', unwrapAlgorithm)
    if (normalizedKeyAlgorithm instanceof Error) {
    // 7. If failed, then try again with op as 'encrypt'
      return Promise.reject(normalizedKeyAlgorithm)
    }

    // 8-9. Setup and asynchronously return a new promise
    return new Promise((resolve, reject) => {
      // 10. Try catch the following step...
      // if anything goes wrong then reject the promise outright
      try {
          // 11. Validate normalizedAlgorithm name property
          if (normalizedAlgorithm.name !== unwrappingKey.algorithm.name) {
            throw new InvalidAccessError('NormalizedAlgorthm name must be same as unwrappingKey algorithm name')
          }

          // 12. Validate usages property contains unwrap
          if (!unwrappingKey.usages.includes('unwrapKey')) {
            throw new InvalidAccessError('Unwrapping key usages must include "unwrapKey"')
          }

          let keyPromise
          // 13.1. If the normalizedAlgorithm supports unwrapKey then use it
          if (normalizedAlgorithm['unwrapKey']){
            keyPromise = this.unwrapKey(unwrapAlgorithm,unwrappingKey,wrappedKey)
          }

          // 13.2. Otherwise try with decrypt
          else if (normalizedAlgorithm['decrypt']){
            keyPromise = this.decrypt(unwrapAlgorithm,unwrappingKey,wrappedKey)
          }

          // 13.3. Otherwise throw error
          else {
            return reject (new NotSupportedError(normalizedAlgorithm.name))
          }

          return keyPromise.then( key => {
            let bytes
            // 14.1. If format is "raw", "pkcs8", or "spki":
              if (["raw", "pkcs8","spki"].includes(format)) {
              bytes = key
            }

            // 14.2. If format is "jwk"
            else if (format === "jwk"){
              bytes = JSON.parse(new TextDecoder().decode(key))
              console.log("bytes",bytes)
            }

            // 15. Import the resulting unwrapped content
            //  importKey (format, keyData, algorithm, extractable, keyUsages)
            return normalizedKeyAlgorithm.importKey(format,
                                            bytes,
                                            unwrappedKeyAlgorithm,
                                            extractable,
                                            keyUsages)
          }).then(result => {
            // 16. Validate type parameters and usage length
            if ((result.type === "secret" || result.type === "private") && result.usages.length === 0){
              throw new SyntaxError("Usages cannot be empty")
            }

            // 17. Set extractable
            result.extractable = extractable

            // 18. Set usages
            result.usages = keyUsages

            // 19. Resolve promise
            return resolve(result)
          }).catch(console.log)
      } catch (error) {
        return reject(error)
      }
    })
  }
}

/**
 * Export
 */
module.exports = SubtleCrypto

// const AES_GCM = require('./algorithms/AES-GCM')

// aes = new AES_GCM({ name: "AES-GCM", length: 256 })
// key = aes.importKey(
//     "jwk",
//     {
//         kty: "oct",
//         k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
//         alg: "A256GCM",
//         ext: true,
//     },
//     {
//         name: "AES-GCM",
//     },
//     true,
//     ["encrypt", "decrypt","wrapKey","unwrapKey"]
// )
// let SC = new SubtleCrypto()

// let x = SC.wrapKey('jwk',key,key,{name:"AES-GCM",iv: new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])})
// x.then(result => console.log("is this working?",JSON.stringify(Array.from(new Uint8Array(result))),new Uint8Array(result).length))

// let wc = new Uint8Array([
//   161, 111, 8, 29, 75, 53, 230, 127, 59, 123, 74, 164, 212, 248, 8,
//   118, 77, 163, 181, 229, 178, 102, 47, 241, 15, 21, 165, 199, 188,
//   70, 180, 186, 130, 108, 22, 194, 178, 189, 218, 129, 99, 220, 189,
//   173, 65, 196, 48, 254, 194, 241, 242, 76, 26, 125, 53, 110, 200,
//   129, 229, 237, 142, 222, 49, 159, 156, 88, 8, 7, 124, 186, 207, 42,
//   236, 235, 65, 210, 182, 85, 91, 37, 84, 102, 49, 40, 156, 132, 128,
//   181, 198, 118, 104, 191, 21, 124, 54, 45, 122, 238, 195, 207,
//   112, 241, 214, 194, 112, 112, 89, 246, 223, 170, 149, 175, 128, 240,
//   184, 64, 134, 230, 203, 23, 48, 55, 94, 57, 102, 249, 11, 254,
//   163, 199, 68, 122, 112, 46, 14, 239, 198, 173, 58, 86, 251, 222, 217,
//   108, 233, 161, 227, 112
// ])

// SC.unwrapKey(
//   'jwk',
//   wc,
//   key,
//   {
//     name:"AES-GCM",
//     iv: new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]),
//     tagLength: 128
//   },
//   {
//       name: "AES-GCM",
//       length: 256
//   },
//   true,
//   ["encrypt","decrypt","unwrapKey"]
// ).then(key => SC.exportKey("jwk",key) ).then(console.log).catch(console.error)

<|endoftext|>


<commit_before>// URL: https://beta.observablehq.com/@randomfractals/chicago-community-areas
// Title: Chicago Community Areas
// Author: Taras Novak (@randomfractals)
// Version: 136
// Runtime version: 1

const m0 = {
  id: "fe14c39662a972fa@136",
  variables: [
    {
      inputs: ["md"],
      value: (function(md){return(
md`# Chicago Community Areas

Chicago is divided into 77 community areas and 9 sides as defined by the Social Science Research Committee at the University of Chicago back in 2012:

https://en.wikipedia.org/wiki/Community_areas_in_Chicago
`
)})
    },
    {
      inputs: ["html"],
      value: (function(html){return(
html `<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Map_of_the_Community_Areas_and_%27Sides%27_of_the_City_of_Chicago.svg"></img>`
)})
    },
    {
      inputs: ["md"],
      value: (function(md){return(
md `## Mapping Chicago Communites with [Vega Lite Embed Geo Projection](https://vega.github.io/vega-lite/docs/projection.html)`
)})
    },
    {
      name: "embed",
      inputs: ["require"],
      value: (function(require){return(
require("vega-embed@3")
)})
    },
    {
      name: "viewof map",
      inputs: ["embed","width","layers"],
      value: (function(embed,width,layers){return(
embed({
  width: width,
  height: width * .6,
  layer: layers,
  config: {
    view: {stroke: 'transparent'}
  }
})
)})
    },
    {
      name: "map",
      inputs: ["Generators","viewof map"],
      value: (G, _) => G.input(_)
    },
    {
      inputs: ["map"],
      value: (function(map){return(
map.renderer('svg').run()
)})
    },
    {
      name: "layers",
      inputs: ["topoJsonUrl","outlineColor"],
      value: (function(topoJsonUrl,outlineColor){return(
[{
  data: {
    url: topoJsonUrl,
    format: {
      type: 'topojson',
      feature: 'chicago-community-areas'
    },
  },
  projection: {
    type: 'mercator',
  },
  mark: 'geoshape',
  encoding: {
    stroke: {value: outlineColor},
    fill: {value: '#ccc'}, // colors[i % colors.length]},
    // "fill": {
    //   "field": "properties.AWATER",
    //   "type": "quantitative"
    // },
    tooltip: [
      {field: 'properties.community', type: 'nominal', title: 'Community'},
    ],
  },
}]
)})
    },
    {
      name: "colors",
      inputs: ["d3"],
      value: (function(d3){return(
d3[`scheme${'Pastel1'}`]
)})
    },
    {
      name: "outlineColor",
      value: (function(){return(
'#333'
)})
    },
    {
      name: "hoverStyle",
      inputs: ["html"],
      value: (function(html){return(
html`
<style>
  .vega-embed .mark-shape path:hover {
    fill-opacity: 0.5;
    fill: #000 !important;
  }
</style>
`
)})
    },
    {
      inputs: ["md"],
      value: (function(md){return(
md `## Chicago Communities Data`
)})
    },
    {
      name: "topoJsonUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.topojson'
)})
    },
    {
      name: "geoJsonUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.geojson'
)})
    },
    {
      name: "dataUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.csv'
)})
    },
    {
      name: "d3",
      inputs: ["require"],
      value: (function(require){return(
require('d3')
)})
    },
    {
      name: "geoData",
      inputs: ["d3","geoJsonUrl"],
      value: (function(d3,geoJsonUrl){return(
d3.json(geoJsonUrl)
)})
    },
    {
      name: "communityData",
      inputs: ["d3","dataUrl"],
      value: (function(d3,dataUrl){return(
d3.csv(dataUrl)
)})
    },
    {
      name: "sides",
      inputs: ["communityData"],
      value: (function(communityData)
{
  // group communities by side
  const sides = {}
  communityData.slice(1) // skip 1st null row
    .map(community => {
      if (!sides[community.Side]) {
        sides[community.Side] = [];
      }
      sides[community.Side].push(community);
    });
  return sides;
}
)
    },
    {
      name: "communities",
      inputs: ["communityData"],
      value: (function(communityData)
{
  // create communities info map
  const communities = {}
  communityData.slice(1) // skip 1st null row
    .map(community => communities[community.CommunityName.toLowerCase()] = community);
  return communities;
}
)
    },
    {
      name: "features",
      inputs: ["addCommunityInfo","geoData","communities"],
      value: (function(addCommunityInfo,geoData,communities){return(
addCommunityInfo(geoData, communities)
)})
    },
    {
      name: "addCommunityInfo",
      value: (function(){return(
function addCommunityInfo(geoData, communities) {
  geoData.features.map(feature => {
    // replace community name with community info
    const communityName = feature.properties.community.toLowerCase();
    feature.properties.community = communities[communityName];
  });
  return geoData.features;
}
)})
    }
  ]
};

const notebook = {
  id: "fe14c39662a972fa@136",
  modules: [m0]
};

export default notebook;
<commit_msg>vega lite grey chicago community areas map code clean<commit_after>// URL: https://beta.observablehq.com/@randomfractals/chicago-community-areas
// Title: Chicago Community Areas
// Author: Taras Novak (@randomfractals)
// Version: 141
// Runtime version: 1

const m0 = {
  id: "fe14c39662a972fa@141",
  variables: [
    {
      inputs: ["md"],
      value: (function(md){return(
md`# Chicago Community Areas

Chicago is divided into 77 community areas and 9 sides as defined by the Social Science Research Committee at the University of Chicago back in 2012:

https://en.wikipedia.org/wiki/Community_areas_in_Chicago
`
)})
    },
    {
      inputs: ["html"],
      value: (function(html){return(
html `<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Map_of_the_Community_Areas_and_%27Sides%27_of_the_City_of_Chicago.svg"></img>`
)})
    },
    {
      inputs: ["md"],
      value: (function(md){return(
md `## Mapping Chicago Communites with [Vega Lite Embed Geo Projection](https://vega.github.io/vega-lite/docs/projection.html)`
)})
    },
    {
      name: "embed",
      inputs: ["require"],
      value: (function(require){return(
require("vega-embed@3")
)})
    },
    {
      name: "viewof map",
      inputs: ["embed","width","layers"],
      value: (function(embed,width,layers){return(
embed({
  width: width,
  height: width * .6,
  layer: layers,
  config: {
    view: {stroke: 'transparent'}
  }
})
)})
    },
    {
      name: "map",
      inputs: ["Generators","viewof map"],
      value: (G, _) => G.input(_)
    },
    {
      inputs: ["map"],
      value: (function(map){return(
map.renderer('svg').run()
)})
    },
    {
      name: "layers",
      inputs: ["topoJsonUrl"],
      value: (function(topoJsonUrl){return(
[{
  data: {
    url: topoJsonUrl,
    format: {
      type: 'topojson',
      feature: 'chicago-community-areas'
    },
  },
  projection: {
    type: 'mercator',
  },
  mark: 'geoshape',
  encoding: {
    stroke: {value: '#333'},
    fill: {value: '#ccc'},
    tooltip: [
      {field: 'properties.community', type: 'nominal', title: 'Community'},
    ],
  },
}]
)})
    },
    {
      name: "sideColors",
      inputs: ["d3"],
      value: (function(d3){return(
d3[`scheme${'Pastel1'}`]
)})
    },
    {
      name: "hoverStyle",
      inputs: ["html"],
      value: (function(html){return(
html`
<style>
  .vega-embed .mark-shape path:hover {
    fill-opacity: 0.5;
    fill: #000 !important;
  }
</style>
`
)})
    },
    {
      inputs: ["md"],
      value: (function(md){return(
md `## Chicago Communities Data`
)})
    },
    {
      name: "topoJsonUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.topojson'
)})
    },
    {
      name: "geoJsonUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.geojson'
)})
    },
    {
      name: "dataUrl",
      value: (function(){return(
'https://raw.githubusercontent.com/RandomFractals/ChicagoCrimes/master/data/chicago-community-areas.csv'
)})
    },
    {
      name: "d3",
      inputs: ["require"],
      value: (function(require){return(
require('d3')
)})
    },
    {
      name: "geoData",
      inputs: ["d3","geoJsonUrl"],
      value: (function(d3,geoJsonUrl){return(
d3.json(geoJsonUrl)
)})
    },
    {
      name: "communityData",
      inputs: ["d3","dataUrl"],
      value: (function(d3,dataUrl){return(
d3.csv(dataUrl)
)})
    },
    {
      name: "sides",
      inputs: ["communityData"],
      value: (function(communityData)
{
  // group communities by side
  const sides = {}
  communityData.slice(1) // skip 1st null row
    .map(community => {
      if (!sides[community.Side]) {
        sides[community.Side] = [];
      }
      sides[community.Side].push(community);
    });
  return sides;
}
)
    },
    {
      name: "communities",
      inputs: ["communityData"],
      value: (function(communityData)
{
  // create communities info map
  const communities = {}
  communityData.slice(1) // skip 1st null row
    .map(community => communities[community.CommunityName.toLowerCase()] = community);
  return communities;
}
)
    },
    {
      name: "features",
      inputs: ["addCommunityInfo","geoData","communities"],
      value: (function(addCommunityInfo,geoData,communities){return(
addCommunityInfo(geoData, communities)
)})
    },
    {
      name: "addCommunityInfo",
      value: (function(){return(
function addCommunityInfo(geoData, communities) {
  geoData.features.map(feature => {
    // replace community name with community info
    const communityName = feature.properties.community.toLowerCase();
    feature.properties.community = communities[communityName];
  });
  return geoData.features;
}
)})
    }
  ]
};

const notebook = {
  id: "fe14c39662a972fa@141",
  modules: [m0]
};

export default notebook;
<|endoftext|>