diff options
Diffstat (limited to 'public/assets/javascripts/ui')
| -rw-r--r-- | public/assets/javascripts/ui/builder/BuilderSettings.js | 2 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/builder/BuilderView.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/Collaborators.js | 128 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorSettings.js | 25 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorToolbar.js | 5 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorView.js | 3 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/LightControl.js | 299 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaEditor.js | 11 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaUpload.js | 73 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaViewer.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/WallpaperPicker.js | 164 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/FormView.js | 12 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/ModalView.js | 9 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/UploadView.js | 90 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/site/SignUpModal.js | 1 |
15 files changed, 599 insertions, 225 deletions
diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index 0091454..796c398 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -29,6 +29,8 @@ var BuilderSettings = FormView.extend({ this.$id.val(data._id) this.$name.val(data.name) + this.parent.lightControl.loadDefaults() + data.rooms && Rooms.deserialize(data.rooms) data.startPosition && scene.camera.move(data.startPosition) data.privacy && this.$privacy.find("[value=" + data.privacy + "]").prop('checked', "checked") diff --git a/public/assets/javascripts/ui/builder/BuilderView.js b/public/assets/javascripts/ui/builder/BuilderView.js index 555cd58..a89111f 100644 --- a/public/assets/javascripts/ui/builder/BuilderView.js +++ b/public/assets/javascripts/ui/builder/BuilderView.js @@ -11,6 +11,7 @@ var BuilderView = View.extend({ this.info = new BuilderInfo ({ parent: this }) this.toolbar = new BuilderToolbar ({ parent: this }) this.settings = new BuilderSettings ({ parent: this }) + this.lightControl = new LightControl ({ parent: this }) }, load: function(name){ diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js new file mode 100644 index 0000000..452ad15 --- /dev/null +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -0,0 +1,128 @@ + +var Collaborators = ModalFormView.extend({ + el: ".mediaDrawer.collaborators", + + template: $("#collaborator-template").html(), + + indexAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/index" }, + createAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/create" }, + destroyAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/destroy" }, + + events: { + "keydown [name=email]": "enterSubmit", + "click [data-role=destroy-collaborator]": "destroy", + }, + + show: function(){ + this.action = this.createAction + this.$("#collaborator-url-rapper").hide() + + if (! this.loaded) { + this.load() + } + else { + this.__super__.show.call(this) + } + }, + + load: function(){ + $.get(this.indexAction(), this.populate.bind(this)) + }, + + populate: function(collaborators){ + this.loaded = true + collaborators.forEach(function(collab){ + var $el = $( this.template ) + $el.data("collaborator-id", collab._id) + + if (collab.user) { + $el.find(".email").remove() + + $el.find(".user") + .attr("href", "/profile/" + collab.user.username) + + $el.find(".avatar") + .css("background-image", "url(" + collab.user.photo + ")") + + $el.find(".username") + .html( collab.user.displayName ) + + if (collab.owner) { + $el.find("button").remove() + } + else { + $el.find(".role").remove() + } + } + else { + $el.find(".user").remove() + $el.find(".role").remove() + $el.find(".email").html( collab.email ) + } + + $("#collaborator-list").append($el) + }.bind(this)) + + this.__super__.show.call(this) + }, + + enterSubmit: function (e) { + e.stopPropagation() + var base = this + if (e.keyCode == 13) { + setTimeout(function(){ + base.save(e) + base.reset() + }, 100) + } + }, + + validate: function(){ + var errors = [] + + var email = this.$("[name=email]").val() + if (! email.length) { + errors.push("Please enter an email address"); + } + else if (email.indexOf("@") === -1) { + errors.push("Please enter a valid email address"); + } + + return errors + }, + + success: function(data){ + this.reset() + this.populate([data]) + // weird! this.$("#collaborator-url") not working here, but works without this + setTimeout(function(){ + $("#collaborator-url").val("http://vvalls.com/join/" + data.nonce) + }, 100) + this.$("#collaborator-dummy-email").html(data.email) + this.$("#collaborator-url-rapper").slideDown(300) + }, + + destroy: function(e){ + var base = this + var $el = $(e.currentTarget).closest("li") + + if ($el.find(".user").length) { + var name = $el.find(".username").html() + ConfirmModal.confirm("Are you sure you want to remove " + name + " from this project?", _destroy) + } + else { + _destroy() + } + + function _destroy () { + var _id = $el.data("collaborator-id") + $el.remove() + $.ajax({ + type: "DELETE", + url: base.destroyAction(), + data: { _id: _id, _csrf: $("[name=_csrf]").val() }, + }) + } + }, + +}) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index e9239e4..2a3929a 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -9,6 +9,7 @@ var EditorSettings = FormView.extend({ events: { "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', + "click [data-role='show-collaborators']": 'showCollaborators', "click [data-role='save-project']": 'save', "click [data-role='clone-project']": 'clone', "click [data-role='clear-project']": 'clear', @@ -28,15 +29,23 @@ var EditorSettings = FormView.extend({ load: function(data){ this.action = data.isNew ? this.createAction : this.updateAction - + this.parent.data = data + data.rooms && Rooms.deserialize(data.rooms) + data.walls && Walls.deserialize(data.walls) data.startPosition && scene.camera.move(data.startPosition) - + + if (data.colors && data.colors.wall) { + this.parent.lightControl.load(data.colors) + } + else { + this.parent.lightControl.loadDefaults() + } + if (data.isNew) { this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) } else { - // console.log(data) this.thumbnailIsStale() this.$id.val( data._id ) @@ -48,6 +57,11 @@ var EditorSettings = FormView.extend({ } }, + showCollaborators: function(e){ + e && e.preventDefault() + this.parent.collaborators.show() + }, + clone: function(){ var names = this.$name.val().split(" ") if ( ! isNaN(Number( names[names.length-1] )) ) { @@ -122,7 +136,8 @@ var EditorSettings = FormView.extend({ fd.append( "description", this.$description.val() ) fd.append( "privacy", this.$privacy.filter(":checked").val() == "private" ) fd.append( "rooms", JSON.stringify( Rooms.serialize() ) ) - fd.append( "walls", JSON.stringify( Rooms.serializeWalls() ) ) + fd.append( "walls", JSON.stringify( Walls.serialize() ) ) + fd.append( "colors", JSON.stringify( Walls.colors ) ) fd.append( "media", JSON.stringify( Scenery.serialize() ) ) fd.append( "startPosition", JSON.stringify( app.position(scene.camera) ) ) @@ -152,6 +167,8 @@ var EditorSettings = FormView.extend({ Minotaur.hide() window.history.pushState(null, document.title, "/project/" + data.slug + "/edit") + + this.parent.data = data }, }) diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 5e0da7e..c631317 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -56,6 +56,11 @@ var EditorToolbar = View.extend({ $(".inuse").removeClass("inuse") $("[data-role='resize-media']").toggleClass("inuse", state) if (state) { + if (this.parent.mediaEditor.scenery) { + Scenery.resize.show( this.parent.mediaEditor.scenery ) + } + } + else { Scenery.resize.hide() } }, diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 4067c4d..e11f189 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -16,6 +16,7 @@ var EditorView = View.extend({ this.mediaEditor = new MediaEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) this.lightControl = new LightControl ({ parent: this }) + this.collaborators = new Collaborators ({ parent: this }) }, load: function(name){ @@ -30,7 +31,7 @@ var EditorView = View.extend({ ready: function(data){ $("#map").hide() - + this.settings.load(data) }, diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index c3e80c2..bd09dc2 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -1,43 +1,272 @@ var LightControl = View.extend({ - el: ".lightcontrol", - - events: { - "mousedown": "stopPropagation", - }, + el: ".lightcontrol", + + events: { + "mousedown": "stopPropagation", + "click .swatch": "clickSwatch", + "click label": "clickLabel", + "input #shadow-control": "updateShadow", + "mousedown #brightness-control": "beginBrightness", + "input #brightness-control": "updateBrightness", + "input #outline-hue": "updateShadow", + "input #wall-hue": "updateShadow", + }, + + initialize: function(){ + this.colorPicker = new LabColorPicker(this, 180, 180) + this.$el.prepend( this.colorPicker.canvas ) + + this.$swatches = this.$(".swatch") + this.$labels = this.$(".swatch + label") + this.$swatch = { + wall: this.$("#wall-color"), + outline: this.$("#outline-color"), + floor: this.$("#floor-color"), + ceiling: this.$("#ceiling-color"), + } + this.$brightnessControl = this.$("#brightness-control") + }, - toggle: function(state){ + modes: [ "wall", "outline", "floor", "ceiling" ], + + load: function(data){ + this.modes.forEach(function(mode){ + Walls.setColor[mode](data[mode]) + this.$swatch[ mode ].css("background-color", rgb_string(data[mode])) + }.bind(this)) + this.setMode("wall") + }, + + loadDefaults: function(){ + var colors = { + wall: app.defaults.wallColor.slice(), + outline: app.defaults.outlineColor.slice(), + floor: app.defaults.floorColor.slice(), + ceiling: app.defaults.ceilingColor.slice(), + } + this.load(colors) + }, + + toggle: function(state){ this.$el.toggleClass("active", state); + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + pick: function(rgb, Lab){ + this.labColor = Lab + this.setSwatchColor(this.mode, rgb) + Walls.setColor[ this.mode ](rgb) + }, + + setSwatchColor: function(mode, rgb) { + this.$swatch[ mode ].css("background-color", rgb_string(rgb)) + }, + + initialState: null, + + begin: function(){ + this.initialState = this.serialize() + }, + + serialize: function(){ + return { + mode: this.mode, + rgb: Walls.colors[ this.mode ] + } + }, + + finalize: function(){ + if (! this.initialState) { return } + UndoStack.push({ + type: 'update-colors', + undo: this.initialState, + redo: this.serialize(), + }) + this.initialState = null + }, + + setMode: function (mode) { + var color, brightness + this.mode = mode + this.$swatches.removeClass("selected") + this.$labels.removeClass("selected") + this.$swatch[ mode ].addClass("selected") + color = Walls.colors[ mode ] + + this.$(".swatch.selected").next("label").addClass("selected") + this.labColor = this.colorPicker.load(color) + this.$brightnessControl.val( this.labColor[0] ) + }, + + clickLabel: function(e){ + $(e.currentTarget).prev(".swatch").trigger("click") + }, + clickSwatch: function(e){ + var mode = $(e.currentTarget).data('mode') + this.setMode(mode) + }, + + beginBrightness: function(){ + this.begin() + $(window).one("mouseup", this.finalize.bind(this)) + }, + + updateBrightness: function(){ + this.labColor[0] = parseFloat( this.$brightnessControl.val() ) + var rgb = this.colorPicker.setLab( this.labColor ) + this.pick(rgb, this.labColor) + }, - // toggle the class that makes the cursor a paintbucket - // $("body").removeClass("pastePaper"); - }, - show: function(){ - this.toggle(true) - }, - hide: function(){ - this.toggle(false) - }, +}) -/* - $("#shadow-control").on({ - mousedown: function(){ app.dragging = true }, - change: function(){ - var hex = (~~($(this).int() / 100 * 0xff)).toString(10) - if (hex.length == 1) hex = "0" + hex; - var color = "rgba(" + [hex, hex, hex, "1.0"] + ")" - $(".face").css("border-color", color) - } - }) +var LabColorPicker = function (parent, w, h) { + var base = this + var canvas = this.canvas = document.createElement('canvas') + var ctx = this.ctx = canvas.getContext('2d') + var imageData = ctx.createImageData(w,h) + var data = imageData.data - $("#brightness-control").on({ - mousedown: function(){ app.dragging = true }, - change: function(){ - var hex = (~~($(this).int() / 100 * 0xff)).toString(10) - var color = "rgba(" + [hex, hex, hex, "0.9"] + ")" - $("body,.face").css("background-color", color) - } - }) -*/ +// var cursor = this.cursor = document.createElement("div") +// cursor.className = "colorPickerCursor" -}) + canvas.width = w + canvas.height = h + canvas.className = "colorPicker" + + var ww = w-1 + var hh = h-1 + + var L_range = [0, 110] + var a_range = [-86.185, 98.254] + var b_range = [-107.863, 94.482] + + var rgb = [0,0,0] + + var val = 80 + + this.mouse = new mouse({ + el: canvas, + down: function(e, cursor){ + parent.begin() + cursor.x.a = -cursor.x.a + base.pick(cursor.x.a, cursor.y.a) + }, + drag: function(e, cursor){ + cursor.x.b = -cursor.x.b + base.pick(cursor.x.b, cursor.y.b) + }, + up: function(){ + parent.finalize() + } + }) + + this.setLab = function(Lab) { + val = Lab[0] + this.paint() + var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round) + return rgb + } + this.pick = function(i, j){ + var x = mix( i/ww, a_range[0], a_range[1] ) + var y = mix( j/hh, b_range[0], b_range[1] ) + var rgb = xyz2rgb(hunterlab2xyz(val, x, y)).map(Math.round) + parent.pick( rgb, [val,x,y] ) + } + this.load = function(rgba){ + var Lab = xyz2hunterlab(rgb2xyz(rgba)) + var val = clamp( Lab[0], L_range[0], L_range[1] ) + var x = mix( norm(Lab[1], a_range[0], a_range[1]), 0, ww ) + var y = mix( norm(Lab[2], b_range[0], b_range[1]), 0, hh ) + // move the cursor + this.setLab(Lab) + return Lab + } + this.paint = function() { + val = clamp(val, L_range[0], L_range[1]) + var x, y, t + for (var i = 0; i < w; i++) { + for (var j = 0; j < h; j++) { + x = mix( i/ww, a_range[0], a_range[1] ) + y = mix( j/hh, b_range[0], b_range[1] ) + t = (j*w + i) * 4 + rgb = xyz2rgb(hunterlab2xyz(val, x, y)) + data[t] = Math.round( rgb[0] ) + data[t+1] = Math.round( rgb[1] ) + data[t+2] = Math.round( rgb[2] ) + data[t+3] = 255 + } + } + ctx.putImageData(imageData,0,0) + } + + function hunterlab2xyz (L,a,b) { + var_Y = L / 10 + var_X = a / 17.5 * L / 10 + var_Z = b / 7 * L / 10 + + Y = Math.pow(var_Y, 2) + X = ( var_X + Y ) / 1.02 + Z = -( var_Z - Y ) / 0.847 + xyz = [X,Y,Z] + } + function xyz2rgb(){ + var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) + var var_Y = xyz[1] / 100 //Y from 0 to 100.000 + var var_Z = xyz[2] / 100 //Z from 0 to 108.883 + + var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986 + var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415 + var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570 + + if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + rgb[0] = clamp(var_R * 255, 0, 255) + rgb[1] = clamp(var_G * 255, 0, 255) + rgb[2] = clamp(var_B * 255, 0, 255) + return rgb + } + function rgb2xyz(RGB){ + var var_R = ( RGB[0] / 255 ) // R from 0 to 255 + var var_G = ( RGB[1] / 255 ) // G from 0 to 255 + var var_B = ( RGB[2] / 255 ) // B from 0 to 255 + + if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4 + else var_R = var_R / 12.92 + if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4 + else var_G = var_G / 12.92 + if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4 + else var_B = var_B / 12.92 + + var_R = var_R * 100 + var_G = var_G * 100 + var_B = var_B * 100 + + //Observer. = 2°, Illuminant = D65 + var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 + var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 + var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 + return [x,y,z] + } + function xyz2hunterlab (XYZ) { + var X = XYZ[0] + var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) + var Z = XYZ[2] + var L = 10 * sqrt( Y ) + var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) + var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) + return [L,a,b] + } +} diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index cc924da..750cf41 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -116,17 +116,18 @@ var MediaEditor = FormView.extend({ }, setDimensions: function(){ - this.$width.unitVal( Number(this.scenery.dimensions.a * this.scenery.scale) || "" ) - this.$height.unitVal( Number(this.scenery.dimensions.b * this.scenery.scale) || "" ) + if (! this.scenery) return + this.$width.unitVal( Number(this.scenery.naturalDimensions.a * this.scenery.scale) || "" ) + this.$height.unitVal( Number(this.scenery.naturalDimensions.b * this.scenery.scale) || "" ) }, changeWidth: function(e){ e.stopPropagation() - this.scenery.set_scale( this.$width.unitVal() / this.scenery.dimensions.a ) + this.scenery.set_scale( this.$width.unitVal() / this.scenery.naturalDimensions.a ) this.setDimensions() }, changeHeight: function(e){ e.stopPropagation() - this.scenery.set_scale( this.$height.unitVal() / this.scenery.dimensions.b ) + this.scenery.set_scale( this.$height.unitVal() / this.scenery.naturalDimensions.b ) this.setDimensions() }, changeUnits: function(){ @@ -137,11 +138,13 @@ var MediaEditor = FormView.extend({ bind: function(scenery){ this.scenery = scenery this.scenery.mx.bound = true + this.scenery.mx.el.classList.add("picked") }, unbind: function(){ if (this.scenery && this.scenery.mx) { this.scenery.mx.bound = false + this.scenery.mx.el.classList.remove("picked") } this.scenery = null }, diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js index 86bf767..92cf2bd 100644 --- a/public/assets/javascripts/ui/editor/MediaUpload.js +++ b/public/assets/javascripts/ui/editor/MediaUpload.js @@ -1,5 +1,5 @@ -var MediaUpload = View.extend({ +var MediaUpload = UploadView.extend({ el: ".fileUpload", createAction: "/api/media/new", @@ -7,16 +7,12 @@ var MediaUpload = View.extend({ events: { "keydown .url": "enterSubmit", - "change .file": "handleFileSelect", - "submit form": "preventDefault", }, initialize: function(opt){ + this.__super__.initialize.call(this) this.parent = opt.parent - this.$csrf = this.$("[name=_csrf]") this.$url = this.$(".url") - this.$file = this.$(".file") - this.$upload = this.$(".upload-icon") }, show: function(){ @@ -45,7 +41,7 @@ var MediaUpload = View.extend({ return } - media._csrf = this.$csrf.val() + media._csrf = $("[name=_csrf]").val() console.log(media) var request = $.ajax({ @@ -57,68 +53,13 @@ var MediaUpload = View.extend({ }.bind(this)) }, - handleFileSelect: function(e) { - e.stopPropagation(); - e.preventDefault(); - - this.parent.mediaViewer.deleteArmed(false) - - var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; - - for (var i = 0, f; f = files[i]; i++) { - if ( ! f.type.match('image.*')) { - continue; - } - - this.getImageDimensions(f) - } - }, - - getImageDimensions: function(f){ - var base = this - - this.$upload.addClass('uploading') - - var reader = new FileReader(); - - reader.onload = function(e) { - var image = new Image() - image.onload = function(){ - var width = image.naturalWidth, - height = image.naturalHeight - base.upload(f, width, height) - } - image.src = e.target.result - } - - reader.readAsDataURL(f); - }, - - upload: function(f, width, height){ - var fd = new FormData() - fd.append('image', f) - fd.append('width', width) - fd.append('height', height) - fd.append('_csrf', this.$csrf.val()) - - var request = $.ajax({ - url: this.uploadAction, - type: "post", - data: fd, - dataType: "json", - processData: false, - contentType: false, - }) - request.done(this.add.bind(this)) - }, - add: function(media){ console.log(media) - if (media.error) { - return - } - this.$upload.removeClass('uploading') this.parent.mediaViewer.add(media) + }, + + beforeUpload: function(){ + this.parent.mediaViewer.deleteArmed(false) } }) diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 40bfe80..7cfa863 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -2,6 +2,7 @@ var MediaViewer = ModalView.extend({ el: ".mediaDrawer.mediaViewer", destroyAction: "/api/media/destroy", + usesFileUpload: true, events: { 'click .foundToggle': "foundToggle", diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index 9ee441b..61ecb78 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -1,40 +1,70 @@ -var WallpaperPicker = View.extend({ +var WallpaperPicker = UploadView.extend({ el: ".wallpaper", + mediaTag: "wallpaper", + uploadAction: "/api/media/upload", + events: { "click .swatch": 'pick', - }, + }, initialize: function(){ - var wm = new WallpaperManager() - app.on('wallpaper-ready', function(){ - var black = [0,0,0,1.0] - var white = [255,255,255,1.0] - var swatches = wm.buildSwatches(black, white, 2) - swatches.forEach(function(swatch){ - var dataUrl = swatch.toDataURL() - var span = document.createElement('span') - span.style.backgroundImage = "url(" + dataUrl + ")" - span.className = "swatch" - this.$el.append(span) - }.bind(this)) - }.bind(this)) - wm.init() + this.__super__.initialize.call(this) + this.$swatches = this.$(".swatches") + }, + + loaded: false, + show: function(){ + if (! this.loaded) { + this.load() + } + else { + this.toggle(true) + } + }, + + hide: function(){ + this.__super__.hide.call(this) }, - toggle: function(state){ - this.$el.toggleClass("active", state); - // toggle the class that makes the cursor a paintbucket - // $("body").removeClass("pastePaper"); + load: function(){ + $.get("/api/media/user", { tag: this.mediaTag }, this.populate.bind(this)) }, - show: function(){ - this.toggle(true) + + populate: function(data){ + console.log(data) + this.loaded = true + data && data.forEach(this.add.bind(this)) + this.toggle(true) + }, + + add: function (media) { + if (media.type !== "image") { return } + var swatch = document.createElement("div") + swatch.className = "swatch" + swatch.style.backgroundImage = "url(" + media.url + ")" + this.$swatches.append(swatch) + }, + + toggle: function (state) { + if (state && ! this.loaded) { + this.show() + } + else { + this.$el.toggleClass("active", state) + } + // toggle the class that makes the cursor a paintbucket + // $("body").removeClass("pastePaper") }, + hide: function(){ this.toggle(false) }, + beforeUpload: function(){ + }, + pick: function(e){ var $swatch = $(e.currentTarget) var $floatingSwatch = $(".floatingSwatch") @@ -58,94 +88,6 @@ var WallpaperPicker = View.extend({ $floatingSwatch.show() _followCursor(e); }) - } + }, }) - -// pattern -// scale -// foreground -// background - -var WallpaperManager = function () { - - var image = new Image () - var imageData - var w, h - - this.masks = [] - - this.init = function(){ - this.load() - } - - this.load = function(){ - image.onload = function(){ - this.loadImageData() - this.buildMasks() - app.tube('wallpaper-ready') - }.bind(this) - - image.src = "/assets/img/palette.gif" - } - - this.loadImageData = function(){ - var canvas = document.createElement('canvas') - var ctx = canvas.getContext('2d') - w = canvas.width = image.naturalWidth - h = canvas.height = image.naturalHeight - ctx.drawImage(image, 0,0) - imageData = ctx.getImageData(0,0,image.naturalWidth,image.naturalHeight).data - } - - this.buildMasks = function(){ - var mask - for (var y = 0; y < 6; y++) { - for (var x = 0; x < 16; x++) { - mask = this.buildMask(x,y) - this.masks.push(mask) - } - } - } - - this.buildMask = function(x,y){ - // add the offset of the top-left swatch - x = (x * 18) + 15 - y = (y * 16) + 5 - - var mask = new Array(64) - var t = 0 - for (var i = 0; i < 8; i++) { - for (var j = 0; j < 8; j++) { - t = ( w*(y+j) + x+i ) * 4 - mask[j*8+i] = imageData[t] === 0 - } - } - return mask - } - - this.buildSwatches = function(black, white, scale) { - var swatches = this.masks.map(function(mask){ - return this.buildSwatch(mask,black,white,scale) - }.bind(this)) - - return swatches - } - - this.buildSwatch = function(mask,black,white,scale){ - black = 'rgba(' + black.join(',') + ')' - white = 'rgba(' + white.join(',') + ')' - var canvas = document.createElement("canvas") - canvas.width = 8*scale - canvas.height = 8*scale - var ctx = canvas.getContext('2d') - for (var i = 0; i < 8; i++) { - for (var j = 0; j < 8; j++) { - ctx.fillStyle = mask[j*8+i] ? black : white - ctx.fillRect(i*scale, j*scale, scale, scale) - } - } - return canvas - } - -}
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index ab33bc0..17b748a 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -33,7 +33,7 @@ var FormView = View.extend({ }, serialize: function(){ - var fd = new FormData() + var fd = new FormData(), hasCSRF = false this.$("input[name], select[name], textarea[name]").each( function(){ if (this.type == "file") { @@ -48,9 +48,14 @@ var FormView = View.extend({ } else { fd.append(this.name, this.value); + hasCSRF = hasCSRF || this.name == "_csrf" } }); + if (! hasCSRF) { + fd.append("_csrf", $("[name=_csrf]").val()) + } + return fd }, @@ -71,9 +76,12 @@ var FormView = View.extend({ return } } + + var action = typeof this.action == "function" ? this.action() : this.action + if (! action) return var request = $.ajax({ - url: this.action, + url: action, type: this.method, data: this.serialize(), dataType: "json", diff --git a/public/assets/javascripts/ui/lib/ModalView.js b/public/assets/javascripts/ui/lib/ModalView.js index 937c1e9..d9b518a 100644 --- a/public/assets/javascripts/ui/lib/ModalView.js +++ b/public/assets/javascripts/ui/lib/ModalView.js @@ -10,9 +10,15 @@ var ModalView = View.extend({ } }, + usesFileUpload: false, + show: function(){ $(".mediaDrawer").removeClass("active") - $(".fileUpload").removeClass("active") + + if (! this.usesFileUpload) { + $(".fileUpload").removeClass("active") + } + this.$el.addClass("active") $("body").addClass("noOverflow") }, @@ -32,4 +38,5 @@ var ModalView = View.extend({ this.hide() } } + }) diff --git a/public/assets/javascripts/ui/lib/UploadView.js b/public/assets/javascripts/ui/lib/UploadView.js new file mode 100644 index 0000000..efaa8c9 --- /dev/null +++ b/public/assets/javascripts/ui/lib/UploadView.js @@ -0,0 +1,90 @@ + +var UploadView = View.extend({ + + // define uploadAction + + events: { + "change .file": "handleFileSelect", + "submit form": "preventDefault", + }, + + initialize: function(){ + this.$file = this.$(".file") + this.$upload = this.$(".upload-icon") + }, + + beforeUpload: function(){ + }, + + handleFileSelect: function(e) { + e.stopPropagation(); + e.preventDefault(); + + this.beforeUpload() + + var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; + + for (var i = 0, f; f = files[i]; i++) { + if ( ! f.type.match('image.*')) { + continue; + } + + this.getImageDimensions(f) + } + }, + + getImageDimensions: function(f){ + var base = this + + this.$upload.addClass('uploading') + + var reader = new FileReader(); + + reader.onload = function(e) { + var image = new Image() + image.onload = function(){ + var width = image.naturalWidth, + height = image.naturalHeight + base.upload(f, width, height) + } + image.src = e.target.result + } + + reader.readAsDataURL(f); + }, + + upload: function(f, width, height){ + var fd = new FormData() + fd.append('image', f) + fd.append('width', width) + fd.append('height', height) + fd.append('_csrf', $("[name=_csrf]").val()) + + if (this.mediaTag) { + fd.append('tag', this.mediaTag) + } + + var request = $.ajax({ + url: this.uploadAction, + type: "post", + data: fd, + dataType: "json", + processData: false, + contentType: false, + }) + request.done(this.success.bind(this)) + }, + + success: function(media){ + if (media.error) { + return + } + this.$upload.removeClass('uploading') + this.add(media) + }, + + add: function(media){ + console.log(media) + }, + +}) diff --git a/public/assets/javascripts/ui/site/SignUpModal.js b/public/assets/javascripts/ui/site/SignUpModal.js index 5c651ee..a452023 100644 --- a/public/assets/javascripts/ui/site/SignUpModal.js +++ b/public/assets/javascripts/ui/site/SignUpModal.js @@ -34,4 +34,3 @@ var SignUpModal = ModalFormView.extend({ } }) - |
