Merge tag 'beta' into unreadcount
4chan X v1.8.7. Conflicts: CHANGELOG.md LICENSE builds/4chan-X-beta.crx builds/4chan-X-beta.meta.js builds/4chan-X-beta.user.js builds/4chan-X-noupdate.crx builds/4chan-X-noupdate.user.js builds/4chan-X.crx builds/4chan-X.meta.js builds/4chan-X.user.js builds/4chan-X.zip builds/updates-beta.xml builds/updates.xml package.json
37
CHANGELOG.md
@ -1,3 +1,21 @@
|
|||||||
|
**ccd0**
|
||||||
|
- Fix unread count updating bug in Firefox as in v1.8.6.2.
|
||||||
|
|
||||||
|
### v1.8.7
|
||||||
|
*2014-07-20*
|
||||||
|
|
||||||
|
Based on v1.8.6.1.
|
||||||
|
|
||||||
|
**ccd0**
|
||||||
|
- Various bugfixes.
|
||||||
|
|
||||||
|
**MayhemYDG**
|
||||||
|
- Improvements to Chrom* storage API.
|
||||||
|
|
||||||
|
**Zixaphir**
|
||||||
|
- Add gallery option `Scroll to Post`: Scrolls to the post containing the currently active image.
|
||||||
|
- Gallery now loops.
|
||||||
|
|
||||||
### v1.8.6.2
|
### v1.8.6.2
|
||||||
*2014-07-23*
|
*2014-07-23*
|
||||||
|
|
||||||
@ -67,7 +85,6 @@
|
|||||||
- Begin making available a version of the script with the updater disabled.
|
- Begin making available a version of the script with the updater disabled.
|
||||||
- The removal of slugs from the URL when you open a thread is now optional, and can be disabled by unchecking `Normalize URL`.
|
- The removal of slugs from the URL when you open a thread is now optional, and can be disabled by unchecking `Normalize URL`.
|
||||||
- The boards and file extensions for which a Sauce link is displayed can now be controlled by adding `;boards:[list]` and `types:[list]` respectively.
|
- The boards and file extensions for which a Sauce link is displayed can now be controlled by adding `;boards:[list]` and `types:[list]` respectively.
|
||||||
- Restrict Sauce links to `http` and `https` to prevent malicious script installation.
|
|
||||||
- Although usually not needed, `%%` can be used in format specifiers to write a literal `%`.
|
- Although usually not needed, `%%` can be used in format specifiers to write a literal `%`.
|
||||||
- Various bugfixes.
|
- Various bugfixes.
|
||||||
|
|
||||||
@ -647,7 +664,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
**Spittie**
|
**Spittie**
|
||||||
- Check image dimension before uploading
|
- Check image dimension before uploading
|
||||||
|
|
||||||

|

|
||||||
- Bug fixes
|
- Bug fixes
|
||||||
- Update archives
|
- Update archives
|
||||||
|
|
||||||
@ -695,7 +712,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
**Spittie**
|
**Spittie**
|
||||||
- Upload images directly from urls
|
- Upload images directly from urls
|
||||||
|
|
||||||

|

|
||||||
- Add gfycat.com embedding
|
- Add gfycat.com embedding
|
||||||
- Replace some icons with fontawesome
|
- Replace some icons with fontawesome
|
||||||
- Add Metro favicons (lel)
|
- Add Metro favicons (lel)
|
||||||
@ -771,7 +788,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
- The last index refresh timer will now indicate the last time the index changed from 4chan's side, instead of the last time you refreshed the index.
|
- The last index refresh timer will now indicate the last time the index changed from 4chan's side, instead of the last time you refreshed the index.
|
||||||
- You can now refresh the index page you are on with the refresh shortcut in the header bar or the same keybind for refreshing threads.
|
- You can now refresh the index page you are on with the refresh shortcut in the header bar or the same keybind for refreshing threads.
|
||||||
- You can now switch between paged and all-threads index modes via the "Index Navigation" header sub-menu (note that this replaces infinite scrolling):<br>
|
- You can now switch between paged and all-threads index modes via the "Index Navigation" header sub-menu (note that this replaces infinite scrolling):<br>
|
||||||

|

|
||||||
- Threads in the index can now be sorted by:
|
- Threads in the index can now be sorted by:
|
||||||
<ul>
|
<ul>
|
||||||
<li> Bump order
|
<li> Bump order
|
||||||
@ -881,7 +898,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
|
|
||||||
**Zixaphir**:
|
**Zixaphir**:
|
||||||
- Fix an issue with the file dialog randomly opening multiple times (with seaweedchan)
|
- Fix an issue with the file dialog randomly opening multiple times (with seaweedchan)
|
||||||

|

|
||||||
- Add new feature: `Gallery`.
|
- Add new feature: `Gallery`.
|
||||||
* Opens images in a lightweight Gallery script.
|
* Opens images in a lightweight Gallery script.
|
||||||
* If enabled while Image Expansion is disabled, will takeover as the default action when images are clicked.
|
* If enabled while Image Expansion is disabled, will takeover as the default action when images are clicked.
|
||||||
@ -932,7 +949,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
|
|
||||||
**seaweedchan**:
|
**seaweedchan**:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Ported `Custom Board Titles` feature from Appchan X (with Zixaphir)
|
- Ported `Custom Board Titles` feature from Appchan X (with Zixaphir)
|
||||||
- This allows you to edit the board title and subtitle in real-time by ctrl+clicking them
|
- This allows you to edit the board title and subtitle in real-time by ctrl+clicking them
|
||||||
@ -963,7 +980,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
|
|
||||||
**MayhemYDG**:
|
**MayhemYDG**:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Greatly improved thread watcher
|
- Greatly improved thread watcher
|
||||||
- Added submenu with ability to prune 404'd threads, filter by current board, etc
|
- Added submenu with ability to prune 404'd threads, filter by current board, etc
|
||||||
@ -978,7 +995,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
|
|
||||||
**Zixaphir**:
|
**Zixaphir**:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Drastically improved the accuracy and quality of the linkifier (with seaweedchan)
|
- Drastically improved the accuracy and quality of the linkifier (with seaweedchan)
|
||||||
- Removed `Allow False Positives` option due to the accuracy of the new linkifier regex
|
- Removed `Allow False Positives` option due to the accuracy of the new linkifier regex
|
||||||
@ -1220,7 +1237,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
**seaweedchan**:
|
**seaweedchan**:
|
||||||
- Small bug fixes
|
- Small bug fixes
|
||||||
|
|
||||||
## v1.2.0 - "Youmu" 
|
## v1.2.0 - "Youmu" 
|
||||||
*2013-05-10*
|
*2013-05-10*
|
||||||
|
|
||||||
**MayhemYDG**:
|
**MayhemYDG**:
|
||||||
@ -1252,7 +1269,7 @@ Remove /v/ from stable Foolz archive.
|
|||||||
- QR with 4chan Pass made a little wider
|
- QR with 4chan Pass made a little wider
|
||||||
- Styling changes for spoiler label, also added `.has-spoiler` class for QR
|
- Styling changes for spoiler label, also added `.has-spoiler` class for QR
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### v1.1.17
|
### v1.1.17
|
||||||
*2013-05-08*
|
*2013-05-08*
|
||||||
|
|||||||
@ -180,16 +180,6 @@ module.exports = (grunt) ->
|
|||||||
pkg = grunt.config 'pkg'
|
pkg = grunt.config 'pkg'
|
||||||
pkg.type = type
|
pkg.type = type
|
||||||
grunt.config 'pkg', pkg
|
grunt.config 'pkg', pkg
|
||||||
|
|
||||||
if type is 'crx'
|
|
||||||
pkg.align = '-webkit-align'
|
|
||||||
pkg.justify = '-webkit-justify-content'
|
|
||||||
pkg.transform = '-webkit-transform'
|
|
||||||
else
|
|
||||||
pkg.align = 'align'
|
|
||||||
pkg.justify = 'justify-content'
|
|
||||||
pkg.transform = 'transform'
|
|
||||||
|
|
||||||
grunt.log.ok 'pkg.type = %s', type
|
grunt.log.ok 'pkg.type = %s', type
|
||||||
|
|
||||||
grunt.registerTask 'set-channel', 'Set the update channel', (channel) ->
|
grunt.registerTask 'set-channel', 'Set the update channel', (channel) ->
|
||||||
|
|||||||
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.8.6.2 - 2014-07-23
|
* 4chan X - Version 1.8.7 - 2014-07-20
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
||||||
|
|||||||
14
README.md
@ -6,7 +6,10 @@ https://github.com/Nebukazar/OneeChan
|
|||||||
## [Install](https://ccd0.github.io/4chan-x/builds/4chan-X.user.js) (Firefox)
|
## [Install](https://ccd0.github.io/4chan-x/builds/4chan-X.user.js) (Firefox)
|
||||||
Install [Greasemonkey](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/), then click the link above to install.
|
Install [Greasemonkey](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/), then click the link above to install.
|
||||||
|
|
||||||
**Note**: The combination of Firefox 29 and Greasemonkey 2.0 may cause 4chan X not to work.
|
You may want to try the [Greasemonkey 2.1 beta](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/versions/2.1beta1), which fixes bugs in 2.0 that can prevent 4chan X from updating[[1]](https://github.com/greasemonkey/greasemonkey/issues/1938) or, in some versions of Firefox, break posting images from URLs and downloading with the original filename[[2]](https://github.com/greasemonkey/greasemonkey/issues/1937).
|
||||||
|
|
||||||
|
### Known issues
|
||||||
|
The combination of Firefox 29 and Greasemonkey 2.0 may cause 4chan X not to work.
|
||||||
Try [upgrading Firefox](http://www.mozilla.org/en-US/firefox/new/) to version 30 or higher.
|
Try [upgrading Firefox](http://www.mozilla.org/en-US/firefox/new/) to version 30 or higher.
|
||||||
Alternatively, you can downgrade to [Greasemonkey 1.15](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/versions/#version-1.15) and turn off automatic updates for Greasemonkey ([see pic](https://raw.githubusercontent.com/ccd0/4chan-x/master/img/2014-07-12_16-19-32.png)).
|
Alternatively, you can downgrade to [Greasemonkey 1.15](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/versions/#version-1.15) and turn off automatic updates for Greasemonkey ([see pic](https://raw.githubusercontent.com/ccd0/4chan-x/master/img/2014-07-12_16-19-32.png)).
|
||||||
|
|
||||||
@ -16,6 +19,9 @@ This should also work for non-Windows/dev/canary Chrome and Chromium-based versi
|
|||||||
|
|
||||||
**Note**: The stable and beta releases of Chrome on Windows will disable extensions not installed from the Chrome store, so users will need to install 4chan X from [here](https://chrome.google.com/webstore/detail/4chan-x/ohnjgmpcibpbafdlkimncjhflgedgpam).
|
**Note**: The stable and beta releases of Chrome on Windows will disable extensions not installed from the Chrome store, so users will need to install 4chan X from [here](https://chrome.google.com/webstore/detail/4chan-x/ohnjgmpcibpbafdlkimncjhflgedgpam).
|
||||||
|
|
||||||
|
### Known issues
|
||||||
|
Some recent versions of Chromium/Chrome (starting at 38.0.2085.0) suffer from a [bug](https://crbug.com/393686) that prevents extensions from making HTTP requests in the usual way. This breaks, among other things, thread updating, quick reply, and, when `JSON Navigation` is enabled, the thread index. Until this is fixed, try another version or a different browser.
|
||||||
|
|
||||||
## Other browsers
|
## Other browsers
|
||||||
This fork of 4chan X is not guaranteed to work correctly in other browsers, but you are welcome to try your luck. Pull requests to fix the bugs you will likely find are always welcome.
|
This fork of 4chan X is not guaranteed to work correctly in other browsers, but you are welcome to try your luck. Pull requests to fix the bugs you will likely find are always welcome.
|
||||||
|
|
||||||
@ -32,7 +38,7 @@ New features and non-urgent bugfixes are released on the beta channel for furthe
|
|||||||
- [Firefox version](https://ccd0.github.io/4chan-x/builds/4chan-X-beta.user.js)
|
- [Firefox version](https://ccd0.github.io/4chan-x/builds/4chan-X-beta.user.js)
|
||||||
- [Chromium version](https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx)
|
- [Chromium version](https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx)
|
||||||
|
|
||||||
## [Frequently Asked Questions](https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions)
|
## More information
|
||||||
|
### [Frequently Asked Questions](https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions)
|
||||||
## [Reporting Bugs and Contributing](https://github.com/ccd0/4chan-x/blob/master/CONTRIBUTING.md)
|
### [Reporting Bugs and Contributing](https://github.com/ccd0/4chan-x/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan X
|
// @name 4chan X
|
||||||
// @version 1.8.6.2
|
// @version 1.8.7
|
||||||
// @minGMVer 1.14
|
// @minGMVer 1.14
|
||||||
// @minFFVer 26
|
// @minFFVer 26
|
||||||
// @namespace 4chan-X
|
// @namespace 4chan-X
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan X
|
// @name 4chan X
|
||||||
// @version 1.8.6.2
|
// @version 1.8.7
|
||||||
// @minGMVer 1.14
|
// @minGMVer 1.14
|
||||||
// @minFFVer 26
|
// @minFFVer 26
|
||||||
// @namespace 4chan-X
|
// @namespace 4chan-X
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.8.6.2' />
|
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.8.7' />
|
||||||
</app>
|
</app>
|
||||||
</gupdate>
|
</gupdate>
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.8.6.2' />
|
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.8.7' />
|
||||||
</app>
|
</app>
|
||||||
</gupdate>
|
</gupdate>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 355 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "4chan-X",
|
"name": "4chan-X",
|
||||||
"version": "1.8.6.2",
|
"version": "1.8.7",
|
||||||
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "4chan X",
|
"name": "4chan X",
|
||||||
|
|||||||
@ -448,13 +448,15 @@ Config =
|
|||||||
'Hide Thumbnails': [
|
'Hide Thumbnails': [
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
# Fit Width =/= Fit width
|
'Fit Width': [ # 'Fit width' (lowercase W) belongs to Image Expansion. Engine limitations, heh.
|
||||||
'Fit Width': [
|
|
||||||
true
|
true
|
||||||
]
|
]
|
||||||
'Fit Height': [
|
'Fit Height': [
|
||||||
true
|
true
|
||||||
]
|
]
|
||||||
|
'Scroll to Post': [
|
||||||
|
true
|
||||||
|
]
|
||||||
'Slide Delay': [
|
'Slide Delay': [
|
||||||
5.0
|
5.0
|
||||||
]
|
]
|
||||||
|
|||||||
@ -360,7 +360,7 @@ Header =
|
|||||||
editCustomNav: ->
|
editCustomNav: ->
|
||||||
Settings.open 'Advanced'
|
Settings.open 'Advanced'
|
||||||
settings = $.id 'fourchanx-settings'
|
settings = $.id 'fourchanx-settings'
|
||||||
$('input[name=boardnav]', settings).focus()
|
$('textarea[name=boardnav]', settings).focus()
|
||||||
|
|
||||||
hashScroll: ->
|
hashScroll: ->
|
||||||
hash = @location.hash[1..]
|
hash = @location.hash[1..]
|
||||||
|
|||||||
@ -147,6 +147,7 @@ Index =
|
|||||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
switch e.target.nodeName
|
switch e.target.nodeName
|
||||||
when 'BUTTON'
|
when 'BUTTON'
|
||||||
|
e.target.blur()
|
||||||
a = e.target.parentNode
|
a = e.target.parentNode
|
||||||
when 'A'
|
when 'A'
|
||||||
a = e.target
|
a = e.target
|
||||||
|
|||||||
@ -35,7 +35,7 @@ Main =
|
|||||||
Conf['CachedTitles'] = []
|
Conf['CachedTitles'] = []
|
||||||
$.get Conf, (items) ->
|
$.get Conf, (items) ->
|
||||||
$.extend Conf, items
|
$.extend Conf, items
|
||||||
$.asap (-> doc = d.documentElement), Main.initFeatures
|
Main.initFeatures()
|
||||||
|
|
||||||
$.on d, '4chanMainInit', Main.initStyle
|
$.on d, '4chanMainInit', Main.initStyle
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ Main =
|
|||||||
return if !Main.isThisPageLegit() or $.hasClass doc, 'fourchan-x'
|
return if !Main.isThisPageLegit() or $.hasClass doc, 'fourchan-x'
|
||||||
# disable the mobile layout
|
# disable the mobile layout
|
||||||
$('link[href*=mobile]', d.head)?.disabled = true
|
$('link[href*=mobile]', d.head)?.disabled = true
|
||||||
$.addClass doc, 'fourchan-x', 'seaweedchan', g.VIEW, '<% if (type === 'crx') { %>blink<% } else { %>gecko<% } %>'
|
$.addClass doc, 'fourchan-x', 'seaweedchan', g.VIEW, if chrome? then 'blink' else 'gecko'
|
||||||
$.addStyle Main.css
|
$.addStyle Main.css
|
||||||
|
|
||||||
Main.setClass()
|
Main.setClass()
|
||||||
@ -335,4 +335,4 @@ Main =
|
|||||||
<% } %>
|
<% } %>
|
||||||
]
|
]
|
||||||
|
|
||||||
Main.init()
|
$.asap (-> (doc = d.documentElement) and d.head), Main.init
|
||||||
|
|||||||
@ -313,9 +313,9 @@ Settings =
|
|||||||
interval.value = Conf['Interval']
|
interval.value = Conf['Interval']
|
||||||
customCSS.checked = Conf['Custom CSS']
|
customCSS.checked = Conf['Custom CSS']
|
||||||
inputs['usercss'].disabled = !Conf['Custom CSS']
|
inputs['usercss'].disabled = !Conf['Custom CSS']
|
||||||
$.on interval, 'change', ThreadUpdater.cb.interval
|
$.on interval, 'change', ThreadUpdater.cb.interval
|
||||||
$.on customCSS, 'change', Settings.togglecss
|
$.on customCSS, 'change', Settings.togglecss
|
||||||
$.on $.id('apply-css'), 'click', Settings.usercss
|
$.on $('#apply-css', section), 'click', Settings.usercss
|
||||||
|
|
||||||
archBoards = {}
|
archBoards = {}
|
||||||
for {name, boards, files, software, withCredentials} in Redirect.archives
|
for {name, boards, files, software, withCredentials} in Redirect.archives
|
||||||
@ -357,7 +357,7 @@ Settings =
|
|||||||
|
|
||||||
boardSelect = $('#archive-board-select', section)
|
boardSelect = $('#archive-board-select', section)
|
||||||
$.add boardSelect, boardOptions
|
$.add boardSelect, boardOptions
|
||||||
table = $.id 'archive-table'
|
table = $('#archive-table', section)
|
||||||
$.on boardSelect, 'change', ->
|
$.on boardSelect, 'change', ->
|
||||||
$('tbody > :not([hidden])', table).hidden = true
|
$('tbody > :not([hidden])', table).hidden = true
|
||||||
$("tbody > .#{@value}", table).hidden = false
|
$("tbody > .#{@value}", table).hidden = false
|
||||||
|
|||||||
@ -849,7 +849,9 @@ span.hide-announcement {
|
|||||||
}
|
}
|
||||||
.persona {
|
.persona {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
#dump-button {
|
#dump-button {
|
||||||
@ -869,6 +871,7 @@ span.hide-announcement {
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
.persona .field {
|
.persona .field {
|
||||||
|
-webkit-flex: 1;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
@ -1279,22 +1282,32 @@ div.boardTitle {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
background: rgba(0,0,0,0.7);
|
background: rgba(0,0,0,0.7);
|
||||||
}
|
}
|
||||||
.gal-viewport {
|
.gal-viewport {
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
<%= align %>-items: stretch;
|
-webkit-align-items: stretch;
|
||||||
|
align-items: stretch;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
-webkit-flex: 1 1 auto;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
.gal-thumbnails {
|
.gal-thumbnails {
|
||||||
|
-webkit-flex: 0 0 150px;
|
||||||
flex: 0 0 150px;
|
flex: 0 0 150px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-flex-direction: column;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
<%= align %>-items: stretch;
|
-webkit-align-items: stretch;
|
||||||
|
align-items: stretch;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: rgba(0,0,0,.5);
|
background: rgba(0,0,0,.5);
|
||||||
border-left: 1px solid #222;
|
border-left: 1px solid #222;
|
||||||
@ -1309,6 +1322,7 @@ div.boardTitle {
|
|||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
.gal-thumb {
|
.gal-thumb {
|
||||||
|
-webkit-flex: 0 0 auto;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
@ -1327,6 +1341,7 @@ div.boardTitle {
|
|||||||
}
|
}
|
||||||
.gal-prev,
|
.gal-prev,
|
||||||
.gal-next {
|
.gal-next {
|
||||||
|
-webkit-flex: 0 0 20px;
|
||||||
flex: 0 0 20px;
|
flex: 0 0 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -1341,7 +1356,8 @@ div.boardTitle {
|
|||||||
.gal-next::after {
|
.gal-next::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 48.6%;
|
top: 48.6%;
|
||||||
<%= transform %>: translateY(-50%)
|
-webkit-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-top: 11px solid transparent;
|
border-top: 11px solid transparent;
|
||||||
border-bottom: 11px solid transparent;
|
border-bottom: 11px solid transparent;
|
||||||
@ -1357,10 +1373,14 @@ div.boardTitle {
|
|||||||
}
|
}
|
||||||
.gal-image {
|
.gal-image {
|
||||||
order: 1;
|
order: 1;
|
||||||
|
-webkit-flex: 1 0 auto;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
<%= align %>-items: flex-start;
|
-webkit-align-items: flex-start;
|
||||||
<%= justify %>: space-around;
|
align-items: flex-start;
|
||||||
|
-webkit-justify-content: space-around;
|
||||||
|
justify-content: space-around;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
/* Flex > Non-Flex child max-width and overflow fix (Firefox only?) */
|
/* Flex > Non-Flex child max-width and overflow fix (Firefox only?) */
|
||||||
width: 1%;
|
width: 1%;
|
||||||
|
|||||||
@ -42,11 +42,24 @@ $.ajax = do ->
|
|||||||
# With the `If-Modified-Since` header we only receive the HTTP headers and no body for 304 responses.
|
# With the `If-Modified-Since` header we only receive the HTTP headers and no body for 304 responses.
|
||||||
# This saves a lot of bandwidth and CPU time for both the users and the servers.
|
# This saves a lot of bandwidth and CPU time for both the users and the servers.
|
||||||
lastModified = {}
|
lastModified = {}
|
||||||
|
blockedURLs = {}
|
||||||
|
blockedError = (url) ->
|
||||||
|
return if blockedURLs[url]
|
||||||
|
blockedURLs[url] = true
|
||||||
|
h_message = '<%= meta.name %> was blocked from loading the following URL:<br><span></span><br>'
|
||||||
|
h_message += '[<a href="<%= meta.faq %>#why-was-4chan-x-blocked-from-loading-a-url" target="_blank">More info</a>]'
|
||||||
|
message = $.el 'div', innerHTML: h_message
|
||||||
|
$('span', message).textContent = (if /^\/\//.test url then location.protocol else '') + url
|
||||||
|
new Notice 'error', message, 30, -> delete blockedURLs[url]
|
||||||
(url, options, extra={}) ->
|
(url, options, extra={}) ->
|
||||||
{type, whenModified, upCallbacks, form} = extra
|
{type, whenModified, upCallbacks, form} = extra
|
||||||
r = new XMLHttpRequest()
|
r = new XMLHttpRequest()
|
||||||
type or= form and 'post' or 'get'
|
type or= form and 'post' or 'get'
|
||||||
r.open type, url, true
|
try
|
||||||
|
r.open type, url, true
|
||||||
|
catch err
|
||||||
|
blockedError url
|
||||||
|
return options.onerror?()
|
||||||
if whenModified
|
if whenModified
|
||||||
r.setRequestHeader 'If-Modified-Since', lastModified[url] if url of lastModified
|
r.setRequestHeader 'If-Modified-Since', lastModified[url] if url of lastModified
|
||||||
$.on r, 'load', -> lastModified[url] = r.getResponseHeader 'Last-Modified'
|
$.on r, 'load', -> lastModified[url] = r.getResponseHeader 'Last-Modified'
|
||||||
@ -275,9 +288,6 @@ $.sync = do ->
|
|||||||
cb changes[key].newValue, key
|
cb changes[key].newValue, key
|
||||||
return
|
return
|
||||||
(key, cb) -> $.syncing[key] = cb
|
(key, cb) -> $.syncing[key] = cb
|
||||||
|
|
||||||
$.desync = (key) -> delete $.syncing[key]
|
|
||||||
|
|
||||||
$.localKeys = [
|
$.localKeys = [
|
||||||
# filters
|
# filters
|
||||||
'name',
|
'name',
|
||||||
@ -295,85 +305,99 @@ $.localKeys = [
|
|||||||
# custom css
|
# custom css
|
||||||
'usercss'
|
'usercss'
|
||||||
]
|
]
|
||||||
|
|
||||||
# https://developer.chrome.com/extensions/storage.html
|
# https://developer.chrome.com/extensions/storage.html
|
||||||
|
do ->
|
||||||
$.delete = (keys) ->
|
|
||||||
chrome.storage.sync.remove keys
|
|
||||||
|
|
||||||
$.get = (key, val, cb) ->
|
|
||||||
if typeof cb is 'function'
|
|
||||||
items = $.item key, val
|
|
||||||
else
|
|
||||||
items = key
|
|
||||||
cb = val
|
|
||||||
localItems = null
|
|
||||||
syncItems = null
|
|
||||||
for key, val of items
|
|
||||||
if key in $.localKeys
|
|
||||||
(localItems or= {})[key] = val
|
|
||||||
else
|
|
||||||
(syncItems or= {})[key] = val
|
|
||||||
|
|
||||||
count = 0
|
|
||||||
done = (item) ->
|
|
||||||
if chrome.runtime.lastError
|
|
||||||
c.error chrome.runtime.lastError.message
|
|
||||||
$.extend items, item
|
|
||||||
cb items unless --count
|
|
||||||
|
|
||||||
if localItems
|
|
||||||
count++
|
|
||||||
chrome.storage.local.get localItems, done
|
|
||||||
if syncItems
|
|
||||||
count++
|
|
||||||
chrome.storage.sync.get syncItems, done
|
|
||||||
|
|
||||||
$.set = do ->
|
|
||||||
items =
|
items =
|
||||||
sync: {}
|
|
||||||
local: {}
|
local: {}
|
||||||
timeout = {}
|
sync: {}
|
||||||
|
|
||||||
|
$.delete = (keys) ->
|
||||||
|
if typeof keys is 'string'
|
||||||
|
keys = [keys]
|
||||||
|
local = []
|
||||||
|
sync = []
|
||||||
|
for key in keys
|
||||||
|
if key in $.localKeys
|
||||||
|
local.push key
|
||||||
|
delete items.local[key]
|
||||||
|
else
|
||||||
|
sync.push key
|
||||||
|
delete items.sync[key]
|
||||||
|
chrome.storage.local.remove local
|
||||||
|
chrome.storage.sync.remove sync
|
||||||
|
|
||||||
|
$.get = (key, val, cb) ->
|
||||||
|
if typeof cb is 'function'
|
||||||
|
data = $.item key, val
|
||||||
|
else
|
||||||
|
data = key
|
||||||
|
cb = val
|
||||||
|
|
||||||
|
localItems = null
|
||||||
|
syncItems = null
|
||||||
|
for key, val of data
|
||||||
|
if key in $.localKeys
|
||||||
|
(localItems or= {})[key] = val
|
||||||
|
else
|
||||||
|
(syncItems or= {})[key] = val
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
done = (result) ->
|
||||||
|
if chrome.runtime.lastError
|
||||||
|
c.error chrome.runtime.lastError.message
|
||||||
|
$.extend data, result
|
||||||
|
cb data unless --count
|
||||||
|
|
||||||
|
if localItems
|
||||||
|
count++
|
||||||
|
chrome.storage.local.get localItems, done
|
||||||
|
if syncItems
|
||||||
|
count++
|
||||||
|
chrome.storage.sync.get syncItems, done
|
||||||
|
|
||||||
|
timeout = {}
|
||||||
setArea = (area) ->
|
setArea = (area) ->
|
||||||
data = items[area]
|
data = items[area]
|
||||||
return if !Object.keys(data).length or timeout[area]
|
return if !Object.keys(data).length or timeout[area] > Date.now()
|
||||||
items[area] = {}
|
|
||||||
chrome.storage[area].set data, ->
|
chrome.storage[area].set data, ->
|
||||||
if chrome.runtime.lastError
|
if chrome.runtime.lastError
|
||||||
c.error chrome.runtime.lastError.message
|
c.error chrome.runtime.lastError.message
|
||||||
for key, val of data when key not of items[area]
|
for key, val of data when key not of items[area]
|
||||||
|
if area is 'sync' and chrome.storage.sync.QUOTA_BYTES_PER_ITEM < JSON.stringify(val).length + key.length
|
||||||
|
c.error chrome.runtime.lastError.message, key, val
|
||||||
|
continue
|
||||||
items[area][key] = val
|
items[area][key] = val
|
||||||
timeout[area] = setTimeout setArea, $.MINUTE, area
|
setTimeout setArea, $.MINUTE, area
|
||||||
|
timeout[area] = Date.now() + $.MINUTE
|
||||||
return
|
return
|
||||||
delete timeout[area]
|
delete timeout[area]
|
||||||
|
items[area] = {}
|
||||||
|
|
||||||
setAll = $.debounce $.SECOND, ->
|
setSync = $.debounce $.SECOND, ->
|
||||||
for key in $.localKeys
|
setArea 'sync'
|
||||||
if key of items.sync
|
|
||||||
items.local[key] = items.sync[key]
|
|
||||||
delete items.sync[key]
|
|
||||||
try
|
|
||||||
setArea 'local'
|
|
||||||
setArea 'sync'
|
|
||||||
catch err
|
|
||||||
c.error err.stack
|
|
||||||
|
|
||||||
(key, val) ->
|
$.set = (key, val) ->
|
||||||
if typeof key is 'string'
|
if typeof key is 'string'
|
||||||
items.sync[key] = val
|
items.sync[key] = val
|
||||||
else
|
else
|
||||||
$.extend items.sync, key
|
$.extend items.sync, key
|
||||||
setAll()
|
for key in $.localKeys when key of items.sync
|
||||||
$.clear = (cb) ->
|
items.local[key] = items.sync[key]
|
||||||
count = 2
|
delete items.sync[key]
|
||||||
done = ->
|
setArea 'local'
|
||||||
if chrome.runtime.lastError
|
setSync()
|
||||||
c.error chrome.runtime.lastError.message
|
|
||||||
return
|
$.clear = (cb) ->
|
||||||
cb?() unless --count
|
items.local = {}
|
||||||
chrome.storage.local.clear done
|
items.sync = {}
|
||||||
chrome.storage.sync.clear done
|
count = 2
|
||||||
|
done = ->
|
||||||
|
if chrome.runtime.lastError
|
||||||
|
c.error chrome.runtime.lastError.message
|
||||||
|
return
|
||||||
|
cb?() unless --count
|
||||||
|
chrome.storage.local.clear done
|
||||||
|
chrome.storage.sync.clear done
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
|
|
||||||
# http://wiki.greasespot.net/Main_Page
|
# http://wiki.greasespot.net/Main_Page
|
||||||
@ -383,8 +407,6 @@ $.sync = do ->
|
|||||||
cb JSON.parse(newValue), key
|
cb JSON.parse(newValue), key
|
||||||
(key, cb) -> $.syncing[g.NAMESPACE + key] = cb
|
(key, cb) -> $.syncing[g.NAMESPACE + key] = cb
|
||||||
|
|
||||||
$.desync = (key) -> delete $.syncing[g.NAMESPACE + key]
|
|
||||||
|
|
||||||
$.delete = (keys) ->
|
$.delete = (keys) ->
|
||||||
unless keys instanceof Array
|
unless keys instanceof Array
|
||||||
keys = [keys]
|
keys = [keys]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
class Notice
|
class Notice
|
||||||
constructor: (type, content, @timeout) ->
|
constructor: (type, content, @timeout, @onclose) ->
|
||||||
@el = $.el 'div',
|
@el = $.el 'div',
|
||||||
innerHTML: '<a href="javascript:;" class="close fa fa-times" title="Close"></a><div class="message"></div>'
|
innerHTML: '<a href="javascript:;" class="close fa fa-times" title="Close"></a><div class="message"></div>'
|
||||||
@el.style.opacity = 0
|
@el.style.opacity = 0
|
||||||
@ -27,3 +27,4 @@ class Notice
|
|||||||
close: =>
|
close: =>
|
||||||
$.off d, 'visibilitychange', @add
|
$.off d, 'visibilitychange', @add
|
||||||
$.rm @el
|
$.rm @el
|
||||||
|
@onclose?()
|
||||||
|
|||||||
@ -77,7 +77,7 @@ Gallery =
|
|||||||
nodes.current.parentElement.scrollTop = 0
|
nodes.current.parentElement.scrollTop = 0
|
||||||
|
|
||||||
Gallery.cb.open.call if image
|
Gallery.cb.open.call if image
|
||||||
$ "[href='#{image.href.replace /https?:/, ''}']", nodes.thumbs
|
$("[href='#{image.href}']", nodes.thumbs) or Gallery.images[0]
|
||||||
else
|
else
|
||||||
Gallery.images[0]
|
Gallery.images[0]
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ Gallery =
|
|||||||
|
|
||||||
generateThumb: (file) ->
|
generateThumb: (file) ->
|
||||||
post = Get.postFromNode file
|
post = Get.postFromNode file
|
||||||
|
return if post.isClone or post.isHidden
|
||||||
return unless post.file and (post.file.isImage or post.file.isVideo or Conf['PDF in Gallery'])
|
return unless post.file and (post.file.isImage or post.file.isVideo or Conf['PDF in Gallery'])
|
||||||
return if Gallery.fullIDs[post.fullID]
|
return if Gallery.fullIDs[post.fullID]
|
||||||
Gallery.fullIDs[post.fullID] = true
|
Gallery.fullIDs[post.fullID] = true
|
||||||
@ -137,7 +138,9 @@ Gallery =
|
|||||||
|
|
||||||
{nodes} = Gallery
|
{nodes} = Gallery
|
||||||
{name} = nodes
|
{name} = nodes
|
||||||
slideshow = Gallery.slideshow and +@dataset.id > +nodes.current.dataset.id
|
oldID = +nodes.current.dataset.id
|
||||||
|
newID = +@dataset.id
|
||||||
|
slideshow = Gallery.slideshow and (newID > oldID or (oldID is Gallery.images.length-1 and newID is 0))
|
||||||
|
|
||||||
$.rmClass el, 'gal-highlight' if el = $ '.gal-highlight', nodes.thumbs
|
$.rmClass el, 'gal-highlight' if el = $ '.gal-highlight', nodes.thumbs
|
||||||
$.addClass @, 'gal-highlight'
|
$.addClass @, 'gal-highlight'
|
||||||
@ -162,6 +165,10 @@ Gallery =
|
|||||||
nodes.next.focus()
|
nodes.next.focus()
|
||||||
Gallery.cb[if slideshow then 'setupTimer' else 'stop']()
|
Gallery.cb[if slideshow then 'setupTimer' else 'stop']()
|
||||||
|
|
||||||
|
# Scroll to post
|
||||||
|
if Conf['Scroll to Post'] and post = (post = g.posts[file.dataset.post])?.nodes.root
|
||||||
|
Header.scrollTo post
|
||||||
|
|
||||||
# Center selected thumbnail
|
# Center selected thumbnail
|
||||||
nodes.thumbs.scrollTop = @offsetTop + @offsetHeight/2 - nodes.thumbs.clientHeight/2
|
nodes.thumbs.scrollTop = @offsetTop + @offsetHeight/2 - nodes.thumbs.clientHeight/2
|
||||||
|
|
||||||
@ -199,8 +206,14 @@ Gallery =
|
|||||||
if postObj.filedeleted
|
if postObj.filedeleted
|
||||||
post.kill true
|
post.kill true
|
||||||
|
|
||||||
prev: -> Gallery.cb.open.call Gallery.images[+Gallery.nodes.current.dataset.id - 1]
|
prev: ->
|
||||||
next: -> Gallery.cb.open.call Gallery.images[+Gallery.nodes.current.dataset.id + 1]
|
Gallery.cb.open.call(
|
||||||
|
Gallery.images[+Gallery.nodes.current.dataset.id - 1] or Gallery.images[Gallery.images.length - 1]
|
||||||
|
)
|
||||||
|
next: ->
|
||||||
|
Gallery.cb.open.call(
|
||||||
|
Gallery.images[+Gallery.nodes.current.dataset.id + 1] or Gallery.images[0]
|
||||||
|
)
|
||||||
enterKey: -> if Gallery.nodes.current.paused then Gallery.nodes.current.play() else Gallery.cb.next()
|
enterKey: -> if Gallery.nodes.current.paused then Gallery.nodes.current.play() else Gallery.cb.next()
|
||||||
click: -> Gallery.cb[if Gallery.nodes.current.controls then 'stop' else 'enterKey']()
|
click: -> Gallery.cb[if Gallery.nodes.current.controls then 'stop' else 'enterKey']()
|
||||||
toggle: -> (if Gallery.nodes then Gallery.cb.close else Gallery.build)()
|
toggle: -> (if Gallery.nodes then Gallery.cb.close else Gallery.build)()
|
||||||
@ -223,7 +236,6 @@ Gallery =
|
|||||||
{current} = Gallery.nodes
|
{current} = Gallery.nodes
|
||||||
isVideo = current.nodeName is 'VIDEO'
|
isVideo = current.nodeName is 'VIDEO'
|
||||||
Video.start current if isVideo
|
Video.start current if isVideo
|
||||||
return Gallery.cb.stop() if !Gallery.images[+Gallery.nodes.current.dataset.id + 1]
|
|
||||||
if (if isVideo then current.readyState > 4 else current.complete) or current.nodeName is 'IFRAME'
|
if (if isVideo then current.readyState > 4 else current.complete) or current.nodeName is 'IFRAME'
|
||||||
Gallery.cb.startTimer()
|
Gallery.cb.startTimer()
|
||||||
else
|
else
|
||||||
@ -291,7 +303,7 @@ Gallery =
|
|||||||
el: label
|
el: label
|
||||||
|
|
||||||
createSubEntries: ->
|
createSubEntries: ->
|
||||||
subEntries = ['Hide Thumbnails', 'Fit Width', 'Fit Height'].map Gallery.menu.createSubEntry
|
subEntries = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Scroll to Post'].map Gallery.menu.createSubEntry
|
||||||
|
|
||||||
delayLabel = $.el 'label', innerHTML: 'Slide Delay: <input type="number" name="Slide Delay" min="0" step="any" class="field">'
|
delayLabel = $.el 'label', innerHTML: 'Slide Delay: <input type="number" name="Slide Delay" min="0" step="any" class="field">'
|
||||||
delayInput = delayLabel.firstElementChild
|
delayInput = delayLabel.firstElementChild
|
||||||
|
|||||||
@ -10,22 +10,19 @@ ImageHover =
|
|||||||
$.on @file.thumb, 'mouseover', ImageHover.mouseover
|
$.on @file.thumb, 'mouseover', ImageHover.mouseover
|
||||||
mouseover: (e) ->
|
mouseover: (e) ->
|
||||||
post = Get.postFromNode @
|
post = Get.postFromNode @
|
||||||
{isVideo} = post.file
|
{file} = post
|
||||||
if post.file.fullImage
|
{isVideo} = file
|
||||||
el = post.file.fullImage
|
if el = file.fullImage
|
||||||
|
el.id = 'ihover'
|
||||||
TrashQueue.remove el
|
TrashQueue.remove el
|
||||||
else
|
else
|
||||||
el = $.el (if isVideo then 'video' else 'img'),
|
file.fullImage = el = $.el (if isVideo then 'video' else 'img'),
|
||||||
className: 'full-image'
|
className: 'full-image'
|
||||||
src: post.file.URL
|
id: 'ihover'
|
||||||
post.file.fullImage = el
|
el.dataset.fullID = post.fullID
|
||||||
{thumb} = post.file
|
$.on el, 'error', ImageHover.error
|
||||||
if d.body.contains thumb
|
el.src = file.URL
|
||||||
$.after thumb, el unless el is thumb.nextSibling
|
$.after file.thumb, el
|
||||||
else
|
|
||||||
$.add Header.hover, el if el.parentNode isnt Header.hover
|
|
||||||
el.id = 'ihover'
|
|
||||||
el.dataset.fullID = post.fullID
|
|
||||||
if isVideo
|
if isVideo
|
||||||
el.loop = true
|
el.loop = true
|
||||||
el.controls = false
|
el.controls = false
|
||||||
@ -35,7 +32,7 @@ ImageHover =
|
|||||||
el: el
|
el: el
|
||||||
latestEvent: e
|
latestEvent: e
|
||||||
endEvents: 'mouseout click'
|
endEvents: 'mouseout click'
|
||||||
asapTest: -> (if isVideo then el.videoHeight else el.naturalHeight)
|
asapTest: -> (if isVideo then el.readyState >= el.HAVE_CURRENT_DATA else el.naturalHeight)
|
||||||
noRemove: true
|
noRemove: true
|
||||||
cb: ->
|
cb: ->
|
||||||
$.off el, 'error', ImageHover.error
|
$.off el, 'error', ImageHover.error
|
||||||
@ -43,7 +40,6 @@ ImageHover =
|
|||||||
el.pause()
|
el.pause()
|
||||||
TrashQueue.add el, post
|
TrashQueue.add el, post
|
||||||
el.removeAttribute 'id'
|
el.removeAttribute 'id'
|
||||||
$.on el, 'error', ImageHover.error
|
|
||||||
error: ->
|
error: ->
|
||||||
return unless doc.contains @
|
return unless doc.contains @
|
||||||
post = g.posts[@dataset.fullID]
|
post = g.posts[@dataset.fullID]
|
||||||
|
|||||||
@ -44,7 +44,6 @@ Sauce =
|
|||||||
a = Sauce.link.cloneNode true
|
a = Sauce.link.cloneNode true
|
||||||
a.href = parts['url']
|
a.href = parts['url']
|
||||||
a.textContent = parts['text']
|
a.textContent = parts['text']
|
||||||
return null unless /^https?:$/.test a.protocol
|
|
||||||
a
|
a
|
||||||
node: ->
|
node: ->
|
||||||
return if @isClone or !@file
|
return if @isClone or !@file
|
||||||
|
|||||||
@ -151,13 +151,12 @@ Linkify =
|
|||||||
|
|
||||||
embed: (data) ->
|
embed: (data) ->
|
||||||
[key, uid, options, link, post] = data
|
[key, uid, options, link, post] = data
|
||||||
href = link.href
|
|
||||||
embed = $.el 'a',
|
embed = $.el 'a',
|
||||||
className: 'embedder'
|
className: 'embedder'
|
||||||
href: 'javascript:;'
|
href: link.href
|
||||||
textContent: '(embed)'
|
textContent: '(embed)'
|
||||||
|
|
||||||
embed.dataset[name] = value for name, value of {key, href, uid, options}
|
embed.dataset[name] = value for name, value of {key, uid, options}
|
||||||
|
|
||||||
$.addClass link, "#{embed.dataset.key}"
|
$.addClass link, "#{embed.dataset.key}"
|
||||||
|
|
||||||
@ -181,7 +180,8 @@ Linkify =
|
|||||||
return
|
return
|
||||||
|
|
||||||
cb:
|
cb:
|
||||||
toggle: ->
|
toggle: (e) ->
|
||||||
|
e?.preventDefault()
|
||||||
if $.hasClass @, "embedded"
|
if $.hasClass @, "embedded"
|
||||||
$.rm @previousElementSibling
|
$.rm @previousElementSibling
|
||||||
@previousElementSibling.hidden = false
|
@previousElementSibling.hidden = false
|
||||||
@ -253,14 +253,14 @@ Linkify =
|
|||||||
el: (a) ->
|
el: (a) ->
|
||||||
el = $.el 'div'
|
el = $.el 'div'
|
||||||
el.innerHTML = '<a target="_blank"><img></a>'
|
el.innerHTML = '<a target="_blank"><img></a>'
|
||||||
el.firstChild.href = el.firstChild.firstChild.src = a.dataset.href
|
el.firstChild.href = el.firstChild.firstChild.src = a.href
|
||||||
el
|
el
|
||||||
,
|
,
|
||||||
key: 'InstallGentoo'
|
key: 'InstallGentoo'
|
||||||
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/
|
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/
|
||||||
el: (a) ->
|
el: (a) ->
|
||||||
$.el 'iframe',
|
$.el 'iframe',
|
||||||
src: "http://paste.installgentoo.com/view/embed/#{a.dataset.uid}"
|
src: "https://paste.installgentoo.com/view/embed/#{a.dataset.uid}"
|
||||||
,
|
,
|
||||||
key: 'Twitter'
|
key: 'Twitter'
|
||||||
regExp: /.*twitter.com\/(.+\/status\/\d+)/
|
regExp: /.*twitter.com\/(.+\/status\/\d+)/
|
||||||
@ -302,7 +302,7 @@ Linkify =
|
|||||||
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
|
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
|
||||||
when 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'
|
when 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'
|
||||||
el.innerHTML = '<a target="_blank"><img></a>'
|
el.innerHTML = '<a target="_blank"><img></a>'
|
||||||
el.firstChild.href = a.dataset.href
|
el.firstChild.href = a.href
|
||||||
el.firstChild.firstChild.src = "https://mediacru.sh/#{file.file}"
|
el.firstChild.firstChild.src = "https://mediacru.sh/#{file.file}"
|
||||||
when 'audio/mpeg', 'audio/ogg'
|
when 'audio/mpeg', 'audio/ogg'
|
||||||
el.innerHTML = '<audio controls><source type="audio/ogg"><source type="audio/mpeg"></audio>'
|
el.innerHTML = '<audio controls><source type="audio/ogg"><source type="audio/mpeg"></audio>'
|
||||||
@ -322,20 +322,20 @@ Linkify =
|
|||||||
regExp: /.*gfycat.com\/(?:iframe\/)?(\S*)/
|
regExp: /.*gfycat.com\/(?:iframe\/)?(\S*)/
|
||||||
el: (a) ->
|
el: (a) ->
|
||||||
div = $.el 'iframe',
|
div = $.el 'iframe',
|
||||||
src: "http://gfycat.com/iframe/#{a.dataset.uid}"
|
src: "//gfycat.com/iframe/#{a.dataset.uid}"
|
||||||
,
|
,
|
||||||
key: 'SoundCloud'
|
key: 'SoundCloud'
|
||||||
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/
|
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/
|
||||||
style: 'border: 0; width: 500px; height: 400px;'
|
style: 'border: 0; width: 500px; height: 400px;'
|
||||||
el: (a) ->
|
el: (a) ->
|
||||||
$.el 'iframe',
|
$.el 'iframe',
|
||||||
src: "//w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent a.dataset.uid}"
|
src: "https://w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent a.dataset.uid}"
|
||||||
title:
|
title:
|
||||||
api: (uid) -> "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent uid}"
|
api: (uid) -> "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F#{encodeURIComponent uid}"
|
||||||
text: (_) -> _.title
|
text: (_) -> _.title
|
||||||
,
|
,
|
||||||
key: 'StrawPoll'
|
key: 'StrawPoll'
|
||||||
regExp: /strawpoll\.me\/(?:embed_\d+\/)?(\d+)/
|
regExp: /strawpoll\.me\/(?:embed_\d+\/)?(\d+(?:\/r)?)/
|
||||||
style: 'border: 0; width: 600px; height: 406px;'
|
style: 'border: 0; width: 600px; height: 406px;'
|
||||||
el: (a) ->
|
el: (a) ->
|
||||||
$.el 'iframe',
|
$.el 'iframe',
|
||||||
|
|||||||