start keybinds rewrite

This commit is contained in:
James Campos 2011-04-09 01:09:42 -07:00
parent 34c53d5819
commit 7c7d256f3e
2 changed files with 191 additions and 103 deletions

View File

@ -59,7 +59,7 @@
*/ */
(function() { (function() {
var $, $$, NAMESPACE, a, as, autoWatch, callback, changeCheckbox, changeValue, config, d, delform, el, expand, expandComment, expandThread, g, imageClick, imageExpand, imageExpandClick, imageHover, imageResize, imageThumb, imageToggle, imageType, imageTypeChange, keyModeInsert, keyModeNormal, keydown, keypress, log, nav, navtopr, nodeInserted, omitted, onloadComment, onloadThread, option, options, parseResponse, pathname, qr, recaptcha, recaptchaListener, recaptchaReload, redirect, replyHiding, replyNav, report, request, scroll, scrollThread, span, temp, text, threadHiding, tzOffset, ui, updateAuto, updateCallback, updateFavicon, updateInterval, updateNow, updateTime, updateTitle, updateVerbose, updater, updaterMake, watcher, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _m, _ref, _ref2, _ref3, _ref4; var $, $$, NAMESPACE, a, as, autoWatch, callback, changeCheckbox, changeValue, config, d, delform, el, expand, expandComment, expandThread, g, imageClick, imageExpand, imageExpandClick, imageHover, imageResize, imageThumb, imageToggle, imageType, imageTypeChange, keyModeNormal, keybinds, log, nav, navtopr, nodeInserted, omitted, onloadComment, onloadThread, option, options, parseResponse, pathname, qr, recaptcha, recaptchaListener, recaptchaReload, redirect, replyHiding, replyNav, report, request, scroll, scrollThread, span, temp, text, threadHiding, tzOffset, ui, updateAuto, updateCallback, updateFavicon, updateInterval, updateNow, updateTime, updateTitle, updateVerbose, updater, updaterMake, watcher, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _m, _ref, _ref2, _ref3, _ref4;
var __slice = Array.prototype.slice; var __slice = Array.prototype.slice;
if (typeof console != "undefined" && console !== null) { if (typeof console != "undefined" && console !== null) {
log = console.log; log = console.log;
@ -75,7 +75,7 @@
'Image Expansion': [true, 'Expand images'], 'Image Expansion': [true, 'Expand images'],
'Image Hover': [false, 'Show full image on mouseover'], 'Image Hover': [false, 'Show full image on mouseover'],
'Image Preloading': [false, 'Preload Images'], 'Image Preloading': [false, 'Preload Images'],
'Keybinds': [false, 'Binds actions to keys'], 'Keybinds': [true, 'Binds actions to keys'],
'Localize Time': [true, 'Show times based on your timezone'], 'Localize Time': [true, 'Show times based on your timezone'],
'Persistent QR': [false, 'Quick reply won\'t disappear after posting. Only in replies.'], 'Persistent QR': [false, 'Quick reply won\'t disappear after posting. Only in replies.'],
'Post in Title': [true, 'Show the op\'s post in the tab title'], 'Post in Title': [true, 'Show the op\'s post in the tab title'],
@ -662,42 +662,90 @@
thumb.className = ''; thumb.className = '';
return $.remove(thumb.nextSibling); return $.remove(thumb.nextSibling);
}; };
keydown = function(e) { keybinds = {
var kc; init: function() {
kc = e.keyCode; $.bind(d, 'keydown', keybinds.cb.keydown);
g.keyCode = kc; return $.bind(d, 'keypress', keybinds.cb.keypress);
return g.char = String.fromCharCode(kc); },
}; cb: {
keypress = function(e) { keydown: function(e) {
var _ref; var kc, key, _ref;
if ((_ref = d.activeElement.nodeName) === 'TEXTAREA' || _ref === 'INPUT') { if ((_ref = d.activeElement.nodeName) === 'TEXTAREA' || _ref === 'INPUT') {
return keyModeInsert(e); keybinds.mode = keybinds.insert;
} else { } else {
return keyModeNormal(e); keybinds.mode = keybinds.normal;
} }
}; kc = e.keyCode;
keyModeInsert = function(e) { if ((65 <= kc && kc <= 90)) {
var char, kc, range, selEnd, selStart, ta, valEnd, valMid, valStart, value; key = String.fromCharCode(kc);
kc = g.keyCode; if (!e.shiftKey) {
char = g.char; key = key.toLowerCase();
if (kc === 27) { }
$.remove($('#qr')); if (e.ctrlKey) {
return e.preventDefault(); key = '^' + key;
} else if (e.ctrlKey && char === "S") { }
ta = d.activeElement; } else {
if (ta.nodeName !== 'TEXTAREA') { if (kc === 27) {
return; key = '<Esc>';
}
}
return keybinds.key = key;
},
keypress: function(e) {
return keybinds.mode(e);
}
},
insert: function(e) {
var range, selEnd, selStart, ta, valEnd, valMid, valStart, value;
switch (keybinds.key) {
case '<Esc>':
e.preventDefault();
return $.remove($('#qr'));
case '^s':
ta = d.activeElement;
if (ta.nodeName !== 'TEXTAREA') {
return;
}
e.preventDefault();
value = ta.value;
selStart = ta.selectionStart;
selEnd = ta.selectionEnd;
valStart = value.slice(0, selStart) + '[spoiler]';
valMid = value.slice(selStart, selEnd);
valEnd = '[/spoiler]' + value.slice(selEnd);
ta.value = valStart + valMid + valEnd;
range = valStart.length + valMid.length;
return ta.setSelectionRange(range, range);
}
},
normal: function(e) {
var thread;
switch (keybinds.key) {
case 'I':
break;
case 'J':
break;
case 'K':
break;
case 'M':
break;
case 'i':
break;
case 'm':
break;
case 'n':
return nav.down();
case 'o':
break;
case 'p':
return nav.up();
case 'u':
break;
case 'w':
thread = nav.getThread()[0];
return watcher.toggle(thread);
case 'x':
} }
value = ta.value;
selStart = ta.selectionStart;
selEnd = ta.selectionEnd;
valStart = value.slice(0, selStart) + '[spoiler]';
valMid = value.slice(selStart, selEnd);
valEnd = '[/spoiler]' + value.slice(selEnd);
ta.value = valStart + valMid + valEnd;
range = valStart.length + valMid.length;
ta.setSelectionRange(range, range);
return e.preventDefault();
} }
}; };
keyModeNormal = function(e) { keyModeNormal = function(e) {
@ -708,16 +756,6 @@
char = g.char; char = g.char;
hash = location.hash; hash = location.hash;
switch (char) { switch (char) {
case "0":
return location.pathname = "/" + g.BOARD;
case "G":
if (e.shiftKey) {
return window.scrollTo(0, 99999);
} else {
window.scrollTo(0, 0);
return location.hash = '';
}
break;
case "I": case "I":
if (g.REPLY) { if (g.REPLY) {
if (!(qrLink = $('td.replyhl span[id] a:not(:first-child)'))) { if (!(qrLink = $('td.replyhl span[id] a:not(:first-child)'))) {
@ -1729,7 +1767,7 @@
} }
favicon = $.el('img', { favicon = $.el('img', {
src: src, src: src,
className: 'pointer' className: 'favicon'
}); });
$.bind(favicon, 'click', watcher.cb.toggle); $.bind(favicon, 'click', watcher.cb.toggle);
_results.push($.before(input, favicon)); _results.push($.before(input, favicon));
@ -1750,7 +1788,7 @@
}, },
cb: { cb: {
toggle: function(e) { toggle: function(e) {
return watcher.toggle(e.target); return watcher.toggle(e.target.parentNode);
}, },
x: function(e) { x: function(e) {
var board, id, _, _ref; var board, id, _, _ref;
@ -1758,8 +1796,9 @@
return watcher.unwatch(board, id); return watcher.unwatch(board, id);
} }
}, },
toggle: function(favicon) { toggle: function(thread) {
var id; var favicon, id;
favicon = $('img.favicon', thread);
id = favicon.nextSibling.name; id = favicon.nextSibling.name;
if (favicon.src === g.favEmpty) { if (favicon.src === g.favEmpty) {
return watcher.watch(id, favicon); return watcher.watch(id, favicon);
@ -1848,7 +1887,7 @@
div.dialog > div.move {\ div.dialog > div.move {\
cursor: move;\ cursor: move;\
}\ }\
label, a, .pointer {\ label, a, {\
cursor: pointer;\ cursor: pointer;\
}\ }\
\ \
@ -1931,6 +1970,9 @@
.new {\ .new {\
background: lime;\ background: lime;\
}\ }\
.favicon {\
cursor: pointer;\
}\
'); ');
if (location.hostname === 'sys.4chan.org') { if (location.hostname === 'sys.4chan.org') {
qr.sys(); qr.sys();
@ -2088,8 +2130,7 @@
for (_i = 0, _len = arr.length; _i < _len; _i++) { for (_i = 0, _len = arr.length; _i < _len; _i++) {
el = arr[_i]; el = arr[_i];
a = $.el('a', { a = $.el('a', {
textContent: '[ ! ]', textContent: '[ ! ]'
className: 'pointer'
}); });
$.bind(a, 'click', report); $.bind(a, 'click', report);
$.after(el, a); $.after(el, a);
@ -2119,8 +2160,7 @@
}); });
} }
if ($.config('Keybinds')) { if ($.config('Keybinds')) {
$.bind(d, 'keydown', keydown); keybinds.init();
$.bind(d, 'keypress', keypress);
} }
if ($.config('Thread Updater')) { if ($.config('Thread Updater')) {
updater.init(); updater.init();
@ -2176,7 +2216,7 @@
for (_k = 0, _len3 = omitted.length; _k < _len3; _k++) { for (_k = 0, _len3 = omitted.length; _k < _len3; _k++) {
span = omitted[_k]; span = omitted[_k];
a = $.el('a', { a = $.el('a', {
className: 'pointer omittedposts', className: 'omittedposts',
textContent: "+ " + span.textContent textContent: "+ " + span.textContent
}); });
$.bind(a, 'click', expandThread); $.bind(a, 'click', expandThread);

View File

@ -1,4 +1,4 @@
# TODO floating nav buttons FUCKING AWESOME # TODO
# option to skip post form directly to contents on first page, # option to skip post form directly to contents on first page,
# like what happens when using thread nav to go to next page # like what happens when using thread nav to go to next page
# (floating) qr no-quote button? # (floating) qr no-quote button?
@ -6,6 +6,7 @@
# XXX error on FUCKING CHROME # XXX error on FUCKING CHROME
{log} = console if console? {log} = console if console?
# TODO put keybinds back to false when done
config = config =
main: main:
checkbox: checkbox:
@ -17,7 +18,7 @@ config =
'Image Expansion': [true, 'Expand images'] 'Image Expansion': [true, 'Expand images']
'Image Hover': [false, 'Show full image on mouseover'] 'Image Hover': [false, 'Show full image on mouseover']
'Image Preloading': [false, 'Preload Images'] 'Image Preloading': [false, 'Preload Images']
'Keybinds': [false, 'Binds actions to keys'] 'Keybinds': [true, 'Binds actions to keys']
'Localize Time': [true, 'Show times based on your timezone'] 'Localize Time': [true, 'Show times based on your timezone']
'Persistent QR': [false, 'Quick reply won\'t disappear after posting. Only in replies.'] 'Persistent QR': [false, 'Quick reply won\'t disappear after posting. Only in replies.']
'Post in Title': [true, 'Show the op\'s post in the tab title'] 'Post in Title': [true, 'Show the op\'s post in the tab title']
@ -481,53 +482,98 @@ imageThumb = (thumb) ->
thumb.className = '' thumb.className = ''
$.remove thumb.nextSibling $.remove thumb.nextSibling
keydown = (e) -> keybinds =
kc = e.keyCode init: ->
g.keyCode = kc $.bind d, 'keydown', keybinds.cb.keydown
g.char = String.fromCharCode kc $.bind d, 'keypress', keybinds.cb.keypress
keypress = (e) -> cb:
if d.activeElement.nodeName in ['TEXTAREA', 'INPUT'] keydown: (e) ->
keyModeInsert e if d.activeElement.nodeName in ['TEXTAREA', 'INPUT']
else keybinds.mode = keybinds.insert
keyModeNormal e else
keybinds.mode = keybinds.normal
keyModeInsert = (e) -> kc = e.keyCode
kc = g.keyCode if 65 <= kc <= 90 #A-Z
char = g.char key = String.fromCharCode kc
if kc is 27 #escape if !e.shiftKey
$.remove $ '#qr' key = key.toLowerCase()
e.preventDefault() if e.ctrlKey then key = '^' + key
else if e.ctrlKey and char is "S" else
ta = d.activeElement if kc is 27
return unless ta.nodeName is 'TEXTAREA' key = '<Esc>'
keybinds.key = key
value = ta.value keypress: (e) ->
selStart = ta.selectionStart keybinds.mode e
selEnd = ta.selectionEnd
valStart = value[0...selStart] + '[spoiler]' insert: (e) ->
valMid = value[selStart...selEnd] switch keybinds.key
valEnd = '[/spoiler]' + value[selEnd..] when '<Esc>'
e.preventDefault()
$.remove $ '#qr'
when '^s'
ta = d.activeElement
return unless ta.nodeName is 'TEXTAREA'
e.preventDefault()
value = ta.value
selStart = ta.selectionStart
selEnd = ta.selectionEnd
valStart = value[0...selStart] + '[spoiler]'
valMid = value[selStart...selEnd]
valEnd = '[/spoiler]' + value[selEnd..]
ta.value = valStart + valMid + valEnd
range = valStart.length + valMid.length
ta.setSelectionRange range, range
normal: (e) ->
switch keybinds.key
when 'I'
#qr no text
return
when 'J'
#highlight next
return
when 'K'
#highlight prev
return
when 'M'
#expand all
return
when 'i'
#qr
return
when 'm'
#expand img
return
when 'n'
nav.down()
when 'o'
#open in new tab
return
when 'p'
nav.up()
when 'u'
#update now
return
when 'w'
[thread] = nav.getThread()
watcher.toggle thread
when 'x'
#toggle hide thread
return
ta.value = valStart + valMid + valEnd
range = valStart.length + valMid.length
ta.setSelectionRange range, range
e.preventDefault()
keyModeNormal = (e) -> keyModeNormal = (e) ->
return if e.ctrlKey or e.altKey return if e.ctrlKey or e.altKey
char = g.char char = g.char
hash = location.hash hash = location.hash
switch char switch char
when "0"
location.pathname = "/#{g.BOARD}"
when "G"
if e.shiftKey
window.scrollTo 0, 99999
else
window.scrollTo 0, 0
location.hash = ''
when "I" when "I"
if g.REPLY if g.REPLY
unless qrLink = $ 'td.replyhl span[id] a:not(:first-child)' unless qrLink = $ 'td.replyhl span[id] a:not(:first-child)'
@ -1337,7 +1383,7 @@ watcher =
src = g.favEmpty src = g.favEmpty
favicon = $.el 'img', favicon = $.el 'img',
src: src src: src
className: 'pointer' className: 'favicon'
$.bind favicon, 'click', watcher.cb.toggle $.bind favicon, 'click', watcher.cb.toggle
$.before input, favicon $.before input, favicon
@ -1354,13 +1400,14 @@ watcher =
cb: cb:
toggle: (e) -> toggle: (e) ->
watcher.toggle e.target watcher.toggle e.target.parentNode
x: (e) -> x: (e) ->
[board, _, id] = e.target.nextElementSibling [board, _, id] = e.target.nextElementSibling
.getAttribute('href').substring(1).split('/') .getAttribute('href').substring(1).split('/')
watcher.unwatch board, id watcher.unwatch board, id
toggle: (favicon) -> toggle: (thread) ->
favicon = $ 'img.favicon', thread
id = favicon.nextSibling.name id = favicon.nextSibling.name
if favicon.src == g.favEmpty if favicon.src == g.favEmpty
watcher.watch id, favicon watcher.watch id, favicon
@ -1453,7 +1500,7 @@ $.addStyle '
div.dialog > div.move { div.dialog > div.move {
cursor: move; cursor: move;
} }
label, a, .pointer { label, a, {
cursor: pointer; cursor: pointer;
} }
@ -1536,6 +1583,9 @@ $.addStyle '
.new { .new {
background: lime; background: lime;
} }
.favicon {
cursor: pointer;
}
' '
if location.hostname is 'sys.4chan.org' if location.hostname is 'sys.4chan.org'
@ -1653,7 +1703,6 @@ if $.config 'Quick Report'
for el in arr for el in arr
a = $.el 'a', a = $.el 'a',
textContent: '[ ! ]' textContent: '[ ! ]'
className: 'pointer'
$.bind a, 'click', report $.bind a, 'click', report
$.after el, a $.after el, a
$.after el, $.tn(' ') $.after el, $.tn(' ')
@ -1674,8 +1723,7 @@ if $.config 'Anonymize'
$.remove trip $.remove trip
if $.config 'Keybinds' if $.config 'Keybinds'
$.bind d, 'keydown', keydown keybinds.init()
$.bind d, 'keypress', keypress
if $.config 'Thread Updater' if $.config 'Thread Updater'
updater.init() updater.init()
@ -1716,7 +1764,7 @@ else #not reply
omitted = $$('span.omittedposts') omitted = $$('span.omittedposts')
for span in omitted for span in omitted
a = $.el 'a', a = $.el 'a',
className: 'pointer omittedposts' className: 'omittedposts'
textContent: "+ #{span.textContent}" textContent: "+ #{span.textContent}"
$.bind a, 'click', expandThread $.bind a, 'click', expandThread
$.replace(span, a) $.replace(span, a)