NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name SDMB Editor shortcuts // @namespace http://tampermonkey.net/ // @version 0.95 // @description Adds better keyboard shortcuts for the post editor, even on Chrome // @author BigT@SDMB // @match *://boards.straightdope.com/sdmb/showthread.php* // @match *://boards.straightdope.com/sdmb/newreply.php* // @match *://boards.straightdope.com/sdmb/private.php* // @grant none // @license MIT // ==/UserScript== var keytest = false; if (keytest) { window.alert('keytest active'); } var vB_Editor = window.vB_Editor || window.wrappedJSObject.vB_Editor; var editorID = Object.keys(vB_Editor)[0]; var textbox = document.getElementById(editorID + '_textarea'); var buttonList = { undo: ['undo', 'Shift-Z', 'Shift-Z) (works on formatting'], redo: ['redo', 'Shift-Y', 'Shift-Y) (works on formatting'], bold: ['Bold', 'B'], italic: ['Italic', 'I'], underline: ['Underline', 'U'], createlink: ['Insert link', 'K'], wrap0_quote: ['Wrap [QUOTE] tags around selected text', 'Q'], removeformat: ['Remove text formatting', ' ', 'Space'], resize_0_: ['Decrease size' + ((editorID == 'vB_Editor_001') ? '100' : '99'), 'ARROWUP', 'Up'], resize_1_: ['Increase size' + ((editorID == 'vB_Editor_001') ? '100' : '99'), 'ARROWDOWN', 'Down'], justifyleft: ['justifyleft', 'L'], justifyright: ['justifyright', 'R'], justifycenter: ['justifycenter', 'E'], insertorderedlist: ['insertorderedlist', '1'], insertunorderedlist: ['insertunorderedlist', 'Shift-L'], indent: ['indent', 'M'], unlink: ['unlink', 'Shift-K'], outdent: ['outdent', 'Shift-M'], wrap0_code: ['wrap0_code','3','#', 'Shift-#'], wrap0_php: ['wrap0_php','H'], wrap0_del: ['wrap0_del', 'S'], switchmode: ['switchmode', 'Shift-S'] }; applyTooltips(buttonList, editorID); textbox.addEventListener('keydown', function(key) { keyCheck(key, editorID);} ); /* Doesn't work applyEditButton(); function applyEditButton() { var editButton = document.querySelector('[alt="Edit/Delete Message"]'); if (editButton) { var postEditorID = editButton.parentNode.name.split('::')[2]; var postEditor = document.getElementById('post_message_' + postEditorID); editButton.addEventListener('click', function() { console.warn('Edit button clicked'); var observer = new MutationObserver(function() { applyEditbox(postEditor); observer.disconnect(); }); observer.observe(postEditor, { childList: true }); }/*, { once: true }*//*); } var submitButton = document.getElementById('qr_submit'); if (submitButton) { submitButton.addEventListener('click', function() { console.warn('"Post Quick Reply" pressed'); var observer = new MutationObserver( function() { applyEditButton(); observer.disconnect(); }); observer.observe(postEditor, { childList: true }); }); } } END doesn't work */ function applyTooltips(buttonList, editorID) { //window.fakeConsole = ''; for (let command in buttonList) { let buttonID = buttonList[command]; let element = document.getElementById(editorID + '_cmd_' + command); //fakeConsole += command + '\n'; if (element) { if (!element.firstChild.title) { element.firstChild.title = buttonID[0]; } //[0] = tooltip if (element.firstChild.title.search('Ctrl-') === -1) { element.firstChild.title += ' (Ctrl-' + (buttonID[2] ? buttonID[2] : buttonID[1]) + ')'; } } } //alert(fakeConsole); } function keyCheck(event, editorID){ var finished; if (event.ctrlKey) { var keypress = (event.shiftKey ? 'Shift-' : '') + event.key.toUpperCase(); for (let button in buttonList) { let key = buttonList[button]; if (keypress === key[1] || keypress === key[2] || keypress === key[3]) { vB_Editor[editorID].format(new Event('click'), button); event.preventDefault(); event.stopPropagation(); finished = true; break; } } } else if (event.altKey && !event.ShiftKey && !event.CtrlKey && event.key.toUpperCase() === 'S') { var submitButton = document.getElementById('qr_submit'); if (submitButton) { submitButton.dispatchEvent('click'); event.preventDefault(); event.stopPropagation(); finished = true; } } if (keytest && !finished && event.key !== 'Control' && event.key !== 'Shift' && event.key !== 'Alt') { let Ctrl = event.ctrlKey ? 'Ctrl-' : '', Alt = event.altKey ? 'Alt-' : '', Shift = event.shiftKey ? 'Shift-' : '', Key = event.key.search(/^[a-z]$/) !== -1 ? event.key.toUpperCase() + ' (lowercase)' : event.key; if (Ctrl || Alt || event.key.search(/^[\w `\-=[\]\\;',./!@#$%^&*()+{}:"<>?]$/) === -1) { console.warn(Ctrl + Alt + Shift + Key); if (Key !== 'Backspace' && Key !== 'Enter') { event.preventDefault(); event.stopPropagation(); } } } } function applyEditbox(postEditor) { var editorID; var editbox = postEditor.getElementsByTagName('textarea')[0]; if (editbox) { editorID = editbox.id.split('_textarea')[0]; } applyTooltips(buttonList, editorID); editbox.addEventListener('keydown', function (key) { keyCheck(key, editorID); }); var observer2 = new MutationObserver(function () { applyWysiwyg(editorID); observer2.disconnect(); }); observer2.observe(editbox.parentNode, { childList: true }); } // ---Apply to WYSIWYG editor, too.--- function applyWysiwyg(editorID) { //alert('applyWysiwyg() fired'); var wysiwyg = document.getElementById(editorID + '_iframe'); if (wysiwyg) { wysiwyg.contentWindow.document.body.addEventListener('keydown', function(event) { keyCheck(event, editorID); }); } return !!wysiwyg; //true if function worked, false otherwise } if (!applyWysiwyg() && window.MutationObserver) { //don't create observer unnecessarily var observer = new MutationObserver(function () { applyWysiwyg(editorID); observer.disconnect(); } ); observer.observe(textbox.parentNode, { childList: true }); } /**/