Merge branch 'v3' of git://github.com/MayhemYDG/4chan-x into v3
Conflicts: Gruntfile.js src/config.coffee src/css/style.css src/features.coffee src/main.coffee
This commit is contained in:
commit
a067ad6262
@ -1,3 +1,10 @@
|
|||||||
|
## 3.2.0 - *2013-04-23*
|
||||||
|
|
||||||
|
- The top and bottom original board lists are now optional, disabled by default.
|
||||||
|
- The button to show a hidden announcement is now inside the header's menu.
|
||||||
|
- Reorganized Header menu:<br>
|
||||||
|
- Added the `board-replace` setting to Custom Board Navigation ricing.
|
||||||
|
- Added the option `Cooldown Prediction`, enabled by default.
|
||||||
- Added the option `Hide Unread Count at (0)`, disabled by default.
|
- Added the option `Hide Unread Count at (0)`, disabled by default.
|
||||||
|
|
||||||
### 3.1.4 - *2013-04-17*
|
### 3.1.4 - *2013-04-17*
|
||||||
|
|||||||
@ -189,7 +189,7 @@ module.exports = (grunt) ->
|
|||||||
grunt.registerTask 'reloadPkg', 'Reload the package', ->
|
grunt.registerTask 'reloadPkg', 'Reload the package', ->
|
||||||
# Update the `pkg` object with the new version.
|
# Update the `pkg` object with the new version.
|
||||||
pkg = grunt.file.readJSON('package.json')
|
pkg = grunt.file.readJSON('package.json')
|
||||||
concatOptions.process.data = pkg
|
grunt.config.data.pkg = concatOptions.process.data = pkg
|
||||||
grunt.log.ok('pkg reloaded.')
|
grunt.log.ok('pkg reloaded.')
|
||||||
|
|
||||||
grunt.registerTask 'updcl', 'Update the changelog', (i) ->
|
grunt.registerTask 'updcl', 'Update the changelog', (i) ->
|
||||||
|
|||||||
194
Gruntfile.js
Normal file
194
Gruntfile.js
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
var pkg = grunt.file.readJSON('package.json');
|
||||||
|
var concatOptions = {
|
||||||
|
process: {
|
||||||
|
data: pkg
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var shellOptions = {
|
||||||
|
stdout: true,
|
||||||
|
stderr: true,
|
||||||
|
failOnError: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: pkg,
|
||||||
|
concat: {
|
||||||
|
coffee: {
|
||||||
|
options: concatOptions,
|
||||||
|
src: [
|
||||||
|
'src/config.coffee',
|
||||||
|
'src/globals.coffee',
|
||||||
|
'lib/ui.coffee',
|
||||||
|
'lib/$.coffee',
|
||||||
|
'lib/polyfill.coffee',
|
||||||
|
'src/features.coffee',
|
||||||
|
'src/qr.coffee',
|
||||||
|
'src/report.coffee',
|
||||||
|
'src/databoard.coffee',
|
||||||
|
'src/main.coffee'
|
||||||
|
],
|
||||||
|
dest: 'tmp-<%= pkg.type %>/script.coffee'
|
||||||
|
},
|
||||||
|
crx: {
|
||||||
|
options: concatOptions,
|
||||||
|
files: {
|
||||||
|
'builds/crx/manifest.json': 'src/manifest.json',
|
||||||
|
'builds/crx/script.js': [
|
||||||
|
'src/banner.js',
|
||||||
|
'tmp-<%= pkg.type %>/script.js'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userjs: {
|
||||||
|
options: concatOptions,
|
||||||
|
src: [
|
||||||
|
'src/metadata.js',
|
||||||
|
'src/banner.js',
|
||||||
|
'tmp-<%= pkg.type %>/script.js'
|
||||||
|
],
|
||||||
|
dest: 'builds/<%= pkg.name %>.js'
|
||||||
|
},
|
||||||
|
userscript: {
|
||||||
|
options: concatOptions,
|
||||||
|
files: {
|
||||||
|
'builds/<%= pkg.name %>.meta.js': 'src/metadata.js',
|
||||||
|
'builds/<%= pkg.name %>.user.js': [
|
||||||
|
'src/metadata.js',
|
||||||
|
'src/banner.js',
|
||||||
|
'tmp-<%= pkg.type %>/script.js'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
copy: {
|
||||||
|
crx: {
|
||||||
|
src: 'img/*.png',
|
||||||
|
dest: 'builds/crx/',
|
||||||
|
expand: true,
|
||||||
|
flatten: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
coffee: {
|
||||||
|
script: {
|
||||||
|
src: 'tmp-<%= pkg.type %>/script.coffee',
|
||||||
|
dest: 'tmp-<%= pkg.type %>/script.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
concurrent: {
|
||||||
|
build: ['build-crx', 'build-userjs', 'build-userscript']
|
||||||
|
},
|
||||||
|
shell: {
|
||||||
|
commit: {
|
||||||
|
options: shellOptions,
|
||||||
|
command: [
|
||||||
|
'git checkout <%= pkg.meta.mainBranch %>',
|
||||||
|
'git commit -am "Release <%= pkg.meta.name %> v<%= pkg.version %>."',
|
||||||
|
'git tag -a <%= pkg.version %> -m "<%= pkg.meta.name %> v<%= pkg.version %>."',
|
||||||
|
'git tag -af stable-v3 -m "<%= pkg.meta.name %> v<%= pkg.version %>."'
|
||||||
|
].join(' && ')
|
||||||
|
},
|
||||||
|
push: {
|
||||||
|
options: shellOptions,
|
||||||
|
command: 'git push origin --tags -f && git push origin --all'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
all: {
|
||||||
|
options: {
|
||||||
|
interrupt: true
|
||||||
|
},
|
||||||
|
files: [
|
||||||
|
'Gruntfile.js',
|
||||||
|
'package.json',
|
||||||
|
'lib/**/*',
|
||||||
|
'src/**/*',
|
||||||
|
'css/**/*',
|
||||||
|
'img/**/*'
|
||||||
|
],
|
||||||
|
tasks: 'build'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compress: {
|
||||||
|
crx: {
|
||||||
|
options: {
|
||||||
|
archive: 'builds/<%= pkg.name %>.zip',
|
||||||
|
level: 9,
|
||||||
|
pretty: true
|
||||||
|
},
|
||||||
|
expand: true,
|
||||||
|
flatten: true,
|
||||||
|
src: 'builds/crx/*',
|
||||||
|
dest: '/'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clean: {
|
||||||
|
builds: 'builds',
|
||||||
|
tmpcrx: 'tmp-crx',
|
||||||
|
tmpuserjs: 'tmp-userjs',
|
||||||
|
tmpuserscript: 'tmp-userscript'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-bump');
|
||||||
|
grunt.loadNpmTasks('grunt-concurrent');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-coffee');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
|
grunt.loadNpmTasks('grunt-shell');
|
||||||
|
|
||||||
|
grunt.registerTask('default', ['build']);
|
||||||
|
|
||||||
|
grunt.registerTask('set-build', 'Set the build type variable', function(type) {
|
||||||
|
pkg.type = type;
|
||||||
|
grunt.log.ok('pkg.type = %s', type);
|
||||||
|
});
|
||||||
|
grunt.registerTask('build', ['concurrent:build']);
|
||||||
|
grunt.registerTask('build-crx', [
|
||||||
|
'set-build:crx',
|
||||||
|
'concat:coffee',
|
||||||
|
'coffee:script',
|
||||||
|
'concat:crx',
|
||||||
|
'copy:crx',
|
||||||
|
'clean:tmpcrx'
|
||||||
|
]);
|
||||||
|
grunt.registerTask('build-userjs', [
|
||||||
|
'set-build:userjs',
|
||||||
|
'concat:coffee',
|
||||||
|
'coffee:script',
|
||||||
|
'concat:userjs',
|
||||||
|
'clean:tmpuserjs'
|
||||||
|
]);
|
||||||
|
grunt.registerTask('build-userscript', [
|
||||||
|
'set-build:userscript',
|
||||||
|
'concat:coffee',
|
||||||
|
'coffee:script',
|
||||||
|
'concat:userscript',
|
||||||
|
'clean:tmpuserscript'
|
||||||
|
]);
|
||||||
|
|
||||||
|
grunt.registerTask('release', ['shell:commit', 'shell:push', 'build-crx', 'compress:crx']);
|
||||||
|
grunt.registerTask('patch', ['bump', 'reloadPkg', 'updcl:3', 'release']);
|
||||||
|
grunt.registerTask('minor', ['bump:minor', 'reloadPkg', 'updcl:2', 'release']);
|
||||||
|
grunt.registerTask('major', ['bump:major', 'reloadPkg', 'updcl:1', 'release']);
|
||||||
|
|
||||||
|
grunt.registerTask('reloadPkg', 'Reload the package', function() {
|
||||||
|
// Update the `pkg` object with the new version.
|
||||||
|
pkg = grunt.file.readJSON('package.json');
|
||||||
|
grunt.config.data.pkg = concatOptions.process.data = pkg;
|
||||||
|
grunt.log.ok('pkg reloaded.');
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.registerTask('updcl', 'Update the changelog', function(i) {
|
||||||
|
// i is the number of #s for markdown.
|
||||||
|
var version = new Array(+i + 1).join('#') + ' ' + pkg.version + ' - *' + grunt.template.today('yyyy-mm-dd') + '*';
|
||||||
|
grunt.file.write('CHANGELOG.md', version + '\n\n' + grunt.file.read('CHANGELOG.md'));
|
||||||
|
grunt.log.ok('Changelog updated for v' + pkg.version + '.');
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "4chan X",
|
"name": "4chan X",
|
||||||
"version": "3.1.4",
|
"version": "3.2.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Cross-browser extension for productive lurking on 4chan.",
|
"description": "Cross-browser extension for productive lurking on 4chan.",
|
||||||
"icons": {
|
"icons": {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
BIN
img/changelog/3.2.0/0.png
Normal file
BIN
img/changelog/3.2.0/0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "4chan-X",
|
"name": "4chan-X",
|
||||||
"version": "3.1.4",
|
"version": "3.2.0",
|
||||||
"description": "Cross-browser extension for productive lurking on 4chan.",
|
"description": "Cross-browser extension for productive lurking on 4chan.",
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "4chan X",
|
"name": "4chan X",
|
||||||
@ -20,8 +20,8 @@
|
|||||||
"grunt-bump": "~0.0.2",
|
"grunt-bump": "~0.0.2",
|
||||||
"grunt-concurrent": "~0.2.0",
|
"grunt-concurrent": "~0.2.0",
|
||||||
"grunt-contrib-clean": "~0.4.1",
|
"grunt-contrib-clean": "~0.4.1",
|
||||||
"grunt-contrib-coffee": "~0.6.7",
|
"grunt-contrib-coffee": "~0.7.0",
|
||||||
"grunt-contrib-compress": "~0.4.10",
|
"grunt-contrib-compress": "~0.5.0",
|
||||||
"grunt-contrib-concat": "~0.2.0",
|
"grunt-contrib-concat": "~0.2.0",
|
||||||
"grunt-contrib-copy": "~0.4.1",
|
"grunt-contrib-copy": "~0.4.1",
|
||||||
"grunt-contrib-watch": "~0.3.1",
|
"grunt-contrib-watch": "~0.3.1",
|
||||||
|
|||||||
@ -9,10 +9,6 @@ Config =
|
|||||||
false
|
false
|
||||||
'Link to external catalog instead of the internal one.'
|
'Link to external catalog instead of the internal one.'
|
||||||
]
|
]
|
||||||
'Custom Board Navigation': [
|
|
||||||
true
|
|
||||||
'Show custom links instead of the full board list.'
|
|
||||||
]
|
|
||||||
'QR Shortcut': [
|
'QR Shortcut': [
|
||||||
false,
|
false,
|
||||||
'Adds a small [QR] link in the header.'
|
'Adds a small [QR] link in the header.'
|
||||||
@ -257,6 +253,10 @@ Config =
|
|||||||
true
|
true
|
||||||
'Prevent "flood detected" errors.'
|
'Prevent "flood detected" errors.'
|
||||||
]
|
]
|
||||||
|
'Cooldown Prediction': [
|
||||||
|
true
|
||||||
|
'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'
|
||||||
|
]
|
||||||
|
|
||||||
'Quote Links':
|
'Quote Links':
|
||||||
'Quote Backlinks': [
|
'Quote Backlinks': [
|
||||||
@ -388,13 +388,13 @@ http://iqdb.org/?url=%TURL
|
|||||||
|
|
||||||
'Custom CSS': false
|
'Custom CSS': false
|
||||||
|
|
||||||
'Boards Navigation': 'Sticky top'
|
Header:
|
||||||
|
'Fixed Header': true
|
||||||
'Header auto-hide': false
|
'Header auto-hide': false
|
||||||
|
'Bottom Header': false
|
||||||
'Footer auto-hide': true
|
'Header catalog links': false
|
||||||
|
'Bottom Board List': false
|
||||||
'Header catalog links': false
|
'Custom Board Navigation': false
|
||||||
|
|
||||||
boardnav: '[ toggle-all ] [current-title]'
|
boardnav: '[ toggle-all ] [current-title]'
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,9 @@ a[href="javascript:;"] {
|
|||||||
.warning {
|
.warning {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
#boardNavDesktop {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 4chan style fixes */
|
/* 4chan style fixes */
|
||||||
.opContainer, .op {
|
.opContainer, .op {
|
||||||
@ -367,6 +370,9 @@ a[href="javascript:;"] {
|
|||||||
a.hide-announcement {
|
a.hide-announcement {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
#toggleMsgBtn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unread */
|
/* Unread */
|
||||||
#unread-line {
|
#unread-line {
|
||||||
|
|||||||
@ -2,6 +2,20 @@ PSAHiding =
|
|||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Announcement Hiding']
|
return if !Conf['Announcement Hiding']
|
||||||
|
|
||||||
|
entry =
|
||||||
|
type: 'header'
|
||||||
|
el: $.el 'a',
|
||||||
|
textContent: 'Show announcement'
|
||||||
|
className: 'show-announcement'
|
||||||
|
href: 'javascript:;'
|
||||||
|
order: 50
|
||||||
|
open: ->
|
||||||
|
if $.id('globalMessage')?.hidden
|
||||||
|
return true
|
||||||
|
false
|
||||||
|
$.event 'AddMenuEntry', entry
|
||||||
|
|
||||||
|
$.on entry.el, 'click', PSAHiding.toggle
|
||||||
$.addClass doc, 'hide-announcement'
|
$.addClass doc, 'hide-announcement'
|
||||||
|
|
||||||
$.on d, '4chanXInitFinished', @setup
|
$.on d, '4chanXInitFinished', @setup
|
||||||
@ -14,12 +28,12 @@ PSAHiding =
|
|||||||
return
|
return
|
||||||
|
|
||||||
PSAHiding.btn = btn = $.el 'a',
|
PSAHiding.btn = btn = $.el 'a',
|
||||||
title: 'Toggle announcement.'
|
innerHTML: '<span>[ - ]</span>'
|
||||||
innerHTML: '<span></span>'
|
title: 'Hide announcement.'
|
||||||
|
className: 'hide-announcement'
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
$.on btn, 'click', PSAHiding.toggle
|
$.on btn, 'click', PSAHiding.toggle
|
||||||
|
|
||||||
text = PSAHiding.trim psa
|
|
||||||
$.get 'hiddenPSAs', [], (item) ->
|
$.get 'hiddenPSAs', [], (item) ->
|
||||||
PSAHiding.sync item['hiddenPSAs']
|
PSAHiding.sync item['hiddenPSAs']
|
||||||
$.before psa, btn
|
$.before psa, btn
|
||||||
@ -33,19 +47,21 @@ PSAHiding =
|
|||||||
$.get 'hiddenPSAs', [], ({hiddenPSAs}) ->
|
$.get 'hiddenPSAs', [], ({hiddenPSAs}) ->
|
||||||
if hide
|
if hide
|
||||||
hiddenPSAs.push text
|
hiddenPSAs.push text
|
||||||
|
hiddenPSAs = hiddenPSAs[-5..]
|
||||||
else
|
else
|
||||||
|
$.event 'CloseMenu'
|
||||||
i = hiddenPSAs.indexOf text
|
i = hiddenPSAs.indexOf text
|
||||||
hiddenPSAs.splice i, 1
|
hiddenPSAs.splice i, 1
|
||||||
hiddenPSAs = hiddenPSAs[-5..]
|
|
||||||
PSAHiding.sync hiddenPSAs
|
PSAHiding.sync hiddenPSAs
|
||||||
$.set 'hiddenPSAs', hiddenPSAs
|
$.set 'hiddenPSAs', hiddenPSAs
|
||||||
|
|
||||||
sync: (hiddenPSAs) ->
|
sync: (hiddenPSAs) ->
|
||||||
{btn} = PSAHiding
|
psa = $.id 'globalMessage'
|
||||||
psa = $.id 'globalMessage'
|
psa.hidden = PSAHiding.btn.hidden = if PSAHiding.trim(psa) in hiddenPSAs
|
||||||
[psa.hidden, btn.firstChild.textContent, btn.className] = if PSAHiding.trim(psa) in hiddenPSAs
|
true
|
||||||
[true, '[\u00A0+\u00A0]', 'show-announcement']
|
|
||||||
else
|
else
|
||||||
[false, '[\u00A0-\u00A0]', 'hide-announcement']
|
false
|
||||||
|
if hr = $.x 'following-sibling::hr', psa
|
||||||
|
hr.hidden = psa.hidden
|
||||||
trim: (psa) ->
|
trim: (psa) ->
|
||||||
psa.textContent.replace(/\W+/g, '').toLowerCase()
|
psa.textContent.replace(/\W+/g, '').toLowerCase()
|
||||||
@ -27,7 +27,11 @@ CatalogLinks =
|
|||||||
|
|
||||||
set: (useCatalog) ->
|
set: (useCatalog) ->
|
||||||
path = if useCatalog then 'catalog' else ''
|
path = if useCatalog then 'catalog' else ''
|
||||||
for a in $$ 'a', $.id('board-list')
|
for a in $$ """
|
||||||
|
#board-list a[href*="boards.4chan.org"],
|
||||||
|
#boardNavDesktop a[href*="boards.4chan.org"],
|
||||||
|
#boardNavDesktopFoot a[href*="boards.4chan.org"]
|
||||||
|
"""
|
||||||
board = a.pathname.split('/')[1]
|
board = a.pathname.split('/')[1]
|
||||||
continue if ['f', 'status', '4chan'].contains(board) or !board
|
continue if ['f', 'status', '4chan'].contains(board) or !board
|
||||||
if Conf['External Catalog']
|
if Conf['External Catalog']
|
||||||
|
|||||||
@ -1,26 +1,45 @@
|
|||||||
Header =
|
Header =
|
||||||
init: ->
|
init: ->
|
||||||
|
@menu = new UI.Menu 'header'
|
||||||
@menuButton = $.el 'span',
|
@menuButton = $.el 'span',
|
||||||
className: 'menu-button'
|
className: 'menu-button'
|
||||||
innerHTML: '<i></i>'
|
innerHTML: '<i></i>'
|
||||||
|
|
||||||
@menu = new UI.Menu 'header'
|
barFixedToggler = $.el 'label',
|
||||||
|
innerHTML: '<input type=checkbox name="Fixed Header"> Fixed Header'
|
||||||
headerToggler = $.el 'label',
|
headerToggler = $.el 'label',
|
||||||
innerHTML: '<input type=checkbox name="Header auto-hide"> Auto-hide header'
|
innerHTML: '<input type=checkbox name="Header auto-hide"> Auto-hide header'
|
||||||
|
barPositionToggler = $.el 'label',
|
||||||
|
innerHTML: '<input type=checkbox name="Bottom header"> Bottom header'
|
||||||
|
customNavToggler = $.el 'label',
|
||||||
|
innerHTML: '<input type=checkbox name="Custom Board Navigation"> Custom board navigation'
|
||||||
|
footerToggler = $.el 'label',
|
||||||
|
innerHTML: "<input type=checkbox #{unless Conf['Bottom Board List'] then 'checked' else ''}> Hide Footer Nav"
|
||||||
|
editCustomNav = $.el 'a',
|
||||||
|
textContent: 'Edit custom board navigation'
|
||||||
|
href: 'javascript:;'
|
||||||
|
|
||||||
@headerToggler = headerToggler.firstElementChild
|
@barFixedToggler = barFixedToggler.firstElementChild
|
||||||
|
@barPositionToggler = barPositionToggler.firstElementChild
|
||||||
|
@headerToggler = headerToggler.firstElementChild
|
||||||
|
@footerToggler = footerToggler.firstElementChild
|
||||||
|
@customNavToggler = customNavToggler.firstElementChild
|
||||||
|
|
||||||
$.on @menuButton, 'click', @menuToggle
|
$.on @menuButton, 'click', @menuToggle
|
||||||
$.on window, 'load hashchange', Header.hashScroll
|
$.on @barFixedToggler, 'change', @toggleBarFixed
|
||||||
$.on @headerToggler, 'change', @toggleBarVisibility
|
$.on @barPositionToggler, 'change', @toggleBarPosition
|
||||||
|
$.on @headerToggler, 'change', @toggleBarVisibility
|
||||||
|
$.on @footerToggler, 'change', @toggleFooterVisibility
|
||||||
|
$.on @customNavToggler, 'change', @toggleCustomNav
|
||||||
|
$.on editCustomNav, 'click', @editCustomNav
|
||||||
|
|
||||||
{createSubEntry} = Header
|
@setBarFixed Conf['Fixed Header']
|
||||||
subEntries = []
|
@setBarVisibility Conf['Header auto-hide']
|
||||||
for setting in ['Sticky top', 'Sticky bottom', 'Top']
|
@setBarPosition Conf['Bottom Header']
|
||||||
subEntries.push createSubEntry setting
|
|
||||||
|
|
||||||
subEntries.push {el: headerToggler}
|
$.sync 'Fixed Header', Header.setBarFixed
|
||||||
|
$.sync 'Bottom Header', Header.setBarPosition
|
||||||
|
$.sync 'Header auto-hide', Header.setBarVisibility
|
||||||
|
|
||||||
@addShortcut Header.menuButton
|
@addShortcut Header.menuButton
|
||||||
|
|
||||||
@ -29,32 +48,38 @@ Header =
|
|||||||
el: $.el 'span',
|
el: $.el 'span',
|
||||||
textContent: 'Header'
|
textContent: 'Header'
|
||||||
order: 105
|
order: 105
|
||||||
subEntries: subEntries
|
subEntries: [
|
||||||
|
{el: barFixedToggler}
|
||||||
@footerToggler = $.el 'label',
|
{el: headerToggler}
|
||||||
innerHTML: "<input type=checkbox #{if Conf['Footer auto-hide'] then 'checked' else ''}> Hide Footer Nav"
|
{el: barPositionToggler}
|
||||||
$.on @footerToggler.firstElementChild, 'change', @toggleFooterVisibility
|
{el: footerToggler}
|
||||||
|
{el: customNavToggler}
|
||||||
$.event 'AddMenuEntry',
|
{el: editCustomNav}
|
||||||
type: 'header'
|
]
|
||||||
el: @footerToggler
|
|
||||||
order: 100
|
|
||||||
|
|
||||||
|
$.on window, 'load hashchange', Header.hashScroll
|
||||||
$.on d, 'CreateNotification', @createNotification
|
$.on d, 'CreateNotification', @createNotification
|
||||||
|
|
||||||
$.asap (-> d.body), ->
|
$.asap (-> d.body), =>
|
||||||
return unless Main.isThisPageLegit()
|
return unless Main.isThisPageLegit()
|
||||||
# Wait for #boardNavMobile instead of #boardNavDesktop,
|
# Wait for #boardNavMobile instead of #boardNavDesktop,
|
||||||
# it might be incomplete otherwise.
|
# it might be incomplete otherwise.
|
||||||
$.asap (-> $.id 'boardNavMobile'), Header.setBoardList
|
$.asap (-> $.id('boardNavMobile') or d.readyState is 'complete'), Header.setBoardList
|
||||||
|
$.prepend d.body, @bar
|
||||||
|
|
||||||
$.ready ->
|
$.ready =>
|
||||||
$.add d.body, Header.hover
|
if a = $ "a[href*='/#{g.BOARD}/']", $.id 'boardNavDesktopFoot'
|
||||||
Header.footer = footer = $.id 'boardNavDesktopFoot'
|
a.className = 'current'
|
||||||
Header.setFooterVisibility Conf['Footer auto-hide']
|
|
||||||
$.sync 'Footer auto-hide', Header.setFooterVisibility
|
$.add d.body, @hover
|
||||||
|
@footer = $.id 'boardNavDesktopFoot'
|
||||||
|
@setFooterVisibility !Conf['Bottom Board List']
|
||||||
|
$.sync 'Bottom Board List', Header.setFooterVisibility
|
||||||
|
|
||||||
bar: $.el 'div',
|
bar: $.el 'div',
|
||||||
|
id: 'header-bar'
|
||||||
|
|
||||||
|
notify: $.el 'div',
|
||||||
id: 'notifications'
|
id: 'notifications'
|
||||||
|
|
||||||
shortcuts: $.el 'span',
|
shortcuts: $.el 'span',
|
||||||
@ -66,61 +91,33 @@ Header =
|
|||||||
toggle: $.el 'div',
|
toggle: $.el 'div',
|
||||||
id: 'scroll-marker'
|
id: 'scroll-marker'
|
||||||
|
|
||||||
createSubEntry: (setting) ->
|
|
||||||
label = $.el 'label',
|
|
||||||
textContent: "#{setting}"
|
|
||||||
|
|
||||||
$.on label, 'click', Header.setBarPosition
|
|
||||||
|
|
||||||
el: label
|
|
||||||
|
|
||||||
setBoardList: ->
|
setBoardList: ->
|
||||||
Header.nav = nav = $.id 'boardNavDesktop'
|
fourchannav = $.id 'boardNavDesktop'
|
||||||
nav.id = 'header-bar'
|
if a = $ "a[href*='/#{g.BOARD}/']", fourchannav
|
||||||
if a = $ "a[href*='/#{g.BOARD}/']", nav
|
|
||||||
a.className = 'current'
|
a.className = 'current'
|
||||||
|
|
||||||
boardList = $.el 'span',
|
boardList = $.el 'span',
|
||||||
id: 'board-list'
|
id: 'board-list'
|
||||||
|
innerHTML: "<span id=custom-board-list></span><span id=full-board-list hidden>[<a href=javascript:; class='hide-board-list-button'> - </a>]#{fourchannav.innerHTML}</span>"
|
||||||
|
fullBoardList = $ '#full-board-list', boardList
|
||||||
|
btn = $ '.hide-board-list-button', fullBoardList
|
||||||
|
$.on btn, 'click', Header.toggleBoardList
|
||||||
|
|
||||||
$.add boardList, fullBoardList = $.el 'span',
|
$.rm $ '#navtopright', fullBoardList
|
||||||
id: 'full-board-list'
|
$.add boardList, fullBoardList
|
||||||
|
$.add Header.bar, [boardList, Header.shortcuts, Header.notify, Header.toggle]
|
||||||
|
|
||||||
Header.setBarPosition.call textContent: "#{Conf['Boards Navigation']}"
|
Header.setCustomNav Conf['Custom Board Navigation']
|
||||||
$.sync 'Boards Navigation', Header.changeBarPosition
|
Header.generateBoardList Conf['boardnav']
|
||||||
|
|
||||||
Header.setBarVisibility Conf['Header auto-hide']
|
$.sync 'Custom Board Navigation', Header.setCustomNav
|
||||||
$.sync 'Header auto-hide', Header.setBarVisibility
|
$.sync 'boardnav', Header.generateBoardList
|
||||||
|
|
||||||
$.add fullBoardList, [nav.childNodes...]
|
|
||||||
$.add nav, [boardList, Header.shortcuts, Header.bar, Header.toggle]
|
|
||||||
|
|
||||||
if Conf['Custom Board Navigation']
|
|
||||||
fullBoardList.hidden = true
|
|
||||||
customBoardList = $.el 'span',
|
|
||||||
id: 'custom-board-list'
|
|
||||||
$.add boardList, customBoardList
|
|
||||||
|
|
||||||
Header.generateBoardList Conf['boardnav']
|
|
||||||
$.sync 'boardnav', Header.generateBoardList
|
|
||||||
|
|
||||||
btn = $.el 'span',
|
|
||||||
className: 'hide-board-list-button'
|
|
||||||
innerHTML: '[<a href=javascript:;> - </a>]\u00A0'
|
|
||||||
$.on btn, 'click', Header.toggleBoardList
|
|
||||||
|
|
||||||
$.prepend fullBoardList, btn
|
|
||||||
|
|
||||||
else
|
|
||||||
fullBoardList.hidden = false
|
|
||||||
|
|
||||||
generateBoardList: (text) ->
|
generateBoardList: (text) ->
|
||||||
unless list = $ '#custom-board-list', Header.nav
|
list = $ '#custom-board-list', Header.bar
|
||||||
# init'd with the custom board list disabled.
|
|
||||||
return
|
|
||||||
$.rmAll list
|
$.rmAll list
|
||||||
return unless text
|
return unless text
|
||||||
as = $$('#full-board-list a', Header.nav)[0...-2] # ignore the Settings and Home links
|
as = $$('#full-board-list a', Header.bar)[0...-2] # ignore the Settings and Home links
|
||||||
nodes = text.match(/[\w@]+(-(all|title|replace|full|index|catalog|text:"[^"]+"))*|[^\w@]+/g).map (t) ->
|
nodes = text.match(/[\w@]+(-(all|title|replace|full|index|catalog|text:"[^"]+"))*|[^\w@]+/g).map (t) ->
|
||||||
if /^[^\w@]/.test t
|
if /^[^\w@]/.test t
|
||||||
return $.tn t
|
return $.tn t
|
||||||
@ -159,46 +156,51 @@ Header =
|
|||||||
$.add list, nodes
|
$.add list, nodes
|
||||||
|
|
||||||
toggleBoardList: ->
|
toggleBoardList: ->
|
||||||
{nav} = Header
|
{bar} = Header
|
||||||
custom = $ '#custom-board-list', nav
|
custom = $ '#custom-board-list', bar
|
||||||
full = $ '#full-board-list', nav
|
full = $ '#full-board-list', bar
|
||||||
showBoardList = !full.hidden
|
showBoardList = !full.hidden
|
||||||
custom.hidden = !showBoardList
|
custom.hidden = !showBoardList
|
||||||
full.hidden = showBoardList
|
full.hidden = showBoardList
|
||||||
|
|
||||||
setBarPosition: ->
|
setBarPosition: (bottom) ->
|
||||||
|
Header.barPositionToggler.checked = bottom
|
||||||
|
if bottom
|
||||||
|
$.rmClass doc, 'top'
|
||||||
|
$.addClass doc, 'bottom'
|
||||||
|
else
|
||||||
|
$.rmClass doc, 'bottom'
|
||||||
|
$.addClass doc, 'top'
|
||||||
|
|
||||||
|
toggleBarPosition: ->
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
|
|
||||||
Header.changeBarPosition @textContent
|
Header.setBarPosition @checked
|
||||||
|
|
||||||
Conf['Boards Navigation'] = @textContent
|
Conf['Bottom Header'] = @checked
|
||||||
$.set 'Boards Navigation', @textContent
|
$.set 'Bottom Header', @checked
|
||||||
|
|
||||||
changeBarPosition: (setting) ->
|
setBarFixed: (fixed) ->
|
||||||
$.rmClass doc, 'top'
|
Header.barFixedToggler.checked = fixed
|
||||||
$.rmClass doc, 'fixed'
|
if fixed
|
||||||
$.rmClass doc, 'bottom'
|
$.addClass doc, 'fixed'
|
||||||
$.rmClass Header.nav, 'dialog'
|
$.addClass Header.bar, 'dialog'
|
||||||
switch setting
|
else
|
||||||
when 'Sticky top'
|
$.rmClass doc, 'fixed'
|
||||||
$.addClass doc, 'top'
|
$.rmClass Header.bar, 'dialog'
|
||||||
$.addClass doc, 'fixed'
|
|
||||||
$.addClass Header.nav, 'dialog'
|
toggleBarFixed: ->
|
||||||
when 'Sticky bottom'
|
$.event 'CloseMenu'
|
||||||
$.addClass doc, 'fixed'
|
|
||||||
$.addClass doc, 'bottom'
|
Header.setBarFixed @checked
|
||||||
$.addClass Header.nav, 'dialog'
|
|
||||||
when 'Top'
|
Conf['Fixed Header'] = @checked
|
||||||
$.addClass doc, 'top'
|
$.set 'Fixed Header', @checked
|
||||||
|
|
||||||
setBarVisibility: (hide) ->
|
setBarVisibility: (hide) ->
|
||||||
Header.headerToggler.checked = hide
|
Header.headerToggler.checked = hide
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
(if hide then $.addClass else $.rmClass) Header.nav, 'autohide'
|
(if hide then $.addClass else $.rmClass) Header.bar, 'autohide'
|
||||||
|
|
||||||
setFooterVisibility: (hide) ->
|
|
||||||
Header.footerToggler.firstElementChild.checked = hide
|
|
||||||
Header.footer.hidden = hide
|
|
||||||
|
|
||||||
toggleBarVisibility: (e) ->
|
toggleBarVisibility: (e) ->
|
||||||
return if e.type is 'mousedown' and e.button isnt 0 # not LMB
|
return if e.type is 'mousedown' and e.button isnt 0 # not LMB
|
||||||
@ -215,20 +217,43 @@ Header =
|
|||||||
'The header bar will remain visible.'
|
'The header bar will remain visible.'
|
||||||
new Notification 'info', message, 2
|
new Notification 'info', message, 2
|
||||||
|
|
||||||
|
setFooterVisibility: (hide) ->
|
||||||
|
Header.footerToggler.checked = hide
|
||||||
|
Header.footer.hidden = hide
|
||||||
|
|
||||||
toggleFooterVisibility: ->
|
toggleFooterVisibility: ->
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
hide = if @nodeName is 'INPUT'
|
hide = if @nodeName is 'INPUT'
|
||||||
@checked
|
@checked
|
||||||
else
|
else
|
||||||
!Header.footer.hidden
|
!!Header.footer.hidden
|
||||||
Header.setFooterVisibility hide
|
Header.setFooterVisibility hide
|
||||||
$.set 'Footer auto-hide', hide
|
$.set 'Bottom Board List', hide
|
||||||
message = if hide
|
message = if hide
|
||||||
'The bottom navigation will now be hidden.'
|
'The bottom navigation will now be hidden.'
|
||||||
else
|
else
|
||||||
'The bottom navigation will remain visible.'
|
'The bottom navigation will remain visible.'
|
||||||
new Notification 'info', message, 2
|
new Notification 'info', message, 2
|
||||||
|
|
||||||
|
setCustomNav: (show) ->
|
||||||
|
Header.customNavToggler.checked = show
|
||||||
|
cust = $ '#custom-board-list', Header.bar
|
||||||
|
full = $ '#full-board-list', Header.bar
|
||||||
|
btn = $ '.hide-board-list-button', full
|
||||||
|
[cust.hidden, full.hidden, btn.hidden] = if show
|
||||||
|
[false, true, false]
|
||||||
|
else
|
||||||
|
[true, false, true]
|
||||||
|
|
||||||
|
toggleCustomNav: ->
|
||||||
|
$.cb.checked.call @
|
||||||
|
Header.setCustomNav @checked
|
||||||
|
|
||||||
|
editCustomNav: ->
|
||||||
|
Settings.open 'Rice'
|
||||||
|
settings = $.id 'fourchanx-settings'
|
||||||
|
$('input[name=boardnav]', settings).focus()
|
||||||
|
|
||||||
hashScroll: ->
|
hashScroll: ->
|
||||||
return unless (hash = @location.hash) and post = $.id hash[1..]
|
return unless (hash = @location.hash) and post = $.id hash[1..]
|
||||||
return if (Get.postFromRoot post).isHidden
|
return if (Get.postFromRoot post).isHidden
|
||||||
@ -236,7 +261,7 @@ Header =
|
|||||||
|
|
||||||
scrollToPost: (post) ->
|
scrollToPost: (post) ->
|
||||||
{top} = post.getBoundingClientRect()
|
{top} = post.getBoundingClientRect()
|
||||||
if Conf['Boards Navigation'] is 'Sticky top'
|
if Conf['Fixed Header'] and not Conf['Bottom Header']
|
||||||
headRect = Header.bar.getBoundingClientRect()
|
headRect = Header.bar.getBoundingClientRect()
|
||||||
top += - headRect.top - headRect.height
|
top += - headRect.top - headRect.height
|
||||||
(if $.engine is 'webkit' then d.body else doc).scrollTop += top
|
(if $.engine is 'webkit' then d.body else doc).scrollTop += top
|
||||||
|
|||||||
@ -263,7 +263,7 @@ QR =
|
|||||||
elapsed = Math.floor (now - start) / $.SECOND
|
elapsed = Math.floor (now - start) / $.SECOND
|
||||||
if elapsed >= 0 # clock changed since then?
|
if elapsed >= 0 # clock changed since then?
|
||||||
seconds = Math.max seconds, types[type] - elapsed
|
seconds = Math.max seconds, types[type] - elapsed
|
||||||
if hasFile and upSpd
|
if Conf['Cooldown Prediction'] and hasFile and upSpd
|
||||||
seconds -= Math.floor post.file.size / upSpd * upSpdAccuracy
|
seconds -= Math.floor post.file.size / upSpd * upSpdAccuracy
|
||||||
seconds = Math.max seconds, 0
|
seconds = Math.max seconds, 0
|
||||||
unless start <= now <= cooldown.timeout
|
unless start <= now <= cooldown.timeout
|
||||||
|
|||||||
@ -153,7 +153,7 @@ class Post
|
|||||||
unless strong = $ 'strong.warning', @nodes.info
|
unless strong = $ 'strong.warning', @nodes.info
|
||||||
strong = $.el 'strong',
|
strong = $.el 'strong',
|
||||||
className: 'warning'
|
className: 'warning'
|
||||||
textContent: '[Deleted]'
|
textContent: if @isReply then '[Deleted]' else '[Dead]'
|
||||||
$.after $('input', @nodes.info), strong
|
$.after $('input', @nodes.info), strong
|
||||||
strong.textContent = if file then '[File deleted]' else '[Deleted]'
|
strong.textContent = if file then '[File deleted]' else '[Deleted]'
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user