<commit_before>/* global chrome, $ */

(function() {
  // Expose this library.
  chrome.options = {};
  chrome.options.base = {};
  chrome.options.opts = {
    // If not given, title of the page will be set to the extension's name.
    // Set to `false` if you want to hide the title.
    title: null,

    // Set this if you want to customize the about tab's contents,
    // otherwise it will be set to the extension's description.
    // Set to `false` if you don't want an About page.
    about: null,

    // True if you want settings to be saved as they are changed.
    autoSave: true,

    // True if you want default values to be saved when user visits
    // the options page. Useful if you want to only specify default values
    // in one place, without having to check if an option is set.
    // Note that it requires the options page to be visited once.
    saveDefaults: true,
  };


  var $menu = $('#main-menu');
  var $mainview = $('.mainview');
  var lastHash = null;

  function menuClick() {
    var hash = window.location.hash;
    if (!hash) {
      $('.mainview > *:nth-child(2)').addClass('selected');
      $('#main-menu li:first-child').addClass('selected');
      return;
    }
    if (hash === lastHash) { return; }
    lastHash = hash;

    $('.mainview > *, .menu li').removeClass('selected');

    var $target = $('.menu a[href="' + hash + '"]');
    $target.parent().addClass('selected');
    var $currentView = $(hash);
    $currentView.addClass('selected');
    $('body')[0].scrollTop = 0;
  }

  setTimeout(menuClick, 100);
  window.addEventListener('hashchange', menuClick);

  var changedValues = {};
  var $saveContainer = $('.save-container');
  var $saveButton = $saveContainer.find('button')
    .click(function() {
      chrome.storage.sync.set(changedValues);
      $saveButton.attr('disabled', true);
    });
  var showSavedAlert = flashClass($saveContainer, 'show', 2000);
  var flashSavedAlert = flashClass($saveContainer, 'flash', 150);

  // Shortcut.
  var raf = window.requestAnimationFrame;

  // Add the extension's title to the top of the page.
  var setupRan = false;
  function setup() {
    if (setupRan) { return; }
    var manifest = chrome.runtime.getManifest();

    var extensionName = chrome.options.opts.title || manifest.name || 'chrome';
    $('title').text(extensionName + ' options');
    var $title = $('.chrome-options-title');
    $title.text(extensionName);
    if (chrome.options.opts.title === false) {
      $title.hide();
    }

    if (chrome.options.opts.about === false ||
       (!chrome.options.opts.about && !manifest.description)) {
      $('.menu.about').hide();
    } else {
      if (chrome.options.opts.about) {
        $('#about .content > p').html(chrome.options.opts.about);
      } else {
        $('#about .content > p').text(manifest.description);
      }
    }

    if (chrome.options.opts.autoSave) {
      $saveButton.hide();
    } else {
      $saveContainer.find('.auto').hide();
      $saveContainer.addClass('show');
    }

    setupRan = true;
  }


  /**
   * @param {String} name
   * @param {String!} desc Will be placed at the top of the page of the tab
   * @param {Array.<Object>} options
   */
  chrome.options.addTab = function(name, desc, options) {
    setup();
    if (!options) {
      options = desc;
      desc = null;
    }
    var keyName = name.toLowerCase().replace(' ', '_');
    var $menuButton = $('<li><a href="#' + keyName + '">' + name + '</a></li>');
    $menuButton.find('a').click(menuClick);
    $menuButton.appendTo($menu);
    var $tabview = $('<div id="' + keyName + '">' +
      '<header><h1></h1></header>' +
      '</div>');
    $tabview.find('header > h1').text(name);
    var $tabcontent = $('<div class="content"></div>');
    if (desc) {
      $tabcontent.append($('<p></p>').text(desc));
    }
    keyName = keyName ? keyName + '.' : '';
    var keys = options
      .filter(function(option) { return !!option.name; })
      .map(function(option) {
        return keyName + option.name;
      });
    chrome.storage.sync.get(keys, function(items) {
      addTabOptions($tabcontent, keyName, items, options);
    });
    $tabcontent.appendTo($tabview);
    $tabview.appendTo($mainview);
  };


  /**
   * @param {String} desc
   * @param {Array.<Object>} options
   */
  chrome.options.set = function(desc, options) {
    chrome.options.opts.title = false;
    chrome.options.addTab('', desc, options);
    $('.frame .navigation, .frame .mainview header').hide();
    $('.frame .mainview').css('-webkit-margin-start', '10px');
    $('.frame .content').css('padding-top', '2px');
  };

  function addTabOptions($parent, keyName, values, options) {
    options.forEach(function(option) {
      var key = keyName + option.name;
      var $container;
      switch (option.type) {
        case 'h3':
          $container = addH3(option);
          break;

        default:
          var value = values[key];
          var latestValue = value;

          // Clone value so that it can be compared to new value.
          function cloneValue() { value = deepClone(latestValue); }

          // Also use a timeout so that it doensn't seep into load time.
          raf(cloneValue);

          var save = function(newValue) {
            latestValue = newValue;

            // Wrap this in requestAnimationFrame so that it
            // doesn't block user interaction.
            raf(function() {
              var isEqual = deepEqual(value, newValue);
              if (chrome.options.opts.autoSave) {
                if (!isEqual) {
                  chrome.storage.sync.set({ [key]: newValue });
                  showSavedAlert();
                  flashSavedAlert();
                  cloneValue();
                }
              } else if (isEqual) {
                delete changedValues[key];
                $saveButton.off('click', cloneValue);
                flashSavedAlert();
                if (!Object.keys(changedValues).length) {
                  $saveButton.attr('disabled', true);
                }
              } else {
                changedValues[key] = newValue;
                $saveButton.attr('disabled', false);<commit_msg>dont flash save button when it gets disabled<commit_after>/* global chrome, $ */

(function() {
  // Expose this library.
  chrome.options = {};
  chrome.options.base = {};
  chrome.options.opts = {
    // If not given, title of the page will be set to the extension's name.
    // Set to `false` if you want to hide the title.
    title: null,

    // Set this if you want to customize the about tab's contents,
    // otherwise it will be set to the extension's description.
    // Set to `false` if you don't want an About page.
    about: null,

    // True if you want settings to be saved as they are changed.
    autoSave: true,

    // True if you want default values to be saved when user visits
    // the options page. Useful if you want to only specify default values
    // in one place, without having to check if an option is set.
    // Note that it requires the options page to be visited once.
    saveDefaults: true,
  };


  var $menu = $('#main-menu');
  var $mainview = $('.mainview');
  var lastHash = null;

  function menuClick() {
    var hash = window.location.hash;
    if (!hash) {
      $('.mainview > *:nth-child(2)').addClass('selected');
      $('#main-menu li:first-child').addClass('selected');
      return;
    }
    if (hash === lastHash) { return; }
    lastHash = hash;

    $('.mainview > *, .menu li').removeClass('selected');

    var $target = $('.menu a[href="' + hash + '"]');
    $target.parent().addClass('selected');
    var $currentView = $(hash);
    $currentView.addClass('selected');
    $('body')[0].scrollTop = 0;
  }

  setTimeout(menuClick, 100);
  window.addEventListener('hashchange', menuClick);

  var changedValues = {};
  var $saveContainer = $('.save-container');
  var $saveButton = $saveContainer.find('button')
    .click(function() {
      chrome.storage.sync.set(changedValues);
      $saveButton.attr('disabled', true);
    });
  var showSavedAlert = flashClass($saveContainer, 'show', 2000);
  var flashSavedAlert = flashClass($saveContainer, 'flash', 150);

  // Shortcut.
  var raf = window.requestAnimationFrame;

  // Add the extension's title to the top of the page.
  var setupRan = false;
  function setup() {
    if (setupRan) { return; }
    var manifest = chrome.runtime.getManifest();

    var extensionName = chrome.options.opts.title || manifest.name || 'chrome';
    $('title').text(extensionName + ' options');
    var $title = $('.chrome-options-title');
    $title.text(extensionName);
    if (chrome.options.opts.title === false) {
      $title.hide();
    }

    if (chrome.options.opts.about === false ||
       (!chrome.options.opts.about && !manifest.description)) {
      $('.menu.about').hide();
    } else {
      if (chrome.options.opts.about) {
        $('#about .content > p').html(chrome.options.opts.about);
      } else {
        $('#about .content > p').text(manifest.description);
      }
    }

    if (chrome.options.opts.autoSave) {
      $saveButton.hide();
    } else {
      $saveContainer.find('.auto').hide();
      $saveContainer.addClass('show');
    }

    setupRan = true;
  }


  /**
   * @param {String} name
   * @param {String!} desc Will be placed at the top of the page of the tab
   * @param {Array.<Object>} options
   */
  chrome.options.addTab = function(name, desc, options) {
    setup();
    if (!options) {
      options = desc;
      desc = null;
    }
    var keyName = name.toLowerCase().replace(' ', '_');
    var $menuButton = $('<li><a href="#' + keyName + '">' + name + '</a></li>');
    $menuButton.find('a').click(menuClick);
    $menuButton.appendTo($menu);
    var $tabview = $('<div id="' + keyName + '">' +
      '<header><h1></h1></header>' +
      '</div>');
    $tabview.find('header > h1').text(name);
    var $tabcontent = $('<div class="content"></div>');
    if (desc) {
      $tabcontent.append($('<p></p>').text(desc));
    }
    keyName = keyName ? keyName + '.' : '';
    var keys = options
      .filter(function(option) { return !!option.name; })
      .map(function(option) {
        return keyName + option.name;
      });
    chrome.storage.sync.get(keys, function(items) {
      addTabOptions($tabcontent, keyName, items, options);
    });
    $tabcontent.appendTo($tabview);
    $tabview.appendTo($mainview);
  };


  /**
   * @param {String} desc
   * @param {Array.<Object>} options
   */
  chrome.options.set = function(desc, options) {
    chrome.options.opts.title = false;
    chrome.options.addTab('', desc, options);
    $('.frame .navigation, .frame .mainview header').hide();
    $('.frame .mainview').css('-webkit-margin-start', '10px');
    $('.frame .content').css('padding-top', '2px');
  };

  function addTabOptions($parent, keyName, values, options) {
    options.forEach(function(option) {
      var key = keyName + option.name;
      var $container;
      switch (option.type) {
        case 'h3':
          $container = addH3(option);
          break;

        default:
          var value = values[key];
          var latestValue = value;

          // Clone value so that it can be compared to new value.
          function cloneValue() { value = deepClone(latestValue); }

          // Also use a timeout so that it doensn't seep into load time.
          raf(cloneValue);

          var save = function(newValue) {
            latestValue = newValue;

            // Wrap this in requestAnimationFrame so that it
            // doesn't block user interaction.
            raf(function() {
              var isEqual = deepEqual(value, newValue);
              if (chrome.options.opts.autoSave) {
                if (!isEqual) {
                  chrome.storage.sync.set({ [key]: newValue });
                  showSavedAlert();
                  flashSavedAlert();
                  cloneValue();
                }
              } else if (isEqual) {
                delete changedValues[key];
                $saveButton.off('click', cloneValue);
                if (!Object.keys(changedValues).length) {
                  $saveButton.attr('disabled', true);
                } else {
                  flashSavedAlert();
                }
              } else {
                changedValues[key] = newValue;
                $saveButton.attr('disabled', false);
{'fraction_non_alphanumeric': 0.15811484638893358, 'fraction_numerical': 0.0033778349686343894, 'mean_word_length': 2.363538003786854, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1827171', 'n_tokens_mistral': 3765, 'n_tokens_neox': 3611, 'n_words': 949}