formagic 0.3.9 → 0.3.10

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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/assets/javascripts/formagic.coffee +5 -2
  4. data/app/assets/javascripts/formagic/form.coffee +4 -1
  5. data/app/assets/javascripts/formagic/inputs/ace-css.coffee +25 -0
  6. data/app/assets/javascripts/formagic/inputs/ace-html.coffee +25 -0
  7. data/app/assets/javascripts/formagic/inputs/ace-js.coffee +25 -0
  8. data/app/assets/javascripts/formagic/inputs/ace-markdown.coffee +51 -0
  9. data/app/assets/javascripts/formagic/inputs/{markdown_toolbar.coffee → ace-markdown_toolbar.coffee} +27 -7
  10. data/app/assets/javascripts/formagic/inputs/{html.coffee → ace.coffee} +27 -29
  11. data/app/assets/javascripts/formagic/inputs/documents_reorder.coffee +3 -0
  12. data/app/assets/javascripts/formagic/inputs/list_reorder.coffee +2 -0
  13. data/app/assets/javascripts/formagic/inputs/url.coffee +1 -1
  14. data/app/assets/javascripts/vendor/ace.js +264 -123
  15. data/app/assets/javascripts/vendor/mode-css.js +1008 -0
  16. data/app/assets/javascripts/vendor/mode-html.js +488 -129
  17. data/app/assets/javascripts/vendor/mode-javascript.js +1154 -0
  18. data/app/assets/javascripts/vendor/mode-markdown.js +489 -129
  19. data/app/assets/javascripts/vendor/slip.js +792 -0
  20. data/app/assets/stylesheets/formagic.scss +9 -1
  21. data/app/assets/stylesheets/formagic/{nested-form.scss → documents.scss} +0 -0
  22. data/app/assets/stylesheets/formagic/markdown.scss +4 -1
  23. data/app/assets/stylesheets/formagic/switch.scss +1 -1
  24. data/lib/formagic/version.rb +1 -1
  25. metadata +12 -6
  26. data/app/assets/javascripts/formagic/inputs/markdown.coffee +0 -94
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79015f55a3f1cfacca4bee34191aa33b1fb3f745
4
- data.tar.gz: a76c54dbe60f720d3dcb4cd91d1e3bb8cf005767
3
+ metadata.gz: 6c17147c1c2a4a84bee088722eea1cb2d27622fb
4
+ data.tar.gz: 6dcc25eaed38bdc251b3837e2eb088b08a38d105
5
5
  SHA512:
6
- metadata.gz: 5a1dfef367302b2b09eef3e03d463ba029ffd355663ef8647e34e7f8e7d5ce184c81170286608143144cec3d83b24a2e185e3d8a788f3bbc9404091513f094b2
7
- data.tar.gz: a3d522aafd769bd9bd9670ada5b00597ef4c4ed460b0eb3dc49e596b93afbaeb8ec513469c1f97ad1cf38223978c1520701d3f592e2ae09348472ca060a72d1a
6
+ metadata.gz: 40fca5873df0a180ffe38b1cc7329f5cb06d1070d4b1fe40de5a833030ff50a6d136fd2213588284ba8b62829adae27d892d06f2c140cab510b8f251f5bbe8d8
7
+ data.tar.gz: d3ecd7856db1be847f9cae39f56616c07d324618d207cc4743a4a9f6fded67aec181938c92e22e7f98d8c4fe952e3f5385005e827a569692bff8b9bb89d0fc61
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- formagic (0.3.9)
4
+ formagic (0.3.10)
5
5
  bourbon (>= 3.2)
6
6
  normalize-rails (>= 3.0)
7
7
 
@@ -26,8 +26,11 @@
26
26
 
27
27
  ## OPTIONAL
28
28
  # require ./formagic/inputs/redactor
29
- # require ./formagic/inputs/html
30
- # require ./formagic/inputs/markdown
29
+ # require ./formagic/inputs/ace-html
30
+ # require ./formagic/inputs/ace-css
31
+ # require ./formagic/inputs/ace-js
32
+ # require ./formagic/inputs/ace-coffee
33
+ # require ./formagic/inputs/ace-markdown
31
34
 
32
35
  @Icons ?= {}
33
36
  @Icons.reorderDocuments = "<i class='fa fa-ellipsis-v'></i>"
@@ -83,7 +83,10 @@ class @Form
83
83
  if groupConfig.inputs
84
84
  @_build_schema(groupConfig.inputs, $group)
85
85
 
86
- group = { $el: $group, klassName: klassName, onInitialize: groupConfig.onInitialize }
86
+ group =
87
+ $el: $group
88
+ klassName: klassName
89
+ onInitialize: groupConfig.onInitialize
87
90
  @groups.push group
88
91
 
89
92
  return group
@@ -0,0 +1,25 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ # -----------------------------------------------------------------------------
5
+ # INPUT CSS
6
+ # -----------------------------------------------------------------------------
7
+ # Config options:
8
+ # label - Input label
9
+ # pluginConfig - Custom options for overriding default ones
10
+ #
11
+ # Input config example:
12
+ # css_field: { type: 'css', label: 'Styles' }
13
+ #
14
+ # Dependencies:
15
+ #= require ./ace
16
+ #= require vendor/mode-css
17
+ # -----------------------------------------------------------------------------
18
+ class @InputCss extends InputAce
19
+
20
+ # PRIVATE ===================================================================
21
+
22
+ _set_mode: ->
23
+ @session.setMode("ace/mode/css")
24
+
25
+ chr.formInputs['css'] = InputCss
@@ -0,0 +1,25 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ # -----------------------------------------------------------------------------
5
+ # INPUT HTML
6
+ # -----------------------------------------------------------------------------
7
+ # Config options:
8
+ # label - Input label
9
+ # pluginConfig - Custom options for overriding default ones
10
+ #
11
+ # Input config example:
12
+ # body_html: { type: 'html', label: 'Article' }
13
+ #
14
+ # Dependencies:
15
+ #= require ./ace
16
+ #= require vendor/mode-html
17
+ # -----------------------------------------------------------------------------
18
+ class @InputHtml extends InputAce
19
+
20
+ # PRIVATE ===================================================================
21
+
22
+ _set_mode: ->
23
+ @session.setMode("ace/mode/html")
24
+
25
+ chr.formInputs['html'] = InputHtml
@@ -0,0 +1,25 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ # -----------------------------------------------------------------------------
5
+ # INPUT JS
6
+ # -----------------------------------------------------------------------------
7
+ # Config options:
8
+ # label - Input label
9
+ # pluginConfig - Custom options for overriding default ones
10
+ #
11
+ # Input config example:
12
+ # js_field: { type: 'js', label: 'JavaScript' }
13
+ #
14
+ # Dependencies:
15
+ #= require ./ace
16
+ #= require vendor/mode-javascript
17
+ # -----------------------------------------------------------------------------
18
+ class @InputJs extends InputAce
19
+
20
+ # PRIVATE ===================================================================
21
+
22
+ _set_mode: ->
23
+ @session.setMode("ace/mode/javascript")
24
+
25
+ chr.formInputs['js'] = InputJs
@@ -0,0 +1,51 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ # -----------------------------------------------------------------------------
5
+ # INPUT MARKDOWN
6
+ # -----------------------------------------------------------------------------
7
+ # Markdown input supports syntax highlighting and optional compilation to html.
8
+ #
9
+ # Config options:
10
+ # label - Input label
11
+ # pluginConfig - Custom options for overriding default ones
12
+ # getHtmlInput - return input so store generated HTML content
13
+ # disableToolbar - Do not show shorcuts panel
14
+ #
15
+ # Input config example:
16
+ # body_md:
17
+ # type: 'markdown'
18
+ # label: 'Article'
19
+ # getHtmlInput: -> chr.module.view.form.inputs.body_html
20
+ #
21
+ # Dependencies:
22
+ #= require ./ace
23
+ #= require vendor/marked
24
+ #= require vendor/ace
25
+ #= require vendor/mode-markdown
26
+ #= require ./ace-markdown_toolbar
27
+ # -----------------------------------------------------------------------------
28
+ class @InputMarkdown extends InputAce
29
+ # PRIVATE ===================================================================
30
+
31
+ _before_initialize: ->
32
+ @config.imageSize ||= "large"
33
+ if ! @config.disableToolbar
34
+ @_add_toolbar()
35
+
36
+ _update_inputs: ->
37
+ markdown = @session.getValue()
38
+ @$input.val(markdown)
39
+ @$input.trigger('change')
40
+
41
+ if @config.getHtmlInput
42
+ html = marked(markdown)
43
+ input = @config.getHtmlInput()
44
+ input.updateValue(html)
45
+
46
+ _set_mode: ->
47
+ @session.setMode("ace/mode/markdown")
48
+
49
+ include(InputMarkdown, inputMarkdownToolbar)
50
+
51
+ chr.formInputs['markdown'] = InputMarkdown
@@ -15,6 +15,9 @@ class @InputMarkdownToolbar
15
15
 
16
16
  # PRIVATE ===================================================================
17
17
 
18
+ _is_visible: ->
19
+ @$el.is(":visible")
20
+
18
21
  _bind_window_scroll: ->
19
22
  @$window =$ ".content:visible"
20
23
  @$window.on "scroll", => @_check_offset()
@@ -32,9 +35,8 @@ class @InputMarkdownToolbar
32
35
  if isBelowAceTop && isAboveAceBottom then @_fix() else @_unfix()
33
36
 
34
37
  _fix: ->
35
- if @isFixed
36
- return
37
- # some legacy workaround for mobile:
38
+ if @isFixed || ! @_is_visible() then return
39
+ # TODO: make this work on mobile ...
38
40
  # webkit does not recalc top: 0 when focused on contenteditable
39
41
  # if chr.isMobile() && @isFocused
40
42
  # @$el.css
@@ -51,7 +53,7 @@ class @InputMarkdownToolbar
51
53
  @isFixed = true
52
54
 
53
55
  _unfix: ->
54
- if ! @isFixed then return
56
+ if ! @isFixed || ! @_is_visible() then return
55
57
 
56
58
  @$ace = @input.$editor
57
59
  @$el.css
@@ -72,6 +74,7 @@ class @InputMarkdownToolbar
72
74
  @buttons[title] = $btn
73
75
 
74
76
  @inputMarkdownToolbar =
77
+
75
78
  # PRIVATE ===================================================================
76
79
 
77
80
  _add_toolbar: ->
@@ -80,6 +83,7 @@ class @InputMarkdownToolbar
80
83
 
81
84
  @toolbar.addButton "Link", $.proxy(@_insert_link, this)
82
85
  @toolbar.addButton "Image", $.proxy(@_insert_images, this)
86
+ @toolbar.addButton "File", $.proxy(@_insert_files, this)
83
87
 
84
88
  _insert_link: (editor) ->
85
89
  url = prompt("URL", "")
@@ -90,7 +94,23 @@ class @InputMarkdownToolbar
90
94
  editor.focus()
91
95
 
92
96
  _insert_images: (editor) ->
93
- chr.modules.loft.showModal "images", true, (objects) ->
97
+ # TODO: add workaround when loft is not available
98
+ onAccept = (objects) =>
94
99
  for image in objects
95
- editor.insert "![#{image.name}](#{image.file.url})\n"
96
- editor.focus()
100
+ name = image.name
101
+ url = image.file[@config.imageSize].url
102
+ editor.insert "![#{name}](#{url})\n"
103
+ editor.focus()
104
+ onCancel = -> editor.focus()
105
+ chr.modules.loft.showImages true, onAccept, onCancel
106
+
107
+ _insert_files: (editor) ->
108
+ # TODO: add workaround when loft is not available
109
+ onAccept = (objects) =>
110
+ for file in objects
111
+ name = file.name
112
+ url = file.file.url
113
+ editor.insert "[#{name}](#{url})\n"
114
+ editor.focus()
115
+ onCancel = -> editor.focus()
116
+ chr.modules.loft.showDocuments true, onAccept, onCancel
@@ -2,20 +2,12 @@
2
2
  # Author: Alexander Kravets <alex@slatestudio.com>,
3
3
  # Slate Studio (http://www.slatestudio.com)
4
4
  # -----------------------------------------------------------------------------
5
- # INPUT HTML
5
+ # ABSTRACT ACE EDITOR
6
6
  # -----------------------------------------------------------------------------
7
- # Config options:
8
- # label - Input label
9
- # aceOptions - Custom options for overriding default ones
10
- #
11
- # Input config example:
12
- # body_html: { type: 'html', label: 'Article' }
13
- #
14
7
  # Dependencies:
15
8
  #= require vendor/ace
16
- #= require vendor/mode-html
17
9
  # -----------------------------------------------------------------------------
18
- class @InputHtml extends InputString
10
+ class @InputAce extends InputString
19
11
 
20
12
  # PRIVATE ===================================================================
21
13
 
@@ -23,17 +15,32 @@ class @InputHtml extends InputString
23
15
  @$input =$ "<input type='hidden' name='#{ @name }' value='#{ @_safe_value() }' />"
24
16
  @$el.append @$input
25
17
 
26
- @$editor =$ "<div></div>"
18
+ @$editor =$ "<div>"
27
19
  @$el.append @$editor
28
20
 
29
21
  _update_inputs: ->
30
- @value = @editor.getSession().getValue()
22
+ @value = @session.getValue()
31
23
  @$input.val(@value)
32
- @$input.trigger('change')
24
+ @$input.trigger("change")
25
+
26
+ _set_mode: ->
27
+
28
+ # ace options: https://github.com/ajaxorg/ace/wiki/Configuring-Ace
29
+ _default_options: ->
30
+ autoScrollEditorIntoView: true
31
+ minLines: 8
32
+ maxLines: Infinity
33
+ showLineNumbers: false
34
+ showGutter: false
35
+ highlightActiveLine: false
36
+ showPrintMargin: false
37
+ tabSize: 2
33
38
 
34
39
  # PUBLIC ====================================================================
35
40
 
36
41
  initialize: ->
42
+ @_before_initialize?()
43
+ @config.pluginConfig ||= {}
37
44
  @config.beforeInitialize?(this)
38
45
 
39
46
  @editor = ace.edit(@$editor.get(0))
@@ -43,24 +50,15 @@ class @InputHtml extends InputString
43
50
  @session.setUseWorker(false)
44
51
  @session.setValue(@$input.val())
45
52
  @session.setUseWrapMode(true)
46
- @session.setMode("ace/mode/html")
47
-
48
- # ace options: https://github.com/ajaxorg/ace/wiki/Configuring-Ace
49
- @editor.setOptions
50
- autoScrollEditorIntoView: true
51
- minLines: 5
52
- maxLines: Infinity
53
- showLineNumbers: false
54
- showGutter: false
55
- highlightActiveLine: false
56
- showPrintMargin: false
53
+ @_set_mode()
57
54
 
58
- @session.on 'change', (e) => @_update_inputs()
55
+ aceOptions = @_default_options()
56
+ $.merge(aceOptions, @config.pluginConfig)
57
+ @editor.setOptions(aceOptions)
59
58
 
59
+ @session.on "change", (e) => @_update_inputs()
60
+ @_after_initialize?()
60
61
  @config.onInitialize?(this)
61
62
 
62
63
  updateValue: (@value) ->
63
- @editor.getSession().setValue(@value)
64
- @$input.val(@value)
65
-
66
- chr.formInputs['html'] = InputHtml
64
+ @session.setValue(@value)
@@ -4,6 +4,9 @@
4
4
  # -----------------------------------------------------------------------------
5
5
  # INPUT "NESTED" FORM REORDER
6
6
  # -----------------------------------------------------------------------------
7
+ # Dependencies:
8
+ #= require vendor/slip
9
+ # -----------------------------------------------------------------------------
7
10
  @inputFormReorder =
8
11
  # PRIVATE ===================================================================
9
12
 
@@ -3,6 +3,8 @@
3
3
  # Slate Studio (http://www.slatestudio.com)
4
4
  # -----------------------------------------------------------------------------
5
5
  # INPUT LIST REORDER
6
+ # Dependencies:
7
+ #= require vendor/slip
6
8
  # -----------------------------------------------------------------------------
7
9
  @inputListReorder =
8
10
  # PRIVATE ===================================================================
@@ -15,7 +15,7 @@ class @InputUrl extends InputString
15
15
  @$actions.append @$chooseBtn
16
16
 
17
17
  @$chooseBtn.on 'click', (e) =>
18
- chr.modules.loft.showModal 'all', false, (objects) =>
18
+ chr.modules.loft.showAll false, (objects) =>
19
19
  url = objects[0].file.url
20
20
  @updateValue(url)
21
21
 
@@ -960,7 +960,7 @@ exports.getDocumentHead = function(doc) {
960
960
  if (!doc)
961
961
  doc = document;
962
962
  return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement;
963
- }
963
+ };
964
964
 
965
965
  exports.createElement = function(tag, ns) {
966
966
  return document.createElementNS ?
@@ -999,7 +999,7 @@ exports.toggleCssClass = function(el, name) {
999
999
  add = false;
1000
1000
  classes.splice(index, 1);
1001
1001
  }
1002
- if(add)
1002
+ if (add)
1003
1003
  classes.push(name);
1004
1004
 
1005
1005
  el.className = classes.join(" ");
@@ -1044,10 +1044,7 @@ exports.importCssString = function importCssString(cssText, id, doc) {
1044
1044
  if (id)
1045
1045
  style.owningElement.id = id;
1046
1046
  } else {
1047
- style = doc.createElementNS
1048
- ? doc.createElementNS(XHTML_NS, "style")
1049
- : doc.createElement("style");
1050
-
1047
+ style = exports.createElement("style");
1051
1048
  style.appendChild(doc.createTextNode(cssText));
1052
1049
  if (id)
1053
1050
  style.id = id;
@@ -1287,7 +1284,7 @@ var Keys = (function() {
1287
1284
  80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',
1288
1285
  87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',
1289
1286
  186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
1290
- 219: '[', 220: '\\',221: ']', 222: '\''
1287
+ 219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*'
1291
1288
  }
1292
1289
  };
1293
1290
  var name, i;
@@ -1385,6 +1382,9 @@ define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/use
1385
1382
  var keys = require("./keys");
1386
1383
  var useragent = require("./useragent");
1387
1384
 
1385
+ var pressedKeys = null;
1386
+ var ts = 0;
1387
+
1388
1388
  exports.addListener = function(elem, type, callback) {
1389
1389
  if (elem.addEventListener) {
1390
1390
  return elem.addEventListener(type, callback, false);
@@ -1593,7 +1593,7 @@ function normalizeCommandKeys(callback, e, keyCode) {
1593
1593
  var hashId = getModifierHash(e);
1594
1594
 
1595
1595
  if (!useragent.isMac && pressedKeys) {
1596
- if (pressedKeys[91] || pressedKeys[92])
1596
+ if (pressedKeys.OSKey)
1597
1597
  hashId |= 8;
1598
1598
  if (pressedKeys.altGr) {
1599
1599
  if ((3 & hashId) != 3)
@@ -1617,8 +1617,7 @@ function normalizeCommandKeys(callback, e, keyCode) {
1617
1617
  if (keyCode in keys.MODIFIER_KEYS) {
1618
1618
  keyCode = -1;
1619
1619
  }
1620
-
1621
- if (hashId & 8 && (keyCode === 91 || keyCode === 93)) {
1620
+ if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) {
1622
1621
  keyCode = -1;
1623
1622
  }
1624
1623
 
@@ -1645,8 +1644,7 @@ function normalizeCommandKeys(callback, e, keyCode) {
1645
1644
  return callback(e, hashId, keyCode);
1646
1645
  }
1647
1646
 
1648
- var pressedKeys = null;
1649
- var ts = 0;
1647
+
1650
1648
  exports.addCommandKeyListener = function(el, callback) {
1651
1649
  var addListener = exports.addListener;
1652
1650
  if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
@@ -1661,8 +1659,18 @@ exports.addCommandKeyListener = function(el, callback) {
1661
1659
  var lastDefaultPrevented = null;
1662
1660
 
1663
1661
  addListener(el, "keydown", function(e) {
1664
- pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1;
1665
- var result = normalizeCommandKeys(callback, e, e.keyCode);
1662
+ var keyCode = e.keyCode;
1663
+ pressedKeys[keyCode] = (pressedKeys[keyCode] || 0) + 1;
1664
+ if (keyCode == 91 || keyCode == 92) {
1665
+ pressedKeys.OSKey = true;
1666
+ } else if (pressedKeys.OSKey) {
1667
+ if (e.timeStamp - pressedKeys.lastT > 200 && pressedKeys.count == 1)
1668
+ resetPressedKeys();
1669
+ }
1670
+ if (pressedKeys[keyCode] == 1)
1671
+ pressedKeys.count++;
1672
+ pressedKeys.lastT = e.timeStamp;
1673
+ var result = normalizeCommandKeys(callback, e, keyCode);
1666
1674
  lastDefaultPrevented = e.defaultPrevented;
1667
1675
  return result;
1668
1676
  });
@@ -1675,7 +1683,16 @@ exports.addCommandKeyListener = function(el, callback) {
1675
1683
  });
1676
1684
 
1677
1685
  addListener(el, "keyup", function(e) {
1678
- pressedKeys[e.keyCode] = null;
1686
+ var keyCode = e.keyCode;
1687
+ if (!pressedKeys[keyCode]) {
1688
+ resetPressedKeys();
1689
+ } else {
1690
+ pressedKeys.count = Math.max(pressedKeys.count - 1, 0);
1691
+ }
1692
+ if (keyCode == 91 || keyCode == 92) {
1693
+ pressedKeys.OSKey = false;
1694
+ }
1695
+ pressedKeys[keyCode] = null;
1679
1696
  });
1680
1697
 
1681
1698
  if (!pressedKeys) {
@@ -1684,8 +1701,10 @@ exports.addCommandKeyListener = function(el, callback) {
1684
1701
  }
1685
1702
  }
1686
1703
  };
1687
- function resetPressedKeys(e) {
1704
+ function resetPressedKeys() {
1688
1705
  pressedKeys = Object.create(null);
1706
+ pressedKeys.count = 0;
1707
+ pressedKeys.lastT = 0;
1689
1708
  }
1690
1709
 
1691
1710
  if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
@@ -2749,7 +2768,7 @@ function GutterHandler(mouseHandler) {
2749
2768
  if (mouseHandler.$tooltipFollowsMouse) {
2750
2769
  moveTooltip(mouseEvent);
2751
2770
  } else {
2752
- var gutterElement = gutter.$cells[editor.session.documentToScreenRow(row, 0)].element;
2771
+ var gutterElement = mouseEvent.domEvent.target;
2753
2772
  var rect = gutterElement.getBoundingClientRect();
2754
2773
  var style = tooltip.getElement().style;
2755
2774
  style.left = rect.right + "px";
@@ -3766,6 +3785,8 @@ var MouseHandler = function(editor) {
3766
3785
  if (!document.hasFocus || !document.hasFocus())
3767
3786
  window.focus();
3768
3787
  editor.focus();
3788
+ if (!editor.isFocused())
3789
+ window.focus();
3769
3790
  };
3770
3791
 
3771
3792
  var mouseTarget = editor.renderer.getMouseEventTarget();
@@ -4067,7 +4088,7 @@ var KeyBinding = function(editor) {
4067
4088
  if (toExecute.command == "null") {
4068
4089
  success = true;
4069
4090
  } else {
4070
- success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
4091
+ success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
4071
4092
  }
4072
4093
  if (success && e && hashId != -1 &&
4073
4094
  toExecute.passEvent != true && toExecute.command.passEvent != true
@@ -4077,6 +4098,15 @@ var KeyBinding = function(editor) {
4077
4098
  if (success)
4078
4099
  break;
4079
4100
  }
4101
+
4102
+ if (!success && hashId == -1) {
4103
+ toExecute = {command: "insertstring"};
4104
+ success = commands.exec("insertstring", this.$editor, keyString);
4105
+ }
4106
+
4107
+ if (success)
4108
+ this.$editor._signal("keyboardActivity", toExecute);
4109
+
4080
4110
  return success;
4081
4111
  };
4082
4112
 
@@ -4086,9 +4116,7 @@ var KeyBinding = function(editor) {
4086
4116
  };
4087
4117
 
4088
4118
  this.onTextInput = function(text) {
4089
- var success = this.$callKeyboardHandlers(-1, text);
4090
- if (!success)
4091
- this.$editor.commands.exec("insertstring", this.$editor, text);
4119
+ this.$callKeyboardHandlers(-1, text);
4092
4120
  };
4093
4121
 
4094
4122
  }).call(KeyBinding.prototype);
@@ -4827,8 +4855,10 @@ var Selection = function(session) {
4827
4855
  var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);
4828
4856
 
4829
4857
  if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) {
4830
- if (this.session.lineWidgets && this.session.lineWidgets[docPos.row])
4831
- docPos.row++;
4858
+ if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) {
4859
+ if (docPos.row > 0 || rows > 0)
4860
+ docPos.row++;
4861
+ }
4832
4862
  }
4833
4863
  this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
4834
4864
  };
@@ -5108,6 +5138,9 @@ var Tokenizer = function(rules) {
5108
5138
  if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end)))
5109
5139
  src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
5110
5140
  }
5141
+ if (src.charAt(0) != "^") src = "^" + src;
5142
+ if (src.charAt(src.length - 1) != "$") src += "$";
5143
+
5111
5144
  return new RegExp(src, (flag||"").replace("g", ""));
5112
5145
  };
5113
5146
  this.getLineTokens = function(line, startState) {
@@ -5280,13 +5313,12 @@ var TextHighlightRules = function() {
5280
5313
  for (var i = 0; i < state.length; i++) {
5281
5314
  var rule = state[i];
5282
5315
  if (rule.next || rule.onMatch) {
5283
- if (typeof rule.next != "string") {
5284
- if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
5285
- rule.nextState = prefix + rule.nextState;
5286
- } else {
5316
+ if (typeof rule.next == "string") {
5287
5317
  if (rule.next.indexOf(prefix) !== 0)
5288
5318
  rule.next = prefix + rule.next;
5289
5319
  }
5320
+ if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
5321
+ rule.nextState = prefix + rule.nextState;
5290
5322
  }
5291
5323
  }
5292
5324
  this.$rules[prefix + key] = state;
@@ -6435,7 +6467,7 @@ var Document = function(textOrLines) {
6435
6467
  }
6436
6468
  };
6437
6469
  this.replace = function(range, text) {
6438
- if (!range instanceof Range)
6470
+ if (!(range instanceof Range))
6439
6471
  range = Range.fromPoints(range.start, range.end);
6440
6472
  if (text.length === 0 && range.isEmpty())
6441
6473
  return range.start;
@@ -7336,7 +7368,7 @@ function Folding() {
7336
7368
  var folds = this.getFoldsInRange(ranges);
7337
7369
  }
7338
7370
  return folds;
7339
- }
7371
+ };
7340
7372
  this.getAllFolds = function() {
7341
7373
  var folds = [];
7342
7374
  var foldLines = this.$foldData;
@@ -7421,15 +7453,15 @@ function Folding() {
7421
7453
  end = foldLine.end.row,
7422
7454
  start = foldLine.start.row;
7423
7455
  if (end >= last) {
7424
- if(start < last) {
7425
- if(start >= first)
7456
+ if (start < last) {
7457
+ if (start >= first)
7426
7458
  rowCount -= last-start;
7427
7459
  else
7428
- rowCount = 0;//in one fold
7460
+ rowCount = 0; // in one fold
7429
7461
  }
7430
7462
  break;
7431
- } else if(end >= first){
7432
- if (start >= first) //fold inside range
7463
+ } else if (end >= first){
7464
+ if (start >= first) // fold inside range
7433
7465
  rowCount -= end-start;
7434
7466
  else
7435
7467
  rowCount -= end-first+1;
@@ -7514,7 +7546,7 @@ function Folding() {
7514
7546
  else
7515
7547
  this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);
7516
7548
  this.$modified = true;
7517
- this._emit("changeFold", { data: fold, action: "add" });
7549
+ this._signal("changeFold", { data: fold, action: "add" });
7518
7550
 
7519
7551
  return fold;
7520
7552
  };
@@ -7563,7 +7595,7 @@ function Folding() {
7563
7595
  this.$updateRowLengthCache(startRow, endRow);
7564
7596
  }
7565
7597
  this.$modified = true;
7566
- this._emit("changeFold", { data: fold, action: "remove" });
7598
+ this._signal("changeFold", { data: fold, action: "remove" });
7567
7599
  };
7568
7600
 
7569
7601
  this.removeFolds = function(folds) {
@@ -7742,7 +7774,7 @@ function Folding() {
7742
7774
  var placeholder = "...";
7743
7775
  if (!range.isMultiLine()) {
7744
7776
  placeholder = this.getTextRange(range);
7745
- if(placeholder.length < 4)
7777
+ if (placeholder.length < 4)
7746
7778
  return;
7747
7779
  placeholder = placeholder.trim().substring(0, 2) + "..";
7748
7780
  }
@@ -7759,7 +7791,7 @@ function Folding() {
7759
7791
  if (dir != 1) {
7760
7792
  do {
7761
7793
  token = iterator.stepBackward();
7762
- } while(token && re.test(token.type));
7794
+ } while (token && re.test(token.type));
7763
7795
  iterator.stepForward();
7764
7796
  }
7765
7797
 
@@ -7771,7 +7803,7 @@ function Folding() {
7771
7803
  if (dir != -1) {
7772
7804
  do {
7773
7805
  token = iterator.stepForward();
7774
- } while(token && re.test(token.type));
7806
+ } while (token && re.test(token.type));
7775
7807
  token = iterator.stepBackward();
7776
7808
  } else
7777
7809
  token = iterator.getCurrentToken();
@@ -7840,7 +7872,7 @@ function Folding() {
7840
7872
 
7841
7873
  this.off('change', this.$updateFoldWidgets);
7842
7874
  this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
7843
- this._emit("changeAnnotation");
7875
+ this._signal("changeAnnotation");
7844
7876
 
7845
7877
  if (!foldMode || this.$foldStyle == "manual") {
7846
7878
  this.foldWidgets = null;
@@ -7882,7 +7914,7 @@ function Folding() {
7882
7914
  range: i !== -1 && range,
7883
7915
  firstRange: firstRange
7884
7916
  };
7885
- }
7917
+ };
7886
7918
 
7887
7919
  this.onFoldWidgetClick = function(row, e) {
7888
7920
  e = e.domEvent;
@@ -7894,7 +7926,7 @@ function Folding() {
7894
7926
 
7895
7927
  var range = this.$toggleFoldWidget(row, options);
7896
7928
  if (!range) {
7897
- var el = (e.target || e.srcElement)
7929
+ var el = (e.target || e.srcElement);
7898
7930
  if (el && /ace_fold-widget/.test(el.className))
7899
7931
  el.className += " ace_invalid";
7900
7932
  }
@@ -7989,7 +8021,7 @@ function Folding() {
7989
8021
  if (this.foldWidgets.length > rows.first)
7990
8022
  this.foldWidgets.splice(rows.first, this.foldWidgets.length);
7991
8023
  }
7992
- }
8024
+ };
7993
8025
  }
7994
8026
 
7995
8027
  exports.Folding = Folding;
@@ -9753,6 +9785,29 @@ var EditSession = function(text, mode) {
9753
9785
  return screenRows;
9754
9786
  };
9755
9787
  this.$setFontMetrics = function(fm) {
9788
+ if (!this.$enableVarChar) return;
9789
+ this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
9790
+ if (maxScreenColumn === 0)
9791
+ return [0, 0];
9792
+ if (!maxScreenColumn)
9793
+ maxScreenColumn = Infinity;
9794
+ screenColumn = screenColumn || 0;
9795
+
9796
+ var c, column;
9797
+ for (column = 0; column < str.length; column++) {
9798
+ c = str.charAt(column);
9799
+ if (c === "\t") {
9800
+ screenColumn += this.getScreenTabSize(screenColumn);
9801
+ } else {
9802
+ screenColumn += fm.getCharacterWidth(c);
9803
+ }
9804
+ if (screenColumn > maxScreenColumn) {
9805
+ break;
9806
+ }
9807
+ }
9808
+
9809
+ return [screenColumn, column];
9810
+ };
9756
9811
  };
9757
9812
 
9758
9813
  this.destroy = function() {
@@ -10394,6 +10449,7 @@ MultiHashHandler.prototype = HashHandler.prototype;
10394
10449
  };
10395
10450
 
10396
10451
  this.handleKeyboard = function(data, hashId, keyString, keyCode) {
10452
+ if (keyCode < 0) return;
10397
10453
  var key = KEY_MODS[hashId] + keyString;
10398
10454
  var command = this.commandKeyBinding[key];
10399
10455
  if (data.$keyChain) {
@@ -13092,7 +13148,7 @@ var UndoManager = function() {
13092
13148
  var deltaSets = this.$undoStack.pop();
13093
13149
  var undoSelectionRange = null;
13094
13150
  if (deltaSets) {
13095
- undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
13151
+ undoSelectionRange = this.$doc.undoChanges(deltaSets, dontSelect);
13096
13152
  this.$redoStack.push(deltaSets);
13097
13153
  this.dirtyCounter--;
13098
13154
  }
@@ -13898,7 +13954,7 @@ var Text = function(parentEl) {
13898
13954
 
13899
13955
  this.$renderToken = function(stringBuilder, screenColumn, token, value) {
13900
13956
  var self = this;
13901
- var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
13957
+ var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
13902
13958
  var replaceFunc = function(c, a, b, tabIdx, idx4) {
13903
13959
  if (a) {
13904
13960
  return self.showInvisibles
@@ -14644,7 +14700,7 @@ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
14644
14700
  this.getCharacterWidth = function(ch) {
14645
14701
  var w = this.charSizes[ch];
14646
14702
  if (w === undefined) {
14647
- this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
14703
+ w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
14648
14704
  }
14649
14705
  return w;
14650
14706
  };
@@ -16550,7 +16606,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16550
16606
 
16551
16607
  this.$pos = pos;
16552
16608
  var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
16553
- this.$undoStackDepth = undoStack.length;
16609
+ this.$undoStackDepth = undoStack.length;
16554
16610
  this.setup();
16555
16611
 
16556
16612
  session.selection.on("changeCursor", this.$onCursorChange);
@@ -16563,103 +16619,97 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16563
16619
  var _self = this;
16564
16620
  var doc = this.doc;
16565
16621
  var session = this.session;
16566
- var pos = this.$pos;
16567
16622
 
16568
16623
  this.selectionBefore = session.selection.toJSON();
16569
16624
  if (session.selection.inMultiSelectMode)
16570
16625
  session.selection.toSingleRange();
16571
16626
 
16572
- this.pos = doc.createAnchor(pos.row, pos.column);
16573
- this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
16574
- this.pos.on("change", function(event) {
16575
- session.removeMarker(_self.markerId);
16576
- _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false);
16577
- });
16627
+ this.pos = doc.createAnchor(this.$pos.row, this.$pos.column);
16628
+ var pos = this.pos;
16629
+ pos.$insertRight = true;
16630
+ pos.detach();
16631
+ pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
16578
16632
  this.others = [];
16579
16633
  this.$others.forEach(function(other) {
16580
16634
  var anchor = doc.createAnchor(other.row, other.column);
16635
+ anchor.$insertRight = true;
16636
+ anchor.detach();
16581
16637
  _self.others.push(anchor);
16582
16638
  });
16583
16639
  session.setUndoSelect(false);
16584
16640
  };
16585
16641
  this.showOtherMarkers = function() {
16586
- if(this.othersActive) return;
16642
+ if (this.othersActive) return;
16587
16643
  var session = this.session;
16588
16644
  var _self = this;
16589
16645
  this.othersActive = true;
16590
16646
  this.others.forEach(function(anchor) {
16591
16647
  anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);
16592
- anchor.on("change", function(event) {
16593
- session.removeMarker(anchor.markerId);
16594
- anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false);
16595
- });
16596
16648
  });
16597
16649
  };
16598
16650
  this.hideOtherMarkers = function() {
16599
- if(!this.othersActive) return;
16651
+ if (!this.othersActive) return;
16600
16652
  this.othersActive = false;
16601
16653
  for (var i = 0; i < this.others.length; i++) {
16602
16654
  this.session.removeMarker(this.others[i].markerId);
16603
16655
  }
16604
16656
  };
16605
16657
  this.onUpdate = function(delta) {
16658
+ if (this.$updating)
16659
+ return this.updateAnchors(delta);
16660
+
16606
16661
  var range = delta;
16607
- if(range.start.row !== range.end.row) return;
16608
- if(range.start.row !== this.pos.row) return;
16609
- if (this.$updating) return;
16662
+ if (range.start.row !== range.end.row) return;
16663
+ if (range.start.row !== this.pos.row) return;
16610
16664
  this.$updating = true;
16611
16665
  var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column;
16666
+ var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1;
16667
+ var distanceFromStart = range.start.column - this.pos.column;
16668
+
16669
+ this.updateAnchors(delta);
16612
16670
 
16613
- if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {
16614
- var distanceFromStart = range.start.column - this.pos.column;
16671
+ if (inMainRange)
16615
16672
  this.length += lengthDiff;
16616
- if(!this.session.$fromUndo) {
16617
- if(delta.action === 'insert') {
16618
- for (var i = this.others.length - 1; i >= 0; i--) {
16619
- var otherPos = this.others[i];
16620
- var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
16621
- if(otherPos.row === range.start.row && range.start.column < otherPos.column)
16622
- newPos.column += lengthDiff;
16623
- this.doc.insertMergedLines(newPos, delta.lines);
16624
- }
16625
- } else if(delta.action === 'remove') {
16626
- for (var i = this.others.length - 1; i >= 0; i--) {
16627
- var otherPos = this.others[i];
16628
- var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
16629
- if(otherPos.row === range.start.row && range.start.column < otherPos.column)
16630
- newPos.column += lengthDiff;
16631
- this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
16632
- }
16633
- }
16634
- if(range.start.column === this.pos.column && delta.action === 'insert') {
16635
- setTimeout(function() {
16636
- this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);
16637
- for (var i = 0; i < this.others.length; i++) {
16638
- var other = this.others[i];
16639
- var newPos = {row: other.row, column: other.column - lengthDiff};
16640
- if(other.row === range.start.row && range.start.column < other.column)
16641
- newPos.column += lengthDiff;
16642
- other.setPosition(newPos.row, newPos.column);
16643
- }
16644
- }.bind(this), 0);
16673
+
16674
+ if (inMainRange && !this.session.$fromUndo) {
16675
+ if (delta.action === 'insert') {
16676
+ for (var i = this.others.length - 1; i >= 0; i--) {
16677
+ var otherPos = this.others[i];
16678
+ var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
16679
+ this.doc.insertMergedLines(newPos, delta.lines);
16645
16680
  }
16646
- else if(range.start.column === this.pos.column && delta.action === 'remove') {
16647
- setTimeout(function() {
16648
- for (var i = 0; i < this.others.length; i++) {
16649
- var other = this.others[i];
16650
- if(other.row === range.start.row && range.start.column < other.column) {
16651
- other.setPosition(other.row, other.column - lengthDiff);
16652
- }
16653
- }
16654
- }.bind(this), 0);
16681
+ } else if (delta.action === 'remove') {
16682
+ for (var i = this.others.length - 1; i >= 0; i--) {
16683
+ var otherPos = this.others[i];
16684
+ var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
16685
+ this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
16655
16686
  }
16656
16687
  }
16657
- this.pos._emit("change", {value: this.pos});
16658
- for (var i = 0; i < this.others.length; i++) {
16659
- this.others[i]._emit("change", {value: this.others[i]});
16660
- }
16661
16688
  }
16689
+
16662
16690
  this.$updating = false;
16691
+ this.updateMarkers();
16692
+ };
16693
+
16694
+ this.updateAnchors = function(delta) {
16695
+ this.pos.onChange(delta);
16696
+ for (var i = this.others.length; i--;)
16697
+ this.others[i].onChange(delta);
16698
+ this.updateMarkers();
16699
+ };
16700
+
16701
+ this.updateMarkers = function() {
16702
+ if (this.$updating)
16703
+ return;
16704
+ var _self = this;
16705
+ var session = this.session;
16706
+ var updateMarker = function(pos, className) {
16707
+ session.removeMarker(pos.markerId);
16708
+ pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false);
16709
+ };
16710
+ updateMarker(this.pos, this.mainClass);
16711
+ for (var i = this.others.length; i--;)
16712
+ updateMarker(this.others[i], this.othersClass);
16663
16713
  };
16664
16714
 
16665
16715
  this.onCursorChange = function(event) {
@@ -16674,20 +16724,16 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16674
16724
  }
16675
16725
  };
16676
16726
  this.detach = function() {
16677
- this.session.removeMarker(this.markerId);
16727
+ this.session.removeMarker(this.pos && this.pos.markerId);
16678
16728
  this.hideOtherMarkers();
16679
16729
  this.doc.removeEventListener("change", this.$onUpdate);
16680
16730
  this.session.selection.removeEventListener("changeCursor", this.$onCursorChange);
16681
- this.pos.detach();
16682
- for (var i = 0; i < this.others.length; i++) {
16683
- this.others[i].detach();
16684
- }
16685
16731
  this.session.setUndoSelect(true);
16686
16732
  this.session = null;
16687
16733
  };
16688
16734
  this.cancel = function() {
16689
- if(this.$undoStackDepth === -1)
16690
- throw Error("Canceling placeholders only supported with undo manager attached to session.");
16735
+ if (this.$undoStackDepth === -1)
16736
+ return;
16691
16737
  var undoManager = this.session.getUndoManager();
16692
16738
  var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;
16693
16739
  for (var i = 0; i < undosRequired; i++) {
@@ -18007,6 +18053,7 @@ function LineWidgets(session) {
18007
18053
  this.$onChangeEditor = this.$onChangeEditor.bind(this);
18008
18054
 
18009
18055
  this.session.on("change", this.updateOnChange);
18056
+ this.session.on("changeFold", this.updateOnFold);
18010
18057
  this.session.on("changeEditor", this.$onChangeEditor);
18011
18058
  }
18012
18059
 
@@ -18027,8 +18074,8 @@ function LineWidgets(session) {
18027
18074
  this.$getWidgetScreenLength = function() {
18028
18075
  var screenRows = 0;
18029
18076
  this.lineWidgets.forEach(function(w){
18030
- if (w && w.rowCount)
18031
- screenRows +=w.rowCount;
18077
+ if (w && w.rowCount && !w.hidden)
18078
+ screenRows += w.rowCount;
18032
18079
  });
18033
18080
  return screenRows;
18034
18081
  };
@@ -18072,6 +18119,32 @@ function LineWidgets(session) {
18072
18119
  });
18073
18120
  };
18074
18121
 
18122
+ this.updateOnFold = function(e, session) {
18123
+ var lineWidgets = session.lineWidgets;
18124
+ if (!lineWidgets || !e.action)
18125
+ return;
18126
+ var fold = e.data;
18127
+ var start = fold.start.row;
18128
+ var end = fold.end.row;
18129
+ var hide = e.action == "add";
18130
+ for (var i = start + 1; i < end; i++) {
18131
+ if (lineWidgets[i])
18132
+ lineWidgets[i].hidden = hide;
18133
+ }
18134
+ if (lineWidgets[end]) {
18135
+ if (hide) {
18136
+ if (!lineWidgets[start])
18137
+ lineWidgets[start] = lineWidgets[end];
18138
+ else
18139
+ lineWidgets[end].hidden = hide;
18140
+ } else {
18141
+ if (lineWidgets[start] == lineWidgets[end])
18142
+ lineWidgets[start] = undefined;
18143
+ lineWidgets[end].hidden = hide;
18144
+ }
18145
+ }
18146
+ };
18147
+
18075
18148
  this.updateOnChange = function(delta) {
18076
18149
  var lineWidgets = this.session.lineWidgets;
18077
18150
  if (!lineWidgets) return;
@@ -18102,6 +18175,10 @@ function LineWidgets(session) {
18102
18175
  if (w) {
18103
18176
  noWidgets = false;
18104
18177
  w.row = i;
18178
+ while (w.$oldWidget) {
18179
+ w.$oldWidget.row = i;
18180
+ w = w.$oldWidget;
18181
+ }
18105
18182
  }
18106
18183
  });
18107
18184
  if (noWidgets)
@@ -18112,8 +18189,19 @@ function LineWidgets(session) {
18112
18189
  if (!this.session.lineWidgets)
18113
18190
  this.session.lineWidgets = new Array(this.session.getLength());
18114
18191
 
18192
+ var old = this.session.lineWidgets[w.row];
18193
+ if (old) {
18194
+ w.$oldWidget = old;
18195
+ if (old.el && old.el.parentNode) {
18196
+ old.el.parentNode.removeChild(old.el);
18197
+ old._inDocument = false;
18198
+ }
18199
+ }
18200
+
18115
18201
  this.session.lineWidgets[w.row] = w;
18116
18202
 
18203
+ w.session = this.session;
18204
+
18117
18205
  var renderer = this.editor.renderer;
18118
18206
  if (w.html && !w.el) {
18119
18207
  w.el = dom.createElement("div");
@@ -18133,29 +18221,67 @@ function LineWidgets(session) {
18133
18221
  if (!w.pixelHeight) {
18134
18222
  w.pixelHeight = w.el.offsetHeight;
18135
18223
  }
18136
- if (w.rowCount == null)
18224
+ if (w.rowCount == null) {
18137
18225
  w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight;
18226
+ }
18138
18227
 
18228
+ var fold = this.session.getFoldAt(w.row, 0);
18229
+ w.$fold = fold;
18230
+ if (fold) {
18231
+ var lineWidgets = this.session.lineWidgets;
18232
+ if (w.row == fold.end.row && !lineWidgets[fold.start.row])
18233
+ lineWidgets[fold.start.row] = w;
18234
+ else
18235
+ w.hidden = true;
18236
+ }
18237
+
18139
18238
  this.session._emit("changeFold", {data:{start:{row: w.row}}});
18140
18239
 
18141
18240
  this.$updateRows();
18142
18241
  this.renderWidgets(null, renderer);
18242
+ this.onWidgetChanged(w);
18143
18243
  return w;
18144
18244
  };
18145
18245
 
18146
18246
  this.removeLineWidget = function(w) {
18147
18247
  w._inDocument = false;
18248
+ w.session = null;
18148
18249
  if (w.el && w.el.parentNode)
18149
18250
  w.el.parentNode.removeChild(w.el);
18150
18251
  if (w.editor && w.editor.destroy) try {
18151
18252
  w.editor.destroy();
18152
18253
  } catch(e){}
18153
- if (this.session.lineWidgets)
18154
- this.session.lineWidgets[w.row] = undefined;
18254
+ if (this.session.lineWidgets) {
18255
+ var w1 = this.session.lineWidgets[w.row]
18256
+ if (w1 == w) {
18257
+ this.session.lineWidgets[w.row] = w.$oldWidget;
18258
+ if (w.$oldWidget)
18259
+ this.onWidgetChanged(w.$oldWidget);
18260
+ } else {
18261
+ while (w1) {
18262
+ if (w1.$oldWidget == w) {
18263
+ w1.$oldWidget = w.$oldWidget;
18264
+ break;
18265
+ }
18266
+ w1 = w1.$oldWidget;
18267
+ }
18268
+ }
18269
+ }
18155
18270
  this.session._emit("changeFold", {data:{start:{row: w.row}}});
18156
18271
  this.$updateRows();
18157
18272
  };
18158
18273
 
18274
+ this.getWidgetsAtRow = function(row) {
18275
+ var lineWidgets = this.session.lineWidgets;
18276
+ var w = lineWidgets && lineWidgets[row];
18277
+ var list = [];
18278
+ while (w) {
18279
+ list.push(w);
18280
+ w = w.$oldWidget;
18281
+ }
18282
+ return list;
18283
+ };
18284
+
18159
18285
  this.onWidgetChanged = function(w) {
18160
18286
  this.session._changedWidgets.push(w);
18161
18287
  this.editor && this.editor.renderer.updateFull();
@@ -18169,7 +18295,11 @@ function LineWidgets(session) {
18169
18295
  var min = Infinity;
18170
18296
  for (var i = 0; i < changedWidgets.length; i++) {
18171
18297
  var w = changedWidgets[i];
18298
+ if (!w || !w.el) continue;
18299
+ if (w.session != this.session) continue;
18172
18300
  if (!w._inDocument) {
18301
+ if (this.session.lineWidgets[w.row] != w)
18302
+ continue;
18173
18303
  w._inDocument = true;
18174
18304
  renderer.container.appendChild(w.el);
18175
18305
  }
@@ -18218,7 +18348,10 @@ function LineWidgets(session) {
18218
18348
  for (var i = first; i <= last; i++) {
18219
18349
  var w = lineWidgets[i];
18220
18350
  if (!w || !w.el) continue;
18221
-
18351
+ if (w.hidden) {
18352
+ w.el.style.top = -100 - (w.pixelHeight || 0) + "px";
18353
+ continue;
18354
+ }
18222
18355
  if (!w._inDocument) {
18223
18356
  w._inDocument = true;
18224
18357
  renderer.container.appendChild(w.el);
@@ -18232,7 +18365,11 @@ function LineWidgets(session) {
18232
18365
  if (!w.fixedWidth)
18233
18366
  left -= renderer.scrollLeft;
18234
18367
  w.el.style.left = left + "px";
18235
-
18368
+
18369
+ if (w.fullWidth && w.screenWidth) {
18370
+ w.el.style.minWidth = config.width + 2 * config.padding + "px";
18371
+ }
18372
+
18236
18373
  if (w.fixedWidth) {
18237
18374
  w.el.style.right = renderer.scrollBar.getWidth() + "px";
18238
18375
  } else {
@@ -18316,7 +18453,9 @@ exports.showErrorMarker = function(editor, dir) {
18316
18453
 
18317
18454
  var pos = editor.getCursorPosition();
18318
18455
  var row = pos.row;
18319
- var oldWidget = session.lineWidgets && session.lineWidgets[row];
18456
+ var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) {
18457
+ return w.type == "errorMarker";
18458
+ })[0];
18320
18459
  if (oldWidget) {
18321
18460
  oldWidget.destroy();
18322
18461
  } else {
@@ -18346,7 +18485,8 @@ exports.showErrorMarker = function(editor, dir) {
18346
18485
  row: pos.row,
18347
18486
  fixedWidth: true,
18348
18487
  coverGutter: true,
18349
- el: dom.createElement("div")
18488
+ el: dom.createElement("div"),
18489
+ type: "errorMarker"
18350
18490
  };
18351
18491
  var el = w.el.appendChild(dom.createElement("div"));
18352
18492
  var arrow = w.el.appendChild(dom.createElement("div"));
@@ -18501,6 +18641,7 @@ exports.createEditSession = function(text, mode) {
18501
18641
  }
18502
18642
  exports.EditSession = EditSession;
18503
18643
  exports.UndoManager = UndoManager;
18644
+ exports.version = "1.2.2";
18504
18645
  });
18505
18646
  (function() {
18506
18647
  window.require(["ace/ace"], function(a) {