Darkino Tools

Toutes les options pour profiter pleinement de Darkino.

// ==UserScript==
// @namespace       https://greasyfork.org/fr/users/868328-invincible812
// @name            Darkino Tools
// @match           *://www*.darkino.*/**
// @match           *://www2.darkino.*/**
// @match           *://www*.sumoweb.*/**
// @grant           none
// @version         2.6.4
// @author          Invincible812
// @description     Toutes les options pour profiter pleinement de Darkino.
// @supportURL      https://www2.darkino.net/user/Invincible812
// @icon            https://www2.darkino.net/images/logo.svg
// @run-at          document-end
// @grant           GM.xmlHttpRequest
// @grant           GM_getValue
// @grant           GM_setValue
// @grant           GM_registerMenuCommand
// @grant           GM_addStyle
// ==/UserScript==

window.addEventListener('load', function () {

  var cfg = new MonkeyConfig({
    title: 'Options - Script Darkino Tools',
    menuCommand: true,
    params: {
      /**Sauvegarder_prez: {
        type: 'select',
        choices: ['Oui', 'Non'],
        default: 'Non'
      },*/
      Auto_Affiche_Liens: {
        type: 'select',
        choices: ['Oui', 'Non'],
        default: 'Oui'
      },
      /*Afficher_tous_les_liens: {
        type: 'select',
        choices: ['Oui', 'Non'],
        default: 'Non'
      },*/
      Auto_tri_des_liens_panel: {
        type: 'select',
        choices: ['Oui', 'Non'],
        default: 'Non'
      },
      Remplace_Uptobox_eu: {
        type: 'select',
        choices: ['Oui', 'Non'],
        default: 'Oui'
      }
    },
  });
  if (location.hostname.includes('darkino')) {
    console.log('[DARKINO TOOLS] Script lancé sur Darkino')
    if (!location.href.includes('/panel')) {
      if (document.getElementsByClassName('dropdown flex-shrink-0')[0] === undefined) { // Non connecté
        document.getElementsByClassName('shadow-sm')[0].children[0].children[2].children[0].insertAdjacentHTML('afterend', `<a href="#" title="Options Script" id="options-script" class="flex items-center p-2 rounded-full bg-white-light/40 dark:bg-dark/40 hover:text-primary hover:bg-white-light/90 dark:hover:bg-dark/60">
        <svg class="h-4.5 w-4.5 ltr:mr-2 rtl:ml-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke:currentColor;"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
        </a>`)
        console.log('[DARKINO TOOLS] [MENU-SCRIPT] Non connecté • Ajout bouton');
      }
    } else if (location.href.includes('/panel')) { // Si panel
      document.getElementsByClassName('flex items-center justify-between flex-1')[0].children[3].children[1].children[0].insertAdjacentHTML('afterend', `<a href="#" title="Options Script" id="options-script" class="filament-dropdown-header flex w-full p-3 text-sm">
        <svg class="h-4.5 w-4.5 ltr:mr-2 rtl:ml-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke:currentColor;"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
        <span>Options Script</span></a>`)
      console.log('[DARKINO TOOLS] [MENU-SCRIPT] Connecté • Ajout menu sur le panel');
    }
    if (!location.href.includes('/panel')) { // si connecté
      document.getElementsByClassName('shadow-sm')[0].children[0].children[2].children[4].children[1].children[0].insertAdjacentHTML('afterend', `<li>
        <a href="#" id="options-script">
        <svg class="h-4.5 w-4.5 ltr:mr-2 rtl:ml-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke:currentColor;"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
        <span>Options Script</span></a></li>`);
      console.log('[DARKINO TOOLS] [MENU-SCRIPT] Connecté • Ajout menu');
    }


    const link = document.getElementById('options-script');
    link.addEventListener('click', function (event) {
      event.preventDefault();
      cfg.open();
    });
  }

  //let saveprez = cfg.get('Sauvegarder_prez');
  let autoaffiche = cfg.get('Auto_Affiche_Liens');
  //let affichtoutliens = cfg.get('Afficher_tous_les_liens');
  let tri_liens = cfg.get('Auto_tri_des_liens_panel');
  let replace_upto = cfg.get('Remplace_Uptobox_eu');
  /*if (saveprez == "Oui") {
    saveprez = true;
  } else {
    saveprez = false;
  }*/
  /*if (autoaffiche == "Oui") {
    autoaffiche = true;
  } else {
    autoaffiche = false;
  }
  if (affichtoutliens == "Oui") {
    affichtoutliens = true;
  } else {
    affichtoutliens = false;
  }*/
  if (tri_liens == "Oui") {
    tri_liens = true;
  } else {
    tri_liens = false;
  }
  if (replace_upto == "Oui") {
    replace_upto = true;
  } else {
    replace_upto = false;
  }

  //---------------------------------------------------------------------------------//

  document.title = document.title.replace(' - Darkino Officiel', '').replace('gratuitement', '').replace('Télécharger ', '').replace('ou voir en Streaming ', '');

  /*if (saveprez) {
    if (document.location.pathname.includes('/mypanel/addlink/')) {
      document.getElementsByClassName('addnews')[0].insertAdjacentHTML('beforeend', `<b id="b_restore" class="inline-block align-middle text-center select-none border font-normal whitespace-no-wrap rounded py-1 px-3 leading-normal no-underline bg-gray-600 text-white hover:bg-gray-700 restore" title="Restore">Restore Prez</b>`);
      document.getElementsByClassName('flex justify-end')[0].insertAdjacentHTML('afterbegin', `<b id="b_save" class="inline-block align-middle text-center select-none border font-normal whitespace-no-wrap rounded py-1 px-3 leading-normal no-underline bg-gray-600 text-white hover:bg-gray-700 save" title="Save">Save Prez</b>`);
      document.getElementsByClassName('panel')[0].children[1].children[0].insertAdjacentHTML('afterend', `<span id="prez_logs"></span>`);
      function save_prez() {
        let options = [];
        document.getElementById('prez_logs').textContent = "Sauvegarde de la prez comportant : ";
        let langues = "Langue(s) : ";
        let qualité = "Qualité : ";
        let subs = "Sous-titre(s) : ";
        for (let a = 0; a < document.getElementsByTagName('option').length; a++) {
          if (document.getElementsByTagName('option')[a].selected) {
            options.push(a);
            console.log(a)
            if (a >= 0 && a <= 40) { // Langue(s)
              langues = langues + document.getElementsByTagName('option')[a].textContent + ', ';
            }

            if (a >= 41 && a <= 102) { // Qualité
              qualité = qualité + document.getElementsByTagName('option')[a].textContent + ', ';
            }

            if (a >= 103 && a <= 142) { // Sous-titre
              subs = subs + document.getElementsByTagName('option')[a].textContent + ', ';
            }
          }
        }
        document.getElementById('prez_logs').textContent = document.getElementById('prez_logs').textContent + langues + qualité + subs;
        localStorage.setItem('options', JSON.stringify(options));
      }

      document.getElementsByClassName('inline-block align-middle text-center select-none border font-normal whitespace-no-wrap rounded py-1 px-3 leading-normal no-underline bg-gray-600 text-white hover:bg-gray-700 save')[0].addEventListener('click', function () {
        save_prez();
      });

      function restore_prez() {
        let options = JSON.parse(localStorage.getItem('options'));
        document.getElementById('prez_logs').textContent = "Restauration de la précédent prez comportant : ";
        let langues = "Langue(s) : ";
        let qualité = "Qualité : ";
        let subs = "Sous-titre(s) : ";
        if (options) {
          for (let i = 0; i < options.length; i++) {
            document.getElementsByTagName('option')[options[i]].selected = true;

            if (options[i] >= 0 && options[i] <= 40) { // Langue(s)
              langues = langues + document.getElementsByTagName('option')[options[i]].textContent + ', ';
            }

            if (options[i] >= 41 && options[i] <= 102) { // Qualité
              qualité = qualité + document.getElementsByTagName('option')[options[i]].textContent + ', ';
            }

            if (options[i] >= 103 && options[i] <= 142) { // Sous-titre
              subs = subs + document.getElementsByTagName('option')[options[i]].textContent + ', ';
            }
          }
          document.getElementById('prez_logs').textContent = document.getElementById('prez_logs').textContent + langues + qualité + subs;
        }
      }

      document.addEventListener('click', function (event) {
        if (event.target && event.target.classList.contains('restore')) {
          restore_prez();
        }
      });
    }
  }; */

  if (autoaffiche) {
    if (window.location.pathname.match(/\/(.)+\/(\d)+/g) && window.location.pathname.search("/coll") != 0 && !document.location.pathname.includes('/addlink/') && !document.location.pathname.includes('/mylinks/') && document.location.href.includes('/post/') && !document.location.href.includes('/edit')) {
      if (document.getElementsByClassName('space-y-2 font-semibold')[0].childElementCount == "2") {
        document.getElementsByClassName('space-y-2 font-semibold')[0].children[1].children[0].click()
         console.log('[DARKINO TOOLS] [AUTO-AFFICHE-LIENS] Click effectué');
      } else {
        document.getElementsByClassName('space-y-2 font-semibold')[0].children[0].children[0].click()
        console.log('[DARKINO TOOLS] [AUTO-AFFICHE-LIENS] Click effectué');
      }
    }
  } //fin autoaffiche

  /*if (affichtoutliens) {
    if (window.location.pathname.match(/\/(.)+\/(\d)+/g) && window.location.pathname.search("/coll") != 0 && !document.location.pathname.includes('/addlink/') && !document.location.pathname.includes('/mylinks/')) {
      let id;
      if (document.getElementsByClassName('space-y-2 font-semibold')[0].childElementCount == "2") {
        id = '1';
      } else {
        id = '0';
      }
      let nb_table = document.getElementsByClassName('space-y-2 font-semibold')[0].children[id].children[1].children[0].childElementCount;
      let nb_page = document.getElementsByClassName('space-y-2 font-semibold')[0].children[id].children[1].children[0].children[0].children[3].children[1].lastElementChild.textContent;

      function creationtable(table) {
        let codehtml = "";
        for (let a = 0; a < nb_page; a++) { // par page
          console.log(a);
          codehtml = codehtml + document.getElementsByClassName('space-y-2 font-semibold')[0].children[id].children[1].children[0].children[table].children[1].children[1].innerHTML;
          //console.log(codehtml)
          if (a + 1 != nb_page) {
            //console.log('Bouton ' +document.getElementsByClassName('space-y-2 font-semibold')[0].children[0].children[1].children[0].children[0].children[3].children[1].children[a+1].textContent+ ' va être cliqué')
            document.getElementsByClassName('space-y-2 font-semibold')[0].children[id].children[1].children[0].children[table].children[3].children[1].children[a + 1].click();
          }
        }
        document.getElementsByClassName('space-y-2 font-semibold')[0].children[id].children[1].children[0].children[table].children[1].children[1].innerHTML = codehtml;
      }
      function creationgigatable(table) {
        null
      }
      for (let a = 0; a < nb_table; a++) { // par page
        let codehtml = "";
        if (nb_page < 6) {
          creationtable(a);
        } else {
          creationgigatable(a)
        }
      }
    }
  } // fin affiche tout les liens */

  if (tri_liens) {
    if (location.href.includes('/panel/mylinks')) {
      setTimeout(document.getElementsByClassName('filament-tables-table w-full text-start divide-y table-auto dark:divide-gray-700')[0].children[0].children[0].children[0].children[0].click(), 4000)
      setTimeout(document.getElementsByClassName('filament-tables-table w-full text-start divide-y table-auto dark:divide-gray-700')[0].children[0].children[0].children[0].children[0].click(), 5000)
    }
  }

  if (replace_upto) {
    function attente_dl_premium(){
      const element = document.querySelector('.filament-link');
      element.addEventListener('click', function(event) {
        // Vérification de la classe et de l'attribut
        if (element.classList.contains('filament-link') && element.getAttribute('3').includes('download')) {
          // Le code à exécuter lorsque les conditions sont remplies
          let urlupto = document.getElementsByClassName('filament-modal-window w-full py-2 bg-white cursor-default pointer-events-auto dark:bg-gray-800 relative rounded-xl mx-auto max-w-4xl')[0].children[1].children[1].children[0].children[0].children[0].children[0].href
          console.log(urlupto)
        }
      });

    }

    if (location.hostname.includes('sumoweb')) {
      if (document.getElementById('captcha')) {
        document.getElementById('captcha').click();
      }

      if (document.querySelector('div.alert a')) {
        var link1 = document.querySelector('div.alert a')
        link1.href = link1.href.replace('uptobox.com', 'uptobox.eu')
        link1.text = link1.href.replace('uptobox.com', 'uptobox.eu')
      }
    }

  }

});




// POUR OPTIONS
function MonkeyConfig() {
  var cfg = this,
    /* Data object passed to the constructor */
    data,
    /* Configuration parameters (data.parameters or data.params) */
    params,
    /* Current values of configuration parameters */
    values = {},
    /* Identifier used to store/retrieve configuration */
    storageKey,
    /* Is the configuration dialog displayed? */
    displayed,
    /* Currently displayed window/layer */
    openWin, openLayer,
    /* DOM element wrapping the configuration form */
    container,
    /* Darkened overlay used in the layer display mode */
    overlay;

  /**
   * Initialize configuration
   *
   * @param newData New data object
   */
  function init(newData) {
    data = newData;

    if (data) {
      params = data.parameters || data.params;

      if (data.buttons === undefined)
        /* Set default buttons */
        data.buttons = ['save', 'defaults', 'cancel'];

      if (data.title === undefined)
        /*
         * If GM_getMetadata is available, get the name of the script
         * and use it in the dialog title
         */
        if (typeof GM_getMetadata == 'function') {
          var scriptName = GM_getMetadata('name');
          data.title = scriptName + ' Configuration';
        }
        else
          data.title = 'Configuration';
    }

    /* Make a safe version of title to be used as stored value identifier */
    var safeTitle = data && data.title ?
      data.title.replace(/[^a-zA-Z0-9]/g, '_') : '';

    storageKey = '_MonkeyConfig_' + safeTitle + '_cfg';

    var storedValues;

    /* Load stored values (if present) */
    if (GM_getValue(storageKey))
      storedValues = JSON.parse(GM_getValue(storageKey));

    for (var name in params) {
      /* If there's a value defined in the passed data object, use it */
      if (params[name]['value'] !== undefined)
        set(name, params[name].value);
      /* Check if there's a stored value for this parameter */
      else if (storedValues && storedValues[name] !== undefined)
        set(name, storedValues[name]);
      /* Otherwise, set the default value (if defined) */
      else if (params[name]['default'] !== undefined)
        set(name, params[name]['default']);
      else
        set(name, '');
    }

    if (data.menuCommand) {
      /* Add an item to the User Script Commands menu */
      var caption = data.menuCommand !== true ? data.menuCommand :
        data.title;

      GM_registerMenuCommand(caption, function () { cfg.open(); });
    }

    /* Expose public methods */
    cfg.open = open;
    cfg.close = close;
    cfg.get = get;
    cfg.set = function (name, value) {
      set(name, value);
      update();
    };
  }

  /**
   * Get the value of a configuration parameter
   *
   * @param name Name of the configuration parameter
   * @returns Value of the configuration parameter
   */
  function get(name) {
    return values[name];
  }

  /**
   * Set the value of a configuration parameter
   *
   * @param name Name of the configuration parameter
   * @param value New value of the configuration parameter
   */
  function set(name, value) {
    values[name] = value;
  }

  /**
   * Reset configuration parameters to default values
   */
  function setDefaults() {
    for (var name in params) {
      if (typeof params[name]['default'] !== 'undefined') {
        set(name, params[name]['default']);
      }
    }
  }

  /**
   * Render the configuration dialog
   */
  function render() {
    var html = '<div class="__MonkeyConfig_container">' +
      '<h1>' + data.title + '</h1>' +
      '<table>';

    for (var name in params) {
      html += MonkeyConfig.formatters['tr'](name, params[name]);
    }

    html += '<tr><td colspan="2" class="__MonkeyConfig_buttons">' +
      '<table><tr>';

    /* Render buttons */
    for (var button in data.buttons) {
      html += '<td>';

      switch (data.buttons[button]) {
        case 'cancel':
          html += '<button type="button" ' +
            'id="__MonkeyConfig_button_cancel">' +
            '<img src="data:image/png;base64,' +
            MonkeyConfig.res.icons.cancel + '" />&nbsp;' +
            'Annuler</button>';
          break;
        case 'defaults':
          html += '<button type="button" ' +
            'id="__MonkeyConfig_button_defaults">' +
            '<img src="data:image/png;base64,' +
            MonkeyConfig.res.icons.arrow_undo + '" />&nbsp;' +
            'Par&nbsp;Défaut</button>';
          break;
        case 'save':
          html += '<button type="button" ' +
            'id="__MonkeyConfig_button_save">' +
            '<img src="data:image/png;base64,' +
            MonkeyConfig.res.icons.tick + '" />&nbsp;' +
            'Sauvegarder</button>';
          break;
      }

      html += '</td>';
    }

    html += '</tr></table></td></tr>';

    html += "</table><div>";

    return html;
  }

  /**
   * Update the fields in the dialog to reflect current values
   */
  function update() {
    /* Do nothing if the dialog is not currently displayed */
    if (!displayed)
      return;

    for (var name in params) {
      var value = values[name];

      switch (params[name].type) {
        case 'checkbox':
          var elem = container.querySelector('[name="' + name + '"]');
          elem.checked = !!value;
          break;
        case 'custom':
          params[name].set(value, container
            .querySelector('#__MonkeyConfig_parent_' + name));
          break;
        case 'number': case 'text':
          var elem = container.querySelector('[name="' + name + '"]');
          elem.value = value;
          break;
        case 'select':
          var elem = container.querySelector('[name="' + name + '"]');

          if (elem.tagName.toLowerCase() == 'input') {
            if (elem.type && elem.type == 'radio') {
              /* Single selection with radio buttons */
              elem = container.querySelector(
                '[name="' + name + '"][value="' + value + '"]');
              elem.checked = true;
            }
            else if (elem.type && elem.type == 'checkbox') {
              /* Multiple selection with checkboxes */
              var checkboxes = container.querySelectorAll(
                'input[name="' + name + '"]');

              for (var i = 0; i < checkboxes.length; i++)
                checkboxes[i].checked =
                  (value.indexOf(checkboxes[i].value) > -1);
            }
          }
          else if (elem.tagName.toLowerCase() == 'select')
            if (elem.multiple) {
              /* Multiple selection element */
              var options = container.querySelectorAll(
                'select[name="' + name + '"] option');

              for (var i = 0; i < options.length; i++)
                options[i].selected =
                  (value.indexOf(options[i].value) > -1);
            }
            else
              /* Single selection element */
              elem.value = value;
          break;
      }
    }
  }

  /**
   * Save button click event handler
   */
  function saveClick() {
    for (name in params) {
      switch (params[name].type) {
        case 'checkbox':
          var elem = container.querySelector('[name="' + name + '"]');
          values[name] = elem.checked;
          break;
        case 'custom':
          values[name] = params[name].get(container
            .querySelector('#__MonkeyConfig_parent_' + name));
          break;
        case 'number': case 'text':
          var elem = container.querySelector('[name="' + name + '"]');
          values[name] = elem.value;
          break;
        case 'select':
          var elem = container.querySelector('[name="' + name + '"]');

          if (elem.tagName.toLowerCase() == 'input') {
            if (elem.type && elem.type == 'radio')
              /* Single selection with radio buttons */
              values[name] = container.querySelector(
                '[name="' + name + '"]:checked').value;
            else if (elem.type && elem.type == 'checkbox') {
              /* Multiple selection with checkboxes */
              values[name] = [];
              var inputs = container.querySelectorAll(
                'input[name="' + name + '"]');

              for (var i = 0; i < inputs.length; i++)
                if (inputs[i].checked)
                  values[name].push(inputs[i].value);
            }
          }
          else if (elem.tagName.toLowerCase() == 'select' && elem.multiple) {
            /* Multiple selection element */
            values[name] = [];
            var options = container.querySelectorAll(
              'select[name="' + name + '"] option');

            for (var i = 0; i < options.length; i++)
              if (options[i].selected)
                values[name].push(options[i].value);
          }
          else
            values[name] = elem.value;
          break;
      }
    }

    GM_setValue(storageKey, JSON.stringify(values));

    close();

    if (data.onSave)
      data.onSave(values);
  }

  /**
   * Cancel button click event handler
   */
  function cancelClick() {
    close();
  }

  /**
   * Set Defaults button click event handler
   */
  function defaultsClick() {
    setDefaults();
    update();
  }

  /**
   * Open configuration dialog
   *
   * @param mode
   *            Display mode ("iframe", "layer", or "window", defaults to
   *            "iframe")
   * @param options
   *            Display mode options
   */
  function open(mode, options) {
    function openDone() {
      /* Attach button event handlers */
      var button;

      if (button = container.querySelector('#__MonkeyConfig_button_save'))
        button.addEventListener('click', saveClick, true);
      if (button = container.querySelector('#__MonkeyConfig_button_cancel'))
        button.addEventListener('click', cancelClick, true);
      if (button = container.querySelector('#__MonkeyConfig_button_defaults'))
        button.addEventListener('click', defaultsClick, true);

      displayed = true;
      update();
    }

    switch (mode) {
      case 'window':
        var windowFeatures = {
          location: 'no',
          status: 'no',
          left: window.screenX,
          top: window.screenY,
          width: 100,
          height: 100
        };

        /* Additional features may be specified as an option */
        if (options && options.windowFeatures)
          for (var name in options.windowFeatures)
            windowFeatures[name] = options.windowFeatures[name];

        var featuresArray = [];

        for (var name in windowFeatures)
          featuresArray.push(name + '=' + windowFeatures[name]);

        var win = window.open('', data.title, featuresArray.join(','));

        /* Find head and body (then call the blood spatter analyst) */
        var head = win.document.getElementsByTagName('head')[0],
          body = win.document.getElementsByTagName('body')[0];

        head.innerHTML = '<title>' + data.title + '</title>' +
          '<style type="text/css">' +
          MonkeyConfig.res.stylesheets.main + '</style>';

        body.className = '__MonkeyConfig_window';
        /* Place the rendered configuration dialog inside the window body */
        body.innerHTML = render();

        /* Find the container (CBAN-3489) */
        container = win.document.querySelector('.__MonkeyConfig_container');

        /* Resize window to the dimensions of the container div */
        win.innerWidth = container.clientWidth;
        win.resizeBy(0, -win.innerHeight + container.clientHeight);

        /* Place the window centered relative to the parent */
        win.moveBy(Math.round((window.outerWidth - win.outerWidth) / 2),
          Math.round((window.outerHeight - win.outerHeight) / 2));

        openWin = win;

        openDone();

        break;
      case 'layer':
        if (!MonkeyConfig.styleAdded) {
          GM_addStyle(MonkeyConfig.res.stylesheets.main);
          MonkeyConfig.styleAdded = true;
        }

        var body = document.querySelector('body');

        /* Create the layer element */
        openLayer = document.createElement('div');
        openLayer.className = '__MonkeyConfig_layer';

        /* Create the overlay */
        overlay = document.createElement('div');
        overlay.className = '__MonkeyConfig_overlay';
        overlay.style.left = 0;
        overlay.style.top = 0;
        overlay.style.width = window.innerWidth + 'px';
        overlay.style.height = window.innerHeight + 'px';
        overlay.style.zIndex = 9999;

        body.appendChild(overlay);
        body.appendChild(openLayer);

        /*
         * Place the rendered configuration dialog inside the layer element
         */
        openLayer.innerHTML = render();

        /* Position the layer in the center of the viewport */
        openLayer.style.left = Math.round((window.innerWidth -
          openLayer.clientWidth) / 2) + 'px';
        openLayer.style.top = Math.round((window.innerHeight -
          openLayer.clientHeight) / 2) + 'px';
        openLayer.style.zIndex = 9999;

        container = document.querySelector('.__MonkeyConfig_container');

        openDone();

        break;
      case 'iframe':
      default:
        if (!MonkeyConfig.styleAdded) {
          GM_addStyle(MonkeyConfig.res.stylesheets.main);
          MonkeyConfig.styleAdded = true;
        }

        var body = document.querySelector('body');
        var iframe = document.createElement('iframe');

        /* Create the layer element */
        openLayer = document.createElement('div');
        openLayer.className = '__MonkeyConfig_layer';

        /* Create the overlay */
        overlay = document.createElement('div');
        overlay.className = '__MonkeyConfig_overlay';
        overlay.style.left = 0;
        overlay.style.top = 0;
        overlay.style.width = window.innerWidth + 'px';
        overlay.style.height = window.innerHeight + 'px';
        overlay.style.zIndex = 9999;

        iframe.id = '__MonkeyConfig_frame';
        /*
         * Make the iframe transparent so that it remains invisible until
         * the document inside it is ready
         */
        iframe.style.opacity = 0;
        iframe.src = 'about:blank';

        /* Make the iframe seamless with no border and no scrollbars */
        if (undefined !== iframe.frameborder)
          iframe.frameBorder = '0';
        if (undefined !== iframe.scrolling)
          iframe.scrolling = 'no';
        if (undefined !== iframe.seamless)
          iframe.seamless = true;

        /* Do the rest in the load event handler */
        iframe.addEventListener('load', function () {
          iframe.contentDocument.body.innerHTML = render();
          iframe.style.opacity = 1;

          /* Append the style to the head */
          var head = iframe.contentDocument.querySelector('head'),
            style = iframe.contentDocument.createElement('style');
          style.setAttribute('type', 'text/css');
          style.appendChild(iframe.contentDocument.createTextNode(
            MonkeyConfig.res.stylesheets.main));
          head.appendChild(style);

          var body = iframe.contentDocument.querySelector('body');
          body.className = '__MonkeyConfig_body';

          container = iframe.contentDocument
            .querySelector('.__MonkeyConfig_container');

          iframe.width = container.clientWidth;
          iframe.height = container.clientHeight;

          /* Position the layer in the center of the viewport */
          openLayer.style.left = Math.round((window.innerWidth -
            openLayer.clientWidth) / 2.45) + 'px';
          openLayer.style.top = Math.round((window.innerHeight -
            openLayer.clientHeight) / 2) + 'px';
          openLayer.style.zIndex = 9999;

          openDone();
        }, false);

        setTimeout(function () {
          iframe.width = container.clientWidth;
          iframe.height = container.clientHeight;

          /* Position the layer in the center of the viewport */
          openLayer.style.left = Math.round((window.innerWidth -
            openLayer.clientWidth) / 2) + 'px';
          openLayer.style.top = Math.round((window.innerHeight -
            openLayer.clientHeight) / 2) + 'px';
          openLayer.style.zIndex = 9999;
        }, 0);

        body.appendChild(overlay);
        body.appendChild(openLayer);
        openLayer.appendChild(iframe);

        break;
    }
  }

  /**
   * Close configuration dialog
   */
  function close() {
    if (openWin) {
      openWin.close();
      openWin = undefined;
    }
    else if (openLayer) {
      openLayer.parentNode.removeChild(openLayer);
      openLayer = undefined;

      if (overlay) {
        overlay.parentNode.removeChild(overlay);
        overlay = undefined;
      }
    }

    displayed = false;
  }

  init(arguments[0]);
}

/**
 * Replace double quotes with entities so that the string can be safely used
 * in a HTML attribute
 *
 * @param string A string
 * @returns String with double quotes replaced with entities
 */
MonkeyConfig.esc = function (string) {
  return string.replace(/"/g, '&quot;');
};

MonkeyConfig.HTML = {
  '_field': function (name, options, data) {
    var html;

    if (options.type && MonkeyConfig.HTML[options.type])
      html = MonkeyConfig.HTML[options.type](name, options, data);
    else
      return;

    if (/\[FIELD\]/.test(options.html)) {
      html = options.html.replace(/\[FIELD\]/, html);
    }

    return html;
  },
  '_label': function (name, options, data) {
    var label = options['label'] ||
      name.substring(0, 1).toUpperCase() + name.substring(1)
        .replace(/_/g, '&nbsp;')
        .replace(/é/g, "\u002F")
        .replace(/0/g, "...")
        .replace(/1/g, "'");

    return '<label for="__MonkeyConfig_field_' + name + '">' + label +
      '</label>';
  },
  'checkbox': function (name, options, data) {
    return '<input id="__MonkeyConfig_field_' + name +
      '" type="checkbox" name="' + name + '" />';
  },
  'custom': function (name, options, data) {
    return options.html;
  },
  'number': function (name, options, data) {
    return '<input id="__MonkeyConfig_field_' + name + '" ' +
      'type="text" class="__MonkeyConfig_field_number" ' +
      'name="' + name + '" />';
  },
  'select': function (name, options, data) {
    var choices = {}, html = '';

    if (options.choices.constructor == Array) {
      /* options.choices is an array -- build key/value pairs */
      for (var i = 0; i < options.choices.length; i++)
        choices[options.choices[i]] = options.choices[i];
    }
    else
      /* options.choices is an object -- use it as it is */
      choices = options.choices;

    if (!options.multiple) {
      /* Single selection */
      if (!/^radio/.test(options.variant)) {
        /* Select element */
        html += '<select id="__MonkeyConfig_field_' + name + '" ' +
          'class="__MonkeyConfig_field_select" ' +
          'name="' + name + '">';

        for (var value in choices)
          html += '<option value="' + MonkeyConfig.esc(value) + '">' +
            choices[value] + '</option>';

        html += '</select>';
      }
      else {
        /* Radio buttons */
        for (var value in choices) {
          html += '<label><input type="radio" name="' + name + '" ' +
            'value="' + MonkeyConfig.esc(value) + '" />&nbsp;' +
            choices[value] + '</label>' +
            (/ column/.test(options.variant) ? '<br />' : '');
        }
      }
    }
    else {
      /* Multiple selection */
      if (!/^checkbox/.test(options.variant)) {
        /* Checkboxes */
        html += '<select id="__MonkeyConfig_field_' + name + '" ' +
          'class="__MonkeyConfig_field_select" ' +
          'multiple="multiple" ' +
          'name="' + name + '">';

        for (var value in choices)
          html += '<option value="' + MonkeyConfig.esc(value) + '">' +
            choices[value] + '</option>';

        html += '</select>';
      }
      else {
        /* Select element */
        for (var value in choices) {
          html += '<label><input type="checkbox" ' +
            'name="' + name + '" ' +
            'value="' + MonkeyConfig.esc(value) + '" />&nbsp;' +
            choices[value] + '</label>' +
            (/ column/.test(options.variant) ? '<br />' : '');
        }
      }
    }

    return html;
  },
  'text': function (name, options, data) {
    if (options.long)
      return '<textarea id="__MonkeyConfig_field_' + name + '" ' +
        'class="__MonkeyConfig_field_text" ' +
        (!isNaN(options.long) ? 'rows="' + options.long + '" ' : '') +
        'name="' + name + '"></textarea>';
    else
      return '<input id="__MonkeyConfig_field_' + name + '" ' +
        'type="text" class="__MonkeyConfig_field_text" ' +
        'name="' + name + '" />';
  }

};

MonkeyConfig.formatters = {
  'tr': function (name, options, data) {
    var html = '<tr>';

    switch (options.type) {
      case 'checkbox':
        /* Checkboxes get special treatment */
        html += '<td id="__MonkeyConfig_parent_' + name + '" colspan="2">';
        html += MonkeyConfig.HTML['_field'](name, options, data) + ' ';
        html += MonkeyConfig.HTML['_label'](name, options, data);
        html += '</td>';
        break;
      default:
        html += '<td>';
        html += MonkeyConfig.HTML['_label'](name, options, data);
        html += '</td><td id="__MonkeyConfig_parent_' + name + '">';
        html += MonkeyConfig.HTML['_field'](name, options, data);
        html += '</td>';
        break;
    }

    html += '</tr>';

    return html;
  }
};

/* Has the stylesheet been added? */
MonkeyConfig.styleAdded = false;

/* Resources */
MonkeyConfig.res = {};

/* Icons */
MonkeyConfig.res.icons = {
  'arrow_undo': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIJSURBVDjLpVM9aJNRFD35GsRSoUKKzQ/B\
0NJJF3EQlKrVgijSCBmC4NBFKihIcXBwEZdSHVoUwUInFUEkQ1DQ4CKiFsQsTrb5xNpgaZHw2Uog\
5t5zn0NJNFaw0guX97hwzuPcc17IOYfNlIdNVrhxufR6xJkZjAbSQGXjNAorqixSWFDV3KPhJ+UG\
LtSQMPryrDscPwLnAHOEOQc6gkbUpIagGmApWIb/pZRX4fjj889nWiSQtgYyBZ1BTUEj6AjPa0P7\
1nb0Jfqwa+futIheHrzRn2yRQCUK/lOQhApBJVQJChHfnkCqOwWEQ+iORJHckUyX5ksvAEyGNuJC\
+s6xCRXNHNxzKMmQ4luwgjfvZp69uvr2+IZcyJ8rjIporrxURggetnV0QET3rrPxzMNM2+n7p678\
jUTrCiWhphAjVHR9DlR0WkSzf4IHxg5MSF0zXZEuVKWKSlCBCostS8zeG7oV64wPqxInbw86lbVX\
KEQ8mkAqmUJ4SxieeVhcnANFC02C7N2h69HO2IXeWC8MDj2JnqaFNAMd8f3HKjx6+LxQRmnOz1OZ\
axKIaF1VISYwB9ARZoQaYY6o1WpYCVYxt+zDn/XzVBv/MOWXW5J44ubRyVgkelFpmF/4BJVfOVDl\
VyqLVBZI5manPjajDOdcswfG9k/3X9v3/vfZv7rFBanriIo++J/f+BMT+YWS6hXl7QAAAABJRU5E\
rkJggg==',
  'cancel': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHdSURBVDjLpZNraxpBFIb3a0ggISmmNISW\
XmOboKihxpgUNGWNSpvaS6RpKL3Ry//Mh1wgf6PElaCyzq67O09nVjdVlJbSDy8Lw77PmfecMwZg\
/I/GDw3DCo8HCkZl/RlgGA0e3Yfv7+DbAfLrW+SXOvLTG+SHV/gPbuMZRnsyIDL/OASziMxkkKkU\
QTJJsLaGn8/iHz6nd+8mQv87Ahg2H9Th/BxZqxEkEgSrq/iVCvLsDK9awtvfxb2zjD2ARID+lVVl\
babTgWYTv1rFL5fBUtHbbeTJCb3EQ3ovCnRC6xAgzJtOE+ztheYIEkqbFaS3vY2zuIj77AmtYYDu\
sPy8/zuvunJkDKXM7tYWTiyGWFjAqeQnAD6+7ueNx/FLpRGAru7mcoj5ebqzszil7DggeF/DX1nB\
N82rzPqrzbRayIsLhJqMPT2N83Sdy2GApwFqRN7jFPL0tF+10cDd3MTZ2AjNUkGCoyO6y9cRxfQo\
wFUbpufr1ct4ZoHg+Dg067zduTmEbq4yi/UkYidDe+kaTcP4ObJIajksPd/eyx3c+N2rvPbMDPbU\
FPZSLKzcGjKPrbJaDsu+dQO3msfZzeGY2TCvKGYQhdSYeeJjUt21dIcjXQ7U7Kv599f4j/oF55W4\
g/2e3b8AAAAASUVORK5CYII=',
  'tick': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLvZPZLkNhFIV75zjvYm7VGFNC\
qoZUJ+roKUUpjRuqp61Wq0NKDMelGGqOxBSUIBKXWtWGZxAvobr8lWjChRgSF//dv9be+9trCwAI\
/vIE/26gXmviW5bqnb8yUK028qZjPfoPWEj4Ku5HBspgAz941IXZeze8N1bottSo8BTZviVWrEh5\
46EO03EXpuJOdG63otJbjBKHkEp/Ml6yNYYzpuezWL4s5VMtT8acCMQcb5XL3eJE8VgBlR7BeMGW\
9Z4yT9y1CeyucuhdTGDxfftaBO7G4L+zg91UocxVmCiy51NpiP3n2treUPujL8xhOjYOzZYsQWAN\
yRYlU4Y9Br6oHd5bDh0bCpSOixJiWx71YY09J5pM/WEbzFcDmHvwwBu2wnikg+lEj4mwBe5bC5h1\
OUqcwpdC60dxegRmR06TyjCF9G9z+qM2uCJmuMJmaNZaUrCSIi6X+jJIBBYtW5Cge7cd7sgoHDfD\
aAvKQGAlRZYc6ltJlMxX03UzlaRlBdQrzSCwksLRbOpHUSb7pcsnxCCwngvM2Rm/ugUCi84fycr4\
l2t8Bb6iqTxSCgNIAAAAAElFTkSuQmCC'
};

/* Stylesheets */
MonkeyConfig.res.stylesheets = {
  'main': '\
body.__MonkeyConfig_window {\
    appearance: window !important;\
    -moz-appearance: window !important;\
    background: auto;\
    font-family: sans-serif !important;\
    height: 100% !important;\
    margin: 0 !important;\
    padding: 0 !important;\
    width: 100% !important;\
}\
\
div.__MonkeyConfig_container {\
    display: table !important;\
    font-family: sans-serif !important;\
    padding: 0.3em !important;\
}\
\
body.__MonkeyConfig_window div.__MonkeyConfig_container {\
    appearance: window !important;\
    -moz-appearance: window !important;\
    height: 100%;\
    width: 100%;\
}\
\
div.__MonkeyConfig_container h1 {\
    border-bottom: solid 1px #999 !important;\
    font-family: sans-serif !important;\
    font-size: 120% !important;\
    margin: 0 !important;\
    padding: 0 0 0.3em 0 !important;\
}\
\
div.__MonkeyConfig_container table {\
    border-spacing: 0 !important;\
    margin: 0 !important;\
}\
\
div.__MonkeyConfig_container table td {\
    border: none !important;\
    line-height: 100% !important;\
    padding: 0.3em !important;\
    text-align: left !important;\
    vertical-align: top !important;\
    white-space: nowrap !important;\
}\
\
div.__MonkeyConfig_container table td.__MonkeyConfig_buttons {\
    padding: 0.2em 0 !important;\
}\
\
.__MonkeyConfig_field_number {\
    width: 5em !important;\
}\
\
div.__MonkeyConfig_container td.__MonkeyConfig_buttons table {\
    border-top: solid 1px #999 !important;\
    width: 100% !important;\
}\
\
div.__MonkeyConfig_container td.__MonkeyConfig_buttons td {\
    padding: 0.6em 0.3em 0.1em 0.3em !important;\
    text-align: center !important;\
    vertical-align: top;\
}\
\
div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\
    appearance: button !important;\
    -moz-appearance: button !important;\
    background-position: 8px 50% !important;\
    background-repeat: no-repeat !important;\
    padding: 3px 8px 3px 24px !important;\
    padding: 3px 8px !important;\
    white-space: nowrap !important;\
}\
\
div.__MonkeyConfig_container td.__MonkeyConfig_buttons button img {\
    vertical-align: middle !important;\
}\
\
div.__MonkeyConfig_layer {\
    display: table !important;\
    position: fixed !important;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container,\
body.__MonkeyConfig_body > div.__MonkeyConfig_container {\
    background: #eee linear-gradient(180deg,\
        #f8f8f8 0, #ddd 100%) !important;\
    border-radius: 0.5em !important;\
    box-shadow: 2px 2px 16px #000 !important;\
    color: #000 !important;\
    font-family: sans-serif !important;\
    font-size: 11pt !important;\
    padding: 1em 1em 0.4em 1em !important;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container td,\
div.__MonkeyConfig_layer div.__MonkeyConfig_container label,\
div.__MonkeyConfig_layer div.__MonkeyConfig_container input,\
div.__MonkeyConfig_layer div.__MonkeyConfig_container select,\
div.__MonkeyConfig_layer div.__MonkeyConfig_container textarea,\
div.__MonkeyConfig_layer div.__MonkeyConfig_container button {\
    color: #000 !important;\
    font-family: sans-serif !important;\
    font-size: 11pt !important;\
    line-height: 100% !important;\
    margin: 0 !important;\
    vertical-align: baseline !important;\
}\
\
div.__MonkeyConfig_container label {\
    line-height: 120% !important;\
    vertical-align: baseline !important;\
}\
\
div.__MonkeyConfig_container textarea {\
    vertical-align: text-top !important;\
    width: 100%;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container input[type="text"] {\
    appearance: textfield !important;\
    -moz-appearance: textfield !important;\
    background: #fff !important;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container h1 {\
    font-weight: bold !important;\
    text-align: left !important;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button,\
body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\
    appearance: button !important;\
    -moz-appearance: button !important;\
    background: #ccc linear-gradient(180deg,\
        #ddd 0, #ccc 45%, #bbb 50%, #aaa 100%) !important;\
    border-style: solid !important;\
    border-width: 1px !important;\
    border-radius: 0.5em !important;\
    box-shadow: 0 0 1px #000 !important;\
    color: #000 !important;\
    font-size: 11pt !important;\
}\
\
div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover,\
body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover {\
    background: #d2d2d2 linear-gradient(180deg,\
        #e2e2e2 0, #d2d2d2 45%, #c2c2c2 50%, #b2b2b2 100%) !important;\
}\
\
div.__MonkeyConfig_overlay {\
    background-color: #000 !important;\
    opacity: 0.6 !important;\
    position: fixed !important;\
}\
\
iframe#__MonkeyConfig_frame {\
    border: none !important;\
    box-shadow: 2px 2px 16px #000 !important;\
}\
\
body.__MonkeyConfig_body {\
    margin: 0 !important;\
    padding: 0 !important;\
}\
\
embed, iframe, object {\
    max-width: 200% !important;\
    width: 167% !important;\
}\
'
};