Permalink
Browse files

make every element editable

  • Loading branch information...
maccman committed Apr 17, 2012
1 parent 087fcc7 commit 1b762f81fe5558230b81bdf48a8f0b0881b07a57
@@ -19,6 +19,7 @@ class Element extends Spine.Controller
elementEvents:
'mousedown': 'toggleSelect'
+ 'dblclick': 'startEditing'
constructor: (attrs = {}) ->
super(el: attrs.el)
@@ -30,6 +31,8 @@ class Element extends Spine.Controller
@selected = !!attrs.selected
@resizing = new Resizing(this)
+ @text(attrs.text) if attrs.text
+
@set @defaults()
@set attrs.properties or attrs
@@ -72,6 +75,9 @@ class Element extends Spine.Controller
# Selecting elements
toggleSelect: (e) ->
+ # Disable selection when editing
+ return if @editing
+
if @selected
@el.trigger('deselect.element', [this, e?.shiftKey])
else
@@ -81,9 +87,43 @@ class Element extends Spine.Controller
if bool?
@selected = bool
@el.toggleClass('selected', bool)
+
+ @stopEditing() unless bool
@resizing.toggle(bool)
+
@selected
+ # Text editing
+
+ startEditing: ->
+ return if @editing
+ @editing = true
+
+ # We don't want the element to be
+ # resizable, or draggable
+ @resizing.toggle(false)
+ @el.removeClass('selected')
+ @el.addClass('editing')
+
+ # Enable text editing and select text
+ @el.attr('contenteditable', true)
+ @el.focus()
+ document.execCommand('selectAll', false, null)
+
+ stopEditing: ->
+ return unless @editing
+ @editing = false
+
+ @el.blur()
+ @el.removeAttr('contenteditable')
+ @el.scrollTop(0)
+ @el.addClass('selected')
+ @el.removeClass('editing')
+
+ text: (text) ->
+ @el.text(text) if text?
+ @el.text()
+
# Position & Area
area: ->
@@ -145,5 +185,6 @@ class Element extends Spine.Controller
result =
selected: @selected
properties: @properties
+ text: @text()
module.exports = Element
@@ -6,7 +6,6 @@ class Text extends Rectangle
id: module.id
events:
- 'dblclick': 'startEditing'
'dblclick .thumb.br': 'fitToText'
defaults: ->
@@ -17,47 +16,15 @@ class Text extends Rectangle
$.extend({}, super, result)
- constructor: (attrs = {}) ->
- super
- @text(attrs.text)
-
- startEditing: ->
- return if @editing
- @editing = true
-
- # We don't want the element to be
- # resizable, or draggable
- @resizing.toggle(false)
- @el.removeClass('selected')
- @el.addClass('editing')
- @el.css(height: 'auto')
-
- # Enable text editing and select text
- @el.attr('contenteditable', true)
- @el.focus()
- document.execCommand('selectAll', false, null)
-
stopEditing: ->
return unless @editing
- @editing = false
-
- @el.blur()
- @el.removeAttr('contenteditable')
- @el.scrollTop(0)
- @el.addClass('selected')
- @el.removeClass('editing')
- @set(height: @el.outerHeight())
-
- # Remove the element if empty
- @remove() unless @text()
-
- toggleSelect: ->
- return if @editing
super
- setSelected: (bool) ->
- @stopEditing() unless bool
- super
+ if @text()
+ @fitToText()
+ else
+ # Remove the element if empty
+ @remove()
fitToText: ->
@el.css(width: 'auto', height: 'auto')
@@ -66,13 +33,4 @@ class Text extends Rectangle
height: @el.outerHeight()
)
- text: (text) ->
- @el.text(text) if text?
- @el.text()
-
- toValue: ->
- result = super
- result.text = @text()
- result
-
module.exports = Text
@@ -38,8 +38,6 @@ class SelectArea extends Spine.Controller
# Only listen to mousedown's on the stage
return if e.target isnt e.currentTarget
- e.preventDefault()
-
@offset = @el.offset()
@offset.left -= @el.scrollLeft()
@offset.top -= @el.scrollTop()
@@ -48,6 +46,7 @@ class SelectArea extends Spine.Controller
$(document).mousemove(@drag)
$(document).mouseup(@drop)
+ true
drag: (e) =>
# We offset by 1, so it doesn't
@@ -72,11 +71,13 @@ class SelectArea extends Spine.Controller
@stage.selection.add(element)
else
@stage.selection.remove(element)
+ true
drop: (e) =>
@selectArea?.release()
@selectArea = null
$(document).unbind('mousemove', @drag)
$(document).unbind('mouseup', @drop)
+ true
module.exports = SelectArea
@@ -10,20 +10,25 @@
// background: url('bg-grid.png')
background: #FFF
overflow: auto
- // -webkit-user-select: text
+ -webkit-user-select: none
.element {
border-box()
color: #000
+ outline: none
}
- .element.text.editing, .element.text.selected {
- outline: 1px solid rgba(0, 0, 0, 0.2)
+ .element.editing {
+ -webkit-user-select: text
}
.element.text {
white-space: nowrap
padding: 5px
+
+ &.editing, &.selected {
+ outline: 1px solid rgba(0, 0, 0, 0.2)
+ }
}
.resizing .thumb {
@@ -98,7 +98,8 @@ this.require.define({"app/controllers/element":function(exports, require, module
};
Element.prototype.elementEvents = {
- 'mousedown': 'toggleSelect'
+ 'mousedown': 'toggleSelect',
+ 'dblclick': 'startEditing'
};
function Element(attrs) {
@@ -115,6 +116,9 @@ this.require.define({"app/controllers/element":function(exports, require, module
this.properties = {};
this.selected = !!attrs.selected;
this.resizing = new Resizing(this);
+ if (attrs.text) {
+ this.text(attrs.text);
+ }
this.set(this.defaults());
this.set(attrs.properties || attrs);
}
@@ -165,6 +169,9 @@ this.require.define({"app/controllers/element":function(exports, require, module
};
Element.prototype.toggleSelect = function(e) {
+ if (this.editing) {
+ return;
+ }
if (this.selected) {
return this.el.trigger('deselect.element', [this, e != null ? e.shiftKey : void 0]);
} else {
@@ -176,11 +183,46 @@ this.require.define({"app/controllers/element":function(exports, require, module
if (bool != null) {
this.selected = bool;
this.el.toggleClass('selected', bool);
+ if (!bool) {
+ this.stopEditing();
+ }
this.resizing.toggle(bool);
}
return this.selected;
};
+ Element.prototype.startEditing = function() {
+ if (this.editing) {
+ return;
+ }
+ this.editing = true;
+ this.resizing.toggle(false);
+ this.el.removeClass('selected');
+ this.el.addClass('editing');
+ this.el.attr('contenteditable', true);
+ this.el.focus();
+ return document.execCommand('selectAll', false, null);
+ };
+
+ Element.prototype.stopEditing = function() {
+ if (!this.editing) {
+ return;
+ }
+ this.editing = false;
+ this.el.blur();
+ this.el.removeAttr('contenteditable');
+ this.el.scrollTop(0);
+ this.el.addClass('selected');
+ return this.el.removeClass('editing');
+ };
+
+ Element.prototype.text = function(text) {
+ if (text != null) {
+ this.el.text(text);
+ }
+ return this.el.text();
+ };
+
Element.prototype.area = function() {
var area;
area = {};
@@ -244,7 +286,8 @@ this.require.define({"app/controllers/element":function(exports, require, module
var result;
return result = {
selected: this.selected,
- properties: this.properties
+ properties: this.properties,
+ text: this.text()
};
};
Oops, something went wrong.

0 comments on commit 1b762f8

Please sign in to comment.