mercury-rails 0.2.0 → 0.2.3
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.
- data/POST_INSTALL +15 -0
 - data/README.md +27 -6
 - data/VERSION +1 -1
 - data/app/controllers/mercury_controller.rb +4 -4
 - data/app/views/layouts/mercury.html.erb +14 -3
 - data/app/views/mercury/panels/snippets.html +1 -1
 - data/app/views/mercury/snippets/{example_options.html.erb → example/options.html.erb} +0 -0
 - data/app/views/mercury/snippets/{example.html.erb → example/preview.html.erb} +0 -0
 - data/config/routes.rb +2 -2
 - data/features/loading/loading.feature +22 -0
 - data/features/loading/navigating.feature +77 -0
 - data/features/loading/user_interface.feature +67 -0
 - data/features/regions/editable/advanced_editing.feature +0 -0
 - data/features/regions/editable/basic_editing.feature +195 -0
 - data/features/regions/editable/inserting_links.feature +98 -0
 - data/features/regions/editable/inserting_media.feature +110 -0
 - data/features/regions/editable/inserting_snippets.feature +103 -0
 - data/features/regions/editable/inserting_special_characters.feature +24 -0
 - data/features/regions/editable/inserting_tables.feature +109 -0
 - data/features/regions/editable/pasting.feature +0 -0
 - data/features/regions/editable/uploading_images.feature +0 -0
 - data/features/regions/markupable/advanced_editing.feature +0 -0
 - data/features/regions/markupable/basic_editing.feature +0 -0
 - data/features/regions/markupable/inserting_links.feature +0 -0
 - data/features/regions/markupable/inserting_media.feature +0 -0
 - data/features/regions/markupable/inserting_snippets.feature +0 -0
 - data/features/regions/markupable/inserting_special_characters.feature +0 -0
 - data/features/regions/markupable/inserting_tables.feature +0 -0
 - data/features/regions/markupable/uploading_images.feature +0 -0
 - data/features/regions/snippetable/advanced_editing.feature +0 -0
 - data/features/regions/snippetable/basic_editing.feature +0 -0
 - data/features/regions/snippetable/inserting_snippets.feature +0 -0
 - data/features/saving/saving.feature +33 -0
 - data/features/step_definitions/debug_steps.rb +2 -2
 - data/features/step_definitions/mercury_steps.rb +441 -0
 - data/features/support/env.rb +3 -3
 - data/features/support/mercury_contents.rb +25 -0
 - data/features/support/mercury_selectors.rb +147 -0
 - data/features/support/paths.rb +20 -18
 - data/features/support/selectors.rb +5 -3
 - data/lib/generators/mercury/install/install_generator.rb +14 -0
 - data/mercury-rails.gemspec +50 -20
 - data/spec/javascripts/mercury/lightview_spec.js.coffee +55 -27
 - data/spec/javascripts/mercury/mercury_spec.js.coffee +3 -3
 - data/spec/javascripts/mercury/modal_spec.js.coffee +2 -2
 - data/spec/javascripts/mercury/native_extensions_spec.js.coffee +0 -24
 - data/spec/javascripts/mercury/page_editor_spec.js.coffee +148 -67
 - data/spec/javascripts/mercury/panel_spec.js.coffee +2 -2
 - data/spec/javascripts/mercury/region_spec.js.coffee +10 -7
 - data/spec/javascripts/mercury/regions/editable_spec.js.coffee +0 -20
 - data/spec/javascripts/mercury/snippet_toolbar_spec.js.coffee +2 -2
 - data/spec/javascripts/mercury/toolbar.button_group_spec.js.coffee +1 -1
 - data/spec/javascripts/mercury/toolbar.expander_spec.js.coffee +1 -1
 - data/spec/javascripts/templates/mercury/page_editor.html +3 -3
 - data/vendor/assets/images/mercury/close.png +0 -0
 - data/vendor/assets/javascripts/mercury.js +140 -73
 - data/vendor/assets/javascripts/{mercury_dependencies → mercury/dependencies}/jquery-1.6.js +0 -0
 - data/vendor/assets/javascripts/{mercury_dependencies → mercury/dependencies}/jquery-ui-1.8.13.custom.js +0 -0
 - data/vendor/assets/javascripts/{mercury_dependencies → mercury/dependencies}/jquery.additions.js +0 -0
 - data/vendor/assets/javascripts/mercury/dependencies/jquery.htmlClean.js +527 -0
 - data/vendor/assets/javascripts/{mercury_dependencies → mercury/dependencies}/liquidmetal.js +0 -0
 - data/vendor/assets/javascripts/{mercury_dependencies → mercury/dependencies}/showdown.js +0 -0
 - data/vendor/assets/javascripts/mercury/lightview.js.coffee +5 -2
 - data/vendor/assets/javascripts/mercury/mercury.js.coffee +9 -8
 - data/vendor/assets/javascripts/mercury/modals/htmleditor.js.coffee +3 -1
 - data/vendor/assets/javascripts/mercury/modals/inserttable.js.coffee +2 -2
 - data/vendor/assets/javascripts/mercury/native_extensions.js.coffee +6 -17
 - data/vendor/assets/javascripts/mercury/page_editor.js.coffee +29 -8
 - data/vendor/assets/javascripts/mercury/plugins/save_as_xml/mercury/page_editor.js.coffee +27 -0
 - data/vendor/assets/javascripts/mercury/plugins/save_as_xml/plugin.js +9 -0
 - data/vendor/assets/javascripts/mercury/region.js.coffee +2 -2
 - data/vendor/assets/javascripts/mercury/regions/editable.js.coffee +89 -93
 - data/vendor/assets/javascripts/mercury/regions/markupable.js.coffee +1 -1
 - data/vendor/assets/javascripts/mercury/support/history.js +1 -0
 - data/vendor/assets/javascripts/mercury/uploader.js.coffee +0 -1
 - data/vendor/assets/javascripts/mercury_loader.js +4 -4
 - data/vendor/assets/stylesheets/mercury/lightview.css +8 -0
 - data/vendor/assets/stylesheets/mercury/mercury.css +12 -0
 - data/vendor/assets/stylesheets/mercury/modal.css +0 -12
 - data/vendor/assets/stylesheets/mercury/toolbar.css +1 -0
 - data/vendor/assets/stylesheets/mercury_overrides.css +17 -0
 - metadata +73 -45
 - data/app/views/mercury/lightviews/imageprocessor.html +0 -3
 - data/app/views/mercury/modals/sanitizer.html +0 -9
 - data/features/editing/basic.feature +0 -11
 - data/vendor/assets/images/mercury/clippy.png +0 -0
 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         @@ -27,6 +27,8 @@ jQuery.extend Mercury.lightview, { 
     | 
|
| 
       27 
27 
     | 
    
         
             
                @overlay = jQuery('<div>', {class: 'mercury-lightview-overlay'})
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                @titleElement = @element.find('.mercury-lightview-title')
         
     | 
| 
      
 30 
     | 
    
         
            +
                @titleElement.append('<a class="mercury-lightview-close"></a>') if @options.closeButton
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       30 
32 
     | 
    
         
             
                @contentElement = @element.find('.mercury-lightview-content')
         
     | 
| 
       31 
33 
     | 
    
         | 
| 
       32 
34 
     | 
    
         
             
                @element.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
         
     | 
| 
         @@ -39,7 +41,8 @@ jQuery.extend Mercury.lightview, { 
     | 
|
| 
       39 
41 
     | 
    
         
             
                Mercury.bind 'refresh', => @resize(true)
         
     | 
| 
       40 
42 
     | 
    
         
             
                Mercury.bind 'resize', => @position() if @visible
         
     | 
| 
       41 
43 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                @overlay.click => @hide()
         
     | 
| 
      
 44 
     | 
    
         
            +
                @overlay.click => @hide() unless @options.closeButton
         
     | 
| 
      
 45 
     | 
    
         
            +
                @titleElement.find('.mercury-lightview-close').click => @hide()
         
     | 
| 
       43 
46 
     | 
    
         | 
| 
       44 
47 
     | 
    
         
             
                jQuery(document).bind 'keydown', (event) =>
         
     | 
| 
       45 
48 
     | 
    
         
             
                   @hide() if event.keyCode == 27 && @visible
         
     | 
| 
         @@ -52,7 +55,7 @@ jQuery.extend Mercury.lightview, { 
     | 
|
| 
       52 
55 
     | 
    
         
             
                @overlay.animate {opacity: 1}, 200, 'easeInOutSine', =>
         
     | 
| 
       53 
56 
     | 
    
         
             
                  @setTitle()
         
     | 
| 
       54 
57 
     | 
    
         
             
                  @element.show().css({opacity: 0})
         
     | 
| 
       55 
     | 
    
         
            -
                  @element.animate {opacity: 1}, 200, 'easeInOutSine', =>
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @element.stop().animate {opacity: 1}, 200, 'easeInOutSine', =>
         
     | 
| 
       56 
59 
     | 
    
         
             
                    @visible = true
         
     | 
| 
       57 
60 
     | 
    
         
             
                    @load()
         
     | 
| 
       58 
61 
     | 
    
         | 
| 
         @@ -1,9 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # ## Require all the dependencies
         
     | 
| 
       2 
     | 
    
         
            -
            #= require  
     | 
| 
       3 
     | 
    
         
            -
            #= require  
     | 
| 
       4 
     | 
    
         
            -
            #= require  
     | 
| 
       5 
     | 
    
         
            -
            #= require  
     | 
| 
       6 
     | 
    
         
            -
            #= require  
     | 
| 
      
 2 
     | 
    
         
            +
            #= require mercury/dependencies/jquery-1.6
         
     | 
| 
      
 3 
     | 
    
         
            +
            #= require mercury/dependencies/jquery-ui-1.8.13.custom
         
     | 
| 
      
 4 
     | 
    
         
            +
            #= require mercury/dependencies/jquery.additions
         
     | 
| 
      
 5 
     | 
    
         
            +
            #= require mercury/dependencies/jquery.htmlClean
         
     | 
| 
      
 6 
     | 
    
         
            +
            #= require mercury/dependencies/liquidmetal
         
     | 
| 
      
 7 
     | 
    
         
            +
            #= require mercury/dependencies/showdown
         
     | 
| 
       7 
8 
     | 
    
         
             
            #
         
     | 
| 
       8 
9 
     | 
    
         
             
            # ## Require all mercury files
         
     | 
| 
       9 
10 
     | 
    
         
             
            #= require_self
         
     | 
| 
         @@ -33,7 +34,7 @@ 
     | 
|
| 
       33 
34 
     | 
    
         
             
            #
         
     | 
| 
       34 
35 
     | 
    
         
             
            @Mercury ||= {}
         
     | 
| 
       35 
36 
     | 
    
         
             
            jQuery.extend @Mercury, {
         
     | 
| 
       36 
     | 
    
         
            -
              version: '0.2. 
     | 
| 
      
 37 
     | 
    
         
            +
              version: '0.2.3'
         
     | 
| 
       37 
38 
     | 
    
         | 
| 
       38 
39 
     | 
    
         
             
              # No IE support yet because it doesn't follow the W3C standards for HTML5 contentEditable (aka designMode).
         
     | 
| 
       39 
40 
     | 
    
         
             
              supported: document.getElementById && document.designMode && !jQuery.browser.konqueror && !jQuery.browser.msie
         
     | 
| 
         @@ -47,12 +48,12 @@ jQuery.extend @Mercury, { 
     | 
|
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
              # Custom event and logging methods
         
     | 
| 
       49 
50 
     | 
    
         
             
              bind: (eventName, callback) ->
         
     | 
| 
       50 
     | 
    
         
            -
                jQuery( 
     | 
| 
      
 51 
     | 
    
         
            +
                jQuery(top).bind("mercury:#{eventName}", callback)
         
     | 
| 
       51 
52 
     | 
    
         | 
| 
       52 
53 
     | 
    
         | 
| 
       53 
54 
     | 
    
         
             
              trigger: (eventName, options) ->
         
     | 
| 
       54 
55 
     | 
    
         
             
                Mercury.log(eventName, options)
         
     | 
| 
       55 
     | 
    
         
            -
                jQuery( 
     | 
| 
      
 56 
     | 
    
         
            +
                jQuery(top).trigger("mercury:#{eventName}", options)
         
     | 
| 
       56 
57 
     | 
    
         | 
| 
       57 
58 
     | 
    
         | 
| 
       58 
59 
     | 
    
         
             
              log: ->
         
     | 
| 
         @@ -1,6 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            @Mercury.modalHandlers.htmlEditor = ->
         
     | 
| 
       2 
2 
     | 
    
         
             
              # fill the text area with the content
         
     | 
| 
       3 
     | 
    
         
            -
               
     | 
| 
      
 3 
     | 
    
         
            +
              content = Mercury.region.content(null, true, false)
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  content = jQuery.htmlClean(content, {format: true, replace: [], allowedClasses: ['mercury-snippet']})
         
     | 
| 
      
 5 
     | 
    
         
            +
              @element.find('textarea').val(content)
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
              # replace the contents on form submit
         
     | 
| 
       6 
8 
     | 
    
         
             
              @element.find('form').submit (event) =>
         
     | 
| 
         @@ -5,7 +5,7 @@ 
     | 
|
| 
       5 
5 
     | 
    
         
             
              table.click (event) =>
         
     | 
| 
       6 
6 
     | 
    
         
             
                cell = jQuery(event.target)
         
     | 
| 
       7 
7 
     | 
    
         
             
                table = cell.closest('table')
         
     | 
| 
       8 
     | 
    
         
            -
                table.find('.selected'). 
     | 
| 
      
 8 
     | 
    
         
            +
                table.find('.selected').removeAttr('class')
         
     | 
| 
       9 
9 
     | 
    
         
             
                cell.addClass('selected')
         
     | 
| 
       10 
10 
     | 
    
         
             
                Mercury.tableEditor(table, cell, ' ')
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -44,7 +44,7 @@ 
     | 
|
| 
       44 
44 
     | 
    
         
             
              # build the table on form submission
         
     | 
| 
       45 
45 
     | 
    
         
             
              @element.find('form').submit (event) =>
         
     | 
| 
       46 
46 
     | 
    
         
             
                event.preventDefault()
         
     | 
| 
       47 
     | 
    
         
            -
                table.find('.selected'). 
     | 
| 
      
 47 
     | 
    
         
            +
                table.find('.selected').removeAttr('class')
         
     | 
| 
       48 
48 
     | 
    
         
             
                table.find('td, th').html(' ')
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
                html = jQuery('<div>').html(table).html()
         
     | 
| 
         @@ -9,23 +9,6 @@ String::toHex = -> 
     | 
|
| 
       9 
9 
     | 
    
         
             
                "##{parseInt(r).toHex()}#{parseInt(g).toHex()}#{parseInt(b).toHex()}"
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            String::singleDiff = (that) ->
         
     | 
| 
       13 
     | 
    
         
            -
              diff = ''
         
     | 
| 
       14 
     | 
    
         
            -
              for char, index in that
         
     | 
| 
       15 
     | 
    
         
            -
                break if char == 'each'
         
     | 
| 
       16 
     | 
    
         
            -
                if char != @[index]
         
     | 
| 
       17 
     | 
    
         
            -
                  re = new RegExp(@substr(index).regExpEscape().replace(/^\s+|^( )+/g, '') + '$', 'm')
         
     | 
| 
       18 
     | 
    
         
            -
                  diff = that.substr(index).replace(re, '')
         
     | 
| 
       19 
     | 
    
         
            -
                  break
         
     | 
| 
       20 
     | 
    
         
            -
              return diff
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
            String::regExpEscape = ->
         
     | 
| 
       24 
     | 
    
         
            -
              specials = ['/','.','*','+','?','|','(',')','[',']','{','}','\\']
         
     | 
| 
       25 
     | 
    
         
            -
              escaped = new RegExp('(\\' + specials.join('|\\') + ')', 'g')
         
     | 
| 
       26 
     | 
    
         
            -
              return @replace(escaped, '\\$1')
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
12 
     | 
    
         
             
            String::sanitizeHTML = ->
         
     | 
| 
       30 
13 
     | 
    
         
             
              element = jQuery('<div>').html(@.toString())
         
     | 
| 
       31 
14 
     | 
    
         
             
              element.find('style').remove()
         
     | 
| 
         @@ -46,3 +29,9 @@ Number::toBytes = -> 
     | 
|
| 
       46 
29 
     | 
    
         
             
                bytes /= 1024
         
     | 
| 
       47 
30 
     | 
    
         
             
                i += 1
         
     | 
| 
       48 
31 
     | 
    
         
             
              return if i then "#{bytes.toFixed(2)}#{['', ' kb', ' Mb', ' Gb', ' Tb', ' Pb', ' Eb'][i]}" else "#{bytes} bytes"
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            # make setTimeout not suck for coffeescript
         
     | 
| 
      
 35 
     | 
    
         
            +
            window.originalSetTimeout = window.setTimeout
         
     | 
| 
      
 36 
     | 
    
         
            +
            window.setTimeout = (arg1, arg2) ->
         
     | 
| 
      
 37 
     | 
    
         
            +
              if typeof(arg1) == 'number' then window.originalSetTimeout(arg2, arg1) else window.originalSetTimeout(arg1, arg2)
         
     | 
| 
         @@ -2,6 +2,8 @@ class @Mercury.PageEditor 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
              # options
         
     | 
| 
       4 
4 
     | 
    
         
             
              # saveStyle: 'form', or 'json' (defaults to json)
         
     | 
| 
      
 5 
     | 
    
         
            +
              # saveDataType: 'xml', 'json', 'jsonp', 'script', 'text', 'html' (defaults to json)
         
     | 
| 
      
 6 
     | 
    
         
            +
              # saveMethod: 'POST', or 'PUT', create or update actions on save (defaults to POST)
         
     | 
| 
       5 
7 
     | 
    
         
             
              # visible: boolean, if the interface should start visible or not (defaults to true)
         
     | 
| 
       6 
8 
     | 
    
         
             
              constructor: (@saveUrl = null, @options = {}) ->
         
     | 
| 
       7 
9 
     | 
    
         
             
                throw "Mercury.PageEditor is unsupported in this client. Supported browsers are chrome 10+, firefix 4+, and safari 5+." unless Mercury.supported
         
     | 
| 
         @@ -17,8 +19,9 @@ class @Mercury.PageEditor 
     | 
|
| 
       17 
19 
     | 
    
         | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
              initializeInterface: ->
         
     | 
| 
       20 
     | 
    
         
            -
                @focusableElement = jQuery('<input>', { 
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                @focusableElement = jQuery('<input>', {class: 'mercury-focusable', type: 'text'}).appendTo(@options.appendTo ? 'body')
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                @iframe = jQuery('<iframe>', {id: 'mercury_iframe', class: 'mercury-iframe', seamless: 'true', frameborder: '0', src: 'about:blank'})
         
     | 
| 
       22 
25 
     | 
    
         
             
                @iframe.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
         
     | 
| 
       23 
26 
     | 
    
         | 
| 
       24 
27 
     | 
    
         
             
                @iframe.load => @initializeFrame()
         
     | 
| 
         @@ -32,8 +35,10 @@ class @Mercury.PageEditor 
     | 
|
| 
       32 
35 
     | 
    
         
             
                try
         
     | 
| 
       33 
36 
     | 
    
         
             
                  return if @iframe.data('loaded')
         
     | 
| 
       34 
37 
     | 
    
         
             
                  @iframe.data('loaded', true)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  alert("Opera isn't a fully supported browser, your results may not be optimal.") if jQuery.browser.opera
         
     | 
| 
       35 
39 
     | 
    
         
             
                  @document = jQuery(@iframe.get(0).contentWindow.document)
         
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
      
 40 
     | 
    
         
            +
                  stylesToInject = Mercury.config.injectedStyles.replace(/{{regionClass}}/g, Mercury.config.regionClass)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  jQuery("<style mercury-styles=\"true\">").html(stylesToInject).appendTo(@document.find('head'))
         
     | 
| 
       37 
42 
     | 
    
         | 
| 
       38 
43 
     | 
    
         
             
                  # jquery: make jQuery evaluate scripts within the context of the iframe window -- note that this means that we
         
     | 
| 
       39 
44 
     | 
    
         
             
                  # can't use eval in mercury (eg. script tags in ajax responses) because it will eval in the wrong context (you can
         
     | 
| 
         @@ -41,13 +46,18 @@ class @Mercury.PageEditor 
     | 
|
| 
       41 
46 
     | 
    
         
             
                  # todo: look into `context` options for ajax as an alternative
         
     | 
| 
       42 
47 
     | 
    
         
             
                  iframeWindow = @iframe.get(0).contentWindow
         
     | 
| 
       43 
48 
     | 
    
         
             
                  jQuery.globalEval = (data) -> (iframeWindow.execScript || (data) -> iframeWindow["eval"].call(iframeWindow, data))(data) if (data && /\S/.test(data))
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       44 
50 
     | 
    
         
             
                  iframeWindow.Mercury = Mercury
         
     | 
| 
      
 51 
     | 
    
         
            +
                  iframeWindow.History = History if window.History && History.Adapter
         
     | 
| 
       45 
52 
     | 
    
         | 
| 
       46 
53 
     | 
    
         
             
                  @bindEvents()
         
     | 
| 
       47 
54 
     | 
    
         
             
                  @resize()
         
     | 
| 
       48 
55 
     | 
    
         
             
                  @initializeRegions()
         
     | 
| 
       49 
56 
     | 
    
         
             
                  @finalizeInterface()
         
     | 
| 
       50 
57 
     | 
    
         
             
                  Mercury.trigger('ready')
         
     | 
| 
      
 58 
     | 
    
         
            +
                  jQuery(iframeWindow).trigger('mercury:ready')
         
     | 
| 
      
 59 
     | 
    
         
            +
                  iframeWindow.Event.fire(iframeWindow, 'mercury:ready') if iframeWindow.Event && iframeWindow.Event.fire
         
     | 
| 
      
 60 
     | 
    
         
            +
                  iframeWindow.onMercuryReady() if iframeWindow.onMercuryReady
         
     | 
| 
       51 
61 
     | 
    
         | 
| 
       52 
62 
     | 
    
         
             
                  @iframe.css({visibility: 'visible'})
         
     | 
| 
       53 
63 
     | 
    
         
             
                catch error
         
     | 
| 
         @@ -55,7 +65,7 @@ class @Mercury.PageEditor 
     | 
|
| 
       55 
65 
     | 
    
         | 
| 
       56 
66 
     | 
    
         | 
| 
       57 
67 
     | 
    
         
             
              initializeRegions: ->
         
     | 
| 
       58 
     | 
    
         
            -
                @buildRegion(jQuery(region)) for region in jQuery( 
     | 
| 
      
 68 
     | 
    
         
            +
                @buildRegion(jQuery(region)) for region in jQuery(".#{Mercury.config.regionClass}", @document)
         
     | 
| 
       59 
69 
     | 
    
         
             
                return unless @options.visible
         
     | 
| 
       60 
70 
     | 
    
         
             
                for region in @regions
         
     | 
| 
       61 
71 
     | 
    
         
             
                  if region.focus
         
     | 
| 
         @@ -73,6 +83,9 @@ class @Mercury.PageEditor 
     | 
|
| 
       73 
83 
     | 
    
         | 
| 
       74 
84 
     | 
    
         | 
| 
       75 
85 
     | 
    
         
             
              finalizeInterface: ->
         
     | 
| 
      
 86 
     | 
    
         
            +
                @santizerElement = jQuery('<div>', {id: 'mercury_sanitizer', contenteditable: 'true', style: 'position:fixed;width:100px;height:100px;top:-100px;left:-100px;opacity:0'})
         
     | 
| 
      
 87 
     | 
    
         
            +
                @santizerElement.appendTo(@options.appendTo ? @document.find('body'))
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
       76 
89 
     | 
    
         
             
                @snippetToolbar = new Mercury.SnippetToolbar(@document)
         
     | 
| 
       77 
90 
     | 
    
         | 
| 
       78 
91 
     | 
    
         
             
                @hijackLinksAndForms()
         
     | 
| 
         @@ -92,7 +105,7 @@ class @Mercury.PageEditor 
     | 
|
| 
       92 
105 
     | 
    
         
             
                @document.mousedown (event) ->
         
     | 
| 
       93 
106 
     | 
    
         
             
                  Mercury.trigger('hide:dialogs')
         
     | 
| 
       94 
107 
     | 
    
         
             
                  if Mercury.region
         
     | 
| 
       95 
     | 
    
         
            -
                    Mercury.trigger('unfocus:regions') unless jQuery(event.target).closest( 
     | 
| 
      
 108 
     | 
    
         
            +
                    Mercury.trigger('unfocus:regions') unless jQuery(event.target).closest(".#{Mercury.config.regionClass}").get(0) == Mercury.region.element.get(0)
         
     | 
| 
       96 
109 
     | 
    
         | 
| 
       97 
110 
     | 
    
         
             
                jQuery(window).resize => @resize()
         
     | 
| 
       98 
111 
     | 
    
         
             
                window.onbeforeunload = @beforeUnload
         
     | 
| 
         @@ -138,7 +151,7 @@ class @Mercury.PageEditor 
     | 
|
| 
       138 
151 
     | 
    
         
             
                    if jQuery(element).hasClass(classname)
         
     | 
| 
       139 
152 
     | 
    
         
             
                      ignored = true
         
     | 
| 
       140 
153 
     | 
    
         
             
                      continue
         
     | 
| 
       141 
     | 
    
         
            -
                  if !ignored && (element.target == '' || element.target == '_self') && !jQuery(element).closest( 
     | 
| 
      
 154 
     | 
    
         
            +
                  if !ignored && (element.target == '' || element.target == '_self') && !jQuery(element).closest(".#{Mercury.config.regionClass}").length
         
     | 
| 
       142 
155 
     | 
    
         
             
                    jQuery(element).attr('target', '_top')
         
     | 
| 
       143 
156 
     | 
    
         | 
| 
       144 
157 
     | 
    
         | 
| 
         @@ -148,15 +161,23 @@ class @Mercury.PageEditor 
     | 
|
| 
       148 
161 
     | 
    
         
             
                return null
         
     | 
| 
       149 
162 
     | 
    
         | 
| 
       150 
163 
     | 
    
         | 
| 
      
 164 
     | 
    
         
            +
              getRegionByName: (id) ->
         
     | 
| 
      
 165 
     | 
    
         
            +
                for region in @regions
         
     | 
| 
      
 166 
     | 
    
         
            +
                  return region if region.name == id
         
     | 
| 
      
 167 
     | 
    
         
            +
                return null
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
       151 
170 
     | 
    
         
             
              save: ->
         
     | 
| 
       152 
171 
     | 
    
         
             
                url = @saveUrl ? Mercury.saveURL ? @iframeSrc()
         
     | 
| 
       153 
172 
     | 
    
         
             
                data = @serialize()
         
     | 
| 
       154 
173 
     | 
    
         
             
                Mercury.log('saving', data)
         
     | 
| 
       155 
174 
     | 
    
         
             
                data = jQuery.toJSON(data) unless @options.saveStyle == 'form'
         
     | 
| 
      
 175 
     | 
    
         
            +
                method = 'PUT' if @options.saveMethod == 'PUT'
         
     | 
| 
       156 
176 
     | 
    
         
             
                jQuery.ajax url, {
         
     | 
| 
       157 
     | 
    
         
            -
                  type: 'POST'
         
     | 
| 
      
 177 
     | 
    
         
            +
                  type: method || 'POST'
         
     | 
| 
      
 178 
     | 
    
         
            +
                  dataType: @options.saveDataType || 'json'
         
     | 
| 
       158 
179 
     | 
    
         
             
                  headers: @saveHeaders()
         
     | 
| 
       159 
     | 
    
         
            -
                  data: {content: data}
         
     | 
| 
      
 180 
     | 
    
         
            +
                  data: {content: data, _method: method}
         
     | 
| 
       160 
181 
     | 
    
         
             
                  success: =>
         
     | 
| 
       161 
182 
     | 
    
         
             
                    Mercury.changes = false
         
     | 
| 
       162 
183 
     | 
    
         
             
                  error: =>
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Mercury.PageEditor extends Mercury.PageEditor
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              save: ->
         
     | 
| 
      
 4 
     | 
    
         
            +
                url = @saveUrl ? Mercury.saveURL ? @iframeSrc()
         
     | 
| 
      
 5 
     | 
    
         
            +
                data = @serializeAsXml()
         
     | 
| 
      
 6 
     | 
    
         
            +
                console.log('saving', data)
         
     | 
| 
      
 7 
     | 
    
         
            +
                return
         
     | 
| 
      
 8 
     | 
    
         
            +
                method = 'PUT' if @options.saveMethod == 'PUT'
         
     | 
| 
      
 9 
     | 
    
         
            +
                jQuery.ajax url, {
         
     | 
| 
      
 10 
     | 
    
         
            +
                  type: method || 'POST'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  dataType: 'xml'
         
     | 
| 
      
 12 
     | 
    
         
            +
                  data: data
         
     | 
| 
      
 13 
     | 
    
         
            +
                  success: =>
         
     | 
| 
      
 14 
     | 
    
         
            +
                    Mercury.changes = false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  error: =>
         
     | 
| 
      
 16 
     | 
    
         
            +
                    alert("Mercury was unable to save to the url: #{url}")
         
     | 
| 
      
 17 
     | 
    
         
            +
                }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              serializeAsXml: ->
         
     | 
| 
      
 20 
     | 
    
         
            +
                data = @serialize()
         
     | 
| 
      
 21 
     | 
    
         
            +
                regionNodes = []
         
     | 
| 
      
 22 
     | 
    
         
            +
                for regionName, regionProperties of data
         
     | 
| 
      
 23 
     | 
    
         
            +
                  snippetNodes = []
         
     | 
| 
      
 24 
     | 
    
         
            +
                  for snippetName, snippetProperties of regionProperties['snippets']
         
     | 
| 
      
 25 
     | 
    
         
            +
                    snippetNodes.push("<#{snippetName} name=\"#{snippetProperties['name']}\"><![CDATA[#{jQuery.toJSON(snippetProperties['options'])}]]></#{snippetName}>")
         
     | 
| 
      
 26 
     | 
    
         
            +
                  regionNodes.push("<region name=\"#{regionName}\" type=\"#{regionProperties['type']}\"><value>\n<![CDATA[#{regionProperties['value']}]]>\n</value><snippets>#{snippetNodes.join('')}</snippets></region>")
         
     | 
| 
      
 27 
     | 
    
         
            +
                return "<regions>#{regionNodes.join('')}</regions>"
         
     | 
| 
         @@ -0,0 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*!
         
     | 
| 
      
 2 
     | 
    
         
            +
             * This is an example plugin that will serialize to XML instead of JSON before saving.  This could be useful to someone,
         
     | 
| 
      
 3 
     | 
    
         
            +
             * but is mostly provided as an example of how to write a simple plugin.
         
     | 
| 
      
 4 
     | 
    
         
            +
             *
         
     | 
| 
      
 5 
     | 
    
         
            +
             * This file is could be a nice place to provide configuration options for your plugin.
         
     | 
| 
      
 6 
     | 
    
         
            +
             *
         
     | 
| 
      
 7 
     | 
    
         
            +
             *= require_self
         
     | 
| 
      
 8 
     | 
    
         
            +
             *= require_tree ./mercury
         
     | 
| 
      
 9 
     | 
    
         
            +
             */
         
     | 
| 
         @@ -66,11 +66,11 @@ class @Mercury.Region 
     | 
|
| 
       66 
66 
     | 
    
         
             
              togglePreview: ->
         
     | 
| 
       67 
67 
     | 
    
         
             
                if @previewing
         
     | 
| 
       68 
68 
     | 
    
         
             
                  @previewing = false
         
     | 
| 
       69 
     | 
    
         
            -
                  @element.addClass( 
     | 
| 
      
 69 
     | 
    
         
            +
                  @element.addClass(Mercury.config.regionClass).removeClass("#{Mercury.config.regionClass}-preview")
         
     | 
| 
       70 
70 
     | 
    
         
             
                  @focus() if Mercury.region == @
         
     | 
| 
       71 
71 
     | 
    
         
             
                else
         
     | 
| 
       72 
72 
     | 
    
         
             
                  @previewing = true
         
     | 
| 
       73 
     | 
    
         
            -
                  @element.addClass( 
     | 
| 
      
 73 
     | 
    
         
            +
                  @element.addClass("#{Mercury.config.regionClass}-preview").removeClass(Mercury.config.regionClass)
         
     | 
| 
       74 
74 
     | 
    
         
             
                  Mercury.trigger('region:blurred', {region: @})
         
     | 
| 
       75 
75 
     | 
    
         | 
| 
       76 
76 
     | 
    
         | 
| 
         @@ -28,11 +28,14 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                # add the basic editor settings to the document (only once)
         
     | 
| 
       30 
30 
     | 
    
         
             
                unless @document.mercuryEditing
         
     | 
| 
       31 
     | 
    
         
            -
                  @document.execCommand('styleWithCSS', false, false)
         
     | 
| 
       32 
     | 
    
         
            -
                  @document.execCommand('insertBROnReturn', false, true)
         
     | 
| 
       33 
     | 
    
         
            -
                  @document.execCommand('enableInlineTableEditing', false, false)
         
     | 
| 
       34 
     | 
    
         
            -
                  @document.execCommand('enableObjectResizing', false, false)
         
     | 
| 
       35 
31 
     | 
    
         
             
                  @document.mercuryEditing = true
         
     | 
| 
      
 32 
     | 
    
         
            +
                  try
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @document.execCommand('styleWithCSS', false, false)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @document.execCommand('insertBROnReturn', false, true)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @document.execCommand('enableInlineTableEditing', false, false)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @document.execCommand('enableObjectResizing', false, false)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  catch e
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # intentionally do nothing if any of these fail, to broaden support for Opera
         
     | 
| 
       36 
39 
     | 
    
         | 
| 
       37 
40 
     | 
    
         | 
| 
       38 
41 
     | 
    
         
             
              bindEvents: ->
         
     | 
| 
         @@ -85,7 +88,7 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       85 
88 
     | 
    
         
             
                # isn't handled (eg, putting the image where it was dropped,) so to allow the browser to do it's thing, and also do
         
     | 
| 
       86 
89 
     | 
    
         
             
                # our thing we have this little hack.  *sigh*
         
     | 
| 
       87 
90 
     | 
    
         
             
                # read: http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
         
     | 
| 
       88 
     | 
    
         
            -
                @element.bind 'possible:drop',  
     | 
| 
      
 91 
     | 
    
         
            +
                @element.bind 'possible:drop', =>
         
     | 
| 
       89 
92 
     | 
    
         
             
                  return if @previewing
         
     | 
| 
       90 
93 
     | 
    
         
             
                  if snippet = @element.find('img[data-snippet]').get(0)
         
     | 
| 
       91 
94 
     | 
    
         
             
                    @focus()
         
     | 
| 
         @@ -96,16 +99,15 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       96 
99 
     | 
    
         
             
                # through a clipboard in firefox (heaven forbid), and to keep the behavior across all browsers, we manually detect
         
     | 
| 
       97 
100 
     | 
    
         
             
                # what was pasted by running a quick diff, removing it by calling undo, making our adjustments, and then putting the
         
     | 
| 
       98 
101 
     | 
    
         
             
                # content back.  This is possible, so it doesn't make sense why it wouldn't be exposed in a sensible way.  *sigh*
         
     | 
| 
       99 
     | 
    
         
            -
                @element.bind 'paste', =>
         
     | 
| 
      
 102 
     | 
    
         
            +
                @element.bind 'paste', (event) =>
         
     | 
| 
       100 
103 
     | 
    
         
             
                  return if @previewing
         
     | 
| 
       101 
104 
     | 
    
         
             
                  return unless Mercury.region == @
         
     | 
| 
       102 
     | 
    
         
            -
                  Mercury.changes = true
         
     | 
| 
       103 
105 
     | 
    
         
             
                  if @specialContainer
         
     | 
| 
       104 
106 
     | 
    
         
             
                    event.preventDefault()
         
     | 
| 
       105 
107 
     | 
    
         
             
                    return
         
     | 
| 
       106 
     | 
    
         
            -
                   
     | 
| 
       107 
     | 
    
         
            -
                   
     | 
| 
       108 
     | 
    
         
            -
                  @ 
     | 
| 
      
 108 
     | 
    
         
            +
                  return if @pasting
         
     | 
| 
      
 109 
     | 
    
         
            +
                  Mercury.changes = true
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @handlePaste(event.originalEvent)
         
     | 
| 
       109 
111 
     | 
    
         | 
| 
       110 
112 
     | 
    
         
             
                @element.focus =>
         
     | 
| 
       111 
113 
     | 
    
         
             
                  return if @previewing
         
     | 
| 
         @@ -144,25 +146,27 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       144 
146 
     | 
    
         
             
                      return
         
     | 
| 
       145 
147 
     | 
    
         | 
| 
       146 
148 
     | 
    
         
             
                    when 13 # enter
         
     | 
| 
       147 
     | 
    
         
            -
                      if jQuery.browser.webkit && @selection().commonAncestor().closest('li, ul', @element).length == 0
         
     | 
| 
      
 149 
     | 
    
         
            +
                      if jQuery.browser.webkit && @selection().commonAncestor().closest('li, ul, ol', @element).length == 0
         
     | 
| 
       148 
150 
     | 
    
         
             
                        event.preventDefault()
         
     | 
| 
       149 
     | 
    
         
            -
                        @document.execCommand(' 
     | 
| 
       150 
     | 
    
         
            -
                      else if @specialContainer
         
     | 
| 
       151 
     | 
    
         
            -
                        # mozilla: pressing enter in any  
     | 
| 
      
 151 
     | 
    
         
            +
                        @document.execCommand('insertParagraph', false, null)
         
     | 
| 
      
 152 
     | 
    
         
            +
                      else if @specialContainer || jQuery.browser.opera
         
     | 
| 
      
 153 
     | 
    
         
            +
                        # mozilla: pressing enter in any element besides a div handles strangely
         
     | 
| 
       152 
154 
     | 
    
         
             
                        event.preventDefault()
         
     | 
| 
       153 
155 
     | 
    
         
             
                        @document.execCommand('insertHTML', false, '<br/>')
         
     | 
| 
       154 
156 
     | 
    
         | 
| 
       155 
157 
     | 
    
         
             
                    when 9 # tab
         
     | 
| 
       156 
158 
     | 
    
         
             
                      event.preventDefault()
         
     | 
| 
       157 
159 
     | 
    
         
             
                      container = @selection().commonAncestor()
         
     | 
| 
       158 
     | 
    
         
            -
                      handled = false
         
     | 
| 
       159 
160 
     | 
    
         | 
| 
       160 
161 
     | 
    
         
             
                      # indent when inside of an li
         
     | 
| 
       161 
162 
     | 
    
         
             
                      if container.closest('li', @element).length
         
     | 
| 
       162 
     | 
    
         
            -
                         
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
             
     | 
| 
      
 163 
     | 
    
         
            +
                        unless event.shiftKey
         
     | 
| 
      
 164 
     | 
    
         
            +
                          @execCommand('indent')
         
     | 
| 
      
 165 
     | 
    
         
            +
                        # do not outdent on last ul/ol parent, or we break out of the list
         
     | 
| 
      
 166 
     | 
    
         
            +
                        else if container.parents('ul, ol').length > 1
         
     | 
| 
      
 167 
     | 
    
         
            +
                          @execCommand('outdent')
         
     | 
| 
      
 168 
     | 
    
         
            +
                      else
         
     | 
| 
      
 169 
     | 
    
         
            +
                        @execCommand('insertHTML', {value: '  '})
         
     | 
| 
       166 
170 
     | 
    
         | 
| 
       167 
171 
     | 
    
         
             
                  if event.metaKey
         
     | 
| 
       168 
172 
     | 
    
         
             
                    switch event.keyCode
         
     | 
| 
         @@ -320,78 +324,69 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       320 
324 
     | 
    
         
             
                return element
         
     | 
| 
       321 
325 
     | 
    
         | 
| 
       322 
326 
     | 
    
         | 
| 
       323 
     | 
    
         
            -
              handlePaste: ( 
     | 
| 
       324 
     | 
    
         
            -
                 
     | 
| 
       325 
     | 
    
         
            -
             
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
     | 
    
         
            -
                 
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
             
     | 
| 
       332 
     | 
    
         
            -
                   
     | 
| 
       333 
     | 
    
         
            -
                   
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
             
     | 
| 
       337 
     | 
    
         
            -
             
     | 
| 
       338 
     | 
    
         
            -
                   
     | 
| 
       339 
     | 
    
         
            -
                    #  
     | 
| 
       340 
     | 
    
         
            -
                    @ 
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
             
     | 
| 
       343 
     | 
    
         
            -
             
     | 
| 
       344 
     | 
    
         
            -
                     
     | 
| 
       345 
     | 
    
         
            -
             
     | 
| 
       346 
     | 
    
         
            -
             
     | 
| 
       347 
     | 
    
         
            -
             
     | 
| 
       348 
     | 
    
         
            -
             
     | 
| 
       349 
     | 
    
         
            -
             
     | 
| 
       350 
     | 
    
         
            -
             
     | 
| 
      
 327 
     | 
    
         
            +
              handlePaste: (event) ->
         
     | 
| 
      
 328 
     | 
    
         
            +
                # get the text content from the clipboard and fall back to using the sanitizer if unavailable
         
     | 
| 
      
 329 
     | 
    
         
            +
                if Mercury.config.pasting.sanitize == 'text' && event.clipboardData
         
     | 
| 
      
 330 
     | 
    
         
            +
                  @execCommand('insertHTML', {value: event.clipboardData.getData('text/plain')})
         
     | 
| 
      
 331 
     | 
    
         
            +
                  event.preventDefault()
         
     | 
| 
      
 332 
     | 
    
         
            +
                  return
         
     | 
| 
      
 333 
     | 
    
         
            +
                else
         
     | 
| 
      
 334 
     | 
    
         
            +
                  console.debug('testing')
         
     | 
| 
      
 335 
     | 
    
         
            +
                  # get current selection & range
         
     | 
| 
      
 336 
     | 
    
         
            +
                  selection = @selection()
         
     | 
| 
      
 337 
     | 
    
         
            +
                  selection.placeMarker()
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                  sanitizer = jQuery('#mercury_sanitizer', @document).focus()
         
     | 
| 
      
 340 
     | 
    
         
            +
             
     | 
| 
      
 341 
     | 
    
         
            +
                  # set 1ms timeout to allow paste event to complete
         
     | 
| 
      
 342 
     | 
    
         
            +
                  setTimeout 1, =>
         
     | 
| 
      
 343 
     | 
    
         
            +
                    # sanitize the content
         
     | 
| 
      
 344 
     | 
    
         
            +
                    content = @sanitize(sanitizer)
         
     | 
| 
      
 345 
     | 
    
         
            +
             
     | 
| 
      
 346 
     | 
    
         
            +
                    # move cursor back to original element & position
         
     | 
| 
      
 347 
     | 
    
         
            +
                    selection.selectMarker(@element)
         
     | 
| 
      
 348 
     | 
    
         
            +
                    selection.removeMarker()
         
     | 
| 
      
 349 
     | 
    
         
            +
             
     | 
| 
      
 350 
     | 
    
         
            +
                    # paste sanitized content
         
     | 
| 
      
 351 
     | 
    
         
            +
                    @element.focus()
         
     | 
| 
      
 352 
     | 
    
         
            +
                    @execCommand('insertHTML', {value: content})
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
              sanitize: (sanitizer) ->
         
     | 
| 
      
 356 
     | 
    
         
            +
                # always remove nested regions
         
     | 
| 
      
 357 
     | 
    
         
            +
                sanitizer.find(".#{Mercury.config.regionClass}").remove()
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
                if Mercury.config.pasting.sanitize
         
     | 
| 
      
 360 
     | 
    
         
            +
                  switch Mercury.config.pasting.sanitize
         
     | 
| 
      
 361 
     | 
    
         
            +
                    when 'blacklist'
         
     | 
| 
      
 362 
     | 
    
         
            +
                      # todo: finish writing black list functionality
         
     | 
| 
      
 363 
     | 
    
         
            +
                      sanitizer.find('[style]').removeAttr('style')
         
     | 
| 
      
 364 
     | 
    
         
            +
                      sanitizer.find('[class="Apple-style-span"]').removeClass('Apple-style-span')
         
     | 
| 
      
 365 
     | 
    
         
            +
                      content = sanitizer.html()
         
     | 
| 
      
 366 
     | 
    
         
            +
                    when 'whitelist'
         
     | 
| 
      
 367 
     | 
    
         
            +
                      for element in sanitizer.find('*')
         
     | 
| 
      
 368 
     | 
    
         
            +
                        allowed = false
         
     | 
| 
      
 369 
     | 
    
         
            +
                        for allowedTag, allowedAttributes of Mercury.config.pasting.whitelist
         
     | 
| 
      
 370 
     | 
    
         
            +
                          if element.tagName.toLowerCase() == allowedTag.toLowerCase()
         
     | 
| 
      
 371 
     | 
    
         
            +
                            allowed = true
         
     | 
| 
      
 372 
     | 
    
         
            +
                            for attr, index in element.attributes
         
     | 
| 
      
 373 
     | 
    
         
            +
                              jQuery(element).attr(attr.name, null) if attr && allowedAttributes.indexOf(attr.name) == -1
         
     | 
| 
      
 374 
     | 
    
         
            +
                            break
         
     | 
| 
      
 375 
     | 
    
         
            +
                        jQuery(element).replaceWith(jQuery(element).contents()) unless allowed
         
     | 
| 
      
 376 
     | 
    
         
            +
                      content = sanitizer.html()
         
     | 
| 
      
 377 
     | 
    
         
            +
                    else content = sanitizer.text()
         
     | 
| 
      
 378 
     | 
    
         
            +
                else
         
     | 
| 
      
 379 
     | 
    
         
            +
                  # force text if it looks like it's from word/pages, even if there's no sanitizing requested
         
     | 
| 
      
 380 
     | 
    
         
            +
                  content = sanitizer.html()
         
     | 
| 
      
 381 
     | 
    
         
            +
                  if content.indexOf('<!--StartFragment-->') > -1 || content.indexOf('="mso-') > -1 || content.indexOf('<o:') > -1 || content.indexOf('="Mso') > -1
         
     | 
| 
      
 382 
     | 
    
         
            +
                    content = sanitizer.text()
         
     | 
| 
       351 
383 
     | 
    
         | 
| 
       352 
     | 
    
         
            -
             
     | 
| 
       353 
     | 
    
         
            -
             
     | 
| 
      
 384 
     | 
    
         
            +
                sanitizer.html('')
         
     | 
| 
      
 385 
     | 
    
         
            +
                return content
         
     | 
| 
       354 
386 
     | 
    
         | 
| 
       355 
387 
     | 
    
         | 
| 
       356 
388 
     | 
    
         
             
              # Custom actions (eg. things that execCommand doesn't do, or doesn't do well)
         
     | 
| 
       357 
389 
     | 
    
         
             
              @actions: {
         
     | 
| 
       358 
     | 
    
         
            -
            #    bold: (selection) ->
         
     | 
| 
       359 
     | 
    
         
            -
            #      unless selection.collapsed
         
     | 
| 
       360 
     | 
    
         
            -
            #        @document.execCommand('bold', false, null)
         
     | 
| 
       361 
     | 
    
         
            -
            #      else
         
     | 
| 
       362 
     | 
    
         
            -
            ##        selection.selectWordByCursor()
         
     | 
| 
       363 
     | 
    
         
            -
            ##        @document.execCommand('bold', false, null)
         
     | 
| 
       364 
     | 
    
         
            -
            #
         
     | 
| 
       365 
     | 
    
         
            -
            #        selection.placeMarker()
         
     | 
| 
       366 
     | 
    
         
            -
            #        node = @element.find('.mercury-marker').get(0)
         
     | 
| 
       367 
     | 
    
         
            -
            #        prev = node.previousSibling
         
     | 
| 
       368 
     | 
    
         
            -
            #        selection.removeMarker()
         
     | 
| 
       369 
     | 
    
         
            -
            #        next = prev.nextSibling
         
     | 
| 
       370 
     | 
    
         
            -
            #        console.debug(prev, next)
         
     | 
| 
       371 
     | 
    
         
            -
            ##        if prev.textContent[prev.textContent.length - 1] != ' ' &&
         
     | 
| 
       372 
     | 
    
         
            -
             
     | 
| 
       373 
     | 
    
         
            -
             
     | 
| 
       374 
     | 
    
         
            -
            #[some]| content
         
     | 
| 
       375 
     | 
    
         
            -
            # textContent = some, wholeText = some
         
     | 
| 
       376 
     | 
    
         
            -
            # textContent = '', wholeText = some
         
     | 
| 
       377 
     | 
    
         
            -
            #content |[some]
         
     | 
| 
       378 
     | 
    
         
            -
            #content [s|ome]
         
     | 
| 
       379 
     | 
    
         
            -
            #co|ntent [some]
         
     | 
| 
       380 
     | 
    
         
            -
            #|content [some]
         
     | 
| 
       381 
     | 
    
         
            -
             
     | 
| 
       382 
     | 
    
         
            -
             
     | 
| 
       383 
     | 
    
         
            -
            #
         
     | 
| 
       384 
     | 
    
         
            -
            #        console.debug(commonAncestor)
         
     | 
| 
       385 
     | 
    
         
            -
            #        beforeText = commonAncestor.textContent
         
     | 
| 
       386 
     | 
    
         
            -
            #        afterText = commonAncestor.wholeText.substring(commonAncestor.wholeText.lastIndexOf(beforeText) + beforeText.length, commonAncestor.wholeText.length)
         
     | 
| 
       387 
     | 
    
         
            -
            #        if beforeText && afterText && (beforeChar = beforeText[beforeText.length - 1]) != ' ' && (afterChar = afterText[0]) != ' '
         
     | 
| 
       388 
     | 
    
         
            -
            #          console.debug('bolding word', beforeChar, afterChar)
         
     | 
| 
       389 
     | 
    
         
            -
            #        else
         
     | 
| 
       390 
     | 
    
         
            -
            #          @document.execCommand('bold', false, null)
         
     | 
| 
       391 
     | 
    
         
            -
            #
         
     | 
| 
       392 
     | 
    
         
            -
            ##          selection.selectWord()
         
     | 
| 
       393 
     | 
    
         
            -
            ##      commonAncestor.wholeText, commonAncestor.textContent
         
     | 
| 
       394 
     | 
    
         
            -
            #      else
         
     | 
| 
       395 
390 
     | 
    
         | 
| 
       396 
391 
     | 
    
         
             
                insertRowBefore: -> Mercury.tableEditor.addRow('before')
         
     | 
| 
       397 
392 
     | 
    
         | 
| 
         @@ -417,6 +412,8 @@ class @Mercury.Regions.Editable extends Mercury.Region 
     | 
|
| 
       417 
412 
     | 
    
         | 
| 
       418 
413 
     | 
    
         
             
                redo: -> @content(@history.redo())
         
     | 
| 
       419 
414 
     | 
    
         | 
| 
      
 415 
     | 
    
         
            +
                horizontalRule: -> this.execCommand('insertHorizontalRule')
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
       420 
417 
     | 
    
         
             
                removeFormatting: (selection) -> selection.insertTextNode(selection.textContent())
         
     | 
| 
       421 
418 
     | 
    
         | 
| 
       422 
419 
     | 
    
         
             
                backColor: (selection, options) -> selection.wrap("<span style=\"background-color:#{options.value.toHex()}\">", true)
         
     | 
| 
         @@ -490,7 +487,7 @@ class Mercury.Regions.Editable.Selection 
     | 
|
| 
       490 
487 
     | 
    
         | 
| 
       491 
488 
     | 
    
         
             
              is: (elementType) ->
         
     | 
| 
       492 
489 
     | 
    
         
             
                content = @content()
         
     | 
| 
       493 
     | 
    
         
            -
                return jQuery(content.firstChild) if content. 
     | 
| 
      
 490 
     | 
    
         
            +
                return jQuery(content.firstChild) if jQuery(content).length == 1 && jQuery(content.firstChild).is(elementType)
         
     | 
| 
       494 
491 
     | 
    
         
             
                return false
         
     | 
| 
       495 
492 
     | 
    
         | 
| 
       496 
493 
     | 
    
         | 
| 
         @@ -498,18 +495,16 @@ class Mercury.Regions.Editable.Selection 
     | 
|
| 
       498 
495 
     | 
    
         
             
                return unless jQuery.browser.webkit
         
     | 
| 
       499 
496 
     | 
    
         
             
                range = @context.createRange()
         
     | 
| 
       500 
497 
     | 
    
         | 
| 
       501 
     | 
    
         
            -
                # todo: the \00 thing breaks when using uglifier, and is escapped to "0".. it's been fixed, but isn't available yet
         
     | 
| 
       502 
     | 
    
         
            -
                # https://github.com/lautis/uglifier/issues/11
         
     | 
| 
       503 
498 
     | 
    
         
             
                if @range
         
     | 
| 
       504 
499 
     | 
    
         
             
                  if @commonAncestor(true).closest('.mercury-snippet').length
         
     | 
| 
       505 
     | 
    
         
            -
                    lastChild = @context.createTextNode('\00') 
     | 
| 
      
 500 
     | 
    
         
            +
                    lastChild = @context.createTextNode('\00')
         
     | 
| 
       506 
501 
     | 
    
         
             
                    element.appendChild(lastChild)
         
     | 
| 
       507 
502 
     | 
    
         
             
                else
         
     | 
| 
       508 
503 
     | 
    
         
             
                  if element.lastChild && element.lastChild.nodeType == 3 && element.lastChild.textContent.replace(/^[\s+|\n+]|[\s+|\n+]$/, '') == ''
         
     | 
| 
       509 
504 
     | 
    
         
             
                    lastChild = element.lastChild
         
     | 
| 
       510 
     | 
    
         
            -
                    element.lastChild.textContent = '\00' 
     | 
| 
      
 505 
     | 
    
         
            +
                    element.lastChild.textContent = '\00'
         
     | 
| 
       511 
506 
     | 
    
         
             
                  else
         
     | 
| 
       512 
     | 
    
         
            -
                    lastChild = @context.createTextNode(' 
     | 
| 
      
 507 
     | 
    
         
            +
                    lastChild = @context.createTextNode('\00')
         
     | 
| 
       513 
508 
     | 
    
         
             
                    element.appendChild(lastChild)
         
     | 
| 
       514 
509 
     | 
    
         | 
| 
       515 
510 
     | 
    
         
             
                if lastChild
         
     | 
| 
         @@ -582,7 +577,7 @@ class Mercury.Regions.Editable.Selection 
     | 
|
| 
       582 
577 
     | 
    
         
             
                @selection.addRange(@range)
         
     | 
| 
       583 
578 
     | 
    
         | 
| 
       584 
579 
     | 
    
         | 
| 
       585 
     | 
    
         
            -
              replace: (element) ->
         
     | 
| 
      
 580 
     | 
    
         
            +
              replace: (element, collapse) ->
         
     | 
| 
       586 
581 
     | 
    
         
             
                element = element.get(0) if element.get
         
     | 
| 
       587 
582 
     | 
    
         
             
                element = jQuery(element, @context).get(0) if jQuery.type(element) == 'string'
         
     | 
| 
       588 
583 
     | 
    
         | 
| 
         @@ -590,3 +585,4 @@ class Mercury.Regions.Editable.Selection 
     | 
|
| 
       590 
585 
     | 
    
         
             
                @range.insertNode(element)
         
     | 
| 
       591 
586 
     | 
    
         
             
                @range.selectNodeContents(element)
         
     | 
| 
       592 
587 
     | 
    
         
             
                @selection.addRange(@range)
         
     | 
| 
      
 588 
     | 
    
         
            +
                @range.collapse(false) if collapse
         
     |