summaryrefslogtreecommitdiff
path: root/public/assets/javascripts/ui
diff options
context:
space:
mode:
Diffstat (limited to 'public/assets/javascripts/ui')
-rw-r--r--public/assets/javascripts/ui/_router.js101
-rw-r--r--public/assets/javascripts/ui/builder/BuilderInfo.js160
-rw-r--r--public/assets/javascripts/ui/builder/BuilderSettings.js15
-rw-r--r--public/assets/javascripts/ui/builder/BuilderView.js9
-rw-r--r--public/assets/javascripts/ui/editor/EditorSettings.js13
-rw-r--r--public/assets/javascripts/ui/editor/EditorToolbar.js1
-rw-r--r--public/assets/javascripts/ui/editor/EditorView.js18
-rw-r--r--public/assets/javascripts/ui/editor/LightControl.js1
-rw-r--r--public/assets/javascripts/ui/editor/MediaEditor.js134
-rw-r--r--public/assets/javascripts/ui/editor/MediaUpload.js8
-rw-r--r--public/assets/javascripts/ui/editor/MediaViewer.js24
-rw-r--r--public/assets/javascripts/ui/editor/WallpaperPicker.js131
-rw-r--r--public/assets/javascripts/ui/lib/FormView.js4
-rw-r--r--public/assets/javascripts/ui/lib/Parser.js84
-rw-r--r--public/assets/javascripts/ui/lib/Router.js4
-rw-r--r--public/assets/javascripts/ui/lib/View.js6
-rw-r--r--public/assets/javascripts/ui/reader/MediaPlayer.js100
-rw-r--r--public/assets/javascripts/ui/reader/ReaderView.js50
-rw-r--r--public/assets/javascripts/ui/site/DocumentModal.js4
-rw-r--r--public/assets/javascripts/ui/site/EditProfileModal.js4
-rw-r--r--public/assets/javascripts/ui/site/EditProjectModal.js4
-rw-r--r--public/assets/javascripts/ui/site/LayoutsModal.js19
-rw-r--r--public/assets/javascripts/ui/site/PasswordForgot.js26
-rw-r--r--public/assets/javascripts/ui/site/PasswordReset.js31
-rw-r--r--public/assets/javascripts/ui/site/ProfileView.js28
-rw-r--r--public/assets/javascripts/ui/site/UsernameTaken.js27
26 files changed, 915 insertions, 91 deletions
diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js
index 6d41d5b..d070d55 100644
--- a/public/assets/javascripts/ui/_router.js
+++ b/public/assets/javascripts/ui/_router.js
@@ -5,6 +5,7 @@ var SiteRouter = Router.extend({
events: {
"click [data-role='show-signup-modal']": 'signup',
"click [data-role='show-signin-modal']": 'signin',
+ "click [data-role='forgot-password']": 'passwordForgot',
"click [data-role='new-project-modal']": 'newProject',
"click [data-role='edit-project-modal']": 'editProject',
"click [data-role='edit-profile-modal']": 'editProfile',
@@ -18,6 +19,11 @@ var SiteRouter = Router.extend({
routes: {
"/login": 'signin',
"/signup": 'signup',
+
+ "/auth/usernameTaken": 'usernameTaken',
+ "/auth/password": 'passwordReset',
+ "/auth/forgotPassword": 'passwordForgot',
+
"/profile": 'profile',
"/profile/edit": 'editProfile',
"/about/:name/edit": 'editDocument',
@@ -29,7 +35,10 @@ var SiteRouter = Router.extend({
"/project": 'projectPicker',
"/project/new": 'newProject',
"/project/new/:layout": 'projectNewWithLayout',
- "/project/:name": 'projectEditor',
+ "/project/:name": 'project',
+ "/project/:name/view": 'projectViewer',
+
+ "/test/wallpaper": 'testWallpaper',
},
initialize: function(){
@@ -40,7 +49,9 @@ var SiteRouter = Router.extend({
this.newProjectModal = new NewProjectModal()
this.editProjectModal = new EditProjectModal()
this.editProfileModal = new EditProfileModal()
+ this.passwordForgotModal = new PasswordForgot()
this.documentModal = new DocumentModal()
+ this.profileView = new ProfileView()
this.route()
@@ -52,7 +63,7 @@ var SiteRouter = Router.extend({
app.mode.builder = true
app.launch()
- this.builderView = new BuilderView()
+ this.builderView = app.controller = new BuilderView()
this.builderView.load(name)
},
@@ -83,25 +94,35 @@ var SiteRouter = Router.extend({
layout = slugify(layout)
window.history.pushState(null, document.title, "/project/new/" + layout)
- this.editorView = new EditorView()
+ this.editorView = app.controller = new EditorView()
this.editorView.loadLayout(layout)
},
- projectEditor: function(e, name){
- app.mode.editor = true
- app.launch()
-
+ project: function(e, name){
if ($(".aboutRoom").length) {
- this.readerView = new ReaderView()
- this.readerView.load(name)
+ this.projectViewer(e, name)
}
else {
- this.editorView = new EditorView()
- this.editorView.load(name)
+ this.projectEditor(e, name)
}
},
+ projectEditor: function(e, name){
+ app.mode.editor = true
+ app.launch()
+
+ this.editorView = app.controller = new EditorView()
+ this.editorView.load(name)
+ },
+ projectViewer: function(e, name){
+ app.mode.editor = true
+ app.launch()
+
+ this.readerView = app.controller = new ReaderView()
+ this.readerView.load(name)
+ },
+
/*
editProject: function(e){
e && e.preventDefault()
@@ -122,14 +143,23 @@ var SiteRouter = Router.extend({
this.signInModal.load()
},
- profile: function(e){
- var classes = ['one', 'two', 'three', 'four',
- 'five', 'six', 'seven', 'eight',
- 'nine', 'ten', 'eleven', 'twelve',
- 'thirteen'];
- $(".bio").addClass(choice(classes));
+ usernameTaken: function(e){
+ this.usernameTakenModal = new UsernameTaken ()
+ this.usernameTakenModal.load()
+ },
+ passwordForgot: function(e){
+ e && e.preventDefault()
+ window.history.pushState(null, document.title, "/auth/forgotPassword")
+ this.passwordForgotModal.load()
+ },
+ passwordReset: function(e){
+ this.passwordResetModal = new PasswordReset ()
+ this.passwordResetModal.load()
},
+ profile: function(e){
+ this.profileView.load()
+ },
editProfile: function(e){
e && e.preventDefault()
window.history.pushState(null, document.title, "/profile/edit")
@@ -160,16 +190,41 @@ var SiteRouter = Router.extend({
var name = e ? $(e.currentTarget).data("name") : name
- confirmModal.confirm("Are you sure you want to delete " + name + "?", $.proxy(function(){
- this.documentModal.destroy(name, $.proxy(function(){
- AlertModal.alert("Document deleted!", $.proxy(function(){
+ ConfirmModal.confirm("Are you sure you want to delete " + name + "?", function(){
+ this.documentModal.destroy(name, function(){
+ AlertModal.alert("Document deleted!", function(){
window.location.href = "/about"
- }, this))
- }, this))
- }, this))
+ }.bind(this))
+ }.bind(this))
+ }.bind(this))
// this.documentModal.destroy(name)
},
+
+ testWallpaper: function(e){
+ var content = document.getElementById("content")
+ content.style.width = "680px"
+ content.style.margin = "0 auto"
+ var wm = new WallpaperManager()
+ app.on('wallpaper-ready', function(){
+ var black = [0,0,0,0]
+ var white = [255,255,255,1.0]
+ var swatches = wm.buildSwatches(black, white, 4)
+ document.body.style.backgroundColor = "#eee"
+ swatches.forEach(function(swatch){
+ swatch.style.margin = "4px"
+ swatch.style.border = "1px solid lime"
+ swatch.style.backgroundColor = "#888"
+ content.appendChild(swatch)
+ swatch.onclick = function(){
+ dataUrl = swatch.toDataURL()
+ document.body.style.backgroundImage = "url(" + dataUrl + ")"
+ }
+ })
+ })
+ wm.init()
+ },
+
})
diff --git a/public/assets/javascripts/ui/builder/BuilderInfo.js b/public/assets/javascripts/ui/builder/BuilderInfo.js
new file mode 100644
index 0000000..9bbd385
--- /dev/null
+++ b/public/assets/javascripts/ui/builder/BuilderInfo.js
@@ -0,0 +1,160 @@
+
+var BuilderInfo = View.extend({
+ el: "#builderInfo",
+
+ events: {
+ "keydown": 'stopPropagation',
+ "change [name=x]": 'changePosition',
+ "change [name=y]": 'changePosition',
+ "change [name=width]": 'changeDimensions',
+ "change [name=depth]": 'changeDimensions',
+ "change [name=height]": 'changeDimensions',
+ "change [name=units]": 'changeUnits',
+ "change [name=resolution]": 'changeResolution',
+ "change [name=viewHeight]": 'changeViewHeight',
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+ this.$x = this.$("[name=x]")
+ this.$y = this.$("[name=y]")
+ this.$width = this.$("[name=width]")
+ this.$depth = this.$("[name=depth]")
+ this.$height = this.$("[name=height]")
+ this.$units = this.$("[name=units]")
+ this.$viewHeight = this.$("[name=viewHeight]")
+ this.$unitName = this.$(".unitName")
+ app.on("builder-pick-room", this.pick.bind(this))
+ app.on("builder-destroy-room", this.destroy.bind(this))
+ },
+
+ load: function(data){
+ this.$viewHeight.unitVal( data.viewHeight || app.defaults.viewHeight )
+ this.$units.val( "ft" )
+ this.$unitName.html( "ft" )
+ this.$resolution.val( app.defaults.footResolution )
+ },
+
+ toggle: function(state){
+ this.$el.toggleClass("active", state)
+ },
+
+ show: function(){
+ this.toggle(true)
+ },
+
+ hide: function(){
+ this.toggle(false)
+ },
+
+ room: null,
+
+ pick: function(room){
+ this.room = room
+ this.$width.unitVal( room.rect.x.length() )
+ this.$depth.unitVal( room.rect.y.length() )
+ this.$height.unitVal( room.height )
+ this.$x.unitVal( room.rect.x.a )
+ this.$y.unitVal( room.rect.y.a )
+
+ console.log(room)
+ },
+
+ destroy: function(room){
+ this.room = null
+ this.hide()
+ },
+
+ changeDimensions: function(){
+// this.$width.unitVal( room.rect.x.length() )
+// this.$depth.unitVal( room.rect.y.length() )
+// this.$height.unitVal( room.height )
+ },
+
+ changeUnits: function(){
+ app.units = this.$units.val()
+ this.$('.units').resetUnitVal()
+ },
+
+ changeViewHeight: function(){
+ window.viewHeight = this.$viewHeight.unitVal( )
+ },
+
+})
+
+$.fn.resetUnitVal = function(){
+ this.each(function(){
+ var n = $(this).data("px")
+ $(this).unitVal(n)
+ });
+}
+
+$.fn.unitVal = function(n){
+ var s
+ if (typeof n === "undefined") {
+ s = $(this).val()
+ n = stringToMeasurement( s )
+ }
+ s = measurementToString( n )
+ $(this).val( s ).data("px", n)
+ return n
+}
+
+function measurementToString( n ) {
+ var s, ft, inch
+ switch (app.units) {
+ case 'm':
+ s = round(n/36 * 0.3048 * 100) / 100 + " m"
+ break
+ case 'ft':
+ ft = floor(n / 36)
+ inch = abs(round((n % 36) / 3))
+ s = ft + "'"
+ if (inch > 0) {
+ s += " " + inch + '"'
+ }
+ break
+ case 'px':
+ default:
+ s = round(n) + " px"
+ break
+ }
+ return s
+}
+function stringToMeasurement( s ) {
+ var ft, inch, ft_in, type
+ if (s.indexOf("'") !== -1 || s.indexOf('"') !== -1 || s.indexOf('ft') !== -1) {
+ ft_in = s.match(/[0-9.]+/g)
+ if (ft_in.length >= 2) {
+ ft = parseFloat( ft_in[0] )
+ inch = parseFloat( ft_in[1] )
+ }
+ else if (ft_in.length == 1) {
+ if (s.indexOf('"') !== -1) {
+ ft = 0
+ inch = parseFloat( ft_in[0] )
+ }
+ else {
+ ft = parseFloat( ft_in[0] )
+ inch = 0
+ }
+ }
+ else {
+ ft = inch = 0
+ }
+ n = ft * 36 + inch * 3
+ }
+ else if (type === "m") {
+ n = parseFloat(s.match(/[0-9.]+/)) * 36 / 0.3048
+ }
+ else if (s.indexOf("px") !== -1) {
+ n = parseFloat(s.match(/[0-9.]+/))
+ }
+ else {
+ n = abs( stringToMeasurement( s + app.units ) )
+ }
+ if (s.indexOf('-') !== -1) {
+ n *= -1
+ }
+ return n
+} \ No newline at end of file
diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js
index 9b2f753..c551f95 100644
--- a/public/assets/javascripts/ui/builder/BuilderSettings.js
+++ b/public/assets/javascripts/ui/builder/BuilderSettings.js
@@ -2,11 +2,12 @@
var BuilderSettings = FormView.extend({
el: "#builderSettings",
- createAction: "/api/layouts/new",
- updateAction: "/api/layouts/edit",
- destroyAction: "/api/layouts/destroy",
+ createAction: "/api/layout/new",
+ updateAction: "/api/layout/edit",
+ destroyAction: "/api/layout/destroy",
events: {
+ "keydown": 'stopPropagation',
"keydown [name=name]": 'enterSubmit',
"click [data-role='save-layout']": 'save',
"click [data-role='clone-layout']": 'clone',
@@ -57,7 +58,7 @@ var BuilderSettings = FormView.extend({
destroy: function(){
var msg = "Are you sure you want to delete the layout " + sanitize(this.$name.val()) + "?"
- ConfirmModal.confirm(msg, $.proxy(function(){
+ ConfirmModal.confirm(msg, function(){
$.ajax({
url: this.destroyAction,
type: "delete",
@@ -66,11 +67,11 @@ var BuilderSettings = FormView.extend({
window.location.href = "/layout"
}
})
- }, this))
+ }.bind(this))
},
- toggle: function(){
- this.$el.toggleClass("active")
+ toggle: function(state){
+ this.$el.toggleClass("active", state)
},
enterSubmit: function (e) {
diff --git a/public/assets/javascripts/ui/builder/BuilderView.js b/public/assets/javascripts/ui/builder/BuilderView.js
index 33aface..555cd58 100644
--- a/public/assets/javascripts/ui/builder/BuilderView.js
+++ b/public/assets/javascripts/ui/builder/BuilderView.js
@@ -2,12 +2,13 @@
var BuilderView = View.extend({
el: "#builderView",
- action: "/api/layouts/",
+ action: "/api/layout/",
events: {
},
initialize: function(){
+ this.info = new BuilderInfo ({ parent: this })
this.toolbar = new BuilderToolbar ({ parent: this })
this.settings = new BuilderSettings ({ parent: this })
},
@@ -20,11 +21,15 @@ var BuilderView = View.extend({
name = sanitize(name)
- $.get(this.action + name, $.proxy(this.ready, this))
+ $.get(this.action + name, this.ready.bind(this))
},
ready: function(data){
this.settings.load(data)
+ this.info.load(data)
},
+
+ hideExtras: function(){
+ }
})
diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js
index b9f4560..13a6f60 100644
--- a/public/assets/javascripts/ui/editor/EditorSettings.js
+++ b/public/assets/javascripts/ui/editor/EditorSettings.js
@@ -2,11 +2,12 @@
var EditorSettings = FormView.extend({
el: "#editorSettings",
- createAction: "/api/projects/new",
- updateAction: "/api/projects/edit",
- destroyAction: "/api/projects/destroy",
+ createAction: "/api/project/new",
+ updateAction: "/api/project/edit",
+ destroyAction: "/api/project/destroy",
events: {
+ "keydown": 'stopPropagation',
"keydown [name=name]": 'enterSubmit',
"click [data-role='save-project']": 'save',
"click [data-role='clone-project']": 'clone',
@@ -32,7 +33,7 @@ var EditorSettings = FormView.extend({
data.startPosition && scene.camera.move(data.startPosition)
if (! data.isNew) {
- console.log(data)
+ // console.log(data)
this.$id.val( data._id )
this.$name.val( data.name )
@@ -65,7 +66,7 @@ var EditorSettings = FormView.extend({
destroy: function(){
var msg = "Are you sure you want to delete the project " + sanitize(this.$name.val()) + "?"
- ConfirmModal.confirm(msg, $.proxy(function(){
+ ConfirmModal.confirm(msg, function(){
$.ajax({
url: this.destroyAction,
type: "delete",
@@ -74,7 +75,7 @@ var EditorSettings = FormView.extend({
window.location.href = "/project"
}
})
- }, this))
+ }.bind(this))
},
toggle: function(){
diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js
index 210ef6c..a3abc5a 100644
--- a/public/assets/javascripts/ui/editor/EditorToolbar.js
+++ b/public/assets/javascripts/ui/editor/EditorToolbar.js
@@ -87,6 +87,7 @@ var EditorToolbar = View.extend({
var editor = new function(){
this.permissions = new Permissions({
+ 'pick': true,
'move': true,
'resize': false,
'destroy': false,
diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js
index b87ac83..4067c4d 100644
--- a/public/assets/javascripts/ui/editor/EditorView.js
+++ b/public/assets/javascripts/ui/editor/EditorView.js
@@ -2,8 +2,8 @@
var EditorView = View.extend({
el: "#editorView",
- projectAction: "/api/projects/",
- layoutAction: "/api/layouts/",
+ projectAction: "/api/project/",
+ layoutAction: "/api/layout/",
events: {
},
@@ -13,18 +13,19 @@ var EditorView = View.extend({
this.settings = new EditorSettings ({ parent: this })
this.mediaViewer = new MediaViewer ({ parent: this })
this.mediaUpload = new MediaUpload ({ parent: this })
+ this.mediaEditor = new MediaEditor ({ parent: this })
this.wallpaperPicker = new WallpaperPicker ({ parent: this })
this.lightControl = new LightControl ({ parent: this })
},
load: function(name){
name = sanitize(name)
- $.get(this.projectAction + name, $.proxy(this.ready, this))
+ $.get(this.projectAction + name, this.ready.bind(this))
},
loadLayout: function(layout){
layout = sanitize(layout)
- $.get(this.layoutAction + layout, $.proxy(this.readyLayout, this))
+ $.get(this.layoutAction + layout, this.readyLayout.bind(this))
},
ready: function(data){
@@ -36,7 +37,14 @@ var EditorView = View.extend({
readyLayout: function(data){
data.isNew = true
this.ready(data)
+ },
+
+ pick: function(scenery){
+ this.mediaEditor.pick(scenery)
+ },
+
+ hideExtras: function(){
+ this.mediaEditor.hide()
}
})
-
diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js
index 20c3577..93d97ed 100644
--- a/public/assets/javascripts/ui/editor/LightControl.js
+++ b/public/assets/javascripts/ui/editor/LightControl.js
@@ -3,6 +3,7 @@ var LightControl = View.extend({
el: ".lightcontrol",
events: {
+ "mousedown": "stopPropagation",
},
toggle: function(){
diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js
new file mode 100644
index 0000000..a075e6b
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/MediaEditor.js
@@ -0,0 +1,134 @@
+
+var MediaEditor = FormView.extend({
+ el: "#mediaEditor",
+
+ events: {
+ "keydown": 'stopPropagation',
+ "click [data-role=play-media]": "togglePaused",
+ "mousedown [name=keyframe]": "stopPropagation",
+ "mousedown": "stopPropagation",
+ "change [name=keyframe]": "seek",
+ "change [name=autoplay]": "setAutoplay",
+ "change [name=loop]": "setLoop",
+ "change [name=mute]": "setMute",
+ "click [data-role=destroy-media]": "destroy",
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+ this.__super__.initialize.call(this)
+
+ this.$name = this.$("[name=name]")
+ this.$description = this.$("[name=description]")
+
+ // image fields
+ this.$widthDimension = this.$("[name=width]")
+ this.$heightDimension = this.$("[name=height]")
+ this.$units = this.$("[name=units]")
+
+ // video fields
+ this.$playButton = this.$("[data-role=play-media]")
+ this.$autoplay = this.$("[name=autoplay]")
+ this.$loop = this.$("[name=loop]")
+ this.$mute = this.$("[name=mute]")
+ this.$keyframe = this.$("[name=keyframe]")
+ },
+
+ toggle: function(state) {
+ this.$el.toggleClass("active", state);
+ },
+
+ togglePaused: function(state){
+ var state = this.scenery.toggle(state)
+ this.$playButton.toggleClass("paused", ! state)
+ },
+
+ pick: function(scenery) {
+ if (this.scenery) {
+ this.unbind()
+ }
+
+ this.bind(scenery)
+ this.$el.addClass("active")
+
+ var media = scenery.media
+
+ this.$name.val(media.title)
+ this.$description.val(media.description)
+
+ switch (media.type) {
+ case "image":
+ this.$(".image").show()
+ this.$(".video").hide()
+
+ this.$widthDimension.val( Number(media.widthDimension) || "" )
+ this.$heightDimension.val( Number(media.heightDimension) || "" )
+ this.$units.val( media.units || "cm" )
+
+ break
+
+ case "youtube":
+ case "vimeo":
+ case "video":
+ this.$(".video").show()
+ this.$(".image").hide()
+
+ this.$playButton.toggleClass("paused", ! this.scenery.paused())
+ this.$autoplay.prop('checked', !! media.autoplay)
+ this.$loop.prop('checked', !! media.loop)
+ this.$mute.prop('checked', !! media.mute)
+ this.$keyframe.val( Number(media.keyframe || 0) )
+
+ break
+ }
+ },
+
+ hide: function(scenery){
+ if (this.scenery) {
+ this.unbind()
+ }
+ this.toggle(false)
+ },
+
+ seek: function(){
+ var n = parseFloat( this.$keyframe.val() )
+ this.scenery.seek(n)
+
+ this.scenery.media.keyframe = n
+ },
+ setAutoplay: function(){
+ var checked = this.$autoplay.prop('checked')
+ this.scenery.media.autoplay = checked
+ if (checked && this.scenery.paused()) {
+ this.togglePaused()
+ }
+ },
+ setLoop: function(){
+ var checked = this.$loop.prop('checked')
+ this.scenery.media.loop = checked
+ },
+ setMute: function(){
+ var checked = this.$mute.prop('checked')
+ this.scenery.media.mute = checked
+ this.scenery.mute(checked)
+ },
+
+ bind: function(scenery){
+ this.scenery = scenery
+ this.scenery.mx.bound = true
+ },
+
+ unbind: function(){
+ this.scenery.mx.bound = false
+ this.scenery = null
+ },
+
+ destroy: function(){
+ ConfirmModal.confirm("Are you sure you want to this media?", function(){
+ var scenery = this.scenery
+ this.hide()
+ Scenery.remove(scenery.id)
+ }.bind(this))
+ },
+
+})
diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js
index b7fea07..86bf767 100644
--- a/public/assets/javascripts/ui/editor/MediaUpload.js
+++ b/public/assets/javascripts/ui/editor/MediaUpload.js
@@ -39,7 +39,7 @@ var MediaUpload = View.extend({
var url = this.$url.val()
this.$url.val("")
- Parser.parse(url, $.proxy(function(media){
+ Parser.parse(url, function(media){
if (! media) {
alert("Not a valid image/video link")
return
@@ -53,8 +53,8 @@ var MediaUpload = View.extend({
url: this.createAction,
data: media,
})
- request.done($.proxy(this.add, this))
- }, this))
+ request.done(this.add.bind(this))
+ }.bind(this))
},
handleFileSelect: function(e) {
@@ -109,7 +109,7 @@ var MediaUpload = View.extend({
processData: false,
contentType: false,
})
- request.done($.proxy(this.add, this))
+ request.done(this.add.bind(this))
},
add: function(media){
diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js
index 2535f1b..264ed7c 100644
--- a/public/assets/javascripts/ui/editor/MediaViewer.js
+++ b/public/assets/javascripts/ui/editor/MediaViewer.js
@@ -40,12 +40,12 @@ var MediaViewer = ModalView.extend({
},
load: function(){
- $.get("/api/media/user", $.proxy(this.populate, this))
+ $.get("/api/media/user", this.populate.bind(this))
},
populate: function(data){
this.loaded = true
- data && data.forEach($.proxy(this.add, this))
+ data && data.forEach(this.add.bind(this))
this.__super__.show.call(this)
},
@@ -62,6 +62,15 @@ var MediaViewer = ModalView.extend({
case 'vimeo':
image.src = media.thumbnail
break
+
+ case 'video':
+ image = document.createElement('video')
+ image.addEventListener("loadedmetadata", function(){
+ image.currentTime = image.duration * 1/3
+ })
+ image.src = media.url
+ image.load()
+ break
}
$span.data("media", media)
@@ -124,7 +133,16 @@ var MediaViewer = ModalView.extend({
var $floatingImg = $('.floatingImg');
Scenery.nextMedia = media
- $floatingImg.attr('src', image.attr('src'));
+
+ switch (media.type) {
+ case "video":
+ $floatingImg.attr('src', 'http://www.rawrcast.com/wp-content/uploads/2010/02/BluePlayButton.png')
+ break
+
+ default:
+ $floatingImg.attr('src', image.attr('src'))
+ break
+ }
var height = $floatingImg.height()
var width = $floatingImg.width()
diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js
index ffbd935..cb1e361 100644
--- a/public/assets/javascripts/ui/editor/WallpaperPicker.js
+++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js
@@ -3,7 +3,24 @@ var WallpaperPicker = View.extend({
el: ".wallpaper",
events: {
- "click .paper1": 'pick',
+ "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()
},
toggle: function(){
@@ -13,8 +30,116 @@ var WallpaperPicker = View.extend({
},
pick: function(e){
- $("body").toggleClass("pastePaper");
- $(e.currentTarget).toggleClass("active");
+ var $swatch = $(e.currentTarget)
+ var $floatingSwatch = $(".floatingSwatch")
+
+ $floatingSwatch.css('background-image', $swatch.css('background-image'))
+
+ Scenery.nextWallpaper = $swatch.css('background-image')
+
+ setTimeout(function(){
+ function _followCursor(e) {
+ $floatingSwatch.css({
+ top: (e.pageY + 10) + 'px',
+ left: (e.pageX + 10) + 'px'
+ });
+ }
+ $(window).on('mousemove', _followCursor);
+ $(window).one('click', function () {
+ $(window).off('mousemove', _followCursor);
+ $floatingSwatch.hide();
+ });
+ $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 0106ce0..219952d 100644
--- a/public/assets/javascripts/ui/lib/FormView.js
+++ b/public/assets/javascripts/ui/lib/FormView.js
@@ -26,9 +26,9 @@ var FormView = View.extend({
this.$errorList.append('<div>' + errors[i] + '</div>');
}
this.$errors.css("opacity", 1.0);
- setTimeout($.proxy(function(){
+ setTimeout(function(){
this.$errors.show().css("opacity", 1.0);
- }, this), 200)
+ }.bind(this), 200)
}
},
diff --git a/public/assets/javascripts/ui/lib/Parser.js b/public/assets/javascripts/ui/lib/Parser.js
index 705ff04..dfff7b2 100644
--- a/public/assets/javascripts/ui/lib/Parser.js
+++ b/public/assets/javascripts/ui/lib/Parser.js
@@ -2,12 +2,18 @@ var Parser = {
integrations: [{
type: 'image',
regex: /\.(jpeg|jpg|gif|png|svg)(\?.*)?$/i,
- async: false,
fetch: function(url, done) {
var img = new Image ()
img.onload = function(){
- done("", "", img.naturalWidth, img.naturalHeight, "")
+ var width = img.naturalWidth, height = img.naturalHeight
img = null
+ done({
+ token: "",
+ thumbnail: "",
+ title: "",
+ width: width,
+ height: height,
+ })
}
img.src = url
if (img.complete) {
@@ -18,9 +24,30 @@ var Parser = {
return '<img src="' + media.url + '" onerror="imgError(this);">';
}
}, {
+ type: 'video',
+ regex: /\.(mp4|webm)(\?.*)?$/i,
+ fetch: function(url, done) {
+ var video = document.createElement("video")
+ video.addEventListener("loadedmetadata", function(){
+ var width = video.videoWidth, height = video.videoHeight
+ video = null
+ done({
+ token: "",
+ thumbnail: "",
+ title: "",
+ width: width,
+ height: height,
+ })
+ })
+ video.src = url
+ video.load()
+ },
+ tag: function (media) {
+ return '<video src="' + media.url + '" onerror="imgError(this);">';
+ }
+ }, {
type: 'youtube',
regex: /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,
- async: false,
fetch: function(url, done) {
var id = (url.match(/v=([-_a-zA-Z0-9]{11})/i) || url.match(/youtu.be\/([-_a-zA-Z0-9]{11})/i) || url.match(/embed\/([-_a-zA-Z0-9]{11})/i))[1].split('&')[0];
var thumb = "http://i.ytimg.com/vi/" + id + "/hqdefault.jpg"
@@ -34,8 +61,14 @@ var Parser = {
part: "id,contentDetails,snippet,status",
},
success: function(result){
- var res = res.items[0]
- done(id, thumb, 640, 360, res.snippet.title);
+ var res = result.items[0]
+ done({
+ token: id,
+ thumbnail: thumb,
+ title: res.snippet.title,
+ width: 640,
+ height: 360,
+ })
}
})
},
@@ -45,7 +78,6 @@ var Parser = {
}, {
type: 'vimeo',
regex: /vimeo.com\/\d+$/i,
- async: true,
fetch: function(url, done) {
var id = url.match(/\d+$/i)[0];
$.ajax({
@@ -54,7 +86,13 @@ var Parser = {
success: function(result){
if (result.length == 0) { return done(id, "", 640, 360) }
var res = result[0]
- done(id, res.thumbnail_large, res.width, res.height, res.title)
+ done({
+ token: id,
+ thumbnail: res.thumbnail_large,
+ title: res.title,
+ width: res.width,
+ height: res.height,
+ })
}
})
},
@@ -66,7 +104,6 @@ var Parser = {
{
type: 'soundcloud',
regex: /soundcloud.com\/[-a-zA-Z0-9]+\/[-a-zA-Z0-9]+\/?$/i,
- async: true,
fetch: function (url, done) {
$.ajax({
type: 'GET',
@@ -75,7 +112,13 @@ var Parser = {
+ '&client_id='
+ '0673fbe6fc794a7750f680747e863b10',
success: function(result) {
- done(result.id, "");
+ done({
+ token: result.id,
+ thumbnail: "",
+ title: "",
+ width: 100,
+ height: 100,
+ })
}
});
},
@@ -87,9 +130,14 @@ var Parser = {
}, {
type: 'link',
regex: /^http.+/i,
- async: false,
fetch: function(url, done) {
- done("", "")
+ done({
+ token: "",
+ thumbnail: "",
+ title: "",
+ width: 100,
+ height: 100,
+ })
},
tag: function (media) {
return '<a href="' + media.url + '" target="_blank">' + media.url + '</a>'
@@ -101,16 +149,10 @@ var Parser = {
parse: function (url, cb) {
var matched = Parser.integrations.some(function(integration){
if (integration.regex.test(url)) {
- integration.fetch(url, function(token, thumbnail, width, height, title){
- cb({
- token: token,
- thumbnail: thumbnail,
- type: integration.type,
- title: title,
- width: width,
- height: height,
- url: url,
- })
+ integration.fetch(url, function(res){
+ res.url = url
+ res.type = integration.type
+ cb(res)
})
return true
}
diff --git a/public/assets/javascripts/ui/lib/Router.js b/public/assets/javascripts/ui/lib/Router.js
index 214603c..d27654a 100644
--- a/public/assets/javascripts/ui/lib/Router.js
+++ b/public/assets/javascripts/ui/lib/Router.js
@@ -10,6 +10,10 @@ var Router = View.extend({
path[i] = null
}
}
+
+ if (path[path.length-1] == null) {
+ path.pop()
+ }
for (var route in this.routes) {
var routePath = route.split("/")
diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js
index 5fc6736..999a0e5 100644
--- a/public/assets/javascripts/ui/lib/View.js
+++ b/public/assets/javascripts/ui/lib/View.js
@@ -84,7 +84,11 @@ var View = (function($, _){
preventDefault: function(e){
e && e.preventDefault()
- }
+ },
+
+ stopPropagation: function(e){
+ e && e.stopPropagation()
+ },
});
diff --git a/public/assets/javascripts/ui/reader/MediaPlayer.js b/public/assets/javascripts/ui/reader/MediaPlayer.js
new file mode 100644
index 0000000..df2d075
--- /dev/null
+++ b/public/assets/javascripts/ui/reader/MediaPlayer.js
@@ -0,0 +1,100 @@
+
+var MediaPlayer = FormView.extend({
+ el: "#mediaPlayer",
+
+ events: {
+ "click [data-role=play-media]": "togglePaused",
+ "click [data-role=mute-media]": "toggleMuted",
+ "mousedown": "stopPropagation",
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+ this.__super__.initialize.call(this)
+
+ this.$name = this.$(".name")
+ this.$description = this.$(".description")
+
+ // image fields
+ this.$dimensions = this.$(".dimensions")
+
+ // video fields
+ this.$playButton = this.$("[data-role=play-media]")
+ this.$muteButton = this.$("[data-role=mute-media]")
+ },
+
+ toggle: function(state) {
+ this.$el.toggleClass("active", state);
+ },
+
+ togglePaused: function(state){
+ var state = this.scenery.toggle(state)
+ this.$playButton.toggleClass("paused", ! state)
+ },
+
+ toggleMuted: function(state){
+ var state = this.scenery.toggleMuted(state)
+ this.$muteButton.toggleClass("muted", state)
+ },
+
+ pick: function(scenery) {
+ var media = scenery.media
+
+ if (this.scenery) {
+ this.unbind()
+ }
+ if (media.type == "image") {
+ if ((! media.title || ! media.title.length) && (! media.description || ! media.description.length)) {
+ this.hide()
+ return
+ }
+ }
+
+ this.bind(scenery)
+ this.$el.addClass("active")
+
+ this.$name.html(media.title)
+ this.$description.html(media.description)
+
+ switch (media.type) {
+ case "image":
+ this.$(".image").show()
+ this.$(".video").hide()
+
+// this.$widthDimension.html( Number(media.widthDimension) || "" )
+// this.$heightDimension.html( Number(media.heightDimension) || "" )
+// this.$units.html( media.units || "cm" )
+
+ break
+
+ case "youtube":
+ case "vimeo":
+ case "video":
+ this.$(".video").show()
+ this.$(".image").hide()
+
+ this.$playButton.toggleClass("paused", ! this.scenery.paused())
+ this.$muteButton.toggleClass("muted", this.scenery.muted())
+
+ break
+ }
+ },
+
+ hide: function(scenery){
+ if (this.scenery) {
+ this.unbind()
+ }
+ this.toggle(false)
+ },
+
+ bind: function(scenery){
+ this.scenery = scenery
+ this.scenery.mx.bound = true
+ },
+
+ unbind: function(){
+ this.scenery.mx.bound = false
+ this.scenery = null
+ },
+
+})
diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js
index 001d097..9d38daa 100644
--- a/public/assets/javascripts/ui/reader/ReaderView.js
+++ b/public/assets/javascripts/ui/reader/ReaderView.js
@@ -2,17 +2,24 @@
var ReaderView = View.extend({
el: "#readerView",
- projectAction: "/api/projects/",
+ projectAction: "/api/project/",
events: {
},
initialize: function(){
+ this.mediaPlayer = new MediaPlayer ({ parent: this })
},
load: function(name){
+ if (window.location.search.indexOf("noui") !== -1) {
+ $(".logo,.topLinks,#editorView").hide()
+ }
+ if (window.location.search.indexOf("mute") !== -1) {
+ app.muted = true
+ }
name = sanitize(name)
- $.get(this.projectAction + name, $.proxy(this.ready, this))
+ $.get(this.projectAction + name, this.ready.bind(this))
},
ready: function(data){
@@ -23,6 +30,45 @@ var ReaderView = View.extend({
data.startPosition && scene.camera.move(data.startPosition)
editor.permissions.clear()
+
+ this.listen()
+ },
+
+ listen: function(){
+ var base = this
+
+ $(window).on('message', function(event){
+ if (event.originalEvent.origin !== window.location.origin) {
+ return
+ }
+ var message = event.originalEvent.data
+ switch (message) {
+ case "spin-on":
+ base.spinning = true
+ break
+ case "spin-off":
+ base.spinning = false
+ break
+ }
+ })
+
+ requestAnimationFrame(this.spin.bind(this))
+ },
+
+ spinning: false,
+ spin: function(){
+ requestAnimationFrame(this.spin.bind(this))
+ if (this.spinning) {
+ scene.camera.rotationY -= 1/180
+ }
+ },
+
+ pick: function(scenery){
+ this.mediaPlayer.pick(scenery)
+ },
+
+ hideExtras: function(){
+ this.mediaPlayer.hide()
}
})
diff --git a/public/assets/javascripts/ui/site/DocumentModal.js b/public/assets/javascripts/ui/site/DocumentModal.js
index 6f16169..067977d 100644
--- a/public/assets/javascripts/ui/site/DocumentModal.js
+++ b/public/assets/javascripts/ui/site/DocumentModal.js
@@ -20,7 +20,7 @@ var DocumentModal = ModalFormView.extend({
this.action = this.updateAction
- $.get("/api/docs", { name: name }, $.proxy(function(data){
+ $.get("/api/docs", { name: name }, function(data){
if (data.isNew) {
this.action = this.createAction
}
@@ -31,7 +31,7 @@ var DocumentModal = ModalFormView.extend({
this.$("[name='new_name']").val(name)
this.show()
- }, this))
+ }.bind(this))
},
success: function(res){
diff --git a/public/assets/javascripts/ui/site/EditProfileModal.js b/public/assets/javascripts/ui/site/EditProfileModal.js
index 6b89ad8..b023923 100644
--- a/public/assets/javascripts/ui/site/EditProfileModal.js
+++ b/public/assets/javascripts/ui/site/EditProfileModal.js
@@ -6,7 +6,7 @@ var EditProfileModal = ModalFormView.extend({
load: function(){
this.reset()
- $.get("/api/profile", $.proxy(function(data){
+ $.get("/api/profile", function(data){
console.log(data)
for (var i in data) {
@@ -23,7 +23,7 @@ var EditProfileModal = ModalFormView.extend({
}
this.show()
- }, this))
+ }.bind(this))
},
validate: function(){
diff --git a/public/assets/javascripts/ui/site/EditProjectModal.js b/public/assets/javascripts/ui/site/EditProjectModal.js
index 356d8b7..20baa54 100644
--- a/public/assets/javascripts/ui/site/EditProjectModal.js
+++ b/public/assets/javascripts/ui/site/EditProjectModal.js
@@ -31,7 +31,7 @@ var EditProjectModal = ModalView.extend({
var fields = this.$form.serializeArray()
var request = $.post(this.action, $.param(fields));
- request.done($.proxy(function (response) {
+ request.done(function (response) {
if (response.error) {
this.$errors.show();
for (var key in response.error.errors) {
@@ -42,7 +42,7 @@ var EditProjectModal = ModalView.extend({
else {
window.location.href = "/profile"
}
- }, this));
+ }.bind(this));
}
})
diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js
index 46ed634..4948b0e 100644
--- a/public/assets/javascripts/ui/site/LayoutsModal.js
+++ b/public/assets/javascripts/ui/site/LayoutsModal.js
@@ -3,23 +3,30 @@ var LayoutsIndex = View.extend({
initialize: function(){
this.$templates = this.$(".templates")
+ this.$noTemplates = this.$(".no-templates")
+ this.$form = this.$("form")
},
load: function(type){
this.$templates.children("span").remove()
- $.get(this.action, $.proxy(this.populate, this))
+ $.get(this.action, this.populate.bind(this))
},
populate: function(data){
- data.forEach($.proxy(function(room){
+ if (! data.length) {
+ this.$templates.hide()
+ this.$form.hide()
+ this.$noTemplates.show()
+ }
+ data.forEach(function(room){
var $span = $("<span>")
// $span.html(JSON.stringify(room))
$span.data("slug", room.slug)
$span.css("background-image", "url(" + room.photo + ")")
this.$templates.append($span)
- }, this))
+ }.bind(this))
this.show()
}
@@ -28,7 +35,7 @@ var LayoutsIndex = View.extend({
var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({
el: ".mediaDrawer.projects",
- action: "/api/projects",
+ action: "/api/project",
events: {
"click .templates span": 'toggleActive',
@@ -65,7 +72,7 @@ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({
var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({
el: ".mediaDrawer.layouts",
- action: "/api/layouts",
+ action: "/api/layout",
events: {
"click .templates span": 'toggleActive',
@@ -93,7 +100,7 @@ var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({
var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({
el: ".mediaDrawer.newProject",
- action: "/api/layouts",
+ action: "/api/layout",
events: {
"click .templates span": 'toggleActive',
diff --git a/public/assets/javascripts/ui/site/PasswordForgot.js b/public/assets/javascripts/ui/site/PasswordForgot.js
new file mode 100644
index 0000000..ecbfc07
--- /dev/null
+++ b/public/assets/javascripts/ui/site/PasswordForgot.js
@@ -0,0 +1,26 @@
+var PasswordForgot = ModalFormView.extend({
+ el: ".mediaDrawer.passwordForgot",
+ action: "/auth/forgotPassword",
+
+ validate: function(){
+ var errors = []
+
+ var email = this.$("#emailInput").val()
+
+ if (! email.length) {
+ errors.push("Please enter your email address");
+ }
+ if (email.indexOf("@") === -1) {
+ errors.push("Sorry, that is not a valid email address");
+ }
+
+ return errors
+ },
+
+ success: function(res){
+ AlertModal.alert("Check your email, you should receive further instructions momentarily.", function(e){
+ window.location.href = "/"
+ })
+ },
+
+})
diff --git a/public/assets/javascripts/ui/site/PasswordReset.js b/public/assets/javascripts/ui/site/PasswordReset.js
new file mode 100644
index 0000000..9b87d37
--- /dev/null
+++ b/public/assets/javascripts/ui/site/PasswordReset.js
@@ -0,0 +1,31 @@
+var PasswordReset = ModalFormView.extend({
+ el: ".mediaDrawer.passwordReset",
+ action: "/auth/password",
+
+ load: function(){
+ var opt = JSON.parse( $("#opt").html() )
+ this.$("[name=nonce]").val( opt.nonce )
+ this.__super__.load.call(this)
+ },
+
+ validate: function(){
+ var errors = []
+
+ var pw1 = this.$("#passwordInput1").val()
+ var pw2 = this.$("#passwordInput2").val()
+
+ if (! pw1.length) {
+ errors.push("Please enter a password");
+ }
+ if (pw1 !== pw2) {
+ errors.push("Passwords don't match");
+ }
+
+ return errors
+ },
+
+ success: function(res){
+ window.location.href = "/profile"
+ }
+
+})
diff --git a/public/assets/javascripts/ui/site/ProfileView.js b/public/assets/javascripts/ui/site/ProfileView.js
new file mode 100644
index 0000000..8661bcd
--- /dev/null
+++ b/public/assets/javascripts/ui/site/ProfileView.js
@@ -0,0 +1,28 @@
+
+var ProfileView = View.extend({
+
+ initialize: function() {
+ },
+
+ load: function() {
+ var classes = ['one', 'two', 'three', 'four',
+ 'five', 'six', 'seven', 'eight',
+ 'nine', 'ten', 'eleven', 'twelve',
+ 'thirteen'];
+ $(".bio").addClass(choice(classes));
+
+ $("td.border").each(function() {
+ var iframe = $(this).find("iframe").get('0')
+ if (! iframe) return
+ $(this).on({
+ mouseenter: function(e){
+ iframe.contentWindow.postMessage("spin-on", window.location.origin)
+ },
+ mouseleave: function(e){
+ iframe.contentWindow.postMessage("spin-off", window.location.origin)
+ }
+ })
+ })
+ }
+
+})
diff --git a/public/assets/javascripts/ui/site/UsernameTaken.js b/public/assets/javascripts/ui/site/UsernameTaken.js
new file mode 100644
index 0000000..fc9f50a
--- /dev/null
+++ b/public/assets/javascripts/ui/site/UsernameTaken.js
@@ -0,0 +1,27 @@
+var UsernameTaken = ModalFormView.extend({
+ el: ".mediaDrawer.usernameTaken",
+ action: "/auth/usernameTaken",
+
+ load: function(){
+ var opt = JSON.parse( $("#opt").html() )
+ this.$("#usernameThatIsTaken").html( opt.username )
+ this.__super__.load.call(this)
+ },
+
+ validate: function(){
+ var errors = []
+
+ var username = this.$("#usernameInput").val()
+
+ if (! username.length) {
+ errors.push("Please enter a username");
+ }
+
+ return errors
+ },
+
+ success: function(res){
+ window.location.href = "/profile"
+ }
+
+})