[READ-ONLY] Mirror of https://github.com/probablykasper/lumix. Art website (unfinished)
art website
0

Configure Feed

Select the types of activity you want to include in your feed.

Upload page closer to complete

KH (Mar 5, 2018, 6:35 PM +0100) 85a245f0 b6a6201c

+452 -117
web/images/05aekeq36av.png

This is a binary file and will not be displayed.

web/images/ctrcg0192td.png

This is a binary file and will not be displayed.

web/images/ctyjx2hkc74.png

This is a binary file and will not be displayed.

web/images/pt9w27b2m0t.png

This is a binary file and will not be displayed.

web/images/qcvkgk8nc49.png

This is a binary file and will not be displayed.

web/images/r4f140jqccd.png

This is a binary file and will not be displayed.

web/images/t5gkhmknum0.png

This is a binary file and will not be displayed.

+11 -6
web/js/common.js
··· 10 10 } 11 11 } 12 12 13 - window.xhr = (reqContent, url, callback, options = {}) => { 14 - var xhr = new XMLHttpRequest(); 13 + window.xhr = (reqContent, url, options = {}, callback) => { 14 + if (typeof options == "function") callback = options; 15 + if (typeof options == "function") options = {}; 15 16 if (options.type == undefined) options.type = "POST"; 16 17 if (options.contentType == undefined) options.contentType = "json"; 18 + var xhr = new XMLHttpRequest(); 17 19 xhr.open(options.type, url, true); 18 20 if (options.type == "GET") { 19 21 xhr.send(); 20 - } else if (options.contentType == "values") { 22 + } else if (options.contentType == "form") { 21 23 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 22 24 xhr.send("data="+JSON.stringify(reqContent)); 23 25 } else if (options.contentType == "json") { 24 26 xhr.setRequestHeader("Content-type", "application/json"); 25 27 xhr.send(JSON.stringify(reqContent)); 28 + } else if (options.contentType == "none") { 29 + xhr.send(reqContent); 30 + // for file uploads (multipart/form-data) 31 + } else if (options.contentType) { 32 + xhr.setRequestHeader("Content-type", options.contentType); 33 + xhr.send(reqContent); 26 34 } 27 - // else if (options.contentType == "multipart") { 28 - // // xhr.setRequestHeader("Content-type", "multipart/form-data"); 29 - // } 30 35 xhr.onreadystatechange = function() { 31 36 if (this.readyState == 4) { 32 37 let res = JSON.parse(this.responseText);
+96 -38
web/js/forms.js
··· 1 - import qq from "fine-uploader/lib/core/traditional"; 2 1 // register form 3 2 fold("register form", () => { 4 3 ··· 60 59 61 60 fold("upload form", () => { 62 61 63 - function submitUploadForm() { 64 - const req = { 65 - title: $(".upload-form input.title").val(), 66 - description: $(".upload-form textarea.description").val(), 67 - }; 68 - // xhr(req, "/upload", (res, err) => { 69 - // if (err); // http status code not 2xx 70 - // console.log(res); 71 - // if (res.errors.length == 0) { 72 - // window.lcation = "???" 73 - // } 74 - // }); 75 - } 76 - 77 - fold("file upload", () => { 62 + fold("file select", () => { 78 63 79 64 // click "select file" button opens file select dialog 80 65 $("body").on("click", ".upload-form button.files", () => { ··· 82 67 }); 83 68 84 69 function containsAFile(e) { 85 - const dtTypes = e.originalEvent.dataTransfer.types; 86 - console.log(e.originalEvent.dataTransfer.files); 87 - // if (dtTypes.length == 1 && dtTypes[0] == "Files") { 88 - // return true; 89 - // } 90 - // return false; 70 + if (e.originalEvent) e = e.originalEvent; 71 + const dtTypes = e.dataTransfer.types; 72 + if (dtTypes.length == 1 && dtTypes[0] == "Files") { 73 + return true; 74 + } 75 + return false; 91 76 } 92 77 93 78 // setup 94 - const setupEvents = "drag dragstart dragend dragover dragenter dragleave drop"; 79 + // const setupEvents = "drag dragstart dragend dragover dragenter dragleave drop"; 80 + const setupEvents = "dragover dragenter dragleave drop"; 95 81 $(window).on(setupEvents, (e) => { 96 - console.log(containsAFile(e)); 97 82 if (containsAFile(e)) { 98 83 e.preventDefault(); 99 84 e.stopPropagation(); 100 85 } 101 86 }); 102 87 103 - // const qq = require("fine-uploader/fine-uploader/fine-uploader.core.js"); 104 - const uploader = new qq.FineUploaderBasic({ 105 - debug: true, 106 - element: $(".upload-form button.files").get(0), 107 - request: { 108 - endpoint: "/uploads", 109 - }, 110 - deleteFile: { 111 - enabled: true, 112 - endpoint: "uploads", 113 - }, 114 - retry: { 115 - enableAuto: true, 116 - }, 88 + function show() { 89 + $(".upload-form .select-file").addClass("hidden"); 90 + $(".upload-form button.files").addClass("file-drag"); 91 + $(".upload-form .drop-to-select-file").removeClass("hidden"); 92 + } 93 + function hide() { 94 + $(".upload-form .select-file").removeClass("hidden"); 95 + $(".upload-form button.files").removeClass("file-drag"); 96 + $(".upload-form .drop-to-select-file").addClass("hidden"); 97 + } 98 + // show 99 + $(window).on("dragenter", (e) => { 100 + if (containsAFile(e)) show(); 101 + if (containsAFile(e)) $(".upload-form .main-form").addClass("hidden"); 117 102 }); 103 + // hide 104 + $(window).on("dragend dragleave", (e) => { 105 + if (window.uploadData) { 106 + $(".upload-form .main-form").removeClass("hidden"); 107 + hide(); 108 + } 109 + e = e.originalEvent; 110 + if (containsAFile(e)) { 111 + if (e.type == "dragleave" && e.relatedTarget == null) hide(); 112 + else if (e.type != "dragleave") hide(); 113 + } 114 + }); 115 + // drop 116 + $(window).on("drop", (e) => { 117 + hide(); 118 + if (containsAFile(e)) { 119 + const files = e.originalEvent.dataTransfer.files; 120 + if (files[0].type == "image/png" || files[0].type == "image/jpeg") { 121 + handleFiles(files); 122 + } else { // wrong fileExt 123 + 124 + } 125 + } 126 + }); 127 + 128 + $("body").on("change", ".upload-form input#files", function(e) { 129 + const input = $(this); 130 + const files = input.prop("files"); 131 + handleFiles(files); 132 + }); 133 + 134 + // handle files 135 + function handleFiles(files) { 136 + window.uploadData = files; 137 + $(".select-file.container").addClass("hidden"); 138 + $(".upload-form .main-form").removeClass("hidden"); 139 + } 118 140 119 141 }); 120 142 ··· 144 166 if (e.target == e.currentTarget) { 145 167 $(".upload-form input.add-tag").focus(); 146 168 } 169 + }); 170 + 171 + function upload() { 172 + 173 + const data = new FormData(); 174 + data.append("image", uploadData[0], uploadData[0].name); 175 + data.append("title", $(".upload-form input.title").val()); 176 + data.append("description", $(".upload-form textarea.description").val()); 177 + 178 + const tagsArray = []; 179 + $(".upload-form .tags-box .tag").each((i, obj) => { 180 + const tagText = $(obj).find(".tag-text").html(); 181 + tagsArray.push(tagText); 182 + }); 183 + data.append("tags", JSON.stringify(tagsArray)); 184 + 185 + console.log(data.get("image")); 186 + console.log(data.get("title")); 187 + console.log(data.get("description")); 188 + console.log(data.get("tags")); 189 + 190 + xhr(data, "/upload", { 191 + contentType: "none", 192 + }, (res, err) => { 193 + if (err); // http status code not 2xx 194 + console.log(res); 195 + if (res.errors.length == 0) { 196 + console.log("success!"); 197 + } 198 + }); 199 + 200 + } 201 + 202 + // upload button click 203 + $("body").on("click", ".upload-form button.upload", () => { 204 + upload(); 147 205 }); 148 206 149 207 });
+50 -14
web/node/upload-routes.js
··· 1 1 "use strict"; 2 - const multiparty = require("multiparty"); 2 + 3 + function b32() { 4 + const length = 11; 5 + let string = require("crypto").randomBytes(7); 6 + string = require("base32").encode(string); 7 + return string.substr(0, length); 8 + } 9 + 10 + const multer = require("multer"); 11 + const storage = multer.diskStorage({ 12 + destination: function(req, file, callback) { 13 + callback(null, "images/"); 14 + }, 15 + filename: function(req, file, callback) { 16 + file.filename = b32(); 17 + let extension; 18 + if (file.mimetype == "image/jpeg") extension = ".jpg"; 19 + else if (file.mimetype == "image/png") extension = ".png"; 20 + else res.err = "wrongExt"; 21 + callback(null, file.filename+extension); 22 + } 23 + }); 24 + const upload = multer({ 25 + storage: storage, 26 + limits: { 27 + fileSize: 30*1000*1000 28 + } 29 + }); 3 30 4 31 module.exports = (app) => { 5 32 6 - app.post("/uploads", (req, res) => { 7 - const form = new multiparty.Form(); 33 + app.post("/upload", (req, res) => { 34 + if (res.locals.loggedIn) { 35 + let errors = []; 36 + upload.array("image", 1)(req, res, function(err) { 37 + if (err) { 38 + // error when uploading 39 + console.log("ERROR UPLOADING"); 40 + console.log(err); 41 + return; 42 + } 43 + // success 44 + console.log("SUCCESS UPLOADING"); 45 + req.files[0].filename; 46 + req.files[0].path; 47 + console.log(req.files); 48 + console.log(req.body); 8 49 9 - form.parse(req, (err, fields, files) => { 10 - let partIndex = fields.qqpartindex; 11 - // text/plain is required to ensure support for IE9 and older 12 - res.set("Content-Type", "text/plain"); 13 - if (partIndex == null) { 14 - onSimpleUpload(fields, files[fileInputName][0], res); 15 - } else { 16 - onChunkedUpload(fields, files[fileInputName][0], res); 17 - } 18 - }); 50 + let title = req.body.title; 51 + let description = req.body.description; 52 + let tags = JSON.parse(req.body.tags); 19 53 54 + }); 55 + } 20 56 }); 21 - 57 + 22 58 }
+3 -2
web/package.json
··· 37 37 "bcryptjs": "2.4.x", 38 38 39 39 "mongoose": "5.0.x", 40 - "fine-uploader": "5.15.x", 41 - "multiparty": "4.1.x" 40 + "multiparty": "4.1.x", 41 + "multer": "1.3.x", 42 + "base32": "0.0.x" 42 43 } 43 44 }
+19 -15
web/pug/logged-in/upload.pug
··· 1 1 .form-container.upload-form.page-width 2 2 .form 3 - button.button.files Select file 4 - input(type="file" name="files" id="files") 5 - label(for="title") Title 6 - input.form-field.title(type="text", name="title" id="title") 7 - label(for="description") Description 8 - textarea.form-field.auto-resize.description(type="text", name="description" id="description", rows="3") 9 - .tags-box 10 - .tag 11 - .tag-text Hey 12 - button.remove-tag x 13 - .tag 14 - .tag-text There 15 - button.remove-tag x 16 - input.add-tag(placeholder="Add a tag...") 17 - button.button.upload(tabIndex="0") Upload 3 + .select-file.container 4 + button.button.files Select file 5 + .drop-to-select-file.container.hidden 6 + p Drop to select the file 7 + .main-form.hidden 8 + input(type="file" name="files" id="files", accept="image/jpeg,image/png") 9 + label(for="title") Title 10 + input.form-field.title(type="text", name="title" id="title") 11 + label(for="description") Description 12 + textarea.form-field.auto-resize.description(type="text", name="description" id="description", rows="3") 13 + .tags-box 14 + .tag 15 + .tag-text Hey 16 + button.remove-tag x 17 + .tag 18 + .tag-text There 19 + button.remove-tag x 20 + input.add-tag(placeholder="Add a tag...") 21 + button.button.upload(tabIndex="0") Upload
+1
web/sass/buttons.sass
··· 2 2 padding: 12px 8px 3 3 position: relative 4 4 display: block 5 + background-color: transparent 5 6 &:hover::before 6 7 width: 50% 7 8 &:focus::before
+23 -2
web/sass/forms.sass
··· 10 10 flex-direction: column 11 11 font-size: 15px 12 12 .form 13 + position: relative 13 14 textarea 14 15 resize: none 15 16 input.form-field, textarea.form-field, .tags-box ··· 22 23 &.login-form 23 24 &.register-form 24 25 .form-container.upload-form 25 - button.files 26 - margin: auto 26 + .container 27 + position: absolute 28 + width: 100% 29 + height: 100% 30 + // background-color: white 31 + z-index: 1 32 + opacity: 1 33 + display: flex 34 + align-items: center 35 + justify-content: center 36 + transition: $transition-20 all 37 + &.hidden 38 + opacity: 0 39 + pointer-events: none 40 + .main-form 41 + &.hidden 42 + transform: scale(0.9) 43 + opacity: 0 44 + transition: $transition-30 all 45 + 27 46 input#files 28 47 display: none 29 48 input.form-field, textarea.form-field, .tags-box ··· 72 91 padding: $tag-padding $tag-padding 73 92 margin-bottom: 6px 74 93 background-color: transparent 94 + button.upload 95 + margin: auto
+35 -12
web/static/global.css
··· 185 185 html .button { 186 186 padding: 12px 8px; 187 187 position: relative; 188 - display: block; } 188 + display: block; 189 + background-color: transparent; } 189 190 html .button:hover::before { 190 191 width: 50%; } 191 192 html .button:focus::before { ··· 213 214 justify-content: center; 214 215 flex-direction: column; 215 216 font-size: 15px; } 216 - html .form-container .form textarea { 217 - resize: none; } 218 - html .form-container .form input.form-field, html .form-container .form textarea.form-field, html .form-container .form .tags-box { 219 - padding: 10px 14px; 220 - margin-top: 5px; 221 - margin-bottom: 15px; 222 - border-radius: 5px; 223 - width: 250px; 224 - background-color: #F3F3F3; } 217 + html .form-container .form { 218 + position: relative; } 219 + html .form-container .form textarea { 220 + resize: none; } 221 + html .form-container .form input.form-field, html .form-container .form textarea.form-field, html .form-container .form .tags-box { 222 + padding: 10px 14px; 223 + margin-top: 5px; 224 + margin-bottom: 15px; 225 + border-radius: 5px; 226 + width: 250px; 227 + background-color: #F3F3F3; } 228 + 229 + html .form-container.upload-form .container { 230 + position: absolute; 231 + width: 100%; 232 + height: 100%; 233 + z-index: 1; 234 + opacity: 1; 235 + display: flex; 236 + align-items: center; 237 + justify-content: center; 238 + transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1) all; } 239 + html .form-container.upload-form .container.hidden { 240 + opacity: 0; 241 + pointer-events: none; } 225 242 226 - html .form-container.upload-form button.files { 227 - margin: auto; } 243 + html .form-container.upload-form .main-form { 244 + transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1) all; } 245 + html .form-container.upload-form .main-form.hidden { 246 + transform: scale(0.9); 247 + opacity: 0; } 228 248 229 249 html .form-container.upload-form input#files { 230 250 display: none; } ··· 274 294 padding: 5px 5px; 275 295 margin-bottom: 6px; 276 296 background-color: transparent; } 297 + 298 + html .form-container.upload-form button.upload { 299 + margin: auto; }
+214 -28
web/static/global.js
··· 96 96 i++; 97 97 } 98 98 }; 99 - window.xhr = function (reqContent, url, callback) { 100 - var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; 101 99 102 - var xhr = new XMLHttpRequest(); 100 + window.xhr = function (reqContent, url) { 101 + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 102 + var callback = arguments[3]; 103 + 104 + if (typeof options == "function") callback = options; 105 + if (typeof options == "function") options = {}; 103 106 if (options.type == undefined) options.type = "POST"; 104 107 if (options.contentType == undefined) options.contentType = "json"; 108 + var xhr = new XMLHttpRequest(); 105 109 xhr.open(options.type, url, true); 106 110 if (options.type == "GET") { 107 111 xhr.send(); 108 - } else if (options.contentType == "values") { 112 + } else if (options.contentType == "form") { 109 113 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 110 114 xhr.send("data=" + JSON.stringify(reqContent)); 111 115 } else if (options.contentType == "json") { 112 116 xhr.setRequestHeader("Content-type", "application/json"); 113 117 xhr.send(JSON.stringify(reqContent)); 118 + } else if (options.contentType == "none") { 119 + xhr.send(reqContent); 120 + // for file uploads (multipart/form-data) 121 + } else if (options.contentType) { 122 + xhr.setRequestHeader("Content-type", options.contentType); 123 + xhr.send(reqContent); 114 124 } 115 - // else if (options.contentType == "multipart") { 116 - // // xhr.setRequestHeader("Content-type", "multipart/form-data"); 117 - // } 118 125 xhr.onreadystatechange = function () { 119 126 if (this.readyState == 4) { 120 127 var res = JSON.parse(this.responseText); ··· 142 149 143 150 // search, press enter 144 151 var searchField = $(".search")[0]; 145 - $(".search").keypress(function (e) { 152 + $("body").on("keypress", ".search", function (e) { 146 153 if (e.which == 13) { 147 154 var searchQuery = searchField.value; 148 155 window.location = "/search/" + searchQuery; ··· 152 159 if (loggedIn) { 153 160 154 161 // press profile pic to toggle account box 155 - $("img.account-icon").on("click", function () { 162 + $("body").on("click", "img.account-icon", function () { 156 163 $(".account-box").toggleClass("visible"); 157 164 }); 158 165 $(document).on("click", function (e) { ··· 162 169 }); 163 170 } 164 171 165 - // function fullPageElement(element) { 166 - // const headerHeight = $(".site-header").height(); 167 - // let windowHeight = $(window).height(); 168 - // element.height(windowHeight - headerHeight); 169 - // $(window).on("resize", () => { 170 - // windowHeight = $(window).height(); 171 - // element.height(windowHeight - headerHeight); 172 - // }); 173 - // } 174 - // if (page == "home") fullPageElement($(".center-container")); 175 - // if (page == "login") fullPageElement($(".form-container")); 176 - // if (page == "register") fullPageElement($(".form-container")); 172 + // auto-resize textareas 173 + $("body").on("input", "textarea.auto-resize", function (e) { 174 + var textarea = e.target; 175 + textarea.style.height = "auto"; 176 + var scrollheight = textarea.scrollHeight; 177 + var computedStyle = getComputedStyle(textarea); 178 + var paddingTop = computedStyle.paddingBottom.slice(0, -2); 179 + var paddingBot = computedStyle.paddingTop.slice(0, -2); 180 + var padding = Number(paddingTop) + Number(paddingBot); 181 + textarea.style.height = textarea.scrollHeight - padding + "px"; 182 + }); 177 183 178 184 /***/ }), 179 185 /* 3 */ ··· 183 189 184 190 185 191 // register form 186 - if (page == "register") { 187 - $("button.register").on("click", function () { 192 + fold("register form", function () { 193 + 194 + function submitRegisterForm() { 188 195 var req = { 189 196 displayname: $(".register-form input.displayname").val(), 190 197 username: $(".register-form input.username").val(), 191 198 email: $(".register-form input.email").val(), 192 199 password: $(".register-form input.password").val() 193 - // const req = 194 - // `email=${email}`+ 195 - // `&password=${password}` 196 - };xhr(req, "/register", function (res, err) { 200 + }; 201 + xhr(req, "/register", function (res, err) { 202 + if (err) ; // http status code not 2xx 203 + console.log(res); 204 + if (res.errors.length == 0) { 205 + window.location = "/login"; 206 + } 207 + }); 208 + } 209 + 210 + // register button click 211 + $("body").on("click", "button.register", function () { 212 + submitRegisterForm(); 213 + }); 214 + 215 + // enter to register 216 + $("body").on("keypress", ".register-form input", function (e) { 217 + if (e.which == 13) submitRegisterForm(); // enter 218 + }); 219 + }); 220 + 221 + fold("login form", function () { 222 + 223 + function submitLoginForm() { 224 + var req = { 225 + email: $(".login-form input.email").val(), 226 + password: $(".login-form input.password").val() 227 + }; 228 + xhr(req, "/login" + window.location.search, function (res, err) { 197 229 if (err) ; // http status code not 2xx 198 230 console.log(res); 231 + if (res.errors.length == 0) { 232 + window.location = res.redirect; 233 + } 199 234 }); 235 + } 236 + 237 + // login button click 238 + $("body").on("click", ".login-form button.login", function () { 239 + submitLoginForm(); 240 + }); 241 + 242 + // enter to login 243 + $("body").on("keypress", ".login-form input", function (e) { 244 + if (e.which == 13) submitLoginForm(); // enter 200 245 }); 201 - } 246 + }); 247 + 248 + fold("upload form", function () { 249 + 250 + fold("file select", function () { 251 + 252 + // click "select file" button opens file select dialog 253 + $("body").on("click", ".upload-form button.files", function () { 254 + $(".upload-form input#files").click(); 255 + }); 256 + 257 + function containsAFile(e) { 258 + if (e.originalEvent) e = e.originalEvent; 259 + var dtTypes = e.dataTransfer.types; 260 + if (dtTypes.length == 1 && dtTypes[0] == "Files") { 261 + return true; 262 + } 263 + return false; 264 + } 265 + 266 + // setup 267 + // const setupEvents = "drag dragstart dragend dragover dragenter dragleave drop"; 268 + var setupEvents = "dragover dragenter dragleave drop"; 269 + $(window).on(setupEvents, function (e) { 270 + if (containsAFile(e)) { 271 + e.preventDefault(); 272 + e.stopPropagation(); 273 + } 274 + }); 275 + 276 + function show() { 277 + $(".upload-form .select-file").addClass("hidden"); 278 + $(".upload-form button.files").addClass("file-drag"); 279 + $(".upload-form .drop-to-select-file").removeClass("hidden"); 280 + } 281 + function hide() { 282 + $(".upload-form .select-file").removeClass("hidden"); 283 + $(".upload-form button.files").removeClass("file-drag"); 284 + $(".upload-form .drop-to-select-file").addClass("hidden"); 285 + } 286 + // show 287 + $(window).on("dragenter", function (e) { 288 + if (containsAFile(e)) show(); 289 + if (containsAFile(e)) $(".upload-form .main-form").addClass("hidden"); 290 + }); 291 + // hide 292 + $(window).on("dragend dragleave", function (e) { 293 + if (window.uploadData) { 294 + $(".upload-form .main-form").removeClass("hidden"); 295 + hide(); 296 + } 297 + e = e.originalEvent; 298 + if (containsAFile(e)) { 299 + if (e.type == "dragleave" && e.relatedTarget == null) hide();else if (e.type != "dragleave") hide(); 300 + } 301 + }); 302 + // drop 303 + $(window).on("drop", function (e) { 304 + hide(); 305 + if (containsAFile(e)) { 306 + var files = e.originalEvent.dataTransfer.files; 307 + if (files[0].type == "image/png" || files[0].type == "image/jpeg") { 308 + handleFiles(files); 309 + } else {// wrong fileExt 310 + 311 + } 312 + } 313 + }); 314 + 315 + $("body").on("change", ".upload-form input#files", function (e) { 316 + var input = $(this); 317 + var files = input.prop("files"); 318 + handleFiles(files); 319 + }); 320 + 321 + // handle files 322 + function handleFiles(files) { 323 + window.uploadData = files; 324 + $(".select-file.container").addClass("hidden"); 325 + $(".upload-form .main-form").removeClass("hidden"); 326 + } 327 + }); 328 + 329 + // add tag when comma/enter 330 + $("body").on("keypress", ".upload-form input.add-tag", function (e) { 331 + if (e.which == 44) e.preventDefault(); // comma 332 + if (e.which == 44 || e.which == 13) { 333 + // comma || enter 334 + var $inputElement = $(this); 335 + var value = $(this).val(); 336 + $inputElement.val(""); // empty the input 337 + $("\n <div class=\"tag\">\n <div class=\"tag-text\">" + value + "</div>\n <button class=\"remove-tag\">x</div>\n </div>\n ").insertBefore($inputElement); 338 + } 339 + }); 340 + 341 + // remove tag button 342 + $("body").on("click", ".upload-form .remove-tag", function () { 343 + $(this).parent().remove(); 344 + }); 345 + 346 + // clicking the tags-box focuses the add-tag input element 347 + $("body").on("click", ".upload-form .tags-box", function (e) { 348 + if (e.target == e.currentTarget) { 349 + $(".upload-form input.add-tag").focus(); 350 + } 351 + }); 352 + 353 + function upload() { 354 + 355 + var data = new FormData(); 356 + data.append("image", uploadData[0], uploadData[0].name); 357 + data.append("title", $(".upload-form input.title").val()); 358 + data.append("description", $(".upload-form textarea.description").val()); 359 + 360 + var tagsArray = []; 361 + $(".upload-form .tags-box .tag").each(function (i, obj) { 362 + var tagText = $(obj).find(".tag-text").html(); 363 + tagsArray.push(tagText); 364 + }); 365 + data.append("tags", JSON.stringify(tagsArray)); 366 + 367 + console.log(data.get("image")); 368 + console.log(data.get("title")); 369 + console.log(data.get("description")); 370 + console.log(data.get("tags")); 371 + 372 + xhr(data, "/upload", { 373 + contentType: "none" 374 + }, function (res, err) { 375 + if (err) ; // http status code not 2xx 376 + console.log(res); 377 + if (res.errors.length == 0) { 378 + console.log("success!"); 379 + } 380 + }); 381 + } 382 + 383 + // upload button click 384 + $("body").on("click", ".upload-form button.upload", function () { 385 + upload(); 386 + }); 387 + }); 202 388 203 389 /***/ }) 204 390 /******/ ]);