From 099dfd16940c62e931bf01e7f62b7a45f2b8c654 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 13:12:27 -0400 Subject: collaborators api --- views/controls/editor/collaborators.ejs | 21 +++++++++++++++++++++ views/mail/collaborator.html.ejs | 20 ++++++++++++++++++++ views/mail/collaborator.text.ejs | 7 +++++++ views/mail/welcome.text.ejs | 2 +- 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 views/controls/editor/collaborators.ejs create mode 100644 views/mail/collaborator.html.ejs create mode 100644 views/mail/collaborator.text.ejs (limited to 'views') diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs new file mode 100644 index 0000000..448b6d4 --- /dev/null +++ b/views/controls/editor/collaborators.ejs @@ -0,0 +1,21 @@ +
+ X + + + +
+ To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet. +
+ +
+ + +
+ +
diff --git a/views/mail/collaborator.html.ejs b/views/mail/collaborator.html.ejs new file mode 100644 index 0000000..5621c1e --- /dev/null +++ b/views/mail/collaborator.html.ejs @@ -0,0 +1,20 @@ + + + +

+ +

+ +

+ [[- username ]] has invited you to join the project + [[- projectName ]] on Vvalls. +

+ +

+ Accept the invitation below: +

+ +Join Project + + + diff --git a/views/mail/collaborator.text.ejs b/views/mail/collaborator.text.ejs new file mode 100644 index 0000000..52d39b6 --- /dev/null +++ b/views/mail/collaborator.text.ejs @@ -0,0 +1,7 @@ + +[[- username ]] has invited you to join the project [[- projectName ]] on Vvalls. + +Accept the invitation below: + +http://vvalls.com/join/[[- nonce ]] + diff --git a/views/mail/welcome.text.ejs b/views/mail/welcome.text.ejs index cab9c15..02b449b 100644 --- a/views/mail/welcome.text.ejs +++ b/views/mail/welcome.text.ejs @@ -1,4 +1,4 @@ Welcome to Vvalls, [[- username ]] -http://www.posthang.com +http://www.vvalls.com -- cgit v1.2.3-70-g09d2 From 124a698130f39992a1b47dcc8f32ef30c61a00eb Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 14:24:45 -0400 Subject: stub in collaborator ui --- .../assets/javascripts/ui/editor/Collaborators.js | 64 ++++++++++++++++++++++ public/assets/javascripts/ui/editor/EditorView.js | 1 + public/assets/stylesheets/app.css | 6 ++ server/index.js | 4 +- server/lib/api/collaborator.js | 4 +- server/lib/views.js | 2 + views/controls/editor/collaborators.ejs | 24 +++++--- views/controls/reader/about-room.ejs | 7 ++- views/partials/scripts.ejs | 1 + 9 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 public/assets/javascripts/ui/editor/Collaborators.js (limited to 'views') diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js new file mode 100644 index 0000000..bb163f8 --- /dev/null +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -0,0 +1,64 @@ + +var Collaborators = ModalFormView.extend({ + el: ".mediaDrawer.collaborators", + + template: $("#collaborator-template").html(), + + createAction: "/api/collaborator/:slug/create", + destroyAction: "/api/collaborator/:slug/destroy", + + events: { + "click [data-role=destroy-collaborator]": "destroy", + }, + + show: function(){ + if (! this.loaded) { + this.load() + } + else { + this.__super__.show.call(this) + } + }, + + load: function(){ + $.get("/api/collaborator/:slug/index", this.populate.bind(this)) + }, + + populate: function(collaborators){ + // + 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.username) + + $el.find(".avatar") + .css("background-image", "url(" + collab.photo + ")") + + $el.find(".username") + .html( collab.displayName ) + } + else { + $el.remove(".user") + $el.find(".email").html( collab.email ) + } + + $("#collaborators").append($el) + }.bind(this)) + + this.__super__.show.call(this) + }, + + success: function(data){ + this.populate([data]) + }, + + destroy: function(e){ + var _id = $(e.currentTarget).closest("li").data("collaborator-id") + }, + +}) diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 4067c4d..5fc5147 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){ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3b00cd2..92eed33 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1615,6 +1615,12 @@ form li textarea { text-decoration:underline; } +.aboutRoom .editlink { + color: red; + text-decoration: none; + border-bottom: 1px dotted; +} + .aboutRoom h2{ font-size: 13px; margin: 5px 0; diff --git a/server/index.js b/server/index.js index 212db01..e946788 100644 --- a/server/index.js +++ b/server/index.js @@ -125,8 +125,8 @@ site.route = function () { app.get('/project', middleware.ensureAuthenticated, views.modal) app.get('/project/new', middleware.ensureAuthenticated, views.modal) app.get('/project/new/:layout', middleware.ensureAuthenticated, views.editor_new) - app.get('/project/:slug', middleware.ensureProject, views.reader) - app.get('/project/:slug/view', middleware.ensureProject, views.reader) + app.get('/project/:slug', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) + app.get('/project/:slug/view', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) app.get('/project/:slug/edit', middleware.ensureProject, middleware.ensureIsCollaborator, views.editor) app.get('/api/layout', middleware.ensureAuthenticated, api.layouts.index) diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index 4b55f09..f39022f 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -54,9 +54,9 @@ var collaborator = { return res.json({ error: "can't find project" }) } var data = util.cleanQuery(req.body) - delete data.user_id - + data.email = util.sanitize( data.email ) data.project_id = req.project._id + delete data.user_id Collaborator.makeNonce(function(nonce){ data.nonce = nonce diff --git a/server/lib/views.js b/server/lib/views.js index 4faf80f..7137041 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -57,6 +57,8 @@ views.reader = function (req, res) { date: moment(req.project.updated_at).format("M/DD/YYYY"), author: user.displayName, authorlink: "/profile/" + user.username, + canEdit: req.isOwner || req.isCollaborator, + editlink: "/project/" + req.project.slug + "/edit", noui: !! (req.query.noui === '1'), }) }) diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 448b6d4..035507b 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -1,14 +1,6 @@ -
+
X -
    -
  • -
    - - -
  • -
-
To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet.
@@ -18,4 +10,18 @@ +
    +
+
+ + diff --git a/views/controls/reader/about-room.ejs b/views/controls/reader/about-room.ejs index f990da8..2aa244b 100644 --- a/views/controls/reader/about-room.ejs +++ b/views/controls/reader/about-room.ejs @@ -3,7 +3,12 @@ [[- name ]],
[[- author ]] -

Last modified [[- date ]]

+

+ Last modified [[- date ]] + [[ if (canEdit) { ]] + · Edit + [[ } ]] +

[[- description ]]
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 6d85699..ae5b31f 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -91,6 +91,7 @@ + -- cgit v1.2.3-70-g09d2 From 9257818363269a2893c1a7ee61adb497f749e38f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 18:15:40 -0400 Subject: collab stuff 90% there --- public/assets/img/logo.svg | 49 ++++++++++ .../assets/javascripts/ui/editor/Collaborators.js | 54 ++++++++--- .../assets/javascripts/ui/editor/EditorSettings.js | 12 ++- public/assets/javascripts/ui/editor/EditorView.js | 3 +- public/assets/javascripts/ui/lib/FormView.js | 12 ++- public/assets/stylesheets/app.css | 107 ++++++++++++++++++--- server/lib/api/collaborator.js | 20 ++-- server/lib/auth/mail.js | 2 +- server/lib/schemas/Collaborator.js | 1 + server/lib/views.js | 2 +- views/controls/editor/collaborators.ejs | 29 +++--- views/controls/editor/settings.ejs | 8 +- views/editor.ejs | 1 + views/mail/collaborator.html.ejs | 2 +- views/mail/welcome.html.ejs | 2 +- 15 files changed, 247 insertions(+), 57 deletions(-) create mode 100644 public/assets/img/logo.svg (limited to 'views') diff --git a/public/assets/img/logo.svg b/public/assets/img/logo.svg new file mode 100644 index 0000000..72b904a --- /dev/null +++ b/public/assets/img/logo.svg @@ -0,0 +1,49 @@ + + + +]> + + + + + + + + + + diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js index bb163f8..c27dbe0 100644 --- a/public/assets/javascripts/ui/editor/Collaborators.js +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -4,14 +4,18 @@ var Collaborators = ModalFormView.extend({ template: $("#collaborator-template").html(), - createAction: "/api/collaborator/:slug/create", - destroyAction: "/api/collaborator/:slug/destroy", + 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 + if (! this.loaded) { this.load() } @@ -21,44 +25,70 @@ var Collaborators = ModalFormView.extend({ }, load: function(){ - $.get("/api/collaborator/:slug/index", this.populate.bind(this)) + $.get(this.indexAction(), this.populate.bind(this)) }, populate: function(collaborators){ - // collaborators.forEach(function(collab){ var $el = $( this.template ) - $el.data("collaborator-id", collab.id) - + $el.data("collaborator-id", collab._id) + if (collab.user) { $el.find(".email").remove() $el.find(".user") - .attr("href", "/profile/" + collab.username) + .attr("href", "/profile/" + collab.user.username) $el.find(".avatar") - .css("background-image", "url(" + collab.photo + ")") + .css("background-image", "url(" + collab.user.photo + ")") $el.find(".username") - .html( collab.displayName ) + .html( collab.user.displayName ) + + if (collab.owner) { + $el.find("button").remove() + } + else { + $el.find(".role").remove() + } } else { - $el.remove(".user") + $el.find(".user").remove() + $el.find(".role").remove() $el.find(".email").html( collab.email ) } - $("#collaborators").append($el) + $("#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) + } + }, + success: function(data){ + this.reset() this.populate([data]) }, destroy: function(e){ - var _id = $(e.currentTarget).closest("li").data("collaborator-id") + var $el = $(e.currentTarget).closest("li") + var _id = $el.data("collaborator-id") + $el.remove() + $.ajax({ + type: "DELETE", + url: this.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..e5dd844 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,7 +29,8 @@ 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.startPosition && scene.camera.move(data.startPosition) @@ -36,7 +38,6 @@ var EditorSettings = FormView.extend({ this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) } else { - // console.log(data) this.thumbnailIsStale() this.$id.val( data._id ) @@ -48,6 +49,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] )) ) { @@ -152,6 +158,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/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 5fc5147..b75a912 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -31,8 +31,9 @@ var EditorView = View.extend({ ready: function(data){ $("#map").hide() - + this.settings.load(data) + this.collaborators.show() }, readyLayout: function(data){ 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/stylesheets/app.css b/public/assets/stylesheets/app.css index 92eed33..f59635b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1202,13 +1202,13 @@ input[type="range"]::-webkit-slider-thumb { transform: translateY(0px); } -#startpoint { +.modalLink { text-decoration: none; } - -#startpoint:hover { +.modalLink:hover { text-decoration: underline; } + @-webkit-keyframes fade { 50% { opacity:0.6; @@ -1270,7 +1270,7 @@ input[type="range"]::-webkit-slider-thumb { width: 100%; margin-top: 10px; } -.settings .subButtons a{ +.settings .subButtons a { font-size: 12px; font-weight: 300; width: 40px; @@ -1553,12 +1553,15 @@ form li textarea { position: fixed; right: 20px; top: 20px; + z-index: 20; } .close:hover { color:lightgreen; } + + .facebook { width: 100%; display: inline-block; @@ -1652,26 +1655,100 @@ form li textarea { .share a:hover{ text-decoration:underline; } -@-webkit-keyframes borderanimation -{ + +/* COLLABORATORS */ + +.collaborators > div { + width: 600px; + margin: 0 auto; + text-align: left; + background: white; + padding: 10px; + margin: 20px auto; +} +.collaborators button { + width: auto; + position: relative; + top: -2px; +} +.collaborators form { + max-width: none; +} +.collaborators form input[type=submit] { + float: none; + width: 150px; + position: relative; + top: -2px; + font-size: 11px; + + padding: 8px; + border: 1px solid; + font-weight: 500; + background: white; + cursor: pointer; +} +.collaborators form input[type=submit]:hover { + background-color: black; + border-color: black; +} +.collaborators p { + margin: 20px 0; +} +.collaborators form input[type=text] { + font-size: 16px; + width: 300px; +} +.collaborators h2 { + margin: 20px auto 10px; +} +#collaborator-list { + margin-top: 20px; +} +#collaborator-list li { + list-style-type: none; + background: #fff; + padding-top: 4px; +} +#collaborator-list .avatar { + width: 32px; + height: 32px; + background-size: cover; + display: inline-block; + margin-right: 10px; +} +#collaborator-list .username { + position: relative; + top: -10px; +} +#collaborator-list .role { + float: right; + font-style: italic; + margin-top: 5px; + font-weight: 300; +} +#collaborator-list .email { + line-height: 31px; + position: relative; + left: 42px; + font-weight: 300; + font-style: italic; +} + +/* MARCHING ANTS ANIMATION */ + +@-webkit-keyframes borderanimation { 0%{width:600px;} 100%{width:750px;left:2px;} } - -@-webkit-keyframes borderanimationleftright -{ +@-webkit-keyframes borderanimationleftright { 0%{height:250px;} 100%{height:500px;top:2px;} } - -@keyframes borderanimation -{ +@keyframes borderanimation { 0%{width:500px;} 100%{width:750px;left:2px;} } - -@keyframes borderanimationleftright -{ +@keyframes borderanimationleftright { 0%{height:250px;} 100%{height:500px;top:2px;} } diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index f39022f..c080070 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -1,20 +1,22 @@ /* jshint node: true */ var _ = require('lodash'), + auth = require('../auth'), util = require('../util'), upload = require('../upload'), config = require('../../../config.json'), + User = require('../schemas/User'), Collaborator = require('../schemas/Collaborator'), Project = require('../schemas/Project'); var collaborator = { join: function(req, res){ - var nonce = req.query.nonce + var nonce = req.params.nonce if (! nonce || ! nonce.length) { return res.json({ error: "invalid invite code" }) } Collaborator.findOne({ nonce: nonce }, function(err, collaborator){ if (err || ! collaborator) { return res.json({ error: "can't find collaborator" }) } - collaborator.user_id = req.user.user_id + collaborator.user_id = req.user._id collaborator.nonce = "" collaborator.save(function(err, collaborator){ Project.findOne({ _id: collaborator.project_id }, function(err, project){ @@ -31,7 +33,7 @@ var collaborator = { if (! req.project) { return res.json({ error: "can't find project" }) } - if (req.project.user_id !== req.user._id) { return res.json({ error: "insufficient permission" }) } + if (String(req.project.user_id) !== String(req.user._id)) { return res.json({ error: "insufficient permission" }) } Collaborator.find({ project_id: req.project._id }, function(err, collaborators){ var user_ids = _.pluck(collaborators, "user_id").filter(function(id){ return !! id }) User.find({ _id: user_ids }, "username displayName photo", function(err, users){ @@ -44,6 +46,7 @@ var collaborator = { obj.user = userIndex[ obj.user_id ] return obj }) + collaborators.unshift( { user: req.user.toObject(), owner: true } ) res.json(collaborators) }) }) @@ -60,11 +63,12 @@ var collaborator = { Collaborator.makeNonce(function(nonce){ data.nonce = nonce + new Collaborator(data).save(function(err, collaborator){ if (err || ! collaborator) { return res.json({ error: err }) } - auth.mail.forgotPassword(req.project, req.user, collaborator, function(){ - res.json(collaborator) - }) + console.log(collaborator) + res.json(collaborator) + auth.mail.collaborator(req.project, req.user, collaborator, function(){}) }) }) }, @@ -73,10 +77,10 @@ var collaborator = { if (! req.project) { return res.json({ error: "can't find project" }) } - if (req.project.user_id !== req.user._id) { + if (String(req.project.user_id) !== String(req.user._id)) { return res.json({ error: "insufficient permission" }) } - Collaborator.remove({ _id: _id }, function(err){ + Collaborator.remove({ _id: req.body._id }, function(err){ res.json({ status: "OK" }) }) } diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js index 0211325..0ba6d5d 100644 --- a/server/lib/auth/mail.js +++ b/server/lib/auth/mail.js @@ -81,7 +81,7 @@ var mail = { ] } mail.send(message, cb) - console.log("sent collaborator email to", user.email) + console.log("sent collaborator email to", collaborator.email) }, } diff --git a/server/lib/schemas/Collaborator.js b/server/lib/schemas/Collaborator.js index 79e3287..6b3d452 100644 --- a/server/lib/schemas/Collaborator.js +++ b/server/lib/schemas/Collaborator.js @@ -2,6 +2,7 @@ var mongoose = require('mongoose'), _ = require('lodash'), + crypto = require('crypto'), config = require('../../../config.json'), util = require('../util'); diff --git a/server/lib/views.js b/server/lib/views.js index 7137041..b3c1d18 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -33,7 +33,7 @@ views.editor = function (req, res) { if (! req.project) { res.redirect('/') } - else if (req.isCollaborator || req.isOwner) { + else if (req.isOwner || req.isCollaborator) { res.render('editor') } else { diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 035507b..1386a5c 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -1,27 +1,32 @@
X - +
- To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet. -
+

Collaborators

+ +

+ To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet. +

-
- - -
- -
    -
+
+ + +
+ +
    +
+ +
diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index 6f46be3..e4ec7ee 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -3,11 +3,17 @@ +
diff --git a/views/editor.ejs b/views/editor.ejs index 5d1e052..9950878 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -17,6 +17,7 @@ [[ include controls/editor/media-editor ]] [[ include controls/editor/wallpaper ]] [[ include controls/editor/light-control ]] + [[ include controls/editor/collaborators ]] [[ include controls/editor/settings ]]
diff --git a/views/mail/collaborator.html.ejs b/views/mail/collaborator.html.ejs index 5621c1e..2a08a1c 100644 --- a/views/mail/collaborator.html.ejs +++ b/views/mail/collaborator.html.ejs @@ -2,7 +2,7 @@

- +

diff --git a/views/mail/welcome.html.ejs b/views/mail/welcome.html.ejs index 8b7194b..b2c329f 100644 --- a/views/mail/welcome.html.ejs +++ b/views/mail/welcome.html.ejs @@ -2,7 +2,7 @@

- +

-- cgit v1.2.3-70-g09d2 From 5f5fcfee56a4f7067c1b9ccf51e662463b71e7f1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 18:32:45 -0400 Subject: showing the collab url --- .../assets/javascripts/ui/editor/Collaborators.js | 21 +++++++++++++++- public/assets/javascripts/ui/site/SignUpModal.js | 1 - server/lib/api/collaborator.js | 2 +- views/controls/editor/collaborators.ejs | 29 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js index c27dbe0..eee412a 100644 --- a/public/assets/javascripts/ui/editor/Collaborators.js +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -29,6 +29,7 @@ var Collaborators = ModalFormView.extend({ }, populate: function(collaborators){ + this.loaded = true collaborators.forEach(function(collab){ var $el = $( this.template ) $el.data("collaborator-id", collab._id) @@ -74,12 +75,30 @@ var Collaborators = ModalFormView.extend({ }, 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 + $("#collaborator-url").val("http://vvalls.com/join/" + data.nonce) + this.$("#collaborator-dummy-email").html(data.email) + this.$("#collaborator-url-rapper").slideDown(300) }, - + destroy: function(e){ var $el = $(e.currentTarget).closest("li") var _id = $el.data("collaborator-id") 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({ } }) - diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index c080070..1fda01b 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -57,7 +57,7 @@ var collaborator = { return res.json({ error: "can't find project" }) } var data = util.cleanQuery(req.body) - data.email = util.sanitize( data.email ) + data.email = util.trim( util.sanitize( data.email ) ) data.project_id = req.project._id delete data.user_id diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 1386a5c..69e5b64 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -13,6 +13,12 @@ +

+ We've sent a link to join this project to . + You can also send this link yourself: + +
+
@@ -30,3 +36,26 @@ owner + + -- cgit v1.2.3-70-g09d2 From 9bd30008c165fdb561f574dd2f83c35e609c96b1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 26 Aug 2014 12:30:06 -0400 Subject: editor pick styles --- public/assets/javascripts/rectangles/engine/scenery/resize.js | 1 + public/assets/javascripts/ui/editor/EditorToolbar.js | 5 +++++ public/assets/javascripts/ui/editor/EditorView.js | 1 - public/assets/javascripts/ui/editor/MediaEditor.js | 2 ++ public/assets/stylesheets/app.css | 7 +++++++ views/reader.ejs | 2 +- 6 files changed, 16 insertions(+), 2 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index d9cce18..48ada6c 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -109,6 +109,7 @@ Scenery.resize = new function(){ } base.hide = function () { + if (! obj) return obj = null dots.forEach(function(dot){ scene.remove(dot) 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 b75a912..e11f189 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -33,7 +33,6 @@ var EditorView = View.extend({ $("#map").hide() this.settings.load(data) - this.collaborators.show() }, readyLayout: function(data){ diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index cc924da..f1ded50 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -137,11 +137,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/stylesheets/app.css b/public/assets/stylesheets/app.css index f59635b..b1be797 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -544,6 +544,13 @@ iframe.embed { .mx-scenery { cursor: pointer; } +.editing .mx-scenery:hover, +.editing .mx-scenery.picked { + border: 1px dashed #000; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} .mx-scenery:active { cursor: pointer; } diff --git a/views/reader.ejs b/views/reader.ejs index 7c31766..ed5df1f 100644 --- a/views/reader.ejs +++ b/views/reader.ejs @@ -4,7 +4,7 @@ vvalls [[ include partials/meta ]] - +
-- cgit v1.2.3-70-g09d2 From 2bf7351025b29d1bc8ec2e5792dcb0532c4deb95 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 26 Aug 2014 18:59:24 -0400 Subject: color picker thingie --- .../assets/javascripts/rectangles/models/wall.js | 70 +++--- .../assets/javascripts/ui/editor/LightControl.js | 262 +++++++++++++++++++-- .../javascripts/ui/editor/WallpaperPicker.js | 4 + public/assets/javascripts/util.js | 5 +- public/assets/stylesheets/app.css | 61 +++-- views/controls/editor/light-control.ejs | 13 +- 6 files changed, 339 insertions(+), 76 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 8723c3c..1dd0ebf 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -82,7 +82,16 @@ } }) }) - this.outline() + + // flip the mx order + var shouldFlip = this.side & (LEFT | BACK) + if (! shouldFlip) { + this.mx.reverse() + } + + var wallColor = "rgba(255,255,255,0.95)" + var outlineColor = "rgba(0,0,0,1.0)" + this.outline(wallColor, outlineColor) } @@ -207,44 +216,39 @@ }) } - Wall.prototype.outline = function(){ + Wall.prototype.outline = function(wallColor, outlineColor){ var useX = this.side & FRONT_BACK - var shouldFlip = this.side & (LEFT | BACK) var mx = this.mx - if (! shouldFlip) { - mx = mx.reverse() - } - var len = this.mx.length - - var backgroundColor = "rgba(255,255,255,0.95)" - var borderColor = "rgba(0,0,0,1.0)" - - zz = window.zz || 0 + var outlineString = "1px solid " + outlineColor + zz = 0 mx.forEach(function(mx, i){ - if (mx.outlined) return - mx.outlined = true - mx.el.style.backgroundColor = backgroundColor - - // all walls get bottom lines - mx.el.style.borderBottom = "1px solid " + borderColor - - // all walls get top lines - mx.el.style.borderTop = "1px solid " + borderColor - - // walls on initial sides get left lines - // if their left edge lines up with the rect edge - if (i == 0) { - mx.el.style.borderLeft = "1px solid " + borderColor - } - - // walls on terminal sides get right lines.... - // if their right edge lines up with the rect edge - if (i == len-1) { - mx.el.style.borderRight = "1px solid " + borderColor - } + // if (mx.outlined) return + // mx.outlined = true + if (wallColor) { + mx.el.style.backgroundColor = wallColor + } + if (outlineColor) { + // all walls get bottom lines + mx.el.style.borderBottom = outlineString + + // all walls get top lines + mx.el.style.borderTop = outlineString + + // walls on initial sides get left lines + // if their left edge lines up with the rect edge + if (i == 0) { + mx.el.style.borderLeft = outlineString + } + + // walls on terminal sides get right lines.... + // if their right edge lines up with the rect edge + if (i == len-1) { + mx.el.style.borderRight = outlineString + } + } }) } diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index c3e80c2..b1c5b85 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -4,40 +4,254 @@ var LightControl = View.extend({ events: { "mousedown": "stopPropagation", + "click #wall-color": "editWallColor", + "click #outline-color": "editOutlineColor", + "click label": "clickLabel", + "input #shadow-control": "updateShadow", + "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.$wallSwatch = this.$("#wall-color") + this.$outlineSwatch = this.$("#outline-color") + this.$brightnessControl = this.$("#brightness-control") + + this.setMode("wall") + + this.setWallColor([255,255,255], false) + this.setOutlineColor([0,0,0]) + }, + toggle: function(state){ this.$el.toggleClass("active", state); - - // toggle the class that makes the cursor a paintbucket - // $("body").removeClass("pastePaper"); }, + show: function(){ this.toggle(true) }, + hide: function(){ this.toggle(false) }, + + pick: function(rgb, Lab){ + this.labColor = Lab + switch (this.mode) { + case "wall": + this.setWallColor(rgb) + break + case "outline": + this.setOutlineColor(rgb) + break + } + }, + + wallColor: [255,255,255], + outlineColor: [0,0,0], + + setMode: function (mode) { + var color, brightness + this.mode = mode + switch (mode) { + case "wall": + this.$wallSwatch.addClass("selected") + this.$outlineSwatch.removeClass("selected") + color = this.wallColor + break + case "outline": + this.$outlineSwatch.addClass("selected") + this.$wallSwatch.removeClass("selected") + color = this.outlineColor + break + } + this.labColor = this.colorPicker.load(color) + this.$brightnessControl.val( this.labColor[0] ) + }, + + clickLabel: function(e){ + $(e.currentTarget).prev(".swatch").trigger("click") + }, + editWallColor: function(){ + this.setMode("wall") + }, + editOutlineColor: function(){ + this.setMode("outline") + }, + + setWallColor: function(rgb, repaint){ + repaint = typeof repaint != "undefined" ? repaint : true + var rgbColor = rgb_string(rgb) + var rgbaColor = rgba_string(rgb, 0.95) + this.wallColor = rgb + this.$wallSwatch.css("background-color", rgbColor) + Rooms.walls.forEach(function(wall){ + wall.outline(rgbaColor, null) + }) + }, -/* - $("#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) - } - }) - - $("#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) - } - }) -*/ + setOutlineColor: function(rgb){ + repaint = typeof repaint != "undefined" ? repaint : true + var rgbColor = rgb_string(rgb) + this.outlineColor = rgb + this.$outlineSwatch.css("background-color", rgbColor) + Rooms.walls.forEach(function(wall){ + wall.outline(null, rgbColor) + }) + }, + + updateBrightness: function(){ + this.labColor[0] = parseFloat( this.$brightnessControl.val() ) + var rgb = this.colorPicker.setLab( this.labColor ) + this.pick(rgb, this.labColor) + }, }) + +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 + +// var cursor = this.cursor = document.createElement("div") +// cursor.className = "colorPickerCursor" + + canvas.width = w + canvas.height = h + canvas.className = "colorPicker" + + var down = false + + 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){ + 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) + } + }) + + 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] + 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] + } + + // this.paint(val) +} diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index 9ee441b..2309e22 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -7,6 +7,10 @@ var WallpaperPicker = View.extend({ }, initialize: function(){ + this.el.innerHTML = "wallpaper coming soon" + this.el.style.padding = "10px" + this.el.style.fontWeight = "300" + return var wm = new WallpaperManager() app.on('wallpaper-ready', function(){ var black = [0,0,0,1.0] diff --git a/public/assets/javascripts/util.js b/public/assets/javascripts/util.js index b92dcf3..7812a4d 100644 --- a/public/assets/javascripts/util.js +++ b/public/assets/javascripts/util.js @@ -12,7 +12,10 @@ function sanitize (s){ return (s || "").replace(new RegExp("[<>&]", 'g'), "") } function capitalize (s){ return s.split(" ").map(capitalizeWord).join(" ") } function capitalizeWord (s){ return s.charAt(0).toUpperCase() + s.slice(1) } function slugify (s){ return (s || "").toLowerCase().replace(/\s/g,"-").replace(/[^-_a-zA-Z0-9]/g, '-').replace(/-+/g,"-") } - +function rgb_string (rgb) { return "rgb(" + rgb.map(Math.round).join(",") + ")" } +function rgba_string (rgb,a) { return "rgba(" + rgb.map(Math.round).join(",") + "," + a + ")" } +function hex_string (rgb) { return "#" + rgb.map(Math.round).map(function(n){ var s = n.toString(16); return s.length == 1 ? "0"+s : s }).join("") } +function parse_rgba_string (s) { return s.match(/(\d+)/g).slice(0,3) } var E = Math.E var PI = Math.PI diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index b1be797..ff35ca4 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -636,6 +636,9 @@ iframe.embed { background-size: 100% 100%; } + +/* AUTOSAVE MONITOR */ + #minotaur { position: absolute; top: 26px; @@ -655,6 +658,7 @@ iframe.embed { content: 'SAVING'; } + .rapper { position:relative; } @@ -1092,6 +1096,9 @@ iframe.embed { transition:opacity 0.3s ease-in-out; } + +/* WALLPAPER PICKER */ + .wallpaper{ right: 80px; margin-top: 77px; @@ -1149,6 +1156,9 @@ iframe.embed { transform: translateX(3px) translateY(-3px); } + +/* COLOR PICKER */ + .lightcontrol { margin-top: 13%; right: 80px; @@ -1158,35 +1168,54 @@ iframe.embed { transform: translateX(400px); transition: -webkit-transform 0.2s ease-in-out; } - .lightcontrol.active { -webkit-transform: translateX(0px); transform: translateX(0px); } - -.lightcontrol .slider { - +.lightcontrol .slider { } h4 { font-weight:300; font-size:11px; } input[type=range] { - -webkit-appearance: none; - -moz-appearance: none; - background-color: black; - width: 180px; - height:3px; + -webkit-appearance: none; + -moz-appearance: none; + background-color: black; + width: 180px; + height:3px; } - input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - background-color: #000; - width: 10px; - height: 10px; - border-radius:10px; - cursor:pointer; + -webkit-appearance: none; + background-color: #000; + width: 10px; + height: 10px; + border-radius:10px; + cursor:pointer; } +.colorPicker { + cursor: crosshair; +} +.swatch { + width: 20px; + height: 20px; + border: 1px solid black; + display: inline-block; +} +.swatch.selected { + border-width: 2px; +} +.color-swatches { + margin-top: 10px; +} +.color-swatches label { + font-size: 11px; + font-weight: 300; + position: relative; + top: -6px; + margin-right: 15px; +} + .settings.info { right: auto; diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index ddd282b..4324087 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -1,8 +1,16 @@
+
- -

Outline Hue

+ +

Brightness

+ +
+
+
+
+ +
-- cgit v1.2.3-70-g09d2 From 098a330fab261885a86c7ae9a5b2ed294987dc6b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 27 Aug 2014 12:47:05 -0400 Subject: fix tests --- .../javascripts/rectangles/engine/rooms/builder.js | 4 +--- .../javascripts/rectangles/engine/rooms/grouper.js | 13 +++++++++---- public/assets/javascripts/rectangles/models/surface.js | 3 --- public/assets/javascripts/ui/editor/LightControl.js | 1 - views/partials/meta.ejs | 17 +++++++++++++++++ 5 files changed, 27 insertions(+), 11 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index f321f71..5396ced 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -165,7 +165,6 @@ room.mx_ceiling.push(el) } }.bind(this)) - } else { // render floor and ceiling for the entire rectangle @@ -282,7 +281,6 @@ el.side = CEILING return el } - this.make_wall = function (klass) { var el = new MX.Object3D(".face" + (klass || "")) el.width = el.height = el.scaleX = el.scaleY = el.scaleZ = 1 @@ -293,7 +291,7 @@ el.side = 0 el.rect = null el.destroy = function(){ - this.el = this.rect = this.face = null + this.el = this.rect = this.face = null } // possible if walls are opaque diff --git a/public/assets/javascripts/rectangles/engine/rooms/grouper.js b/public/assets/javascripts/rectangles/engine/rooms/grouper.js index cde9fbb..2ec1ee7 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/grouper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/grouper.js @@ -83,7 +83,10 @@ collection.sort( useX ? sort.compare_zx : sort.compare_xz ) collection.forEach(function(mx){ - if (last_mx && last_mx.rect.eq(mx.rect)) { + if (mx.culled) { + return + } + if (last_mx && mx && last_mx.rect.eq(mx.rect)) { // culls half-walls if (last_mx.rect.id == mx.rect.id) { last_mx.height += mx.height/2 @@ -91,9 +94,11 @@ last_mx.face.y.b += mx.height/2 } last_mx.side = side - mx.culled = true - mx.destroy() - scene.remove(mx) + if (! mx.culled) { + scene.remove(mx) + mx.destroy() + mx.culled = true + } return } widthVec = mx.rect[useX ? 'x' : 'y'].clone() diff --git a/public/assets/javascripts/rectangles/models/surface.js b/public/assets/javascripts/rectangles/models/surface.js index 636f7c0..53977c8 100644 --- a/public/assets/javascripts/rectangles/models/surface.js +++ b/public/assets/javascripts/rectangles/models/surface.js @@ -147,9 +147,6 @@ Surface.prototype.index_for_x = function(x, min_i){ min_i = min_i || 0 - if (min_i >= this.faces.length-1) { - return -1 - } for (var i = min_i; i < this.faces.length; i++) { if (this.faces[i].x.contains(x)) { return i diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index 1bd660e..f35b19e 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -170,7 +170,6 @@ var LabColorPicker = function (parent, w, h) { var y = mix( norm(Lab[2], b_range[0], b_range[1]), 0, hh ) // move the cursor this.setLab(Lab) - console.log(rgba) return Lab } this.paint = function() { diff --git a/views/partials/meta.ejs b/views/partials/meta.ejs index ceaaba1..9916b34 100644 --- a/views/partials/meta.ejs +++ b/views/partials/meta.ejs @@ -1,3 +1,20 @@ + + + -- cgit v1.2.3-70-g09d2 From 63b0e94e3e36838240c2d86e780a641c2255ed89 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 27 Aug 2014 13:03:46 -0400 Subject: floor/ceiling colors --- .../assets/javascripts/rectangles/models/room.js | 12 +++++ .../assets/javascripts/ui/editor/LightControl.js | 63 ++++++++++++++++++++-- public/assets/stylesheets/app.css | 9 +++- views/controls/editor/light-control.ejs | 7 ++- 4 files changed, 83 insertions(+), 8 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/rectangles/models/room.js b/public/assets/javascripts/rectangles/models/room.js index 33a94d0..1cc929f 100644 --- a/public/assets/javascripts/rectangles/models/room.js +++ b/public/assets/javascripts/rectangles/models/room.js @@ -182,6 +182,18 @@ return collision } + Room.prototype.setFloorColor = function(rgbColor) { + this.mx_floor.map(function(mx){ + mx.el.style.backgroundColor = rgbColor + }) + } + + Room.prototype.setCeilingColor = function(rgbColor) { + this.mx_ceiling.map(function(mx){ + mx.el.style.backgroundColor = rgbColor + }) + } + if ('window' in this) { window.Room = Room } diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index f35b19e..a3a19c7 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -6,6 +6,8 @@ var LightControl = View.extend({ "mousedown": "stopPropagation", "click #wall-color": "editWallColor", "click #outline-color": "editOutlineColor", + "click #floor-color": "editFloorColor", + "click #ceiling-color": "editCeilingColor", "click label": "clickLabel", "input #shadow-control": "updateShadow", "input #brightness-control": "updateBrightness", @@ -17,14 +19,20 @@ var LightControl = View.extend({ this.colorPicker = new LabColorPicker(this, 180, 180) this.$el.prepend( this.colorPicker.canvas ) + this.$swatches = this.$(".swatch") + this.$labels = this.$(".swatch + label") this.$wallSwatch = this.$("#wall-color") this.$outlineSwatch = this.$("#outline-color") + this.$floorSwatch = this.$("#floor-color") + this.$ceilingSwatch = this.$("#ceiling-color") this.$brightnessControl = this.$("#brightness-control") this.setMode("wall") - this.setWallColor([255,255,255], false) - this.setOutlineColor([0,0,0]) + this.setWallColor(this.wallColor, false) + this.setOutlineColor(this.outlineColor) + this.setFloorColor(this.floorColor) + this.setCeilingColor(this.ceilingColor) }, toggle: function(state){ @@ -48,27 +56,44 @@ var LightControl = View.extend({ case "outline": this.setOutlineColor(rgb) break + case "floor": + this.setFloorColor(rgb) + break + case "ceiling": + this.setCeilingColor(rgb) + break } }, wallColor: [255,255,255], outlineColor: [0,0,0], + floorColor: [246,246,246], + ceilingColor: [255,255,255], setMode: function (mode) { var color, brightness this.mode = mode + this.$swatches.removeClass("selected") + this.$labels.removeClass("selected") switch (mode) { case "wall": this.$wallSwatch.addClass("selected") - this.$outlineSwatch.removeClass("selected") color = this.wallColor break case "outline": this.$outlineSwatch.addClass("selected") - this.$wallSwatch.removeClass("selected") color = this.outlineColor break + case "floor": + this.$floorSwatch.addClass("selected") + color = this.floorColor + break + case "ceiling": + this.$ceilingSwatch.addClass("selected") + color = this.ceilingColor + break } + this.$(".swatch.selected").next("label").addClass("selected") this.labColor = this.colorPicker.load(color) this.$brightnessControl.val( this.labColor[0] ) }, @@ -83,7 +108,15 @@ var LightControl = View.extend({ this.setMode("outline") }, - setWallColor: function(rgb, repaint){ + editFloorColor: function(){ + this.setMode("floor") + }, + + editCeilingColor: function(){ + this.setMode("ceiling") + }, + + setWallColor: function(rgb, repaint){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) var rgbaColor = rgba_string(rgb, 0.95) @@ -94,6 +127,26 @@ var LightControl = View.extend({ }) }, + setFloorColor: function(rgb, repaint){ + repaint = typeof repaint != "undefined" ? repaint : true + var rgbColor = rgb_string(rgb) + this.floorColor = rgb + this.$floorSwatch.css("background-color", rgbColor) + Rooms.forEach(function(room){ + room.setFloorColor(rgbColor) + }) + }, + + setCeilingColor: function(rgb, repaint){ + repaint = typeof repaint != "undefined" ? repaint : true + var rgbColor = rgb_string(rgb) + this.ceilingColor = rgb + this.$ceilingSwatch.css("background-color", rgbColor) + Rooms.forEach(function(room){ + room.setCeilingColor(rgbColor) + }) + }, + setOutlineColor: function(rgb){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index ff35ca4..6f6a192 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1201,6 +1201,7 @@ input[type="range"]::-webkit-slider-thumb { height: 20px; border: 1px solid black; display: inline-block; + cursor: pointer; } .swatch.selected { border-width: 2px; @@ -1213,7 +1214,13 @@ input[type="range"]::-webkit-slider-thumb { font-weight: 300; position: relative; top: -6px; - margin-right: 15px; + padding-left: 5px; + display: inline-block; + width: 60px; + cursor: pointer; +} +.color-swatches label.selected { + font-weight: 500; } diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index 4324087..02a78b6 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -6,8 +6,11 @@
-
-
+
+
+
+
+
+
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index ae5b31f..544c37e 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -63,6 +63,7 @@ + -- cgit v1.2.3-70-g09d2 From e200f73bdc55e4b6e3dcdf17f5fb5bfd6c020c2a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 28 Aug 2014 17:22:28 -0400 Subject: split out walls stuff, remove dead code --- public/assets/javascripts/app.js | 7 -- public/assets/javascripts/defaults.js | 11 +++ .../javascripts/rectangles/engine/rooms/_rooms.js | 9 --- .../javascripts/rectangles/engine/rooms/_walls.js | 91 ++++++++++++++++++++++ .../javascripts/rectangles/engine/rooms/builder.js | 1 + .../javascripts/rectangles/engine/rooms/grouper.js | 12 +-- .../rectangles/engine/scenery/_scenery.js | 2 +- .../javascripts/rectangles/engine/scenery/undo.js | 4 +- .../assets/javascripts/rectangles/models/room.js | 23 ------ .../assets/javascripts/rectangles/models/wall.js | 34 +++----- .../assets/javascripts/rectangles/util/colors.js | 5 -- .../javascripts/ui/builder/BuilderSettings.js | 2 + .../assets/javascripts/ui/builder/BuilderView.js | 1 + .../assets/javascripts/ui/editor/EditorSettings.js | 10 ++- .../assets/javascripts/ui/editor/LightControl.js | 44 ++++++----- public/assets/stylesheets/app.css | 20 ++--- views/controls/editor/wallpaper.ejs | 2 +- views/partials/scripts.ejs | 2 + 18 files changed, 168 insertions(+), 112 deletions(-) create mode 100644 public/assets/javascripts/defaults.js create mode 100644 public/assets/javascripts/rectangles/engine/rooms/_walls.js (limited to 'views') diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index ad3c601..1dd8a5e 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -98,11 +98,4 @@ app.position = function(obj){ return pos } -app.defaults = { - viewHeight: window.viewHeight = 186, - units: app.units = "ft", - footResolution: 36, - meterResolution: 100, -} - document.addEventListener('DOMContentLoaded', app.init) diff --git a/public/assets/javascripts/defaults.js b/public/assets/javascripts/defaults.js new file mode 100644 index 0000000..98ea0c3 --- /dev/null +++ b/public/assets/javascripts/defaults.js @@ -0,0 +1,11 @@ +app.defaults = { + viewHeight: window.viewHeight = 186, + units: app.units = "ft", + footResolution: 36, + meterResolution: 100, + wallOpacity: 0.95, + wallColor: [255,255,255], + outlineColor: [0,0,0], + floorColor: [246,246,246], + ceilingColor: [255,255,255], +} diff --git a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js index 29dee41..5ed7be8 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js @@ -35,7 +35,6 @@ var base = this base.list = {} - base.walls = {} base.regions = [] base.uid = new UidGenerator(base.list) @@ -110,14 +109,6 @@ Rooms.clipper.update() } - base.serializeWalls = function(){ - return [] - } - - base.deserializeWalls = function(walls_data){ - return [] - } - base.sorted_by_position = function(){ return sort.rooms_by_position( base.values() ) } diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js new file mode 100644 index 0000000..f5ef6be --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -0,0 +1,91 @@ +(function(){ + + var vec2, Rect, Room, sort, UidGenerator, _ + if ('window' in this) { + vec2 = window.vec2 + Rect = window.Rect + Room = window.Room + sort = window.sort + UidGenerator = window.UidGenerator + _ = window._ + } + else { + vec2 = require('../../models/vec2') + Rect = require('../../models/rect') + Room = require('../../models/room') + UidGenerator = require('../../util/uid') + sort = require('../../util/sort') + _ = require('lodash') + FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20 + TOP = CEILING, BOTTOM = FLOOR + function sidesToString(sides){ + var s = "" + if (sides & FRONT) s += "front " + if (sides & BACK) s += "back " + if (sides & LEFT) s += "left " + if (sides & RIGHT) s += "right " + if (sides & TOP) s += "top " + if (sides & BOTTOM) s += "bottom " + return s + } + } + + var Walls = new function(){ + + var base = this + + base.list = [] + base.lookup = {} + base.colors = {} + + base.first = function(){ + for (var i in base.list) { + if (base.list.hasOwnProperty(i)) { + return base.list[i] + } + } + } + + base.assign = function(list){ + base.list = list + base.lookup = {} + list.forEach(function(wall){ + base.lookup[wall.id] = wall + }) + } + + base.bind = function(){ + base.list.forEach(function(wall){ + wall.bind() + }) + } + + base.count = function(){ + return this.list.length + } + + base.forEach = function(f){ + return base.list.forEach(f) + } + + base.map = function(f){ + return base.list.map(f) + } + + base.serialize = function(){ + return [] + } + + base.deserialize = function(walls_data){ + return [] + } + + } + + if ('window' in this) { + window.Walls = Walls + } + else { + module.exports = Walls + } +})() diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index 5396ced..f0935d4 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -282,6 +282,7 @@ return el } this.make_wall = function (klass) { + // klass += ".backface-hidden" var el = new MX.Object3D(".face" + (klass || "")) el.width = el.height = el.scaleX = el.scaleY = el.scaleZ = 1 el.z = el.y = el.x = 0 diff --git a/public/assets/javascripts/rectangles/engine/rooms/grouper.js b/public/assets/javascripts/rectangles/engine/rooms/grouper.js index 2ec1ee7..ba510e1 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/grouper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/grouper.js @@ -52,8 +52,8 @@ base.group(walls, collections, BACK) base.group(walls, collections, LEFT) base.group(walls, collections, RIGHT) - Rooms.walls = walls - base.bind() + Walls.assign( walls ) + Walls.bind() } base.collect = function(){ var collections = {} @@ -147,7 +147,6 @@ } } wall = new Wall ({ - id: base.uid(), side: side, mx: [ mx ], surface: new Surface( mx.face ), @@ -160,13 +159,6 @@ return walls } - - base.bind = function(){ - Rooms.walls.forEach(function(wall){ - wall.bind() - wall.randomize_colors() - }) - } } diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index 2fd6122..4cf5b06 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -84,7 +84,7 @@ var Scenery = new function(){ base.deserialize = function(scenery_data){ scenery_data.forEach(function(data){ - var wall = Rooms.walls[data.wall_id] || Rooms.walls[0] + var wall = Walls.list[data.wall_id] || Walls.first() var scene_media = base.add({ data: data, wall: wall, diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 54ab755..a7e7d61 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -20,7 +20,7 @@ undo: function(state){ var scenery = Scenery.find(state.id) scenery.deserialize(state) - scenery.set_wall(Rooms.walls[ state.wall_id ]) + scenery.set_wall(Walls.find( state.wall_id )) if (editor.permissions.resize) { Scenery.resize.show(scenery) @@ -32,7 +32,7 @@ redo: function(state){ var scenery = Scenery.find(state.id) scenery.deserialize(state) - scenery.set_wall(Rooms.walls[ state.wall_id ]) + scenery.set_wall(Walls.find( state.wall_id )) if (editor.permissions.resize) { Scenery.resize.show(scenery) diff --git a/public/assets/javascripts/rectangles/models/room.js b/public/assets/javascripts/rectangles/models/room.js index 1cc929f..0f09325 100644 --- a/public/assets/javascripts/rectangles/models/room.js +++ b/public/assets/javascripts/rectangles/models/room.js @@ -32,9 +32,6 @@ this.id = opt.id || Rooms.uid("room_") this.rect = opt.rect this.regions = [] - this.walls = [] - this.floor = [] - this.ceiling = [] this.height = opt.height || 200 this.focused = false @@ -69,30 +66,10 @@ this.intersects = [] this.constructed = false - this.walls = [] - this.mx_walls = [] this.mx_floor = [] this.mx_ceiling = [] } - - Room.prototype.bind = function(){ - var base = this - base.mx_walls.forEach(function(wall){ - $(wall.el).bind({ - mouseover: function(){ - }, - mousemove: function(e){ - var color = choice(window.palettes.colors) - base.mx_walls.forEach(function(wall){ - $(wall.el).css("background-color", color) - }) - }, - mousedown: function(){ - } - }) - }) - } Room.prototype.clipTo = function(r){ // for each of this rect's regions split the region if necessary diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 1dd0ebf..61de95e 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -13,7 +13,7 @@ } var Wall = function(opt){ - this.id = opt.id + this.id = [ opt.side, opt.edge, opt.vec.a ].join("_") this.vec = opt.vec this.edge = opt.edge this.side = opt.side @@ -89,9 +89,7 @@ this.mx.reverse() } - var wallColor = "rgba(255,255,255,0.95)" - var outlineColor = "rgba(0,0,0,1.0)" - this.outline(wallColor, outlineColor) + // this.outline(wallColor, outlineColor) } @@ -199,7 +197,7 @@ } Wall.prototype.color = function(color){ - this.$walls && this.$walls.css("background-color", color) + this.$walls.css("background-color", color) } Wall.prototype.wallpaper = function(){ @@ -254,33 +252,21 @@ Wall.prototype.siblings = function(){ return this -// var base = this -// var match = base.side | base.half_side -// var walls = Rooms.list[this.room].walls.filter(function(w){ -// return (w.side | w.half_side) & match && w.$walls -// }) -// return walls - } - - Wall.prototype.randomize_colors = function(){ - var color = window.grayColors[ this.side | this.half_side ] - // this.color(color) } Wall.prototype.stroke_colors = function(){ var color = "#fff" - var siblings = this.siblings() - siblings.forEach(function(w, i){ - if (! w.$walls) return + var len = this.mx.length-1 + this.mx.forEach(function(mx, i){ w.color(color) if (i == 0) { - w.$walls.css("border-left", "1px solid #000") + mx.el.css("border-left", "1px solid #000") } - if (i == siblings.length-1) { - w.$walls.css("border-right", "1px solid #000") + if (i == len) { + mx.el.css("border-right", "1px solid #000") } - w.$walls.css("border-top", "1px solid #000") - w.$walls.css("border-bottom", "1px solid #000") + mx.el.css("border-top", "1px solid #000") + mx.el.css("border-bottom", "1px solid #000") }) } diff --git a/public/assets/javascripts/rectangles/util/colors.js b/public/assets/javascripts/rectangles/util/colors.js index 16d34dd..4ad96fc 100644 --- a/public/assets/javascripts/rectangles/util/colors.js +++ b/public/assets/javascripts/rectangles/util/colors.js @@ -50,11 +50,6 @@ var select = document.querySelector("#palette") select && select.addEventListener("change", function(){ colors = color_palettes[select.value] - Rooms.forEach(function(room){ - room.walls.forEach(function(wall){ - wall.randomize_colors() - }) - }) select.blur() }) 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/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index e5dd844..2d3201e 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -32,8 +32,16 @@ var EditorSettings = FormView.extend({ 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) { + this.parent.lightControl.load() + } + else { + this.parent.lightControl.loadDefaults() + } + if (data.isNew) { this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) } diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index a3a19c7..5133de2 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -26,14 +26,25 @@ var LightControl = View.extend({ this.$floorSwatch = this.$("#floor-color") this.$ceilingSwatch = this.$("#ceiling-color") this.$brightnessControl = this.$("#brightness-control") - - this.setMode("wall") - - this.setWallColor(this.wallColor, false) - this.setOutlineColor(this.outlineColor) - this.setFloorColor(this.floorColor) - this.setCeilingColor(this.ceilingColor) }, + + load: function(data){ + this.setWallColor(data.wallColor, false) + this.setOutlineColor(data.outlineColor) + this.setFloorColor(data.floorColor) + this.setCeilingColor(data.ceilingColor) + this.setMode("wall") + }, + + loadDefaults: function(){ + var colors = { + wallColor: app.defaults.wallColor.slice(), + outlineColor: app.defaults.outlineColor.slice(), + floorColor: app.defaults.floorColor.slice(), + ceilingColor: app.defaults.ceilingColor.slice(), + } + this.load(colors) + }, toggle: function(state){ this.$el.toggleClass("active", state); @@ -65,11 +76,6 @@ var LightControl = View.extend({ } }, - wallColor: [255,255,255], - outlineColor: [0,0,0], - floorColor: [246,246,246], - ceilingColor: [255,255,255], - setMode: function (mode) { var color, brightness this.mode = mode @@ -119,10 +125,10 @@ var LightControl = View.extend({ setWallColor: function(rgb, repaint){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) - var rgbaColor = rgba_string(rgb, 0.95) - this.wallColor = rgb + var rgbaColor = rgba_string(rgb, app.defaults.wallOpacity) + Walls.colors.wall = this.wallColor = rgb this.$wallSwatch.css("background-color", rgbColor) - Rooms.walls.forEach(function(wall){ + Walls.forEach(function(wall){ wall.outline(rgbaColor, null) }) }, @@ -130,7 +136,7 @@ var LightControl = View.extend({ setFloorColor: function(rgb, repaint){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) - this.floorColor = rgb + Walls.colors.floor = this.floorColor = rgb this.$floorSwatch.css("background-color", rgbColor) Rooms.forEach(function(room){ room.setFloorColor(rgbColor) @@ -140,7 +146,7 @@ var LightControl = View.extend({ setCeilingColor: function(rgb, repaint){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) - this.ceilingColor = rgb + Walls.colors.ceiling = this.ceilingColor = rgb this.$ceilingSwatch.css("background-color", rgbColor) Rooms.forEach(function(room){ room.setCeilingColor(rgbColor) @@ -150,9 +156,9 @@ var LightControl = View.extend({ setOutlineColor: function(rgb){ repaint = typeof repaint != "undefined" ? repaint : true var rgbColor = rgb_string(rgb) - this.outlineColor = rgb + Walls.colors.outline = this.outlineColor = rgb this.$outlineSwatch.css("background-color", rgbColor) - Rooms.walls.forEach(function(wall){ + Walls.forEach(function(wall){ wall.outline(null, rgbColor) }) }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 493cf67..c2e7119 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -768,13 +768,13 @@ iframe.embed { content:"show map"; } .fixed { - position:fixed; - top:0; - left:0; - width:100%; - height:100%; - z-index:3; - overflow-y:scroll; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 3; + overflow-y: scroll; } .fixed::-webkit-scrollbar { @@ -794,7 +794,7 @@ iframe.embed { } .fixed::-moz-scrollbar-track { - background:white; + background: white; } .fixed::-moz-scrollbar-thumb{ @@ -1116,9 +1116,9 @@ iframe.embed { } .wallpaper.active .swatches .swatch { width: 40px; - height: 35px; + height: 40px; display: inline-block; - border:1px solid; + border: 1px solid; background-size: contain; -webkit-transition: -webkit-transform 0.1s ease-in-out; line-height: 0; diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index ecb15ca..55ecf85 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -1,4 +1,4 @@ -
+
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 544c37e..7d56b2e 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -41,6 +41,7 @@ + @@ -104,6 +105,7 @@ + -- cgit v1.2.3-70-g09d2 From a7e198fd71b1d0b9ec544c3f2b1e38eaca4d719f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 29 Aug 2014 22:13:20 -0400 Subject: undo/redo for colors --- .../javascripts/rectangles/engine/rooms/_walls.js | 37 ++- .../javascripts/rectangles/engine/scenery/undo.js | 75 +++--- .../assets/javascripts/rectangles/util/minotaur.js | 2 +- .../javascripts/rectangles/util/undostack.js | 13 +- .../assets/javascripts/ui/editor/LightControl.js | 268 +++++++++------------ views/controls/editor/light-control.ejs | 8 +- 6 files changed, 201 insertions(+), 202 deletions(-) (limited to 'views') diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js index 046961b..f2f395b 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_walls.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -86,8 +86,43 @@ var wall = base.lookup[ wall_data.id ] wall.deserialize( wall_data ) }) + }, + + base.setColor = { + + wall: function(rgb){ + var rgbaColor = rgba_string(rgb, app.defaults.wallOpacity) + Walls.colors.wall = rgb + Walls.forEach(function(wall){ + wall.outline(rgbaColor, null) + }) + }, + + outline: function(rgb){ + var rgbColor = rgb_string(rgb) + Walls.colors.outline = rgb + Walls.forEach(function(wall){ + wall.outline(null, rgbColor) + }) + }, + + floor: function(rgb){ + var rgbColor = rgb_string(rgb) + Walls.colors.floor = rgb + Rooms.forEach(function(room){ + room.setFloorColor(rgbColor) + }) + }, + + ceiling: function(rgb){ + var rgbColor = rgb_string(rgb) + Walls.colors.ceiling = rgb + Rooms.forEach(function(room){ + room.setCeilingColor(rgbColor) + }) + }, + } - } if ('window' in this) { diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 1632c5b..ac9fdc0 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -1,7 +1,7 @@ (function(){ - UndoStack.register([ - { - type: "create-scenery", + UndoStack.register([ + { + type: "create-scenery", undo: function(state){ Scenery.remove(state.id) @@ -14,9 +14,9 @@ // TODO: watch individual scenery object here Minotaur.watch( app.router.editorView.settings ) }, - }, - { - type: "update-scenery", + }, + { + type: "update-scenery", undo: function(state){ var scenery = Scenery.find(state.id) scenery.deserialize(state) @@ -43,9 +43,9 @@ // TODO: watch individual scenery object here Minotaur.watch( app.router.editorView.settings ) }, - }, - { - type: "destroy-scenery", + }, + { + type: "destroy-scenery", undo: function(state){ Scenery.deserialize([ state ]) @@ -58,12 +58,12 @@ // TODO: watch individual scenery object here Minotaur.watch( app.router.editorView.settings ) }, - }, - - // - - { - type: "create-room", + }, + + // + + { + type: "create-room", undo: function(room){ Rooms.remove(room) Rooms.clipper.update() @@ -71,52 +71,55 @@ redo: function(room){ Rooms.add(new Room(room)) Rooms.clipper.update() - app.tube("builder-pick-room", room) + app.tube("builder-pick-room", room) }, - }, - { - type: "update-room", + }, + { + type: "update-room", undo: function(state){ var room = Rooms.list[state.id] room.rect.assign( state.rect ) room.height = state.height Rooms.clipper.update() - app.tube("builder-pick-room", room) + app.tube("builder-pick-room", room) }, redo: function(state){ var room = Rooms.list[state.id] room.rect.assign( state.rect ) room.height = state.height Rooms.clipper.update() - app.tube("builder-pick-room", room) + app.tube("builder-pick-room", room) }, - }, - { - type: "destroy-room", + }, + { + type: "destroy-room", undo: function(room){ Rooms.add(new Room(room)) Rooms.clipper.update() - app.tube("builder-pick-room", room) + app.tube("builder-pick-room", room) }, redo: function(room){ Rooms.remove(room) Rooms.clipper.update() }, - }, - - // + }, + + // - { - type: "update-wallpaper", + { + type: "update-wallpaper", undo: function(state){ var wall = Walls.lookup[state.id] wall.deserialize(state) }, - redo: function(state){ - var wall = Walls.lookup[state.id] - wall.deserialize(state) + }, + { + type: "update-colors", + undo: function(state){ + Walls.setColor[ state.mode ]( state.rgb ) + app.router.editorView.lightControl.setSwatchColor( state.mode, state.rgb ) }, - }, - - ]) + }, + + ]) })() diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js index 039a053..e6a37e0 100644 --- a/public/assets/javascripts/rectangles/util/minotaur.js +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -4,7 +4,7 @@ var base = this base.$el = $("#minotaur") base.timeout = null - base.delay = 500 + base.delay = 1000 base.objects = {} base.init = function () { diff --git a/public/assets/javascripts/rectangles/util/undostack.js b/public/assets/javascripts/rectangles/util/undostack.js index b93c79e..959e3d1 100644 --- a/public/assets/javascripts/rectangles/util/undostack.js +++ b/public/assets/javascripts/rectangles/util/undostack.js @@ -31,16 +31,17 @@ this.types[ action.type ].redo(action.redo) return this.pointer < this.stack.length-1 } - UndoStack.prototype.register = function(actionType){ - if (actionType.length) { - actionType.forEach(this.registerOne.bind(this)) + UndoStack.prototype.register = function(actions){ + if (actions.length) { + actions.forEach(this.registerOne.bind(this)) } else { - this.registerOne(actionType) + this.registerOne(actions) } } - UndoStack.prototype.registerOne = function(actionType){ - this.types[ actionType.type ] = actionType + UndoStack.prototype.registerOne = function(action){ + if (! action.redo) { action.redo = action.undo } + this.types[ action.type ] = action } if ('window' in this) { window.UndoStack = new UndoStack diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index 84f2e58..76e9da1 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -1,39 +1,41 @@ var LightControl = View.extend({ - el: ".lightcontrol", - - events: { - "mousedown": "stopPropagation", - "click #wall-color": "editWallColor", - "click #outline-color": "editOutlineColor", - "click #floor-color": "editFloorColor", - "click #ceiling-color": "editCeilingColor", - "click label": "clickLabel", - "input #shadow-control": "updateShadow", - "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.$wallSwatch = this.$("#wall-color") - this.$outlineSwatch = this.$("#outline-color") - this.$floorSwatch = this.$("#floor-color") - this.$ceilingSwatch = this.$("#ceiling-color") - this.$brightnessControl = this.$("#brightness-control") - }, + 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") + }, + modes: [ "wall", "outline", "floor", "ceiling" ], + load: function(data){ - this.setWallColor(data.wall, false) - this.setOutlineColor(data.outline) - this.setFloorColor(data.floor) - this.setCeilingColor(data.ceiling) - this.setMode("wall") + 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(){ @@ -45,129 +47,85 @@ var LightControl = View.extend({ } this.load(colors) }, - - toggle: function(state){ + + 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 - switch (this.mode) { - case "wall": - this.setWallColor(rgb) - break - case "outline": - this.setOutlineColor(rgb) - break - case "floor": - this.setFloorColor(rgb) - break - case "ceiling": - this.setCeilingColor(rgb) - break - } - }, - - setMode: function (mode) { - var color, brightness - this.mode = mode + }, + + 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 + + Minotaur.watch( app.router.editorView.settings ) + }, + + setMode: function (mode) { + var color, brightness + this.mode = mode this.$swatches.removeClass("selected") this.$labels.removeClass("selected") - switch (mode) { - case "wall": - this.$wallSwatch.addClass("selected") - color = this.wallColor - break - case "outline": - this.$outlineSwatch.addClass("selected") - color = this.outlineColor - break - case "floor": - this.$floorSwatch.addClass("selected") - color = this.floorColor - break - case "ceiling": - this.$ceilingSwatch.addClass("selected") - color = this.ceilingColor - break - } + 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") - }, - editWallColor: function(){ - this.setMode("wall") - }, - editOutlineColor: function(){ - this.setMode("outline") - }, - - editFloorColor: function(){ - this.setMode("floor") - }, - - editCeilingColor: function(){ - this.setMode("ceiling") - }, - - setWallColor: function(rgb, repaint){ - repaint = typeof repaint != "undefined" ? repaint : true - var rgbColor = rgb_string(rgb) - var rgbaColor = rgba_string(rgb, app.defaults.wallOpacity) - Walls.colors.wall = this.wallColor = rgb - this.$wallSwatch.css("background-color", rgbColor) - Walls.forEach(function(wall){ - wall.outline(rgbaColor, null) - }) - }, - - setFloorColor: function(rgb, repaint){ - repaint = typeof repaint != "undefined" ? repaint : true - var rgbColor = rgb_string(rgb) - Walls.colors.floor = this.floorColor = rgb - this.$floorSwatch.css("background-color", rgbColor) - Rooms.forEach(function(room){ - room.setFloorColor(rgbColor) - }) - }, - - setCeilingColor: function(rgb, repaint){ - repaint = typeof repaint != "undefined" ? repaint : true - var rgbColor = rgb_string(rgb) - Walls.colors.ceiling = this.ceilingColor = rgb - this.$ceilingSwatch.css("background-color", rgbColor) - Rooms.forEach(function(room){ - room.setCeilingColor(rgbColor) - }) - }, - - setOutlineColor: function(rgb){ - repaint = typeof repaint != "undefined" ? repaint : true - var rgbColor = rgb_string(rgb) - Walls.colors.outline = this.outlineColor = rgb - this.$outlineSwatch.css("background-color", rgbColor) - Walls.forEach(function(wall){ - wall.outline(null, rgbColor) - }) - }, - - updateBrightness: function(){ - this.labColor[0] = parseFloat( this.$brightnessControl.val() ) - var rgb = this.colorPicker.setLab( this.labColor ) - this.pick(rgb, this.labColor) - }, + 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) + }, }) @@ -185,8 +143,6 @@ var LabColorPicker = function (parent, w, h) { canvas.height = h canvas.className = "colorPicker" - var down = false - var ww = w-1 var hh = h-1 @@ -197,16 +153,20 @@ var LabColorPicker = function (parent, w, h) { 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() } }) diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index 8536b74..a67df34 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -6,11 +6,11 @@
-
-
-
+
+
+

-
+