<commit_before>/**
 * reader.js
 *
 * Reads in a well formated xlsx to produce a CSV for ingest into Archivematica and DAMS
 */
var xlsx = require('xlsx');
var mkdirp = require('mkdirp');
var rimraf = require('rimraf');
var stringify = require('csv-stringify');
var BCollection = require('./assets/js/brays_model.js');

var metadata_array = [];
var locationpath = '';
var subdir = 'ingest';
var process_counter = 0;
var process_total = 0;
var rolling_back = false;

$(document).ready(function(){

  /** Prevent window from doing default drag and drop actions **/
  $(document).on('dragenter dragover', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });
  $(document).on('drop', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });

  $('#dnd').on('dragenter', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });
  $('#dnd').on('dragover', function(e) {
    e.preventDefault();
    e.stopPropagation();
    $('#dnd').addClass('draghover');
  });
  $('#dnd').on('dragleave', function(e){
    $('#dnd').removeClass('draghover');
  });
  $('#dnd').on('drop', function(e){
    e.stopPropagation();
    e.preventDefault();

    var files = e.originalEvent.dataTransfer.files;

    logger.clear();

    for (var i = 0, f = files[i]; i != files.length; ++i){
      process_dnd_file(f);
    }
  });
});

/**
 * Opens the open file dialog to process a metadata file.
 */
function openFile() {
  logger.clear();
  dialog.showOpenDialog({ filters: [
    { name: 'Excel File', extensions: ['xlsx'] }
  ]},
  function (filenames){
    if (filenames === undefined) return;
    for (var k in filenames) {
      process_open_file(filenames[k]);
    }
  });
}

/**
 * Turns a xlsx worksheet object into a array containing metadata objects and files.
 *
 * @param Object worksheet
 * @return Array
 */
function build_metadata_array(worksheet) {
  var range = xlsx.utils.decode_range(worksheet['!ref']);

  var collections = [];
  var headers = [];
  for ( var R = range.s.r; R <= range.e.r; ++R ) {
    var item = {};
    for ( var C = range.s.c; C <= range.e.c; ++C ) {
      var cell = xlsx.utils.encode_cell({r: R, c: C});

      if ( R === 0 ) {
        headers[C] = worksheet[cell].v;
      }
      else {
        item[headers[C]] = ((worksheet[cell] !== undefined) ? worksheet[cell].v : '');
      }
    }

    if ( R > 0 ) {
      if ( item["COLL"] === 'x' ) {
        if (collection !== undefined) {
          collections.push(collection);
        }
        var collection = new BCollection(item["dc.title"]);
      }
      else if ( item["BOX"] === 'x' ) {
        if ( collection === undefined ) {
          logger.warn("There doesn't seem to be a collection level. I'll keep going assuming there isn't one");
          var collection = new BCollection();
        }
        collection.addBox(item["dc.title"]);
      }
      else if ( item["FOLDER"] === 'x' ) {
        collection.addFolder(item["dc.title"]);
      }
      else if ( item["OBJECT"] === 'x' ) {
        process_total++;

        collection.addObject(item);
      }
      else if ( item["FILE"] === 'x' ) {
        collection.addFile(item);
      }
    }
  }

  collections.push(collection);

  return collections;
}

/**
 * Reads in a xlsx file for processing metadata.
 *
 * @param Object f The file object
 */
function process_dnd_file(f) {
  var reader = new FileReader();
  var name = f.name;
  reader.onload = function(e) {
    var data = e.target.result;

    try {
      logger.log('Reading file: ' + f.path);
      var workbook = xlsx.read(data, {type: 'binary'});
    }
    catch (err) {
      logger.error('Error reading file: ' + err.message);
      dialog.showErrorBox("File Error", err.message);
      return;
    }

    process_metadata(workbook, f.path);
  };
  reader.readAsBinaryString(f);
}

/**
 * Reads in a xlsx file for processing metadata.
 *
 * @param String filename The files full path
 */
function process_open_file(filename) {
  try {
    logger.log('Reading file: ' + f.path);
    var workbook = xlsx.readFile(filename);
  }
  catch (err) {
    logger.error('Error reading file: ' + err.message);
    dialog.showErrorBox('Error reading file: ' + err.message);
    return;
  }
  process_metadata(workbook, filename);
}

/**
 * Process the metadata within the xlsx workbook
 *
 * @param Object workbook The xlsx workbook object
 */
function process_metadata(workbook, path) {
  process_total = 0;
  rolling_back = false;
  process_counter = 0;

  var worksheet = workbook.Sheets[workbook.SheetNames[0]];
  metadata_array = build_metadata_array(worksheet);
  if ( metadata_array === false ) return;

  locationpath = path.match(/.*[/\\]/);

  process_metadata_objects();
}

/**
 * Processes the metadata array into a format that can be used in Archivematica
 *
 * @param String locationpath The location where the xlsx lives long with the files
 * @param String subdir The sub directory to place all the processed files
 * @return Array
 */
function process_metadata_objects() {
  if (settings.mint_arks) {
    logger.log('Sending objects for minting...');
  }

  metadata_array.forEach(function(collection){
    var objects = collection.getObjects();
    objects.forEach(function(object){
      if (settings.mint_arks) {
        mint_object(object);
      }
      else {
        if ( !('dcterms.identifier' in object.metadata) ) {
          object.metadata['dcterms.identifier'] = '';
        }
        process_object_files(object);
      }
    });
  });
}

/**
 * Process all the files in a object
 *
 * @param Object object The item to process
 */
function process_object_files(object) {
    if ( rolling_back ) return;
    process_counter++;

    var id = object.metadata['dcterms.identifier'];
    var id_parts = id.split('/');
    var seq = (parseInt(object.index) + 1);
    object.parts += seq.toString().padLeft(4, "0") + ((id_parts[2] !== undefined) ? '_' + id_parts[2] : '');

    var part_types = ['ac', 'mm', 'pm'];
    object.files.forEach(function(file){
      part_types.forEach(function(type){
        file.setParts(object.parts);
        var part_dir = file.getPartsByType(type);
        if (part_dir) {
          var dest = locationpath + subdir + '/' + part_dir;
          object.parts_by_type[type] = part_dir;
          move_file(file.getFilename(type), dest);
        }
      });
    });

    if ( process_counter === process_total ) {
      output_am_csv_file();
    }
}

/**
 * Movies file to destination
 *
 * @param String filename The file name to be moved
 * @param String dest The destination path
 * @return Boolean True if move was successful
 */
function move_file(filename, dest) {
  mkdirp.sync(dest, function(err) {
    if (err) {
      logger.error('Failed to create object directory. "' + dirdest + '"');
      return false;
    }
  });

  var srcfilepath = locationpath + filename;

  try {
    fs.renameSync(srcfilepath, dest + '/' + filename);
    logger.log('Moved file "' + filename + '" to "' + dest + '"');
  }
  catch (err) {
    logger.error('Failed to move file "' + filename + '", ' + err.message);
    return false;
  }

  return true;
}

/**
 * Output the Archivematica CSV file from metadata_array
 */
function output_am_csv_file() {
  logger.log('Building Archivematica CSV...');
  var out = build_am_csv_array();
  var metadatadir = locationpath + subdir + '/metadata';
  mkdirp.sync(metadatadir);

  mkdirp.sync(locationpath + subdir + '/log');

  stringify(out, function(err, output) {
      writer.write(output, metadatadir + '/metadata.csv');
      logger.log('Saved CSV file');
      logger.log('Done');
  });
}

/**
 * Builds a array for CSV output from the metadata_array
 *
 * @return Array
 */
function build_am_csv_array() {
  // Build the headers for the AM output
  output_am_metadata = [[
    'parts',
    'dc.title',
    'dcterms.creator',
    'dcterms.date',
    'dcterms.description',
    'dcterms.publisher',
    'dcterms.isPartOf',
    'dc.rights',
    'dcterms.accessRights',
    'dcterms.identifier'
  ]];

  var part_types = ['ac', 'mm', 'pm'];
  metadata_array.forEach(function(collection){
    output_am_metadata.push(build_am_row_array({ parts: 'objects', "dc.title": collection.title }));
    var objects = collection.getObjects();
    part_types.forEach(function(type) {
      objects.forEach(function(object){
        var parts;
        if ( (parts = object.getPartsByType(type)) ) {
          output_am_metadata.push(build_am_row_array(Object.assign(
            object.metadata,
            { parts: parts }
          )));
          object.files.forEach(function(file){
            if (file.hasMetadata()) {
              output_am_metadata.push(build_am_row_array(Object.assign(
                file["metadata"],
                { parts: file.getPartsByType(type) + '/' + file.getFilename(type) }
              )));
            }
          });
        }
      });
    });
  });

  return output_am_metadata;
}

/**
 * Builds a single row that will be used in the AM ingest CSV
 *
 * @param Object item The item containing the metadata
 * @return Array The array formated for AM
 */
function build_am_row_array(item) {
  /*
   * Header columns
   *  parts
   *  dc.title
   *  dcterms.creator
   *  dcterms.date
   *  dc.description
   *  dcterms.publisher
   *  dcterms.isPartOf
   *  dc.rights
   *  dcterms.accessRights
   *  dcterms.identifier
   */
  return [
    item['parts'] || '',
    item['dc.title'] || '',
    item['dcterms.creator'] || '',
    item['dcterms.date'] || '',
    item['dcterms.description'] || '',
    item['dcterms.publisher'] || '',
    item['dcterms.isPartOf'] || '',
    item['dc.rights'] || '',
    item['dcterms.accessRights'] || '',
    item['dcterms.identifier'] || ''
  ];
}

/**
 * Walks the directory and subdirectory and returns an array of files.
 *
 * @param String dir The directory to walk
 * @param Array filelist The list of files found in walk
 * @return Array
 */
function walk(dir, filelist) {
  var files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(function(file) {
    if (fs.statSync(dir + '/' + file).isDirectory()) {
      filelist = walk(dir + '/' + file, filelist);
    }
    else {
      filelist.push(dir + '/' + file);
    }
  });
  return filelist;
}

/**
 * Mints an Ark for the given object
 *
 * @param Object object The item being minted
 * @param Int counter A counter keeping track of how many times we've gone around
 * @return String The ARK identifier
 */
function mint_object(object, counter) {
  if ( counter === undefined ) {
    counter = 0;
  }

  var post_data = {
    who: object.metadata['dcterms.creator'] || 'unknown',
    what: object.metadata['dc.title'],
    when: object.metadata['dcterms.date'] || 'unknown'
  };

  if ( settings.mint_url === '' || settings.api_key === '' ) {
    logger.error('Unable to mint. Please provide the URL and/or API key for the minter.');
    return;
  }

  $.ajax({
    url: settings.mint_url,
    headers: {
      'api-key': settings.api_key
    },
    dataType: 'json',
    method: 'POST',
    data: post_data,
    success: function (data) {
      var id = data['id'];
      logger.log('Identifier "' + id + '" => "' + object.metadata['dc.title'] + '"', 'good');
      object.metadata['dcterms.identifier'] = id;
      process_object_files(object);
    },
    error: function(data) {
      logger.warn('FAILED to mint "' + object.metadata['dc.title'] + '", trying again...');
      if ( counter > 5 ) {
        logger.error('FAILED to mint "' + object.metadata['dc.title'] + "\" for the last time");
        logger.error("Unable to get ARK identifier. Something bad must have happened so I'm quitting.");
        rollback();
      }
      else {
        mint_object(object, counter + 1);
      }
    }
  });
}

$(document).ajaxStop(function(){
  if ( process_counter !== process_total ) {
    logger.warn("Finished minting but processing didn't seem to finish. This doesn't seem right");
  }
});

/**
 * Rollback what has been done. This deletes all minted identifiers during the process and moves files back.
 */
function rollback(){
  rolling_back = true;
  logger.warn('ROLLING BACK TO ORIGINAL STATE...');

  if (settings.mint_arks) {
    metadata_array.forEach(function(collection){
      var objects = collection.getObjects();
      objects.forEach(function(object){
        var ark = object.metadata['dcterms.identifier'];
        if (ark !== undefined && ark !== '' && ~ark.indexOf('ark:/')) {
          delete_identifier(ark);
        }
      });
    });
  }

  logger.warn('Moving files back to "' + locationpath + '"');
  var files = walk(locationpath + subdir + '/objects');

  files.forEach(function(file){
    var filename = file.match(/[^\/\\]+$/)[0];
    try {
      fs.renameSync(file, locationpath + filename);
      logger.log('Moved file "' + filename + '" back to "' + locationpath + '"');
    } catch (err) {
      logger.error(err.message);
    }
  });

  if ( subdir !== '' && subdir !== '/' && subdir !== "\\") {
    var ignestpath = locationpath + subdir;
    logger.log('Removing ingest directory "' + ignestpath + '"');
    rimraf(ignestpath, function(err) { });
  }

  logger.warn('Done');
}

/**
 * Deletes the ARK identifier from the resolver.
 *
 * @param String ark The ARK identifier to delete
 */
function delete_identifier(ark){
  if (settings.destroy_url.slice(-1) !== '/') {
    settings.destroy_url += '/'
  }

  $.ajax({
    url: settings.destroy_url + ark,
    headers: {
      'api-key': settings.api_key
    },
    method: 'DELETE',
    success: function (data) {
      logger.log('Identifier "' + ark + '" successfully destoryed');
    }
  });
}<commit_msg>updated namespace mapping for AM output<commit_after>/**
 * reader.js
 *
 * Reads in a well formated xlsx to produce a CSV for ingest into Archivematica and DAMS
 */
var xlsx = require('xlsx');
var mkdirp = require('mkdirp');
var rimraf = require('rimraf');
var stringify = require('csv-stringify');
var BCollection = require('./assets/js/brays_model.js');

var metadata_array = [];
var locationpath = '';
var subdir = 'ingest';
var process_counter = 0;
var process_total = 0;
var rolling_back = false;

$(document).ready(function(){

  /** Prevent window from doing default drag and drop actions **/
  $(document).on('dragenter dragover', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });
  $(document).on('drop', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });

  $('#dnd').on('dragenter', function(e) {
    e.preventDefault();
    e.stopPropagation();
  });
  $('#dnd').on('dragover', function(e) {
    e.preventDefault();
    e.stopPropagation();
    $('#dnd').addClass('draghover');
  });
  $('#dnd').on('dragleave', function(e){
    $('#dnd').removeClass('draghover');
  });
  $('#dnd').on('drop', function(e){
    e.stopPropagation();
    e.preventDefault();

    var files = e.originalEvent.dataTransfer.files;

    logger.clear();

    for (var i = 0, f = files[i]; i != files.length; ++i){
      process_dnd_file(f);
    }
  });
});

/**
 * Opens the open file dialog to process a metadata file.
 */
function openFile() {
  logger.clear();
  dialog.showOpenDialog({ filters: [
    { name: 'Excel File', extensions: ['xlsx'] }
  ]},
  function (filenames){
    if (filenames === undefined) return;
    for (var k in filenames) {
      process_open_file(filenames[k]);
    }
  });
}

/**
 * Turns a xlsx worksheet object into a array containing metadata objects and files.
 *
 * @param Object worksheet
 * @return Array
 */
function build_metadata_array(worksheet) {
  var range = xlsx.utils.decode_range(worksheet['!ref']);

  var collections = [];
  var headers = [];
  for ( var R = range.s.r; R <= range.e.r; ++R ) {
    var item = {};
    for ( var C = range.s.c; C <= range.e.c; ++C ) {
      var cell = xlsx.utils.encode_cell({r: R, c: C});

      if ( R === 0 ) {
        headers[C] = worksheet[cell].v;
      }
      else {
        item[headers[C]] = ((worksheet[cell] !== undefined) ? worksheet[cell].v : '');
      }
    }

    if ( R > 0 ) {
      if ( item["COLL"] === 'x' ) {
        if (collection !== undefined) {
          collections.push(collection);
        }
        var collection = new BCollection(item["dc.title"]);
      }
      else if ( item["BOX"] === 'x' ) {
        if ( collection === undefined ) {
          logger.warn("There doesn't seem to be a collection level. I'll keep going assuming there isn't one");
          var collection = new BCollection();
        }
        collection.addBox(item["dc.title"]);
      }
      else if ( item["FOLDER"] === 'x' ) {
        collection.addFolder(item["dc.title"]);
      }
      else if ( item["OBJECT"] === 'x' ) {
        process_total++;

        collection.addObject(item);
      }
      else if ( item["FILE"] === 'x' ) {
        collection.addFile(item);
      }
    }
  }

  collections.push(collection);

  return collections;
}

/**
 * Reads in a xlsx file for processing metadata.
 *
 * @param Object f The file object
 */
function process_dnd_file(f) {
  var reader = new FileReader();
  var name = f.name;
  reader.onload = function(e) {
    var data = e.target.result;

    try {
      logger.log('Reading file: ' + f.path);
      var workbook = xlsx.read(data, {type: 'binary'});
    }
    catch (err) {
      logger.error('Error reading file: ' + err.message);
      dialog.showErrorBox("File Error", err.message);
      return;
    }

    process_metadata(workbook, f.path);
  };
  reader.readAsBinaryString(f);
}

/**
 * Reads in a xlsx file for processing metadata.
 *
 * @param String filename The files full path
 */
function process_open_file(filename) {
  try {
    logger.log('Reading file: ' + f.path);
    var workbook = xlsx.readFile(filename);
  }
  catch (err) {
    logger.error('Error reading file: ' + err.message);
    dialog.showErrorBox('Error reading file: ' + err.message);
    return;
  }
  process_metadata(workbook, filename);
}

/**
 * Process the metadata within the xlsx workbook
 *
 * @param Object workbook The xlsx workbook object
 */
function process_metadata(workbook, path) {
  process_total = 0;
  rolling_back = false;
  process_counter = 0;

  var worksheet = workbook.Sheets[workbook.SheetNames[0]];
  metadata_array = build_metadata_array(worksheet);
  if ( metadata_array === false ) return;

  locationpath = path.match(/.*[/\\]/);

  process_metadata_objects();
}

/**
 * Processes the metadata array into a format that can be used in Archivematica
 *
 * @param String locationpath The location where the xlsx lives long with the files
 * @param String subdir The sub directory to place all the processed files
 * @return Array
 */
function process_metadata_objects() {
  if (settings.mint_arks) {
    logger.log('Sending objects for minting...');
  }

  metadata_array.forEach(function(collection){
    var objects = collection.getObjects();
    objects.forEach(function(object){
      if (settings.mint_arks) {
        mint_object(object);
      }
      else {
        if ( !('dcterms.identifier' in object.metadata) ) {
          object.metadata['dcterms.identifier'] = '';
        }
        process_object_files(object);
      }
    });
  });
}

/**
 * Process all the files in a object
 *
 * @param Object object The item to process
 */
function process_object_files(object) {
    if ( rolling_back ) return;
    process_counter++;

    var id = object.metadata['dcterms.identifier'];
    var id_parts = id.split('/');
    var seq = (parseInt(object.index) + 1);
    object.parts += seq.toString().padLeft(4, "0") + ((id_parts[2] !== undefined) ? '_' + id_parts[2] : '');

    var part_types = ['ac', 'mm', 'pm'];
    object.files.forEach(function(file){
      part_types.forEach(function(type){
        file.setParts(object.parts);
        var part_dir = file.getPartsByType(type);
        if (part_dir) {
          var dest = locationpath + subdir + '/' + part_dir;
          object.parts_by_type[type] = part_dir;
          move_file(file.getFilename(type), dest);
        }
      });
    });

    if ( process_counter === process_total ) {
      output_am_csv_file();
    }
}

/**
 * Movies file to destination
 *
 * @param String filename The file name to be moved
 * @param String dest The destination path
 * @return Boolean True if move was successful
 */
function move_file(filename, dest) {
  mkdirp.sync(dest, function(err) {
    if (err) {
      logger.error('Failed to create object directory. "' + dirdest + '"');
      return false;
    }
  });

  var srcfilepath = locationpath + filename;

  try {
    fs.renameSync(srcfilepath, dest + '/' + filename);
    logger.log('Moved file "' + filename + '" to "' + dest + '"');
  }
  catch (err) {
    logger.error('Failed to move file "' + filename + '", ' + err.message);
    return false;
  }

  return true;
}

/**
 * Output the Archivematica CSV file from metadata_array
 */
function output_am_csv_file() {
  logger.log('Building Archivematica CSV...');
  var out = build_am_csv_array();
  var metadatadir = locationpath + subdir + '/metadata';
  mkdirp.sync(metadatadir);

  mkdirp.sync(locationpath + subdir + '/log');

  stringify(out, function(err, output) {
      writer.write(output, metadatadir + '/metadata.csv');
      logger.log('Saved CSV file');
      logger.log('Done');
  });
}

/**
 * Builds a array for CSV output from the metadata_array
 *
 * @return Array
 */
function build_am_csv_array() {
  // Build the headers for the AM output
  output_am_metadata = [[
    'parts',
    'dcterms.title',
    'dcterms.creator',
    'dc.date',
    'dcterms.description',
    'dcterms.publisher',
    'dcterms.isPartOf',
    'dc.rights',
    'dcterms.accessRights',
    'dcterms.identifier'
  ]];

  var part_types = ['ac', 'mm', 'pm'];
  metadata_array.forEach(function(collection){
    output_am_metadata.push(build_am_row_array({ parts: 'objects', "dc.title": collection.title }));
    var objects = collection.getObjects();
    part_types.forEach(function(type) {
      objects.forEach(function(object){
        var parts;
        if ( (parts = object.getPartsByType(type)) ) {
          output_am_metadata.push(build_am_row_array(Object.assign(
            object.metadata,
            { parts: parts }
          )));
          object.files.forEach(function(file){
            if (file.hasMetadata()) {
              output_am_metadata.push(build_am_row_array(Object.assign(
                file["metadata"],
                { parts: file.getPartsByType(type) + '/' + file.getFilename(type) }
              )));
            }
          });
        }
      });
    });
  });

  return output_am_metadata;
}

/**
 * Builds a single row that will be used in the AM ingest CSV
 *
 * @param Object item The item containing the metadata
 * @return Array The array formated for AM
 */
function build_am_row_array(item) {
  /*
   * Header columns
   *  parts
   *  dcterms.title
   *  dcterms.creator
   *  dc.date
   *  dcterms.description
   *  dcterms.publisher
   *  dcterms.isPartOf
   *  dc.rights
   *  dcterms.accessRights
   *  dcterms.identifier
   */
  return [
    item['parts'] || '',
    item['dcterms.title'] || '',
    item['dcterms.creator'] || '',
    item['dc.date'] || '',
    item['dcterms.description'] || '',
    item['dcterms.publisher'] || '',
    item['dcterms.isPartOf'] || '',
    item['dc.rights'] || '',
    item['dcterms.accessRights'] || '',
    item['dcterms.identifier'] || ''
  ];
}

/**
 * Walks the directory and subdirectory and returns an array of files.
 *
 * @param String dir The directory to walk
 * @param Array filelist The list of files found in walk
 * @return Array
 */
function walk(dir, filelist) {
  var files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(function(file) {
    if (fs.statSync(dir + '/' + file).isDirectory()) {
      filelist = walk(dir + '/' + file, filelist);
    }
    else {
      filelist.push(dir + '/' + file);
    }
  });
  return filelist;
}

/**
 * Mints an Ark for the given object
 *
 * @param Object object The item being minted
 * @param Int counter A counter keeping track of how many times we've gone around
 * @return String The ARK identifier
 */
function mint_object(object, counter) {
  if ( counter === undefined ) {
    counter = 0;
  }

  var post_data = {
    who: object.metadata['dcterms.creator'] || 'unknown',
    what: object.metadata['dc.title'],
    when: object.metadata['dcterms.date'] || 'unknown'
  };

  if ( settings.mint_url === '' || settings.api_key === '' ) {
    logger.error('Unable to mint. Please provide the URL and/or API key for the minter.');
    return;
  }

  $.ajax({
    url: settings.mint_url,
    headers: {
      'api-key': settings.api_key
    },
    dataType: 'json',
    method: 'POST',
    data: post_data,
    success: function (data) {
      var id = data['id'];
      logger.log('Identifier "' + id + '" => "' + object.metadata['dc.title'] + '"', 'good');
      object.metadata['dcterms.identifier'] = id;
      process_object_files(object);
    },
    error: function(data) {
      logger.warn('FAILED to mint "' + object.metadata['dc.title'] + '", trying again...');
      if ( counter > 5 ) {
        logger.error('FAILED to mint "' + object.metadata['dc.title'] + "\" for the last time");
        logger.error("Unable to get ARK identifier. Something bad must have happened so I'm quitting.");
        rollback();
      }
      else {
        mint_object(object, counter + 1);
      }
    }
  });
}

$(document).ajaxStop(function(){
  if ( process_counter !== process_total ) {
    logger.warn("Finished minting but processing didn't seem to finish. This doesn't seem right");
  }
});

/**
 * Rollback what has been done. This deletes all minted identifiers during the process and moves files back.
 */
function rollback(){
  rolling_back = true;
  logger.warn('ROLLING BACK TO ORIGINAL STATE...');

  if (settings.mint_arks) {
    metadata_array.forEach(function(collection){
      var objects = collection.getObjects();
      objects.forEach(function(object){
        var ark = object.metadata['dcterms.identifier'];
        if (ark !== undefined && ark !== '' && ~ark.indexOf('ark:/')) {
          delete_identifier(ark);
        }
      });
    });
  }

  logger.warn('Moving files back to "' + locationpath + '"');
  var files = walk(locationpath + subdir + '/objects');

  files.forEach(function(file){
    var filename = file.match(/[^\/\\]+$/)[0];
    try {
      fs.renameSync(file, locationpath + filename);
      logger.log('Moved file "' + filename + '" back to "' + locationpath + '"');
    } catch (err) {
      logger.error(err.message);
    }
  });

  if ( subdir !== '' && subdir !== '/' && subdir !== "\\") {
    var ignestpath = locationpath + subdir;
    logger.log('Removing ingest directory "' + ignestpath + '"');
    rimraf(ignestpath, function(err) { });
  }

  logger.warn('Done');
}

/**
 * Deletes the ARK identifier from the resolver.
 *
 * @param String ark The ARK identifier to delete
 */
function delete_identifier(ark){
  if (settings.destroy_url.slice(-1) !== '/') {
    settings.destroy_url += '/'
  }

  $.ajax({
    url: settings.destroy_url + ark,
    headers: {
      'api-key': settings.api_key
    },
    method: 'DELETE',
    success: function (data) {
      logger.log('Identifier "' + ark + '" successfully destoryed');
    }
  });
}<|endoftext|>


<commit_before>const cos = Math.cos;
const sin = Math.sin;
const abs = Math.abs;
const atan2 = Math.atan2;
const floor = Math.floor;
const sqrt = Math.sqrt;

function randint(min, max)
{
	min = Math.ceil(min);
	max = floor(max);
	return floor(Math.random() * (max - min)) + min;
}

//return a gaussian distributed random number
function gaussian()
{
	var sum = 0;
	for(var i = 0; i < 12; i ++)
	{
		sum += Math.random();
	}
	return sum - 6;
}

//Bound radian a to interval [-pi, pi]
function boundRadian(a)
{
	a %= Math.PI*2;
	if(a > Math.PI)
		a -= 2*Math.PI;
	else if(a < -Math.PI)
		a += 2*Math.PI;
	return a;
}<commit_msg>use a slightly faster implementation of gaussian<commit_after>const cos = Math.cos;
const sin = Math.sin;
const abs = Math.abs;
const atan2 = Math.atan2;
const floor = Math.floor;
const sqrt = Math.sqrt;

function randint(min, max)
{
	min = Math.ceil(min);
	max = floor(max);
	return floor(Math.random() * (max - min)) + min;
}

//return a gaussian distributed random number
function gaussian()
{
    return ((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()) - 3) / 3;
}

//Bound radian a to interval [-pi, pi]
function boundRadian(a)
{
	a %= Math.PI*2;
	if(a > Math.PI)
		a -= 2*Math.PI;
	else if(a < -Math.PI)
		a += 2*Math.PI;
	return a;
}<|endoftext|>


<commit_before>/*global d3 */

// construct query string
var params = d3.select("#search-form");

if (!params.empty()) {
  var search_url = params.attr('data-search-url');
  var page = getParameterByName('page');
  if (page === null) { page = 1; }
  var q = getParameterByName('q');
  var tag = getParameterByName('tag');

  var query = encodeURI(search_url + "/pages?page=" + page);
  if (q !== null) { query += "&q=" + q; }
  if (tag !== null) { query += "&tag=" + tag; }
}

// load the data from the DataCite Labs API API
if (query) {
  d3.json(query)
    .get(function(error, json) {
      if (error) { return console.warn(error); }
      searchResult(json);
  });
}

// add search results to page
function searchResult(json) {
  data = json.data;
  meta = json.meta;

  d3.select("#q").property("value", q);

  json.href = "?page={{number}}";
  if (q !== null) { json.href += "&q=" + q; }
  if (tag !== null) { json.href += "&tag=" + tag; }

  if (typeof data === "undefined" || data.length === 0) {
    d3.select("#content").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("No blog posts found.");
    return;
  }

  if (json.meta.total > 1) {
    d3.select("#content").insert("h4")
      .attr("class", "results")
      .text(numberWithDelimiter(json.meta.total) + " Posts");
  }

  for (var i=0; i<data.length; i++) {
    var post = data[i];

    d3.select("#content").insert("div")
      .attr("class", "panel panel-default post-list")
      .attr("id", "panel-" + i).insert("div")
      .attr("class", "panel-body post-content")
      .attr("id", "panel-body-" + i);

    d3.select("#panel-body-" + i).append("header")
      .attr("class", "post-header")
      .append("h2")
      .attr("class", "post-title")
      .append("a")
      .attr("href", function() { return post.id; })
      .text(post.attributes.title);
    d3.select("#panel-body-" + i).append("section")
      .attr("class", "post-excerpt")
      .attr("itemprop", "description").insert("p")
      .html(post.attributes.description);

    d3.select("#panel-" + i).insert("div")
      .attr("class", "panel-footer")
      .attr("id", "panel-footer-" + i).append("span")
      .attr("class", "meta").append("time")
      .attr("datetime", post.attributes.issued)
      .text(formattedDate(post.attributes.issued.substring(0, 10)));

    d3.select("#panel-footer-" + i).insert("span")
      .attr("class", "meta")
      .text(formattedAuthorList(post.attributes.author));

    d3.select("#panel-footer-" + i).insert("a")
      .attr("href", function() { return post.id + "#disqus_thread"; })
      .text("0 comments");

    var t = post.attributes.tags;
    if (typeof t !== "undefined" && t.length > 0)  {
      d3.select("#panel-footer-" + i).insert("span")
        .attr("class", "tags pull-right").append("i")
        .attr("class", "fa fa-tags");
      for (var j=0; j<t.length; j++) {
        d3.select("#panel-footer-" + i + " .tags").append("a")
          .attr("href", function() { return "/index.html?tag=" + t[j]; })
          .text((j + 1 < t.length) ? t[j] + "," : t[j]);
      }
    }
  }

  // convert tags object to array for sorting
  tags = Object.keys(meta.tags);

  if (typeof tags !== "undefined" && tags.length > 0) {
    tags.sort(function (a, b) {
      if (meta.tags[a] > meta.tags[b]) {
        return -1;
      }
      if (meta.tags[a] < meta.tags[b]) {
        return 1;
      }
      // a must be equal to b
      return 0;
    });

    d3.select("#tags")
      .classed("panel facets", true).insert("div")
      .attr("class", "panel-body").insert("h4")
      .text("Tags");

    d3.select("#tags .panel-body").insert("ul");

    for (k = 0; k<tags.length; k++) {
      var key = tags[k];
      if (tag === key) {
        d3.select("#tags .panel-body ul").insert("li")
          .append("a")
          .attr("href", function() { return "/index.html"; }).insert("i")
          .attr("class", "fa fa-check-square-o");
      } else {
        d3.select("#tags .panel-body ul").insert("li")
          .append("a")
          .attr("href", function() { return "/index.html?tag=" + key; }).insert("i")
          .attr("class", "fa fa-square-o");
      }
      d3.select("#tags .panel-body ul li:last-child").insert("span")
        .text(key);
      d3.select("#tags .panel-body ul li:last-child").insert("span")
        .attr("class", "number pull-right")
        .text(meta.tags[key]);

    }
  }
}
<commit_msg>added pagination<commit_after>/*global d3 */

// construct query string
var params = d3.select("#search-form");

if (!params.empty()) {
  var search_url = params.attr('data-search-url');
  var page = getParameterByName('page');
  if (page === null) { page = 1; }
  var q = getParameterByName('q');
  var tag = getParameterByName('tag');

  var query = encodeURI(search_url + "/pages?page=" + page);
  if (q !== null) { query += "&q=" + q; }
  if (tag !== null) { query += "&tag=" + tag; }
}

// load the data from the DataCite Labs API API
if (query) {
  d3.json(query)
    .get(function(error, json) {
      if (error) { return console.warn(error); }
      searchResult(json);

      json.meta["page"] = page;
      json.meta["total_pages"] = Math.ceil(json.meta.total/25);
      paginate(json, "#content");
  });
}

// add search results to page
function searchResult(json) {
  data = json.data;
  meta = json.meta;

  d3.select("#q").property("value", q);

  json.href = "?page={{number}}";
  if (q !== null) { json.href += "&q=" + q; }
  if (tag !== null) { json.href += "&tag=" + tag; }

  if (typeof data === "undefined" || data.length === 0) {
    d3.select("#content").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("No blog posts found.");
    return;
  }

  if (json.meta.total > 1) {
    d3.select("#content").insert("h4")
      .attr("class", "results")
      .text(numberWithDelimiter(json.meta.total) + " Posts");
  }

  for (var i=0; i<data.length; i++) {
    var post = data[i];

    d3.select("#content").insert("div")
      .attr("class", "panel panel-default post-list")
      .attr("id", "panel-" + i).insert("div")
      .attr("class", "panel-body post-content")
      .attr("id", "panel-body-" + i);

    d3.select("#panel-body-" + i).append("header")
      .attr("class", "post-header")
      .append("h2")
      .attr("class", "post-title")
      .append("a")
      .attr("href", function() { return post.id; })
      .text(post.attributes.title);
    d3.select("#panel-body-" + i).append("section")
      .attr("class", "post-excerpt")
      .attr("itemprop", "description").insert("p")
      .html(post.attributes.description);

    d3.select("#panel-" + i).insert("div")
      .attr("class", "panel-footer")
      .attr("id", "panel-footer-" + i).append("span")
      .attr("class", "meta").append("time")
      .attr("datetime", post.attributes.issued)
      .text(formattedDate(post.attributes.issued.substring(0, 10)));

    d3.select("#panel-footer-" + i).insert("span")
      .attr("class", "meta")
      .text(formattedAuthorList(post.attributes.author));

    d3.select("#panel-footer-" + i).insert("a")
      .attr("href", function() { return post.id + "#disqus_thread"; })
      .text("0 comments");

    var t = post.attributes.tags;
    if (typeof t !== "undefined" && t.length > 0)  {
      d3.select("#panel-footer-" + i).insert("span")
        .attr("class", "tags pull-right").append("i")
        .attr("class", "fa fa-tags");
      for (var j=0; j<t.length; j++) {
        d3.select("#panel-footer-" + i + " .tags").append("a")
          .attr("href", function() { return "/index.html?tag=" + t[j]; })
          .text((j + 1 < t.length) ? t[j] + "," : t[j]);
      }
    }
  }

  // convert tags object to array for sorting
  tags = Object.keys(meta.tags);

  if (typeof tags !== "undefined" && tags.length > 0) {
    tags.sort(function (a, b) {
      if (meta.tags[a] > meta.tags[b]) {
        return -1;
      }
      if (meta.tags[a] < meta.tags[b]) {
        return 1;
      }
      // a must be equal to b
      return 0;
    });

    d3.select("#tags")
      .classed("panel facets", true).insert("div")
      .attr("class", "panel-body").insert("h4")
      .text("Tags");

    d3.select("#tags .panel-body").insert("ul");

    for (k = 0; k<tags.length; k++) {
      var key = tags[k];
      if (tag === key) {
        d3.select("#tags .panel-body ul").insert("li")
          .append("a")
          .attr("href", function() { return "/index.html"; }).insert("i")
          .attr("class", "fa fa-check-square-o");
      } else {
        d3.select("#tags .panel-body ul").insert("li")
          .append("a")
          .attr("href", function() { return "/index.html?tag=" + key; }).insert("i")
          .attr("class", "fa fa-square-o");
      }
      d3.select("#tags .panel-body ul li:last-child").insert("span")
        .text(key);
      d3.select("#tags .panel-body ul li:last-child").insert("span")
        .attr("class", "number pull-right")
        .text(meta.tags[key]);

    }
  }
}
<|endoftext|>


<commit_before>"use strict";

var cookieName = 'rgpd-consent';

// RGPD consent has 3 possible states:
// accepted (opt in), rejected (opt out), and undecided yet (default)

function userHasOptOutRGPD() {
  return (Cookies.get(cookieName) === "false")
}

function userHasOptInRGPD() {
    return (Cookies.get(cookieName) === "true")
}

function userHasNotYetDecidedRGPD() {
    return (Cookies.get(cookieName) === undefined)
}

(function($) {

    $(document).on('lbbready', function () {

    var bannerElement = $('.rgpd-banner');

    if (userHasNotYetDecidedRGPD()) {
      bannerElement.show();
      ga('send', 'event', 'RGPD', 'banner');
    }

    $('.rgpd-accept').on('click', function (e) {
      e.preventDefault();
      Cookies.set(cookieName, true, { expires: 365 });
      bannerElement.hide();
      closeModals();
      ga('send', 'event', 'RGPD', 'accept');
    });

    $('.rgpd-reject').on('click', function (e) {
      e.preventDefault();
      Cookies.set(cookieName, false, { expires: 365 });
      bannerElement.hide();
      closeModals();
      ga('send', 'event', 'RGPD', 'reject');
    });

    $('.rgpd-info').on('click', function (e) {
      e.preventDefault();
      showModal("#rgpd-modal");
      ga('send', 'event', 'RGPD', 'info');
    });

    $('.rgpd-consent-required').on('click', function (e) {
      if (userHasOptInRGPD() === false) {
        alert('Vous devez accepter notre politique de confidentialité pour utiliser notre service.');
        showModal("#rgpd-modal");
        e.preventDefault();
        ga('send', 'event', 'RGPD', 'required');
      }
    });

  });

})(jQuery);
<commit_msg>hide PE connect dropdown which interferes with RGPD modal<commit_after>"use strict";

var cookieName = 'rgpd-consent';

// RGPD consent has 3 possible states:
// accepted (opt in), rejected (opt out), and undecided yet (default)

function userHasOptOutRGPD() {
  return (Cookies.get(cookieName) === "false")
}

function userHasOptInRGPD() {
    return (Cookies.get(cookieName) === "true")
}

function userHasNotYetDecidedRGPD() {
    return (Cookies.get(cookieName) === undefined)
}

(function($) {

    $(document).on('lbbready', function () {

    var bannerElement = $('.rgpd-banner');

    if (userHasNotYetDecidedRGPD()) {
      bannerElement.show();
      ga('send', 'event', 'RGPD', 'banner');
    }

    $('.rgpd-accept').on('click', function (e) {
      e.preventDefault();
      Cookies.set(cookieName, true, { expires: 365 });
      bannerElement.hide();
      closeModals();
      ga('send', 'event', 'RGPD', 'accept');
    });

    $('.rgpd-reject').on('click', function (e) {
      e.preventDefault();
      Cookies.set(cookieName, false, { expires: 365 });
      bannerElement.hide();
      closeModals();
      ga('send', 'event', 'RGPD', 'reject');
    });

    $('.rgpd-info').on('click', function (e) {
      e.preventDefault();
      showModal("#rgpd-modal");
      ga('send', 'event', 'RGPD', 'info');
    });

    $('.rgpd-consent-required').on('click', function (e) {
      if (userHasOptInRGPD() === false) {
        alert('Vous devez accepter notre politique de confidentialité pour utiliser notre service.');
        jQuery(".lbb-dropdown").hide();  // hide PE connect dropdown
        showModal("#rgpd-modal");
        e.preventDefault();
        ga('send', 'event', 'RGPD', 'required');
      }
    });

  });

})(jQuery);
<|endoftext|>


<commit_before>var bind_remote = function(selector){
    var cc = $('<input/>')
        .attr('id','azerty')
        .fadeTo(0.2,0)
        .keydown(
        function(event){
                if(event.which == IPython.utils.keycodes.LEFT_ARROW){
                    console.log('go left');
                    IPython.slideshow.prev();
                }
                else if(event.which == IPython.utils.keycodes.RIGHT_ARROW){
                    console.log('go right')
                    IPython.slideshow.next();
                }
            event.preventDefault();
            return false;
            })
            .focusin(function(){$('#qwerty').button('option','label','Slide Mode Enabled')})
            .focusout(function(){$('#qwerty').button('option','label','Enable Slide Mode')})

        var dd = $('<div/>')
            .attr('id','qwerty')
            .button({label:'slide control'})
            .attr('style','float:right')
            .click(
                function(){
                    $('#azerty').focus();
                    console.log('...');
                })
            .keydown(
                function(event){
                    console.log('event append',event);
                event.preventDefault();
                return false;
                })
    var hin = function(){$(selector).fadeTo('slow',1);}
    var hout= function(){$(selector).fadeTo('slow',0.3);}
    $(selector)
        .append(cc)
        .append(dd)
        .fadeTo('slow',0.3)
    .hover(hin,hout)

}

var show_line = function(cell,line_number){
    cell.code_mirror.showLine(cell.code_mirror.getLineHandle(line_number-1))
}

IPython = (function(IPython) {
    var Presentation = function(){
          this.ccell = 0;
    }

    var is_marked_cell = function(cell){
        var def = { "slideshow": {} }

        m = cell.metadata.slideshow ? cell.metadata.slideshow:{}
        return ( m.slide_type != 'slide')
    }

      Presentation.prototype.create_toolbar = function(){
            var pt = $('<div/>').attr('id','toolbar_present').addClass('toolbar');
            var that = this;
            this.avc = $('<div/>').button({label:that.eta()});
            pt.append(this.avc);

            $('#maintoolbar').after(pt);
            var ptoolbar = new IPython.ToolBar('#toolbar_present');
            IPython.ptoolbar = ptoolbar;
            ptoolbar.add_buttons_group([{label:'Stop', icon:'ui-icon-stop', callback:function(){that.stop()}}])
            ptoolbar.add_buttons_group([
                     {label:'Prev Slide', icon:'ui-icon-seek-prev', callback:function(){that.prev_group()}},
                     {label:'Next Slide', icon:'ui-icon-seek-next', callback:function(){that.next_group()}},
                                    ])
            ptoolbar.add_buttons_group([
                     {label:'Step Next', icon:'ui-icon-play', callback:function(){that.next()}}
                     ])
            bind_remote('#toolbar_present');

      }

      Presentation.prototype.remove_toolbar = function(){
          $('#toolbar_present').remove();
      }

      Presentation.prototype.ngroups = function(){
          var cells = IPython.notebook.get_cells();
          var cnt =0
          for( var i=0; i< cells.length;i++)
              if(is_marked_cell(cells[i])) cnt++;
          return cnt
      }

      Presentation.prototype.cgroups = function(){
          var cells = IPython.notebook.get_cells();
          var cnt =0
          for( var i=0; i<= this.ccell ;i++)
              if(is_marked_cell(cells[i])) cnt++;
          return cnt
      }

      Presentation.prototype.eta = function(){
          return this.cgroups()+'/'+this.ngroups()
          }

      Presentation.prototype.next_marked_cell_n = function()
      {
          for(var i=this.ccell+1; i< $('.cell').length; i++)
          {
              if(is_marked_cell(IPython.notebook.get_cell(i)))
                { return i; }
          }
          return null;
      }

      Presentation.prototype.prev_marked_cell_n = function()
      {
          for(var i=this.ccell-1; i> 0; i--)
          {
              if(is_marked_cell(IPython.notebook.get_cell(i))){
                 return i
              }
          }
          return 0;
      }

      Presentation.prototype.start = function(){
          this.restart();
          this.resume();
      }

      Presentation.prototype.restart = function(){
          this.ccell = 0;
          delete this.avc;
      }

      Presentation.prototype.resume = function(){
          this.create_toolbar();
          $('#menubar').addClass('pmode');
          $('#pager_splitter').addClass('pmode');
          $('#pager').addClass('pmode');
          $('#menubar, #pager_splitter, #pager, #header,#maintoolbar').addClass('pmode');
          $('#header').addClass('pmode');
          $('#maintoolbar').addClass('pmode');
          $('div#header').css('display','none');
          IPython.layout_manager.do_resize();
          $('.cell').fadeOut();
          if(this.current_is_marked()){
              $('.cell:nth('+this.ccell+')').fadeIn();
          } else {
              for( var i=this.prev_marked_cell_n() ; i<= this.ccell; i++){
                  $('.cell:nth('+i+')').fadeIn();
              }
          }
          var that=this;
          if(this.avc != undefined)
            $(this.avc).button('option','label',that.eta())
          return this;
      }

      Presentation.prototype.stop = function(){
          $('.cell').fadeIn();
          $('.pmode').removeClass('pmode');
          $('div#header').css('display','block');
          $('div#notebook').removeClass('pmode');
          IPython.layout_manager.do_resize();
          this.remove_toolbar();
      }

      Presentation.prototype.next = function(){
          this.ccell = this.ccell+1;
          var that = this;
          if(this.ccell >= $('.cell').length ){
              this.restart();
              this.stop();
              return;
          }
          var nnext = this.ccell;
          var ncell = IPython.notebook.get_cell(nnext)

          if(is_marked_cell(ncell)){
              $('.cell').fadeOut(500);
              setTimeout(function(){$('.cell:nth('+nnext+')').fadeIn(500)},600);
          } else {
              setTimeout(function(){$('.cell:nth('+nnext+')').fadeIn(500)},0);
          }
          $(this.avc).button('option','label',that.eta())
          return this;
      }

      Presentation.prototype.next_group = function(){
          this.ccell = this.next_marked_cell_n();
          var that = this;
          $('.cell').fadeOut(500);
          setTimeout(function(){
              $('.cell:nth('+that.ccell+')').fadeIn(500)
                  },600);
          $(this.avc).button('option','label',that.eta())
      }

      Presentation.prototype.prev_group = function(){
          this.ccell = this.prev_marked_cell_n();
          var that = this
          $('.cell').fadeOut(500);
          setTimeout(function(){$('.cell:nth('+that.ccell+')').fadeIn(500)},600);
          $(this.avc).button('option','label',that.eta())
      }

      Presentation.prototype.is_n_marked = function(n){
          return is_marked_cell(IPython.notebook.get_cell(n))
      }

      Presentation.prototype.current_is_marked = function(n){
          return is_marked_cell(IPython.notebook.get_cell(this.ccell));
      }

      Presentation.prototype.prev = function(){
          if(is_marked_cell(IPython.notebook.get_cell(this.ccell))){
              var pmcell = this.prev_marked_cell_n();
              $('.cell').fadeOut(500);
              for( var i=pmcell; i< this.ccell ; i++ ){
                  (function(val){
                      return function(){
                                  setTimeout( function(){
                                      $('.cell:nth('+val+')').fadeIn(500)
                                      },600);
                      }
                   })(i)();
              }
          } else {
              $('.cell:nth('+this.ccell+')').fadeOut(500);
          }
          this.ccell = this.ccell -1;
          return this;
      }

      IPython.Presentation = Presentation;
      return IPython;

})(IPython);

//$('body').append($('<style/>').text('.pmode{ display: none !important }'));
//
IPython.slideshow = new IPython.Presentation();

    var sid = 'start_pmode'
    if(($('#'+sid)).length == 0) {
          IPython.toolbar.add_buttons_group([
                  {'label'  :'Start Slideshow',
                    'icon'  :'ui-icon-image',
                    'callback':function(){IPython.slideshow.resume()},'id':sid},
              ])
         }
<commit_msg>clean and fix bad logic<commit_after>var bind_remote = function(selector){
    var cc = $('<input/>')
        .attr('id','azerty')
        .fadeTo(0.2,0)
        .keydown(
        function(event){
                if(event.which == IPython.utils.keycodes.LEFT_ARROW){
                    console.log('go left');
                    IPython.slideshow.prev();
                }
                else if(event.which == IPython.utils.keycodes.RIGHT_ARROW){
                    console.log('go right')
                    IPython.slideshow.next();
                }
            event.preventDefault();
            return false;
            })
            .focusin(function(){$('#qwerty').button('option','label','Slide Mode Enabled')})
            .focusout(function(){$('#qwerty').button('option','label','Enable Slide Mode')})

        var dd = $('<div/>')
            .attr('id','qwerty')
            .button({label:'slide control'})
            .attr('style','float:right')
            .click(
                function(){
                    $('#azerty').focus();
                    console.log('...');
                })
            .keydown(
                function(event){
                    console.log('event append',event);
                event.preventDefault();
                return false;
                })
    var hin = function(){$(selector).fadeTo('slow',1);}
    var hout= function(){$(selector).fadeTo('slow',0.3);}
    $(selector)
        .append(cc)
        .append(dd)
        .fadeTo('slow',0.3)
    .hover(hin,hout)

}

var show_line = function(cell,line_number){
    cell.code_mirror.showLine(cell.code_mirror.getLineHandle(line_number-1))
}

IPython = (function(IPython) {
    var Presentation = function(){
          this.ccell = 0;
    }

    var is_marked_cell = function(cell){
        var def = { "slideshow": {} }

        m = cell.metadata.slideshow ? cell.metadata.slideshow:{}
        return ( m.slide_type == 'slide')
    }

      Presentation.prototype.create_toolbar = function(){
            var pt = $('<div/>').attr('id','toolbar_present').addClass('toolbar');
            var that = this;
            this.avc = $('<div/>').button({label:that.eta()});
            pt.append(this.avc);

            $('#maintoolbar').after(pt);
            var ptoolbar = new IPython.ToolBar('#toolbar_present');
            IPython.ptoolbar = ptoolbar;
            ptoolbar.add_buttons_group([{label:'Stop', icon:'ui-icon-stop', callback:function(){that.stop()}}])
            ptoolbar.add_buttons_group([
                     {label:'Prev Slide', icon:'ui-icon-seek-prev', callback:function(){that.prev_group()}},
                     {label:'Next Slide', icon:'ui-icon-seek-next', callback:function(){that.next_group()}},
                                    ])
            ptoolbar.add_buttons_group([
                     {label:'Step Next', icon:'ui-icon-play', callback:function(){that.next()}}
                     ])
            bind_remote('#toolbar_present');

      }

      Presentation.prototype.remove_toolbar = function(){
          $('#toolbar_present').remove();
      }

      Presentation.prototype.ngroups = function(){
          var cells = IPython.notebook.get_cells();
          var cnt =0
          for( var i=0; i< cells.length;i++)
              if(is_marked_cell(cells[i])) cnt++;
          return cnt
      }

      Presentation.prototype.cgroups = function(){
          var cells = IPython.notebook.get_cells();
          var cnt =0
          for( var i=0; i<= this.ccell ;i++)
              if(is_marked_cell(cells[i])) cnt++;
          return cnt
      }

      Presentation.prototype.eta = function(){
          return this.cgroups()+'/'+this.ngroups()
          }

      Presentation.prototype.next_marked_cell_n = function()
      {
          for(var i=this.ccell+1; i< $('.cell').length; i++)
          {
              if(is_marked_cell(IPython.notebook.get_cell(i)))
                { return i; }
          }
          return null;
      }

      Presentation.prototype.prev_marked_cell_n = function()
      {
          for(var i=this.ccell-1; i> 0; i--)
          {
              if(is_marked_cell(IPython.notebook.get_cell(i))){
                 return i
              }
          }
          return 0;
      }

      Presentation.prototype.start = function(){
          this.restart();
          this.resume();
      }

      Presentation.prototype.restart = function(){
          this.ccell = 0;
          delete this.avc;
      }

      Presentation.prototype.resume = function(){
          this.create_toolbar();
          $('#menubar').addClass('pmode');
          $('#pager_splitter').addClass('pmode');
          $('#pager').addClass('pmode');
          $('#menubar, #pager_splitter, #pager, #header,#maintoolbar').addClass('pmode');
          $('#header').addClass('pmode');
          $('#maintoolbar').addClass('pmode');
          $('div#header').css('display','none');
          IPython.layout_manager.do_resize();
          $('.cell').fadeOut();
          if(this.current_is_marked()){
              $('.cell:nth('+this.ccell+')').fadeIn();
          } else {
              for( var i=this.prev_marked_cell_n() ; i<= this.ccell; i++){
                  $('.cell:nth('+i+')').fadeIn();
              }
          }
          var that=this;
          if(this.avc != undefined)
            $(this.avc).button('option','label',that.eta())
          return this;
      }

      Presentation.prototype.stop = function(){
          $('.cell').fadeIn();
          $('.pmode').removeClass('pmode');
          $('div#header').css('display','block');
          $('div#notebook').removeClass('pmode');
          IPython.layout_manager.do_resize();
          this.remove_toolbar();
      }

      Presentation.prototype.next = function(){
          var current_cell_number = this.ccell
          this.ccell = this.ccell+1
          var number_next_cell = this.ccell

          var that = this;
          if(this.ccell >= $('.cell').length ){
              this.restart();
              this.stop();
              return;
          }
          var next_cell = IPython.notebook.get_cell(number_next_cell)

          if(is_marked_cell(next_cell)){
              $('.cell').fadeOut(500);
              setTimeout(function(){$('.cell:nth('+number_next_cell+')').fadeIn(500)},600);
          } else {
              setTimeout(function(){$('.cell:nth('+number_next_cell+')').fadeIn(500)},0);
          }
          $(this.avc).button('option','label',that.eta())
          return this;
      }

      Presentation.prototype.next_group = function(){
          this.ccell = this.next_marked_cell_n();
          var that = this;
          $('.cell').fadeOut(500);
          setTimeout(function(){
              $('.cell:nth('+that.ccell+')').fadeIn(500)
                  },600);
          $(this.avc).button('option','label',that.eta())
      }

      Presentation.prototype.prev_group = function(){
          this.ccell = this.prev_marked_cell_n();
          var that = this
          $('.cell').fadeOut(500);
          setTimeout(function(){$('.cell:nth('+that.ccell+')').fadeIn(500)},600);
          $(this.avc).button('option','label',that.eta())
      }

      Presentation.prototype.is_n_marked = function(n){
          return is_marked_cell(IPython.notebook.get_cell(n))
      }

      Presentation.prototype.current_is_marked = function(n){
          return is_marked_cell(IPython.notebook.get_cell(this.ccell));
      }

      Presentation.prototype.prev = function(){
          if(is_marked_cell(IPython.notebook.get_cell(this.ccell))){
              var pmcell = this.prev_marked_cell_n();
              $('.cell').fadeOut(500);
              for( var i=pmcell; i< this.ccell ; i++ ){
                  (function(val){
                      return function(){
                                  setTimeout( function(){
                                      $('.cell:nth('+val+')').fadeIn(500)
                                      },600);
                      }
                   })(i)();
              }
          } else {
              $('.cell:nth('+this.ccell+')').fadeOut(500);
          }
          this.ccell = this.ccell -1;
          return this;
      }

      IPython.Presentation = Presentation;
      return IPython;

})(IPython);

//$('body').append($('<style/>').text('.pmode{ display: none !important }'));
//
IPython.slideshow = new IPython.Presentation();

    var sid = 'start_pmode'
    if(($('#'+sid)).length == 0) {
          IPython.toolbar.add_buttons_group([
                  {'label'  :'Start Slideshow',
                    'icon'  :'ui-icon-image',
                    'callback':function(){IPython.slideshow.resume()},'id':sid},
              ])
         }
<|endoftext|>


<commit_before>
  window.idx = lunr(function () {
    this.field('title');
    this.field('excerpt');
    this.field('content', {boost: 10});
    this.ref('id');
  });

  $(document).ready(function() {
    window.data = $.getJSON('/searchposts.json');

    window.data.then(function(loaded_data){
      $.each(loaded_data, function(index, value){
        window.idx.add($.extend({ "id": index }, value));
      });
    });
  });

<commit_msg>Update search.js<commit_after>
  window.idx = lunr(function () {
    this.field('title');
    this.field('excerpt');
    this.field('content', {boost: 10});
    this.ref('id');
  });

  $(document).ready(function() {
    window.data = $.getJSON('/searchposts.json');

    window.data.then(function(loaded_data){
      $.each(loaded_data, function(index, value){
        window.idx.add($.extend({ "id": index }, value));
      });
      var boo = 2;
    });
  });

<|endoftext|>


<commit_before>var trustedSites = [
  'overheid.nl',
  'cbs.nl',
];

function fillTableRows(result) {
  var urlParts = result.uri[0].split('/');
  if (urlParts.length === 3) { // URL is already a base url
    baseURL = result.uri[0];
  } else {
    baseURL = urlParts
      .slice(0, 3)
      .join('/');
  }

  var tableRow =
    '
'+ result.prefixedName[0] +
    '	' +
    ''+ baseURL +
    '
';

  var tld = result.uri[0]
    .split('/')[2];

  if (trustedSites.indexOf(tld) > -1) {
    $('#trustedResults tbody').append(tableRow);
  } else {
    $('#miscResults tbody').append(tableRow);
  }
}

function searchForTerm(data) {
  var searchTerm = data.target.value;

  var settings = {
    async: true,
    crossDomain: true,
    url: 'https://lov.okfn.org/dataset/lov/api/v2/term/search?q=' + searchTerm + "&page_size=100",
    method: 'GET',
  };

  $.ajax(settings).done(function (response) {
    $('#trustedResults tbody').empty();
    $('#miscResults tbody').empty();
    response.results.forEach(fillTableRows);
  });
}

// Using https://raw.githubusercontent.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.js
$('#searchbox').on('input', $.debounce(250, searchForTerm));
<commit_msg>fix domain parsing<commit_after>var trustedSites = [
  'overheid.nl',
  'cbs.nl',
];

function fillTableRows(result) {
  var urlParts = result.uri[0].split('/');
  if (urlParts.length === 3) { // URL is already a base url
    baseURL = result.uri[0];
  } else {
    baseURL = urlParts
      .slice(0, 3)
      .join('/');
  }

  var tableRow =
    '
'+ result.prefixedName[0] +
    '	' +
    ''+ baseURL +
    '
';

  var domain = result.uri[0]
    .split('/')[2]
    .split('.')
    .slice(-2)
    .join('.');
  console.log('tld', domain);

  if (trustedSites.indexOf(domain) > -1) {
    $('#trustedResults tbody').append(tableRow);
  } else {
    $('#miscResults tbody').append(tableRow);
  }
}

function searchForTerm(data) {
  var searchTerm = data.target.value;

  var settings = {
    async: true,
    crossDomain: true,
    url: 'https://lov.okfn.org/dataset/lov/api/v2/term/search?q=' + searchTerm + "&page_size=100",
    method: 'GET',
  };

  $.ajax(settings).done(function (response) {
    $('#trustedResults tbody').empty();
    $('#miscResults tbody').empty();
    response.results.forEach(fillTableRows);
  });
}

// Using https://raw.githubusercontent.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.js
$('#searchbox').on('input', $.debounce(250, searchForTerm));
<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/*
 * IMPORTANT: This file was auto-generated by "grunt generate-config". Please do not modify this directly. Instead
 * please modify sun/package.json to control dependencies.
 *
 * RequireJS configuration file for the sun sim.
 * Paths are relative to the location of this file.
 */

require.config( {

  deps: [ 'sun-main' ],

  paths: {

    // Third-party libs
    text: '../../sherpa/lib/text-2.0.12',

    // PhET plugins
    audio: '../../chipper/js/requirejs-plugins/audio',
    image: '../../chipper/js/requirejs-plugins/image',
    mipmap: '../../chipper/js/requirejs-plugins/mipmap',
    string: '../../chipper/js/requirejs-plugins/string',
    ifphetio: '../../chipper/js/requirejs-plugins/ifphetio',

    // PhET libs, uppercase names to identify them in require.js imports.
    // IMPORTANT: DO NOT modify. This file is auto-generated. See documentation at the top.
    AXON: '../../axon/js',
    BRAND: '../../brand/' + phet.chipper.brand + '/js',
    DOT: '../../dot/js',
    JOIST: '../../joist/js',
    KITE: '../../kite/js',
    PHETCOMMON: '../../phetcommon/js',
    PHET_CORE: '../../phet-core/js',
    PHET_IO: '../../phet-io/js',
    REPOSITORY: '..',
    SCENERY: '../../scenery/js',
    SCENERY_PHET: '../../scenery-phet/js',
    SUN: '.',
    TANDEM: '../../tandem/js'
  },

  // optional cache buster to make browser refresh load all included scripts, can be disabled with ?cacheBuster=false
  urlArgs: phet.chipper.getCacheBusterArgs()
} );
<commit_msg>added the tambo sound library as a dependency for all active runnables, see https://github.com/phetsims/joist/issues/497<commit_after>// Copyright 2018, University of Colorado Boulder

/*
 * IMPORTANT: This file was auto-generated by "grunt generate-config". Please do not modify this directly. Instead
 * please modify sun/package.json to control dependencies.
 *
 * RequireJS configuration file for the sun sim.
 * Paths are relative to the location of this file.
 */

require.config( {

  deps: [ 'sun-main' ],

  paths: {

    // Third-party libs
    text: '../../sherpa/lib/text-2.0.12',

    // PhET plugins
    audio: '../../chipper/js/requirejs-plugins/audio',
    image: '../../chipper/js/requirejs-plugins/image',
    mipmap: '../../chipper/js/requirejs-plugins/mipmap',
    string: '../../chipper/js/requirejs-plugins/string',
    ifphetio: '../../chipper/js/requirejs-plugins/ifphetio',

    // PhET libs, uppercase names to identify them in require.js imports.
    // IMPORTANT: DO NOT modify. This file is auto-generated. See documentation at the top.
    AXON: '../../axon/js',
    BRAND: '../../brand/' + phet.chipper.brand + '/js',
    DOT: '../../dot/js',
    JOIST: '../../joist/js',
    KITE: '../../kite/js',
    PHETCOMMON: '../../phetcommon/js',
    PHET_CORE: '../../phet-core/js',
    PHET_IO: '../../phet-io/js',
    REPOSITORY: '..',
    SCENERY: '../../scenery/js',
    SCENERY_PHET: '../../scenery-phet/js',
    SUN: '.',
    TAMBO: '../../tambo/js',
    TANDEM: '../../tandem/js'
  },

  // optional cache buster to make browser refresh load all included scripts, can be disabled with ?cacheBuster=false
  urlArgs: phet.chipper.getCacheBusterArgs()
} );
<|endoftext|>


<commit_before>
Exhibit.SliderFacet.slider = function(div, facet, precision, horizontal) {
	this._horizontal = horizontal;
	if (horizontal) {
		this.horizontalSlider(div, facet, precision);
	}else {
	    this._div = div;
	    this._facet = facet;
	    if (facet._maxRange.min % 1>0) {
	    	precision = .01;
	    	size = 4;
	    }else {
	    	precision = 1;
	    	size = 2;
	    }
	    this._prec = precision || .1;

	    this._range = {min: facet._maxRange.min,  // round down
			   max: facet._maxRange.max}; // round up

	    this._scaleFactor = null;
	    this._slider1 = {};
	    this._slider2 = {};

		var self = this;

	    this._dom = SimileAjax.DOM.createDOMFromString(
	        div,
		'
' +
		    '<input type="text" size="'+size+'" id="minDisplay" class="exhibit-slider-minDisplay"></input>' +
		'
' +
	        '
' +
		    '

' +
		    '

' +
		    (this._facet._settings.histogram? '<canvas class="exhibit-slider-histogram2" id="histogram"></canvas>' : '') +
		'
'+
		'
' +
		    '<input type="text" size="'+size+'" id="maxDisplay" class="exhibit-slider-maxDisplay"></input>' +
		'
'
	    );

	    this._scaleFactor = (this._range.max - this._range.min)/this._dom.bar.offsetHeight;

	    this._slider1 = new Exhibit.SliderFacet.slider.slider(this._dom.slider1, this);
	    this._slider2 = new Exhibit.SliderFacet.slider.slider(this._dom.slider2, this);

	    this._setSlider(this._slider1, Math.max(facet._selection.min, this._range.min));
    	this._setSlider(this._slider2, Math.min(facet._selection.max, this._range.max));
	    this._registerDragging();

	    SimileAjax.WindowManager.registerEvent(self._dom.minDisplay, "change",
	                function(elmt, evt, target) {self.validateInput(self._slider1, self._dom.minDisplay.value); });

	    SimileAjax.WindowManager.registerEvent(self._dom.maxDisplay, "change",
	                function(elmt, evt, target) {self.validateInput(self._slider2, self._dom.maxDisplay.value); });

	    if(this._dom.histogram) {
		this._dom.histogram.width = this._dom.bar.offsetWidth;
		this._dom.histogram.height = this._dom.bar.offsetHeight;
	    } else {
		this._dom.bar.style.borderTop = '1px solid black';
	    }
    }
};

Exhibit.SliderFacet.slider.prototype.horizontalSlider = function(div, facet, precision) {
	this._div = div;
    this._facet = facet;
    this._prec = precision || .1;
    this._range = {min: parseFloat(Exhibit.Util.round(facet._maxRange.min-precision/2, this._prec)),  // round down
		   max: parseFloat(Exhibit.Util.round(facet._maxRange.max+precision/2, this._prec))}; // round up

    this._scaleFactor = null;
    this._slider1 = {};
    this._slider2 = {};

    this._dom = SimileAjax.DOM.createDOMFromString(
        div,
	'
' +
	    '

' +
	    '

' +
	'
' +
        '
' +
	    '

' +
	    '

' +
	    (this._facet._settings.histogram? '<canvas class="exhibit-slider-histogram" id="histogram"></canvas>' : '') +
	'
'
    );

    this._scaleFactor = (this._range.max - this._range.min)/this._dom.bar.offsetWidth;

    this._slider1 = new Exhibit.SliderFacet.slider.slider(this._dom.slider1, this);
    this._slider2 = new Exhibit.SliderFacet.slider.slider(this._dom.slider2, this);
    this._setSlider(this._slider1, this._range.min);
    this._setSlider(this._slider2, this._range.max);

    this._registerDragging();

    if(this._dom.histogram) {
		this._dom.histogram.width = this._dom.bar.offsetWidth;
		this._dom.histogram.height = this._dom.bar.offsetHeight;
    } else {
		this._dom.bar.style.borderTop = '1px solid black';
    }
};

Exhibit.SliderFacet.slider.prototype.validateInput = function(slider, value) {
	try {
		var numericValue = parseFloat(value);
		if (isNaN(numericValue)) {
			slider.value = slider.value;
		}else if (numericValue<this._range.min) {
			//alert("Input must be bigger than "+this._range.min+"!");
			slider.value = this._range.min;
			slider.div.style.top = (slider.value-this._range.min)/this._scaleFactor - 7 + 'px';
		}else if (numericValue>this._range.max) {
			//alert("Input must be smaller than "+this._range.max+"!");
			slider.value = this._range.max;
			slider.div.style.top = (slider.value-this._range.min)/this._scaleFactor - 7 + 'px';
		}else {
			slider.div.style.top = (value-this._range.min)/this._scaleFactor - 7 + 'px';
			var position = parseInt(slider.div.style.top)+7;
			slider.value = parseFloat(Exhibit.Util.round(position*this._scaleFactor+this._range.min, this._prec));
		}
	}catch(err) {
		slider.value = slider.value;
	}

	this._setDisplays(slider);
	this._notifyFacet();
	return true;
}

// If you call this, it's up to you to notifyFacet if necessary
Exhibit.SliderFacet.slider.prototype.resetSliders = function(){
    this._setSlider(this._slider1, this._range.min);
    this._setSlider(this._slider2, this._range.max);
};

// If you call this, it's up to you to notifyFacet if necessary
Exhibit.SliderFacet.slider.prototype._setSlider = function(slider, value) {
    if (value > this._range.max) {
		value = this._range.max
    }else if (value < this._range.min) {
		value = this._range.min
    }
    value = Exhibit.Util.round(value, this._prec);

    slider.value = value;
    if (this._horizontal) {
    	slider.div.style.left = (value/this._scaleFactor-slider.offset) + 'px';
    }else {
    	slider.div.style.top = (value-this._range.min)/this._scaleFactor - 7 + 'px';
    }
    this._setDisplays(slider);
};

// Updates displays based on slider's value (i.e., slider's value should have changed recently)
Exhibit.SliderFacet.slider.prototype._setDisplays = function(slider) {
    var other = (slider == this._slider1)? this._slider2 : this._slider1;

    var min = Math.min(slider.value, other.value);
    var max = Math.max(slider.value, other.value);

    this._dom.maxDisplay.style.cssFloat = 'left';
    this._dom.minDisplay.value = min;
    this._dom.maxDisplay.value = max;

};

Exhibit.SliderFacet.slider.slider = function(div, self) { // individual slider handle that can be dragged
    var barEl = self._dom.bar;

    this.div = div; // containing div of handle

    if (self._horizontal) {
	    this.div.style.backgroundImage = 'url("'+Exhibit.urlPrefix+'images/slider-handle.png")';
	    this.offset = (this.div.offsetLeft - barEl.offsetLeft) + this.div.offsetWidth/2;
	    this.min = -this.offset; // slider's middle can reach left edge of bar
	    this.max = barEl.offsetWidth - this.offset; //slider's middle can reach right edge of bar
    }else {
	    this.div.style.backgroundImage = 'url("'+Exhibit.urlPrefix+'images/slider-handle2.png")';
	    //this.offset =  barEl.offsetTop;
	    this.min = 0;//-this.offset; // slider's middle can reach left edge of bar
	    this.max = barEl.offsetHeight; //slider's middle can reach right edge of bar
	}
    if (self._facet._settings.histogram) {
		this.div.style.top = (this.div.offsetHeight-4)+'px';
    }
};

Exhibit.SliderFacet.slider.prototype._registerDragging = function() {
    var self = this;

    var startDrag = function(slider) {
		return function(e) {
		    e = e || window.event;

		    var onMove = onDrag(e, slider);

		    if (document.attachEvent) {
			document.attachEvent('onmousemove', onMove);
			document.attachEvent('onmouseup', endDrag(slider, onMove));
		    } else {
			document.addEventListener('mousemove', onMove, false);
			document.addEventListener('mouseup', endDrag(slider, onMove), false);
		    }

		    SimileAjax.DOM.cancelEvent(e);
		    return false;
		};
    };

    var onDrag = function(e, slider) {
		var origY = e.screenY;
		if (this._horizontal) {
			var origLeft = parseInt(slider.div.style.left);
			var min = slider.min;
			var max = slider.max;
		}else {
			var origTop = parseInt(slider.div.style.top);
			var min = slider.min - 7;
			var max = slider.max - 7;
		}

		return function(e) {
		    e = e || window.event

			if (this._horizontal) {
				var dx = e.screenX - origX;
			    var newLeft = origLeft + dx;
			    if (newLeft < min) {
				newLeft = min;
			    }
			    if (newLeft > max) {
				newLeft = max;
			    }
			    slider.div.style.left = newLeft + 'px';

			    //setTimeout keeps setDisplay from slowing down the dragging
			    //I'm not entirely sure why, but I think it might have something to do with it putting the call in a new environment
			    setTimeout(function(){ var position = parseInt(slider.div.style.left) + slider.offset;
				                   slider.value = parseFloat(Exhibit.Util.round(position*self._scaleFactor+self._range.min, self._prec));
						   self._setDisplays(slider); }, 0);
			}else {
			    var dx = e.screenY - origY;
			    var newTop = origTop + dx;
			    if (newTop < min) {
					newTop = min;
			    }
			    if (newTop > max) {
					newTop = max;
			    }
			    slider.div.style.top = newTop + 'px';

			    //setTimeout keeps setDisplay from slowing down the dragging
			    //I'm not entirely sure why, but I think it might have something to do with it putting the call in a new environment
			    setTimeout(function(){ var position = parseInt(slider.div.style.top)+7;
				                   slider.value = parseFloat(Exhibit.Util.round(position*self._scaleFactor+self._range.min, self._prec));
						   self._setDisplays(slider); }, 0);
			}
		};
    };

    var endDrag = function(slider, moveListener) {
		return function(e) {

		    if(document.detachEvent) {
			document.detachEvent('onmousemove', moveListener);
			document.detachEvent('onmouseup', arguments.callee);
		    } else {
			document.removeEventListener('mousemove', moveListener, false);
			document.removeEventListener('mouseup', arguments.callee, false); //remove this function
		    }

		    self._notifyFacet();
		};
    };

    var attachListeners = function(slider) {
		if (document.attachEvent) {
		    slider.div.attachEvent('onmousedown', startDrag(slider));
		} else {
		    slider.div.addEventListener('mousedown', startDrag(slider), false);
		}
    };

    attachListeners(this._slider1);
    attachListeners(this._slider2);

};

Exhibit.SliderFacet.slider.prototype._notifyFacet = function() {
    var val1 = this._slider1.value;
    var val2 = this._slider2.value;
    this._facet.changeRange( {min: Math.min(val1, val2), max: Math.max(val1, val2)} );
};

Exhibit.SliderFacet.slider.prototype.updateHistogram = function(data, n) {
    // data ([numbers]): the values to graphed, in this case the attribute value of all unrestricted items
    // n (int): the number of bars in the histogram
    var n = n? n : 75;
    var histogram = this._dom.histogram;
    var ctx = histogram.getContext('2d');
    ctx.fillStyle = 'rgba(0,0,0,.25)';

    ctx.clearRect(0,0, histogram.width, histogram.height);

    var maxVal = Math.max.apply(Math, data); //find the max of an array

    if (!maxVal) {
		return; //nothing to draw
    }

	if (this._horizontal) {
		var width = this._dom.bar.offsetWidth/n;  // width of each bar
	    var maxHeight = this._dom.bar.offsetHeight;
	    var ratio = maxHeight/maxVal;

	    for (var i=0; i<n; i++){
		var height = Math.round(data[i]*ratio);
		ctx.fillRect(i*width, maxHeight-height, width, height)
	    }
	}else {
	    var height = this._dom.bar.offsetHeight/n;  // width of each bar
	    var maxWidth = this._dom.bar.offsetWidth;
	    var ratio = maxWidth/maxVal;

	    for (var i=0; i<n; i++){
			var width = Math.round(data[i]*ratio);
			ctx.fillRect(0, i*height, width, height)
	    }
	}
};

<commit_msg>taking consideration when _selection min, max are nulls<commit_after>
Exhibit.SliderFacet.slider = function(div, facet, precision, horizontal) {
	this._horizontal = horizontal;
	if (horizontal) {
		this.horizontalSlider(div, facet, precision);
	}else {
	    this._div = div;
	    this._facet = facet;
	    if (facet._maxRange.min % 1>0) {
	    	precision = .01;
	    	size = 4;
	    }else {
	    	precision = 1;
	    	size = 2;
	    }
	    this._prec = precision || .1;

	    this._range = {min: facet._maxRange.min,  // round down
			   max: facet._maxRange.max}; // round up

	    this._scaleFactor = null;
	    this._slider1 = {};
	    this._slider2 = {};

		var self = this;

	    this._dom = SimileAjax.DOM.createDOMFromString(
	        div,
		'
' +
		    '<input type="text" size="'+size+'" id="minDisplay" class="exhibit-slider-minDisplay"></input>' +
		'
' +
	        '
' +
		    '

' +
		    '

' +
		    (this._facet._settings.histogram? '<canvas class="exhibit-slider-histogram2" id="histogram"></canvas>' : '') +
		'
'+
		'
' +
		    '<input type="text" size="'+size+'" id="maxDisplay" class="exhibit-slider-maxDisplay"></input>' +
		'
'
	    );

	    this._scaleFactor = (this._range.max - this._range.min)/this._dom.bar.offsetHeight;

	    this._slider1 = new Exhibit.SliderFacet.slider.slider(this._dom.slider1, this);
	    this._slider2 = new Exhibit.SliderFacet.slider.slider(this._dom.slider2, this);

	    console.log(Math.max(facet._selection.min, this._range.min)+" "+Math.min(facet._selection.max, this._range.max));
	    this._setSlider(this._slider1, (facet._selection.min!=null)?Math.max(facet._selection.min, this._range.min):this._range.min);
    	this._setSlider(this._slider2, (facet._selection.max!=null)?Math.min(facet._selection.max, this._range.max):this._range.max);
	    this._registerDragging();

	    SimileAjax.WindowManager.registerEvent(self._dom.minDisplay, "change",
	                function(elmt, evt, target) {self.validateInput(self._slider1, self._dom.minDisplay.value); });

	    SimileAjax.WindowManager.registerEvent(self._dom.maxDisplay, "change",
	                function(elmt, evt, target) {self.validateInput(self._slider2, self._dom.maxDisplay.value); });

	    if(this._dom.histogram) {
		this._dom.histogram.width = this._dom.bar.offsetWidth;
		this._dom.histogram.height = this._dom.bar.offsetHeight;
	    } else {
		this._dom.bar.style.borderTop = '1px solid black';
	    }
    }
};

Exhibit.SliderFacet.slider.prototype.horizontalSlider = function(div, facet, precision) {
	this._div = div;
    this._facet = facet;
    this._prec = precision || .1;
    this._range = {min: parseFloat(Exhibit.Util.round(facet._maxRange.min-precision/2, this._prec)),  // round down
		   max: parseFloat(Exhibit.Util.round(facet._maxRange.max+precision/2, this._prec))}; // round up

    this._scaleFactor = null;
    this._slider1 = {};
    this._slider2 = {};

    this._dom = SimileAjax.DOM.createDOMFromString(
        div,
	'
' +
	    '

' +
	    '

' +
	'
' +
        '
' +
	    '

' +
	    '

' +
	    (this._facet._settings.histogram? '<canvas class="exhibit-slider-histogram" id="histogram"></canvas>' : '') +
	'
'
    );

    this._scaleFactor = (this._range.max - this._range.min)/this._dom.bar.offsetWidth;

    this._slider1 = new Exhibit.SliderFacet.slider.slider(this._dom.slider1, this);
    this._slider2 = new Exhibit.SliderFacet.slider.slider(this._dom.slider2, this);
    this._setSlider(this._slider1, this._range.min);
    this._setSlider(this._slider2, this._range.max);

    this._registerDragging();

    if(this._dom.histogram) {
		this._dom.histogram.width = this._dom.bar.offsetWidth;
		this._dom.histogram.height = this._dom.bar.offsetHeight;
    } else {
		this._dom.bar.style.borderTop = '1px solid black';
    }
};

Exhibit.SliderFacet.slider.prototype.validateInput = function(slider, value) {
	try {
		var numericValue = parseFloat(value);
		if (isNaN(numericValue)) {
			slider.value = slider.value;
		}else if (numericValue<this._range.min) {
			//alert("Input must be bigger than "+this._range.min+"!");
			slider.value = this._range.min;
			slider.div.style.top = (slider.value-this._range.min)/this._scaleFactor - 7 + 'px';
		}else if (numericValue>this._range.max) {
			//alert("Input must be smaller than "+this._range.max+"!");
			slider.value = this._range.max;
			slider.div.style.top = (slider.value-this._range.min)/this._scaleFactor - 7 + 'px';
		}else {
			slider.div.style.top = (value-this._range.min)/this._scaleFactor - 7 + 'px';
			var position = parseInt(slider.div.style.top)+7;
			slider.value = parseFloat(Exhibit.Util.round(position*this._scaleFactor+this._range.min, this._prec));
		}
	}catch(err) {
		slider.value = slider.value;
	}

	this._setDisplays(slider);
	this._notifyFacet();
	return true;
}

// If you call this, it's up to you to notifyFacet if necessary
Exhibit.SliderFacet.slider.prototype.resetSliders = function(){
    this._setSlider(this._slider1, this._range.min);
    this._setSlider(this._slider2, this._range.max);
};

// If you call this, it's up to you to notifyFacet if necessary
Exhibit.SliderFacet.slider.prototype._setSlider = function(slider, value) {
    if (value > this._range.max) {
		value = this._range.max
    }else if (value < this._range.min) {
		value = this._range.min
    }
    value = Exhibit.Util.round(value, this._prec);

    slider.value = value;
    if (this._horizontal) {
    	slider.div.style.left = (value/this._scaleFactor-slider.offset) + 'px';
    }else {
    	slider.div.style.top = (value-this._range.min)/this._scaleFactor - 7 + 'px';
    }
    this._setDisplays(slider);
};

// Updates displays based on slider's value (i.e., slider's value should have changed recently)
Exhibit.SliderFacet.slider.prototype._setDisplays = function(slider) {
    var other = (slider == this._slider1)? this._slider2 : this._slider1;

    var min = Math.min(slider.value, other.value);
    var max = Math.max(slider.value, other.value);

    this._dom.maxDisplay.style.cssFloat = 'left';
    this._dom.minDisplay.value = min;
    this._dom.maxDisplay.value = max;

};

Exhibit.SliderFacet.slider.slider = function(div, self) { // individual slider handle that can be dragged
    var barEl = self._dom.bar;

    this.div = div; // containing div of handle

    if (self._horizontal) {
	    this.div.style.backgroundImage = 'url("'+Exhibit.urlPrefix+'images/slider-handle.png")';
	    this.offset = (this.div.offsetLeft - barEl.offsetLeft) + this.div.offsetWidth/2;
	    this.min = -this.offset; // slider's middle can reach left edge of bar
	    this.max = barEl.offsetWidth - this.offset; //slider's middle can reach right edge of bar
    }else {
	    this.div.style.backgroundImage = 'url("'+Exhibit.urlPrefix+'images/slider-handle2.png")';
	    //this.offset =  barEl.offsetTop;
	    this.min = 0;//-this.offset; // slider's middle can reach left edge of bar
	    this.max = barEl.offsetHeight; //slider's middle can reach right edge of bar
	}
    if (self._facet._settings.histogram) {
		this.div.style.top = (this.div.offsetHeight-4)+'px';
    }
};

Exhibit.SliderFacet.slider.prototype._registerDragging = function() {
    var self = this;

    var startDrag = function(slider) {
		return function(e) {
		    e = e || window.event;

		    var onMove = onDrag(e, slider);

		    if (document.attachEvent) {
			document.attachEvent('onmousemove', onMove);
			document.attachEvent('onmouseup', endDrag(slider, onMove));
		    } else {
			document.addEventListener('mousemove', onMove, false);
			document.addEventListener('mouseup', endDrag(slider, onMove), false);
		    }

		    SimileAjax.DOM.cancelEvent(e);
		    return false;
		};
    };

    var onDrag = function(e, slider) {
		var origY = e.screenY;
		if (this._horizontal) {
			var origLeft = parseInt(slider.div.style.left);
			var min = slider.min;
			var max = slider.max;
		}else {
			var origTop = parseInt(slider.div.style.top);
			var min = slider.min - 7;
			var max = slider.max - 7;
		}

		return function(e) {
		    e = e || window.event

			if (this._horizontal) {
				var dx = e.screenX - origX;
			    var newLeft = origLeft + dx;
			    if (newLeft < min) {
				newLeft = min;
			    }
			    if (newLeft > max) {
				newLeft = max;
			    }
			    slider.div.style.left = newLeft + 'px';

			    //setTimeout keeps setDisplay from slowing down the dragging
			    //I'm not entirely sure why, but I think it might have something to do with it putting the call in a new environment
			    setTimeout(function(){ var position = parseInt(slider.div.style.left) + slider.offset;
				                   slider.value = parseFloat(Exhibit.Util.round(position*self._scaleFactor+self._range.min, self._prec));
						   self._setDisplays(slider); }, 0);
			}else {
			    var dx = e.screenY - origY;
			    var newTop = origTop + dx;
			    if (newTop < min) {
					newTop = min;
			    }
			    if (newTop > max) {
					newTop = max;
			    }
			    slider.div.style.top = newTop + 'px';

			    //setTimeout keeps setDisplay from slowing down the dragging
			    //I'm not entirely sure why, but I think it might have something to do with it putting the call in a new environment
			    setTimeout(function(){ var position = parseInt(slider.div.style.top)+7;
				                   slider.value = parseFloat(Exhibit.Util.round(position*self._scaleFactor+self._range.min, self._prec));
						   self._setDisplays(slider); }, 0);
			}
		};
    };

    var endDrag = function(slider, moveListener) {
		return function(e) {

		    if(document.detachEvent) {
			document.detachEvent('onmousemove', moveListener);
			document.detachEvent('onmouseup', arguments.callee);
		    } else {
			document.removeEventListener('mousemove', moveListener, false);
			document.removeEventListener('mouseup', arguments.callee, false); //remove this function
		    }

		    self._notifyFacet();
		};
    };

    var attachListeners = function(slider) {
		if (document.attachEvent) {
		    slider.div.attachEvent('onmousedown', startDrag(slider));
		} else {
		    slider.div.addEventListener('mousedown', startDrag(slider), false);
		}
    };

    attachListeners(this._slider1);
    attachListeners(this._slider2);

};

Exhibit.SliderFacet.slider.prototype._notifyFacet = function() {
    var val1 = this._slider1.value;
    var val2 = this._slider2.value;
    this._facet.changeRange( {min: Math.min(val1, val2), max: Math.max(val1, val2)} );
};

Exhibit.SliderFacet.slider.prototype.updateHistogram = function(data, n) {
    // data ([numbers]): the values to graphed, in this case the attribute value of all unrestricted items
    // n (int): the number of bars in the histogram
    var n = n? n : 75;
    var histogram = this._dom.histogram;
    var ctx = histogram.getContext('2d');
    ctx.fillStyle = 'rgba(0,0,0,.25)';

    ctx.clearRect(0,0, histogram.width, histogram.height);

    var maxVal = Math.max.apply(Math, data); //find the max of an array

    if (!maxVal) {
		return; //nothing to draw
    }

	if (this._horizontal) {
		var width = this._dom.bar.offsetWidth/n;  // width of each bar
	    var maxHeight = this._dom.bar.offsetHeight;
	    var ratio = maxHeight/maxVal;

	    for (var i=0; i<n; i++){
		var height = Math.round(data[i]*ratio);
		ctx.fillRect(i*width, maxHeight-height, width, height)
	    }
	}else {
	    var height = this._dom.bar.offsetHeight/n;  // width of each bar
	    var maxWidth = this._dom.bar.offsetWidth;
	    var ratio = maxWidth/maxVal;

	    for (var i=0; i<n; i++){
			var width = Math.round(data[i]*ratio);
			ctx.fillRect(0, i*height, width, height)
	    }
	}
};

<|endoftext|>


<commit_before>$(function() {

  var userRolesModule = (function() {
    var myData = { 'users':[], 'roles':[] };
    var currentUser = '';

    /* Cache DOM elements */
    var $table  = $('#sa-table');
    var $eModal = $('#emodal');
    var $modalTitle = $eModal.find('.modal-title');
    var $modalForm  = $eModal.find('.modal-body form');
    var $modalSave  = $eModal.find('.modal-footer button:nth-child(2)');

    var tableTpl = '

id	Username	Roles

'+
      '
'+
      '{{#.}}'+
        '
{{id}}	{{username}}	{{roles}}
'+
      '{{/.}}'+
      '{{^.}}'+
        '
	No records found
'+
      '{{/.}}'+
      '
';

    var checkboxTpl =
      '{{#.}}'+
        '
<input type="checkbox" name="{{name}}" value="{{id}}">{{name}}
'+
      '{{/.}}';

    /* Initialise module */
    function init() {
      // Open modal form on click of user row
      $table.on('click', 'tr', function() {
        currentUser = $(this).find('.username').text();
        $modalTitle.text('Edit Roles - '+currentUser);
        // Prefill checkboxes
        var user = $.grep(myData.users, function(u) { return u.username == currentUser })[0];
        $modalForm.find('input').each(function() {
          var id = parseInt($(this).val());
          if ($.inArray(id, user.role_ids) !== -1) { $(this).prop('checked', true); }
        });
        // Finally show modal
        $eModal.modal('show');
      });

      $modalSave.on('click', _submitModal);

      // Reset modal style when hidden
      $eModal.on('hidden.bs.modal', function () {
        styleBtn($modalSave, 'primary', 'Save');
        $modalForm.trigger('reset');
      });

      _update();
    }

    /* Render module */
    function _render() {
      // Render table
      var tpl = Mustache.render(tableTpl, myData.users);
      $table.html(tpl);

      // Render modal
      var tpl = Mustache.render(checkboxTpl, myData.roles);
      $modalForm.html(tpl);
    }

    /* Update user & roles data */
    function _update() {
      $.get({
        url: 'api/useraccessgroup.php',
        dataType: 'json'
      })
        .done(function(d) {
          myData.users = d.users;
          myData.roles = d.roles;
        })
        .fail(logAjaxError)
        .always(function() {
          _render();
        });
    }

    /* On submit: send form data, style button, fade out, then hide */
    function _submitModal() {
      var roles = [];
      $modalForm.find('input').each(function() {
        var $check = $(this);
        if ($check.is(':checked')) { roles.push($check.val()); }
      });

      $.ajax({
        method: 'POST',
        url: 'api/useraccessgroup.php',
        data: JSON.stringify({'username': currentUser, 'roles': roles}),
        dataType: 'json'
      })
        .done(function() {
          styleBtn($modalSave, 'success', 'Saved!');
        })
        .fail(function(jq, status, error) {
          styleBtn($modalSave, 'danger', 'Error!');
          logAjaxError(jq, status, error);
        })
        .always(function() {
          _update();
          setTimeout(function() { $eModal.modal('hide'); }, 500);
      });
    }

    function styleBtn(btn, style, text) {
      if (style === 'success') {
        btn.removeClass('btn-primary btn-danger')
           .addClass('btn-success');
      } else if (style === 'danger') {
        btn.removeClass('btn-primary btn-success')
           .addClass('btn-danger');
      } else if (style === 'primary') {
        btn.removeClass('btn-success btn-danger')
           .addClass('btn-primary');
      }
      btn.text(text);
    }

    /* Log AJAX errors */
    function logAjaxError(jq, status, error)  {
        console.log("An AJAX Error Occured!");
        console.log("  Text status: " + status);
        console.log("  Error thrown: " + error);
        console.log("  jqXHR: " + JSON.stringify(jq));
    }

    return {
      init: init
    };
  })();

  userRolesModule.init();
});
<commit_msg>Naming<commit_after>$(function() {

  var userRolesModule = (function() {
    var myData = { 'users':[], 'roles':[] };
    var currentUser = '';

    /* Cache DOM elements */
    var $table  = $('#sa-table');
    var $editModal = $('#edit-modal');
    var $modalTitle = $editModal.find('.modal-title');
    var $modalForm  = $editModal.find('.modal-body form');
    var $modalSave  = $editModal.find('.modal-footer button:nth-child(2)');

    var tableTpl = '

id	Username	Roles

'+
      '
'+
      '{{#.}}'+
        '
{{id}}	{{username}}	{{roles}}
'+
      '{{/.}}'+
      '{{^.}}'+
        '
	No records found
'+
      '{{/.}}'+
      '
';

    var checkboxTpl =
      '{{#.}}'+
        '
<input type="checkbox" name="{{name}}" value="{{id}}">{{name}}
'+
      '{{/.}}';

    /* Initialise module */
    function init() {
      // Open modal form on click of user row
      $table.on('click', 'tr', function() {
        currentUser = $(this).find('.username').text();
        $modalTitle.text('Edit Roles - '+currentUser);
        // Prefill checkboxes
        var user = $.grep(myData.users, function(u) { return u.username == currentUser })[0];
        $modalForm.find('input').each(function() {
          var id = parseInt($(this).val());
          if ($.inArray(id, user.role_ids) !== -1) { $(this).prop('checked', true); }
        });
        // Finally show modal
        $editModal.modal('show');
      });

      $modalSave.on('click', _submitModal);

      // Reset modal style when hidden
      $editModal.on('hidden.bs.modal', function () {
        bsStyleBtn($modalSave, 'primary', 'Save');
        $modalForm.trigger('reset');
      });

      _update();
    }

    /* Render module */
    function _render() {
      // Render table
      var tpl = Mustache.render(tableTpl, myData.users);
      $table.html(tpl);

      // Render modal
      var tpl = Mustache.render(checkboxTpl, myData.roles);
      $modalForm.html(tpl);
    }

    /* Update user & roles data */
    function _update() {
      $.get({
        url: 'api/useraccessgroup.php',
        dataType: 'json'
      })
        .done(function(d) {
          myData.users = d.users;
          myData.roles = d.roles;
        })
        .fail(logAjaxError)
        .always(function() {
          _render();
        });
    }

    /* On submit: send form data, style button, fade out, then hide */
    function _submitModal() {
      var roles = [];
      $modalForm.find('input').each(function() {
        var $check = $(this);
        if ($check.is(':checked')) { roles.push($check.val()); }
      });

      $.ajax({
        method: 'POST',
        url: 'api/useraccessgroup.php',
        data: JSON.stringify({'username': currentUser, 'roles': roles}),
        dataType: 'json'
      })
        .done(function() {
          bsStyleBtn($modalSave, 'success', 'Saved!');
        })
        .fail(function(jq, status, error) {
          bsStyleBtn($modalSave, 'danger', 'Error!');
          logAjaxError(jq, status, error);
        })
        .always(function() {
          _update();
          setTimeout(function() { $editModal.modal('hide'); }, 500);
      });
    }

    function bsStyleBtn(btn, style, text) {
      if (style === 'success') {
        btn.removeClass('btn-primary btn-danger')
           .addClass('btn-success');
      } else if (style === 'danger') {
        btn.removeClass('btn-primary btn-success')
           .addClass('btn-danger');
      } else if (style === 'primary') {
        btn.removeClass('btn-success btn-danger')
           .addClass('btn-primary');
      }
      btn.text(text);
    }

    /* Log AJAX errors */
    function logAjaxError(jq, status, error)  {
        console.log("An AJAX Error Occured!");
        console.log("  Text status: " + status);
        console.log("  Error thrown: " + error);
        console.log("  jqXHR: " + JSON.stringify(jq));
    }

    return {
      init: init
    };
  })();

  userRolesModule.init();
});
<|endoftext|>