Better file input interface.
This commit is contained in:
parent
0c4eaed642
commit
1dcdd2c20a
File diff suppressed because one or more lines are too long
@ -511,10 +511,10 @@ a[href="javascript:;"] {
|
|||||||
background: -webkit-linear-gradient(#CCC, #DDD);
|
background: -webkit-linear-gradient(#CCC, #DDD);
|
||||||
background: linear-gradient(#CCC, #DDD);
|
background: linear-gradient(#CCC, #DDD);
|
||||||
}
|
}
|
||||||
#qr:not(.dump) #dump-list, .dump #spoilerLabel {
|
#qr:not(.dump) #dump-list-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#dump-list {
|
#dump-list-container {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
position: relative;
|
position: relative;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
@ -522,14 +522,14 @@ a[href="javascript:;"] {
|
|||||||
-o-user-select: none;
|
-o-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
#dump-list-container {
|
#dump-list {
|
||||||
counter-reset: qrpreviews;
|
counter-reset: qrpreviews;
|
||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
#dump-list-container:hover {
|
#dump-list:hover {
|
||||||
bottom: -10px;
|
bottom: -10px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -611,7 +611,7 @@ a[href="javascript:;"] {
|
|||||||
.textarea {
|
.textarea {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#charCount {
|
#char-count {
|
||||||
color: #000;
|
color: #000;
|
||||||
background: hsla(0, 0%, 100%, .5);
|
background: hsla(0, 0%, 100%, .5);
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
@ -620,7 +620,7 @@ a[href="javascript:;"] {
|
|||||||
right: 1px;
|
right: 1px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
#charCount.warning {
|
#char-count.warning {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
.captcha-img {
|
.captcha-img {
|
||||||
@ -633,17 +633,47 @@ a[href="javascript:;"] {
|
|||||||
height: 57px;
|
height: 57px;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
#qr [type='file'] {
|
#file-n-submit.has-file > #qr-no-file,
|
||||||
margin: 1px 0;
|
#file-n-submit:not(.has-file) > #qr-filename-container,
|
||||||
width: 70%;
|
#file-n-submit:not(.has-file) > #qr-file-spoiler,
|
||||||
|
#file-n-submit:not(.has-file) > #qr-filerm {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
#qr [type='submit'] {
|
#qr-no-file,
|
||||||
margin: 1px 0;
|
#qr-filename-container,
|
||||||
padding: 1px; /* not Gecko */
|
#qr-file-spoiler,
|
||||||
width: 30%;
|
#qr-filerm {
|
||||||
|
line-height: 2;
|
||||||
}
|
}
|
||||||
.gecko #qr [type='submit'] {
|
#file-n-submit {
|
||||||
padding: 0 1px; /* Gecko does not respect box-sizing: border-box */
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
#qr-no-file, #qr-filename-container {
|
||||||
|
-webkit-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
#qr-filename-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#qr-filename {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#qr-filerm {
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
#qr-file-spoiler {
|
||||||
|
margin: 6px 1px;
|
||||||
|
}
|
||||||
|
#qr input[type='file'] {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
|
|||||||
@ -67,7 +67,6 @@ QR =
|
|||||||
QR.replies[0].rm()
|
QR.replies[0].rm()
|
||||||
QR.cooldown.auto = false
|
QR.cooldown.auto = false
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.resetFileInput()
|
|
||||||
if !Conf['Remember Spoiler'] and QR.nodes.spoiler.checked
|
if !Conf['Remember Spoiler'] and QR.nodes.spoiler.checked
|
||||||
QR.nodes.spoiler.click()
|
QR.nodes.spoiler.click()
|
||||||
QR.cleanNotifications()
|
QR.cleanNotifications()
|
||||||
@ -292,7 +291,8 @@ QR =
|
|||||||
$.addClass QR.nodes.el, 'dump'
|
$.addClass QR.nodes.el, 'dump'
|
||||||
fileInput: (files) ->
|
fileInput: (files) ->
|
||||||
unless files instanceof FileList
|
unless files instanceof FileList
|
||||||
files = @files
|
files = Array::slice.call @files
|
||||||
|
QR.nodes.fileInput.value = null # Don't hold the files from being modified on windows
|
||||||
{length} = files
|
{length} = files
|
||||||
return unless length
|
return unless length
|
||||||
max = QR.nodes.fileInput.max
|
max = QR.nodes.fileInput.max
|
||||||
@ -302,10 +302,8 @@ QR =
|
|||||||
file = files[0]
|
file = files[0]
|
||||||
if file.size > max
|
if file.size > max
|
||||||
QR.error "File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})."
|
QR.error "File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})."
|
||||||
QR.resetFileInput()
|
|
||||||
else unless file.type in QR.mimeTypes
|
else unless file.type in QR.mimeTypes
|
||||||
QR.error 'Unsupported file type.'
|
QR.error 'Unsupported file type.'
|
||||||
QR.resetFileInput()
|
|
||||||
else
|
else
|
||||||
QR.selected.setFile file
|
QR.selected.setFile file
|
||||||
return
|
return
|
||||||
@ -321,9 +319,6 @@ QR =
|
|||||||
else
|
else
|
||||||
new QR.reply().setFile file
|
new QR.reply().setFile file
|
||||||
$.addClass QR.nodes.el, 'dump'
|
$.addClass QR.nodes.el, 'dump'
|
||||||
QR.resetFileInput() # reset input
|
|
||||||
resetFileInput: ->
|
|
||||||
QR.nodes.fileInput.value = null
|
|
||||||
resetThreadSelector: ->
|
resetThreadSelector: ->
|
||||||
if g.BOARD.ID is 'f'
|
if g.BOARD.ID is 'f'
|
||||||
if g.VIEW is 'index'
|
if g.VIEW is 'index'
|
||||||
@ -373,8 +368,10 @@ QR =
|
|||||||
|
|
||||||
QR.replies.push @
|
QR.replies.push @
|
||||||
setFile: (@file) ->
|
setFile: (@file) ->
|
||||||
@nodes.el.title = "#{file.name} (#{$.bytesToString file.size})"
|
@filename = "#{file.name} (#{$.bytesToString file.size})"
|
||||||
|
@nodes.el.title = @filename
|
||||||
@nodes.label.hidden = false if QR.spoiler
|
@nodes.label.hidden = false if QR.spoiler
|
||||||
|
@showFileData()
|
||||||
unless /^image/.test file.type
|
unless /^image/.test file.type
|
||||||
@el.style.backgroundImage = null
|
@el.style.backgroundImage = null
|
||||||
return
|
return
|
||||||
@ -425,13 +422,22 @@ QR =
|
|||||||
|
|
||||||
img.src = fileURL
|
img.src = fileURL
|
||||||
rmFile: ->
|
rmFile: ->
|
||||||
QR.resetFileInput()
|
|
||||||
delete @file
|
delete @file
|
||||||
|
delete @filename
|
||||||
@nodes.el.title = null
|
@nodes.el.title = null
|
||||||
@nodes.el.style.backgroundImage = null
|
@nodes.el.style.backgroundImage = null
|
||||||
@nodes.label.hidden = true if QR.spoiler
|
@nodes.label.hidden = true if QR.spoiler
|
||||||
|
@showFileData()
|
||||||
return unless window.URL
|
return unless window.URL
|
||||||
URL.revokeObjectURL @url
|
URL.revokeObjectURL @url
|
||||||
|
showFileData: (hide) ->
|
||||||
|
if @file
|
||||||
|
QR.nodes.filename.textContent = @filename
|
||||||
|
QR.nodes.filename.title = @filename
|
||||||
|
QR.nodes.spoiler.checked = @spoiler if QR.spoiler
|
||||||
|
$.addClass QR.nodes.fileSubmit, 'has-file'
|
||||||
|
else
|
||||||
|
$.rmClass QR.nodes.fileSubmit, 'has-file'
|
||||||
select: ->
|
select: ->
|
||||||
if QR.selected
|
if QR.selected
|
||||||
QR.selected.nodes.el.id = null
|
QR.selected.nodes.el.id = null
|
||||||
@ -445,8 +451,8 @@ QR =
|
|||||||
# Load this reply's values.
|
# Load this reply's values.
|
||||||
for name in ['name', 'email', 'sub', 'com']
|
for name in ['name', 'email', 'sub', 'com']
|
||||||
QR.nodes[name].value = @[name]
|
QR.nodes[name].value = @[name]
|
||||||
|
@showFileData()
|
||||||
QR.characterCount()
|
QR.characterCount()
|
||||||
QR.nodes.spoiler.checked = @spoiler
|
|
||||||
save: (input) ->
|
save: (input) ->
|
||||||
{value} = input
|
{value} = input
|
||||||
@[input.dataset.name] = value
|
@[input.dataset.name] = value
|
||||||
@ -488,7 +494,6 @@ QR =
|
|||||||
if el = $ '.over', @parentNode
|
if el = $ '.over', @parentNode
|
||||||
$.rmClass el, 'over'
|
$.rmClass el, 'over'
|
||||||
rm: ->
|
rm: ->
|
||||||
QR.resetFileInput()
|
|
||||||
$.rm @nodes.el
|
$.rm @nodes.el
|
||||||
index = QR.replies.indexOf @
|
index = QR.replies.indexOf @
|
||||||
if QR.replies.length is 1
|
if QR.replies.length is 1
|
||||||
@ -614,20 +619,24 @@ QR =
|
|||||||
<input data-name=email title=E-mail placeholder=E-mail class=field size=1>
|
<input data-name=email title=E-mail placeholder=E-mail class=field size=1>
|
||||||
<input data-name=sub title=Subject placeholder=Subject class=field size=1>
|
<input data-name=sub title=Subject placeholder=Subject class=field size=1>
|
||||||
</div>
|
</div>
|
||||||
<div id=dump-list>
|
<div id=dump-list-container>
|
||||||
<div id=dump-list-container>
|
<div id=dump-list>
|
||||||
<a id=addReply href=javascript:; title="Add a reply">+</a>
|
<a id=addReply href=javascript:; title="Add a reply">+</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class=textarea>
|
<div class=textarea>
|
||||||
<textarea data-name=com title=Comment placeholder=Comment class=field></textarea>
|
<textarea data-name=com title=Comment placeholder=Comment class=field></textarea>
|
||||||
<span id=charCount></span>
|
<span id=char-count></span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id=file-n-submit>
|
||||||
<input type=file title="Shift+Click to remove the selected file." multiple size=16>
|
<input id=qr-file-button type=button value='Choose files'>
|
||||||
|
<span id=qr-no-file>No selected file</span>
|
||||||
|
<span id=qr-filename-container><span id=qr-filename></span></span>
|
||||||
|
<a id=qr-filerm href=javascript:; title='Remove file'>×</a>
|
||||||
|
<input type=checkbox id=qr-file-spoiler title='Spoiler image'>
|
||||||
<input type=submit>
|
<input type=submit>
|
||||||
</div>
|
</div>
|
||||||
<label id=spoilerLabel><input type=checkbox id=spoiler> Spoiler Image</label>
|
<input type=file multiple>
|
||||||
</form>
|
</form>
|
||||||
""".replace />\s+</g, '><' # get rid of spaces between elements
|
""".replace />\s+</g, '><' # get rid of spaces between elements
|
||||||
|
|
||||||
@ -643,10 +652,14 @@ QR =
|
|||||||
sub: $ '[data-name=sub]', dialog
|
sub: $ '[data-name=sub]', dialog
|
||||||
com: $ '[data-name=com]', dialog
|
com: $ '[data-name=com]', dialog
|
||||||
addReply: $ '#addReply', dialog
|
addReply: $ '#addReply', dialog
|
||||||
charCount: $ '#charCount', dialog
|
charCount: $ '#char-count', dialog
|
||||||
fileInput: $ '[type=file]', dialog
|
fileSubmit: $ '#file-n-submit', dialog
|
||||||
spoiler: $ '#spoiler', dialog
|
fileButton: $ '#qr-file-button', dialog
|
||||||
|
filename: $ '#qr-filename', dialog
|
||||||
|
fileRM: $ '#qr-filerm', dialog
|
||||||
|
spoiler: $ '#qr-file-spoiler', dialog
|
||||||
status: $ '[type=submit]', dialog
|
status: $ '[type=submit]', dialog
|
||||||
|
fileInput: $ '[type=file]', dialog
|
||||||
|
|
||||||
# Allow only this board's supported files.
|
# Allow only this board's supported files.
|
||||||
mimeTypes = $('ul.rules > li').textContent.trim().match(/: (.+)/)[1].toLowerCase().replace /\w+/g, (type) ->
|
mimeTypes = $('ul.rules > li').textContent.trim().match(/: (.+)/)[1].toLowerCase().replace /\w+/g, (type) ->
|
||||||
@ -666,12 +679,12 @@ QR =
|
|||||||
nodes.fileInput.accept = mimeTypes if $.engine isnt 'presto' # Opera's accept attribute is fucked up
|
nodes.fileInput.accept = mimeTypes if $.engine isnt 'presto' # Opera's accept attribute is fucked up
|
||||||
|
|
||||||
QR.spoiler = !!$ 'input[name=spoiler]'
|
QR.spoiler = !!$ 'input[name=spoiler]'
|
||||||
nodes.spoiler.parentNode.hidden = !QR.spoiler
|
nodes.spoiler.hidden = !QR.spoiler
|
||||||
|
|
||||||
if g.BOARD.ID is 'f'
|
if g.BOARD.ID is 'f'
|
||||||
if g.VIEW is 'index'
|
if g.VIEW is 'index'
|
||||||
nodes.flashTag = $('select[name=filetag]').cloneNode true
|
nodes.flashTag = $('select[name=filetag]').cloneNode true
|
||||||
$.after QR.nodes.autohide, nodes.flashTag
|
$.after nodes.autohide, nodes.flashTag
|
||||||
else # Make a list of visible threads.
|
else # Make a list of visible threads.
|
||||||
nodes.thread = $.el 'select',
|
nodes.thread = $.el 'select',
|
||||||
title: 'Create a new thread / Reply'
|
title: 'Create a new thread / Reply'
|
||||||
@ -679,17 +692,18 @@ QR =
|
|||||||
for key, thread of g.BOARD.threads
|
for key, thread of g.BOARD.threads
|
||||||
threads += "<option value=#{thread.ID}>Thread No.#{thread.ID}</option>"
|
threads += "<option value=#{thread.ID}>Thread No.#{thread.ID}</option>"
|
||||||
nodes.thread.innerHTML = threads
|
nodes.thread.innerHTML = threads
|
||||||
$.after QR.nodes.autohide, nodes.thread
|
$.after nodes.autohide, nodes.thread
|
||||||
QR.resetThreadSelector()
|
QR.resetThreadSelector()
|
||||||
|
|
||||||
$.on nodes.autohide, 'change', QR.toggleHide
|
$.on nodes.autohide, 'change', QR.toggleHide
|
||||||
$.on nodes.close, 'click', QR.close
|
$.on nodes.close, 'click', QR.close
|
||||||
$.on nodes.dumpButton, 'click', -> QR.nodes.el.classList.toggle 'dump'
|
$.on nodes.dumpButton, 'click', -> nodes.el.classList.toggle 'dump'
|
||||||
$.on nodes.addReply, 'click', -> new QR.reply().select()
|
$.on nodes.addReply, 'click', -> new QR.reply().select()
|
||||||
$.on nodes.form, 'submit', QR.submit
|
$.on nodes.form, 'submit', QR.submit
|
||||||
|
$.on nodes.fileButton, 'click', -> QR.nodes.fileInput.click()
|
||||||
|
$.on nodes.fileRM, 'click', -> QR.selected.rmFile()
|
||||||
|
$.on nodes.spoiler, 'change', -> QR.selected.nodes.spoiler.click()
|
||||||
$.on nodes.fileInput, 'change', QR.fileInput
|
$.on nodes.fileInput, 'change', QR.fileInput
|
||||||
$.on nodes.fileInput, 'click', (e) -> if e.shiftKey then QR.selected.rmFile(); e.preventDefault()
|
|
||||||
$.on nodes.spoiler, 'change', -> $('input', QR.selected.el).click()
|
|
||||||
|
|
||||||
new QR.reply().select()
|
new QR.reply().select()
|
||||||
# save selected reply's data
|
# save selected reply's data
|
||||||
@ -894,7 +908,6 @@ QR =
|
|||||||
QR.close()
|
QR.close()
|
||||||
|
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.resetFileInput()
|
|
||||||
|
|
||||||
abort: ->
|
abort: ->
|
||||||
if QR.ajax
|
if QR.ajax
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user