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() {
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;
if (typeof console != "undefined" && console !== null) {
log = console.log;
@ -75,7 +75,7 @@
'Image Expansion': [true, 'Expand images'],
'Image Hover': [false, 'Show full image on mouseover'],
'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'],
'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'],
@ -662,42 +662,90 @@
thumb.className = '';
return $.remove(thumb.nextSibling);
};
keydown = function(e) {
var kc;
kc = e.keyCode;
g.keyCode = kc;
return g.char = String.fromCharCode(kc);
};
keypress = function(e) {
var _ref;
if ((_ref = d.activeElement.nodeName) === 'TEXTAREA' || _ref === 'INPUT') {
return keyModeInsert(e);
} else {
return keyModeNormal(e);
}
};
keyModeInsert = function(e) {
var char, kc, range, selEnd, selStart, ta, valEnd, valMid, valStart, value;
kc = g.keyCode;
char = g.char;
if (kc === 27) {
$.remove($('#qr'));
return e.preventDefault();
} else if (e.ctrlKey && char === "S") {
ta = d.activeElement;
if (ta.nodeName !== 'TEXTAREA') {
return;
keybinds = {
init: function() {
$.bind(d, 'keydown', keybinds.cb.keydown);
return $.bind(d, 'keypress', keybinds.cb.keypress);
},
cb: {
keydown: function(e) {
var kc, key, _ref;
if ((_ref = d.activeElement.nodeName) === 'TEXTAREA' || _ref === 'INPUT') {
keybinds.mode = keybinds.insert;
} else {
keybinds.mode = keybinds.normal;
}
kc = e.keyCode;
if ((65 <= kc && kc <= 90)) {
key = String.fromCharCode(kc);
if (!e.shiftKey) {
key = key.toLowerCase();
}
if (e.ctrlKey) {
key = '^' + key;
}
} else {
if (kc === 27) {
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) {
@ -708,16 +756,6 @@
char = g.char;
hash = location.hash;
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":
if (g.REPLY) {
if (!(qrLink = $('td.replyhl span[id] a:not(:first-child)'))) {
@ -1729,7 +1767,7 @@
}
favicon = $.el('img', {
src: src,
className: 'pointer'
className: 'favicon'
});
$.bind(favicon, 'click', watcher.cb.toggle);
_results.push($.before(input, favicon));
@ -1750,7 +1788,7 @@
},
cb: {
toggle: function(e) {
return watcher.toggle(e.target);
return watcher.toggle(e.target.parentNode);
},
x: function(e) {
var board, id, _, _ref;
@ -1758,8 +1796,9 @@
return watcher.unwatch(board, id);
}
},
toggle: function(favicon) {
var id;
toggle: function(thread) {
var favicon, id;
favicon = $('img.favicon', thread);
id = favicon.nextSibling.name;
if (favicon.src === g.favEmpty) {
return watcher.watch(id, favicon);
@ -1848,7 +1887,7 @@
div.dialog > div.move {\
cursor: move;\
}\
label, a, .pointer {\
label, a, {\
cursor: pointer;\
}\
\
@ -1931,6 +1970,9 @@
.new {\
background: lime;\
}\
.favicon {\
cursor: pointer;\
}\
');
if (location.hostname === 'sys.4chan.org') {
qr.sys();
@ -2088,8 +2130,7 @@
for (_i = 0, _len = arr.length; _i < _len; _i++) {
el = arr[_i];
a = $.el('a', {
textContent: '[ ! ]',
className: 'pointer'
textContent: '[ ! ]'
});
$.bind(a, 'click', report);
$.after(el, a);
@ -2119,8 +2160,7 @@
});
}
if ($.config('Keybinds')) {
$.bind(d, 'keydown', keydown);
$.bind(d, 'keypress', keypress);
keybinds.init();
}
if ($.config('Thread Updater')) {
updater.init();
@ -2176,7 +2216,7 @@
for (_k = 0, _len3 = omitted.length; _k < _len3; _k++) {
span = omitted[_k];
a = $.el('a', {
className: 'pointer omittedposts',
className: 'omittedposts',
textContent: "+ " + span.textContent
});
$.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,
# like what happens when using thread nav to go to next page
# (floating) qr no-quote button?
@ -6,6 +6,7 @@
# XXX error on FUCKING CHROME
{log} = console if console?
# TODO put keybinds back to false when done
config =
main:
checkbox:
@ -17,7 +18,7 @@ config =
'Image Expansion': [true, 'Expand images']
'Image Hover': [false, 'Show full image on mouseover']
'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']
'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']
@ -481,53 +482,98 @@ imageThumb = (thumb) ->
thumb.className = ''
$.remove thumb.nextSibling
keydown = (e) ->
kc = e.keyCode
g.keyCode = kc
g.char = String.fromCharCode kc
keybinds =
init: ->
$.bind d, 'keydown', keybinds.cb.keydown
$.bind d, 'keypress', keybinds.cb.keypress
keypress = (e) ->
if d.activeElement.nodeName in ['TEXTAREA', 'INPUT']
keyModeInsert e
else
keyModeNormal e
cb:
keydown: (e) ->
if d.activeElement.nodeName in ['TEXTAREA', 'INPUT']
keybinds.mode = keybinds.insert
else
keybinds.mode = keybinds.normal
keyModeInsert = (e) ->
kc = g.keyCode
char = g.char
if kc is 27 #escape
$.remove $ '#qr'
e.preventDefault()
else if e.ctrlKey and char is "S"
ta = d.activeElement
return unless ta.nodeName is 'TEXTAREA'
kc = e.keyCode
if 65 <= kc <= 90 #A-Z
key = String.fromCharCode kc
if !e.shiftKey
key = key.toLowerCase()
if e.ctrlKey then key = '^' + key
else
if kc is 27
key = '<Esc>'
keybinds.key = key
value = ta.value
selStart = ta.selectionStart
selEnd = ta.selectionEnd
keypress: (e) ->
keybinds.mode e
valStart = value[0...selStart] + '[spoiler]'
valMid = value[selStart...selEnd]
valEnd = '[/spoiler]' + value[selEnd..]
insert: (e) ->
switch keybinds.key
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) ->
return if e.ctrlKey or e.altKey
char = g.char
hash = location.hash
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"
if g.REPLY
unless qrLink = $ 'td.replyhl span[id] a:not(:first-child)'
@ -1337,7 +1383,7 @@ watcher =
src = g.favEmpty
favicon = $.el 'img',
src: src
className: 'pointer'
className: 'favicon'
$.bind favicon, 'click', watcher.cb.toggle
$.before input, favicon
@ -1354,13 +1400,14 @@ watcher =
cb:
toggle: (e) ->
watcher.toggle e.target
watcher.toggle e.target.parentNode
x: (e) ->
[board, _, id] = e.target.nextElementSibling
.getAttribute('href').substring(1).split('/')
watcher.unwatch board, id
toggle: (favicon) ->
toggle: (thread) ->
favicon = $ 'img.favicon', thread
id = favicon.nextSibling.name
if favicon.src == g.favEmpty
watcher.watch id, favicon
@ -1453,7 +1500,7 @@ $.addStyle '
div.dialog > div.move {
cursor: move;
}
label, a, .pointer {
label, a, {
cursor: pointer;
}
@ -1536,6 +1583,9 @@ $.addStyle '
.new {
background: lime;
}
.favicon {
cursor: pointer;
}
'
if location.hostname is 'sys.4chan.org'
@ -1653,7 +1703,6 @@ if $.config 'Quick Report'
for el in arr
a = $.el 'a',
textContent: '[ ! ]'
className: 'pointer'
$.bind a, 'click', report
$.after el, a
$.after el, $.tn(' ')
@ -1674,8 +1723,7 @@ if $.config 'Anonymize'
$.remove trip
if $.config 'Keybinds'
$.bind d, 'keydown', keydown
$.bind d, 'keypress', keypress
keybinds.init()
if $.config 'Thread Updater'
updater.init()
@ -1716,7 +1764,7 @@ else #not reply
omitted = $$('span.omittedposts')
for span in omitted
a = $.el 'a',
className: 'pointer omittedposts'
className: 'omittedposts'
textContent: "+ #{span.textContent}"
$.bind a, 'click', expandThread
$.replace(span, a)