4chan-x/foltor/foltor.coffee
2010-04-27 23:52:51 -07:00

328 lines
8.2 KiB
CoffeeScript

x: (path, root) ->
root ||= document.body
document.
evaluate(path, root, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).
singleNodeValue
$: (selector, root) ->
root ||= document.body
root.querySelector(selector)
$$: (selector, root) ->
root ||= document.body
result: root.querySelectorAll(selector)
#magic that turns the results object into an array:
node for node in result
inBefore: (root, el) ->
root.parentNode.insertBefore(el, root)
tag: (el) ->
document.createElement(el)
text: (s) ->
document.createTextNode(s)
remove: (root) ->
root.parentNode.removeChild(root)
position: (el) ->
id: el.id
if left: GM_getValue("${id}Left", '0px')
el.style.left: left
else
el.style.right: '0px'
if top: GM_getValue("${id}Top", '0px')
el.style.top: top
else
el.style.bottom: '0px'
move: {}
mousedown: (e) ->
div: this.parentNode
move.div: div
move.divX: div.offsetLeft
move.divY: div.offsetTop
move.clientX: e.clientX
move.clientY: e.clientY
move.bodyX: document.body.clientWidth
move.bodyY: document.body.clientHeight
window.addEventListener('mousemove', mousemove, true)
window.addEventListener('mouseup', mouseup, true)
mousemove: (e) ->
div: move.div
realX: move.divX + (e.clientX - move.clientX)# x + dx
left: if realX < 20 then 0 else realX
if move.bodyX - div.offsetWidth - realX < 20
div.style.left: ''
div.style.right: '0px'
else
div.style.left: left + 'px'
div.style.right: ''
realY: move.divY + (e.clientY - move.clientY)# y + dy
top: if realY < 20 then 0 else realY
if move.bodyY - div.offsetHeight - realY < 20
div.style.top: ''
div.style.bottom: '0px'
else
div.style.top: top + 'px'
div.style.bottom: ''
mouseup: ->
id: move.div.id
GM_setValue("${id}Left", move.div.style.left)
GM_setValue("${id}Top", move.div.style.top)
window.removeEventListener('mousemove', mousemove, true)
window.removeEventListener('mouseup', mouseup, true)
#x-browser
if typeof GM_deleteValue == 'undefined'
this.GM_setValue: (name, value) ->
value: (typeof value)[0] + value
localStorage.setItem(name, value)
this.GM_getValue: (name, defaultValue) ->
if not value: localStorage.getItem(name)
return defaultValue
type: value[0]
value: value.substring(1)
switch type
when 'b'
return value == 'true'
when 'n'
return Number(value)
else
return value
this.GM_addStyle: (css) ->
style: tag('style')
style.type: 'text/css'
style.textContent: css
$('head', document).appendChild(style)
GM_addStyle('
#box, #box_options {
position: fixed;
text-align: right;
border: 1px solid;
}
#box.autohide:not(:hover){
background: rgba(0,0,0,0);
border: none;
}
#box.autohide:not(:hover) > div {
display: none;
}
#box.autohide:not(:hover) > div.top {
display: block;
padding: 0;
}
#box.autohide a:last-child {
font-weight: bold;
}
#box > div {
padding: 0 5px 0 5px;
}
#box > .top {
padding: 5px 5px 0 5px;
}
#box > .bottom {
padding: 0 5px 5px 5px;
}
.move {
cursor: move;
}
.pointer, #box a, #box_options a {
cursor: pointer;
}
.hide {
display: none;
}
')
filterSingle: (table, filter) ->
for field of filter
switch field
when 'Name'
s: $('span.commentpostername', table).textContent
when 'Tripcode'
s: $('span.postertrip', table)?.textContent || ''
when 'Email'
s: $('a.linkmail', table)?.href.slice(7) || ''
when 'Subject'
s: $('span.filetitle', table)?.textContent || ''
when 'Comment'
s: $('blockquote', table).textContent
when 'File'
s: $('span.filesize', table)?.textContent || ''
if filter[field].test(s)
return true
filterAll: ->
filter: {}
inputs: $$('input', box)
for input in inputs
if value: input.value
filter[input.name]: value
filters[select.value]: filter
GM_setValue('filters', JSON.stringify(filters))
#so ugly
compiled: filters
for filter of compiled
for field of compiled[filter]
compiled[filter][field]: new RegExp(compiled[filter][field], 'i')
tables: reset()
for table in tables
for filter of compiled
if filterSingle(table, compiled[filter])
table.className: filter
imagesCount: $$('img[md5]').length
box.firstChild.textContent: "Images: $imagesCount Replies: ${tables.length}"
keydown: (e) ->
if e.keyCode is 13 #enter
filterAll()
reset: ->
tables: $$('form[name="delform"] table')
tables.pop()
tables.pop()
for table in tables
table.className: ''
return tables
autoHide: ->
if box.className is 'reply'
box.className: 'reply autohide'
else
box.className: 'reply'
GM_setValue('className', box.className)
save: ->
div: this.parentNode.parentNode
inputs: $$('input:enabled', div)
for input in inputs
if value: input.value
filters[value]: {}
GM_setValue('filters', JSON.stringify(filters))
remove(div)
cancel: ->
div: this.parentNode.parentNode
remove(div)
addClass: ->
div: tag('div')
input: tag('input')
div.appendChild(input)
inBefore(this, div)
input.focus()
options: ->
if opt: $('#box_options')
remove(opt)
else
opt: tag('div')
opt.id: 'box_options'
opt.className: 'reply'
position(opt)
bar: tag('div')
bar.textContent: 'Options'
bar.className: 'move'
bar.addEventListener('mousedown', mousedown, true)
opt.appendChild(bar)
filters: JSON.parse(GM_getValue('filters', '{ "hide": {} }'))
for filter of filters
div: tag('div')
input: tag('input')
input.value: filter
input.disabled: true
div.appendChild(input)
opt.appendChild(div)
div: tag('div')
a: tag('a')
a.textContent: 'Add Class'
a.addEventListener('click', addClass, true)
div.appendChild(a)
opt.appendChild(div)
div: tag('div')
a: tag('a')
a.textContent: 'save'
a.addEventListener('click', save, true)
div.appendChild(a)
div.appendChild(text(' '))
a: tag('a')
a.textContent: 'cancel'
a.addEventListener('click', cancel, true)
div.appendChild(a)
opt.appendChild(div)
document.body.appendChild(opt)
box: tag('div')
box.id: 'box'
box.className: GM_getValue('className', 'reply')
position(box)
bar: tag('div')
bar.className: 'move top'
bar.addEventListener('mousedown', mousedown, true)
box.appendChild(bar)
select: tag('select')
filters: JSON.parse(GM_getValue('filters', '{ "hide": {} }'))
for filter of filters
option: tag('option')
option.textContent: filter
select.appendChild(option)
box.appendChild(select)
#currently displayed filter
filter: filters[select.value]
fields: [
'Name',
'Tripcode',
'Email',
'Subject',
'Comment',
'File',
]
for field in fields
div: tag('div')
label: tag('label')
label.textContent: field
input: tag('input')
input.value: filter[field] || ''
input.name: field
input.addEventListener('keydown', keydown, true)
label.appendChild(input)
div.appendChild(label)
box.appendChild(div)
div: tag('div')
div.className: 'bottom'
for name in ['apply', 'reset', 'options', 'autohide']
a: tag('a')
a.textContent: name
switch name
when 'apply' then f: filterAll
when 'reset' then f: reset
when 'options' then f: options
when 'autohide' then f: autoHide
a.addEventListener('click', f, true)
div.appendChild(a)
div.appendChild(text(' '))
box.appendChild(div)
document.body.appendChild(box)
filterAll()