<commit_before>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012-2015 Mailvelope GmbH
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Listens for events from options UI in sandbox, forwards requests to pgpModel.js
 */

'use strict';

var mvelo = mvelo || null;
var options = {};

(function(exports, $) {
  // event controller
  var event = $('<div/>');
  var l10n = {};
  var keyringTmpl;
  var $keyringList;
  var keyringId = null;
  var demailSuffix = 'de-mail.de';

  function init() {
    if (document.body.dataset.mvelo) {
      return;
    }
    document.body.dataset.mvelo = true;
    initMessageListener();

    mvelo.appendTpl($('body'), mvelo.extension.getURL('common/ui/settings/tpl/main.html'))
      .then(function() {
        window.Promise.all([
          mvelo.appendTpl($('#general'), mvelo.extension.getURL('common/ui/settings/tpl/general.html')),
          mvelo.appendTpl($('#security'), mvelo.extension.getURL('common/ui/settings/tpl/security.html')),
          mvelo.appendTpl($('#watchList'), mvelo.extension.getURL('common/ui/settings/tpl/watchList.html')),
          mvelo.appendTpl($('#watchList'), mvelo.extension.getURL('common/ui/settings/tpl/watchListEditor.html')),
          mvelo.appendTpl($('#securityLog'), mvelo.extension.getURL('common/ui/settings/tpl/securityLog.html')),
          mvelo.appendTpl($('#displayKeys'), mvelo.extension.getURL('common/ui/keyring/tpl/displayKeys.html')),
          mvelo.appendTpl($('#displayKeys'), mvelo.extension.getURL('common/ui/keyring/tpl/keyEditor.html')),
          mvelo.appendTpl($('#importKey'), mvelo.extension.getURL('common/ui/keyring/tpl/importKey.html')),
          mvelo.appendTpl($('#exportsKey'), mvelo.extension.getURL('common/ui/keyring/tpl/exportKeys.html')),
          mvelo.appendTpl($('#setupProvider'), mvelo.extension.getURL('common/ui/keyring/tpl/setupProvider.html')),
          mvelo.appendTpl($('#generateKey'), mvelo.extension.getURL('common/ui/keyring/tpl/generateKey.html')),
          mvelo.appendTpl($('#encrypting'), mvelo.extension.getURL('common/ui/fileEncrypt/encrypt.html'))

        ]).then(initUI);
      });
  }

  function initUI() {
    mvelo.extension.sendMessage({
      event: 'get-version'
    }, function(version) {
      $('#version').text('v' + version);
    });

    var qs = jQuery.parseQuerystring();

    mvelo.extension.sendMessage({event: 'get-active-keyring'}, function(data) {
      keyringId = data || mvelo.LOCAL_KEYRING_ID;
      if (qs.hasOwnProperty('krid')) {
        keyringId = decodeURIComponent(qs.krid);
        if (keyringId.indexOf(demailSuffix) > 3) {
          $('#genKeyEmail').attr('disabled', 'disabled');
          $('#genKeyEmailLabel').attr('data-l10n-id', 'key_gen_demail');
        }
      }

      setKeyRing(keyringId);
      setKeyGenDefaults(qs);

      // No private key yet? Navigate to setup tab
      options.keyring('getPrivateKeys')
        .then(function(result) {
          if (!result.length) {
            $('.keyring_setup_message').addClass('active');

            $('#setupProviderButton')
              .tab('show') // Activate setup tab
              .addClass('active')
              .siblings('a.list-group-item').removeClass('active') // Activate setup navigation
            ;
          } else {
            $('#displayKeysButton')
              .tab('show') // Activate display keys tab
              .addClass('active')
              .siblings('a.list-group-item').removeClass('active') // Activate display keys navigation
            ;
            $('.keyring_setup_message').removeClass('active');
          }

          registerL10nMessages([
            'keygrid_user_email',
            'key_gen_demail'
          ]);

          mvelo.l10n.localizeHTML();
          mvelo.util.showSecurityBackground();

          $keyringList = $('#keyringList');
          if (keyringTmpl === undefined) {
            keyringTmpl = $keyringList.html();
            $keyringList.empty();
          }

          // Disable submitting of forms by for example pressing enter
          $('form').submit(function(e) { e.preventDefault(); });

          // Enabling selection of the elements in settings navigation
          $('.list-group-item').on('click', function() {
            window.location.hash = $(this).attr('href');
            var self = $(this);
            if (!self.hasClass('disabled')) {
              self.parent().find('.list-group-item').each(function() {
                $(this).removeClass('active');
              });
              self.addClass('active');
            }
          });

          // Activate tab after switch from links to tabs outside
          $('[data-toggle="tab"]:not(.list-group-item)').on('click', function() {
            window.location.hash = $(this).attr('href');
            var id = $(this).attr('href'),
              tabTrigger = $('.list-group a[href="' + id + '"]');

            if (id && tabTrigger) {
              tabTrigger.siblings('a.list-group-item').removeClass('active');
              tabTrigger.addClass('active');
            }
          });

          options.getAllKeyringAttr()
            .then(function(result) {
              initKeyringSelection(result);

              switch (window.location.hash) {
                case '#securityLog':
                  $('#settingsButton').tab('show');
                  options.startSecurityLogMonitoring();
                  break;
                case '#general':
                case '#security':
                case '#watchList':
                case '#backup':
                  $('#settingsButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                case '#displayKeys':
                case '#importKey':
                case '#exportKeys':
                case '#generateKey':
                case '#setupProvider':
                  $('#keyringButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                case '#encrypting':
                case '#file_encrypting':
                case '#file_decrypting':
                  $('#encryptingButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                default:
                  if (window.location.hash == '#settings') {
                    $('#settingsButton').tab('show');
                  } else if (window.location.hash == '#keyring') {
                    $('#keyringButton').tab('show');
                  } else {
                    //console.log((window.location.hash) ? window.location.hash : 'no hash found');
                    window.location.hash = 'displayKeys';
                    $('#keyringButton').tab('show');
                  }
              }
              activateTabButton(window.location.hash);

              getL10nMessages(Object.keys(l10n), function(result) {
                exports.l10n = result;
                event.triggerHandler('ready');
              });
            });
        });
    });
  }

  function setKeyGenDefaults(qs) {
    if (qs.hasOwnProperty('email')) {
      var decodedEmail = decodeURIComponent(qs.email);
      $('#genKeyEmail').val(decodedEmail);
    }

    if (qs.hasOwnProperty('fname')) {
      $('#genKeyName').val(decodeURIComponent(qs.fname));
    }
  }

  function initKeyringSelection(data) {
    if (data === undefined) {
      return false;
    }

    var keyringHTML;
    var keyringName;

    for (var keyRingId in data) {
      keyringName = splitKeyringId(keyRingId);
      keyringHTML = $.parseHTML(keyringTmpl);

      var obj = data[keyRingId];
      if (obj.hasOwnProperty('primary_key')) {
        if (exports.keyringId === keyRingId) {
          exports.primaryKeyId = obj.primary_key;
        }
        $(keyringHTML).find('.keyRingName').attr('data-primarykeyid', obj.primary_key);
      }
      if (obj.hasOwnProperty('logo_data_url')) {
        $(keyringHTML).find('.keyRingName').attr('data-providerlogo', obj.logo_data_url);
      }

      if (keyRingId === mvelo.LOCAL_KEYRING_ID) {
        keyringName = 'Mailvelope';
        $(keyringHTML).find('.deleteKeyRing').hide();
      }

      $(keyringHTML).find('.keyRingName').text(keyringName);
      $(keyringHTML).find('.keyRingName').attr('data-keyringid', keyRingId);
      $(keyringHTML).find('.deleteKeyRing').attr('data-keyringid', keyRingId);
      $keyringList.append(keyringHTML);
    }

    $keyringList.find('.keyRingName').on('click', switchKeyring);
    $keyringList.find('.deleteKeyRing').on('click', exports.deleteKeyring);

    setKeyRing(keyringId);
  }

  function activateTabButton(hash) {
    if (!hash) {
      return;
    }

    var name = hash + 'Button';
    $(name)
      .tab('show')
      .addClass('active')
      .siblings('a.list-group-item').removeClass('active')
    ;
  }

  function setKeyRing(keyringId) {
    var primaryKeyId = $('a[data-keyringid="' + keyringId + '"]').attr('data-primarykeyid');
    var providerLogo = $('a[data-keyringid="' + keyringId + '"]').attr('data-providerlogo');

    var keyringName;
    if (keyringId === mvelo.LOCAL_KEYRING_ID) {
      keyringName = 'Mailvelope';
    } else if (keyringId) {
      keyringName = splitKeyringId(keyringId);
    }

    $('#keyringSwitcherLabel').text(keyringName);
    exports.keyringId = keyringId;

    if (primaryKeyId) {
      exports.primaryKeyId = primaryKeyId;
      $('.keyring_setup_message').removeClass('active');
    } else {
      $('.keyring_setup_message').addClass('active');
    }

    var $logoArea = $('.third-party-logo');
    if (providerLogo) {
      $logoArea.css({
        'background-image': 'url(' + providerLogo + ')',
        'background-repeat': 'no-repeat',
        'background-position': 'right top'
      });
    } else {
      $logoArea.css('background-image', 'none');
    }
  }

  function switchKeyring() {
    var keyringId = $(this).attr('data-keyringid');
    setKeyRing(keyringId);

    $('#genKeyEmailLabel').removeAttr('data-l10n-id');

    mvelo.util.showLoadingAnimation();
    options.event.triggerHandler('keygrid-reload');
  }

  function initMessageListener() {
    mvelo.extension.onMessage.addListener(
      function(request, sender, sendResponse) {
        return handleRequests(request, sender, sendResponse);
      }
    );
  }

  function splitKeyringId(keyringId) {
    return keyringId.split(mvelo.KEYRING_DELIMITER)[0] + ' (' + keyringId.split(mvelo.KEYRING_DELIMITER)[1] + ')';
  }

  function handleRequests(request, sender, sendResponse) {
    switch (request.event) {
      case 'add-watchlist-item':
        $('#settingsButton').trigger('click');
        $('#watchListButton').trigger('click');
        options.addToWatchList(request.site);
        break;
      case 'reload-options':
        if (request.hash === '#showlog') {
          $('#settingsButton').trigger('click');
          $('#securityLogButton').trigger('click');
        } else {
          options.reloadOptions();
        }
        break;
      case 'import-key':
        $('#keyringButton').trigger('click');
        $('#importKeyButton').trigger('click');
        options.importKey(request.armored, function(result) {
          sendResponse({
            result: result,
            id: request.id
          });
        });
        return true;
      default:
      // TODO analyse message events
      //console.log('unknown event:', request);
    }
  }

  function reloadOptions() {
    document.location.reload();
  }

  function sendMessage(obj) {
    return new Promise(function(resolve, reject) {
      mvelo.extension.sendMessage(obj, function(data) {
        if (data.error) {
          reject(data.error);
        } else {
          resolve(data.result);
        }
      });
    });
  }

  function getAllKeyringAttr() {
    return sendMessage({ event: 'get-all-keyring-attr'});
  }

  function getAllKeyUserId() {
    return sendMessage({ event: 'get-all-key-userid'});
  }

  function pgpModel(method, args) {
    return sendMessage({
      event: 'pgpmodel',
      method: method,
      args: args
    });
  }

  function keyring(method, args) {
    return sendMessage({
      event: 'keyring',
      method: method,
      args: args,
      keyringId: options.keyringId
    });
  }

  function copyToClipboard(text) {
    var copyFrom = $('<textarea />');
    $('body').append(copyFrom);
    copyFrom.hide();
    copyFrom.text(text);
    copyFrom.select();
    document.execCommand('copy');
    copyFrom.remove();
  }

  function getL10nMessages(ids, callback) {
    mvelo.l10n.getMessages(ids, callback);
  }

  function registerL10nMessages(ids) {
    ids.forEach(function(id) {
      exports.l10n[id] = true;
    });
  }

  function openTab(url) {
    return send({
      event: 'open-tab',
      url: url
    });
  }

  function send(options) {
    return new Promise(function(resolve, reject) {
      mvelo.extension.sendMessage(options, function(data) {
        if (data.error) {
          reject(data.error);
        } else {
          resolve(data.result);
        }
      });
    });
  }

  exports.reloadOptions = reloadOptions;
  exports.getAllKeyringAttr = getAllKeyringAttr;
  exports.getAllKeyUserId = getAllKeyUserId;
  exports.pgpModel = pgpModel;
  exports.keyring = keyring;
  exports.copyToClipboard = copyToClipboard;
  exports.getL10nMessages = getL10nMessages;
  exports.registerL10nMessages = registerL10nMessages;
  exports.keyringId = keyringId;
  exports.openTab = openTab;

  exports.event = event;
  exports.l10n = l10n;

  // Update visibility of setup alert box
  options.event.on('keygrid-reload', function() {
    options.keyring('getPrivateKeys')
      .then(function(result) {
        if (!result.length) {
          $('.keyring_setup_message').addClass('active');
        } else {
          $('.keyring_setup_message').removeClass('active');
        }
      });
  });

  $(document).ready(init);

}(options, jQuery));
<commit_msg>Cleanup: wrap mvelo.extension.sendMessage in generic helper<commit_after>/**
 * Mailvelope - secure email with OpenPGP encryption for Webmail
 * Copyright (C) 2012-2015 Mailvelope GmbH
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Listens for events from options UI in sandbox, forwards requests to pgpModel.js
 */

'use strict';

var mvelo = mvelo || null;
var options = {};

(function(exports, $) {
  // event controller
  var event = $('<div/>');
  var l10n = {};
  var keyringTmpl;
  var $keyringList;
  var keyringId = null;
  var demailSuffix = 'de-mail.de';

  function init() {
    if (document.body.dataset.mvelo) {
      return;
    }
    document.body.dataset.mvelo = true;
    initMessageListener();

    mvelo.appendTpl($('body'), mvelo.extension.getURL('common/ui/settings/tpl/main.html'))
      .then(function() {
        window.Promise.all([
          mvelo.appendTpl($('#general'), mvelo.extension.getURL('common/ui/settings/tpl/general.html')),
          mvelo.appendTpl($('#security'), mvelo.extension.getURL('common/ui/settings/tpl/security.html')),
          mvelo.appendTpl($('#watchList'), mvelo.extension.getURL('common/ui/settings/tpl/watchList.html')),
          mvelo.appendTpl($('#watchList'), mvelo.extension.getURL('common/ui/settings/tpl/watchListEditor.html')),
          mvelo.appendTpl($('#securityLog'), mvelo.extension.getURL('common/ui/settings/tpl/securityLog.html')),
          mvelo.appendTpl($('#displayKeys'), mvelo.extension.getURL('common/ui/keyring/tpl/displayKeys.html')),
          mvelo.appendTpl($('#displayKeys'), mvelo.extension.getURL('common/ui/keyring/tpl/keyEditor.html')),
          mvelo.appendTpl($('#importKey'), mvelo.extension.getURL('common/ui/keyring/tpl/importKey.html')),
          mvelo.appendTpl($('#exportsKey'), mvelo.extension.getURL('common/ui/keyring/tpl/exportKeys.html')),
          mvelo.appendTpl($('#setupProvider'), mvelo.extension.getURL('common/ui/keyring/tpl/setupProvider.html')),
          mvelo.appendTpl($('#generateKey'), mvelo.extension.getURL('common/ui/keyring/tpl/generateKey.html')),
          mvelo.appendTpl($('#encrypting'), mvelo.extension.getURL('common/ui/fileEncrypt/encrypt.html'))

        ]).then(initUI);
      });
  }

  function initUI() {
    mvelo.extension.sendMessage({
      event: 'get-version'
    }, function(version) {
      $('#version').text('v' + version);
    });

    var qs = jQuery.parseQuerystring();

    mvelo.extension.sendMessage({event: 'get-active-keyring'}, function(data) {
      keyringId = data || mvelo.LOCAL_KEYRING_ID;
      if (qs.hasOwnProperty('krid')) {
        keyringId = decodeURIComponent(qs.krid);
        if (keyringId.indexOf(demailSuffix) > 3) {
          $('#genKeyEmail').attr('disabled', 'disabled');
          $('#genKeyEmailLabel').attr('data-l10n-id', 'key_gen_demail');
        }
      }

      setKeyRing(keyringId);
      setKeyGenDefaults(qs);

      // No private key yet? Navigate to setup tab
      options.keyring('getPrivateKeys')
        .then(function(result) {
          if (!result.length) {
            $('.keyring_setup_message').addClass('active');

            $('#setupProviderButton')
              .tab('show') // Activate setup tab
              .addClass('active')
              .siblings('a.list-group-item').removeClass('active') // Activate setup navigation
            ;
          } else {
            $('#displayKeysButton')
              .tab('show') // Activate display keys tab
              .addClass('active')
              .siblings('a.list-group-item').removeClass('active') // Activate display keys navigation
            ;
            $('.keyring_setup_message').removeClass('active');
          }

          registerL10nMessages([
            'keygrid_user_email',
            'key_gen_demail'
          ]);

          mvelo.l10n.localizeHTML();
          mvelo.util.showSecurityBackground();

          $keyringList = $('#keyringList');
          if (keyringTmpl === undefined) {
            keyringTmpl = $keyringList.html();
            $keyringList.empty();
          }

          // Disable submitting of forms by for example pressing enter
          $('form').submit(function(e) { e.preventDefault(); });

          // Enabling selection of the elements in settings navigation
          $('.list-group-item').on('click', function() {
            window.location.hash = $(this).attr('href');
            var self = $(this);
            if (!self.hasClass('disabled')) {
              self.parent().find('.list-group-item').each(function() {
                $(this).removeClass('active');
              });
              self.addClass('active');
            }
          });

          // Activate tab after switch from links to tabs outside
          $('[data-toggle="tab"]:not(.list-group-item)').on('click', function() {
            window.location.hash = $(this).attr('href');
            var id = $(this).attr('href'),
              tabTrigger = $('.list-group a[href="' + id + '"]');

            if (id && tabTrigger) {
              tabTrigger.siblings('a.list-group-item').removeClass('active');
              tabTrigger.addClass('active');
            }
          });

          options.getAllKeyringAttr()
            .then(function(result) {
              initKeyringSelection(result);

              switch (window.location.hash) {
                case '#securityLog':
                  $('#settingsButton').tab('show');
                  options.startSecurityLogMonitoring();
                  break;
                case '#general':
                case '#security':
                case '#watchList':
                case '#backup':
                  $('#settingsButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                case '#displayKeys':
                case '#importKey':
                case '#exportKeys':
                case '#generateKey':
                case '#setupProvider':
                  $('#keyringButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                case '#encrypting':
                case '#file_encrypting':
                case '#file_decrypting':
                  $('#encryptingButton').tab('show');
                  activateTabButton(window.location.hash);
                  break;
                default:
                  if (window.location.hash == '#settings') {
                    $('#settingsButton').tab('show');
                  } else if (window.location.hash == '#keyring') {
                    $('#keyringButton').tab('show');
                  } else {
                    //console.log((window.location.hash) ? window.location.hash : 'no hash found');
                    window.location.hash = 'displayKeys';
                    $('#keyringButton').tab('show');
                  }
              }
              activateTabButton(window.location.hash);

              getL10nMessages(Object.keys(l10n), function(result) {
                exports.l10n = result;
                event.triggerHandler('ready');
              });
            });
        });
    });
  }

  function setKeyGenDefaults(qs) {
    if (qs.hasOwnProperty('email')) {
      var decodedEmail = decodeURIComponent(qs.email);
      $('#genKeyEmail').val(decodedEmail);
    }

    if (qs.hasOwnProperty('fname')) {
      $('#genKeyName').val(decodeURIComponent(qs.fname));
    }
  }

  function initKeyringSelection(data) {
    if (data === undefined) {
      return false;
    }

    var keyringHTML;
    var keyringName;

    for (var keyRingId in data) {
      keyringName = splitKeyringId(keyRingId);
      keyringHTML = $.parseHTML(keyringTmpl);

      var obj = data[keyRingId];
      if (obj.hasOwnProperty('primary_key')) {
        if (exports.keyringId === keyRingId) {
          exports.primaryKeyId = obj.primary_key;
        }
        $(keyringHTML).find('.keyRingName').attr('data-primarykeyid', obj.primary_key);
      }
      if (obj.hasOwnProperty('logo_data_url')) {
        $(keyringHTML).find('.keyRingName').attr('data-providerlogo', obj.logo_data_url);
      }

      if (keyRingId === mvelo.LOCAL_KEYRING_ID) {
        keyringName = 'Mailvelope';
        $(keyringHTML).find('.deleteKeyRing').hide();
      }

      $(keyringHTML).find('.keyRingName').text(keyringName);
      $(keyringHTML).find('.keyRingName').attr('data-keyringid', keyRingId);
      $(keyringHTML).find('.deleteKeyRing').attr('data-keyringid', keyRingId);
      $keyringList.append(keyringHTML);
    }

    $keyringList.find('.keyRingName').on('click', switchKeyring);
    $keyringList.find('.deleteKeyRing').on('click', exports.deleteKeyring);

    setKeyRing(keyringId);
  }

  function activateTabButton(hash) {
    if (!hash) {
      return;
    }

    var name = hash + 'Button';
    $(name)
      .tab('show')
      .addClass('active')
      .siblings('a.list-group-item').removeClass('active')
    ;
  }

  function setKeyRing(keyringId) {
    var primaryKeyId = $('a[data-keyringid="' + keyringId + '"]').attr('data-primarykeyid');
    var providerLogo = $('a[data-keyringid="' + keyringId + '"]').attr('data-providerlogo');

    var keyringName;
    if (keyringId === mvelo.LOCAL_KEYRING_ID) {
      keyringName = 'Mailvelope';
    } else if (keyringId) {
      keyringName = splitKeyringId(keyringId);
    }

    $('#keyringSwitcherLabel').text(keyringName);
    exports.keyringId = keyringId;

    if (primaryKeyId) {
      exports.primaryKeyId = primaryKeyId;
      $('.keyring_setup_message').removeClass('active');
    } else {
      $('.keyring_setup_message').addClass('active');
    }

    var $logoArea = $('.third-party-logo');
    if (providerLogo) {
      $logoArea.css({
        'background-image': 'url(' + providerLogo + ')',
        'background-repeat': 'no-repeat',
        'background-position': 'right top'
      });
    } else {
      $logoArea.css('background-image', 'none');
    }
  }

  function switchKeyring() {
    var keyringId = $(this).attr('data-keyringid');
    setKeyRing(keyringId);

    $('#genKeyEmailLabel').removeAttr('data-l10n-id');

    mvelo.util.showLoadingAnimation();
    options.event.triggerHandler('keygrid-reload');
  }

  function initMessageListener() {
    mvelo.extension.onMessage.addListener(
      function(request, sender, sendResponse) {
        return handleRequests(request, sender, sendResponse);
      }
    );
  }

  function splitKeyringId(keyringId) {
    return keyringId.split(mvelo.KEYRING_DELIMITER)[0] + ' (' + keyringId.split(mvelo.KEYRING_DELIMITER)[1] + ')';
  }

  function handleRequests(request, sender, sendResponse) {
    switch (request.event) {
      case 'add-watchlist-item':
        $('#settingsButton').trigger('click');
        $('#watchListButton').trigger('click');
        options.addToWatchList(request.site);
        break;
      case 'reload-options':
        if (request.hash === '#showlog') {
          $('#settingsButton').trigger('click');
          $('#securityLogButton').trigger('click');
        } else {
          options.reloadOptions();
        }
        break;
      case 'import-key':
        $('#keyringButton').trigger('click');
        $('#importKeyButton').trigger('click');
        options.importKey(request.armored, function(result) {
          sendResponse({
            result: result,
            id: request.id
          });
        });
        return true;
      default:
      // TODO analyse message events
      //console.log('unknown event:', request);
    }
  }

  function reloadOptions() {
    document.location.reload();
  }

  function getAllKeyringAttr() {
    return sendMessage({ event: 'get-all-keyring-attr'});
  }

  function getAllKeyUserId() {
    return sendMessage({ event: 'get-all-key-userid'});
  }

  function pgpModel(method, args) {
    return sendMessage({
      event: 'pgpmodel',
      method: method,
      args: args
    });
  }

  function keyring(method, args) {
    return sendMessage({
      event: 'keyring',
      method: method,
      args: args,
      keyringId: options.keyringId
    });
  }

  function copyToClipboard(text) {
    var copyFrom = $('<textarea />');
    $('body').append(copyFrom);
    copyFrom.hide();
    copyFrom.text(text);
    copyFrom.select();
    document.execCommand('copy');
    copyFrom.remove();
  }

  function getL10nMessages(ids, callback) {
    mvelo.l10n.getMessages(ids, callback);
  }

  function registerL10nMessages(ids) {
    ids.forEach(function(id) {
      exports.l10n[id] = true;
    });
  }

  function openTab(url) {
    return sendMessage({event: 'open-tab', url: url});
  }

  function sendMessage(options) {
    return new Promise(function(resolve, reject) {
      mvelo.extension.sendMessage(options, function(data) {
        if (data.error) {
          reject(data.error);
        } else {
          resolve(data.result);
        }
      });
    });
  }

  exports.reloadOptions = reloadOptions;
  exports.getAllKeyringAttr = getAllKeyringAttr;
  exports.getAllKeyUserId = getAllKeyUserId;
  exports.pgpModel = pgpModel;
  exports.keyring = keyring;
  exports.copyToClipboard = copyToClipboard;
  exports.getL10nMessages = getL10nMessages;
  exports.registerL10nMessages = registerL10nMessages;
  exports.keyringId = keyringId;
  exports.openTab = openTab;

  exports.event = event;
  exports.l10n = l10n;

  // Update visibility of setup alert box
  options.event.on('keygrid-reload', function() {
    options.keyring('getPrivateKeys')
      .then(function(result) {
        if (!result.length) {
          $('.keyring_setup_message').addClass('active');
        } else {
          $('.keyring_setup_message').removeClass('active');
        }
      });
  });

  $(document).ready(init);

}(options, jQuery));
<|endoftext|>


<commit_before>Core.Object.extend('Core.FilePostUploader',
/**@lends Core.FilePostUploader#*/
{
	file: undefined,
	destination: undefined,
	service: undefined,
	reader: undefined,
	request: undefined,
	binaryString: false,
	responseText: undefined,
	fileReader: undefined,
	boundary: undefined,

	/**
	*	@constructs
	*	@class
	*	@extends Core.Object
	*/
	constructor: function(config) {
		this.addEvents('progress', 'complete', 'error');
	},

	getFile: function() {
		return this.file;
	},

	setFile: function(file) {
		this.file = file;
	},

	setService: function(service) {
		this.service = service;
	},

	setDestination: function(destination) {
		this.destination = destination;
	},

	/**Send the file*/
	send: function() {
		/**#nocode+ Avoid Jsdoc warnings...*/
		if(this.file.fileApi != undefined) {
			if(navigator.supportFormData) {
				var formData = new FormData();
				if(this.destination == undefined)
					this.destination = this.file.getFileName();
				formData.append("destination", this.destination);
				formData.append("file", this.file.fileApi);

				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open("POST", this.service);
				this.request.send(formData);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;
			}
			else {
				this.fileReader = new FileReader();
				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open("POST", this.service);

				this.boundary = '----';
                var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                for(var i = 0; i < 16; i++)
					this.boundary += characters[Math.floor(Math.random()*characters.length)];
				this.boundary += '----';

				this.request.setRequestHeader("Content-Type", "multipart/form-data, boundary="+this.boundary);
				this.request.setRequestHeader("Content-Length", this.file.fileApi.size);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;

				var readerWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerWrapper.scope = this;
				readerWrapper.callback = this.onFileReaderLoad;
				this.fileReader.onload = readerWrapper;

				var readerErrorWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerErrorWrapper.scope = this;
				readerErrorWrapper.callback = this.onFileReaderError;
				this.fileReader.onerror = readerErrorWrapper;

				this.fileReader.readAsBinaryString(this.file.fileApi);
			}
		}
		else {
			this.file.form.action = this.service;

			var destDrawing = document.createElement('input');
			destDrawing.type = 'hidden';
			destDrawing.setAttribute('name', 'destination');
			destDrawing.setAttribute('value', this.destination);
			this.file.form.insertBefore(destDrawing, this.file.form.firstChild);

			this.connect(this.file.iframe, 'load', this.onIFrameLoad);
			var errorCount = 0;
			var done = false;
			while(!done && (errorCount < 5)) {
				try {
					this.file.form.submit();
					done = true;
				}
				catch(e) {
					errorCount++;
				}
			}
		}
	/**#nocode-*/
	},

	getResponseText: function() {
		return this.responseText;
	},

	/**#@+
	* @private
	*/
	onStateChange: function(event) {
		if(this.request.readyState == 4) {
			if(this.request.status == 200) {
				this.responseText = this.request.responseText;
				this.fireEvent('complete', this);
			}
			else
				this.fireEvent('error', this, this.request.status);
			this.request = undefined;
		}
	},

	onUpdateProgress: function(event) {
		this.fireEvent('progress', this, event.loaded, event.total);
	},

	onFileReaderError: function(event) {
		this.request.abort();
		this.request = undefined;
		this.fireEvent('error', this);
		this.fileReader = undefined;
	},

	onFileReaderLoad: function(event) {
		var body = '--'+this.boundary+'\r\n';
		body += "Content-Disposition: form-data; name='file'; filename='"+this.file.fileApi.name+"'\r\n";
		body += 'Content-Type: '+this.file.fileApi.type+'\r\n\r\n';
		body += event.target.result+'\r\n';
		body += '--'+this.boundary+'--';
		this.request.sendAsBinary(body);

		this.fileReader = undefined;
	},

	onIFrameLoad: function(event) {
		this.responseText = event.target.contentWindow.document.body.innerText;
		document.body.removeChild(this.file.iframe);
		this.fireEvent('complete', this);
	}
	/**#@-*/
});

<commit_msg>add getResponseJSON to Core.FilePostUploader<commit_after>Core.Object.extend('Core.FilePostUploader',
/**@lends Core.FilePostUploader#*/
{
	file: undefined,
	destination: undefined,
	service: undefined,
	reader: undefined,
	request: undefined,
	binaryString: false,
	responseText: undefined,
	fileReader: undefined,
	boundary: undefined,

	/**
	*	@constructs
	*	@class
	*	@extends Core.Object
	*/
	constructor: function(config) {
		this.addEvents('progress', 'complete', 'error');
	},

	getFile: function() {
		return this.file;
	},

	setFile: function(file) {
		this.file = file;
	},

	setService: function(service) {
		this.service = service;
	},

	setDestination: function(destination) {
		this.destination = destination;
	},

	/**Send the file*/
	send: function() {
		/**#nocode+ Avoid Jsdoc warnings...*/
		if(this.file.fileApi != undefined) {
			if(navigator.supportFormData) {
				var formData = new FormData();
				if(this.destination == undefined)
					this.destination = this.file.getFileName();
				formData.append("destination", this.destination);
				formData.append("file", this.file.fileApi);

				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open("POST", this.service);
				this.request.send(formData);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;
			}
			else {
				this.fileReader = new FileReader();
				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open("POST", this.service);

				this.boundary = '----';
                var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                for(var i = 0; i < 16; i++)
					this.boundary += characters[Math.floor(Math.random()*characters.length)];
				this.boundary += '----';

				this.request.setRequestHeader("Content-Type", "multipart/form-data, boundary="+this.boundary);
				this.request.setRequestHeader("Content-Length", this.file.fileApi.size);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;

				var readerWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerWrapper.scope = this;
				readerWrapper.callback = this.onFileReaderLoad;
				this.fileReader.onload = readerWrapper;

				var readerErrorWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerErrorWrapper.scope = this;
				readerErrorWrapper.callback = this.onFileReaderError;
				this.fileReader.onerror = readerErrorWrapper;

				this.fileReader.readAsBinaryString(this.file.fileApi);
			}
		}
		else {
			this.file.form.action = this.service;

			var destDrawing = document.createElement('input');
			destDrawing.type = 'hidden';
			destDrawing.setAttribute('name', 'destination');
			destDrawing.setAttribute('value', this.destination);
			this.file.form.insertBefore(destDrawing, this.file.form.firstChild);

			this.connect(this.file.iframe, 'load', this.onIFrameLoad);
			var errorCount = 0;
			var done = false;
			while(!done && (errorCount < 5)) {
				try {
					this.file.form.submit();
					done = true;
				}
				catch(e) {
					errorCount++;
				}
			}
		}
	/**#nocode-*/
	},

	getResponseText: function() {
		return this.responseText;
	},

	getResponseJSON: function() {
		var res;
		try {
			res = JSON.parse(this.getResponseText());
		}
		catch(err) {
			res = undefined;
		}
		return res;
	},

	/**#@+
	* @private
	*/
	onStateChange: function(event) {
		if(this.request.readyState == 4) {
			if(this.request.status == 200) {
				this.responseText = this.request.responseText;
				this.fireEvent('complete', this);
			}
			else
				this.fireEvent('error', this, this.request.status);
			this.request = undefined;
		}
	},

	onUpdateProgress: function(event) {
		this.fireEvent('progress', this, event.loaded, event.total);
	},

	onFileReaderError: function(event) {
		this.request.abort();
		this.request = undefined;
		this.fireEvent('error', this);
		this.fileReader = undefined;
	},

	onFileReaderLoad: function(event) {
		var body = '--'+this.boundary+'\r\n';
		body += "Content-Disposition: form-data; name='file'; filename='"+this.file.fileApi.name+"'\r\n";
		body += 'Content-Type: '+this.file.fileApi.type+'\r\n\r\n';
		body += event.target.result+'\r\n';
		body += '--'+this.boundary+'--';
		this.request.sendAsBinary(body);

		this.fileReader = undefined;
	},

	onIFrameLoad: function(event) {
		this.responseText = event.target.contentWindow.document.body.innerText;
		document.body.removeChild(this.file.iframe);
		this.fireEvent('complete', this);
	}
	/**#@-*/
});

<|endoftext|>


<commit_before>(function (angular) {
    'use strict';

    angular.module('Notepads.controllers', [])

    .controller('MainCtrl', [
        '$scope', 'flash', '$timeout', '$window',
        function ($scope, flash, $timeout, $window) {

            $scope.flash = flash;

            //TODO: doesn't work, fix it with directive or extra var for show/hide
            if ($scope.flash.get().msg) {
                $timeout(function () {
                    $scope.flash.clear();
                }, 1E3);
            }

            $scope.cancel = function () {
                $window.history.back();
            };
        }
    ])

    .controller('IndexCtrl', [
        function () {
            //...
        }
    ])

    .controller('DashboardCtrl', [
        '$scope', 'Api', '$location',
        function ($scope, Api, $location) {
            function list() {
                Api.notepads.list()
                    .success(function (categories) {
                        $scope.categories = categories;
                    });
            }

            $scope.editNotepad = function (id) {
                $location.path('/notepads/' + id + '/edit');
            };

            $scope.deleteNotepad = function (id) {
                $location.path('/notepads/' + id + '/delete');
            };

            list();
        }
    ])

    .controller('NotepadCtrl', [
        '$scope', '$location', 'Api', '$routeParams', 'flash',
        function ($scope, $location, Api, $routeParams, flash) {

            var notepadId = $routeParams.id,
                // /notepads/add/catid/:cid
                catId = $routeParams.cid;

            if (!notepadId) {
                $scope.notepad = {category: '', title: '', text: ''};
                $scope.pageTitle = 'Add Notepad';
                $scope.buttonText = 'Add';
                $scope.catId = catId;
            } else {
                Api.notepads.getById(notepadId)
                    .success(function (notepad) {
                        $scope.notepad = notepad;
                    });
                $scope.pageTitle = 'Edit Notepad';
                $scope.buttonText = 'Update';
            }

            Api.categories.list()
                .success(function (categories) {
                    $scope.categories = categories;
                });

            $scope.addEditNotepad = function () {
                if (!checkNotepadValues()) {
                    $scope.alert = 'Please provide category, title and text!';
                    $scope.alertType = 'danger';
                } else {
                    $scope.alert = '';
                    if (!notepadId) {
                        if (!$scope.notepad.category && catId) {
                            $scope.notepad.category = catId;
                        }
                        Api.notepads.add($scope.notepad)
                            .success(function () {
                                flash.set({
                                    msg: 'Notepad Added Successfully!',
                                    type: 'success'
                                });
                                $location.path('/');
                            });
                    } else {
                        Api.notepads.update($scope.notepad)
                            .success(function () {
                                flash.set({
                                    msg: 'Notepad Updated Successfully!',
                                    type: 'success'
                                });
                                $location.path('/');
                            });
                    }
                }
            };
            function checkNotepadValues() {
                return ($scope.notepad.category !== '' || catId) &&
                    $scope.notepad.title !== '' &&
                    $scope.notepad.text !== '';
            }
        }
    ])

    .controller('NotepadDelCtrl', [
        '$scope', '$routeParams', 'Api', 'flash', '$location',
        function ($scope, $routeParams, Api, flash, $location) {

            var notepadId = $routeParams.id;

            //TODO: check if id is given/valid

            Api.notepads.getById(notepadId)
                .success(function (notepad) {
                    $scope.title = notepad.title;
                });

            $scope.remove = function () {
                Api.notepads.remove(notepadId)
                    .success(function () {
                        flash.set({
                            msg: 'Notepad Deleted Successfully!',
                            type: 'success'
                        });
                        $location.path('/');
                    });
            };

        }
    ])

    .controller('CategoriesCtrl', [
        '$scope', 'Api', '$location',
        function ($scope, Api, $location) {
            Api.categories.list()
                .success(function (categories) {
                    $scope.categories = categories;
                });

            $scope.addCategory = function () {
                $location.path('/categories/add');
            };
        }
    ])

    .controller('CategoryDelCtrl', [
        '$scope', '$routeParams', 'Api', 'flash', '$location',
        function ($scope, $routeParams, Api, flash, $location) {

            var catId = $routeParams.id;

            //TODO: check if id is given/valid

            Api.categories.getById(catId)
                .success(function (cat) {
                    $scope.name = cat.name;
                });

            $scope.remove = function () {
                Api.categories.remove(catId)
                    .success(function () {
                        flash.set({
                            msg: 'Category Deleted Successfully!',
                            type: 'success'
                        });
                        $location.path('/');
                    });
            };

        }
    ])

    .controller('CategoryCtrl', [
        '$scope', 'Api', '$location', '$routeParams',
        function ($scope, Api, $location, $routeParams) {

            var catId = $routeParams.id;

            if (!catId) {
                $scope.category = {name: ''};
                $scope.pageTitle = 'Add Category';
                $scope.buttonText = 'Add';
            } else {
                Api.categories.getById(catId)
                    .success(function (category) {
                        $scope.category = category;
                    });
                $scope.pageTitle = 'Edit Category';
                $scope.buttonText = 'Update';
            }

            function checkCatValues() {
                return $scope.category.name !== '';
            }

            $scope.addEditCategory = function () {
                if (!checkCatValues()) {
                    $scope.alert = 'Please provide a name!';
                } else {
                    $scope.alert = '';
                    if (catId) {
                        Api.categories.update($scope.category)
                            .success(function () {
                                $location.path('/categories');
                                flash.set({
                                    msg: '',
                                    type: 'success'
                                });
                            });
                    } else {
                        Api.categories.add($scope.category)
                            .success(function () {
                                $location.path('/categories');
                                $scope.$broadcast('categoryupdated');
                            });
                    }
                }
            };

        }
    ]);

})(angular);
<commit_msg>added a missing injection of the custom flash service<commit_after>(function (angular) {
    'use strict';

    angular.module('Notepads.controllers', [])

    .controller('MainCtrl', [
        '$scope', 'flash', '$timeout', '$window',
        function ($scope, flash, $timeout, $window) {

            $scope.flash = flash;

            //TODO: doesn't work, fix it with directive or extra var for show/hide
            if ($scope.flash.get().msg) {
                $timeout(function () {
                    $scope.flash.clear();
                }, 1E3);
            }

            $scope.cancel = function () {
                $window.history.back();
            };
        }
    ])

    .controller('IndexCtrl', [
        function () {
            //...
        }
    ])

    .controller('DashboardCtrl', [
        '$scope', 'Api', '$location',
        function ($scope, Api, $location) {
            function list() {
                Api.notepads.list()
                    .success(function (categories) {
                        $scope.categories = categories;
                    });
            }

            $scope.editNotepad = function (id) {
                $location.path('/notepads/' + id + '/edit');
            };

            $scope.deleteNotepad = function (id) {
                $location.path('/notepads/' + id + '/delete');
            };

            list();
        }
    ])

    .controller('NotepadCtrl', [
        '$scope', '$location', 'Api', '$routeParams', 'flash',
        function ($scope, $location, Api, $routeParams, flash) {

            var notepadId = $routeParams.id,
                // /notepads/add/catid/:cid
                catId = $routeParams.cid;

            if (!notepadId) {
                $scope.notepad = {category: '', title: '', text: ''};
                $scope.pageTitle = 'Add Notepad';
                $scope.buttonText = 'Add';
                $scope.catId = catId;
            } else {
                Api.notepads.getById(notepadId)
                    .success(function (notepad) {
                        $scope.notepad = notepad;
                    });
                $scope.pageTitle = 'Edit Notepad';
                $scope.buttonText = 'Update';
            }

            Api.categories.list()
                .success(function (categories) {
                    $scope.categories = categories;
                });

            $scope.addEditNotepad = function () {
                if (!checkNotepadValues()) {
                    $scope.alert = 'Please provide category, title and text!';
                    $scope.alertType = 'danger';
                } else {
                    $scope.alert = '';
                    if (!notepadId) {
                        if (!$scope.notepad.category && catId) {
                            $scope.notepad.category = catId;
                        }
                        Api.notepads.add($scope.notepad)
                            .success(function () {
                                flash.set({
                                    msg: 'Notepad Added Successfully!',
                                    type: 'success'
                                });
                                $location.path('/');
                            });
                    } else {
                        Api.notepads.update($scope.notepad)
                            .success(function () {
                                flash.set({
                                    msg: 'Notepad Updated Successfully!',
                                    type: 'success'
                                });
                                $location.path('/');
                            });
                    }
                }
            };
            function checkNotepadValues() {
                return ($scope.notepad.category !== '' || catId) &&
                    $scope.notepad.title !== '' &&
                    $scope.notepad.text !== '';
            }
        }
    ])

    .controller('NotepadDelCtrl', [
        '$scope', '$routeParams', 'Api', 'flash', '$location',
        function ($scope, $routeParams, Api, flash, $location) {

            var notepadId = $routeParams.id;

            //TODO: check if id is given/valid

            Api.notepads.getById(notepadId)
                .success(function (notepad) {
                    $scope.title = notepad.title;
                });

            $scope.remove = function () {
                Api.notepads.remove(notepadId)
                    .success(function () {
                        flash.set({
                            msg: 'Notepad Deleted Successfully!',
                            type: 'success'
                        });
                        $location.path('/');
                    });
            };

        }
    ])

    .controller('CategoriesCtrl', [
        '$scope', 'Api', '$location',
        function ($scope, Api, $location) {
            Api.categories.list()
                .success(function (categories) {
                    $scope.categories = categories;
                });

            $scope.addCategory = function () {
                $location.path('/categories/add');
            };
        }
    ])

    .controller('CategoryDelCtrl', [
        '$scope', '$routeParams', 'Api', 'flash', '$location',
        function ($scope, $routeParams, Api, flash, $location) {

            var catId = $routeParams.id;

            //TODO: check if id is given/valid

            Api.categories.getById(catId)
                .success(function (cat) {
                    $scope.name = cat.name;
                });

            $scope.remove = function () {
                Api.categories.remove(catId)
                    .success(function () {
                        flash.set({
                            msg: 'Category Deleted Successfully!',
                            type: 'success'
                        });
                        $location.path('/');
                    });
            };

        }
    ])

    .controller('CategoryCtrl', [
        '$scope', 'Api', '$location', '$routeParams', 'flash',
        function ($scope, Api, $location, $routeParams, flash) {

            var catId = $routeParams.id;

            if (!catId) {
                $scope.category = {name: ''};
                $scope.pageTitle = 'Add Category';
                $scope.buttonText = 'Add';
            } else {
                Api.categories.getById(catId)
                    .success(function (category) {
                        $scope.category = category;
                    });
                $scope.pageTitle = 'Edit Category';
                $scope.buttonText = 'Update';
            }

            function checkCatValues() {
                return $scope.category.name !== '';
            }

            $scope.addEditCategory = function () {
                if (!checkCatValues()) {
                    $scope.alert = 'Please provide a name!';
                } else {
                    $scope.alert = '';
                    if (catId) {
                        Api.categories.update($scope.category)
                            .success(function () {
                                $location.path('/categories');
                                flash.set({
                                    msg: '',
                                    type: 'success'
                                });
                            });
                    } else {
                        Api.categories.add($scope.category)
                            .success(function () {
                                $location.path('/categories');
                                $scope.$broadcast('categoryupdated');
                            });
                    }
                }
            };

        }
    ]);

})(angular);
<|endoftext|>


<commit_before>// construct query string
var params = d3.select("h1#api_key");
if (!params.empty()) {
    var api_key = params.attr('data-api_key');
    var key = params.attr('data-key');
    var query = encodeURI("/api/v5/api_requests?api_key=" + api_key);
    if (key != "") query += "&key=" + key;
};

// load the data from the ALM API
if (query) {
  d3.json(query, function(error, json) {
    if (error) return console.warn(error);
    var data = json["data"];
    crossfilterViz(data);
  });
}

// crossfilter visualization
function crossfilterViz(data) {

  if (!data || data.length == 0) {
    d3.select("#description").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("No API requests found");
    d3.select("div#charts").remove();
    d3.select("div#lists").remove();
    return;
  }

  var today = new Date();

  // A nest operator, for grouping the request list.
  var nestByDate = d3.nest()
    .key(function(d) { return d3.time.day(d.date); });

  // A little coercion, since the JSON is untyped.
  data.forEach(function(d, i) {
    d.index = i;
    d.date = parseDate(d.date);
  });

  console.log(data[1]);

  // Create the crossfilter for the relevant dimensions and groups.
  var request = crossfilter(data),
      all = request.groupAll(),
      hour = request.dimension(function(d) { return d.date.getHours() + d.date.getMinutes() / 60; }),
      hours = hour.group(Math.floor),
      db_duration = request.dimension(function(d) { return Math.max(-60, Math.min(149, d.db_duration)); }),
      db_durations = db_duration.group(function(d) { return Math.floor(d / 10) * 10; }),
      view_duration = request.dimension(function(d) { return Math.min(1999, d.view_duration); }),
      view_durations = view_duration.group(function(d) { return Math.floor(d / 50) * 50; });

  var charts = [

      barChart()
        .dimension(hour)
        .group(hours)
        .x(d3.scale.linear()
        .domain([0, 24])
        .rangeRound([0, 10 * 30])),

      barChart()
        .dimension(db_duration)
        .group(db_durations)
        .x(d3.scale.linear()
        .domain([0, 500])
        .rangeRound([0, 10 * 30])),

      barChart()
        .dimension(view_duration)
        .group(view_durations)
        .x(d3.scale.linear()
        .domain([0, 2000])
        .rangeRound([0, 10 * 30]))
  ];

  // Given our array of charts, which we assume are in the same order as the
  // .req-chart elements in the DOM, bind the charts to the DOM and render them.
  // We also listen to the chart's brush events to update the display.
  var chart = d3.selectAll(".req-chart")
      .data(charts)
      .each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); });

  // Render the initial lists.
  var list = d3.selectAll(".list")
      .data([requestList]);

  // Render the total.
  d3.selectAll("#total")
      .text(formatNumber(request.size()));

  renderAll();

  // Renders the specified chart or list.
  function render(method) {
    d3.select(this).call(method);
  }

  // Whenever the brush moves, re-rendering everything.
  function renderAll() {
    chart.each(render);
    list.each(render);
    d3.select("#active").text(formatNumber(all.value()));
  }

  // Like d3.time.format, but faster.
  function parseDate(d) {
    return new Date(2013,
      d.substring(0, 2) - 1,
      d.substring(2, 4),
      d.substring(4, 6),
      d.substring(6, 8));
  }

  window.filter = function(filters) {
    filters.forEach(function(d, i) { charts[i].filter(d); });
    renderAll();
  };

  window.reset = function(i) {
    charts[i].filter(null);
    renderAll();
  };

  function requestList(div) {
  var requestsByDate = nestByDate.entries(date.top(40));

  div.each(function() {
    var date = d3.select(this).selectAll(".date")
      .data(requestsByDate, function(d) { return d.key; });

    date.enter().append("div")
      .attr("class", "date")
      .append("div")
      .attr("class", "day")
      .text(function(d) { return formatDate(d.values[0].date); });

    date.exit().remove();

    var request = date.order().selectAll(".request")
      .data(function(d) { return d.values; }, function(d) { return d.index; });

    var requestEnter = request.enter().append("div")
      .attr("class", "request");

    requestEnter.append("div")
      .attr("class", "time")
      .text(function(d) { return formatTime(d.date); });

    requestEnter.append("div")
      .attr("class", "duration")
      .text(function(d) { return formatFixed(d.db_duration) + " ms"; });

    requestEnter.append("div")
      .attr("class", "duration")
      .classed("fast", function(d) { return d.view_duration < 100; })
      .classed("slow", function(d) { return d.view_duration >= 1000; })
      .text(function(d) { return formatFixed(d.view_duration) + " ms"; });

    requestEnter.append("div")
      .attr("class", "source")
      .append("a")
      .attr("href", function(d) { return "/admin/users?query=" + d.api_key; })
      .text(function(d) { return d.api_key; });

    requestEnter.append("div")
      .attr("class", "info")
      .text(function(d) { return d.info; });

    requestEnter.append("div")
      .attr("class", "source")
      .text(function(d) { return d.source; });

    requestEnter.append("div")
      .attr("class", "ids")
      .text(function(d) { return d.ids; });

    request.exit().remove();

    request.order();
    });
  }

  function barChart() {
    if (!barChart.id) barChart.id = 0;

    var margin = {top: 10, right: 20, bottom: 20, left: 10},
        x,
        y = d3.scale.linear().range([100, 0]),
        id = barChart.id++,
        axis = d3.svg.axis().orient("bottom"),
        brush = d3.svg.brush(),
        brushDirty,
        dimension,
        group,
        round;

    function chart(div) {
      var width = x.range()[1],
          height = y.range()[0];

      y.domain([0, group.top(1)[0].value]);

      div.each(function() {
      var div = d3.select(this),
          g = div.select("g");

      // Create the skeletal chart.
      if (g.empty()) {
        div.select(".req-chart h5").append("a")
            .attr("href", "javascript:reset(" + id + ")")
            .attr("class", "reset")
            .text("reset")
            .style("display", "none");

        g = div.append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        g.append("clipPath")
            .attr("id", "clip-" + id)
            .append("rect")
            .attr("width", width)
            .attr("height", height);

        g.selectAll(".bar")
            .data(["background", "foreground"])
            .enter().append("path")
            .attr("class", function(d) { return d + " bar"; })
            .datum(group.all());

        g.selectAll(".foreground.bar")
            .attr("clip-path", "url(#clip-" + id + ")");

        g.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(0," + height + ")")
            .call(axis);

        // Initialize the brush component with pretty resize handles.
        var gBrush = g.append("g").attr("class", "brush").call(brush);
        gBrush.selectAll("rect").attr("height", height);
        gBrush.selectAll(".resize").append("path").attr("d", resizePath);
      }

      // Only redraw the brush if set externally.
      if (brushDirty) {
        brushDirty = false;
        g.selectAll(".brush").call(brush);
        div.select(".req-chart h5 a").style("display", brush.empty() ? "none" : null);
        if (brush.empty()) {
          g.selectAll("#clip-" + id + " rect")
            .attr("x", 0)
            .attr("width", width);
        } else {
          var extent = brush.extent();
          g.selectAll("#clip-" + id + " rect")
            .attr("x", x(extent[0]))
            .attr("width", x(extent[1]) - x(extent[0]));
        }
      }

      g.selectAll(".bar").attr("d", barPath);
    });

    function barPath(groups) {
        var path = [],
            i = -1,
            n = groups.length,
            d;
        while (++i < n) {
            d = groups[i];
            path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
        }
        return path.join("");
    }

    function resizePath(d) {
      var e = +(d == "e"),
          x = e ? 1 : -1,
          y = height / 3;
      return "M" + (.5 * x) + "," + y
        + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
        + "V" + (2 * y - 6)
        + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
        + "Z"
        + "M" + (2.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8)
        + "M" + (4.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8);
      }
    }

    brush.on("brushstart.req-chart", function() {
      var div = d3.select(this.parentNode.parentNode.parentNode);
      div.select(".req-chart h5 a").style("display", null);
    });

    brush.on("brush.req-chart", function() {
      var g = d3.select(this.parentNode),
        extent = brush.extent();
      if (round) g.select(".brush")
        .call(brush.extent(extent = extent.map(round)))
        .selectAll(".resize")
        .style("display", null);
      g.select("#clip-" + id + " rect")
        .attr("x", x(extent[0]))
        .attr("width", x(extent[1]) - x(extent[0]));
      dimension.filterRange(extent);
    });

    brush.on("brushend.req-chart", function() {
        if (brush.empty()) {
            var div = d3.select(this.parentNode.parentNode.parentNode);
            div.select(".req-chart h5 a").style("display", "none");
            div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%");
            dimension.filterAll();
        }
    });

    chart.margin = function(_) {
      if (!arguments.length) return margin;
      margin = _;
      return chart;
    };

    chart.x = function(_) {
      if (!arguments.length) return x;
      x = _;
      axis.scale(x);
      brush.x(x);
      return chart;
    };

    chart.y = function(_) {
      if (!arguments.length) return y;
      y = _;
      return chart;
    };

    chart.dimension = function(_) {
      if (!arguments.length) return dimension;
      dimension = _;
      return chart;
    };

    chart.filter = function(_) {
      if (_) {
        brush.extent(_);
        dimension.filterRange(_);
      } else {
        brush.clear();
        dimension.filterAll();
      }
      brushDirty = true;
      return chart;
    };

    chart.group = function(_) {
      if (!arguments.length) return group;
      group = _;
      return chart;
    };

    chart.round = function(_) {
      if (!arguments.length) return round;
      round = _;
      return chart;
    };

    return d3.rebind(chart, brush, "on");
  }
};

// d3 helper functions
var formatNumber = d3.format(",d"),
    formatFixed = d3.format(",.1f"),
    formatDate = d3.time.format("%B %d, %Y"),
    formatTime = d3.time.format("%I:%M %p");
<commit_msg>ALM-640 fix date parsing function<commit_after>// construct query string
var params = d3.select("h1#api_key");
if (!params.empty()) {
    var api_key = params.attr('data-api_key');
    var key = params.attr('data-key');
    var query = encodeURI("/api/v5/api_requests?api_key=" + api_key);
    if (key != "") query += "&key=" + key;
};

// load the data from the ALM API
if (query) {
  d3.json(query, function(error, json) {
    if (error) return console.warn(error);
    var data = json["data"];
    crossfilterViz(data);
  });
}

// crossfilter visualization
function crossfilterViz(data) {

  if (!data || data.length == 0) {
    d3.select("#description").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("No API requests found");
    d3.select("div#charts").remove();
    d3.select("div#lists").remove();
    return;
  }

  var today = new Date();

  // A nest operator, for grouping the request list.
  var nestByDate = d3.nest()
    .key(function(d) { return d3.time.day(d.date); });

  // A little coercion, since the JSON is untyped.
  data.forEach(function(d, i) {
    d.index = i;
    d.date = parseDate(d.date);
  });

  console.log(data[1]);

  // Create the crossfilter for the relevant dimensions and groups.
  var request = crossfilter(data),
      all = request.groupAll(),
      hour = request.dimension(function(d) { return d.date.getHours() + d.date.getMinutes() / 60; }),
      hours = hour.group(Math.floor),
      db_duration = request.dimension(function(d) { return Math.max(-60, Math.min(149, d.db_duration)); }),
      db_durations = db_duration.group(function(d) { return Math.floor(d / 10) * 10; }),
      view_duration = request.dimension(function(d) { return Math.min(1999, d.view_duration); }),
      view_durations = view_duration.group(function(d) { return Math.floor(d / 50) * 50; });

  var charts = [

      barChart()
        .dimension(hour)
        .group(hours)
        .x(d3.scale.linear()
        .domain([0, 24])
        .rangeRound([0, 10 * 30])),

      barChart()
        .dimension(db_duration)
        .group(db_durations)
        .x(d3.scale.linear()
        .domain([0, 500])
        .rangeRound([0, 10 * 30])),

      barChart()
        .dimension(view_duration)
        .group(view_durations)
        .x(d3.scale.linear()
        .domain([0, 2000])
        .rangeRound([0, 10 * 30]))
  ];

  // Given our array of charts, which we assume are in the same order as the
  // .req-chart elements in the DOM, bind the charts to the DOM and render them.
  // We also listen to the chart's brush events to update the display.
  var chart = d3.selectAll(".req-chart")
      .data(charts)
      .each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); });

  // Render the initial lists.
  var list = d3.selectAll(".list")
      .data([requestList]);

  // Render the total.
  d3.selectAll("#total")
      .text(formatNumber(request.size()));

  renderAll();

  // Renders the specified chart or list.
  function render(method) {
    d3.select(this).call(method);
  }

  // Whenever the brush moves, re-rendering everything.
  function renderAll() {
    chart.each(render);
    list.each(render);
    d3.select("#active").text(formatNumber(all.value()));
  }

  // Like d3.time.format, but faster.
  function parseDate(d) {
    return new Date(
      d.substring(0, 3),
      d.substring(5, 6) - 1,
      d.substring(8, 9),
      d.substring(11, 12),
      d.substring(14, 15));
  }

  window.filter = function(filters) {
    filters.forEach(function(d, i) { charts[i].filter(d); });
    renderAll();
  };

  window.reset = function(i) {
    charts[i].filter(null);
    renderAll();
  };

  function requestList(div) {
  var requestsByDate = nestByDate.entries(date.top(40));

  div.each(function() {
    var date = d3.select(this).selectAll(".date")
      .data(requestsByDate, function(d) { return d.key; });

    date.enter().append("div")
      .attr("class", "date")
      .append("div")
      .attr("class", "day")
      .text(function(d) { return formatDate(d.values[0].date); });

    date.exit().remove();

    var request = date.order().selectAll(".request")
      .data(function(d) { return d.values; }, function(d) { return d.index; });

    var requestEnter = request.enter().append("div")
      .attr("class", "request");

    requestEnter.append("div")
      .attr("class", "time")
      .text(function(d) { return formatTime(d.date); });

    requestEnter.append("div")
      .attr("class", "duration")
      .text(function(d) { return formatFixed(d.db_duration) + " ms"; });

    requestEnter.append("div")
      .attr("class", "duration")
      .classed("fast", function(d) { return d.view_duration < 100; })
      .classed("slow", function(d) { return d.view_duration >= 1000; })
      .text(function(d) { return formatFixed(d.view_duration) + " ms"; });

    requestEnter.append("div")
      .attr("class", "source")
      .append("a")
      .attr("href", function(d) { return "/admin/users?query=" + d.api_key; })
      .text(function(d) { return d.api_key; });

    requestEnter.append("div")
      .attr("class", "info")
      .text(function(d) { return d.info; });

    requestEnter.append("div")
      .attr("class", "source")
      .text(function(d) { return d.source; });

    requestEnter.append("div")
      .attr("class", "ids")
      .text(function(d) { return d.ids; });

    request.exit().remove();

    request.order();
    });
  }

  function barChart() {
    if (!barChart.id) barChart.id = 0;

    var margin = {top: 10, right: 20, bottom: 20, left: 10},
        x,
        y = d3.scale.linear().range([100, 0]),
        id = barChart.id++,
        axis = d3.svg.axis().orient("bottom"),
        brush = d3.svg.brush(),
        brushDirty,
        dimension,
        group,
        round;

    function chart(div) {
      var width = x.range()[1],
          height = y.range()[0];

      y.domain([0, group.top(1)[0].value]);

      div.each(function() {
      var div = d3.select(this),
          g = div.select("g");

      // Create the skeletal chart.
      if (g.empty()) {
        div.select(".req-chart h5").append("a")
            .attr("href", "javascript:reset(" + id + ")")
            .attr("class", "reset")
            .text("reset")
            .style("display", "none");

        g = div.append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        g.append("clipPath")
            .attr("id", "clip-" + id)
            .append("rect")
            .attr("width", width)
            .attr("height", height);

        g.selectAll(".bar")
            .data(["background", "foreground"])
            .enter().append("path")
            .attr("class", function(d) { return d + " bar"; })
            .datum(group.all());

        g.selectAll(".foreground.bar")
            .attr("clip-path", "url(#clip-" + id + ")");

        g.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(0," + height + ")")
            .call(axis);

        // Initialize the brush component with pretty resize handles.
        var gBrush = g.append("g").attr("class", "brush").call(brush);
        gBrush.selectAll("rect").attr("height", height);
        gBrush.selectAll(".resize").append("path").attr("d", resizePath);
      }

      // Only redraw the brush if set externally.
      if (brushDirty) {
        brushDirty = false;
        g.selectAll(".brush").call(brush);
        div.select(".req-chart h5 a").style("display", brush.empty() ? "none" : null);
        if (brush.empty()) {
          g.selectAll("#clip-" + id + " rect")
            .attr("x", 0)
            .attr("width", width);
        } else {
          var extent = brush.extent();
          g.selectAll("#clip-" + id + " rect")
            .attr("x", x(extent[0]))
            .attr("width", x(extent[1]) - x(extent[0]));
        }
      }

      g.selectAll(".bar").attr("d", barPath);
    });

    function barPath(groups) {
        var path = [],
            i = -1,
            n = groups.length,
            d;
        while (++i < n) {
            d = groups[i];
            path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
        }
        return path.join("");
    }

    function resizePath(d) {
      var e = +(d == "e"),
          x = e ? 1 : -1,
          y = height / 3;
      return "M" + (.5 * x) + "," + y
        + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
        + "V" + (2 * y - 6)
        + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
        + "Z"
        + "M" + (2.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8)
        + "M" + (4.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8);
      }
    }

    brush.on("brushstart.req-chart", function() {
      var div = d3.select(this.parentNode.parentNode.parentNode);
      div.select(".req-chart h5 a").style("display", null);
    });

    brush.on("brush.req-chart", function() {
      var g = d3.select(this.parentNode),
        extent = brush.extent();
      if (round) g.select(".brush")
        .call(brush.extent(extent = extent.map(round)))
        .selectAll(".resize")
        .style("display", null);
      g.select("#clip-" + id + " rect")
        .attr("x", x(extent[0]))
        .attr("width", x(extent[1]) - x(extent[0]));
      dimension.filterRange(extent);
    });

    brush.on("brushend.req-chart", function() {
        if (brush.empty()) {
            var div = d3.select(this.parentNode.parentNode.parentNode);
            div.select(".req-chart h5 a").style("display", "none");
            div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%");
            dimension.filterAll();
        }
    });

    chart.margin = function(_) {
      if (!arguments.length) return margin;
      margin = _;
      return chart;
    };

    chart.x = function(_) {
      if (!arguments.length) return x;
      x = _;
      axis.scale(x);
      brush.x(x);
      return chart;
    };

    chart.y = function(_) {
      if (!arguments.length) return y;
      y = _;
      return chart;
    };

    chart.dimension = function(_) {
      if (!arguments.length) return dimension;
      dimension = _;
      return chart;
    };

    chart.filter = function(_) {
      if (_) {
        brush.extent(_);
        dimension.filterRange(_);
      } else {
        brush.clear();
        dimension.filterAll();
      }
      brushDirty = true;
      return chart;
    };

    chart.group = function(_) {
      if (!arguments.length) return group;
      group = _;
      return chart;
    };

    chart.round = function(_) {
      if (!arguments.length) return round;
      round = _;
      return chart;
    };

    return d3.rebind(chart, brush, "on");
  }
};

// d3 helper functions
var formatNumber = d3.format(",d"),
    formatFixed = d3.format(",.1f"),
    formatDate = d3.time.format("%B %d, %Y"),
    formatTime = d3.time.format("%I:%M %p");
<|endoftext|>


<commit_before>/**
Author: Alex Ball
screeps-scripts

scripts for the JavaScript-based MMO Screeps.
*/

require('tower').runTowerLogic();

let spawnFunctions = require('spawn');

let roleHarvester = require('role.harvester');
let roleUpgrader = require('role.upgrader');
let roleBuilder = require('role.builder');

/**Functions that are used across different modules.*/
const FUNCTIONS = require('functions');

//Begin main loop.
module.exports.loop = function() {
  FUNCTIONS.respawn();
  FUNCTIONS.clearDeadCreepMemory();

  let spawn = Game.spawns.Spawn1;

  FUNCTIONS.checkForLevelUp(spawn.room);

  let harvesters = {};
  let upgraders = {};
  let builders = {};

  for (let name in Game.creeps) {
    let creep = Game.creeps[name];
    if (creep.memory.role == 'harvester') {
      harvesters[name] = creep.id;
      roleHarvester.run(creep);
    }
    if (creep.memory.role == 'upgrader') {
      upgraders[name] = creep.id;
      roleUpgrader.run(creep);
    }
    if (creep.memory.role == 'builder') {
      builders[name] = creep.id;
      roleBuilder.run(creep);
    }
  }

  if (Object.keys(harvesters).length < 2) {
    spawnFunctions.createCreepWithRole(spawn, 'harvester');
  } else if (Object.keys(upgraders).length < 2) {
    spawnFunctions.createCreepWithRole(spawn, 'upgrader');
  } else if (Object.keys(builders).length < 2) {
    spawnFunctions.createCreepWithRole(spawn, 'builder');
  }

  spawnFunctions.displayCreateCreepVisual(spawn);
};
<commit_msg>Added logic for actions on a per-room basis. There is a now a for loop that runs through Game.rooms.<commit_after>/**
Author: Alex Ball
screeps-scripts

scripts for the JavaScript-based MMO Screeps.
*/

require('tower').runTowerLogic();

let spawnFunctions = require('spawn');

let roleHarvester = require('role.harvester');
let roleUpgrader = require('role.upgrader');
let roleBuilder = require('role.builder');

/**Functions that are used across different modules.*/
const FUNCTIONS = require('functions');

//Begin main loop.
module.exports.loop = function() {
  FUNCTIONS.respawn();
  FUNCTIONS.clearDeadCreepMemory();

  let harvesters = {};
  let upgraders = {};
  let builders = {};

  for (let name in Game.creeps) {
    let creep = Game.creeps[name];
    if (creep.memory.role == 'harvester') {
      harvesters[name] = creep.id;
      roleHarvester.run(creep);
    }
    if (creep.memory.role == 'upgrader') {
      upgraders[name] = creep.id;
      roleUpgrader.run(creep);
    }
    if (creep.memory.role == 'builder') {
      builders[name] = creep.id;
      roleBuilder.run(creep);
    }
  }

  let spawn = Game.spawns.Spawn1;
  for (let roomName in Game.rooms) {
    let room = Game.rooms[roomName];

    FUNCTIONS.checkForLevelUp(room);

    let spawns = room.find(FIND_MY_STRUCTURES, {
      filter: {
        structureType: STRUCTURE_SPAWN
      }
    });

    let spawn = spawns[0];

    //check for sources that are not known in this room.

    //make any unknown sources known.

    //check if a source is MISSING a miner OR its assigned miner will
    //die within the time it takes a new miner to replace it.

    //if so, then build a new miner which will be assigned to
    //that source.

    if (Object.keys(harvesters).length < 2) {
      spawnFunctions.createCreepWithRole(spawn, 'harvester');
    } else if (Object.keys(upgraders).length < 2) {
      spawnFunctions.createCreepWithRole(spawn, 'upgrader');
    } else if (Object.keys(builders).length < 2) {
      spawnFunctions.createCreepWithRole(spawn, 'builder');
    }

    spawnFunctions.displayCreateCreepVisual(spawn);
  }
};
<|endoftext|>


<commit_before>define(["./list"], function(List) {

    var Tab = {

    };

    /*
        config = {

            source: {

            },
            bind: [
                {

                }
            ]
        }
    */

    return function(config) {

        var tab = List(config);

        return tab;
    };
});<commit_msg>require repeater<commit_after>define(["adioo/bind/repeater"], function(Repeater) {

    var Tab = {

    };

    /*
        config = {

            source: {

            },
            bind: [
                {

                }
            ]
        }
    */

    return function(config) {

        var tab = Repeater(config);

        return tab;
    };
});<|endoftext|>


<commit_before>import React from 'react';
import { mount } from 'enzyme';
import { sleep } from '../../../tests/utils';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import BackTop from '..';

describe('BackTop', () => {
  mountTest(BackTop);
  rtlTest(BackTop);

  it('should scroll to top after click it', async () => {
    const wrapper = mount(<BackTop visibilityHeight={-1} />);
    const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
      window.scrollY = y;
      window.pageYOffset = y;
      document.documentElement.scrollTop = y;
    });
    window.scrollTo(0, 400);
    expect(document.documentElement.scrollTop).toBe(400);
    wrapper.find('.ant-back-top').simulate('click');
    await sleep(500);
    expect(document.documentElement.scrollTop).toBe(0);
    scrollToSpy.mockRestore();
  });

  it('support onClick', async () => {
    const onClick = jest.fn();
    const wrapper = mount(<BackTop onClick={onClick} visibilityHeight={-1} />);
    const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
      window.scrollY = y;
      window.pageYOffset = y;
    });
    document.dispatchEvent(new Event('scroll'));
    window.scrollTo(0, 400);
    wrapper.find('.ant-back-top').simulate('click');
    expect(onClick).toHaveBeenCalled();
    scrollToSpy.mockRestore();
  });

  it('invalid target', async () => {
    const onClick = jest.fn();
    const wrapper = mount(
      <BackTop onClick={onClick} visible target={() => ({ documentElement: {} })} />,
    );
    wrapper.find('.ant-back-top').simulate('click');
    expect(onClick).toHaveBeenCalled();
  });
});
<commit_msg>test: move test cases to testing lib (#35909)<commit_after>import React from 'react';
import { sleep, render, fireEvent } from '../../../tests/utils';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import BackTop from '..';

describe('BackTop', () => {
  mountTest(BackTop);
  rtlTest(BackTop);

  it('should scroll to top after click it', async () => {
    const { container } = render(<BackTop visibilityHeight={-1} />);
    const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
      window.scrollY = y;
      window.pageYOffset = y;
      document.documentElement.scrollTop = y;
    });
    window.scrollTo(0, 400);
    expect(document.documentElement.scrollTop).toBe(400);
    fireEvent.click(container.querySelector('.ant-back-top'));
    await sleep(500);
    expect(document.documentElement.scrollTop).toBe(0);
    scrollToSpy.mockRestore();
  });

  it('support onClick', async () => {
    const onClick = jest.fn();
    const { container } = render(<BackTop onClick={onClick} visibilityHeight={-1} />);
    const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
      window.scrollY = y;
      window.pageYOffset = y;
    });
    document.dispatchEvent(new Event('scroll'));
    window.scrollTo(0, 400);
    fireEvent.click(container.querySelector('.ant-back-top'));
    expect(onClick).toHaveBeenCalled();
    scrollToSpy.mockRestore();
  });

  it('invalid target', async () => {
    const onClick = jest.fn();
    const { container } = render(
      <BackTop onClick={onClick} visible target={() => ({ documentElement: {} })} />,
    );
    fireEvent.click(container.querySelector('.ant-back-top'));
    expect(onClick).toHaveBeenCalled();
  });
});
<|endoftext|>