Title manager

Manage page titles per (sub)domain. Shift-T-M for options.

当前为 2014-03-14 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Title manager
// @namespace   grom
// @description Manage page titles per (sub)domain. Shift-T-M for options.
// @include     http*
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @version     1.0.20140314
// @run-at      document-end
// ==/UserScript==


if ( GM_getValue === 'undefined' || GM_setValue === 'undefined' ) {
  alert('=== Title Manager ===\n\nUnable to load or store values.\
  \nPlease use supported script managers:\nGreasemonkey, Tampermonkey...');
}

var domains = GM_getValue('domains-deletable-buffer', '') || GM_getValue('domains', '').replace(/\./g, '\\.'),
    match = window.location.host.toLowerCase().match(domains),
    t = document.getElementsByTagName('title')[0],
    tOriginal = '';

if (match) {
  var _find = GM_getValue(match[0] + '-find', '');
    if (_find.match(/^regex:/)) {
      var _find = _find.replace(/^regex:/, '');
      var _find = new RegExp(_find, 'i');
    }
  var _with = GM_getValue(match[0] + '-with', '');
}
if (t) {
  var tOriginal = t.innerHTML;
  if (_find) t.innerHTML = t.innerHTML.replace(_find, _with);
}

function tm_add(StrReg, escape, isItImport, _domain, _find, _with) {
  // StrReg: is "Search for" string or regex - 'str' or 'reg'
  // escape: escape dollar signs or not - 'escape' or 'noescape'
  var d = document,
      _domainCheck = /^[a-z0-9_\.-]+$/,
      tm_error = d.getElementById('tm-error-notifier');
  if (!isItImport) {
    var _domain = d.getElementById('tm-domain').value.toLowerCase();
    var _find = d.getElementById('tm-find').value;
    var _with = d.getElementById('tm-with').value;
  }
  if (!_domain.match(_domainCheck)) {
    tm_error.innerHTML = 'Domain invalid. Please use letters a-z, numbers 0-9, underscore _, minus - or dot .';
    return;
  }
  // if "Search for" is regex, make sure it starts with "regex:"
  if (StrReg == 'reg') {
    if (!_find.match(/^regex:/)) _find = _find.replace(/^/, 'regex:');
  }
  // store values, if "domain" and "Search for" are valid
  if (_find) { // we don't need to check for _domain, we passed _domainCheck
    var domains = GM_getValue('domains', '');
    if (!domains) {
      GM_setValue('domains', _domain);
    }
    else {
      var match = _domain.replace(/\./g, '\\.');
      var match = new RegExp('(^|\\|)' + match + '($|\\|)');
      if (!domains.match(match)) {
        var domains = domains + '|' + _domain;
        GM_setValue('domains', domains);
      }
    }
    GM_setValue(_domain + '-find', _find);
    if (_with) {
      // if not adding as regex, escape dollar signs
      if (escape == 'escape') var _with = _with.replace(/\$/g, '$$$$');
      GM_setValue(_domain + '-with', _with);
    }
    else if (GM_getValue(_domain + '-with', '')) GM_deleteValue(_domain + '-with');
    // if not in importing loop, create buffer for domains
    if (!isItImport) {
      var domainsDeletableBuffer = GM_getValue('domains', '').replace(/\./g, '\\.');
      GM_setValue('domains-deletable-buffer', domainsDeletableBuffer);
      tm_error.innerHTML = 'Success! Rule added.';
    }
  }
}

function tm_manage() {
  var d = document;
  d.documentElement.innerHTML = '';
  var domains = GM_getValue('domains', '');
  if (domains) {
    var domains = domains.split('|');
    for(var i = 0, j = domains.length; i < j; i++) {
      var _find = GM_getValue(domains[i] + '-find', '');
      var _with = GM_getValue(domains[i] + '-with', '');
      var box = d.createElement('pre');
      box.className = 'item';
      box.innerHTML = '<span>' + domains[i] + '</span><br /><span>' + _find + '</span>\
<br /><span>' + _with + '</span><br /><button>Remove</button><br /><span>========</span>';
      if (d.body) d.body.appendChild(box);
      else d.documentElement.appendChild(box);
      box.getElementsByTagName('button')[0].addEventListener('click', tm_remove);
    }
  }
  // import
  var impList = d.createElement('textarea');
  impList.id = 'tm-import-list';
  d.documentElement.appendChild(impList);
  var imp = d.createElement('input');
  imp.type = 'submit'; imp.id = 'tm-import'; imp.value = 'Import';
  d.documentElement.appendChild(imp);
  imp.addEventListener('click', tm_import);
  // sort button if 2 or more domains
  if (domains.length>1) {
    var sor = d.createElement('input');
    sor.type = 'submit'; sor.id = 'tm-sort'; sor.value = 'Sort';
    d.documentElement.appendChild(sor);
    sor.addEventListener('click', tm_sort);
  }
}

function tm_remove() {
  var item = this.parentNode;
  var _domain = item.getElementsByTagName('span')[0].innerHTML;
  GM_deleteValue(_domain + '-find');
  GM_deleteValue(_domain + '-with');
  var domains = GM_getValue('domains', '');
  var match = _domain.replace(/\./g, '\\.');
  // match: (^ or |) + single/current domain + ($ or |)
  var match = new RegExp('(^|\\|)' + match + '($|\\|)');
  // replace: matched single domain with ^ or |; replace: || with | or remove |$
  var domains = domains.replace(match, '$1').replace(/(\|)\||\|$/g, '$1');
  GM_setValue('domains', domains);
  item.parentNode.removeChild(item);
}

function tm_import() {
  var d = document,
      list = d.getElementById('tm-import-list').value;
  var list = list.match(/.+/g).join('--------').replace(/(--------)+========$/, '').split('========--------');
  for(var i = 0, j = list.length; i < j; i++) {
    var listB = list[i].split('--------');
    if (listB[0] && listB[1]) tm_add('str', 'noescape', 'true', listB[0], listB[1], listB[2]);
  }
  // create buffer for domains, refresh page
  var domainsDeletableBuffer = GM_getValue('domains', '').replace(/\./g, '\\.');
  GM_setValue('domains-deletable-buffer', domainsDeletableBuffer);
  tm_manage();
}

function tm_sort() {
  GM_setValue('domains', GM_getValue('domains', '').split('|').sort().join('|'));
  GM_setValue('domains-deletable-buffer', GM_getValue('domains', '').replace(/\./g, '\\.'));
  tm_manage();
}

function tm_QuickMenu() {
  var d = document,
      box = d.createElement('div'),
      isThere = d.getElementById('grom-TitleManager');
  if (isThere) {
    isThere.parentNode.removeChild(isThere);
    return;
  }
  box.style = 'text-align:center!important;';
  box.id = 'grom-TitleManager';
  box.innerHTML = '<br /><hr><h1 style="margin:initial!important;">Title Manager</h1><p>Full title: "<strong>' + tOriginal + '</strong>"</p>\
<p id="tm-error-notifier">Regex supported only in "Search for"; use single backslash <strong>\\</strong> for escaping characters.</p>\
<p>Domain: <input type="text" id="tm-domain" value="' + window.location.host.toLowerCase() + '" /></p>\
<p>Search for: <input type="text" id="tm-find" value="' + tOriginal + '" /></p>\
<p>Replace with: <input type="text" id="tm-with" value="" /></p>\
<p><input type="submit" id="tm-add" value="Add" /> or <input type="submit" id="tm-add-regex" value="Add as regex" /></p>\
<p><input type="submit" id="tm-manage" value="View and manage all title rules" /></p><br /><br />';
  if (d.body) d.body.appendChild(box);
  else d.documentElement.appendChild(box);
  box.scrollIntoView();
  d.getElementById('tm-add').addEventListener('click', function() { tm_add('str','escape') });
  d.getElementById('tm-add-regex').addEventListener('click', function() { tm_add('reg','noescape') });
  d.getElementById('tm-manage').addEventListener('click', tm_manage);
}

// trigger for QuickMenu: Shift+T+M
var kbd = [];
onkeydown = onkeyup = function(e) {
  kbd[e.keyCode] = e.type == 'keydown';
  if (kbd[16] && kbd[84] && kbd[77]) {
    tm_QuickMenu();
    kbd = [];
    return false;
  }
}