Permalink
Browse files

added undo managing and pairs file

  • Loading branch information...
1 parent 40c1228 commit 2d1fbc5401477564ed47111b98b473e4d78c5405 Jeremy Jackson & Terrence Lee committed May 17, 2011
View
16 .pairs
@@ -0,0 +1,16 @@
+pairs:
+ aw: Alex Welch; alex.welch
+ an: Anthony Navarre; anthony.navarre
+ jz: Jay Zeschin; jay.zeschin
+ br: Brian Rose; brian.rose
+ dp: Don Petersen; don.petersen
+ jj: Jeremy Jackson; jeremy.jackson
+ aj: Andrew Jaswa; andrew.jaswa
+ jg: Justin Gitlin; justin.gitlin
+ gv: Gabe Varela; gabe.varela
+ mk: Matt Kitt; matt.kitt
+ cw: Craig Williams; craig.williams
+ tl: Terrence Lee; terrence.lee
+email:
+ prefix: pair
+ domain: factorylabs.com
@@ -64,7 +64,7 @@ class CarmentaEditor
type = region.data('type').titleize()
@regions.push(new Carmenta.Regions[type](region, {window: @iframe.get(0).contentWindow}))
catch error
- alert(error)
+ alert(error) if Carmenta.debug
alert("Region type is malformed, no data-type provided, or \"#{type}\" is unknown.")
@@ -1,5 +1,29 @@
-class HistoryBuffer extends Array
+class Carmenta.HistoryBuffer
- constructor: ->
- @push(arguments)
+ constructor: (@maxLength = 200) ->
+ @index = 0
+ @stack = []
+
+ push: (item) ->
+ return if @stack[@index] && @stack[@index].replace(/<em class="carmenta-marker"><\/em>/g, '') == item.replace(/<em class="carmenta-marker"><\/em>/g, '') # if it's the same, don't do anything
+
+ @stack = @stack[0...@index + 1]
+ @stack.push(item)
+ @stack.shift() if @stack.length > @maxLength
+ @index = @stack.length - 1
+
+ console.debug('----------------------------------------------------------------', @stack.length)
+ console.debug(@stack[0...@stack.length])
+
+
+ undo: ->
+ return null if @index < 1
+ @index -= 1
+ return @stack[@index]
+
+
+ redo: ->
+ return null if @index > @stack.length - 2
+ @index += 1
+ return @stack[@index]
@@ -10,9 +10,10 @@ class Carmenta.Regions.Editable
@window = @options.window
@document = @window.document
@type = @element.data('type')
- @history = new HistoryBuffer()
+ @history = new Carmenta.HistoryBuffer()
@build()
@bindEvents()
+ @pushHistory()
build: ->
@@ -29,19 +30,22 @@ class Carmenta.Regions.Editable
# mozilla: there's some weird behavior when the element isn't a div
@specialContainer = $.browser.mozilla && @element.get(0).tagName != 'DIV'
- # make it editable and add the basic editor settings
+ # make it editable
@element.get(0).contentEditable = true
- @execCommand('styleWithCSS', {value: false})
- @execCommand('insertBROnReturn', {value: true})
- @execCommand('enableInlineTableEditing', {value: false})
- @execCommand('enableObjectResizing', {value: false})
+
+ # add the basic editor settings to the document (only once)
+ unless @document.carmentaEditing
+ @document.execCommand('styleWithCSS', false, false)
+ @document.execCommand('insertBROnReturn', false, true)
+ @document.execCommand('enableInlineTableEditing', false, false)
+ @document.execCommand('enableObjectResizing', false, false)
+ @document.carmentaEditing = true
bindEvents: ->
Carmenta.bind 'focus:frame', =>
return unless Carmenta.region == @
@focus()
- Carmenta.trigger('region:update', {region: @})
Carmenta.bind 'action', (event, options) =>
return unless Carmenta.region == @
@@ -59,25 +63,38 @@ class Carmenta.Regions.Editable
@element.focus =>
Carmenta.region = @
+ Carmenta.trigger('region:focused', {region: @})
@element.blur =>
- Carmenta.trigger('region:blur', {region: @})
+ Carmenta.trigger('region:blurred', {region: @})
@element.mouseup =>
+ @pushHistory()
Carmenta.trigger('region:update', {region: @})
@element.keydown (event) =>
Carmenta.changes = true
switch event.keyCode
+ when 90 # undo / redo
+ return unless event.metaKey
+ event.preventDefault()
+ if event.shiftKey
+ @execCommand('redo')
+ else
+ @pushHistory()
+ @execCommand('undo')
+
+ return
+
when 13 # enter
if $.browser.webkit
event.preventDefault()
- @execCommand('insertlinebreak')
+ @document.execCommand('insertlinebreak', false, null)
else if @specialContainer
# mozilla: pressing enter in any elemeny besides a div handles strangely
- @execCommand('insertHTML', {value: '<br/>'})
event.preventDefault()
+ @document.execCommand('insertHTML', false, '<br/>')
when 90 # undo and redo
break unless event.metaKey
@@ -111,17 +128,29 @@ class Carmenta.Regions.Editable
@execCommand('underline')
event.preventDefault()
+ @pushHistory(event.keyCode)
@element.keyup =>
- Carmenta.trigger('region:update', {region: @})
+# Carmenta.trigger('region:update', {region: @})
- html: (value = null) ->
+ html: (value = null, includeMarker = false) ->
if value
@element.html(value)
+ @selection().selectMarker(@element)
else
@element.find('meta').remove()
- @element.html().replace(/^\s+|\s+$/g, '')
+ if includeMarker
+ selection = @selection()
+ selection.placeMarker()
+
+ # sanitizes the html before we return it
+ container = $('<div>').appendTo(@document.createDocumentFragment())
+ container.html(@element.html().replace(/^\s+|\s+$/g, ''))
+ html = container.html()
+
+ selection.removeMarker() if includeMarker
+ return html
selection: ->
@@ -130,6 +159,7 @@ class Carmenta.Regions.Editable
focus: ->
@element.focus()
+ Carmenta.trigger('region:update', {region: @})
path: ->
@@ -165,26 +195,55 @@ class Carmenta.Regions.Editable
execCommand: (action, options = {}) ->
- @element.focus
+ @element.focus()
+ @pushHistory() unless action == 'undo' || action == 'redo'
+
+ Carmenta.log('execCommand', action, options.value)
# use a custom handler if there's one, otherwise use execCommand
if handler = Carmenta.config.behaviors[action] || Carmenta.Regions.Editable.actions[action]
handler.call(@, @selection(), options)
else
sibling = @element.get(0).previousSibling if action == 'indent'
options.value = $('<div>').html(options.value).html() if action == 'insertHTML' && options.value && options.value.get
- Carmenta.log('execCommand', action, options.value)
try
@document.execCommand(action, false, options.value)
catch error
# mozilla: indenting when there's no br tag handles strangely
@element.prev().remove() if action == 'indent' && @element.prev() != sibling
+ pushHistory: (keyCode) ->
+ # when pressing return, delete or backspace it should push to the history
+ # all other times it should store if there's a 1 second pause
+ keyCodes = [13, 46, 8]
+ waitTime = 2.5
+ knownKeyCode = keyCodes.indexOf(keyCode) if keyCode
+
+ # clear any pushes to the history
+ clearTimeout(@historyTimeout)
+
+ # if the key code was return, delete, or backspace store now -- unless it was the same as last time
+ if knownKeyCode >= 0 && knownKeyCode != @lastKnownKeyCode # || !keyCode
+ @history.push(@html(null, true))
+ else if keyCode
+ # set a timeout for pushing to the history
+ @historyTimeout = setTimeout((=> @history.push(@html(null, true))), waitTime * 1000)
+ else
+ # push to the history immediately
+ @history.push(@html(null, true))
+
+ @lastKnownKeyCode = knownKeyCode
+
+
# Custom handled actions (eg. things that execCommand doesn't do, or doesn't do well)
Carmenta.Regions.Editable.actions =
+ undo: -> @html(@history.undo())
+
+ redo: -> @html(@history.redo())
+
removeformatting: (selection) -> selection.insertTextNode(selection.textContent())
backcolor: (selection, options) -> selection.wrap("<span style=\"background-color:#{options.value.toHex()}\">", true)
@@ -27,6 +27,46 @@ class Carmenta.Regions.Editable.Selection
return @range.cloneContents()
+ selectMarker: (context) ->
+ markers = context.find('em.carmenta-marker')
+ return unless markers.length
+
+ range = @context.createRange()
+ range.setStartBefore(markers.get(0))
+ range.setEndBefore(markers.get(1)) if markers.length >= 2
+
+ markers.remove()
+
+ @selection.removeAllRanges()
+ @selection.addRange(range)
+
+
+ placeMarker: ->
+ return unless @range
+
+ @startMarker = $('<em class="carmenta-marker"/>', @context).get(0)
+ @endMarker = $('<em class="carmenta-marker"/>', @context).get(0)
+
+ # put a single marker (the end)
+ rangeEnd = @range.cloneRange()
+ rangeEnd.collapse(false)
+ rangeEnd.insertNode(@endMarker)
+
+ unless @range.collapsed
+ # put a start marker
+ rangeStart = @range.cloneRange()
+ rangeStart.collapse(true)
+ rangeStart.insertNode(@startMarker)
+
+ @selection.removeAllRanges()
+ @selection.addRange(@range)
+
+
+ removeMarker: ->
+ $(@startMarker).remove()
+ $(@endMarker).remove()
+
+
insertTextNode: (string) ->
node = @context.createTextNode(string)
@range.extractContents()
@@ -4,4 +4,4 @@ class Carmenta.Regions.Snippet
constructor: (@element) ->
Carmenta.log('making snippetable', @element)
- @history = new HistoryBuffer()
+ @history = new Carmenta.HistoryBuffer()
@@ -44,10 +44,10 @@ class Carmenta.Toolbar
bindEvents: ->
- Carmenta.bind 'region:update', (event, options) =>
+ Carmenta.bind 'region:focused', (event, options) =>
@element.find(".carmenta-#{options.region.type}-toolbar").removeClass('disabled')
- Carmenta.bind 'region:blur', (event, options) =>
+ Carmenta.bind 'region:blurred', (event, options) =>
@element.find(".carmenta-#{options.region.type}-toolbar").addClass('disabled')
@element.click -> Carmenta.trigger('hide:dialogs')
@@ -248,4 +248,4 @@
.character{ 'data-entity' => "#9827", :title => "black club suit (shamrock)" } &#9827;
.character{ 'data-entity' => "#9829", :title => "black heart suit (valentine)" } &#9829;
.character{ 'data-entity' => "#9830", :title => "black diamond suit" } &#9830;
- .character{ 'data-entity' => "#x2603", :title => "snowman" } &#x2603;
+ .character{ 'data-entity' => "#x2603", :title => "snowman" } &#x2603;
@@ -2,7 +2,3 @@
.information It looks like you've pasted directly from Microsoft Office!<br/><br/>Sadly though, your browser wasn't able to properly handle what you pasted. But that's ok, I've sanitized it for you!
%textarea{ :rows => '10', :wrap => 'off' }
%strong You can just copy and paste the sanitized content that appears above.
-
-
-something here
-asdasdasd
@@ -0,0 +1,31 @@
+%form#carmenta_table{ :style => 'width:700px' }
+
+ .carmenta-modal-pane-container
+ .carmenta-modal-pane
+ #table_display
+ %table{ :style => 'width:100%;height:300px;', :border => '1', :cellpadding => '1' }
+ %tr
+ %td
+ %td
+ %tr
+ %td
+ %td
+
+ #table_options
+ .legend Structure Options
+ %fieldset
+ %p
+ %input{ :type => 'button', :value => '+' }/
+ %input{ :type => 'button', :value => '-' }/
+
+ .legend Display Options
+ %fieldset
+ %p
+ %label{ :for => 'alignment' } Alignment
+ %select#alignment{ :name => 'alignment' }
+ %option{ :value => '', :selected => true } None
+ %option{ :value => 'left' } Left
+ %option{ :value => 'right' } Right
+
+ .carmenta-modal-controls
+ %input{ :type => 'submit', :value => 'Insert Table' }

0 comments on commit 2d1fbc5

Please sign in to comment.