WBB Quick Reply Plus

Adds More formatting buttons to Quick/Standard Reply

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name          WBB Quick Reply Plus
// @namespace     erosman
// @description   Adds More formatting buttons to Quick/Standard Reply
// @include       http://www.warez-bb.org/viewtopic.php*
// @include       http://www.warez-bb.org/posting.php*
// @include       http://www.warez-bb.org/privmsg.php*
// @exclude       http://www.warez-bb.org/privmsg.php?folder=*
// @include       https://www.warez-bb.org/viewtopic.php*
// @include       https://www.warez-bb.org/posting.php*
// @include       https://www.warez-bb.org/privmsg.php*
// @exclude       https://www.warez-bb.org/privmsg.php?folder=*
// @grant         none
// @author        erosman
// @version       1.8
// ==/UserScript==


/* --------- Note ---------
  This script adds more formatting options (B, i, u, List, List=) to the Quick Reply Box
  as well as Quote=, Font Size & Font Colour
  Also new functionality of 'RemoveTag', 'To Uppercase', 'To Lowercase' & 'TitleCase'
  Script now adds the functionality to Quick Reply, Normal Reply with/without Quote,
  PM reply and their Preview pages


  --------- History ---------

  1.8 Code rewrite + New DOM insertion method + Removed 'List=' since it is not supported on WBB
      + Added [*] + Added BB2 compatibility
  1.7 Code Improvement
  1.6 Code Improvement + Removed Capitalize (can be done with TitleCase)
  1.5 New RemoveTags function + Minor CSS change
  1.4 Code Improvement + Added Quote= (which is valid but is missing from phpBB inputs)
      + Added Font Size + Added Font Colour
  1.3 Code Improvement + Added PM pages
  1.2 Added TitleCase and new functions + Added script to reply page + Preview page
      + Error checking on phpBB post redirect page
  1.1 Added toLower, toUpper & Capitalize
  1.0 Initial release

*/


(function() { // anonymous function wrapper, used for error checking & limiting scope
'use strict'; // ECMAScript 5
if (frameElement) { return; } // end execution if in a frame, object or other embedding points

var BB3 = document.querySelector('link[href*="main.css"]') ? true : false; // BB2/BB3 check

var textarea = document.getElementById('message');
if (!textarea) { return; }  // end execution if not found

var bbcode = BB3 ? document.querySelector('div.bbcode') : textarea.parentNode;
if (!bbcode) { return; }  // end execution if not found


function makeChange() {

  var obj = textarea;
  obj.selectionEnd = obj.selectionEnd > obj.value.length ? obj.value.length : obj.selectionEnd;
  var startPos = obj.selectionStart;
  var endPos = obj.selectionEnd > obj.selectionStart ? obj.selectionEnd : obj.selectionStart;
  var openTaglength = 0;
  var tagLength = 0;
  var theSelection = obj.value.substring(startPos, endPos);
  var noSelection = 'Nothing was selected';
  var addTag = false;
  var tag, startTag, endTag;

  switch (this.value) {

    /* Actions */
    case 'toLower':
      theSelection.trim() ? theSelection = theSelection.toLowerCase() : alert(noSelection);
      break;
    case 'toUpper':
      theSelection.trim() ? theSelection = theSelection.toUpperCase() : alert(noSelection);
      break;
    case 'TitleCase':
      theSelection.trim() ? theSelection = toTitleCase(theSelection) : alert(noSelection);
      break;

    case 'RemoveTag':
      if (theSelection.trim()) {
        var ret = removeTag(theSelection);
        theSelection = ret[0];
        tagLength = ret[1];
      }
      else { alert(noSelection); }
      break;

    /* Tags */
    case 'B':
    case 'i':
    case 'u':
    case 'List':
      tag = this.value.toLowerCase();
      startTag = '[' + tag + ']';
      endTag = '[/' + tag + ']';
      addTag = true;
      break;

//    case 'List=':
    case 'Quote=':
      tag = this.value.toLowerCase();
      startTag = '[' + tag + '""]';
      endTag = '[/' + tag.slice(0, -1) + ']';
      addTag = true;
      break;

    case '[*]':
      startTag = this.value;
      endTag = '';
      addTag = true;
      break;

    default: // select options
      startTag = '[' + this.id + '=' + this.value + ']';
      endTag = '[/' + this.id + ']';
      addTag = true;
      this.selectedIndex = this.id === 'color' ? 0 : 2;
  }

  if (addTag) {
    theSelection = startTag + theSelection + endTag;
    openTaglength = startTag.length;
  }

  obj.value = obj.value.substring(0,startPos) + theSelection + obj.value.substring(endPos);
  obj.selectionStart = startPos + openTaglength;
  obj.selectionEnd = endPos + openTaglength - tagLength;
  obj.focus();
}

function toTitleCase(txt) {
  return txt.replace(/\w\S*/g,
    function (str) {
      return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
    });
}

function removeTag(txt) {
  var pat = /\[\/?(b|i|u|img|code|quote[^\]]*|\*|list[^\]]*|color[^\]]*|size[^\]]*)\]/gi;
  return [txt.replace(pat, ''), (txt.match(pat) || []).join('').length];
}

/* ----- Inputs ----- */
var buttons1 = [

  { value: 'Quote=', class: 'first-button' },
  { value: 'RemoveTag' },
  { value: 'toLower'},
  { value: 'toUpper' },
  { value: 'TitleCase', class: 'last-button' },
];

var buttons2 = [

  { accesskey: 'b', value: 'B', style: 'font-weight: bold;', class: 'first-button' },
  { accesskey: 'i', value: 'i', style: 'font-style: italic;' },
  { accesskey: 'u', value: 'u', style: 'text-decoration: underline;' },
  { accesskey: 'l', value: 'List' },
  { value: '[*]', class: 'last-button' },
//  { accesskey: 'o', value: 'List=', class: 'last-button' },

];

var options1 = [ // Font colour:

  { value: '#', textContent: 'Default' },
  { value: 'darkred', textContent: 'Dark Red', style: 'color: darkred;' },
  { value: 'red', textContent: 'Red', style: 'color: red;' },
  { value: 'orange', textContent: 'Orange', style: 'color: orange;' },
  { value: 'brown', textContent: 'Brown', style: 'color: brown;' },
  { value: 'yellow', textContent: 'Yellow', style: 'color: yellow;' },
  { value: 'green', textContent: 'Green', style: 'color: green;' },
  { value: 'olive', textContent: 'Olive', style: 'color: olive;' },
  { value: 'cyan', textContent: 'Cyan', style: 'color: cyan;' },
  { value: 'blue', textContent: 'Blue', style: 'color: blue;' },
  { value: 'darkblue', textContent: 'Dark Blue', style: 'color: darkblue;' },
  { value: 'indigo', textContent: 'Indigo', style: 'color: indigo;' },
  { value: 'violet', textContent: 'Violet', style: 'color: violet;' },
  { value: 'white', textContent: 'White', style: 'color: white;' },
  { value: 'black', textContent: 'Black', style: 'color: black;' },
];

var options2 = [ // Font size:

  { value: 7, textContent: 'Tiny' },
  { value: 9, textContent: 'Small' },
  { value: 12, textContent: 'Normal',  selected: 'selected'},
  { value: 18, textContent: 'Large' },
  { value: 24, textContent: 'Huge' },
];


function addNode(obj, templateNode, parentNode) {

  var node = templateNode.cloneNode(false);
  if (node.nodeName === 'INPUT') { node.addEventListener('click', makeChange, false); }

  for (var prop in obj) {
    prop === 'textContent' ? node.textContent = obj[prop] : node.setAttribute(prop, obj[prop]);
  }
  parentNode.appendChild(node);
}


// insert the extra elements in the page

/* ----- templates ----- */
var br = document.createElement('br');
br.setAttribute('style', 'clear: both;');
var input = document.createElement('input');
input.type = 'button';
// empty DocumentFragment object as a temporary container for the elements
var docfrag = document.createDocumentFragment();

if (!BB3) { docfrag.appendChild(br.cloneNode(false)); } // BB2 only

// All Pages (View Topic +  Post)
for (var i = 0, len = buttons1.length; i < len; i++) { addNode(buttons1[i], input, docfrag); }

// View Topic Pages
if (document.URL.indexOf('viewtopic.php') !== -1) {

  // template
  var select = document.createElement('select');
  select.setAttribute('style', 'padding: 0;');
  var option = document.createElement('option');

  docfrag.appendChild(br.cloneNode(false));
  for (var i = 0, len = buttons2.length; i < len; i++) { addNode(buttons2[i], input, docfrag); }

  docfrag.appendChild(document.createTextNode('\u00A0 Font colour: ')); // \u00A0 non-breaking space
  var select1 = select.cloneNode(false);
  select1.id = 'color';
  select1.addEventListener('change', makeChange, false);
  //select1.setAttribute('onchange', "this.selectedIndex=0;");
  for (var i = 0, len = options1.length; i < len; i++) { addNode(options1[i], option, select1); }
  docfrag.appendChild(select1);

  docfrag.appendChild(document.createTextNode('\u00A0  Font size: ')); // \u00A0 non-breaking space
  var select2 = select.cloneNode(false);
  select2.id = 'size';
  select2.addEventListener('change', makeChange, false);
  for (var i = 0, len = options2.length; i < len; i++) { addNode(options2[i], option, select2); }
  docfrag.appendChild(select2);
}

bbcode.appendChild(docfrag);


})(); // end of anonymous function