commit
39aa9d3cb5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
|||||||
builds/
|
builds/
|
||||||
node_modules/
|
node_modules/
|
||||||
tmp-crx/
|
tmp-crx/
|
||||||
tmp-userjs/
|
|
||||||
tmp-userscript/
|
tmp-userscript/
|
||||||
|
|||||||
@ -11,9 +11,8 @@ Reporting bugs:
|
|||||||
4. Your exported settings. If your settings contains sensible information (e.g. personas), edit the text file manually.
|
4. Your exported settings. If your settings contains sensible information (e.g. personas), edit the text file manually.
|
||||||
|
|
||||||
Open your console with:
|
Open your console with:
|
||||||
- `Ctrl + Shift + J` on Chrome.
|
- `Ctrl + Shift + J` on Chrome and Opera.
|
||||||
- `Ctrl + Shift + K` on Firefox.
|
- `Ctrl + Shift + K` on Firefox.
|
||||||
- `Ctrl + Shift + O` on Opera.
|
|
||||||
|
|
||||||
Respect these guidelines:
|
Respect these guidelines:
|
||||||
- Describe the issue clearly, put some effort into it. A one-liner isn't a good enough description.
|
- Describe the issue clearly, put some effort into it. A one-liner isn't a good enough description.
|
||||||
|
|||||||
19
Gruntfile.js
19
Gruntfile.js
@ -56,15 +56,6 @@ module.exports = function(grunt) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
userjs: {
|
|
||||||
options: concatOptions,
|
|
||||||
src: [
|
|
||||||
'src/Meta/metadata.js',
|
|
||||||
'src/Meta/banner.js',
|
|
||||||
'tmp-<%= pkg.type %>/script.js'
|
|
||||||
],
|
|
||||||
dest: 'builds/<%= pkg.name %>.js'
|
|
||||||
},
|
|
||||||
userscript: {
|
userscript: {
|
||||||
options: concatOptions,
|
options: concatOptions,
|
||||||
files: {
|
files: {
|
||||||
@ -102,7 +93,7 @@ module.exports = function(grunt) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
concurrent: {
|
concurrent: {
|
||||||
build: ['build-crx', 'build-userjs', 'build-userscript']
|
build: ['build-crx', 'build-userscript']
|
||||||
},
|
},
|
||||||
bump: {
|
bump: {
|
||||||
options: {
|
options: {
|
||||||
@ -161,7 +152,6 @@ module.exports = function(grunt) {
|
|||||||
clean: {
|
clean: {
|
||||||
builds: 'builds',
|
builds: 'builds',
|
||||||
tmpcrx: 'tmp-crx',
|
tmpcrx: 'tmp-crx',
|
||||||
tmpuserjs: 'tmp-userjs',
|
|
||||||
tmpuserscript: 'tmp-userscript'
|
tmpuserscript: 'tmp-userscript'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -193,13 +183,6 @@ module.exports = function(grunt) {
|
|||||||
'copy:crx',
|
'copy:crx',
|
||||||
'clean:tmpcrx'
|
'clean:tmpcrx'
|
||||||
]);
|
]);
|
||||||
grunt.registerTask('build-userjs', [
|
|
||||||
'set-build:userjs',
|
|
||||||
'concat:coffee',
|
|
||||||
'coffee:script',
|
|
||||||
'concat:userjs',
|
|
||||||
'clean:tmpuserjs'
|
|
||||||
]);
|
|
||||||
grunt.registerTask('build-userscript', [
|
grunt.registerTask('build-userscript', [
|
||||||
'set-build:userscript',
|
'set-build:userscript',
|
||||||
'concat:coffee',
|
'concat:coffee',
|
||||||
|
|||||||
@ -278,10 +278,8 @@ a[href="javascript:;"] {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 0 0 15px rgba(0, 0, 0, .15);
|
box-shadow: 0 0 15px rgba(0, 0, 0, .15);
|
||||||
height: 600px;
|
height: 600px;
|
||||||
min-height: 0;
|
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
min-width: 0;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
@ -468,7 +466,8 @@ a.hide-announcement {
|
|||||||
.deadlink {
|
.deadlink {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {
|
.backlink.deadlink:not(.forwardlink),
|
||||||
|
.quotelink.deadlink:not(.forwardlink) {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
.inlined {
|
.inlined {
|
||||||
@ -508,8 +507,6 @@ a.hide-announcement {
|
|||||||
padding: 2px 2px 5px;
|
padding: 2px 2px 5px;
|
||||||
}
|
}
|
||||||
#qp img {
|
#qp img {
|
||||||
max-height: 300px;
|
|
||||||
max-width: 500px;
|
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
max-width: 50vw;
|
max-width: 50vw;
|
||||||
}
|
}
|
||||||
@ -541,8 +538,7 @@ a.hide-announcement {
|
|||||||
:root.fit-width .full-image {
|
:root.fit-width .full-image {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
:root.gecko.fit-width .full-image,
|
:root.gecko.fit-width .full-image {
|
||||||
:root.presto.fit-width .full-image {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
#ihover {
|
#ihover {
|
||||||
@ -616,9 +612,6 @@ a.hide-announcement {
|
|||||||
color: #000;
|
color: #000;
|
||||||
background-color: #F7F7F7;
|
background-color: #F7F7F7;
|
||||||
}
|
}
|
||||||
.presto #qr select {
|
|
||||||
height: 1em;
|
|
||||||
}
|
|
||||||
#qr .close {
|
#qr .close {
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
}
|
}
|
||||||
@ -649,13 +642,15 @@ a.hide-announcement {
|
|||||||
outline: none;
|
outline: none;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
#dump-button:hover, #dump-button:focus {
|
#dump-button:hover,
|
||||||
|
#dump-button:focus {
|
||||||
background: linear-gradient(#FFF, #DDD);
|
background: linear-gradient(#FFF, #DDD);
|
||||||
}
|
}
|
||||||
#dump-button:active, .dump #dump-button:not(:hover):not(:focus) {
|
#dump-button:active,
|
||||||
|
.dump #dump-button:not(:hover):not(:focus) {
|
||||||
background: linear-gradient(#CCC, #DDD);
|
background: linear-gradient(#CCC, #DDD);
|
||||||
}
|
}
|
||||||
.gecko #dump-button {
|
:root.gecko #dump-button {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
#qr:not(.dump) #dump-list-container {
|
#qr:not(.dump) #dump-list-container {
|
||||||
@ -670,7 +665,10 @@ a.hide-announcement {
|
|||||||
}
|
}
|
||||||
#dump-list {
|
#dump-list {
|
||||||
counter-reset: qrpreviews;
|
counter-reset: qrpreviews;
|
||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -696,8 +694,10 @@ a.hide-announcement {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 92px; width: 92px;
|
height: 92px;
|
||||||
margin: 4px; padding: 2px;
|
width: 92px;
|
||||||
|
margin: 4px;
|
||||||
|
padding: 2px;
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
outline: none;
|
outline: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -707,7 +707,8 @@ a.hide-announcement {
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
.qr-preview:hover, .qr-preview:focus {
|
.qr-preview:hover,
|
||||||
|
.qr-preview:focus {
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
color: #FFF !important;
|
color: #FFF !important;
|
||||||
}
|
}
|
||||||
@ -720,7 +721,8 @@ a.hide-announcement {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-shadow: 0 0 3px #000, 0 0 5px #000;
|
text-shadow: 0 0 3px #000, 0 0 5px #000;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px; right: 3px;
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
}
|
}
|
||||||
.qr-preview.drag {
|
.qr-preview.drag {
|
||||||
border-color: red;
|
border-color: red;
|
||||||
@ -740,7 +742,9 @@ a.hide-announcement {
|
|||||||
}
|
}
|
||||||
.qr-preview > label {
|
.qr-preview > label {
|
||||||
background: rgba(0, 0, 0, .5);
|
background: rgba(0, 0, 0, .5);
|
||||||
right: 0; bottom: 0; left: 0;
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -756,7 +760,8 @@ a.hide-announcement {
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0; bottom: 0;
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
#qr textarea {
|
#qr textarea {
|
||||||
@ -822,7 +827,10 @@ a.hide-announcement {
|
|||||||
}
|
}
|
||||||
#qr-filename {
|
#qr-filename {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -838,10 +846,6 @@ a.hide-announcement {
|
|||||||
-webkit-order: 1;
|
-webkit-order: 1;
|
||||||
order: 1;
|
order: 1;
|
||||||
}
|
}
|
||||||
#qr input[type='file'] {
|
|
||||||
position: absolute;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
.menu-button {
|
.menu-button {
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
<a id="qr-filerm" href="javascript:;" title="Remove file">×</a>
|
<a id="qr-filerm" href="javascript:;" title="Remove file">×</a>
|
||||||
<input type="checkbox" id="qr-file-spoiler" title="Spoiler image">
|
<input type="checkbox" id="qr-file-spoiler" title="Spoiler image">
|
||||||
</div>
|
</div>
|
||||||
<input type="file" multiple>
|
<input type="file" multiple hidden>
|
||||||
</form>
|
</form>
|
||||||
<datalist id="list-name"></datalist>
|
<datalist id="list-name"></datalist>
|
||||||
<datalist id="list-email"></datalist>
|
<datalist id="list-email"></datalist>
|
||||||
|
|||||||
68
lib/$.coffee
68
lib/$.coffee
@ -208,26 +208,19 @@ $.bytesToString = (size) ->
|
|||||||
# Round to an integer otherwise.
|
# Round to an integer otherwise.
|
||||||
Math.round size
|
Math.round size
|
||||||
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
|
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
|
||||||
|
$.item = (key, val) ->
|
||||||
|
item = {}
|
||||||
|
item[key] = val
|
||||||
|
item
|
||||||
$.syncing = {}
|
$.syncing = {}
|
||||||
$.sync = do ->
|
|
||||||
<% if (type === 'crx') { %>
|
<% if (type === 'crx') { %>
|
||||||
|
$.sync = do ->
|
||||||
chrome.storage.onChanged.addListener (changes) ->
|
chrome.storage.onChanged.addListener (changes) ->
|
||||||
for key of changes
|
for key of changes
|
||||||
if cb = $.syncing[key]
|
if cb = $.syncing[key]
|
||||||
cb changes[key].newValue
|
cb changes[key].newValue
|
||||||
return
|
return
|
||||||
(key, cb) -> $.syncing[key] = cb
|
(key, cb) -> $.syncing[key] = cb
|
||||||
<% } else { %>
|
|
||||||
$.on window, 'storage', (e) ->
|
|
||||||
if cb = $.syncing[e.key]
|
|
||||||
cb JSON.parse e.newValue
|
|
||||||
(key, cb) -> $.syncing[g.NAMESPACE + key] = cb
|
|
||||||
<% } %>
|
|
||||||
$.item = (key, val) ->
|
|
||||||
item = {}
|
|
||||||
item[key] = val
|
|
||||||
item
|
|
||||||
<% if (type === 'crx') { %>
|
|
||||||
$.localKeys = [
|
$.localKeys = [
|
||||||
# filters
|
# filters
|
||||||
'name',
|
'name',
|
||||||
@ -300,52 +293,13 @@ $.set = do ->
|
|||||||
else
|
else
|
||||||
$.extend items, key
|
$.extend items, key
|
||||||
set()
|
set()
|
||||||
<% } else if (type === 'userjs') { %>
|
|
||||||
do ->
|
|
||||||
# http://www.opera.com/docs/userjs/specs/#scriptstorage
|
|
||||||
# http://www.opera.com/docs/userjs/using/#securepages
|
|
||||||
# The scriptStorage object is available only during
|
|
||||||
# the main User JavaScript thread, being therefore
|
|
||||||
# accessible only in the main body of the user script.
|
|
||||||
# To access the storage object later, keep a reference
|
|
||||||
# to the object.
|
|
||||||
{scriptStorage} = opera
|
|
||||||
$.delete = (keys) ->
|
|
||||||
unless keys instanceof Array
|
|
||||||
keys = [keys]
|
|
||||||
for key in keys
|
|
||||||
key = g.NAMESPACE + key
|
|
||||||
localStorage.removeItem key
|
|
||||||
delete scriptStorage[key]
|
|
||||||
return
|
|
||||||
$.get = (key, val, cb) ->
|
|
||||||
if typeof cb is 'function'
|
|
||||||
items = $.item key, val
|
|
||||||
else
|
|
||||||
items = key
|
|
||||||
cb = val
|
|
||||||
$.queueTask ->
|
|
||||||
for key of items
|
|
||||||
if val = scriptStorage[g.NAMESPACE + key]
|
|
||||||
items[key] = JSON.parse val
|
|
||||||
cb items
|
|
||||||
$.set = do ->
|
|
||||||
set = (key, val) ->
|
|
||||||
key = g.NAMESPACE + key
|
|
||||||
val = JSON.stringify val
|
|
||||||
if key of $.syncing
|
|
||||||
# for `storage` events
|
|
||||||
localStorage.setItem key, val
|
|
||||||
scriptStorage[key] = val
|
|
||||||
(keys, val) ->
|
|
||||||
if typeof keys is 'string'
|
|
||||||
set keys, val
|
|
||||||
return
|
|
||||||
for key, val of keys
|
|
||||||
set key, val
|
|
||||||
return
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
# http://wiki.greasespot.net/Main_Page
|
# http://wiki.greasespot.net/Main_Page
|
||||||
|
$.sync = do ->
|
||||||
|
$.on window, 'storage', (e) ->
|
||||||
|
if cb = $.syncing[e.key]
|
||||||
|
cb JSON.parse e.newValue
|
||||||
|
(key, cb) -> $.syncing[g.NAMESPACE + key] = cb
|
||||||
$.delete = (keys) ->
|
$.delete = (keys) ->
|
||||||
unless keys instanceof Array
|
unless keys instanceof Array
|
||||||
keys = [keys]
|
keys = [keys]
|
||||||
|
|||||||
@ -1,9 +1,3 @@
|
|||||||
<% if (type === 'userjs') { %>
|
|
||||||
# Opera doesn't support the @match metadata key,
|
|
||||||
# return 4chan X here if we're not on 4chan.
|
|
||||||
return unless /^(boards|images|sys)\.4chan\.org$/.test location.hostname
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
Conf = {}
|
Conf = {}
|
||||||
c = console
|
c = console
|
||||||
d = document
|
d = document
|
||||||
|
|||||||
@ -127,8 +127,6 @@ Main =
|
|||||||
<% if (type === 'crx') { %>
|
<% if (type === 'crx') { %>
|
||||||
$.addClass doc, 'webkit'
|
$.addClass doc, 'webkit'
|
||||||
$.addClass doc, 'blink'
|
$.addClass doc, 'blink'
|
||||||
<% } else if (type === 'userjs') { %>
|
|
||||||
$.addClass doc, 'presto'
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
$.addClass doc, 'gecko'
|
$.addClass doc, 'gecko'
|
||||||
<% } %>
|
<% } %>
|
||||||
@ -151,13 +149,9 @@ Main =
|
|||||||
$.addClass doc, style
|
$.addClass doc, style
|
||||||
setStyle()
|
setStyle()
|
||||||
return unless mainStyleSheet
|
return unless mainStyleSheet
|
||||||
if window.MutationObserver
|
new MutationObserver(setStyle).observe mainStyleSheet,
|
||||||
observer = new MutationObserver setStyle
|
attributes: true
|
||||||
observer.observe mainStyleSheet,
|
attributeFilter: ['href']
|
||||||
attributes: true
|
|
||||||
attributeFilter: ['href']
|
|
||||||
else
|
|
||||||
$.on mainStyleSheet, 'DOMAttrModified', setStyle
|
|
||||||
|
|
||||||
initReady: ->
|
initReady: ->
|
||||||
if d.title is '4chan - 404 Not Found'
|
if d.title is '4chan - 404 Not Found'
|
||||||
@ -252,12 +246,10 @@ Main =
|
|||||||
|
|
||||||
checkUpdate: ->
|
checkUpdate: ->
|
||||||
return unless Conf['Check for Updates'] and Main.isThisPageLegit()
|
return unless Conf['Check for Updates'] and Main.isThisPageLegit()
|
||||||
# Check for updates after:
|
# Check for updates after 7 days since the last update.
|
||||||
# - 6 hours since the last update on Opera because it lacks auto-updating.
|
|
||||||
# - 7 days since the last update on Chrome/Firefox.
|
|
||||||
# After that, check for updates every day if we still haven't updated.
|
# After that, check for updates every day if we still haven't updated.
|
||||||
now = Date.now()
|
now = Date.now()
|
||||||
freq = <% if (type === 'userjs') { %>6 * $.HOUR<% } else { %>7 * $.DAY<% } %>
|
freq = 7 * $.DAY
|
||||||
items =
|
items =
|
||||||
lastupdate: 0
|
lastupdate: 0
|
||||||
lastchecked: 0
|
lastchecked: 0
|
||||||
|
|||||||
@ -52,19 +52,6 @@ ImageExpand =
|
|||||||
return
|
return
|
||||||
setFitness: ->
|
setFitness: ->
|
||||||
(if @checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-'
|
(if @checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-'
|
||||||
<% if (type === 'userjs') { %>
|
|
||||||
# XXX Opera doesn't support CSS vh.
|
|
||||||
return unless @name is 'Fit height'
|
|
||||||
if @checked
|
|
||||||
$.on window, 'resize', ImageExpand.resize
|
|
||||||
unless ImageExpand.style
|
|
||||||
ImageExpand.style = $.addStyle null
|
|
||||||
ImageExpand.resize()
|
|
||||||
else
|
|
||||||
$.off window, 'resize', ImageExpand.resize
|
|
||||||
resize: ->
|
|
||||||
ImageExpand.style.textContent = ":root.fit-height .full-image {max-height:#{doc.clientHeight}px}"
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
toggle: (post) ->
|
toggle: (post) ->
|
||||||
{thumb} = post.file
|
{thumb} = post.file
|
||||||
|
|||||||
@ -4,12 +4,10 @@ Sauce =
|
|||||||
|
|
||||||
links = []
|
links = []
|
||||||
for link in Conf['sauces'].split '\n'
|
for link in Conf['sauces'].split '\n'
|
||||||
continue if link[0] is '#'
|
|
||||||
try
|
try
|
||||||
links.push @createSauceLink link.trim()
|
links.push @createSauceLink link.trim() if link[0] isnt '#'
|
||||||
catch err
|
catch err
|
||||||
# Don't add random text plz.
|
# Don't add random text plz.
|
||||||
continue
|
|
||||||
return unless links.length
|
return unless links.length
|
||||||
@links = links
|
@links = links
|
||||||
@link = $.el 'a', target: '_blank'
|
@link = $.el 'a', target: '_blank'
|
||||||
|
|||||||
@ -15,7 +15,8 @@
|
|||||||
"run_at": "document_start"
|
"run_at": "document_start"
|
||||||
}],
|
}],
|
||||||
"homepage_url": "<%= meta.page %>",
|
"homepage_url": "<%= meta.page %>",
|
||||||
"minimum_chrome_version": "26",
|
"minimum_chrome_version": "27",
|
||||||
|
"minimum_opera_version": "15",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage"
|
"storage"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -114,8 +114,7 @@ ThreadUpdater =
|
|||||||
By sending the `If-Modified-Since` header we get a proper status code, and no response.
|
By sending the `If-Modified-Since` header we get a proper status code, and no response.
|
||||||
This saves bandwidth for both the user and the servers and avoid unnecessary computation.
|
This saves bandwidth for both the user and the servers and avoid unnecessary computation.
|
||||||
###
|
###
|
||||||
# XXX 304 -> 0 in Opera
|
[text, klass] = if req.status is 304
|
||||||
[text, klass] = if req.status in [0, 304]
|
|
||||||
[null, null]
|
[null, null]
|
||||||
else
|
else
|
||||||
["#{req.statusText} (#{req.status})", 'warning']
|
["#{req.statusText} (#{req.status})", 'warning']
|
||||||
|
|||||||
@ -182,9 +182,7 @@ Unread =
|
|||||||
else
|
else
|
||||||
Favicon.default
|
Favicon.default
|
||||||
|
|
||||||
<% if (type !== 'crx') { %>
|
<% if (type === 'userscript') { %>
|
||||||
# `favicon.href = href` doesn't work on Firefox.
|
# `favicon.href = href` doesn't work on Firefox.
|
||||||
# `favicon.href = href` isn't enough on Opera.
|
|
||||||
# Opera won't always update the favicon if the href didn't change.
|
|
||||||
$.add d.head, Favicon.el
|
$.add d.head, Favicon.el
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|||||||
@ -330,7 +330,6 @@ QR =
|
|||||||
post = Get.postFromNode @
|
post = Get.postFromNode @
|
||||||
text = ">>#{post}\n"
|
text = ">>#{post}\n"
|
||||||
if (s = sel.toString().trim()) and post is Get.postFromNode sel.anchorNode
|
if (s = sel.toString().trim()) and post is Get.postFromNode sel.anchorNode
|
||||||
# XXX Opera doesn't retain `\n`s?
|
|
||||||
s = s.replace /\n/g, '\n>'
|
s = s.replace /\n/g, '\n>'
|
||||||
text += ">#{s}\n"
|
text += ">#{s}\n"
|
||||||
|
|
||||||
@ -501,7 +500,6 @@ QR =
|
|||||||
else if @ is QR.selected
|
else if @ is QR.selected
|
||||||
(QR.posts[index-1] or QR.posts[index+1]).select()
|
(QR.posts[index-1] or QR.posts[index+1]).select()
|
||||||
QR.posts.splice index, 1
|
QR.posts.splice index, 1
|
||||||
return unless window.URL
|
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
lock: (lock=true) ->
|
lock: (lock=true) ->
|
||||||
@isLocked = lock
|
@isLocked = lock
|
||||||
@ -558,25 +556,14 @@ QR =
|
|||||||
@filename = "#{file.name} (#{$.bytesToString file.size})"
|
@filename = "#{file.name} (#{$.bytesToString file.size})"
|
||||||
@nodes.el.title = @filename
|
@nodes.el.title = @filename
|
||||||
@nodes.label.hidden = false if QR.spoiler
|
@nodes.label.hidden = false if QR.spoiler
|
||||||
URL.revokeObjectURL @URL if window.URL
|
URL.revokeObjectURL @URL
|
||||||
@showFileData()
|
@showFileData()
|
||||||
unless /^image/.test file.type
|
unless /^image/.test file.type
|
||||||
@nodes.el.style.backgroundImage = null
|
@nodes.el.style.backgroundImage = null
|
||||||
return
|
return
|
||||||
@setThumbnail()
|
@setThumbnail()
|
||||||
setThumbnail: (fileURL) ->
|
setThumbnail: ->
|
||||||
# XXX Opera does not support blob URL
|
|
||||||
# Create a redimensioned thumbnail.
|
# Create a redimensioned thumbnail.
|
||||||
unless window.URL
|
|
||||||
unless fileURL
|
|
||||||
reader = new FileReader()
|
|
||||||
reader.onload = (e) =>
|
|
||||||
@setThumbnail e.target.result
|
|
||||||
reader.readAsDataURL @file
|
|
||||||
return
|
|
||||||
else
|
|
||||||
fileURL = URL.createObjectURL @file
|
|
||||||
|
|
||||||
img = $.el 'img'
|
img = $.el 'img'
|
||||||
|
|
||||||
img.onload = =>
|
img.onload = =>
|
||||||
@ -588,7 +575,7 @@ QR =
|
|||||||
s *= 3 if @file.type is 'image/gif' # let them animate
|
s *= 3 if @file.type is 'image/gif' # let them animate
|
||||||
{height, width} = img
|
{height, width} = img
|
||||||
if height < s or width < s
|
if height < s or width < s
|
||||||
@URL = fileURL if window.URL
|
@URL = fileURL
|
||||||
@nodes.el.style.backgroundImage = "url(#{@URL})"
|
@nodes.el.style.backgroundImage = "url(#{@URL})"
|
||||||
return
|
return
|
||||||
if height <= width
|
if height <= width
|
||||||
@ -601,10 +588,6 @@ QR =
|
|||||||
cv.height = img.height = height
|
cv.height = img.height = height
|
||||||
cv.width = img.width = width
|
cv.width = img.width = width
|
||||||
cv.getContext('2d').drawImage img, 0, 0, width, height
|
cv.getContext('2d').drawImage img, 0, 0, width, height
|
||||||
unless window.URL
|
|
||||||
@nodes.el.style.backgroundImage = "url(#{cv.toDataURL()})"
|
|
||||||
delete @URL
|
|
||||||
return
|
|
||||||
URL.revokeObjectURL fileURL
|
URL.revokeObjectURL fileURL
|
||||||
applyBlob = (blob) =>
|
applyBlob = (blob) =>
|
||||||
@URL = URL.createObjectURL blob
|
@URL = URL.createObjectURL blob
|
||||||
@ -622,6 +605,7 @@ QR =
|
|||||||
|
|
||||||
applyBlob new Blob [ui8a], type: 'image/png'
|
applyBlob new Blob [ui8a], type: 'image/png'
|
||||||
|
|
||||||
|
fileURL = URL.createObjectURL @file
|
||||||
img.src = fileURL
|
img.src = fileURL
|
||||||
rmFile: ->
|
rmFile: ->
|
||||||
delete @file
|
delete @file
|
||||||
@ -630,7 +614,6 @@ QR =
|
|||||||
@nodes.el.style.backgroundImage = null
|
@nodes.el.style.backgroundImage = null
|
||||||
@nodes.label.hidden = true if QR.spoiler
|
@nodes.label.hidden = true if QR.spoiler
|
||||||
@showFileData()
|
@showFileData()
|
||||||
return unless window.URL
|
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
showFileData: ->
|
showFileData: ->
|
||||||
if @file
|
if @file
|
||||||
@ -652,22 +635,17 @@ QR =
|
|||||||
QR.nodes.com.value = @com
|
QR.nodes.com.value = @com
|
||||||
@nodes.span.textContent = @com
|
@nodes.span.textContent = @com
|
||||||
reader.readAsText file
|
reader.readAsText file
|
||||||
dragStart: ->
|
dragStart: -> $.addClass @, 'drag'
|
||||||
$.addClass @, 'drag'
|
dragEnd: -> $.rmClass @, 'drag'
|
||||||
dragEnd: ->
|
dragEnter: -> $.addClass @, 'over'
|
||||||
$.rmClass @, 'drag'
|
dragLeave: -> $.rmClass @, 'over'
|
||||||
dragEnter: ->
|
|
||||||
$.addClass @, 'over'
|
|
||||||
dragLeave: ->
|
|
||||||
$.rmClass @, 'over'
|
|
||||||
dragOver: (e) ->
|
dragOver: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.dataTransfer.dropEffect = 'move'
|
e.dataTransfer.dropEffect = 'move'
|
||||||
drop: ->
|
drop: ->
|
||||||
el = $ '.drag', @parentNode
|
$.rmClass @, 'over'
|
||||||
$.rmClass el, 'drag' # Opera doesn't fire dragEnd if we drop it on something else
|
|
||||||
$.rmClass @, 'over'
|
|
||||||
return unless @draggable
|
return unless @draggable
|
||||||
|
el = $ '.drag', @parentNode
|
||||||
index = (el) -> [el.parentNode.children...].indexOf el
|
index = (el) -> [el.parentNode.children...].indexOf el
|
||||||
oldIndex = index el
|
oldIndex = index el
|
||||||
newIndex = index @
|
newIndex = index @
|
||||||
@ -700,12 +678,8 @@ QR =
|
|||||||
img: imgContainer.firstChild
|
img: imgContainer.firstChild
|
||||||
input: input
|
input: input
|
||||||
|
|
||||||
if window.MutationObserver
|
new MutationObserver(@load.bind @).observe @nodes.challenge,
|
||||||
observer = new MutationObserver @load.bind @
|
childList: true
|
||||||
observer.observe @nodes.challenge,
|
|
||||||
childList: true
|
|
||||||
else
|
|
||||||
$.on @nodes.challenge, 'DOMNodeInserted', @load.bind @
|
|
||||||
|
|
||||||
$.on imgContainer, 'click', @reload.bind @
|
$.on imgContainer, 'click', @reload.bind @
|
||||||
$.on input, 'keydown', @keydown.bind @
|
$.on input, 'keydown', @keydown.bind @
|
||||||
@ -836,10 +810,6 @@ QR =
|
|||||||
# Add empty mimeType to avoid errors with URLs selected in Window's file dialog.
|
# Add empty mimeType to avoid errors with URLs selected in Window's file dialog.
|
||||||
QR.mimeTypes.push ''
|
QR.mimeTypes.push ''
|
||||||
nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value
|
nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value
|
||||||
<% if (type !== 'userjs') { %>
|
|
||||||
# Opera's accept attribute is fucked up
|
|
||||||
nodes.fileInput.accept = "text/*, #{mimeTypes}"
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
QR.spoiler = !!$ 'input[name=spoiler]'
|
QR.spoiler = !!$ 'input[name=spoiler]'
|
||||||
nodes.spoiler.hidden = !QR.spoiler
|
nodes.spoiler.hidden = !QR.spoiler
|
||||||
@ -1018,11 +988,6 @@ QR =
|
|||||||
QR.status()
|
QR.status()
|
||||||
|
|
||||||
response: ->
|
response: ->
|
||||||
<% if (type === 'userjs') { %>
|
|
||||||
# The upload.onload callback is not called
|
|
||||||
# or at least not in time with Opera.
|
|
||||||
QR.req.upload.onload()
|
|
||||||
<% } %>
|
|
||||||
{req} = QR
|
{req} = QR
|
||||||
delete QR.req
|
delete QR.req
|
||||||
|
|
||||||
|
|||||||
@ -28,21 +28,6 @@ QuotePreview =
|
|||||||
cb: QuotePreview.mouseout
|
cb: QuotePreview.mouseout
|
||||||
asapTest: -> qp.firstElementChild
|
asapTest: -> qp.firstElementChild
|
||||||
|
|
||||||
<% if (type === 'userjs') { %>
|
|
||||||
# XXX Opera workaround for "no mouseout fired" bug.
|
|
||||||
# Remove it once Opera uses Blink.
|
|
||||||
root = @
|
|
||||||
workaround = (e) ->
|
|
||||||
if @ is root
|
|
||||||
e.stopPropagation()
|
|
||||||
return
|
|
||||||
$.event 'mouseout', null, root
|
|
||||||
$.off d, 'mousemove', workaround
|
|
||||||
$.off root, 'mousemove', workaround
|
|
||||||
$.on d, 'mousemove', workaround
|
|
||||||
$.on root, 'mousemove', workaround
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
return unless origin = g.posts["#{boardID}.#{postID}"]
|
return unless origin = g.posts["#{boardID}.#{postID}"]
|
||||||
|
|
||||||
if Conf['Quote Highlighting']
|
if Conf['Quote Highlighting']
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user