character_editor 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +1 -0
 - data/Gemfile +4 -0
 - data/Gemfile.lock +14 -0
 - data/README.md +3 -0
 - data/Rakefile +5 -0
 - data/app/assets/javascripts/character_editor.coffee +193 -0
 - data/app/assets/javascripts/character_editor/_selection.coffee +51 -0
 - data/app/assets/javascripts/character_editor/_toolbar.coffee +353 -0
 - data/app/assets/stylesheets/character_editor.scss +126 -0
 - data/character_editor.gemspec +21 -0
 - data/lib/character_editor.rb +2 -0
 - data/lib/character_editor/engine.rb +14 -0
 - data/lib/character_editor/version.rb +5 -0
 - metadata +56 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9de43f73c9a9be5a52713b0e182eae7a3d77a5d4
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 48d6f5ee42ea70ac33468e504d50a96ae9b2f86e
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 733d8129f5be1b895c043aaea78ba6cf692153f7c3c6c4d0e6fa00d55b8a33c50a3574cc5f16cf882f6c361f673d3acb9319d25c1f143ead6899c6f270b66f5b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 6a13445ba089a922eb5df7e77cb74d94117963ca3e6be89bf50a2832a9bb0d20012b80612d845f9d4062338a64f477891ed07422025a7621bdb1e515af8f1b8c
         
     | 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .DS_Store
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    
    
        data/README.md
    ADDED
    
    
    
        data/Rakefile
    ADDED
    
    
| 
         @@ -0,0 +1,193 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ###!
         
     | 
| 
      
 2 
     | 
    
         
            +
            * Character Editor
         
     | 
| 
      
 3 
     | 
    
         
            +
            * Author: Alexander Kravets @ slatestudio.com
         
     | 
| 
      
 4 
     | 
    
         
            +
            * Licensed under the MIT license
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              Usage:
         
     | 
| 
      
 7 
     | 
    
         
            +
              $('#editor').editor({placeholder: 'Title' })
         
     | 
| 
      
 8 
     | 
    
         
            +
              inst = $('#editor').data('editor')
         
     | 
| 
      
 9 
     | 
    
         
            +
              inst.serialize()
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ###
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            #= require_self
         
     | 
| 
      
 14 
     | 
    
         
            +
            #= require character_editor/_selection
         
     | 
| 
      
 15 
     | 
    
         
            +
            #= require character_editor/_toolbar
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            # Object - an object representing a concept that you want
         
     | 
| 
      
 18 
     | 
    
         
            +
            # to model (e.g. a car)
         
     | 
| 
      
 19 
     | 
    
         
            +
            @CharacterEditor =
         
     | 
| 
      
 20 
     | 
    
         
            +
              options:
         
     | 
| 
      
 21 
     | 
    
         
            +
                allowMultiParagraphSelection: true
         
     | 
| 
      
 22 
     | 
    
         
            +
                anchorInputPlaceholder:       'Paste or type a link'
         
     | 
| 
      
 23 
     | 
    
         
            +
                buttons:                      ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote']
         
     | 
| 
      
 24 
     | 
    
         
            +
                delay:                        0
         
     | 
| 
      
 25 
     | 
    
         
            +
                diffLeft:                     0
         
     | 
| 
      
 26 
     | 
    
         
            +
                diffTop:                      -10
         
     | 
| 
      
 27 
     | 
    
         
            +
                disableReturn:                false
         
     | 
| 
      
 28 
     | 
    
         
            +
                disableToolbar:               false
         
     | 
| 
      
 29 
     | 
    
         
            +
                forcePlainText:               true
         
     | 
| 
      
 30 
     | 
    
         
            +
                placeholder:                  'Type your text...'
         
     | 
| 
      
 31 
     | 
    
         
            +
                targetBlank:                  false
         
     | 
| 
      
 32 
     | 
    
         
            +
                firstHeader:                  'h3'
         
     | 
| 
      
 33 
     | 
    
         
            +
                secondHeader:                 'h4'
         
     | 
| 
      
 34 
     | 
    
         
            +
                tabSpaces:                    '    '
         
     | 
| 
      
 35 
     | 
    
         
            +
                viewSelector:                 'body'
         
     | 
| 
      
 36 
     | 
    
         
            +
                parentElements:               ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre']
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              _dataOptions: ->
         
     | 
| 
      
 39 
     | 
    
         
            +
                result = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                dataOptions = @$elem.attr('data-options')
         
     | 
| 
      
 41 
     | 
    
         
            +
                if dataOptions
         
     | 
| 
      
 42 
     | 
    
         
            +
                  opts = dataOptions.split(';')
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  isNumber     = (n)   -> return !isNaN(parseFloat(n)) && isFinite(n)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  removeQuotes = (str) -> str.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g, '')
         
     | 
| 
      
 46 
     | 
    
         
            +
                  trim         = (val) -> if typeof val == 'string' then removeQuotes($.trim(val)) else val
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  $.each opts, (i, opt) ->
         
     | 
| 
      
 49 
     | 
    
         
            +
                    p = opt.split(':')
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    if /true/i.test(p[1])
         
     | 
| 
      
 52 
     | 
    
         
            +
                      p[1] = true
         
     | 
| 
      
 53 
     | 
    
         
            +
                    else if /false/i.test(p[1])
         
     | 
| 
      
 54 
     | 
    
         
            +
                      p[1] = false
         
     | 
| 
      
 55 
     | 
    
         
            +
                    else if isNumber(p[1])
         
     | 
| 
      
 56 
     | 
    
         
            +
                      p[1] = parseFloat(p[1])
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    if p.length == 2 and p[0].length > 0
         
     | 
| 
      
 59 
     | 
    
         
            +
                      result[ trim(p[0]) ] = trim(p[1])
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                return result
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              init: (options, elem) ->
         
     | 
| 
      
 64 
     | 
    
         
            +
                @elem = elem
         
     | 
| 
      
 65 
     | 
    
         
            +
                @$elem = $(elem)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                @options = $.extend({}, @options, @_dataOptions(), options)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                @_build()
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                @_bind()
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                @
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              _build: ->
         
     | 
| 
      
 76 
     | 
    
         
            +
                @$elem.attr('contenteditable', true)
         
     | 
| 
      
 77 
     | 
    
         
            +
                @$elem.attr('data-editor-element', true)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                @_setPlaceholder()
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                if not @options.disableToolbar
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @_addToolbar()
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              _addToolbar: -> # create only one toolbar for now
         
     | 
| 
      
 85 
     | 
    
         
            +
                @toolbar = window.characterEditorToolbar
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                if not @toolbar
         
     | 
| 
      
 88 
     | 
    
         
            +
                  $toolbarElement = $("<div id='character_editor_toolbar' class='character-editor-toolbar' />")
         
     | 
| 
      
 89 
     | 
    
         
            +
                  $(@options.viewSelector).append($toolbarElement)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  @toolbar = Object.create(CharacterEditor.Toolbar).init(@options, $toolbarElement)
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  window.characterEditorToolbar = @toolbar
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              _setPlaceholder: ->
         
     | 
| 
      
 96 
     | 
    
         
            +
                @$elem.attr('data-placeholder', @options.placeholder)
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                activatePlaceholder = (el) ->
         
     | 
| 
      
 99 
     | 
    
         
            +
                  if el.textContent.replace(/^\s+|\s+$/g, '') == ''
         
     | 
| 
      
 100 
     | 
    
         
            +
                    $(el).addClass('character-editor-placeholder')
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                activatePlaceholder(@elem)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                @$elem.on 'blur keypress', (e) ->
         
     | 
| 
      
 105 
     | 
    
         
            +
                  $(@).removeClass('character-editor-placeholder')
         
     | 
| 
      
 106 
     | 
    
         
            +
                  if e.type != 'keypress'
         
     | 
| 
      
 107 
     | 
    
         
            +
                    activatePlaceholder(@)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              _bind: ->
         
     | 
| 
      
 110 
     | 
    
         
            +
                @_bindNewParagraph()
         
     | 
| 
      
 111 
     | 
    
         
            +
                @_bindReturn()
         
     | 
| 
      
 112 
     | 
    
         
            +
                @_bindTab()
         
     | 
| 
      
 113 
     | 
    
         
            +
                @_bindPaste()
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              _bindNewParagraph: ->
         
     | 
| 
      
 116 
     | 
    
         
            +
                @$elem.on 'keyup', (e) =>
         
     | 
| 
      
 117 
     | 
    
         
            +
                  node = getSelectionStart()
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  if node and node.getAttribute('data-editor-element') and node.children.length == 0 and !@options.disableReturn
         
     | 
| 
      
 120 
     | 
    
         
            +
                    document.execCommand('formatBlock', false, 'p')
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  if e.which == 13 and !e.shiftKey
         
     | 
| 
      
 123 
     | 
    
         
            +
                    node    = getSelectionStart()
         
     | 
| 
      
 124 
     | 
    
         
            +
                    tagName = node.tagName.toLowerCase()
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    if !@options.disableReturn and tagName != 'li' and !isListItemChild(node)
         
     | 
| 
      
 127 
     | 
    
         
            +
                      document.execCommand('formatBlock', false, 'p')
         
     | 
| 
      
 128 
     | 
    
         
            +
                      if tagName == 'a'
         
     | 
| 
      
 129 
     | 
    
         
            +
                        document.execCommand('unlink', false, null)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              _bindReturn: ->
         
     | 
| 
      
 132 
     | 
    
         
            +
                @$elem.on 'keypress', (e) =>
         
     | 
| 
      
 133 
     | 
    
         
            +
                  if e.which == 13 and @options.disableReturn
         
     | 
| 
      
 134 
     | 
    
         
            +
                    e.preventDefault()
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
              _bindTab: ->
         
     | 
| 
      
 137 
     | 
    
         
            +
                @$elem.on 'keydown', (e) =>
         
     | 
| 
      
 138 
     | 
    
         
            +
                  if e.which == 9
         
     | 
| 
      
 139 
     | 
    
         
            +
                    tag = getSelectionStart().tagName.toLowerCase()
         
     | 
| 
      
 140 
     | 
    
         
            +
                    if tag == "pre"
         
     | 
| 
      
 141 
     | 
    
         
            +
                      e.preventDefault()
         
     | 
| 
      
 142 
     | 
    
         
            +
                      document.execCommand('insertHtml', null, @options.tabSpaces)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              _bindPaste: ->
         
     | 
| 
      
 145 
     | 
    
         
            +
                return if !@options.forcePlainText
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                @$elem.on 'paste', (e) =>
         
     | 
| 
      
 148 
     | 
    
         
            +
                  html = ''
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  $(@).removeClass('character-editor-placeholder')
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  if e.clipboardData and e.clipboardData.getData
         
     | 
| 
      
 153 
     | 
    
         
            +
                    e.preventDefault()
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                    if !@options.disableReturn
         
     | 
| 
      
 156 
     | 
    
         
            +
                      paragraphs = e.clipboardData.getData('text/plain').split(/[\r\n]/g)
         
     | 
| 
      
 157 
     | 
    
         
            +
                      $.each paragraphs, (i, p) -> if p != '' then html += "<p>#{p}</p>"
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                      document.execCommand('insertHTML', false, html)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    else
         
     | 
| 
      
 161 
     | 
    
         
            +
                      document.execCommand('insertHTML', false, e.clipboardData.getData('text/plain'))
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
              serialize: ->
         
     | 
| 
      
 164 
     | 
    
         
            +
                @$elem.html().trim()
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
              destroy: ->
         
     | 
| 
      
 167 
     | 
    
         
            +
                @$elem.removeAttr('contenteditable')
         
     | 
| 
      
 168 
     | 
    
         
            +
                @$elem.removeAttr('data-editor-element')
         
     | 
| 
      
 169 
     | 
    
         
            +
                @$elem.removeAttr('data-placeholder')
         
     | 
| 
      
 170 
     | 
    
         
            +
                @$elem.removeClass('character-editor-placeholder')
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                @$elem.off 'blur keypress keyup keydown paste'
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                if @toolbar
         
     | 
| 
      
 175 
     | 
    
         
            +
                  @toolbar.destroy()
         
     | 
| 
      
 176 
     | 
    
         
            +
                  delete @toolbar
         
     | 
| 
      
 177 
     | 
    
         
            +
                  delete window.characterEditorToolbar
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
            # Object.create support test, and fallback for browsers without it
         
     | 
| 
      
 180 
     | 
    
         
            +
            if typeof Object.create isnt "function"
         
     | 
| 
      
 181 
     | 
    
         
            +
              Object.create = (o) ->
         
     | 
| 
      
 182 
     | 
    
         
            +
                F = ->
         
     | 
| 
      
 183 
     | 
    
         
            +
                F:: = o
         
     | 
| 
      
 184 
     | 
    
         
            +
                new F()
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
            # Create a plugin based on a defined object
         
     | 
| 
      
 187 
     | 
    
         
            +
            $.plugin = (name, object) ->
         
     | 
| 
      
 188 
     | 
    
         
            +
              $.fn[name] = (options) ->
         
     | 
| 
      
 189 
     | 
    
         
            +
                @each ->
         
     | 
| 
      
 190 
     | 
    
         
            +
                  $.data @, name, Object.create(object).init(options, @)  unless $.data(@, name)
         
     | 
| 
      
 191 
     | 
    
         
            +
              return
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
            $.plugin('editor', CharacterEditor)
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # http://stackoverflow.com/questions/4176923/html-of-selected-text
         
     | 
| 
      
 2 
     | 
    
         
            +
            # by Tim Down
         
     | 
| 
      
 3 
     | 
    
         
            +
            window.getSelectionHtml = ->
         
     | 
| 
      
 4 
     | 
    
         
            +
              html = ''
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              if window.getSelection != undefined
         
     | 
| 
      
 7 
     | 
    
         
            +
                sel = window.getSelection()
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                if sel.rangeCount
         
     | 
| 
      
 10 
     | 
    
         
            +
                  container = document.createElement('div')
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  for i in [0..sel.rangeCount-1]
         
     | 
| 
      
 13 
     | 
    
         
            +
                    container.appendChild(sel.getRangeAt(i).cloneContents())
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  html = container.innerHTML
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              else if document.selection != undefined
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                if document.selection.type == 'Text'
         
     | 
| 
      
 20 
     | 
    
         
            +
                  html = document.selection.createRange().htmlText
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              return html
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            # http://stackoverflow.com/questions/1197401/how-can-i-get-the-element-the-caret-is-in-with-javascript-when-using-contentedi
         
     | 
| 
      
 25 
     | 
    
         
            +
            # by You
         
     | 
| 
      
 26 
     | 
    
         
            +
            window.getSelectionStart = ->
         
     | 
| 
      
 27 
     | 
    
         
            +
              node = document.getSelection().anchorNode
         
     | 
| 
      
 28 
     | 
    
         
            +
              startNode = if node and node.nodeType == 3 then node.parentNode else node
         
     | 
| 
      
 29 
     | 
    
         
            +
              return startNode
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            window.isListItemChild = (node) -> $(node).parents('li').length > 0
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            # http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element
         
     | 
| 
      
 34 
     | 
    
         
            +
            # by Tim Down
         
     | 
| 
      
 35 
     | 
    
         
            +
            window.saveSelection = ->
         
     | 
| 
      
 36 
     | 
    
         
            +
              sel = window.getSelection()
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              if sel.getRangeAt and sel.rangeCount
         
     | 
| 
      
 39 
     | 
    
         
            +
                ranges = []
         
     | 
| 
      
 40 
     | 
    
         
            +
                for i in [0..sel.rangeCount-1]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ranges.push(sel.getRangeAt(i))
         
     | 
| 
      
 42 
     | 
    
         
            +
                return ranges
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              return false
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            window.restoreSelection = (savedSel) ->
         
     | 
| 
      
 47 
     | 
    
         
            +
              sel = window.getSelection()
         
     | 
| 
      
 48 
     | 
    
         
            +
              if savedSel
         
     | 
| 
      
 49 
     | 
    
         
            +
                sel.removeAllRanges()
         
     | 
| 
      
 50 
     | 
    
         
            +
                for i in [0..savedSel.length-1]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  sel.addRange(savedSel[i])
         
     | 
| 
         @@ -0,0 +1,353 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            @CharacterEditor.Toolbar =
         
     | 
| 
      
 3 
     | 
    
         
            +
              init: (options, elem) ->
         
     | 
| 
      
 4 
     | 
    
         
            +
                @options = $.extend({}, @options, options)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                @elem = elem
         
     | 
| 
      
 7 
     | 
    
         
            +
                @$elem = $(elem)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # this helps to not hide toolbar on selection (while toolbar button click)
         
     | 
| 
      
 10 
     | 
    
         
            +
                @keepToolbarVisible = false
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                @_build()
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                @_bind()
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                @
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              options:
         
     | 
| 
      
 19 
     | 
    
         
            +
                buttonLabels:
         
     | 
| 
      
 20 
     | 
    
         
            +
                  bold:           '<i class="fa fa-bold"></i>'
         
     | 
| 
      
 21 
     | 
    
         
            +
                  italic :        '<i class="fa fa-italic"></i>'
         
     | 
| 
      
 22 
     | 
    
         
            +
                  underline:      '<i class="fa fa-underline"></i>'
         
     | 
| 
      
 23 
     | 
    
         
            +
                  strikethrough:  '<i class="fa fa-strikethrough"></i>'
         
     | 
| 
      
 24 
     | 
    
         
            +
                  superscript:    '<i class="fa fa-superscript"></i>'
         
     | 
| 
      
 25 
     | 
    
         
            +
                  subscript:      '<i class="fa fa-subscript"></i>'
         
     | 
| 
      
 26 
     | 
    
         
            +
                  anchor:         '<i class="fa fa-link"></i>'
         
     | 
| 
      
 27 
     | 
    
         
            +
                  image:          '<i class="fa fa-picture-o"></i>'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  quote:          '<i class="fa fa-quote-right"></i>'
         
     | 
| 
      
 29 
     | 
    
         
            +
                  orderedlist:    '<i class="fa fa-list-ol"></i>'
         
     | 
| 
      
 30 
     | 
    
         
            +
                  unorderedlist:  '<i class="fa fa-list-ul"></i>'
         
     | 
| 
      
 31 
     | 
    
         
            +
                  pre:            '<i class="fa fa-code fa-lg"></i>'
         
     | 
| 
      
 32 
     | 
    
         
            +
                  header1:        '<b>H1</b>'
         
     | 
| 
      
 33 
     | 
    
         
            +
                  header2:        '<b>H1</b>'
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              _buttonTemplate: (key) ->
         
     | 
| 
      
 36 
     | 
    
         
            +
                l               = @options.buttonLabels
         
     | 
| 
      
 37 
     | 
    
         
            +
                classPrefix     = 'character-editor-action'
         
     | 
| 
      
 38 
     | 
    
         
            +
                templates =
         
     | 
| 
      
 39 
     | 
    
         
            +
                  bold:           "<li><button class='#{classPrefix} #{classPrefix}-bold'
         
     | 
| 
      
 40 
     | 
    
         
            +
                                               data-action='bold' data-element='b'>#{ l.bold }</button></li>"
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  italic:         "<li><button class='#{classPrefix} #{classPrefix}-italic'
         
     | 
| 
      
 43 
     | 
    
         
            +
                                               data-action='italic' data-element='i'>#{ l.italic }</button></li>"
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  underline:      "<li><button class='#{classPrefix} #{classPrefix}-underline'
         
     | 
| 
      
 46 
     | 
    
         
            +
                                               data-action='underline' data-element='u'>#{ l.underline }</button></li>"
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  strikethrough:  "<li><button class='#{classPrefix} #{classPrefix}-strikethrough'
         
     | 
| 
      
 49 
     | 
    
         
            +
                                               data-action='strikethrough' data-element='strike'>#{ l.strikethrough }</button></li>"
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  superscript:    "<li><button class='#{classPrefix} #{classPrefix}-superscript'
         
     | 
| 
      
 52 
     | 
    
         
            +
                                               data-action='superscript' data-element='sup'>#{ l.superscript }</button></li>"
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  subscript:      "<li><button class='#{classPrefix} #{classPrefix}-subscript'
         
     | 
| 
      
 55 
     | 
    
         
            +
                                               data-action='subscript' data-element='sub'>#{ l.subscript }</button></li>"
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  anchor:         "<li><button class='#{classPrefix} #{classPrefix}-anchor'
         
     | 
| 
      
 58 
     | 
    
         
            +
                                               data-action='anchor' data-element='a'>#{ l.anchor }</button></li>"
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  image:          "<li><button class='#{classPrefix} #{classPrefix}-image'
         
     | 
| 
      
 61 
     | 
    
         
            +
                                               data-action='image' data-element='img'>#{ l.image }</button></li>"
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  quote:          "<li><button class='#{classPrefix} #{classPrefix}-quote'
         
     | 
| 
      
 64 
     | 
    
         
            +
                                               data-action='append-blockquote' data-element='blockquote'>#{ l.quote }</button></li>"
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  orderedlist:    "<li><button class='#{classPrefix} #{classPrefix}-orderedlist'
         
     | 
| 
      
 67 
     | 
    
         
            +
                                               data-action='insertorderedlist' data-element='ol'>#{ l.orderedlist }</button></li>"
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  unorderedlist:  "<li><button class='#{classPrefix} #{classPrefix}-unorderedlist'
         
     | 
| 
      
 70 
     | 
    
         
            +
                                               data-action='insertunorderedlist' data-element='ul'>#{ l.unorderedlist }</button></li>"
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  pre:            "<li><button class='#{classPrefix} #{classPrefix}-pre'
         
     | 
| 
      
 73 
     | 
    
         
            +
                                               data-action='append-pre' data-element='pre'>#{ l.pre }</button></li>"
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  header1:        "<li><button class='#{classPrefix} #{classPrefix}-header1'
         
     | 
| 
      
 76 
     | 
    
         
            +
                                               data-action='append-#{ @options.firstHeader }' data-element='#{ @options.firstHeader }'>#{ l.header1 }</button></li>"
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  header2:        "<li><button class='#{classPrefix} #{classPrefix}-header2'
         
     | 
| 
      
 79 
     | 
    
         
            +
                                               data-action='append-#{ @options.secondHeader }' data-element='#{ @options.secondHeader }'>#{ l.header2 }</button></li>"
         
     | 
| 
      
 80 
     | 
    
         
            +
                return templates[key]
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              _build: ->
         
     | 
| 
      
 83 
     | 
    
         
            +
                html = """<ul id='character_editor_toolbar_buttons'>"""
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                $.each @options.buttons, (i, key) => html += @_buttonTemplate(key)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                html += """</ul>
         
     | 
| 
      
 88 
     | 
    
         
            +
                 <div class='character-editor-toolbar-form-anchor' id='character_editor_toolbar_form_anchor'>
         
     | 
| 
      
 89 
     | 
    
         
            +
                   <input type='text' value='' placeholder='#{ @options.anchorInputPlaceholder }'><a href='#'>×</a>
         
     | 
| 
      
 90 
     | 
    
         
            +
                 </div>"""
         
     | 
| 
      
 91 
     | 
    
         
            +
                @$elem.html(html)
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                @$toolbarButtons = @$elem.find('#character_editor_toolbar_buttons')
         
     | 
| 
      
 94 
     | 
    
         
            +
                @$anchorForm     = @$elem.find('#character_editor_toolbar_form_anchor')
         
     | 
| 
      
 95 
     | 
    
         
            +
                @$anchorInput    = @$anchorForm.children('input')
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                buttonWidth = @$toolbarButtons.find('button').first().width()
         
     | 
| 
      
 98 
     | 
    
         
            +
                @$anchorInput.css('width', (@options.buttons.length - 1) * buttonWidth + @options.buttons.length - 1)
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                @$toolbarButtons.show()
         
     | 
| 
      
 101 
     | 
    
         
            +
                @$anchorForm.hide()
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              _bind: ->
         
     | 
| 
      
 104 
     | 
    
         
            +
                @_bindWindowResize()
         
     | 
| 
      
 105 
     | 
    
         
            +
                @_bindButtons()
         
     | 
| 
      
 106 
     | 
    
         
            +
                @_bindAnchorForm()
         
     | 
| 
      
 107 
     | 
    
         
            +
                @_bindSelect()
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              _hide: ->
         
     | 
| 
      
 110 
     | 
    
         
            +
                @keepToolbarVisible = false
         
     | 
| 
      
 111 
     | 
    
         
            +
                @$elem.removeClass('character-editor-toolbar-active')
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              _show: ->
         
     | 
| 
      
 114 
     | 
    
         
            +
                timer = ''
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                @$anchorForm.hide()
         
     | 
| 
      
 118 
     | 
    
         
            +
                @$toolbarButtons.show()
         
     | 
| 
      
 119 
     | 
    
         
            +
                @keepToolbarVisible = false
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                clearTimeout(timer)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                timer = setTimeout ( =>
         
     | 
| 
      
 124 
     | 
    
         
            +
                  if !@$elem.hasClass('character-editor-toolbar-active')
         
     | 
| 
      
 125 
     | 
    
         
            +
                    @$elem.addClass('character-editor-toolbar-active')
         
     | 
| 
      
 126 
     | 
    
         
            +
                ), 100
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              _setPosition: ->
         
     | 
| 
      
 129 
     | 
    
         
            +
                $contentView      = $(@options.viewSelector)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                contentLeftOffset = $contentView.offset().left
         
     | 
| 
      
 132 
     | 
    
         
            +
                contentTopOffset  = $contentView.offset().top
         
     | 
| 
      
 133 
     | 
    
         
            +
                contentScrollTop  = $contentView.scrollTop()
         
     | 
| 
      
 134 
     | 
    
         
            +
                contentInnerWidth = $contentView.innerWidth()
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                buttonHeight    = 30
         
     | 
| 
      
 137 
     | 
    
         
            +
                selection       = window.getSelection()
         
     | 
| 
      
 138 
     | 
    
         
            +
                range           = selection.getRangeAt(0)
         
     | 
| 
      
 139 
     | 
    
         
            +
                boundary        = range.getBoundingClientRect()
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                offsetWidth  = @$elem.get(0).offsetWidth
         
     | 
| 
      
 142 
     | 
    
         
            +
                offsetHeight = @$elem.get(0).offsetHeight
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                defaultLeft       = (@options.diffLeft) - (offsetWidth / 2)
         
     | 
| 
      
 145 
     | 
    
         
            +
                middleBoundary    = (boundary.left + boundary.right) / 2 - contentLeftOffset
         
     | 
| 
      
 146 
     | 
    
         
            +
                halfOffsetWidth   = offsetWidth / 2
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                if boundary.top < buttonHeight
         
     | 
| 
      
 150 
     | 
    
         
            +
                  @$elem.addClass('character-toolbar-arrow-over')
         
     | 
| 
      
 151 
     | 
    
         
            +
                  @$elem.removeClass('character-toolbar-arrow-under')
         
     | 
| 
      
 152 
     | 
    
         
            +
                  @$elem.css 'top', buttonHeight + boundary.bottom - @options.diffTop + window.pageYOffset - offsetHeight + 'px'
         
     | 
| 
      
 153 
     | 
    
         
            +
                else
         
     | 
| 
      
 154 
     | 
    
         
            +
                  @$elem.addClass('character-toolbar-arrow-under')
         
     | 
| 
      
 155 
     | 
    
         
            +
                  @$elem.removeClass('character-toolbar-arrow-over')
         
     | 
| 
      
 156 
     | 
    
         
            +
                  @$elem.css 'top', boundary.top + @options.diffTop - contentTopOffset + contentScrollTop - offsetHeight + 'px'
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                edgeOffset = 5
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                if middleBoundary < halfOffsetWidth
         
     | 
| 
      
 161 
     | 
    
         
            +
                  @$elem.css 'left', defaultLeft + halfOffsetWidth + edgeOffset + 'px'
         
     | 
| 
      
 162 
     | 
    
         
            +
                else if (contentInnerWidth - middleBoundary) < halfOffsetWidth
         
     | 
| 
      
 163 
     | 
    
         
            +
                  @$elem.css 'left', contentInnerWidth + defaultLeft - halfOffsetWidth - edgeOffset + 'px'
         
     | 
| 
      
 164 
     | 
    
         
            +
                else
         
     | 
| 
      
 165 
     | 
    
         
            +
                  @$elem.css 'left', defaultLeft + middleBoundary + 'px'
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                # TODO: update arrow layout to make it possible to move it on edge cases
         
     | 
| 
      
 168 
     | 
    
         
            +
                #
         
     | 
| 
      
 169 
     | 
    
         
            +
                #
         
     | 
| 
      
 170 
     | 
    
         
            +
                #
         
     | 
| 
      
 171 
     | 
    
         
            +
                #
         
     | 
| 
      
 172 
     | 
    
         
            +
                #
         
     | 
| 
      
 173 
     | 
    
         
            +
                #
         
     | 
| 
      
 174 
     | 
    
         
            +
                #
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
              _bindSelect: ->
         
     | 
| 
      
 177 
     | 
    
         
            +
                if !@options.disableToolbar
         
     | 
| 
      
 178 
     | 
    
         
            +
                  timer = ''
         
     | 
| 
      
 179 
     | 
    
         
            +
                  toolbar = @
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  $(@options.viewSelector).on 'mouseup keyup blur', (e) =>
         
     | 
| 
      
 182 
     | 
    
         
            +
                    console.log $(e.target).parents('#character_editor_toolbar')
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                    clearTimeout(timer)
         
     | 
| 
      
 185 
     | 
    
         
            +
                    timer = setTimeout ( -> console.log 'select' ; toolbar._checkSelection() ), @options.delay
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
              _bindWindowResize: ->
         
     | 
| 
      
 188 
     | 
    
         
            +
                timer = ''
         
     | 
| 
      
 189 
     | 
    
         
            +
                $(window).on 'resize', =>
         
     | 
| 
      
 190 
     | 
    
         
            +
                  clearTimeout(timer)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  timer = setTimeout ( => if @$elem.hasClass('character-editor-toolbar-active') then @_setPosition() ), 100
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
              _getActiveEditor: ->
         
     | 
| 
      
 194 
     | 
    
         
            +
                $editorElement = $(@selection.getRangeAt(0).commonAncestorContainer).parents('[data-editor-element]')
         
     | 
| 
      
 195 
     | 
    
         
            +
                if $editorElement then $editorElement.data('editor') else false
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
              _checkSelection: ->
         
     | 
| 
      
 198 
     | 
    
         
            +
                if not @keepToolbarVisible
         
     | 
| 
      
 199 
     | 
    
         
            +
                  @selection  = window.getSelection()
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                  if @selection.toString().trim() == ''
         
     | 
| 
      
 202 
     | 
    
         
            +
                    return @_hide()
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                  activeEditor = @_getActiveEditor()
         
     | 
| 
      
 205 
     | 
    
         
            +
                  if !activeEditor or activeEditor.options.disableToolbar
         
     | 
| 
      
 206 
     | 
    
         
            +
                    return @_hide()
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                  selectionHtml = getSelectionHtml()
         
     | 
| 
      
 209 
     | 
    
         
            +
                  selectionHtml = selectionHtml.replace(/<[\S]+><\/[\S]+>/gim, '')
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                  hasMultiParagraphs = selectionHtml.match(/<(p|h[0-6]|blockquote)>([\s\S]*?)<\/(p|h[0-6]|blockquote)>/g)
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  if !@options.allowMultiParagraphSelection and hasMultiParagraphs
         
     | 
| 
      
 214 
     | 
    
         
            +
                    return @_hide()
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                  @_setButtonStates()
         
     | 
| 
      
 217 
     | 
    
         
            +
                  @_setPosition()
         
     | 
| 
      
 218 
     | 
    
         
            +
                  @_show()
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
              _setButtonStates: ->
         
     | 
| 
      
 221 
     | 
    
         
            +
                $buttons = @$elem.find('button')
         
     | 
| 
      
 222 
     | 
    
         
            +
                $buttons.removeClass('character-editor-button-active')
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                parentNode = @selection.anchorNode
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                if !parentNode.tagName
         
     | 
| 
      
 227 
     | 
    
         
            +
                  parentNode = @selection.anchorNode.parentNode
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                while parentNode.tagName != undefined and @options.parentElements.indexOf(parentNode.tagName) == -1
         
     | 
| 
      
 230 
     | 
    
         
            +
                  tag = parentNode.tagName.toLowerCase()
         
     | 
| 
      
 231 
     | 
    
         
            +
                  @_activateButton(tag)
         
     | 
| 
      
 232 
     | 
    
         
            +
                  parentNode = parentNode.parentNode
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
              _activateButton: (tag) ->
         
     | 
| 
      
 235 
     | 
    
         
            +
                $el = @$elem.find('[data-element="' + tag + '"]').first()
         
     | 
| 
      
 236 
     | 
    
         
            +
                if $el.length and !$el.hasClass('character-editor-button-active')
         
     | 
| 
      
 237 
     | 
    
         
            +
                  $el.addClass('character-editor-button-active')
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
              _getSelectionData: (el) ->
         
     | 
| 
      
 240 
     | 
    
         
            +
                if el and el.tagName
         
     | 
| 
      
 241 
     | 
    
         
            +
                  tagName = el.tagName.toLowerCase()
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                while el and @options.parentElements.indexOf(tagName) == -1
         
     | 
| 
      
 244 
     | 
    
         
            +
                  el = el.parentNode
         
     | 
| 
      
 245 
     | 
    
         
            +
                  if el and el.tagName
         
     | 
| 
      
 246 
     | 
    
         
            +
                    tagName = el.tagName.toLowerCase()
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
                return { el: el, tagName: tagName }
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
              _execFormatBlock: (el) ->
         
     | 
| 
      
 251 
     | 
    
         
            +
                selectionData = @_getSelectionData(@selection.anchorNode)
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                # FF handles blockquote differently on formatBlock allowing nesting, we need to use outdent
         
     | 
| 
      
 254 
     | 
    
         
            +
                # https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla
         
     | 
| 
      
 255 
     | 
    
         
            +
                if el == 'blockquote' and selectionData.el and selectionData.el.parentNode.tagName.toLowerCase() == 'blockquote'
         
     | 
| 
      
 256 
     | 
    
         
            +
                  return document.execCommand('outdent', false, null)
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                if selectionData.tagName == el
         
     | 
| 
      
 259 
     | 
    
         
            +
                  el = 'p'
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                return document.execCommand('formatBlock', false, el)
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
              _execAction: (action, e) ->
         
     | 
| 
      
 264 
     | 
    
         
            +
                if action.indexOf('append-') > -1
         
     | 
| 
      
 265 
     | 
    
         
            +
                 @_execFormatBlock(action.replace('append-', ''))
         
     | 
| 
      
 266 
     | 
    
         
            +
                 @_setPosition()
         
     | 
| 
      
 267 
     | 
    
         
            +
                 @_setButtonStates()
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
                else if action is 'anchor'
         
     | 
| 
      
 270 
     | 
    
         
            +
                 @_triggerAnchorAction(e)
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                else if action is 'image'
         
     | 
| 
      
 273 
     | 
    
         
            +
                  document.execCommand('insertImage', false, window.getSelection())
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                else
         
     | 
| 
      
 276 
     | 
    
         
            +
                  document.execCommand(action, false, null)
         
     | 
| 
      
 277 
     | 
    
         
            +
                  @_setPosition()
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
      
 279 
     | 
    
         
            +
              _triggerAnchorAction: (e) ->
         
     | 
| 
      
 280 
     | 
    
         
            +
                if @selection.anchorNode.parentNode.tagName.toLowerCase() == 'a'
         
     | 
| 
      
 281 
     | 
    
         
            +
                  document.execCommand('unlink', false, null)
         
     | 
| 
      
 282 
     | 
    
         
            +
                else
         
     | 
| 
      
 283 
     | 
    
         
            +
                  if @$anchorForm.is(':visible') then @_show() else @_showAnchorForm()
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
              _showAnchorForm: ->
         
     | 
| 
      
 286 
     | 
    
         
            +
                @keepToolbarVisible = true
         
     | 
| 
      
 287 
     | 
    
         
            +
             
     | 
| 
      
 288 
     | 
    
         
            +
                @savedSelection = window.saveSelection()
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
                @$anchorForm.show()
         
     | 
| 
      
 291 
     | 
    
         
            +
                @$toolbarButtons.hide()
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                @$anchorInput.focus()
         
     | 
| 
      
 294 
     | 
    
         
            +
                @$anchorInput.val('')
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
              _bindButtons: ->
         
     | 
| 
      
 297 
     | 
    
         
            +
                toolbar  = @
         
     | 
| 
      
 298 
     | 
    
         
            +
                $buttons = @$elem.find('button')
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                triggerAction = (e) ->
         
     | 
| 
      
 301 
     | 
    
         
            +
                  e.preventDefault()
         
     | 
| 
      
 302 
     | 
    
         
            +
                  e.stopPropagation()
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                  $button = $(e.currentTarget)
         
     | 
| 
      
 305 
     | 
    
         
            +
                  $button.toggleClass('character-editor-button-active')
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
                  action = $button.attr('data-action')
         
     | 
| 
      
 308 
     | 
    
         
            +
                  toolbar._execAction(action, e)
         
     | 
| 
      
 309 
     | 
    
         
            +
             
     | 
| 
      
 310 
     | 
    
         
            +
                $buttons.on 'click', triggerAction
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
              _setTargetBlank: ->
         
     | 
| 
      
 313 
     | 
    
         
            +
                el = window.getSelectionStart()
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                if el.tagName.toLowerCase() == 'a'
         
     | 
| 
      
 316 
     | 
    
         
            +
                  el.target = '_blank'
         
     | 
| 
      
 317 
     | 
    
         
            +
                else
         
     | 
| 
      
 318 
     | 
    
         
            +
                  $(el).find('a').each (i, el) -> $(el).attr('target', '_blank')
         
     | 
| 
      
 319 
     | 
    
         
            +
             
     | 
| 
      
 320 
     | 
    
         
            +
              _createLink: (input) ->
         
     | 
| 
      
 321 
     | 
    
         
            +
                window.restoreSelection(@savedSelection)
         
     | 
| 
      
 322 
     | 
    
         
            +
                document.execCommand('createLink', false, @$anchorInput.val())
         
     | 
| 
      
 323 
     | 
    
         
            +
             
     | 
| 
      
 324 
     | 
    
         
            +
                if @options.targetBlank
         
     | 
| 
      
 325 
     | 
    
         
            +
                  @_setTargetBlank()
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
      
 327 
     | 
    
         
            +
                @_show()
         
     | 
| 
      
 328 
     | 
    
         
            +
                @$anchorInput.val('')
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
              _bindAnchorForm: ->
         
     | 
| 
      
 331 
     | 
    
         
            +
                @$anchorForm.on 'click', (e) ->
         
     | 
| 
      
 332 
     | 
    
         
            +
                  e.stopPropagation()
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                @$anchorInput.on 'keyup', (e) =>
         
     | 
| 
      
 335 
     | 
    
         
            +
                  if e.keyCode == 13
         
     | 
| 
      
 336 
     | 
    
         
            +
                    e.preventDefault()
         
     | 
| 
      
 337 
     | 
    
         
            +
                    @_createLink()
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                @$anchorInput.on 'blur', (e) =>
         
     | 
| 
      
 340 
     | 
    
         
            +
                  @keepToolbarVisible = false
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                @$anchorForm.find('a').on 'click', (e) =>
         
     | 
| 
      
 343 
     | 
    
         
            +
                  e.preventDefault()
         
     | 
| 
      
 344 
     | 
    
         
            +
                  window.restoreSelection(@savedSelection)
         
     | 
| 
      
 345 
     | 
    
         
            +
             
     | 
| 
      
 346 
     | 
    
         
            +
              destroy: ->
         
     | 
| 
      
 347 
     | 
    
         
            +
                $(@options.viewSelector).off 'mouseup keyup blur'
         
     | 
| 
      
 348 
     | 
    
         
            +
                $(window).off 'resize'
         
     | 
| 
      
 349 
     | 
    
         
            +
                @$anchorForm.off 'click'
         
     | 
| 
      
 350 
     | 
    
         
            +
                @$anchorForm.find('a').off 'click'
         
     | 
| 
      
 351 
     | 
    
         
            +
                @$anchorInput.on 'keyup blur'
         
     | 
| 
      
 352 
     | 
    
         
            +
                @$elem.find('button').off 'click'
         
     | 
| 
      
 353 
     | 
    
         
            +
                @$elem.remove()
         
     | 
| 
         @@ -0,0 +1,126 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $bgcolor: #57ad68;
         
     | 
| 
      
 2 
     | 
    
         
            +
            $border_color: #fff;
         
     | 
| 
      
 3 
     | 
    
         
            +
            $button_size: 40px;
         
     | 
| 
      
 4 
     | 
    
         
            +
            $link_color: #fff;
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            .character-editor                     {
         
     | 
| 
      
 7 
     | 
    
         
            +
              &:focus                             { outline: 0;
         
     | 
| 
      
 8 
     | 
    
         
            +
              }
         
     | 
| 
      
 9 
     | 
    
         
            +
            }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            .character-editor-placeholder         { position: relative;
         
     | 
| 
      
 12 
     | 
    
         
            +
              &:after                             { position: absolute;
         
     | 
| 
      
 13 
     | 
    
         
            +
                                                    content: attr(data-placeholder);
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                    top: 0;
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                    left: 0;
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                    font-style: italic;
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                    opacity: .5;
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
            }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            .character-editor-toolbar             { position: absolute;
         
     | 
| 
      
 22 
     | 
    
         
            +
                                                    top: 0;
         
     | 
| 
      
 23 
     | 
    
         
            +
                                                    left: 0;
         
     | 
| 
      
 24 
     | 
    
         
            +
                                                    visibility: hidden;
         
     | 
| 
      
 25 
     | 
    
         
            +
                                                    z-index: 2000;
         
     | 
| 
      
 26 
     | 
    
         
            +
                                                    background-color: $bgcolor;
         
     | 
| 
      
 27 
     | 
    
         
            +
                                                    font-family: HelveticaNeue, Helvetica, Arial, sans-serif;
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                    font-size: 16px;
         
     | 
| 
      
 29 
     | 
    
         
            +
                                                    //@include transition(top .075s ease-out,left .075s ease-out);
         
     | 
| 
      
 30 
     | 
    
         
            +
              ul                                  { margin: 0;
         
     | 
| 
      
 31 
     | 
    
         
            +
                                                    padding: 0;
         
     | 
| 
      
 32 
     | 
    
         
            +
              }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              li                                  { float: left;
         
     | 
| 
      
 35 
     | 
    
         
            +
                                                    list-style: none;
         
     | 
| 
      
 36 
     | 
    
         
            +
                                                    margin: 0;
         
     | 
| 
      
 37 
     | 
    
         
            +
                                                    padding: 0;
         
     | 
| 
      
 38 
     | 
    
         
            +
                &:last-child button               { border-right: none;
         
     | 
| 
      
 39 
     | 
    
         
            +
                }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                button                            { display: block;
         
     | 
| 
      
 42 
     | 
    
         
            +
                                                    padding: 0px;
         
     | 
| 
      
 43 
     | 
    
         
            +
                                                    margin: 0;
         
     | 
| 
      
 44 
     | 
    
         
            +
                                                    height: $button_size;
         
     | 
| 
      
 45 
     | 
    
         
            +
                                                    min-width: $button_size;
         
     | 
| 
      
 46 
     | 
    
         
            +
                                                    background-color: transparent;
         
     | 
| 
      
 47 
     | 
    
         
            +
                                                    border: none;
         
     | 
| 
      
 48 
     | 
    
         
            +
                                                    border-right: 1px solid lighten($bgcolor, 20);
         
     | 
| 
      
 49 
     | 
    
         
            +
                                                    color: $link_color;
         
     | 
| 
      
 50 
     | 
    
         
            +
                                                    cursor: pointer;
         
     | 
| 
      
 51 
     | 
    
         
            +
                                                    font-size: 14px;
         
     | 
| 
      
 52 
     | 
    
         
            +
                                                    text-decoration: none;
         
     | 
| 
      
 53 
     | 
    
         
            +
                                                    //@include box-sizing(border-box);
         
     | 
| 
      
 54 
     | 
    
         
            +
                                                    //@include transition(background-color .2s ease-in, color .2s ease-in);
         
     | 
| 
      
 55 
     | 
    
         
            +
                  &:hover                         { background-color: darken($bgcolor, 20);
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                    color: #fff;
         
     | 
| 
      
 57 
     | 
    
         
            +
                  }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  &:focus                         { outline: none;
         
     | 
| 
      
 59 
     | 
    
         
            +
                  }
         
     | 
| 
      
 60 
     | 
    
         
            +
                }
         
     | 
| 
      
 61 
     | 
    
         
            +
              }
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              .character-editor-button-active     { background-color: darken($bgcolor, 30);
         
     | 
| 
      
 64 
     | 
    
         
            +
                                                    color: #fff;
         
     | 
| 
      
 65 
     | 
    
         
            +
              }
         
     | 
| 
      
 66 
     | 
    
         
            +
            }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            .character-editor-toolbar-active      { visibility: visible;
         
     | 
| 
      
 69 
     | 
    
         
            +
                                                    //-webkit-animation: pop-upwards 160ms forwards linear;
         
     | 
| 
      
 70 
     | 
    
         
            +
                                                    //-moz-animation: pop-upwards 160ms forwards linear;
         
     | 
| 
      
 71 
     | 
    
         
            +
                                                    //-ms-animation: pop-upwards 160ms forwards linear;
         
     | 
| 
      
 72 
     | 
    
         
            +
                                                    //-o-animation: pop-upwards 160ms forwards linear;
         
     | 
| 
      
 73 
     | 
    
         
            +
                                                    //animation: pop-upwards 160ms forwards linear;
         
     | 
| 
      
 74 
     | 
    
         
            +
                                                    //@include transition(top .075s ease-out,left .075s ease-out);
         
     | 
| 
      
 75 
     | 
    
         
            +
            }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            .character-editor-toolbar-form-anchor { background: $bgcolor;
         
     | 
| 
      
 78 
     | 
    
         
            +
                                                    color: #fff;
         
     | 
| 
      
 79 
     | 
    
         
            +
              input[type='text'], a               { font-family: HelveticaNeue, Helvetica, Arial, sans-serif;
         
     | 
| 
      
 80 
     | 
    
         
            +
              }
         
     | 
| 
      
 81 
     | 
    
         
            +
              input[type='text']                  { display: inline;
         
     | 
| 
      
 82 
     | 
    
         
            +
                                                    padding: 6px;
         
     | 
| 
      
 83 
     | 
    
         
            +
                                                    height: $button_size;
         
     | 
| 
      
 84 
     | 
    
         
            +
                                                    background-color: $bgcolor!important;
         
     | 
| 
      
 85 
     | 
    
         
            +
                                                    color: $link_color;
         
     | 
| 
      
 86 
     | 
    
         
            +
                                                    border: none;
         
     | 
| 
      
 87 
     | 
    
         
            +
                                                    font-size: 14px;
         
     | 
| 
      
 88 
     | 
    
         
            +
                                                    margin: 0;
         
     | 
| 
      
 89 
     | 
    
         
            +
                                                    //@include box-sizing(border-box);
         
     | 
| 
      
 90 
     | 
    
         
            +
                &:focus                           { outline: 0;
         
     | 
| 
      
 91 
     | 
    
         
            +
                                                    border: none;
         
     | 
| 
      
 92 
     | 
    
         
            +
                                                    box-shadow: none;
         
     | 
| 
      
 93 
     | 
    
         
            +
                }
         
     | 
| 
      
 94 
     | 
    
         
            +
              }
         
     | 
| 
      
 95 
     | 
    
         
            +
              a                                   { color: $link_color;
         
     | 
| 
      
 96 
     | 
    
         
            +
                                                    font-weight: bolder;
         
     | 
| 
      
 97 
     | 
    
         
            +
                                                    font-size: 24px;
         
     | 
| 
      
 98 
     | 
    
         
            +
                                                    text-decoration: none;
         
     | 
| 
      
 99 
     | 
    
         
            +
                                                    padding: 0 13px;
         
     | 
| 
      
 100 
     | 
    
         
            +
                &:hover                           { color: $link_color;
         
     | 
| 
      
 101 
     | 
    
         
            +
                                                    opacity: .8;
         
     | 
| 
      
 102 
     | 
    
         
            +
                }
         
     | 
| 
      
 103 
     | 
    
         
            +
              }
         
     | 
| 
      
 104 
     | 
    
         
            +
            }
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            %character-toolbar-arrow              { content: "";
         
     | 
| 
      
 107 
     | 
    
         
            +
                                                    display: block;
         
     | 
| 
      
 108 
     | 
    
         
            +
                                                    position: absolute;
         
     | 
| 
      
 109 
     | 
    
         
            +
                                                    left: 50%;
         
     | 
| 
      
 110 
     | 
    
         
            +
                                                    margin-left: -5px;
         
     | 
| 
      
 111 
     | 
    
         
            +
                                                    width: 0;
         
     | 
| 
      
 112 
     | 
    
         
            +
                                                    height: 0;
         
     | 
| 
      
 113 
     | 
    
         
            +
                                                    border-style: solid;
         
     | 
| 
      
 114 
     | 
    
         
            +
            }
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            .character-toolbar-arrow-under:after  { @extend %character-toolbar-arrow;
         
     | 
| 
      
 117 
     | 
    
         
            +
                                                    top: $button_size;
         
     | 
| 
      
 118 
     | 
    
         
            +
                                                    border-width: 5px 5px 0 5px;
         
     | 
| 
      
 119 
     | 
    
         
            +
                                                    border-color: $bgcolor transparent transparent transparent;
         
     | 
| 
      
 120 
     | 
    
         
            +
            }
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            .character-toolbar-arrow-over:before { @extend %character-toolbar-arrow;
         
     | 
| 
      
 123 
     | 
    
         
            +
                                                  top: -5px;
         
     | 
| 
      
 124 
     | 
    
         
            +
                                                  border-width: 0 5px 5px 5px;
         
     | 
| 
      
 125 
     | 
    
         
            +
                                                  border-color: transparent transparent $bgcolor transparent;
         
     | 
| 
      
 126 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path('../lib/character_editor/version', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem.name          = 'character_editor'
         
     | 
| 
      
 6 
     | 
    
         
            +
              gem.version       = Character::Editor::VERSION
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.summary       = 'Character WYSIWYG editor'
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.license       = 'MIT'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              gem.authors       = ['Alexander Kravets']
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem.email         = 'alex@slatestudio.com'
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem.homepage      = 'https://github.com/slate-studio/character_editor'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              gem.require_paths = ['lib']
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.files         = `git ls-files`.split($\)
         
     | 
| 
      
 16 
     | 
    
         
            +
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         
     | 
| 
      
 17 
     | 
    
         
            +
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Supress the warning about no rubyforge project
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.rubyforge_project = 'nowarning'
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: character_editor
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Alexander Kravets
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-02-07 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies: []
         
     | 
| 
      
 13 
     | 
    
         
            +
            description: 
         
     | 
| 
      
 14 
     | 
    
         
            +
            email: alex@slatestudio.com
         
     | 
| 
      
 15 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 16 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 17 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 18 
     | 
    
         
            +
            files:
         
     | 
| 
      
 19 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 20 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 21 
     | 
    
         
            +
            - Gemfile.lock
         
     | 
| 
      
 22 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 23 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 24 
     | 
    
         
            +
            - app/assets/javascripts/character_editor.coffee
         
     | 
| 
      
 25 
     | 
    
         
            +
            - app/assets/javascripts/character_editor/_selection.coffee
         
     | 
| 
      
 26 
     | 
    
         
            +
            - app/assets/javascripts/character_editor/_toolbar.coffee
         
     | 
| 
      
 27 
     | 
    
         
            +
            - app/assets/stylesheets/character_editor.scss
         
     | 
| 
      
 28 
     | 
    
         
            +
            - character_editor.gemspec
         
     | 
| 
      
 29 
     | 
    
         
            +
            - lib/character_editor.rb
         
     | 
| 
      
 30 
     | 
    
         
            +
            - lib/character_editor/engine.rb
         
     | 
| 
      
 31 
     | 
    
         
            +
            - lib/character_editor/version.rb
         
     | 
| 
      
 32 
     | 
    
         
            +
            homepage: https://github.com/slate-studio/character_editor
         
     | 
| 
      
 33 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 34 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 35 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 36 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 37 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 38 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 39 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 40 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 41 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 42 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 43 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 44 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 45 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 46 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 47 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 48 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 49 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 50 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 51 
     | 
    
         
            +
            rubyforge_project: nowarning
         
     | 
| 
      
 52 
     | 
    
         
            +
            rubygems_version: 2.2.1
         
     | 
| 
      
 53 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 54 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 55 
     | 
    
         
            +
            summary: Character WYSIWYG editor
         
     | 
| 
      
 56 
     | 
    
         
            +
            test_files: []
         
     |