Most of the Header is done, see changelog file.

Add 4chan and 4chan X settings links in the header's menu.

Add $.asap.

Add UI.Menu.
The menu API now requires a type ("post" or "header").

Add Get.boardsConfig.
This commit is contained in:
Nicolas Stepien 2013-02-09 18:40:18 +01:00
parent c54ddff83d
commit b6cf7220c4
7 changed files with 962 additions and 559 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,16 @@
alpha
- Mayhem
Major rewrite of 4chan X.
New feature, the Header:
Access the list of boards directly from the Header.
Access to settings and extra features easily from the Header's menu.
Can be auto-hidden.
Added touch and multi-touch support for dragging windows.
The Thread Updater will pause when offline, and resume when online.
Added Thread & Post Hiding in the Menu, with individual settings.
Thread & Post Hiding Buttons can now be disabled in the settings.
Recursive Hiding will be automatically applied when manually hiding a post.
Fix Chrome's install warning that 4chan X would execute on all domains.
Fix Chrome's install warning saying that 4chan X would execute on all domains.
Fix Quote Backlinks not affecting inlined quotes.
Fix Quote Highlighting not affecting inlined quotes.

View File

@ -31,17 +31,20 @@ a[href="javascript:;"] {
/* fixed, z-index */
#qp, #ihover,
#updater, #stats,
#boardNavDesktop.reply,
#header,
#qr, #watcher {
position: fixed;
}
#qp, #ihover {
z-index: 100;
}
#menu {
z-index: 95;
}
#updater, #stats {
z-index: 90;
}
#boardNavDesktop.reply:hover {
#header:hover {
z-index: 80;
}
#qr {
@ -50,38 +53,70 @@ a[href="javascript:;"] {
#watcher {
z-index: 30;
}
#boardNavDesktop.reply {
#header {
z-index: 10;
}
/* XXX support different styles */
#header-bar {
font-size: 9pt;
color: #89A;
background-color: #D6DAF0;
border-color: #B7C5D9;
border-width: 0 0 1px;
border-style: solid;
}
/* header */
body.fourchan_x {
margin-top: 2.5em;
margin-top: 2em;
}
#boardNavDesktop.reply {
border-width: 0 0 1px;
padding: 4px;
#header {
top: 0;
right: 0;
left: 0;
transition: opacity .1s ease-in-out;
-o-transition: opacity .1s ease-in-out;
-moz-transition: opacity .1s ease-in-out;
-webkit-transition: opacity .1s ease-in-out;
}
#boardNavDesktop.reply:not(:hover) {
opacity: .4;
transition: opacity 1.5s .5s ease-in-out;
-o-transition: opacity 1.5s .5s ease-in-out;
-moz-transition: opacity 1.5s .5s ease-in-out;
-webkit-transition: opacity 1.5s .5s ease-in-out;
#header-bar {
padding: 4px;
position: relative;
transition: all .1s ease-in-out;
-o-transition: all .1s ease-in-out;
-moz-transition: all .1s ease-in-out;
-webkit-transition: all .1s ease-in-out;
}
#boardNavDesktop.reply a {
margin: -1px;
#header-bar.autohide:not(:hover) {
transform: translateY(-100%);
-o-transform: translateY(-100%);
-moz-transform: translateY(-100%);
-webkit-transform: translateY(-100%);
transition: all .75s .25s ease-in-out;
-o-transition: all .75s .25s ease-in-out;
-moz-transition: all .75s .25s ease-in-out;
-webkit-transition: all .75s .25s ease-in-out;
}
#settings {
#toggle-header-bar {
cursor: n-resize;
left: 0;
right: 0;
bottom: -8px;
height: 10px;
position: absolute;
}
#header-bar.autohide #toggle-header-bar {
cursor: s-resize;
}
#header-bar a {
text-decoration: none;
padding: 1px;
}
#header-bar > .menu-button {
float: right;
padding: 0;
}
body > #boardNavDesktop,
#navtopright,
#boardNavDesktopFoot {
display: none !important;
}
/* thread updater */

View File

@ -78,19 +78,19 @@ $.extend $,
value: ->
$.set @name, @value.trim()
Conf[@name] = @value
asap: (test, cb) ->
if test()
cb()
else
setTimeout $.asap, 25, test, cb
addStyle: (css) ->
style = $.el 'style',
textContent: css
# That's terrible.
# XXX tmp fix for scriptish:
# XXX fix for scriptish:
# https://github.com/scriptish/scriptish/issues/16
f = ->
# XXX Only Chrome has no d.head on document-start.
if root = d.head or d.documentElement
$.add root, style
else
setTimeout f, 20
f()
$.asap (-> d.head), (->
$.add d.head, style
)
style
x: (path, root=d.body) ->
# XPathResult.ANY_UNORDERED_NODE_TYPE === 8

View File

@ -10,6 +10,180 @@ UI = (->
move.addEventListener 'mousedown', dragstart, false
el
class Menu
currentMenu = null
lastToggledButton = null
constructor: (@type) ->
# Doc here: https://github.com/MayhemYDG/4chan-x/wiki/Menu-API
$.on d, 'AddMenuEntry', @addEntryListener.bind @
@close = close.bind @
@entries = []
makeMenu: ->
menu = $.el 'div',
className: 'reply dialog'
id: 'menu'
tabIndex: 0
$.on menu, 'click', (e) -> e.stopPropagation()
$.on menu, 'keydown', @keybinds.bind @
menu
toggle: (e, button, data) ->
e.preventDefault()
e.stopPropagation()
if currentMenu
# Close if it's already opened.
# Reopen if we clicked on another button.
previousButton = lastToggledButton
@close()
return if previousButton is button
return unless @entries.length
@open button, data
open: (button, data) ->
menu = @makeMenu()
currentMenu = menu
lastToggledButton = button
for entry in @entries
@insertEntry entry, menu, data
@focus $ '.entry', menu
$.on d, 'click', @close
$.add d.body, menu
# Position
mRect = menu.getBoundingClientRect()
bRect = button.getBoundingClientRect()
bTop = d.documentElement.scrollTop + d.body.scrollTop + bRect.top
bLeft = d.documentElement.scrollLeft + d.body.scrollLeft + bRect.left
cHeight = d.documentElement.clientHeight
cWidth = d.documentElement.clientWidth
top =
if bRect.top + bRect.height + mRect.height < cHeight
bTop + bRect.height + 2
else
bTop - mRect.height - 2
left =
if bRect.left + mRect.width < cWidth
bLeft
else
bLeft + bRect.width - mRect.width
{style} = menu
style.top = top + 'px'
style.left = left + 'px'
menu.focus()
insertEntry: (entry, parent, data) ->
if typeof entry.open is 'function'
return unless entry.open data
$.add parent, entry.el
return unless entry.children
if submenu = $ '.submenu', entry.el
# Reset sub menu, remove irrelevant entries.
$.rm submenu
submenu = $.el 'div',
className: 'reply dialog submenu'
for child in entry.children
@insertEntry child, submenu, data
$.add entry.el, submenu
return
close = ->
$.rm currentMenu
currentMenu = null
lastToggledButton = null
$.off d, 'click', @close
keybinds: (e) ->
entry = $ '.focused', currentMenu
while subEntry = $ '.focused', entry
entry = subEntry
switch e.keyCode
when 27 # Esc
lastToggledButton.focus()
@close()
when 13, 32 # Enter, Space
entry.click()
when 38 # Up
if next = entry.previousElementSibling
@focus next
when 40 # Down
if next = entry.nextElementSibling
@focus next
when 39 # Right
if (submenu = $ '.submenu', entry) and next = submenu.firstElementChild
@focus next
when 37 # Left
if next = $.x 'parent::*[contains(@class,"submenu")]/parent::*', entry
@focus next
else
return
e.preventDefault()
e.stopPropagation()
focus: (entry) ->
while focused = $.x 'parent::*/child::*[contains(@class,"focused")]', entry
$.rmClass focused, 'focused'
for focused in $$ '.focused', entry
$.rmClass focused, 'focused'
$.addClass entry, 'focused'
# Submenu positioning.
return unless submenu = $ '.submenu', entry
sRect = submenu.getBoundingClientRect()
eRect = entry.getBoundingClientRect()
cHeight = d.documentElement.clientHeight
cWidth = d.documentElement.clientWidth
if eRect.top + sRect.height < cHeight
top = '0px'
bottom = 'auto'
else
top = 'auto'
bottom = '0px'
if eRect.right + sRect.width < cWidth
left = '100%'
right = 'auto'
else
left = 'auto'
right = '100%'
{style} = submenu
style.top = top
style.bottom = bottom
style.left = left
style.right = right
addEntry: (entry) ->
@parseEntry entry
@entries.push entry
parseEntry: (entry) ->
{el, children} = entry
$.addClass el, 'entry'
$.on el, 'focus mouseover', ((e) ->
e.stopPropagation()
@focus el
).bind @
return unless children
$.addClass el, 'has-submenu'
for child in children
@parseEntry child
return
addEntryListener: (e) ->
entry = e.detail
return if entry.type isnt @type
@addEntry entry
dragstart = (e) ->
# prevent text selection
e.preventDefault()
@ -49,24 +223,42 @@ UI = (->
drag.call @, touch
return
drag = (e) ->
left = e.clientX - @dx
top = e.clientY - @dy
if left < 10 then left = 0
else if @width - left < 10 then left = null
if top < 10 then top = 0
else if @height - top < 10 then top = null
if left is null
@style.left = null
@style.right = '0%'
else
@style.left = left / @screenWidth * 100 + '%'
@style.right = null
if top is null
@style.top = null
@style.bottom = '0%'
else
@style.top = top / @screenHeight * 100 + '%'
@style.bottom = null
{clientX, clientY} = e
left = clientX - @dx
left =
if left < 10
0
else if @width - left < 10
null
else
left / @screenWidth * 100 + '%'
top = clientY - @dy
top =
if top < 10
0
else if @height - top < 10
null
else
top / @screenHeight * 100 + '%'
right =
if left is null
0
else
null
bottom =
if top is null
0
else
null
{style} = @
style.left = left
style.right = right
style.top = top
style.bottom = bottom
touchend = (e) ->
for touch in e.changedTouches
if touch.identifier is @identifier
@ -99,22 +291,28 @@ UI = (->
root.addEventListener 'mousemove', o.hover, false
hover = (e) ->
height = @el.offsetHeight
top = e.clientY - 120
@style.top =
if @clientHeight <= height or top <= 0
'0px'
else if top + height >= @clientHeight
@clientHeight - height + 'px'
else
top + 'px'
{clientX, clientY} = e
top = clientY - 120
top =
if @clientHeight <= height or top <= 0
0
else if top + height >= @clientHeight
@clientHeight - height
else
top
{clientX} = e
if clientX <= @clientWidth - 400
@style.left = clientX + 45 + 'px'
@style.right = null
left = clientX + 45 + 'px'
right = null
else
@style.left = null
@style.right = @clientWidth - clientX + 45 + 'px'
left = null
right = @clientWidth - clientX + 45 + 'px'
{style} = @
style.top = top + 'px'
style.left = left
style.right = right
hoverend = ->
@el.parentNode.removeChild @el
for event in @events
@ -122,8 +320,10 @@ UI = (->
@root.removeEventListener 'mousemove', @hover, false
@cb.call @ if @cb
return {
dialog: dialog
Menu: Menu
hover: hoverstart
}
)()

View File

@ -1,3 +1,109 @@
Header =
init: ->
@menu = new UI.Menu 'header'
@headerEl = $.el 'div',
id: 'header'
innerHTML: '<div id=header-bar></div><div id=notifications></div>'
headerBar = $('#header-bar', @headerEl)
if $.get 'autohideHeaderBar', false
$.addClass headerBar, 'autohide'
menuButton = $.el 'a',
className: 'menu-button'
innerHTML: '[<span></span>]'
href: 'javascript:;'
$.on menuButton, 'click', @menuToggle
boardListButton = $.el 'span',
className: 'show-board-list-button'
innerHTML: '[<a href=javascript:;>+</a>]'
title: 'Toggle the board list.'
$.on boardListButton, 'click', @toggleBoardList
boardTitle = $.el 'a',
className: 'board-name'
innerHTML: "<span class=board-path>/#{g.BOARD}/</span> - <span class=board-title>...</span>"
href: "/#{g.BOARD}/"
boardList = $.el 'span',
className: 'board-list'
hidden: true
toggleBar = $.el 'div',
id: 'toggle-header-bar'
title: 'Toggle the header bar.'
$.on toggleBar, 'click', @toggleBar
$.prepend headerBar, [menuButton, boardListButton, $.tn(' '), boardTitle, boardList, toggleBar]
try
@setBoardList()
catch err
# XXX handle error
$.log err, 'Header - board list'
$.asap (-> d.body), ->
$.prepend d.body, Header.headerEl
setBoardList: ->
Get.boardsConfig (boardsConfig) ->
$('.board-title', Header.headerEl).textContent = boardsConfig[g.BOARD].title
$.ready ->
if nav = $.id 'boardNavDesktop'
$("a[href$='/#{g.BOARD}/']", nav)?.className = 'current'
$.add $('.board-list', Header.headerEl),
Array::slice.call nav.childNodes
toggleBoardList: ->
node = @firstElementChild.firstChild
if showBoardList = $.hasClass @, 'show-board-list-button'
@className = 'hide-board-list-button'
node.data = node.data.replace '+', '-'
else
@className = 'show-board-list-button'
node.data = node.data.replace '-', '+'
{headerEl} = Header
$('.board-name', headerEl).hidden = showBoardList
$('.board-list', headerEl).hidden = !showBoardList
toggleBar: ->
bool = $.id('header-bar').classList.toggle 'autohide'
$.set 'autohideHeaderBar', bool
menuToggle: (e) ->
Header.menu.toggle e, @, g
Settings =
init: ->
# 4chan X settings link
link = $.el 'a',
className: 'settings-link'
textContent: '4chan X Settings'
href: 'javascript:;'
$.on link, 'click', Settings.open
Header.menu.addEntry
el: link
# 4chan settings link
link = $.el 'a',
className: 'fourchan-settings-link'
textContent: '4chan Settings'
href: 'javascript:;'
$.on link, 'click', -> $.id('settingsWindowLink').click()
Header.menu.addEntry
el: link
open: -> !Conf['Disable 4chan\'s extension']
return unless Conf['Disable 4chan\'s extension']
settings = JSON.parse(localStorage.getItem '4chan-settings') or {}
return if settings.disableAll
settings.disableAll = true
localStorage.setItem '4chan-settings', JSON.stringify settings
open: ->
Header.menu.close()
# Here be settings
Filter =
filters: {}
init: ->
@ -195,7 +301,7 @@ Filter =
# Add a sub entry for each filter type.
entry.children.push Filter.menu.createSubEntry type[0], type[1]
Menu.addEntry entry
Menu.menu.addEntry entry
createSubEntry: (text, type) ->
el = $.el 'a',
@ -345,7 +451,7 @@ ThreadHiding =
makeStub = $.el 'label',
innerHTML: "<input type=checkbox checked=#{Conf['Stubs']}> Make stub"
Menu.addEntry
Menu.menu.addEntry
el: div
open: (post) ->
{thread} = post
@ -493,7 +599,7 @@ ReplyHiding =
makeStub = $.el 'label',
innerHTML: "<input type=checkbox name=makeStub checked=#{Conf['Stubs']}> Make stub"
Menu.addEntry
Menu.menu.addEntry
el: div
open: (post) ->
if !post.isReply or post.isClone
@ -619,20 +725,18 @@ Recursive =
return
Menu =
entries: []
init: ->
# Doc here: https://github.com/MayhemYDG/4chan-x/wiki/Menu-API
$.on d, 'AddMenuEntry', (e) -> Menu.addEntry e.detail
@menu = new UI.Menu 'post'
Post::callbacks.push
name: 'Menu'
cb: @node
node: ->
a = Menu.makeButton @
button = Menu.makeButton @
if @isClone
$.replace $('.menu-button', @nodes.info), a
$.replace $('.menu-button', @nodes.info), button
return
$.add @nodes.info, [$.tn('\u00A0'), a]
$.add @nodes.info, [$.tn('\u00A0'), button]
makeButton: (post) ->
a = $.el 'a',
@ -644,158 +748,13 @@ Menu =
$.on a, 'click', Menu.toggle
a
makeMenu: ->
menu = $.el 'div',
className: 'reply dialog'
id: 'menu'
tabIndex: 0
$.on menu, 'click', (e) -> e.stopPropagation()
$.on menu, 'keydown', Menu.keybinds
menu
toggle: (e) ->
e.preventDefault()
e.stopPropagation()
if Menu.currentMenu
# Close if it's already opened.
# Reopen if we clicked on another button.
{lastToggledButton} = Menu
Menu.close()
return if lastToggledButton is @
Menu.lastToggledButton = @
post =
if @dataset.clone
Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', @
else
g.posts[@dataset.postid]
Menu.open @, post
open: (button, post) ->
menu = Menu.makeMenu()
Menu.currentMenu = menu
for entry in Menu.entries
Menu.insertEntry entry, menu, post
Menu.focus $ '.entry', menu
$.on d, 'click', Menu.close
$.add d.body, menu
# Position
mRect = menu.getBoundingClientRect()
bRect = button.getBoundingClientRect()
bTop = d.documentElement.scrollTop + d.body.scrollTop + bRect.top
bLeft = d.documentElement.scrollLeft + d.body.scrollLeft + bRect.left
menu.style.top =
if bRect.top + bRect.height + mRect.height < d.documentElement.clientHeight
bTop + bRect.height + 2 + 'px'
else
bTop - mRect.height - 2 + 'px'
menu.style.left =
if bRect.left + mRect.width < d.documentElement.clientWidth
bLeft + 'px'
else
bLeft + bRect.width - mRect.width + 'px'
menu.focus()
insertEntry: (entry, parent, post) ->
if typeof entry.open is 'function'
return unless entry.open post
$.add parent, entry.el
return unless entry.children
if submenu = $ '.submenu', entry.el
# Reset sub menu, remove irrelevant entries.
$.rm submenu
submenu = $.el 'div',
className: 'reply dialog submenu'
$.add entry.el, submenu
for child in entry.children
Menu.insertEntry child, submenu, post
return
close: ->
$.rm Menu.currentMenu
delete Menu.currentMenu
delete Menu.lastToggledButton
$.off d, 'click', Menu.close
keybinds: (e) ->
entry = $ '.focused', Menu.currentMenu
while subEntry = $ '.focused', entry
entry = subEntry
switch Keybinds.keyCode(e) or e.keyCode
when 'Esc'
Menu.lastToggledButton.focus()
Menu.close()
when 13, 32 # 'Enter', 'Space'
entry.click()
when 'Up'
if next = entry.previousElementSibling
Menu.focus next
when 'Down'
if next = entry.nextElementSibling
Menu.focus next
when 'Right'
if (submenu = $ '.submenu', entry) and next = submenu.firstElementChild
Menu.focus next
when 'Left'
if next = $.x 'parent::*[contains(@class,"submenu")]/parent::*', entry
Menu.focus next
else
return
e.preventDefault()
e.stopPropagation()
focus: (entry) ->
while focused = $.x 'parent::*/child::*[contains(@class,"focused")]', entry
$.rmClass focused, 'focused'
for focused in $$ '.focused', entry
$.rmClass focused, 'focused'
$.addClass entry, 'focused'
# Submenu positioning.
return unless submenu = $ '.submenu', entry
sRect = submenu.getBoundingClientRect()
eRect = entry.getBoundingClientRect()
if eRect.top + sRect.height < d.documentElement.clientHeight
top = '0px'
bottom = 'auto'
else
top = 'auto'
bottom = '0px'
if eRect.right + sRect.width < d.documentElement.clientWidth
left = '100%'
right = 'auto'
else
left = 'auto'
right = '100%'
{style} = submenu
style.top = top
style.bottom = bottom
style.left = left
style.right = right
addEntry: (entry) ->
Menu.parseEntry entry
Menu.entries.push entry
parseEntry: (entry) ->
{el, children} = entry
$.addClass el, 'entry'
$.on el, 'focus mouseover', (e) ->
e.stopPropagation()
Menu.focus @
return unless children
$.addClass el, 'has-submenu'
for child in children
Menu.parseEntry child
return
Menu.menu.toggle e, @, post
ReportLink =
init: ->
@ -804,7 +763,7 @@ ReportLink =
href: 'javascript:;'
textContent: 'Report this post'
$.on a, 'click', ReportLink.report
Menu.addEntry
Menu.menu.addEntry
el: a
open: (post) ->
ReportLink.post = post
@ -841,7 +800,7 @@ DeleteLink =
$.on fileEl, 'click', DeleteLink.delete
!!post.file
Menu.addEntry
Menu.menu.addEntry
el: div
open: (post) ->
return false if post.isDead
@ -927,7 +886,7 @@ DownloadLink =
a = $.el 'a',
className: 'download-link'
textContent: 'Download file'
Menu.addEntry
Menu.menu.addEntry
el: a
open: (post) ->
return false unless post.file
@ -962,7 +921,7 @@ ArchiveLink =
# Add a sub entry for each type.
entry.children.push @createSubEntry type[0], type[1]
Menu.addEntry entry
Menu.menu.addEntry entry
createSubEntry: (text, type) ->
el = $.el 'a',
@ -1341,6 +1300,40 @@ Build =
container
Get =
boardsConfig: (->
boardsConfig = null
callbacks = []
parseBoardsConfig = ->
return if @status isnt 200
boardsConfig = {}
for board in JSON.parse(@response).boards
boardName = board.board
delete board.board
boardsConfig[boardName] = board
for callback in callbacks
callback boardsConfig
callbacks = null
boardsConfig.lastModified = @getResponseHeader 'Last-Modified'
$.set 'boardsConfig', boardsConfig
(cb) ->
# Configs were already loaded previously, callback and stop.
if boardsConfig
cb boardsConfig
return
# Load configs, callback, check for updates.
if boardsConfig = $.get 'boardsConfig', null
cb boardsConfig
lastModified = boardsConfig.lastModified
else
return if callbacks.push(cb) > 1
lastModified = 0
$.ajax '//api.4chan.org/boards.json', onloadend: parseBoardsConfig,
headers: 'If-Modified-Since': lastModified
)()
postFromRoot: (root) ->
link = $ 'a[title="Highlight this post"]', root
board = link.pathname.split('/')[1]

View File

@ -158,6 +158,7 @@ class Post
# Get quote/backlinks to this post
# and paint them (Dead).
for quotelink in Get.allQuotelinksLinkingTo @
continue if $.hasClass quotelink, 'deadlink'
$.add quotelink, $.tn '\u00A0(Dead)'
$.addClass quotelink, 'deadlink'
return
@ -267,10 +268,6 @@ Main =
g.THREAD = +pathname[3]
switch location.hostname
when 'boards.4chan.org'
Main.initHeader()
return if g.VIEW is 'catalog'
Main.initFeatures()
when 'sys.4chan.org'
return
when 'images.4chan.org'
@ -280,41 +277,25 @@ Main =
location.href = url if url
return
initHeader: ->
return if g.VIEW is 'catalog'
$.addStyle Main.css
Main.header = $.el 'div',
className: 'reply'
innerHTML: '<div class=extra></div>'
$.ready Main.initHeaderReady
$.asap (-> d.body), (->
$.addClass d.body, $.engine
$.addClass d.body, 'fourchan_x'
)
initHeaderReady: ->
header = Main.header
$.prepend d.body, header
try
Header.init()
catch err
# XXX handle error
$.log err, 'Header'
if nav = $.id 'boardNavDesktop'
header.id = nav.id
$.prepend header, nav
nav.id = nav.className = null
nav.lastElementChild.hidden = true
settings = $.el 'span',
id: 'settings'
innerHTML: '[<a href=javascript:;>Settings</a>]'
$.on settings.firstElementChild, 'click', Main.settings
$.add nav, settings
$("a[href$='/#{g.BOARD}/']", nav)?.className = 'current'
$.addClass d.body, $.engine
$.addClass d.body, 'fourchan_x'
# disable the mobile layout
$('link[href*=mobile]', d.head)?.disabled = true
$.id('boardNavDesktopFoot')?.hidden = true
initFeatures: ->
if Conf['Disable 4chan\'s extension']
settings = JSON.parse(localStorage.getItem '4chan-settings') or {}
settings.disableAll = true
localStorage.setItem '4chan-settings', JSON.stringify settings
try
Settings.init()
catch err
# XXX handle error
$.log err, 'Settings'
if Conf['Resurrect Quotes']
try
@ -497,9 +478,9 @@ Main =
# XXX handle error
$.log err, 'Thread Updater'
$.ready Main.initFeaturesReady
$.ready Main.initReady
initFeaturesReady: ->
initReady: ->
if d.title is '4chan - 404 Not Found'
if Conf['404 Redirect'] and g.VIEW is 'thread'
location.href = Redirect.to
@ -508,7 +489,8 @@ Main =
postID: location.hash
return
return unless $.id 'navtopright'
# disable the mobile layout
$('link[href*=mobile]', d.head)?.disabled = true
threads = []
posts = []
@ -543,9 +525,6 @@ Main =
$.log err.stack
return
settings: ->
alert 'Here be settings'
css: """<%= grunt.file.read('css/style.css') %>"""
Main.init()