From d50fa94e9b758270b15dfeb5100063c6d876d64c Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 15 Oct 2014 12:04:00 -0400 Subject: cursor that follows mouse --- public/assets/javascripts/rectangles/engine/rooms/_walls.js | 2 +- public/assets/javascripts/rectangles/engine/rooms/mover.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js index 119a659..f2348f0 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_walls.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -135,7 +135,7 @@ } base.luminance = function(rgb){ - rgb = rgb || Walls.colors.wall + rgb = rgb || Walls.colors.ceiling var rgb_max = Math.max.apply(0, rgb) var rgb_min = Math.min.apply(255, rgb) return (rgb_max + rgb_min ) / 2 diff --git a/public/assets/javascripts/rectangles/engine/rooms/mover.js b/public/assets/javascripts/rectangles/engine/rooms/mover.js index a2d2223..dd63db2 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/mover.js +++ b/public/assets/javascripts/rectangles/engine/rooms/mover.js @@ -11,7 +11,8 @@ Rooms.mover = new function(){ base.bind = function(){ app.on("move", base.update) - keys.on("backslash", function(){ + keys.on("backslash", function(e){ + if ( ! (e.ctrlKey || e.metaKey) ) return base.noclip = ! base.noclip base.room = null app.movements.gravity( ! base.noclip ) -- cgit v1.2.3-70-g09d2 From dd6b2cc2cdd97b6163d115e5415736bccbffa831 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 15 Oct 2014 12:36:52 -0400 Subject: get rid of menu options --- public/assets/javascripts/rectangles/engine/map/ui_editor.js | 5 +++-- public/assets/javascripts/ui/editor/EditorToolbar.js | 10 +++++----- public/assets/javascripts/ui/editor/HelpCursor.js | 8 ++++++-- views/controls/builder/info.ejs | 5 ++++- views/controls/editor/light-control.ejs | 7 ++++++- views/controls/editor/presets.ejs | 12 ++++-------- views/controls/editor/toolbar.ejs | 4 ++++ views/controls/editor/wallpaper.ejs | 3 +++ 8 files changed, 35 insertions(+), 19 deletions(-) (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/rectangles/engine/map/ui_editor.js b/public/assets/javascripts/rectangles/engine/map/ui_editor.js index 072ff7e..44e416d 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_editor.js +++ b/public/assets/javascripts/rectangles/engine/map/ui_editor.js @@ -213,7 +213,8 @@ Map.UI.Editor = function(map){ if (intersects.length) { wheelState = wheelState || intersects[0].copy() - intersects[0].height = clamp( ~~(intersects[0].height - deltaY), height_min, height_max ) + intersects[0].height = clamp( ~~(intersects[0].height + deltaY * 2), height_min, height_max ) + app.tube("builder-pick-room", intersects[0]) clearTimeout(wheelTimeout) wheelTimeout = setTimeout(function(){ @@ -224,7 +225,7 @@ Map.UI.Editor = function(map){ }) Rooms.rebuild() wheelState = null - }, 500) + }, 250) } else { map.set_zoom(map.zoom_exponent - deltaY/20) diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 4f07d1f..9c2f3d3 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -30,11 +30,11 @@ var EditorToolbar = View.extend({ }, toggleMap: function(state){ - if (typeof state != "boolean") { - state = ! $("[data-role='toggle-map-view']").hasClass("inuse") - this.resetControls() - } - $("[data-role='toggle-map-view']").toggleClass("inuse", state) +// if (typeof state != "boolean") { +// state = ! $("[data-role='toggle-map-view']").hasClass("inuse") +// this.resetControls() +// } +// $("[data-role='toggle-map-view']").toggleClass("inuse", state) map.toggle(state) $("#minimap").toggleClass("hide", state) this.parent.info.toggle(state) diff --git a/public/assets/javascripts/ui/editor/HelpCursor.js b/public/assets/javascripts/ui/editor/HelpCursor.js index 842e871..b2f411d 100644 --- a/public/assets/javascripts/ui/editor/HelpCursor.js +++ b/public/assets/javascripts/ui/editor/HelpCursor.js @@ -3,8 +3,12 @@ var HelpCursor = View.extend({ el: "#helpCursor", messages: { - start: "Welcome to Vvalls!", - move: "Use the up and down keys to move around. Use left and right to pivot. WASD works too.", + start: "Welcome to Vvalls! Click one of the tools at right to learn how it works.", + media: "This is where you pick media to go on the walls. You can upload media, paste links, or use some of the found media.", + presets: "These presets will affect on all the walls. Click some of them to see the walls change.", + wallpaper: "Drag the wallpaper onto the walls, floor, and ceiling.", + colors: "", + settings: "This is where you publish your project.", }, shown: {}, diff --git a/views/controls/builder/info.ejs b/views/controls/builder/info.ejs index 205938f..54bb38e 100644 --- a/views/controls/builder/info.ejs +++ b/views/controls/builder/info.ejs @@ -2,7 +2,10 @@

Map Editor

- Click a room to select it, or click and drag to make a new room. + Click and drag to make a new room. + Click a room to select it. +

+ Press ESC to toggle the map.
diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index 8b20464..4604a7a 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -1,6 +1,11 @@

Edit Room Colors

-
+ +

Preset Colors

+
+
+ +
diff --git a/views/controls/editor/presets.ejs b/views/controls/editor/presets.ejs index 70e48e3..8dd1986 100644 --- a/views/controls/editor/presets.ejs +++ b/views/controls/editor/presets.ejs @@ -1,18 +1,14 @@
-

Preset Colors

-
-
-

Preset Styles

- - Wireframe + + Inverse Shaded - - Inverse + + Wireframe P.Funk diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index 57a98b9..1bb31b8 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -1,9 +1,11 @@ +
+
-- cgit v1.2.3-70-g09d2 From 9ae4f45f24e3e79aeb32e0a128ee798381b80569 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Wed, 15 Oct 2014 22:35:48 -0400 Subject: more help text --- public/assets/javascripts/defaults.js | 2 +- public/assets/javascripts/rectangles/engine/rooms/builder.js | 2 +- public/assets/javascripts/ui/editor/HelpCursor.js | 8 +++++--- public/assets/javascripts/ui/editor/MediaViewer.js | 5 ++++- public/assets/javascripts/ui/editor/Presets.js | 4 ++-- public/assets/stylesheets/app.css | 2 ++ 6 files changed, 15 insertions(+), 8 deletions(-) (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/defaults.js b/public/assets/javascripts/defaults.js index 9ba0b4d..12aed62 100644 --- a/public/assets/javascripts/defaults.js +++ b/public/assets/javascripts/defaults.js @@ -3,7 +3,7 @@ app.defaults = { units: app.units = "ft", footResolution: 36, meterResolution: 100, - wallOpacity: 0.95, + wallOpacity: 0.98, outlineWidth: 2, colors: { wall: [255,255,255], diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index 33333fb..c95734b 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -280,7 +280,7 @@ return el } this.make_wall = function (klass) { - // klass += ".backface-hidden" + 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/ui/editor/HelpCursor.js b/public/assets/javascripts/ui/editor/HelpCursor.js index 8bfaef8..9b6807e 100644 --- a/public/assets/javascripts/ui/editor/HelpCursor.js +++ b/public/assets/javascripts/ui/editor/HelpCursor.js @@ -5,9 +5,11 @@ var HelpCursor = View.extend({ active: false, messages: { - start: "Welcome to Vvalls! Click one of the tools at right to learn how it works.", - media: "This is where you pick media to go on the walls. You can upload media, paste links, or use some of the found media.", - presets: "These presets will affect on all the walls. Click some of them to see the walls change.", + start: "Welcome to Vvalls! Click one of the tools at right to learn about it.", + media: "This is where you pick media to go on the walls. You can upload media and paste links.", + addmedia: "Great, now click a wall to place this image.", + resize: "Drag the image to position it, or use the dots to resize.", + presets: "These are some basic presets to get you started. Click em! :-)", wallpaper: "Drag the wallpaper onto the walls, floor, and ceiling.", colors: "Use these colors to change the color of the walls, floor, and ceiling.", settings: "This is where you publish your project. Give it a name, hit save, and you'll have a URL you can share with your friends.", diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index e196e41..8cae4a4 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -77,6 +77,7 @@ var MediaViewer = ModalView.extend({ this.__super__.hide.call(this) this.deleteArmed(false) this.parent.mediaUpload.hide() + this.parent.cursor.message('start') }, load: function(){ @@ -232,7 +233,8 @@ var MediaViewer = ModalView.extend({ } this.hide() - + this.parent.cursor.message('addmedia') + var $ants = $('.ants'); var $floatingImg = $('.floatingImg'); @@ -267,6 +269,7 @@ var MediaViewer = ModalView.extend({ $(window).off('mousedown', _hideCursor) app.off('cancel-scenery', _hideCursor) $floatingImg.parent().removeClass('edit') + app.controller.cursor.message('resize') } $(window).on('mousemove', _followCursor) $(window).on('mousedown', _hideCursor) diff --git a/public/assets/javascripts/ui/editor/Presets.js b/public/assets/javascripts/ui/editor/Presets.js index 35b5b58..4edc957 100644 --- a/public/assets/javascripts/ui/editor/Presets.js +++ b/public/assets/javascripts/ui/editor/Presets.js @@ -39,11 +39,11 @@ var Presets = View.extend({ }, toggle: function(state){ - this.$el.toggleClass("active", state); + this.$el.toggleClass("active", state) + this.parent.cursor.message(state ? "presets" : "start") }, show: function(){ - this.parent.cursor.message("presets") this.toggle(true) }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 250ae67..1ab1198 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1676,6 +1676,7 @@ input[type="range"]::-webkit-slider-thumb { cursor:pointer; border-bottom: 1px transparent solid; } +.presets span:hover, .presets span.active { text-decoration: underline; } @@ -1728,6 +1729,7 @@ input[type="range"]::-webkit-slider-thumb { padding: 4px; font-weight: 500; z-index: 22; + display: none; } .settings.info { -- cgit v1.2.3-70-g09d2 From f885f2caca46af82ae49149e361a25e3419fedc0 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Wed, 15 Oct 2014 23:40:12 -0400 Subject: fix wallpaper tiling bug --- .../assets/javascripts/rectangles/models/wall.js | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 7ff9015..2ee88d9 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -260,24 +260,34 @@ this.background.y = background.y || this.background.y this.background.scale = background.scale || this.background.scale || 1 - var useX = this.side & FRONT_BACK - var shouldFlip = this.side & (LEFT | BACK) - var mx, dx, dy var w = Math.round( this.backgroundImage.naturalWidth * this.background.scale ) var h = Math.round( this.backgroundImage.naturalHeight * this.background.scale ) this.surface.faces.forEach(function(face, i){ - - if (shouldFlip) { - mx = this.mx[this.mx.length-1-i] - dx = Math.round( this.background.x + face.x.a ) - dy = Math.round( this.background.y + face.y.b ) - } - else { - mx = this.mx[i] - dx = Math.round( this.background.x - face.x.b ) - dy = Math.round( this.background.y + face.y.b ) + // this.mx[i].el.innerHTML = sidesToString(this.side) + + switch (this.side) { + case LEFT: + mx = this.mx[this.mx.length-1-i] + dx = Math.round( this.background.x + face.x.a ) + dy = Math.round( this.background.y + face.y.b ) + break + case RIGHT: + mx = this.mx[this.mx.length-1-i] + dx = Math.round( this.background.x + face.x.b ) + dy = Math.round( this.background.y + face.y.b ) + break + case FRONT: + mx = this.mx[this.mx.length-1-i] + dx = Math.round( this.background.x + face.x.b ) + dy = Math.round( this.background.y + face.y.b ) + break + case BACK: + mx = this.mx[i] + dx = Math.round( this.background.x - face.x.a ) + dy = Math.round( this.background.y + face.y.b ) + break } mx.el.style.backgroundPosition = dx + 'px ' + dy + 'px' @@ -286,7 +296,6 @@ } Wall.prototype.outline = function(wallColor, outlineColor){ - var useX = this.side & FRONT_BACK var mx = this.mx var len = this.mx.length -- cgit v1.2.3-70-g09d2 From a7fe78b6059e3568d38876ba68e650b841912125 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Thu, 16 Oct 2014 00:48:22 -0400 Subject: unfocus ui on esc --- public/assets/javascripts/rectangles/engine/map/_map.js | 2 +- public/assets/javascripts/rectangles/engine/map/ui_editor.js | 12 ++++++++++-- public/assets/javascripts/ui/editor/EditorToolbar.js | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/rectangles/engine/map/_map.js b/public/assets/javascripts/rectangles/engine/map/_map.js index 3a47dab..64372c5 100644 --- a/public/assets/javascripts/rectangles/engine/map/_map.js +++ b/public/assets/javascripts/rectangles/engine/map/_map.js @@ -67,7 +67,7 @@ var Map = function(opt){ } base.toggle = function(state){ - $(base.el).toggle(state) + return $(base.el).toggle(state).is(':visible') } } diff --git a/public/assets/javascripts/rectangles/engine/map/ui_editor.js b/public/assets/javascripts/rectangles/engine/map/ui_editor.js index 44e416d..9d69990 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_editor.js +++ b/public/assets/javascripts/rectangles/engine/map/ui_editor.js @@ -26,6 +26,13 @@ Map.UI.Editor = function(map){ resize: true, destroy: false, }) + + base.blur = function(){ + Rooms.forEach(function(r){ + return r.focused = false + }) + app.tube("builder-pick-nothing") + } // @@ -190,7 +197,7 @@ Map.UI.Editor = function(map){ }) Rooms.rebuild() } - + var intersects = Rooms.filter(function(r){ return r.focused = r.rect.contains(cursor.x.a, cursor.y.a) }) @@ -207,7 +214,7 @@ Map.UI.Editor = function(map){ var cursor = base.mouse.cursor var intersects = Rooms.filter(function(r){ - return r.focused = r.rect.contains(cursor.x.a, cursor.y.a) + return r.focused // = r.rect.contains(cursor.x.a, cursor.y.a) }) if (intersects.length) { @@ -234,4 +241,5 @@ Map.UI.Editor = function(map){ function rightclick (e){ } + } diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 9c2f3d3..a460bbf 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -35,7 +35,8 @@ var EditorToolbar = View.extend({ // this.resetControls() // } // $("[data-role='toggle-map-view']").toggleClass("inuse", state) - map.toggle(state) + var state = map.toggle(state) + if (state) { map.ui.blur() } $("#minimap").toggleClass("hide", state) this.parent.info.toggle(state) }, -- cgit v1.2.3-70-g09d2 From 513a272520222784d67dc22c1ac833aa47a9c844 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Thu, 16 Oct 2014 00:58:28 -0400 Subject: rename light control to color control --- .../javascripts/mx/extensions/mx.movements.js | 4 +- .../javascripts/rectangles/engine/scenery/undo.js | 2 +- .../javascripts/ui/builder/BuilderSettings.js | 2 +- .../assets/javascripts/ui/builder/BuilderView.js | 2 +- .../assets/javascripts/ui/editor/ColorControl.js | 305 +++++++++++++++++++++ .../assets/javascripts/ui/editor/EditorSettings.js | 4 +- .../assets/javascripts/ui/editor/EditorToolbar.js | 20 +- public/assets/javascripts/ui/editor/EditorView.js | 2 +- .../assets/javascripts/ui/editor/LightControl.js | 305 --------------------- public/assets/javascripts/ui/editor/Presets.js | 2 +- public/assets/stylesheets/app.css | 6 +- views/controls/editor/color-control.ejs | 28 ++ views/controls/editor/light-control.ejs | 28 -- views/controls/editor/toolbar.ejs | 2 +- views/editor.ejs | 2 +- views/partials/scripts.ejs | 2 +- 16 files changed, 358 insertions(+), 358 deletions(-) create mode 100644 public/assets/javascripts/ui/editor/ColorControl.js delete mode 100644 public/assets/javascripts/ui/editor/LightControl.js create mode 100644 views/controls/editor/color-control.ejs delete mode 100644 views/controls/editor/light-control.ejs (limited to 'public/assets/javascripts/rectangles') diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js index 40e786d..c2a2473 100644 --- a/public/assets/javascripts/mx/extensions/mx.movements.js +++ b/public/assets/javascripts/mx/extensions/mx.movements.js @@ -131,8 +131,8 @@ MX.Movements = function (cam) { app.controller.mediaViewer.hide() $(".inuse").removeClass("inuse") } - else if (app.controller.lightControl.$el.hasClass('active')) { - app.controller.lightControl.hide() + else if (app.controller.colorControl.$el.hasClass('active')) { + app.controller.colorControl.hide() $(".inuse").removeClass("inuse") } else if (app.controller.wallpaperPicker.$el.hasClass('active')) { diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index bee8c49..ff4f911 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -122,7 +122,7 @@ type: "update-colors", undo: function(state){ Walls.setColor[ state.mode ]( state.rgb ) - app.router.editorView.lightControl.setSwatchColor( state.mode, state.rgb ) + app.router.editorView.colorControl.setSwatchColor( state.mode, state.rgb ) Minotaur.watch( app.router.editorView.settings ) }, diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index fe67e9b..c8c8880 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -30,7 +30,7 @@ var BuilderSettings = FormView.extend({ this.$id.val(data._id) this.$name.val(data.name) - this.parent.lightControl.loadDefaults() + this.parent.colorControl.loadDefaults() data.rooms && Rooms.deserialize(data.rooms) data.startPosition && scene.camera.move(data.startPosition) diff --git a/public/assets/javascripts/ui/builder/BuilderView.js b/public/assets/javascripts/ui/builder/BuilderView.js index a89111f..735274e 100644 --- a/public/assets/javascripts/ui/builder/BuilderView.js +++ b/public/assets/javascripts/ui/builder/BuilderView.js @@ -11,7 +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 }) + this.colorControl = new ColorControl ({ parent: this }) }, load: function(name){ diff --git a/public/assets/javascripts/ui/editor/ColorControl.js b/public/assets/javascripts/ui/editor/ColorControl.js new file mode 100644 index 0000000..26358f1 --- /dev/null +++ b/public/assets/javascripts/ui/editor/ColorControl.js @@ -0,0 +1,305 @@ + +var ColorControl = View.extend({ + el: ".colorcontrol", + + events: { + "mousedown": "stopPropagation", + "click .color-swatches span": "select", + "mousedown #brightness-control": "beginBrightness", + "input #brightness-control": "updateBrightness", + }, + + colors: [ + [255,94,58], + [255,149,0], + [255,219,76], + [76,217,100], + [52,170,220], + [29,98,240], + [198,68,252], + [0,0,0], + [74,74,74], + [125,126,127], + [209,211,212], + [235,235,235], + [255,255,255], + ], + + initialize: function(opt){ + this.parent = opt.parent + + this.colorPicker = new LabColorPicker(this, 180, 180) + this.$("#color-picker").append( this.colorPicker.canvas ) + this.$("#color-picker").append( this.colorPicker.cursor ) + + 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") + + this.$colors = this.$(".colors") + this.colors.forEach(function(color){ + var $swatch = $("") + $swatch.css("background-color","rgb(" + color + ")") + $swatch.data('color', color) + this.$colors.append($swatch) + }.bind(this)) + + }, + + modes: [ "wall", "outline", "floor", "ceiling" ], + + load: function(data){ + this.modes.forEach(function(mode){ + Walls.setColor[mode](data[mode]) + this.$swatch[ mode ].css("background-color", rgb_string(data[mode])) + }.bind(this)) + this.setMode("wall") + }, + + loadDefaults: function(){ + var colors = { + wall: app.defaults.colors.wall.slice(), + outline: app.defaults.colors.outline.slice(), + floor: app.defaults.colors.floor.slice(), + ceiling: app.defaults.colors.ceiling.slice(), + } + this.load(colors) + }, + + toggle: function(state){ + this.$el.toggleClass("active", state); + }, + + show: function(){ + this.parent.cursor.message("colors") + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + pick: function(rgb, Lab){ + this.labColor = Lab + this.setSwatchColor(this.mode, rgb) + // console.log(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 + + // TODO: watch individual wall object here + Minotaur.watch( app.router.editorView.settings ) + }, + + setMode: function (mode) { + var color, brightness + this.mode = mode + this.$(".active").removeClass("active") + this.$swatch[ mode ].parent().addClass("active") + color = Walls.colors[ mode ] + + this.labColor = this.colorPicker.load(color) + this.$brightnessControl.val( this.labColor[0] ) + }, + + select: function(e){ + var mode = $('.swatch', 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) + }, + +}) + +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 ww = w-1 + var hh = h-1 + + var L_range = [0, 110] + var a_range = [-86.185, 98.254] + var b_range = [-107.863, 94.482] + + var rgb = [0,0,0] + + var val = 80 + + this.mouse = new mouse({ + el: canvas, + down: function(e, cursor){ + parent.begin() + cursor.x.a = -cursor.x.a + base.pick(cursor.x.a, cursor.y.a) + }, + drag: function(e, cursor){ + cursor.x.b = -cursor.x.b + base.pick(cursor.x.b, cursor.y.b) + }, + up: function(){ + parent.finalize() + } + }) + + this.setLab = function(Lab) { + val = Lab[0] + this.paint() + var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round) + return rgb + } + this.pick = function(i, j){ + i = clamp(i, 0, w) + j = clamp(j, 0, h) + 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) + this.moveCursor(i, j) + 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 ) + + this.moveCursor(x,y) + this.setLab(Lab) + return Lab + } + this.moveCursor = function(x,y){ + cursor.style.left = x + "px" + cursor.style.top = y + "px" + } + 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 = Math.pow( ( var_R + 0.055 ) / 1.055, 2.4) + else var_R = var_R / 12.92 + if ( var_G > 0.04045 ) var_G = Math.pow( ( var_G + 0.055 ) / 1.055, 2.4) + else var_G = var_G / 12.92 + if ( var_B > 0.04045 ) var_B = Math.pow( ( var_B + 0.055 ) / 1.055, 2.4) + else var_B = var_B / 12.92 + + var_R = var_R * 100 + var_G = var_G * 100 + var_B = var_B * 100 + + //Observer. = 2°, Illuminant = D65 + var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 + var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 + var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 + return [x,y,z] + } + function xyz2hunterlab (XYZ) { + var X = XYZ[0] + var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) + var Z = XYZ[2] + var L = 10 * sqrt( Y ) + var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) + var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) + return [L,a,b] + } +} diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index c0c140f..664b102 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -45,10 +45,10 @@ var EditorSettings = FormView.extend({ } if (data.colors && data.colors.wall) { - this.parent.lightControl.load(data.colors) + this.parent.colorControl.load(data.colors) } else { - this.parent.lightControl.loadDefaults() + this.parent.colorControl.loadDefaults() } if (data.walls) { diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index a460bbf..dceae3c 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -10,7 +10,7 @@ var EditorToolbar = View.extend({ "click [data-role='open-media-viewer']": 'openMediaViewer', "click [data-role='toggle-presets']": 'togglePresets', "click [data-role='toggle-wallpaper-panel']": 'toggleWallpaper', - "click [data-role='toggle-light-control']": 'toggleLightControl', + "click [data-role='toggle-color-control']": 'toggleColorControl', "click [data-role='toggle-text-editor']": 'toggleTextEditor', }, @@ -46,7 +46,7 @@ var EditorToolbar = View.extend({ this.toggleMap(false) this.parent.textEditor.hide() this.parent.presets.hide() - this.parent.lightControl.hide() + this.parent.colorControl.hide() this.parent.wallpaperPicker.hide() this.parent.mediaEditor.hide() this.parent.settings.toggle() @@ -75,7 +75,7 @@ var EditorToolbar = View.extend({ this.parent.textEditor.hide() this.parent.wallpaperPicker.hide() this.parent.presets.hide() - this.parent.lightControl.hide() + this.parent.colorControl.hide() this.parent.settings.hide() }, @@ -111,7 +111,7 @@ var EditorToolbar = View.extend({ this.resetMode() $("[data-role='toggle-wallpaper-panel']").toggleClass("inuse", state) this.parent.mediaEditor.hide() - this.parent.lightControl.hide() + this.parent.colorControl.hide() this.parent.textEditor.hide() this.parent.settings.hide() this.parent.presets.hide() @@ -119,17 +119,17 @@ var EditorToolbar = View.extend({ this.parent.wallpaperPicker.toggle(state) }, - toggleLightControl: function(){ - var state = ! $("[data-role='toggle-light-control']").hasClass("inuse") + toggleColorControl: function(){ + var state = ! $("[data-role='toggle-color-control']").hasClass("inuse") this.resetMode() - $("[data-role='toggle-light-control']").toggleClass("inuse", state) + $("[data-role='toggle-color-control']").toggleClass("inuse", state) this.parent.mediaEditor.hide() this.parent.wallpaperPicker.hide() this.parent.textEditor.hide() this.parent.settings.hide() this.parent.presets.hide() this.toggleMap(false) - this.parent.lightControl.toggle(state) + this.parent.colorControl.toggle(state) }, toggleTextEditor: function(){ @@ -138,7 +138,7 @@ var EditorToolbar = View.extend({ $("[data-role='toggle-text-editor']").toggleClass("inuse", state) this.parent.mediaEditor.hide() this.parent.wallpaperPicker.hide() - this.parent.lightControl.hide() + this.parent.colorControl.hide() this.parent.settings.hide() this.parent.presets.hide() this.toggleMap(false) @@ -153,7 +153,7 @@ var EditorToolbar = View.extend({ this.parent.wallpaperPicker.hide() this.parent.textEditor.hide() this.parent.settings.hide() - this.parent.lightControl.hide() + this.parent.colorControl.hide() this.toggleMap(false) this.parent.presets.toggle(state) }, diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 05d1bec..9946feb 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -17,7 +17,7 @@ var EditorView = View.extend({ this.mediaUpload = new MediaUpload ({ parent: this }) this.mediaEditor = new MediaEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) - this.lightControl = new LightControl ({ parent: this }) + this.colorControl = new ColorControl ({ parent: this }) this.textEditor = new TextEditor ({ parent: this }) this.collaborators = new Collaborators ({ parent: this }) this.presets = new Presets ({ parent: this }) diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js deleted file mode 100644 index 10f8d2c..0000000 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ /dev/null @@ -1,305 +0,0 @@ - -var LightControl = View.extend({ - el: ".lightcontrol", - - events: { - "mousedown": "stopPropagation", - "click .color-swatches span": "select", - "mousedown #brightness-control": "beginBrightness", - "input #brightness-control": "updateBrightness", - }, - - colors: [ - [255,94,58], - [255,149,0], - [255,219,76], - [76,217,100], - [52,170,220], - [29,98,240], - [198,68,252], - [0,0,0], - [74,74,74], - [125,126,127], - [209,211,212], - [235,235,235], - [255,255,255], - ], - - initialize: function(opt){ - this.parent = opt.parent - - this.colorPicker = new LabColorPicker(this, 180, 180) - this.$("#color-picker").append( this.colorPicker.canvas ) - this.$("#color-picker").append( this.colorPicker.cursor ) - - 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") - - this.$colors = this.$(".colors") - this.colors.forEach(function(color){ - var $swatch = $("") - $swatch.css("background-color","rgb(" + color + ")") - $swatch.data('color', color) - this.$colors.append($swatch) - }.bind(this)) - - }, - - modes: [ "wall", "outline", "floor", "ceiling" ], - - load: function(data){ - this.modes.forEach(function(mode){ - Walls.setColor[mode](data[mode]) - this.$swatch[ mode ].css("background-color", rgb_string(data[mode])) - }.bind(this)) - this.setMode("wall") - }, - - loadDefaults: function(){ - var colors = { - wall: app.defaults.colors.wall.slice(), - outline: app.defaults.colors.outline.slice(), - floor: app.defaults.colors.floor.slice(), - ceiling: app.defaults.colors.ceiling.slice(), - } - this.load(colors) - }, - - toggle: function(state){ - this.$el.toggleClass("active", state); - }, - - show: function(){ - this.parent.cursor.message("colors") - this.toggle(true) - }, - - hide: function(){ - this.toggle(false) - }, - - pick: function(rgb, Lab){ - this.labColor = Lab - this.setSwatchColor(this.mode, rgb) - // console.log(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 - - // TODO: watch individual wall object here - Minotaur.watch( app.router.editorView.settings ) - }, - - setMode: function (mode) { - var color, brightness - this.mode = mode - this.$(".active").removeClass("active") - this.$swatch[ mode ].parent().addClass("active") - color = Walls.colors[ mode ] - - this.labColor = this.colorPicker.load(color) - this.$brightnessControl.val( this.labColor[0] ) - }, - - select: function(e){ - var mode = $('.swatch', 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) - }, - -}) - -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 ww = w-1 - var hh = h-1 - - var L_range = [0, 110] - var a_range = [-86.185, 98.254] - var b_range = [-107.863, 94.482] - - var rgb = [0,0,0] - - var val = 80 - - this.mouse = new mouse({ - el: canvas, - down: function(e, cursor){ - parent.begin() - cursor.x.a = -cursor.x.a - base.pick(cursor.x.a, cursor.y.a) - }, - drag: function(e, cursor){ - cursor.x.b = -cursor.x.b - base.pick(cursor.x.b, cursor.y.b) - }, - up: function(){ - parent.finalize() - } - }) - - this.setLab = function(Lab) { - val = Lab[0] - this.paint() - var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round) - return rgb - } - this.pick = function(i, j){ - i = clamp(i, 0, w) - j = clamp(j, 0, h) - 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) - this.moveCursor(i, j) - 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 ) - - this.moveCursor(x,y) - this.setLab(Lab) - return Lab - } - this.moveCursor = function(x,y){ - cursor.style.left = x + "px" - cursor.style.top = y + "px" - } - 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 = Math.pow( ( var_R + 0.055 ) / 1.055, 2.4) - else var_R = var_R / 12.92 - if ( var_G > 0.04045 ) var_G = Math.pow( ( var_G + 0.055 ) / 1.055, 2.4) - else var_G = var_G / 12.92 - if ( var_B > 0.04045 ) var_B = Math.pow( ( var_B + 0.055 ) / 1.055, 2.4) - else var_B = var_B / 12.92 - - var_R = var_R * 100 - var_G = var_G * 100 - var_B = var_B * 100 - - //Observer. = 2°, Illuminant = D65 - var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 - var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 - var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 - return [x,y,z] - } - function xyz2hunterlab (XYZ) { - var X = XYZ[0] - var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) - var Z = XYZ[2] - var L = 10 * sqrt( Y ) - var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) - var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) - return [L,a,b] - } -} diff --git a/public/assets/javascripts/ui/editor/Presets.js b/public/assets/javascripts/ui/editor/Presets.js index 4edc957..a3dc610 100644 --- a/public/assets/javascripts/ui/editor/Presets.js +++ b/public/assets/javascripts/ui/editor/Presets.js @@ -54,7 +54,7 @@ var Presets = View.extend({ selectPreset: function(e){ var preset = $(e.currentTarget).data('preset') if (! this.presets[preset]) return - this.parent.lightControl.load(this.presets[preset]) + this.parent.colorControl.load(this.presets[preset]) this.$(".active").removeClass('active') $(e.currentTarget).addClass('active') }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 1ab1198..d7999b9 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1582,7 +1582,7 @@ border-left: 1px solid black; /* COLOR PICKER */ -.lightcontrol { +.colorcontrol { margin-top: 8%; right: 80px; padding: 13px 20px 20px 20px; @@ -1592,11 +1592,11 @@ border-left: 1px solid black; transition: -webkit-transform 0.2s ease-in-out; } -.lightcontrol.active { +.colorcontrol.active { -webkit-transform: translateX(0px); transform: translateX(0px); } -.lightcontrol .slider { +.colorcontrol .slider { } h4 { font-weight:300; diff --git a/views/controls/editor/color-control.ejs b/views/controls/editor/color-control.ejs new file mode 100644 index 0000000..040808e --- /dev/null +++ b/views/controls/editor/color-control.ejs @@ -0,0 +1,28 @@ +
+

Edit Room Colors

+ +
+
+ + + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs deleted file mode 100644 index 99d68f5..0000000 --- a/views/controls/editor/light-control.ejs +++ /dev/null @@ -1,28 +0,0 @@ -
-

Edit Room Colors

- -
-
- - - -
- -
- -
- -
-
- -
-
- -
-
- -
-
-
-
diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index 1bb31b8..7b08db6 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -29,7 +29,7 @@ data-info="add wallpaper" class="ion-ios7-keypad-outline">