WME Bookmarklets

Put bookmarklets in a tab and provide a better code execution environment

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name        WME Bookmarklets
// @author      Tom 'Glodenox' Puttemans
// @namespace   http://www.tomputtemans.com/
// @description Put bookmarklets in a tab and provide a better code execution environment
// @include     /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
// @version     1.0.7
// @grant       none
// ==/UserScript==
(function() {
  var bookmarklets = [];
  if (localStorage.WME_Bookmarklets) {
    importBookmarklets(JSON.parse(localStorage.WME_Bookmarklets).bookmarklets);
  }

  function init(e) {
    if (e && e.user == null) {
      return;
    }
    if (document.getElementById('user-info') == null) {
      setTimeout(init, 500);
      log('user-info element not yet available, page still loading');
      return;
    }
    if (typeof W.loginManager === 'undefined') {
      setTimeout(init, 300);
      return;
    }
    if (!W.loginManager.user) {
      W.loginManager.events.register('login', null, init);
      W.loginManager.events.register('loginStatus', null, init);
      // Double check as event might have triggered already
      if (!W.loginManager.user) {
        return;
      }
    }

    var bookmarklets_strings = {
      en: {
        tab_title: 'Bookmarklets',
        add_bookmarklet: 'Add bookmarklet',
        empty_list: 'No bookmarklets added yet',
        bookmarklet_name: 'Name',
        bookmarklet_script: 'Script',
        bookmarklet_error: 'Bookmarklet threw an error',
        message: 'Activate a bookmarklet or add a new one:',
        bookmarklet_sources: 'Many Wazers have created bookmarklets to perform small tasks within the WME. Most of these can be found on <a href="https://wiki.waze.com/wiki/Bookmarklets" target="_blank">the wiki</a> or by <a href="https://www.waze.com/forum/search.php?keywords=Bookmarklet&terms=all&sv=0&sc=1&sf=all&sr=posts&sk=t&sd=d&st=0&ch=300&t=0&submit=Search" target="_blank">seaching the forums</a>.',
        bookmarklet_remove: 'Remove bookmarklet'
      }
    };
    setTranslations(bookmarklets_strings);

    var tab = addTab();
    var message = document.createElement('p');
    message.appendChild(document.createTextNode(I18n.t('bookmarklets.message')));
    tab.appendChild(message);

    var emptyList = document.createElement('span');
    emptyList.id = 'emptyBookmarklets';
    emptyList.style.fontStyle = 'italic';
    emptyList.style.display = (bookmarklets.length == 0 ? 'block' : 'none');
    emptyList.appendChild(document.createTextNode(I18n.t('bookmarklets.empty_list')));
    tab.appendChild(emptyList);

    var bookmarkletList = document.createElement('div');
    bookmarkletList.className = 'result-list';
    bookmarkletList.style.marginBottom = '1em';
    bookmarklets.forEach(function(bookmarklet) {
      addBookmarklet(bookmarklet);
    });
    tab.appendChild(bookmarkletList);

    var addBookmarkletForm = document.createElement('form');
    var addBookmarkletTitle = document.createElement('h4');
    addBookmarkletTitle.appendChild(document.createTextNode(I18n.t('bookmarklets.add_bookmarklet')));
    addBookmarkletForm.appendChild(addBookmarkletTitle);
    addBookmarkletForm.style.display = 'none';
    var nameGroup = document.createElement('div');
    nameGroup.className = 'form-group';
    var nameFieldLabel = document.createElement('label');
    nameFieldLabel.htmlFor = 'name';
    nameFieldLabel.appendChild(document.createTextNode(I18n.t('bookmarklets.bookmarklet_name')));
    nameGroup.appendChild(nameFieldLabel);
    var nameField = document.createElement('input');
    nameField.type = 'text';
    nameField.autocomplete = 'off';
    nameField.style.width = '100%';
    nameField.name = 'name';
    nameField.className = 'from-control';
    nameGroup.appendChild(nameField);
    addBookmarkletForm.appendChild(nameGroup);
    var scriptGroup = document.createElement('div');
    scriptGroup.className = 'form-group';
    var scriptFieldLabel = document.createElement('label');
    scriptFieldLabel.htmlFor = 'script';
    scriptFieldLabel.appendChild(document.createTextNode(I18n.t('bookmarklets.bookmarklet_script')));
    scriptGroup.appendChild(scriptFieldLabel);
    var scriptField = document.createElement('textarea');
    scriptField.name = 'script';
    scriptField.className = 'from-control';
    scriptField.style.width = '100%';
    scriptField.style.height = 'auto';
    scriptGroup.appendChild(scriptField);
    addBookmarkletForm.appendChild(scriptGroup);
    var createBookmarklet = document.createElement('input');
    createBookmarklet.type = 'submit';
    createBookmarklet.className = 'btn btn-default';
    createBookmarklet.value = I18n.t('bookmarklets.add_bookmarklet');
    addBookmarkletForm.appendChild(createBookmarklet);

    var addBookmarkletButton = document.createElement('button');
    addBookmarkletButton.className = 'btn btn-default';
    var addSpan = document.createElement('span');
    addSpan.appendChild(document.createTextNode(''));
    addSpan.className = 'fa';
    addSpan.style.marginRight = '5px';
    addBookmarkletButton.appendChild(addSpan);
    addBookmarkletButton.appendChild(document.createTextNode(I18n.t('bookmarklets.add_bookmarklet')));
    addBookmarkletButton.addEventListener('click', function() {
      addBookmarkletButton.style.display = 'none';
      addBookmarkletForm.style.display = 'block';
    });
    tab.appendChild(addBookmarkletButton);
    tab.appendChild(addBookmarkletForm);
    addBookmarkletForm.addEventListener('submit', function(e) {
      e.preventDefault();
      addBookmarkletForm.style.display = 'none';
      addBookmarkletButton.style.display = 'block';
      var newBookmarklet = {};
      newBookmarklet.name = nameField.value;
      newBookmarklet.script = scriptField.value;
      addBookmarklet(newBookmarklet);
      bookmarklets.push(newBookmarklet);
      saveBookmarklets();
      return false;
    }, true);

    var bookmarkletSources = document.createElement('p');
    bookmarkletSources.innerHTML = I18n.t('bookmarklets.bookmarklet_sources');
    bookmarkletSources.style.marginTop = '1em';
    tab.appendChild(bookmarkletSources);
    var versionInfo = document.createElement('a');
    versionInfo.appendChild(document.createTextNode(GM_info.script.name + ' (v' + GM_info.script.version + ')'));
    versionInfo.href = 'https://greasyfork.org/nl/scripts/20379-wme-bookmarklets/';
    versionInfo.target = '_blank';
    tab.appendChild(versionInfo);

    // Create a tab and possibly receive a previous tab to restore (usually in case of a mode change)
    function addTab(recoveredTab) {
      var userInfo = document.getElementById('user-info'),
          tabHandles = userInfo.querySelector('.nav-tabs'),
          tabs = userInfo.querySelector('.tab-content'),
          tabHandle = document.createElement('li'),
          tab = document.createElement('div');
      tabHandle.innerHTML = '<a href="#sidepanel-bookmarklets" data-toggle="tab" title="' + I18n.t('bookmarklets.tab_title') + '"><span class="fa"></span></a>';
      if (recoveredTab) {
        tab = recoveredTab;
      } else {
        tab.id = 'sidepanel-bookmarklets';
        tab.className = 'tab-pane';
      }
      tabHandles.appendChild(tabHandle);
      $(tabHandle.childNodes[0]).tooltip();
      tabs.appendChild(tab);
      return tab;
    }

    function addBookmarklet(bookmarklet) {
      document.getElementById('emptyBookmarklets').style.display = 'none';
      var bookmarkletContainer = document.createElement('div');
      bookmarkletContainer.className = 'result session-available';
      var bookmarkletRemove = document.createElement('button');
      bookmarkletRemove.style.position = 'absolute';
      bookmarkletRemove.style.display = 'none';
      bookmarkletRemove.style.fontSize = '14px';
      bookmarkletRemove.style.top = '4px';
      bookmarkletRemove.style.right = '4px'
      bookmarkletRemove.className = 'btn btn-default fa';
      bookmarkletRemove.addEventListener('click', function(e) {
        e.stopPropagation();
        removeBookmarklet(bookmarklet);
      });
      bookmarkletRemove.appendChild(document.createTextNode(''));
      bookmarkletRemove.title = I18n.t('bookmarklets.bookmarklet_remove');
      $(bookmarkletRemove).tooltip();
      bookmarkletContainer.appendChild(bookmarkletRemove);
      bookmarkletContainer.addEventListener('mouseenter', function() {
        bookmarkletRemove.style.display = 'block';
      });
      bookmarkletContainer.addEventListener('mouseleave', function() {
        bookmarkletRemove.style.display = 'none';
      });
      var bookmarkletName = document.createElement('div');
      bookmarkletName.appendChild(document.createTextNode(bookmarklet.name));
      bookmarkletContainer.appendChild(bookmarkletName);
      var bookmarkletError = document.createElement('div');
      bookmarkletError.style.display = 'none';
      bookmarkletError.style.backgroundColor = 'red';
      bookmarkletError.style.color = '#f2dede';
      bookmarkletError.style.border = '2px solid #f2dede';
      bookmarkletError.style.padding = '4px';
      bookmarkletError.style.margin = '4px 0 4px 0';
      bookmarkletContainer.appendChild(bookmarkletError);
      var bookmarkletErrorClose = document.createElement('button');
      bookmarkletErrorClose.style.fontFamily = 'FontAwesome';
      bookmarkletErrorClose.style.color = '#f2dede';
      bookmarkletErrorClose.style.border = 'none';
      bookmarkletErrorClose.style.background = 'none';
      bookmarkletErrorClose.style.padding = '3px';
      bookmarkletErrorClose.style.float = 'right';
      bookmarkletErrorClose.style.cursor = 'pointer';
      bookmarkletErrorClose.style.height = 'auto';
      bookmarkletErrorClose.style.outline = 'none';
      bookmarkletErrorClose.appendChild(document.createTextNode(''));
      bookmarkletError.addEventListener('click', function(e) {
        e.stopPropagation();
        bookmarkletError.style.display = 'none';
      }, true);
      bookmarkletError.appendChild(bookmarkletErrorClose);
      var bookmarkletErrorTitle = document.createElement('strong');
      bookmarkletErrorTitle.appendChild(document.createTextNode(I18n.t('bookmarklets.bookmarklet_error')));
      bookmarkletError.appendChild(bookmarkletErrorTitle);
      bookmarkletError.appendChild(document.createElement('br'));
      bookmarkletContainer.addEventListener('click', function() {
        try {
          var cleanedUpScript = decodeURI(bookmarklet.script);
          cleanedUpScript = cleanedUpScript.replace('javascript:', '');
          eval(cleanedUpScript);
        } catch (e) {
          log(e);
          if (bookmarkletError.childNodes[3]) { // Remove previous error message
            bookmarkletError.removeChild(bookmarkletError.childNodes[3]);
          }
          bookmarkletError.appendChild(document.createTextNode((e && e.message ? e.message : e)));
          bookmarkletError.style.display = 'block';
        }
      });
      bookmarkletList.appendChild(bookmarkletContainer);
      bookmarklet.container = bookmarkletContainer;
    }

    function removeBookmarklet(bookmarklet) {
      var idx = bookmarklets.indexOf(bookmarklet);
      if (idx > -1) {
        bookmarklets.splice(idx, 1);
      }
      saveBookmarklets();
      bookmarkletList.removeChild(bookmarklet.container);
      if (bookmarklets.length == 0) {
        document.getElementById('emptyBookmarklets').style.display = 'block';
      }
    }
  }

  function setTranslations(translations) {
    I18n.translations[I18n.currentLocale()].bookmarklets = translations.en;
    for (var i = 0; i < Object.keys(translations).length; i++) {
      var locale = Object.keys(translations)[i];
      if (I18n.currentLocale() == locale) {
        I18n.translations[locale].bookmarklets = translations[locale];
        return;
      }
    }
  }

  function importBookmarklets(data) {
    data.forEach(function(bookmarklet) {
      bookmarklets.push(bookmarklet);
    });
  }

  function saveBookmarklets() {
    var storage;
    if (typeof localStorage.WME_Bookmarklets == 'undefined') {
      storage = {};
    } else {
      storage = JSON.parse(localStorage.WME_Bookmarklets);
    }
    storage.bookmarklets = bookmarklets.map(function(bookmarklet) {
      return {
        'name': bookmarklet.name,
        'script': bookmarklet.script
      };
    });
    localStorage.WME_Bookmarklets = JSON.stringify(storage);
  }

  function log(message) {
    if (typeof message === 'string') {
      console.log('%c' + GM_info.script.name + ' (v' + GM_info.script.version + '): %c' + message, 'color:black', 'color:#d97e00');
    } else {
      console.log('%c' + GM_info.script.name + ' (v' + GM_info.script.version + ')', 'color:black', message);
    }
  }

  init();
})();