diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2017-12-15 05:36:50 +0100 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2017-12-15 05:36:50 +0100 |
| commit | 7ad469291c015b33a2d20587db26b9621ed82d00 (patch) | |
| tree | 83e2a56822033a638d03ff7ddf4bfee3181631e6 /public/assets/js | |
| parent | cc585396a85e3107bb7b4298098b84b738919c8f (diff) | |
sort file list by name or date, updates audio player
Diffstat (limited to 'public/assets/js')
| -rw-r--r-- | public/assets/js/lib/views/details/audio.js | 42 | ||||
| -rw-r--r-- | public/assets/js/lib/views/details/files.js | 71 | ||||
| -rw-r--r-- | public/assets/js/lib/views/details/index.js | 2 | ||||
| -rw-r--r-- | public/assets/js/lib/views/details/settings.js | 94 | ||||
| -rw-r--r-- | public/assets/js/lib/views/index/threadbox.js | 2 | ||||
| -rw-r--r-- | public/assets/js/util/format.js | 2 | ||||
| -rw-r--r-- | public/assets/js/vendor/util.js | 1 |
7 files changed, 167 insertions, 47 deletions
diff --git a/public/assets/js/lib/views/details/audio.js b/public/assets/js/lib/views/details/audio.js index 42f5376..e328a07 100644 --- a/public/assets/js/lib/views/details/audio.js +++ b/public/assets/js/lib/views/details/audio.js @@ -3,24 +3,35 @@ var audio = (function(){ var el, music = [], current_index = -1 var links, comment, parent + var selected = false var playing = false audio.init = function () { - links = document.querySelectorAll("a") comment = document.querySelector("#comment") parent = document.querySelector("#audio") - - Array.prototype.slice.apply(links).forEach(function(url){ - if (! url.href.match(/(mp3|wav|ogg)/)) return - url.dataset.index = music.length - music.push(url) - }) + + audio.index() audio.build() } + audio.index = function () { + music = [] + var links = document.querySelectorAll("a") + Array.prototype.slice.apply(links).forEach(function(link){ + if (! link.href.match(/(mp3|wav|ogg)/)) return + link.dataset.index = music.length + music.push(link) + if (playing && link.href === el.src) { + current_index = parseInt(link.dataset.index) + } + }) + if (playing) { + audio.set_cursor() + } + } audio.build = function () { el = document.createElement("audio") el.setAttribute("controls", true) - el.addEventListener("loadeddata", () => { if (playing) el.play() }) + el.addEventListener("loadeddata", () => { if (selected) el.play() }) el.addEventListener("ended", audio.next) el.src = music[0] parent.appendChild(el) @@ -33,10 +44,14 @@ var audio = (function(){ document.body.removeEventListener("keydown", audio.keydown) } audio.play = function (index) { + playing = true current_index = (parseInt(index) + music.length) % music.length el.src = music[current_index].href - playing = document.querySelector(".playing") - if (playing) playing.classList.remove("playing") + audio.set_cursor() + } + audio.set_cursor = function () { + selected = document.querySelector(".playing") + if (selected) selected.classList.remove("playing") music[current_index].classList.add("playing") } audio.prev = function (){ @@ -50,6 +65,13 @@ var audio = (function(){ else el.pause() } audio.keydown = function(e){ + function element_is_text_input(el) { + var tagName = el.tagName.toLowerCase() + return (tagName == 'input' && el.type == 'text' || tagName == 'textarea') + } + if (element_is_text_input(document.activeElement)) { + return + } if (app.typing || e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return switch (e.keyCode) { case 37: // left diff --git a/public/assets/js/lib/views/details/files.js b/public/assets/js/lib/views/details/files.js index e8832a7..b68d42c 100644 --- a/public/assets/js/lib/views/details/files.js +++ b/public/assets/js/lib/views/details/files.js @@ -4,6 +4,8 @@ var FilesView = FormView.extend({ events: { "click .file": "pick", + "click #sortByName": "sortByName", + "click #sortByDate": "sortByDate", }, initialize: function(){ @@ -17,23 +19,61 @@ var FilesView = FormView.extend({ this.$el.hide() } var total = 0, has_music = false + this.files = files files.forEach(function(file){ if (is_image(file.filename)) { // return } - this.appendFile(file) total += file.size has_music = has_music || file.filename.match(/(mp3|wav|ogg)/i) }.bind(this)) - var size = hush_size(total) - var t = this.templateTotal.replace(/{{size_class}}/g, size[0]) - .replace(/{{size}}/g, size[1]) - this.$el.append(t) + this.total = total + this.has_music = has_music - if (has_music) { + if (this.has_music) { audio.init() } + + this.sortByName() + }, + + files: [], + sortedFiles: [], + currentSort: 'name', + reverse: false, + + sortByName: function(e){ + e && e.preventDefault() + if (this.currentSort !== 'name') { + this.currentSort = 'name' + this.reverse = false + } else { + this.reverse = !this.reverse + } + this.sort((a,b) => cmp(a.filename, b.filename)) + }, + sortByDate: function(e){ + e && e.preventDefault() + if (this.currentSort !== 'date') { + this.currentSort = 'date' + this.reverse = true + } else { + this.reverse = !this.reverse + } + this.sort((a,b) => cmp(a.date, b.date)) + }, + + sort: function(f){ + this.$el.empty() + this.sortedFiles = this.reverse ? this.files.sort(f) : this.files.sort(f).reverse() + this.sortedFiles.forEach(file => { + this.appendFile(file) + }) + this.appendTotal() + if (this.has_music) { + audio.index() + } }, parse: function(file){ @@ -64,11 +104,28 @@ var FilesView = FormView.extend({ this.$el.append($el) }, + appendTotal: function(){ + var size = hush_size(this.total) + var nameClass = this.sort === 'name' ? 'bold' : '' + if (nameClass && this.reverse) { + nameClass += ' italic' + } + var dateClass = this.sort === 'date' ? 'bold' : '' + if (dateClass && this.reverse) { + dateClass += ' italic' + } + var t = this.templateTotal.replace(/{{size_class}}/g, size[0]) + .replace(/{{size}}/g, size[1]) + .replace(/{{nameClass}}/g, nameClass) + .replace(/{{dateClass}}/g, dateClass) + this.$el.append(t) + }, + pick: function(e){ if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return if (! e.target.href || ! e.target.href.match(/(mp3|wav|ogg)/i)) return e.preventDefault() - audio.play( e.target.dataset.index ) + audio.play( e.target.dataset.index ) // index set in audio.js }, })
\ No newline at end of file diff --git a/public/assets/js/lib/views/details/index.js b/public/assets/js/lib/views/details/index.js index df2aeff..1b67b92 100644 --- a/public/assets/js/lib/views/details/index.js +++ b/public/assets/js/lib/views/details/index.js @@ -28,7 +28,7 @@ var DetailsView = View.extend({ populate: function(data){ this.data = data - console.log(data) + // console.log(data) set_background_color(data.thread.color || (data.keyword ? data.keyword.color : 'plain')) $("body").removeClass('loading') var thread = data.thread diff --git a/public/assets/js/lib/views/details/settings.js b/public/assets/js/lib/views/details/settings.js index 1124826..0a77774 100644 --- a/public/assets/js/lib/views/details/settings.js +++ b/public/assets/js/lib/views/details/settings.js @@ -8,6 +8,10 @@ var ThreadSettingsForm = FormView.extend({ "click .thread_delete": "deleteThread", "click .close_link": "hide", "change [name=color]": "changeColor", + "change [name=privacy]": "toggleAllowed", + "click #allowed_names [type=checkbox]": "removeAllowed", + "keydown [name=allowed_field]": "keydownAllowed", + "blur [name=allowed_field]": "updateAllowed", }, action: "", @@ -29,7 +33,9 @@ var ThreadSettingsForm = FormView.extend({ var settings = thread.settings var display = thread.display + this.thread = thread this.action = "/api/thread/" + thread.id + this.allowed = (this.thread.allowed || "").split(" ").map(s => s.trim()).filter(s => !! s) this.$(".close_link").attr("href", "/details/" + thread.id) this.$(".metadata").html(metadata(thread)) @@ -38,6 +44,7 @@ var ThreadSettingsForm = FormView.extend({ this.$("[name=hootbox]").prop("checked", !!thread.settings.hootbox) this.$("[name=shorturls]").prop("checked", !!thread.settings.shorturls) this.$("[name=noupload]").prop("checked", !!thread.settings.noupload) + this.$("[name=privacy]").prop("checked", !!thread.privacy) var $color = this.$('[name=color]') Object.keys(COLORS).forEach((color) => { @@ -48,13 +55,13 @@ var ThreadSettingsForm = FormView.extend({ }) $color.val(thread.color || keyword ? keyword.color : "") + this.toggleAllowed() this.fetchKeywords() -// this.fetchAllowedUsers(thread) $("body").removeClass("loading") }, - fetchKeywords: function(){ + fetchKeywords: function(thread){ $.get('/api/keywords', function(data){ var $keyword = this.$('[name=keyword]') data.keywords @@ -66,33 +73,62 @@ var ThreadSettingsForm = FormView.extend({ option.innerHTML = keyword $keyword.append(option) }) - $keyword.val(thread.keyword) + $keyword.val(this.thread.keyword) }.bind(this)) }, -// fetchAllowedUsers: function(thread){ -// var usernameRegexp = new RegExp('{{username}}', g) -// $.get('/api/thread/' + thread.id + '/interested', function(data){ -// var $allowed = this.$(".allowed") -// var tmpl = this.allowedTemplate -// // make a lookup of existing users -// var allowed = {} -// thread.allowed.split(" ").forEach((username) => { -// -// }) -// // build the ui -// data.interestedUsers -// .map( (a) => a.username) -// .sort( (a,b) => a < b ? -1 : a === b ? 0 : 1 ) -// .forEach((username) => { -// var t = tmpl.replace(usernameRegexp, "") -// .replace('{{checked}}', -// $keyword.append(option) -// }) -// $keyword.val(thread.keyword) -// }.bind(this)) -// }, - + toggleAllowed: function(e){ + var checked = this.$('[name=privacy]').prop('checked') + this.$(".allowed_field_container").toggle(checked) + this.$(".allowed_names").toggle(checked) + if (! checked) return + this.$("[name=allowed_field]").focus() + this.displayAllowed() + }, + + displayAllowed: function(e){ + var $allowedNames = this.$(".allowed_names").empty() + this.allowed.forEach(username => { + var t = this.allowedTemplate.replace(/{{username}}/g, username) + $allowedNames.append(t) + }) + }, + + keydownAllowed: function(e){ + if (e.keyCode === 13) { // enter + e.preventDefault() + e.stopPropagation() + this.updateAllowed() + } + }, + + updateAllowed: function(){ + var usernames = this.$('[name=allowed_field]').val().replace(/,/g, ' ').split(' ').map(s => s.trim()).filter(s => !! s) + this.$('[name=allowed_field]').val('') + usernames = usernames.filter( (name) => this.allowed.indexOf(name) === -1 ) + .map( (name) => sanitize(name) ) + $.ajax({ + method: "PUT", + url: "/api/checkUsernames", + headers: { "csrf-token": $("[name=_csrf]").attr("value") }, + data: JSON.stringify({ csrf: csrf(), usernames: usernames }), + contentType: "application/json", + dataType: "json", + success: function(data){ + if (! data.usernames || ! data.usernames.length) return + this.allowed = this.allowed.concat(data.usernames) + this.displayAllowed() + }.bind(this), + }) + }, + + removeAllowed: function(){ + this.allowed = this.$("#allowed_names input[type=checkbox]:checked").map(function(){ + return $(this).val() + }) + this.displayAllowed() + }, + validate: function(){ var errors = [] var title = $("[name=title]").val() @@ -107,11 +143,13 @@ var ThreadSettingsForm = FormView.extend({ title: $("[name=title]").val(), keyword: $("[name=keyword]").val(), color: $("[name=color]").val(), + privacy: $("[name=privacy]:checked").val() ? 1 : 0, + allowed: this.allowed.join(","), settings: { hootbox: $("[name=hootbox]:checked").val() ? true : false, shorturls: $("[name=shorturls]:checked").val() ? true : false, noupload: $("[name=noupload]:checked").val() ? true : false, - } + }, } return JSON.stringify(data) }, @@ -125,6 +163,7 @@ var ThreadSettingsForm = FormView.extend({ show: function(){ this.visible = true + app.typing = true this.populate() this.$el.addClass('visible') app.router.pushState("/details/" + this.options.parent.data.thread.id + "/settings") @@ -133,6 +172,7 @@ var ThreadSettingsForm = FormView.extend({ hide: function(e){ e && e.preventDefault() this.visible = false + app.typing = false this.$el.removeClass('visible') app.router.pushState("/details/" + this.options.parent.data.thread.id) }, diff --git a/public/assets/js/lib/views/index/threadbox.js b/public/assets/js/lib/views/index/threadbox.js index 65ad945..4ecb919 100644 --- a/public/assets/js/lib/views/index/threadbox.js +++ b/public/assets/js/lib/views/index/threadbox.js @@ -53,7 +53,7 @@ var ThreadBox = View.extend({ var size = hush_size(thread.size) var comments = hush_null(thread.comment_count, "c") var files = hush_null(thread.file_count, "f") - var dot = privacy_dot(thread.private) + var dot = privacy_dot(thread.privacy) var datetime = verbose_date(thread.lastmodified) var age = get_age(thread.lastmodified) var id = thread.id + get_revision(thread) diff --git a/public/assets/js/util/format.js b/public/assets/js/util/format.js index 339e4f6..e58928e 100644 --- a/public/assets/js/util/format.js +++ b/public/assets/js/util/format.js @@ -28,7 +28,7 @@ function commatize (n) { function privacy_dot (p) { if (! p) return "·" - else return "·:" + else return ".:" } var short_months = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ") diff --git a/public/assets/js/vendor/util.js b/public/assets/js/vendor/util.js index 34ef45f..b08a914 100644 --- a/public/assets/js/vendor/util.js +++ b/public/assets/js/vendor/util.js @@ -71,6 +71,7 @@ function mod(n,m){ return n-(m * floor(n/m)) } function dist(x0,y0,x1,y1){ return sqrt(pow(x1-x0,2)+pow(y1-y0,2)) } function angle(x0,y0,x1,y1){ return atan2(y1-y0,x1-x0) } function avg(m,n,a){ return (m*(a-1)+n)/a } +function cmp (a,b){ return (a<b)?-1:(a===b)?0:1 } function noop(){} function pixel(x,y){ return 4*(mod(y,actual_h)*actual_w+mod(x,actual_w)) } |
