Created
October 17, 2014 02:22
-
-
Save marktaiwan/8ad8c48405641490a2b7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
8Chan Formatting Tools | |
- Adds a toolbar above the commenting area containing most of 8Chan's formatting options | |
- Press esc to close quick-reply window | |
- Hover cursor over each button to show availiable shortcut | |
*/ | |
if (active_page == 'thread' || active_page == 'index') { | |
var commentToolFormats = { | |
bold: { | |
displayText: 'B', | |
altText: 'bold', | |
styleCSS: 'font-weight: bold;', | |
options: { | |
prefix: "'''", | |
suffix: "'''" | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
}, | |
shortcutKey: 'b' | |
}, | |
italics: { | |
displayText: 'i', | |
altText: 'italics', | |
styleCSS: 'font-style: italic;', | |
options: { | |
prefix: "''", | |
suffix: "''" | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
}, | |
shortcutKey: 'i' | |
}, | |
under: { | |
displayText: 'U', | |
altText: 'underline', | |
styleCSS: 'text-decoration: underline;', | |
options: { | |
prefix: '__', | |
suffix: '__' | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
}, | |
shortcutKey: 'u' | |
}, | |
spoiler: { | |
displayText: 'spoiler', | |
altText: 'mark as spoiler', | |
styleCSS: '', | |
options: { | |
prefix: '[spoiler]', | |
suffix: '[/spoiler]' | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
}, | |
shortcutKey: 's' | |
}, | |
code: { | |
displayText: 'code', | |
altText: "code formatting", | |
styleCSS: 'font-family: "Courier New", Courier, monospace;', | |
options: { | |
prefix: '[code]', | |
suffix: '[/code]', | |
multiline: true | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
} | |
}, | |
strike: { | |
displayText: 'strike', | |
altText: 'strikethrough', | |
styleCSS: 'text-decoration: line-through;', | |
options: { | |
prefix: '~~', | |
suffix: '~~' | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
} | |
}, | |
heading: { | |
displayText: 'heading', | |
altText: 'redtext', | |
styleCSS: 'color: #AF0A0F; font-weight: bold;', | |
options: { | |
prefix: '==', | |
suffix: '==', | |
exclusiveLine: true | |
}, | |
edit: function (box, options) { | |
wrapSelection(box, options); | |
} | |
} | |
}; | |
(function ($, formats) { | |
'use strict'; | |
var key, name, altText, ele; | |
var strBuilder = []; | |
var subStr = ''; | |
var styleRules = ''; | |
//generate the HTML for the toolbar | |
for (ele in formats) { | |
if (formats.hasOwnProperty(ele) && formats[ele].displayText != null) { | |
name = formats[ele].displayText; | |
altText = formats[ele].altText || ''; | |
key = formats[ele].shortcutKey; | |
//add tooltip text | |
if (altText) { | |
if (key) { | |
altText += ' (ctrl+'+ key +')'; | |
} | |
altText = 'title="'+ altText +'"'; | |
} | |
subStr = '<a href="javascript:void(0)" '+ altText +' id="tf-'+ ele +'">'+ name +'</a>'; | |
strBuilder.push(subStr); | |
} else { | |
continue; | |
} | |
} | |
$( 'textarea[name="body"]' ).before( '<div class="tf-toolbar"></div>' ); | |
$( '.tf-toolbar' ).html( strBuilder.join(' | ') ); | |
/* Sets the CSS style | |
*/ | |
styleRules = '\n/* generated by 8chan Formatting Tools */'+ | |
'\n.tf-toolbar {padding: 0px 5px 1px 5px;}'+ | |
'\n.tf-toolbar :link {text-decoration: none;}'; | |
for (ele in formats) { | |
if (formats.hasOwnProperty(ele) && formats[ele].styleCSS) { | |
styleRules += ' \n#tf-' + ele + ' {' + formats[ele].styleCSS + '}'; | |
} | |
} | |
//add CSS rule to user's custom CSS if it exist | |
if ($( '.user-css' ).length !== 0) { | |
$( '.user-css' ).append( styleRules ); | |
} else { | |
$( 'body' ).append( '<style>'+ styleRules +'\n</style>' ); | |
} | |
/* Attach event listeners | |
*/ | |
$( 'body' ).on( 'keydown', 'textarea[name="body"]', {formats: formats}, function (e) { | |
//shortcuts | |
if (e.ctrlKey) { | |
var ch = String.fromCharCode(e.which).toLowerCase(); | |
var box = e.target; | |
var formats = e.data.formats; | |
for (var ele in formats) { | |
if (formats.hasOwnProperty(ele) && (ch === formats[ele].shortcutKey)) { | |
formats[ele].edit(box, formats[ele].options); | |
e.preventDefault(); | |
} | |
} | |
} | |
}); | |
$( 'body' ).on( 'keydown', '#quick-reply textarea[name="body"]', {formats: formats}, function (e) { | |
//close quick reply when esc is prssed | |
if (e.which === 27) { | |
$( '.close-btn' ).trigger( 'click' ); | |
} | |
}); | |
$( 'body' ).on( 'keydown', function (e) { | |
if (e.which === 67 && | |
e.target.nodeName !== 'INPUT' && //The C, the whole C, and nothing but the C | |
e.target.nodeName !== 'TEXTAREA' && | |
!(e.ctrlKey || e.altKey || e.shiftKey)) { | |
document.location.href = '//'+ document.location.host +'/'+ board_name +'/catalog.html'; | |
} | |
}); | |
$( 'body' ).on( 'click', '.tf-toolbar a[id]', {formats: formats}, function (e) { | |
//toolbar buttons | |
var formats = e.data.formats; | |
var box = $(e.target).parent().next()[0]; | |
for (var ele in formats) { | |
if (formats.hasOwnProperty(ele) && (e.target.id === 'tf-' + ele)) { | |
formats[ele].edit(box, formats[ele].options); | |
} | |
} | |
}); | |
}(jQuery, commentToolFormats)); | |
var wrapSelection = function (box, options) { | |
'use strict'; | |
if (box == null) { | |
return; | |
} | |
var prefix = options.prefix; | |
var suffix = options.suffix; | |
var multiline = options.multiline || false; | |
var exclusiveLine = options.exclusiveLine || false; | |
//record scroll top to restore it later. | |
var scrollTop = box.scrollTop; | |
var selectionStart = box.selectionStart; | |
var selectionEnd = box.selectionEnd; | |
var text = box.value; | |
var beforeSelection = text.substring(0, selectionStart); | |
var selectedText = text.substring(selectionStart, selectionEnd); | |
var afterSelection = text.substring(selectionEnd); | |
var breakSpace = ["\r","\n"]; | |
var trailingSpace = ""; | |
var cursor = selectedText.length - 1; | |
//remove trailing space | |
while (cursor > 0 && selectedText[cursor] === " ") { | |
trailingSpace += " "; | |
cursor--; | |
} | |
selectedText = selectedText.substring(0, cursor + 1); | |
if (!multiline) selectedText = selectedText.replace(/(\r|\n|\r\n)/g, suffix +"$1"+ prefix); | |
if (exclusiveLine) { | |
// buffer the begining of the selection until a linebreak | |
cursor = beforeSelection.length -1; | |
while (cursor >= 0 && breakSpace.indexOf(beforeSelection.charAt(cursor)) == -1) { | |
cursor--; | |
} | |
selectedText = beforeSelection.substring(cursor +1) + selectedText; | |
beforeSelection = beforeSelection.substring(0, cursor +1); | |
// buffer the end of the selection until a linebreak | |
cursor = 0; | |
while (cursor < afterSelection.length && breakSpace.indexOf(afterSelection.charAt(cursor)) == -1) { | |
cursor++; | |
} | |
selectedText += afterSelection.substring(0, cursor); | |
afterSelection = afterSelection.substring(cursor); | |
} | |
box.value = beforeSelection + prefix + selectedText + suffix + trailingSpace + afterSelection; | |
box.selectionEnd = beforeSelection.length + prefix.length + selectedText.length; | |
if (selectionStart === selectionEnd) { | |
box.selectionStart = box.selectionEnd; | |
} else { | |
box.selectionStart = beforeSelection.length + prefix.length; | |
} | |
box.scrollTop = scrollTop; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment