HTML templates

This commit is contained in:
ccd0 2014-08-02 22:43:01 -07:00
parent 36fad05cab
commit cff287c9c3
25 changed files with 278 additions and 284 deletions

View File

@ -1,7 +1,30 @@
module.exports = (grunt) ->
importHTML = (filename) ->
"'''#{grunt.file.read("src/General/html/#{filename}.html").replace(/^\s+|\s+$</gm, '').replace(/\n/g, '')}'''"
"(innerHTML: #{JSON.stringify grunt.file.read("src/General/html/#{filename}.html").replace(/^\s+|\s+$</gm, '').replace(/\n/g, '')})"
html = (template) ->
parts = template.split /([\$&@]){([^}]*)}/
parts2 = []
checkText = ''
for part, i in parts
switch i % 3
when 0
parts2.push JSON.stringify part unless part is ''
checkText += part
when 1
if /<[^>]*$/.test(checkText) and not (part is '$' and /\=['"][^"'<>]*$/.test checkText)
throw new Error "Illegal insertion into HTML template: #{template}"
expr = parts[i+1]
expr = "(#{expr})" for x in parts[i+1].split ')'
parts2.push switch part
when '$' then "E#{expr}"
when '&' then "#{expr}.innerHTML"
when '@' then "#{expr}.map((x) -> x.innerHTML).join('')"
unless /^(<\w+( [\w-]+(='[^"'<>]*'|="[^"'<>]*")?)*>|<\/\w+>|[^"'<>]*)*$/.test checkText
throw new Error "HTML template is ill-formed: #{template}"
output = if parts2.length is 0 then '""' else parts2.join ' + '
"(innerHTML: #{output})"
# Project configuration.
grunt.initConfig
@ -12,6 +35,7 @@ module.exports = (grunt) ->
get: ->
pkg = grunt.config 'pkg'
pkg.importHTML = importHTML
pkg.html = html
pkg.tests_enabled or= false
pkg
enumerable: true

View File

@ -137,8 +137,8 @@ ThreadHiding =
makeButton: (thread, type) ->
a = $.el 'a',
className: "#{type}-thread-button"
innerHTML: "<span class='fa fa-#{if type is 'hide' then 'minus' else 'plus'}-square'></span>"
href: 'javascript:;'
$.extend a, <%= html('<span class="fa fa-${if type is "hide" then "minus" else "plus"}-square"></span>') %>
a.dataset.fullID = thread.fullID
$.on a, 'click', ThreadHiding.toggle
a

View File

@ -39,7 +39,7 @@ Build =
flagName: Build.unescape data.country_name
date: data.now
dateUTC: data.time
h_comment: data.com or ''
comment: {innerHTML: data.com or ''}
# thread status
isSticky: !!data.sticky
isClosed: !!data.closed
@ -75,86 +75,75 @@ Build =
postID, threadID, boardID
name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC
isSticky, isClosed
comment
file
} = o
name or= ''
subject or= ''
h_comment = o.h_comment
isOP = postID is threadID
if Build.initPixelRatio >= 2
h_retina = '@2x'
else
h_retina = ''
retina = if Build.initPixelRatio >= 2 then '@2x' else ''
### Name Block ###
switch capcode
when 'admin', 'admin_highlight'
h_capcodeClass = ' capcodeAdmin'
h_capcodeStart = ' <strong class="capcode hand id_admin" title="Highlight posts by the Administrator">## Admin</strong>'
h_capcodeIcon = "<img src='//s.4cdn.org/image/adminicon#{h_retina}.gif' alt='Admin Icon' title='This user is the 4chan Administrator.' class='identityIcon retina'>"
capcodeClass = ' capcodeAdmin'
capcodeStart = <%= html(' <strong class="capcode hand id_admin" title="Highlight posts by the Administrator">## Admin</strong>') %>
capcodeIcon = <%= html('<img src="//s.4cdn.org/image/adminicon${retina}.gif" alt="Admin Icon" title="This user is the 4chan Administrator." class="identityIcon retina">') %>
when 'mod'
h_capcodeClass = ' capcodeMod'
h_capcodeStart = ' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>'
h_capcodeIcon = "<img src='//s.4cdn.org/image/modicon#{h_retina}.gif' alt='Mod Icon' title='This user is a 4chan Moderator.' class='identityIcon retina'>"
capcodeClass = ' capcodeMod'
capcodeStart = <%= html(' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>') %>
capcodeIcon = <%= html('<img src="//s.4cdn.org/image/modicon${retina}.gif" alt="Mod Icon" title="This user is a 4chan Moderator." class="identityIcon retina">') %>
when 'developer'
h_capcodeClass = ' capcodeDeveloper'
h_capcodeStart = ' <strong class="capcode hand id_developer" title="Highlight posts by Developers">## Developer</strong>'
h_capcodeIcon = "<img src='//s.4cdn.org/image/developericon#{h_retina}.gif' alt='Developer Icon' title='This user is a 4chan Developer.' class='identityIcon retina'>"
capcodeClass = ' capcodeDeveloper'
capcodeStart = <%= html(' <strong class="capcode hand id_developer" title="Highlight posts by Developers">## Developer</strong>') %>
capcodeIcon = <%= html('<img src="//s.4cdn.org/image/developericon${retina}.gif" alt="Developer Icon" title="This user is a 4chan Developer." class="identityIcon retina">') %>
else
h_capcodeClass = ''
h_capcodeStart = ''
h_capcodeIcon = ''
capcodeClass = ''
capcodeStart = <%= html('') %>
capcodeIcon = <%= html('') %>
if capcode
h_nameClass = ' capcode'
nameClass = if capcode then ' capcode' else ''
tripcodeField = if tripcode
<%= html(' <span class="postertrip">${tripcode}</span>') %>
else
h_nameClass = ''
<%= html('') %>
if tripcode
h_tripcode = " <span class='postertrip'>#{E tripcode}</span>"
else
h_tripcode = ''
h_emailCont = "<span class='name#{h_nameClass}'>#{E name}</span>#{h_tripcode}#{h_capcodeStart}"
emailField = <%= html('<span class="name${nameClass}">${name}</span>&{tripcodeField}&{capcodeStart}') %>
if email
emailProcessed = encodeURIComponent(email).replace /%40/g, '@'
h_email = "<a href='mailto:#{E emailProcessed}' class='useremail'>#{h_emailCont}</a>"
else
h_email = h_emailCont
emailField = <%= html('<a href="mailto:${emailProcessed}" class="useremail">&{emailField}</a>') %>
unless isOP and boardID is 'f'
h_email += ' '
emailField = <%= html('&{emailField} ') %>
if !capcode and uniqueID
h_userID = " <span class='posteruid id_#{E uniqueID}'>(ID: <span class='hand' title='Highlight posts by this ID'>#{E uniqueID}</span>)</span>"
userID = if !capcode and uniqueID
<%= html(' <span class="posteruid id_${uniqueID}">(ID: <span class="hand" title="Highlight posts by this ID">${uniqueID}</span>)</span>') %>
else
h_userID = ''
<%= html('') %>
unless flagCode
h_flag = ''
flag = unless flagCode
<%= html('') %>
else if boardID is 'pol'
<%= html('<img src="//s.4cdn.org/image/country/troll/${flagCode.toLowerCase()}.gif" alt="${flagCode}" title="${flagName}" class="countryFlag">') %>
else
flagCodeLC = flagCode.toLowerCase()
if boardID is 'pol'
h_flag = "<img src='//s.4cdn.org/image/country/troll/#{E flagCodeLC}.gif' alt='#{E flagCode}' title='#{E flagName}' class='countryFlag'>"
else
h_flag = "<span title='#{E flagName}' class='flag flag-#{E flagCodeLC}'></span>"
<%= html('<span title="${flagName}" class="flag flag-${flagCode.toLowerCase()}"></span>') %>
h_nameBlock = "<span class='nameBlock#{h_capcodeClass}'>"
h_nameBlock += "#{h_email}#{h_capcodeIcon}#{h_userID}#{h_flag}"
h_nameBlock += '</span> '
nameBlock = <%= html(
'<span class="nameBlock${capcodeClass}">' +
'&{emailField}&{capcodeIcon}&{userID}&{flag}' +
'</span> '
) %>
### Post Info ###
if isOP or boardID is 'f'
h_subject = "<span class='subject'>#{E subject}</span> "
subjectField = if isOP or boardID is 'f'
<%= html('<span class="subject">${subject}</span> ') %>
else
h_subject = ''
<%= html('') %>
if isOP and boardID is 'f'
h_desktop2 = ''
else
h_desktop2 = ' desktop'
desktop2 = if isOP and boardID is 'f' then '' else ' desktop'
postLink = Build.postURL boardID, threadID, postID
quoteLink = if Build.sameThread boardID, threadID
@ -162,56 +151,59 @@ Build =
else
"/#{boardID}/thread/#{threadID}\#q#{postID}"
if isOP and g.VIEW is 'index' and Conf['JSON Navigation']
pageIcon = if isOP and g.VIEW is 'index' and Conf['JSON Navigation']
pageNum = Math.floor(Index.liveThreadIDs.indexOf(postID) / Index.threadsNumPerPage) + 1
h_pageIcon = " <span class='page-num' title='This thread is on page #{+pageNum} in the original index.'>[#{+pageNum}]</span>"
<%= html(' <span class="page-num" title="This thread is on page ${pageNum} in the original index.">[${pageNum}]</span>') %>
else
h_pageIcon = ''
<%= html('') %>
if isSticky
h_sticky = " <img src='//s.4cdn.org/image/sticky#{h_retina}.gif' alt='Sticky' title='Sticky' class='stickyIcon retina'>"
sticky = if isSticky
<%= html(' <img src="//s.4cdn.org/image/sticky${retina}.gif" alt="Sticky" title="Sticky" class="stickyIcon retina">') %>
else
h_sticky = ''
<%= html('') %>
if isClosed
h_closed = " <img src='//s.4cdn.org/image/closed#{h_retina}.gif' alt='Closed' title='Closed' class='closedIcon retina'>"
closed = if isClosed
<%= html(' <img src="//s.4cdn.org/image/closed${retina}.gif" alt="Closed" title="Closed" class="closedIcon retina">') %>
else
h_closed = ''
<%= html('') %>
if isOP and g.VIEW is 'index'
h_replyLink = " &nbsp; <span>[<a href='/#{E boardID}/thread/#{+threadID}' class='replylink'>Reply</a>]</span>"
replyLink = if isOP and g.VIEW is 'index'
<%= html(' &nbsp; <span>[<a href="/${boardID}/thread/${threadID}" class="replylink">Reply</a>]</span>') %>
else
h_replyLink = ''
<%= html('') %>
h_postInfo = "<div class='postInfo desktop' id='pi#{+postID}'>"
h_postInfo += "<input type='checkbox' name='#{+postID}' value='delete'> "
h_postInfo += h_subject
h_postInfo += h_nameBlock
h_postInfo += "<span class='dateTime' data-utc='#{+dateUTC}'>#{E date}</span> "
h_postInfo += "<span class='postNum#{h_desktop2}'>"
h_postInfo += "<a href='#{E postLink}' title='Link to this post'>No.</a>"
h_postInfo += "<a href='#{E quoteLink}' title='Reply to this post'>#{+postID}</a>"
h_postInfo += "#{h_pageIcon}#{h_sticky}#{h_closed}#{h_replyLink}"
h_postInfo += '</span>'
h_postInfo += '</div>'
postInfo = <%= html(
'<div class="postInfo desktop" id="pi${postID}">' +
'<input type="checkbox" name="${postID}" value="delete"> ' +
'&{subjectField}' +
'&{nameBlock}' +
'<span class="dateTime" data-utc="${dateUTC}">${date}</span> ' +
'<span class="postNum${desktop2}">' +
'<a href="${postLink}" title="Link to this post">No.</a>' +
'<a href="${quoteLink}" title="Reply to this post">${postID}</a>' +
'&{pageIcon}&{sticky}&{closed}&{replyLink}' +
'</span>' +
'</div>'
) %>
### File Info ###
if file?.isDeleted
h_fileCont = '<span class="fileThumb">'
h_fileCont += "<img src='//s.4cdn.org/image/filedeleted-res#{h_retina}.gif' alt='File deleted.' class='fileDeletedRes retina'>"
h_fileCont += '</span>'
fileCont = if file?.isDeleted
<%= html(
'<span class="fileThumb">' +
'<img src="//s.4cdn.org/image/filedeleted-res${retina}.gif" alt="File deleted." class="fileDeletedRes retina">' +
'</span>'
) %>
else if file and boardID is 'f'
fileSize = $.bytesToString file.size
h_fileCont = "<div class='fileInfo'><span class='fileText' id='fT#{+postID}'>"
h_fileCont += "File: <a data-width='#{+file.width}' data-height='#{+file.height}' href='#{E file.url}' target='_blank'>#{E file.name}</a>"
h_fileCont += "-(#{E fileSize}, #{+file.width}x#{+file.height}, #{E file.tag})"
h_fileCont += '</span></div>'
<%= html(
'<div class="fileInfo"><span class="fileText" id="fT${postID}">' +
'File: <a data-width="${file.width}" data-height="${+file.height}" href="${file.url}" target="_blank">${file.name}</a>' +
'-(${$.bytesToString file.size}, ${file.width}x${file.height}, ${file.tag})' +
'</span></div>'
) %>
else if file
if file.isSpoiler
h_fileTitle1 = "title='#{E file.name}'"
shortFilename = 'Spoiler Image'
h_spoilerClass = ' imgspoiler'
if spoilerRange = Build.spoilerRange[boardID]
# Randomize the spoiler image.
fileThumb = "//s.4cdn.org/image/spoiler-#{boardID}#{Math.floor 1 + spoilerRange * Math.random()}.png"
@ -219,58 +211,58 @@ Build =
fileThumb = '//s.4cdn.org/image/spoiler.png'
file.twidth = file.theight = 100
else
h_fileTitle1 = ''
shortFilename = Build.shortFilename file.name, !isOP
h_spoilerClass = ''
fileThumb = file.turl
if file.isSpoiler or file.name is shortFilename
h_fileTitle2 = ''
fileSize = $.bytesToString file.size
fileDims = if file.url[-4..] is '.pdf' then 'PDF' else "#{+file.width}x#{+file.height}"
fileLink = if file.isSpoiler or file.name is shortFilename
<%= html('<a href="${file.url}" target="_blank">${shortFilename}</a>') %>
else
h_fileTitle2 = "title='#{E file.name}'"
<%= html('<a title="${file.name}" href="${file.url}" target="_blank">${shortFilename}</a>') %>
fileSize = $.bytesToString file.size
if file.url[-4..] is '.pdf'
h_fileDims = 'PDF'
fileText = if file.isSpoiler
<%= html('<div class="fileText" id="fT${postID}" title="${file.name}">File: &{fileLink} (${fileSize}, ${fileDims})</div>') %>
else
h_fileDims = "#{+file.width}x#{+file.height}"
<%= html('<div class="fileText" id="fT${postID}">File: &{fileLink} (${fileSize}, ${fileDims})</div>') %>
h_fileCont = "<div class='fileText' id='fT#{+postID}' #{h_fileTitle1}>"
h_fileCont += "File: <a #{h_fileTitle2} href='#{E file.url}' target='_blank'>#{E shortFilename}</a> (#{E fileSize}, #{h_fileDims})"
h_fileCont += '</div>'
h_fileCont += "<a class='fileThumb#{h_spoilerClass}' href='#{E file.url}' target='_blank'>"
h_fileCont += "<img src='#{E fileThumb}' alt='#{E fileSize}' data-md5='#{E file.MD5}' style='height: #{+file.theight}px; width: #{+file.twidth}px;'>"
h_fileCont += '</a>'
<%= html(
'&{fileText}' +
'<a class="fileThumb${if file.isSpoiler then " imgspoiler" else ""}" href="${file.url}" target="_blank">' +
'<img src="${fileThumb}" alt="${fileSize}" data-md5="${file.MD5}" style="height: ${file.theight}px; width: ${+file.twidth}px;">' +
'</a>'
) %>
if file
h_file = "<div class='file' id='f#{+postID}'>#{h_fileCont}</div>"
fileBlock = if file
<%= html('<div class="file" id="f${postID}">&{fileCont}</div>') %>
else
h_file = ''
<%= html('') %>
### Whole Post ###
if capcode is 'admin_highlight'
h_highlightPost = ' highlightPost'
else
h_highlightPost = ''
highlightPost = if capcode is 'admin_highlight' then ' highlightPost' else ''
h_message = "<blockquote class='postMessage' id='m#{+postID}'>#{h_comment}</blockquote>"
message = <%= html('<blockquote class="postMessage" id="m${postID}">&{comment}</blockquote>') %>
if isOP
h_post = "<div id='p#{+postID}' class='post op#{h_highlightPost}'>"
h_post += "#{h_file}#{h_postInfo}#{h_message}"
h_post += '</div>'
wholePost = if isOP
<%= html(
'<div id="p${postID}" class="post op${highlightPost}">' +
'&{fileBlock}&{postInfo}&{message}' +
'</div>'
) %>
else
h_post = "<div class='sideArrows' id='sa#{+postID}'>&gt;&gt;</div>"
h_post += "<div id='p#{+postID}' class='post reply#{h_highlightPost}'>"
h_post += "#{h_postInfo}#{h_file}#{h_message}"
h_post += '</div>'
<%= html(
'<div class="sideArrows" id="sa${postID}">&gt;&gt;</div>' +
'<div id="p${postID}" class="post reply${highlightPost}">' +
'&{postInfo}&{fileBlock}&{message}' +
'</div>'
) %>
container = $.el 'div',
className: "postContainer #{if isOP then 'op' else 'reply'}Container"
id: "pc#{postID}"
innerHTML: h_post
$.extend container, wholePost
# Fix pathnames
for quote in $$ '.quotelink', container

View File

@ -159,21 +159,24 @@ Get =
root.textContent = data.error
return
# convert comment to html
h_comment = E (data.comment or '')
# https://github.com/eksopl/fuuka/blob/master/Board/Yotsuba.pm#L413-452
# https://github.com/eksopl/asagi/blob/master/src/main/java/net/easymodo/asagi/Yotsuba.java#L109-138
h_comment = h_comment.replace ///
\n
|
\[/?[a-z]+(:lit)?\]
///g, Get.parseMarkup
h_comment = h_comment
# greentext
.replace(/(^|>)(&gt;[^<$]*)(<|$)/g, '$1<span class="quote">$2</span>$3')
# quotes
.replace /((&gt;){2}(&gt;\/[a-z\d]+\/)?\d+)/g, '<span class="deadlink">$1</span>'
comment = (data.comment or '').split /(\n|\[\/?(?:b|spoiler|code|moot|banned)\])/
comment = for text, i in comment
if i % 2 is 1
Get.archiveTags[text]
else
greentext = text[0] is '>'
text = text.replace /(\[\/?[a-z]+):lit(\])/, '$1$2'
text = for text2, j in text.split /(>>(?:>\/[a-z\d]+\/)?\d+)/g
if j % 2 is 1
<%= html('<span class="deadlink">${text2}</span>') %>
else
<%= html('${text2}') %>
text = <%= html('@{text}') %>
text = <%= html('<span class="quote">&{text}</span>') %> if greentext
text
comment = <%= html('@{comment}') %>
threadID = +data.thread_num
o =
@ -195,7 +198,7 @@ Get =
flagName: data.poster_country_name
date: data.fourchan_date
dateUTC: data.timestamp
h_comment: h_comment
comment: comment
# file
if data.media?.media_filename
o.file =
@ -221,17 +224,15 @@ Get =
post.isFetchedQuote = true
Main.callbackNodes Post, [post]
Get.insert post, root, context
parseMarkup: (text) ->
{
'\n': '<br>'
'[b]': '<b>'
'[/b]': '</b>'
'[spoiler]': '<s>'
'[/spoiler]': '</s>'
'[code]': '<pre class="prettyprint">'
'[/code]': '</pre>'
'[moot]': '<div style="padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px">'
'[/moot]': '</div>'
'[banned]': '<strong style="color: red;">'
'[/banned]': '</strong>'
}[text] or text.replace ':lit', ''
archiveTags:
'\n': <%= html('<br>') %>
'[b]': <%= html('<b>') %>
'[/b]': <%= html('</b>') %>
'[spoiler]': <%= html('<s>') %>
'[/spoiler]': <%= html('</s>') %>
'[code]': <%= html('<pre class="prettyprint">') %>
'[/code]': <%= html('</pre>') %>
'[moot]': <%= html('<div style="padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px">') %>
'[/moot]': <%= html('</div>') %>
'[banned]': <%= html('<strong style="color: red;">') %>
'[/banned]': <%= html('</strong>') %>

View File

@ -5,6 +5,9 @@ doc = d.documentElement
g =
VERSION: '<%= version %>'
NAMESPACE: '<%= meta.name %>.'
NAME: '<%= meta.name %>'
FAQ: '<%= meta.faq %>'
CHANGELOG: '<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md'
boards: {}
E = (text) ->
(text+'').replace /[&"'<>]/g, (x) ->

View File

@ -4,7 +4,7 @@ Header =
menuButton = $.el 'span',
className: 'menu-button'
innerHTML: '<i></i>'
$.extend menuButton, <%= html('<i></i>') %>
barFixedToggler = UI.checkbox 'Fixed Header', ' Fixed Header'
headerToggler = UI.checkbox 'Header auto-hide', ' Auto-hide header'
@ -132,7 +132,13 @@ Header =
fourchannav = $.id 'boardNavDesktop'
Header.boardList = boardList = $.el 'span',
id: 'board-list'
innerHTML: "<span id='custom-board-list'></span><span id='full-board-list' hidden><span class='hide-board-list-container brackets-wrap'><a href='javascript:;' class='hide-board-list-button'>&nbsp;-&nbsp;</a></span> #{fourchannav.innerHTML}</span>"
$.extend boardList, <%= html(
'<span id="custom-board-list"></span>' +
'<span id="full-board-list" hidden>' +
'<span class="hide-board-list-container brackets-wrap"><a href="javascript:;" class="hide-board-list-button">&nbsp;-&nbsp;</a></span> ' +
'&{fourchannav}' +
'</span>'
) %>
for a in $$ 'a', boardList
if a.pathname.split('/')[1] is g.BOARD.ID
a.className = 'current'
@ -442,11 +448,11 @@ Header =
return
el = $.el 'span',
innerHTML: '''
<%= meta.name %> needs your permission to show desktop notifications.
[<a href='<%= meta.faq %>#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications' target=_blank>FAQ</a>]<br>
<button>Authorize</button> or <button>Disable</button>
'''
<%= html(
'${g.NAME} needs your permission to show desktop notifications. ' +
'[<a href="${g.FAQ}#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications" target="_blank">FAQ</a>]<br>' +
'<button>Authorize</button> or <button>Disable</button>'
) %>
[authorize, disable] = $$ 'button', el
$.on authorize, 'click', ->
Notification.requestPermission (status) ->

View File

@ -15,9 +15,9 @@ Index =
modeEntry =
el: $.el 'span', textContent: 'Index mode'
subEntries: [
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Mode" value="paged"> Paged' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Mode" value="infinite"> Infinite scrolling' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Mode" value="all pages"> All threads' }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Mode" value="paged"> Paged') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Mode" value="infinite"> Infinite scrolling') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Mode" value="all pages"> All threads') %> }
]
for label in modeEntry.subEntries
input = label.el.firstChild
@ -28,11 +28,11 @@ Index =
sortEntry =
el: $.el 'span', textContent: 'Sort by'
subEntries: [
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Sort" value="bump"> Bump order' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Sort" value="lastreply"> Last reply' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Sort" value="birth"> Creation date' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Sort" value="replycount"> Reply count' }
{ el: $.el 'label', innerHTML: '<input type="radio" name="Index Sort" value="filecount"> File count' }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Sort" value="bump"> Bump order') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Sort" value="lastreply"> Last reply') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Sort" value="birth"> Creation date') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Sort" value="replycount"> Reply count') %> }
{ el: $.el 'label', <%= html('<input type="radio" name="Index Sort" value="filecount"> File count') %> }
]
for label in sortEntry.subEntries
input = label.el.firstChild
@ -66,10 +66,10 @@ Index =
@pagelist = $.el 'div',
className: 'pagelist'
hidden: true
innerHTML: <%= importHTML('Features/Index-pagelist') %>
$.extend @pagelist, <%= importHTML('Features/Index-pagelist') %>
@navLinks = $.el 'div',
className: 'navLinks'
innerHTML: <%= importHTML('Features/Index-navlinks') %>
$.extend @navLinks, <%= importHTML('Features/Index-navlinks') %>
$('.returnlink a', @navLinks).href = "//boards.4chan.org/#{g.BOARD}/"
$('.cataloglink a', @navLinks).href = "//boards.4chan.org/#{g.BOARD}/catalog"
@searchInput = $ '#index-search', @navLinks

View File

@ -189,7 +189,7 @@ Main =
return if previousversion is g.VERSION
if previousversion
el = $.el 'span',
innerHTML: '<%= meta.name %> has been updated to <a href="<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md" target="_blank">version <%= version %></a>.'
<%= html('${g.NAME} has been updated to <a href="${g.CHANGELOG}" target="_blank">version ${g.VERSION}</a>.') %>
new Notice 'info', el, 15
else
Settings.open()
@ -230,7 +230,7 @@ Main =
return
div = $.el 'div',
innerHTML: "#{+errors.length} errors occurred. [<a href='javascript:;'>show</a>]"
<%= html('${errors.length} errors occurred. [<a href="javascript:;">show</a>]') %>
$.on div.lastElementChild, 'click', ->
[@textContent, logs.hidden] = if @textContent is 'show'
['hide', false]

View File

@ -34,7 +34,7 @@ Settings =
Settings.dialog = dialog = $.el 'div',
id: 'fourchanx-settings'
className: 'dialog'
innerHTML: <%= importHTML('Settings/Settings') %>
$.extend dialog, <%= importHTML('Settings/Settings') %>
$.on $('.export', Settings.dialog), 'click', Settings.export
$.on $('.import', Settings.dialog), 'click', Settings.import
@ -90,8 +90,7 @@ Settings =
inputs = {}
for key, obj of Config.main
fs = $.el 'fieldset',
innerHTML: '<legend></legend>'
fs.firstElementChild.textContent = key
<%= html('<legend>${key}</legend>') %>
for key, arr of obj
description = arr[1]
div = $.el 'div'
@ -112,7 +111,7 @@ Settings =
return
div = $.el 'div',
innerHTML: '<button></button><span class="description">: Clear manually-hidden threads and posts on all boards. Reload the page to apply.'
<%= html('<button></button><span class="description">: Clear manually-hidden threads and posts on all boards. Reload the page to apply.') %>
button = $ 'button', div
$.get {hiddenThreads: {}, hiddenPosts: {}}, ({hiddenThreads, hiddenPosts}) ->
hiddenNum = 0
@ -247,7 +246,7 @@ Settings =
$.clear -> window.location.reload() if confirm 'Reset successful. Reload now?'
filter: (section) ->
section.innerHTML = <%= importHTML('Settings/Filter-select') %>
$.extend section, <%= importHTML('Settings/Filter-select') %>
select = $ 'select', section
$.on select, 'change', Settings.selectFilter
Settings.selectFilter.call select
@ -265,11 +264,11 @@ Settings =
$.on ta, 'change', $.cb.value
$.add div, ta
return
div.innerHTML = <%= importHTML('Settings/Filter-guide') %>
$.extend div, <%= importHTML('Settings/Filter-guide') %>
$('.warning', div).hidden = Conf['Filter']
sauce: (section) ->
section.innerHTML = <%= importHTML('Settings/Sauce') %>
$.extend section, <%= importHTML('Settings/Sauce') %>
$('.warning', section).hidden = Conf['Sauce']
ta = $ 'textarea', section
$.get 'sauces', Conf['sauces'], (item) ->
@ -277,7 +276,7 @@ Settings =
$.on ta, 'change', $.cb.value
advanced: (section) ->
section.innerHTML = <%= importHTML('Settings/Advanced') %>
$.extend section, <%= importHTML('Settings/Advanced') %>
warning.hidden = Conf[warning.dataset.feature] for warning in $$ '.warning', section
items = {}
@ -387,7 +386,7 @@ Settings =
textContent: archive
value: archive
td.innerHTML = '<select></select>'
$.extend td, <%= html('<select></select>') %>
select = td.firstElementChild
unless select.disabled = length is 1
# XXX GM can't into datasets
@ -441,7 +440,7 @@ Settings =
CustomCSS.update()
keybinds: (section) ->
section.innerHTML = <%= importHTML('Settings/Keybinds') %>
$.extend section, <%= importHTML('Settings/Keybinds') %>
$('.warning', section).hidden = Conf['Keybinds']
tbody = $ 'tbody', section
@ -449,8 +448,7 @@ Settings =
inputs = {}
for key, arr of Config.hotkeys
tr = $.el 'tr',
innerHTML: '<td></td><td><input class="field"></td>'
tr.firstElementChild.textContent = arr[1]
<%= html('<td>${arr[1]}</td><td><input class="field"></td>') %>
input = $ 'input', tr
input.name = key
input.spellcheck = false

View File

@ -46,9 +46,11 @@ $.ajax = do ->
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
message = $.el 'div',
<%= html(
'${g.NAME} was blocked from loading the following URL:<br><span></span><br>' +
'[<a href="${g.FAQ}#why-was-4chan-x-blocked-from-loading-a-url" target="_blank">More info</a>]'
) %>
$('span', message).textContent = (if /^\/\//.test url then location.protocol else '') + url
new Notice 'error', message, 30, -> delete blockedURLs[url]
(url, options, extra={}) ->

View File

@ -1,7 +1,7 @@
class Notice
constructor: (type, content, @timeout, @onclose) ->
@el = $.el 'div',
innerHTML: '<a href="javascript:;" class="close fa fa-times" title="Close"></a><div class="message"></div>'
<%= html('<a href="javascript:;" class="close fa fa-times" title="Close"></a><div class="message"></div>') %>
@el.style.opacity = 0
@setType type
$.on @el.firstElementChild, 'click', @close

View File

@ -36,7 +36,7 @@ Gallery =
nodes.el = dialog = $.el 'div',
id: 'a-gallery'
innerHTML: <%= importHTML('Features/Gallery') %>
$.extend dialog, <%= importHTML('Features/Gallery') %>
nodes[key] = $ value, dialog for key, value of {
buttons: '.gal-buttons'
@ -288,7 +288,7 @@ Gallery =
createSubEntries: ->
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', <%= html('Slide Delay: <input type="number" name="Slide Delay" min="0" step="any" class="field">') %>
delayInput = delayLabel.firstElementChild
delayInput.value = Gallery.delay
$.on delayInput, 'change', Gallery.cb.setDelay

View File

@ -10,6 +10,8 @@ ImageExpand =
$.on @EAI, 'click', @cb.toggleAll
Header.addShortcut @EAI, 3
$.on d, 'scroll visibilitychange', @cb.playVideos
@videoControls = $.el 'span', className: 'video-controls'
$.extend @videoControls, <%= html('\u00A0<a href="javascript:;" title="You can also contract the video by dragging it to the left.">contract</a>') %>
Post.callbacks.push
name: 'Image Expansion'
@ -219,10 +221,6 @@ ImageExpand =
if controls
ImageCommon.addControls fullImage
videoControls: $.el 'span',
className: 'video-controls'
innerHTML: '\u00A0<a href="javascript:;" title="You can also contract the video by dragging it to the left.">contract</a>'
videoCB: do ->
# dragging to the left contracts the video
mousedown = false

View File

@ -14,7 +14,7 @@ ImageLoader =
return unless Conf['Image Prefetching'] and g.VIEW is 'thread'
prefetch = $.el 'label',
innerHTML: '<input type="checkbox" name="prefetch"> Prefetch Images'
<%= html('<input type="checkbox" name="prefetch"> Prefetch Images') %>
@el = prefetch.firstElementChild
$.on @el, 'change', @toggle

View File

@ -175,8 +175,7 @@ Linkify =
try
$.cache service.api(uid), (-> Linkify.cb.title @, data), responseType: 'json'
catch err
link.innerHTML = '<span class="warning">Title Link Blocked</span> (are you using NoScript?)</a>'
$.prepend link, $.tn "[#{key}] "
$.extend link, <%= html('[${key}] <span class="warning">Title Link Blocked</span> (are you using NoScript?)</a>') %>
return
cb:
@ -239,7 +238,7 @@ Linkify =
key: 'gist'
regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/
el: (a) ->
div = $.el 'iframe',
$.el 'iframe',
# Github doesn't allow embedding straight from the site, so we use an external site to bypass that.
src: "http://www.purplegene.com/script?url=https://gist.github.com/#{a.dataset.uid}.js"
title:
@ -251,10 +250,7 @@ Linkify =
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/
style: 'border: 0; width: auto; height: auto;'
el: (a) ->
el = $.el 'div'
el.innerHTML = '<a target="_blank"><img></a>'
el.firstChild.href = el.firstChild.firstChild.src = a.href
el
$.el 'div', <%= html('<a target="_blank" href="${a.href}"><img src="${a.href}"></a>') %>
,
key: 'InstallGentoo'
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/
@ -297,17 +293,13 @@ Linkify =
return div.textContent = "ERROR: Not a valid filetype" unless embed
switch embed.type
when 'video/mp4', 'video/webm', 'video/ogv'
el.innerHTML = '<video autoplay loop><source type="video/mp4"><source type="video/webm"><source type="video/ogg"></video>'
for ext, i in ['mp4', 'webm', 'ogv']
$.extend el, <%= html('<video autoplay loop><source type="video/mp4"><source type="video/webm"></video>') %>
for ext, i in ['mp4', 'webm']
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
when 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'
el.innerHTML = '<a target="_blank"><img></a>'
el.firstChild.href = a.href
el.firstChild.firstChild.src = "https://mediacru.sh/#{file.file}"
$.extend el, <%= html('<a target="_blank" href="${a.href}"><img src="https://mediacru.sh/${file.file}"></a>') %>
when 'audio/mpeg', 'audio/ogg'
el.innerHTML = '<audio controls><source type="audio/ogg"><source type="audio/mpeg"></audio>'
for ext, i in ['ogg', 'mp3']
el.firstChild.children[i].src = "https://mediacru.sh/#{a.dataset.uid}.#{ext}"
$.extend el, <%= html('<audio controls><source type="audio/ogg" src="https://mediacru.sh/${a.dataset.uid}.ogg"></audio>') %>
else
el.textContent = "ERROR: No valid filetype."
el
@ -350,14 +342,14 @@ Linkify =
idparam = {'b': 'archive_id', 'c': 'chapter_id'}
obj = $.el 'object',
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf'
obj.innerHTML = '<param name="allowFullScreen" value="true"><param name="flashvars">'
$.extend obj, <%= html('<param name="allowFullScreen" value="true"><param name="flashvars">') %>
obj.children[1].value = "channel=#{channel}&start_volume=25&auto_play=false&#{idparam[type]}=#{id}"
obj
else
channel = (/(\w+)/.exec a.dataset.uid)[0]
obj = $.el 'object',
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=#{channel}"
obj.innerHTML = '<param name="allowFullScreen" value="true"><param name="flashvars">'
$.extend obj, <%= html('<param name="allowFullScreen" value="true"><param name="flashvars">') %>
obj.children[1].value = "hostname=www.twitch.tv&channel=#{channel}&auto_play=true&start_volume=25"
obj
,

View File

@ -16,8 +16,8 @@ Menu =
makeButton: do ->
a = $.el 'a',
className: 'menu-button'
innerHTML: '<i class="fa fa-angle-down"></i>'
href: 'javascript:;'
$.extend a, <%= html('<i class="fa fa-angle-down"></i>') %>
->
button = a.cloneNode true
$.on button, 'click', Menu.toggle

View File

@ -22,10 +22,9 @@ PSAHiding =
$.on entry.el, 'click', PSAHiding.toggle
PSAHiding.btn = btn = $.el 'span',
innerHTML: '[<a href="javascript:;">Dismiss</a>]'
title: 'Mark announcement as read and hide.'
className: 'hide-announcement'
href: 'javascript:;'
$.extend btn, <%= html('[<a href="javascript:;">Dismiss</a>]') %>
$.on btn, 'click', PSAHiding.toggle
$.get 'hiddenPSA', 0, ({hiddenPSA}) ->

View File

@ -7,58 +7,34 @@ FileInfo =
cb: @node
node: ->
return if !@file or @isClone
@file.text.innerHTML = '<span class="file-info"></span>'
$.extend @file.text, <%= html('<span class="file-info"></span>') %>
FileInfo.format Conf['fileInfo'], @, @file.text.firstElementChild
format: (formatString, post, outputNode) ->
FileInfo.innerHTML = ''
output = []
formatString.replace /%(.)|[^%]+/g, (s, c) ->
if c of FileInfo.formatters
output.push if c of FileInfo.formatters
FileInfo.formatters[c].call post
else
FileInfo.innerHTML += E s
<%= html('${s}') %>
''
outputNode.innerHTML = FileInfo.innerHTML
$.extend outputNode, <%= html('@{output}') %>
formatters:
t: ->
timestamp = @file.URL.match(/\d+\..+$/)[0]
FileInfo.innerHTML += E timestamp
T: ->
FileInfo.innerHTML += "<a href='#{E @file.URL}' target='_blank'>"
FileInfo.formatters.t.call @
FileInfo.innerHTML += '</a>'
l: ->
FileInfo.innerHTML += "<a href='#{E @file.URL}' target='_blank'>"
FileInfo.formatters.n.call @
FileInfo.innerHTML += '</a>'
L: ->
FileInfo.innerHTML += "<a href='#{E @file.URL}' target='_blank'>"
FileInfo.formatters.N.call @
FileInfo.innerHTML += '</a>'
t: -> <%= html('${@file.URL.match(/\\d+\\..+$/)[0]}') %>
T: -> <%= html('<a href="${@file.URL}" target="_blank">&{FileInfo.formatters.t.call @}</a>') %>
l: -> <%= html('<a href="${@file.URL}" target="_blank">&{FileInfo.formatters.n.call @}</a>') %>
L: -> <%= html('<a href="${@file.URL}" target="_blank">&{FileInfo.formatters.N.call @}</a>') %>
n: ->
fullname = @file.name
shortname = Build.shortFilename @file.name, @isReply
if fullname is shortname
FileInfo.innerHTML += E fullname
<%= html('${fullname}') %>
else
FileInfo.innerHTML += "<span class='fnswitch'><span class='fntrunc'>#{E shortname}</span><span class='fnfull'>#{E fullname}</span></span>"
N: ->
FileInfo.innerHTML += E @file.name
p: ->
if @file.isSpoiler
FileInfo.innerHTML += 'Spoiler, '
s: ->
FileInfo.innerHTML += E @file.size
B: ->
sizeB = Math.round(@file.sizeInBytes)
FileInfo.innerHTML += "#{+sizeB} Bytes"
K: ->
sizeKB = Math.round(@file.sizeInBytes/1024)
FileInfo.innerHTML += "#{+sizeKB} KB"
M: ->
sizeMB = Math.round(@file.sizeInBytes/1048576*100)/100
FileInfo.innerHTML += "#{+sizeMB} MB"
r: ->
dim = @file.dimensions or 'PDF'
FileInfo.innerHTML += E dim
'%': ->
FileInfo.innerHTML += '%'
<%= html('<span class="fnswitch"><span class="fntrunc">${shortname}</span><span class="fnfull">${fullname}</span></span>') %>
N: -> <%= html('${@file.name}') %>
p: -> if @file.isSpoiler then <%= html('Spoiler, ') %> else <%= html('') %>
s: -> <%= html('${@file.size}') %>
B: -> <%= html('${Math.round @file.sizeInBytes} Bytes') %>
K: -> <%= html('${Math.round(@file.sizeInBytes/1024)} KB') %>
M: -> <%= html('${Math.round(@file.sizeInBytes/1048576*100)/100} MB') %>
r: -> <%= html('${@file.dimensions or "PDF"}') %>
'%': -> <%= html('%') %>

View File

@ -2,16 +2,19 @@ ThreadStats =
init: ->
return if g.VIEW isnt 'thread' or !Conf['Thread Stats']
countHTML = <%= html('<span id="post-count">0</span> / <span id="file-count">0</span>') %>
countHTML = <%= html('&{countHTML} / <span id="file-count">0</span>') %> if Conf['Page Count in Stats']
if Conf['Updater and Stats in Header']
@dialog = sc = $.el 'span',
innerHTML: "<span id='post-count'>0</span> / <span id='file-count'>0</span>#{if Conf['Page Count in Stats'] then ' / <span id="page-count">0</span>' else ''}"
id: 'thread-stats'
title: 'Post Count / File Count' + (if Conf["Page Count in Stats"] then " / Page Count" else "")
$.extend sc, countHTML
$.ready ->
Header.addShortcut sc
else
@dialog = sc = UI.dialog 'thread-stats', 'bottom: 0px; right: 0px;',
innerHTML: "<div class='move' title='Post Count / File Count#{if Conf['Page Count in Stats'] then ' / Page Count' else ''}'><span id='post-count'>0</span> / <span id='file-count'>0</span>#{if Conf['Page Count in Stats'] then ' / <span id="page-count">0</span>' else ''}</div>"
<%= html('<div class="move" title="Post Count / File Count${if Conf["Page Count in Stats"] then " / Page Count" else ""}">&{countHTML}</div>') %>
$.ready =>
$.add d.body, sc

View File

@ -4,13 +4,13 @@ ThreadUpdater =
if Conf['Updater and Stats in Header']
@dialog = sc = $.el 'span',
innerHTML: '<span id="update-status"></span><span id="update-timer" title="Update now"></span>'
id: 'updater'
$.extend sc, <%= html('<span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
$.ready ->
Header.addShortcut sc
else
@dialog = sc = UI.dialog 'updater', 'bottom: 0px; left: 0px;',
innerHTML: '<div class="move"></div><span id="update-status"></span><span id="update-timer" title="Update now"></span>'
<%= html('<div class="move"></div><span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
$.addClass doc, 'float'
$.ready =>
$.addClass doc, 'float'
@ -26,8 +26,8 @@ ThreadUpdater =
$.on @status, 'click', @update
updateLink = $.el 'span',
innerHTML: '<a href="javascript:;">Update</a>'
className: 'brackets-wrap updatelink'
$.extend updateLink, <%= html('<a href="javascript:;">Update</a>') %>
$.ready ->
$.add $('.navLinksBot'), [$.tn(' '), updateLink]
$.on updateLink.firstElementChild, 'click', @update
@ -46,7 +46,7 @@ ThreadUpdater =
subEntries.push el: el
@settings = $.el 'span',
innerHTML: '<a href="javascript:;">Interval</a>'
<%= html('<a href="javascript:;">Interval</a>') %>
$.on @settings, 'click', @intervalShortcut

View File

@ -10,7 +10,7 @@ ThreadWatcher =
className: 'disabled fa fa-eye'
@db = new DataBoard 'watchedThreads', @refresh, true
@dialog = UI.dialog 'thread-watcher', 'top: 50px; left: 0px;', innerHTML: <%= importHTML('Monitoring/ThreadWatcher') %>
@dialog = UI.dialog 'thread-watcher', 'top: 50px; left: 0px;', <%= importHTML('Monitoring/ThreadWatcher') %>
@status = $ '#watcher-status', @dialog
@list = @dialog.lastElementChild

View File

@ -8,7 +8,7 @@ QR.captcha =
imgContainer = $.el 'div',
className: 'captcha-img'
title: 'Reload reCAPTCHA'
innerHTML: '<img>'
$.extend imgContainer, <%= html('<img>') %>
input = $.el 'input',
className: 'captcha-input field'
title: 'Verification'

View File

@ -45,9 +45,9 @@ QR =
return unless QR.postingIsEnabled
link = $.el 'h1',
innerHTML: "<a href='javascript:;' class='qr-link'>#{if g.VIEW is 'thread' then 'Reply to Thread' else 'Start a Thread'}</a>"
className: "qr-link-container"
$.extend link, <%= html('<a href="javascript:;" class="qr-link">${if g.VIEW is "thread" then "Reply to Thread" else "Start a Thread"}</a>') %>
QR.link = link.firstElementChild
$.on link.firstChild, 'click', ->
$.event 'CloseMenu'
@ -58,8 +58,8 @@ QR =
if Conf['Bottom QR Link'] and g.VIEW is 'thread'
linkBot = $.el 'div',
innerHTML: '<a href="javascript:;" class="qr-link-bottom">Reply to Thread</a>'
className: "brackets-wrap qr-link-container-bottom"
$.extend linkBot, <%= html('<a href="javascript:;" class="qr-link-bottom">Reply to Thread</a>') %>
$.on linkBot.firstElementChild, 'click', ->
$.event 'CloseMenu'
@ -422,7 +422,7 @@ QR =
dialog: ->
QR.nodes = nodes =
el: dialog = UI.dialog 'qr', 'top:0;right:0;', innerHTML: <%= importHTML('Features/QuickReply') %>
el: dialog = UI.dialog 'qr', 'top:0;right:0;', <%= importHTML('Features/QuickReply') %>
setNode = (name, query) ->
nodes[name] = $ query, dialog
@ -484,17 +484,16 @@ QR =
nodes.spoiler.parentElement.hidden = true
if g.BOARD.ID is 'f' and g.VIEW isnt 'thread'
nodes.flashTag = $.el 'select',
name: 'filetag'
innerHTML: '''
<option value=0>Hentai</option>
<option value=6>Porn</option>
<option value=1>Japanese</option>
<option value=2>Anime</option>
<option value=3>Game</option>
<option value=5>Loop</option>
<option value=4 selected>Other</option>
'''
nodes.flashTag = $.el 'select', name: 'filetag'
$.extend nodes.flashTag, <%= html(
'<option value="0">Hentai</option>' +
'<option value="6">Porn</option>' +
'<option value="1">Japanese</option>' +
'<option value="2">Anime</option>' +
'<option value="3">Game</option>' +
'<option value="5">Loop</option>' +
'<option value="4" selected>Other</option>'
) %>
nodes.flashTag.dataset.default = '4'
$.add nodes.form, nodes.flashTag
@ -682,10 +681,11 @@ QR =
QR.cooldown.auto = false
QR.status()
QR.error $.el 'span',
innerHTML: '''
4chan X encountered an error while posting.
[<a href="//4chan.org/banned" target="_blank">Banned?</a>] [<a href="<%= meta.faq %>#what-does-4chan-x-encountered-an-error-while-posting-please-try-again-mean" target="_blank">More info</a>]
'''
<%= html(
'4chan X encountered an error while posting. ' +
'[<a href="//4chan.org/banned" target="_blank">Banned?</a>] ' +
'[<a href="${g.FAQ}#what-does-4chan-x-encountered-an-error-while-posting-please-try-again-mean" target="_blank">More info</a>]'
) %>
extra =
form: $.formData formData
upCallbacks:
@ -718,9 +718,9 @@ QR =
if ban = $ '.banType', resDoc # banned/warning
err = $.el 'span',
if ban.textContent.toLowerCase() is 'banned'
innerHTML: "You are banned on #{$('.board', resDoc).innerHTML}! ;_;<br>Click <a href='//www.4chan.org/banned' target='_blank'>here</a> to see the reason."
<%= html('You are banned on &{$(".board", resDoc)}! ;_;<br>Click <a href="//www.4chan.org/banned" target="_blank">here</a> to see the reason.') %>
else
innerHTML: "You were issued a warning on #{$('.board', resDoc).innerHTML} as #{$('.nameBlock', resDoc).innerHTML}.<br>Reason: #{$('.reason', resDoc).innerHTML}"
<%= html('You were issued a warning on &{$(".board", resDoc)} as &{$(".nameBlock", resDoc)}.<br>Reason: &{$(".reason", resDoc)}') %>
else if err = resDoc.getElementById 'errmsg' # error!
$('a', err)?.target = '_blank' # duplicate image link
else if resDoc.title isnt 'Post successful!'

View File

@ -4,7 +4,7 @@ QR.post = class
className: 'qr-preview'
draggable: true
href: 'javascript:;'
innerHTML: '<a class="remove fa fa-times-circle" title="Remove"></a><label hidden><input type="checkbox"> Spoiler</label><span></span>'
$.extend el, <%= html('<a class="remove fa fa-times-circle" title="Remove"></a><label hidden><input type="checkbox"> Spoiler</label><span></span>') %>
@nodes =
el: el

View File

@ -8,7 +8,7 @@ QuoteThreading =
@enabled = true
@controls = $.el 'span',
innerHTML: '<label><input id="threadingControl" type="checkbox" checked> Threading</label>'
<%= html('<label><input id="threadingControl" type="checkbox" checked> Threading</label>') %>
input = $ 'input', @controls
$.on input, 'change', @toggle