locomotive-aloha-rails 0.23.2.1 → 0.23.2.2
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/README.md +3 -3
- data/lib/aloha/rails/engine.rb +1 -1
- data/lib/aloha/rails/version.rb +2 -2
- data/lib/tasks/aloha-assets.rake +1 -1
- data/vendor/assets/javascripts/aloha/css/aloha-sidebar.css +41 -17
- data/vendor/assets/javascripts/aloha/css/aloha.css +2 -2
- data/vendor/assets/javascripts/aloha/lib/aloha/contenthandlermanager.js +19 -18
- data/vendor/assets/javascripts/aloha/lib/aloha/engine.js +168 -9
- data/vendor/assets/javascripts/aloha/lib/aloha/ephemera.js +8 -1
- data/vendor/assets/javascripts/aloha/lib/aloha/markup.js +3 -2
- data/vendor/assets/javascripts/aloha/lib/aloha/pluginmanager.js +8 -0
- data/vendor/assets/javascripts/aloha/lib/aloha/sidebar.js +1 -1
- data/vendor/assets/javascripts/aloha/lib/aloha/state-override.js +59 -37
- data/vendor/assets/javascripts/aloha/lib/util/arrays.js +53 -6
- data/vendor/assets/javascripts/aloha/lib/util/boundary-markers.js +86 -0
- data/vendor/assets/javascripts/aloha/lib/util/dom2.js +178 -19
- data/vendor/assets/javascripts/aloha/lib/util/html.js +77 -10
- data/vendor/assets/javascripts/aloha/lib/util/maps.js +23 -1
- data/vendor/assets/javascripts/aloha/lib/util/range-context.js +429 -181
- data/vendor/assets/javascripts/aloha/lib/util/strings.js +9 -1
- data/vendor/assets/javascripts/aloha/plugins/common/align/nls/de/i18n.js +4 -1
- data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockmanager.js +2 -5
- data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/css/characterpicker.css +6 -3
- data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/lib/characterpicker-plugin.js +29 -32
- data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/blockelementcontenthandler.js +41 -70
- data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml.js +1 -1
- data/vendor/assets/javascripts/aloha/plugins/common/format/lib/format-plugin.js +22 -10
- data/vendor/assets/javascripts/aloha/plugins/common/link/css/link.css +2 -8
- data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-cell.js +7 -0
- data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-plugin.js +149 -131
- data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table.js +77 -47
- data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/port-helper-attribute-field.js +4 -8
- data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/de/i18n.js +1 -0
- data/vendor/assets/javascripts/aloha/plugins/extra/cite/css/cite.css +0 -10
- data/vendor/assets/javascripts/aloha/plugins/extra/cite/lib/cite-plugin.js +4 -4
- data/vendor/assets/javascripts/aloha/plugins/extra/headerids/lib/headerids-plugin.js +84 -32
- data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/de/i18n.js +2 -1
- data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/i18n.js +2 -1
- metadata +15 -14
@@ -72,6 +72,7 @@ define([
|
|
72
72
|
'util/dom2',
|
73
73
|
'util/functions',
|
74
74
|
'util/misc',
|
75
|
+
'util/browser',
|
75
76
|
'PubSub'
|
76
77
|
], function (
|
77
78
|
$,
|
@@ -84,6 +85,7 @@ define([
|
|
84
85
|
Dom,
|
85
86
|
Functions,
|
86
87
|
Misc,
|
88
|
+
Browser,
|
87
89
|
PubSub
|
88
90
|
) {
|
89
91
|
'use strict';
|
@@ -325,7 +327,12 @@ define([
|
|
325
327
|
var data = $elem.attr('data-aloha-ephemera-attr');
|
326
328
|
var i;
|
327
329
|
var attrs;
|
328
|
-
|
330
|
+
// Because IE7 crashes if we remove this attribute. If the
|
331
|
+
// dom-to-xhtml plugin is turned on, it will handle the removal
|
332
|
+
// of this attribute during serialization.
|
333
|
+
if (!Browser.ie7) {
|
334
|
+
$elem.removeAttr('data-aloha-ephemera-attr');
|
335
|
+
}
|
329
336
|
if (typeof data === 'string') {
|
330
337
|
attrs = Strings.words(data);
|
331
338
|
for (i = 0; i < attrs.length; i++) {
|
@@ -27,6 +27,7 @@
|
|
27
27
|
define([
|
28
28
|
'aloha/core',
|
29
29
|
'util/class',
|
30
|
+
'util/html',
|
30
31
|
'jquery',
|
31
32
|
'aloha/ecma5shims',
|
32
33
|
'aloha/console',
|
@@ -34,6 +35,7 @@ define([
|
|
34
35
|
], function (
|
35
36
|
Aloha,
|
36
37
|
Class,
|
38
|
+
Html,
|
37
39
|
jQuery,
|
38
40
|
shims,
|
39
41
|
console,
|
@@ -384,14 +386,13 @@ define([
|
|
384
386
|
|
385
387
|
// ENTER
|
386
388
|
if (event.keyCode === 13) {
|
387
|
-
if (event.shiftKey) {
|
389
|
+
if (event.shiftKey || !Html.allowNestedParagraph(Aloha.activeEditable)) {
|
388
390
|
Aloha.execCommand('insertlinebreak', false);
|
389
391
|
return false;
|
390
392
|
}
|
391
393
|
Aloha.execCommand('insertparagraph', false);
|
392
394
|
return false;
|
393
395
|
}
|
394
|
-
|
395
396
|
return true;
|
396
397
|
},
|
397
398
|
|
@@ -80,6 +80,12 @@ define([
|
|
80
80
|
* successfully initialized.
|
81
81
|
*/
|
82
82
|
function initializePlugins(plugins, callback) {
|
83
|
+
if (0 === plugins.length) {
|
84
|
+
if (callback) {
|
85
|
+
callback();
|
86
|
+
}
|
87
|
+
return;
|
88
|
+
}
|
83
89
|
var numToEnable = plugins.length;
|
84
90
|
var onInit = function () {
|
85
91
|
if (0 === --numToEnable && callback) {
|
@@ -102,6 +108,8 @@ define([
|
|
102
108
|
} else {
|
103
109
|
onInit();
|
104
110
|
}
|
111
|
+
} else {
|
112
|
+
onInit();
|
105
113
|
}
|
106
114
|
}
|
107
115
|
}
|
@@ -27,42 +27,38 @@
|
|
27
27
|
define([
|
28
28
|
'aloha/core',
|
29
29
|
'jquery',
|
30
|
-
'aloha/selection',
|
31
30
|
'aloha/command',
|
32
31
|
'util/dom2',
|
32
|
+
'util/maps',
|
33
|
+
'util/range',
|
33
34
|
'PubSub'
|
34
35
|
], function (
|
35
36
|
Aloha,
|
36
37
|
jQuery,
|
37
|
-
Selection,
|
38
38
|
Command,
|
39
39
|
Dom,
|
40
|
+
Maps,
|
41
|
+
RangeObject,
|
40
42
|
PubSub
|
41
43
|
) {
|
42
44
|
'use strict';
|
43
45
|
|
44
|
-
|
46
|
+
// Because we want to provide an easy way to disable the state-override feature.
|
47
|
+
var enabled = Aloha.settings.stateOverride !== false;
|
48
|
+
var overrides = null;
|
49
|
+
var overrideRange = null;
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
// Because the UI may reflect the any potentially state
|
55
|
-
// overrides that are now no longer in effect, we must
|
56
|
-
// redraw the UI according to the current selection.
|
57
|
-
PubSub.pub('aloha.selection.context-change', {
|
58
|
-
range: range,
|
59
|
-
event: event
|
60
|
-
});
|
61
|
-
}
|
62
|
-
});
|
51
|
+
function rangeObjectFromRange(range) {
|
52
|
+
return new RangeObject(range);
|
53
|
+
}
|
54
|
+
|
55
|
+
function clear() {
|
56
|
+
overrideRange = null;
|
57
|
+
overrides = null;
|
58
|
+
}
|
63
59
|
|
64
60
|
function keyPressHandler(event) {
|
65
|
-
if (!
|
61
|
+
if (!overrides) {
|
66
62
|
return;
|
67
63
|
}
|
68
64
|
if (event.altKey || event.ctrlKey || !event.which) {
|
@@ -74,32 +70,37 @@ define([
|
|
74
70
|
}
|
75
71
|
var text = String.fromCharCode(event.which);
|
76
72
|
var range = selection.getRangeAt(0);
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
73
|
+
Dom.insertSelectText(text, range);
|
74
|
+
Maps.forEach(overrides, function (formatFn, command) {
|
75
|
+
formatFn(command, range);
|
76
|
+
});
|
77
|
+
Dom.collapseToEnd(range);
|
78
|
+
selection.removeAllRanges();
|
79
|
+
selection.addRange(range);
|
84
80
|
// Because we handled the character insert ourselves via
|
85
81
|
// insertText we must not let the browser's default action
|
86
82
|
// insert the character a second time.
|
87
83
|
event.preventDefault();
|
88
84
|
}
|
89
85
|
|
90
|
-
function
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
86
|
+
function set(command, range, formatFn) {
|
87
|
+
if (!enabled) {
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
overrideRange = range;
|
91
|
+
overrides = overrides || {};
|
92
|
+
overrides[command] = formatFn;
|
95
93
|
}
|
96
94
|
|
97
|
-
function setWithRangeObject(command,
|
95
|
+
function setWithRangeObject(command, rangeObject, formatFn) {
|
98
96
|
if (!enabled) {
|
99
97
|
return;
|
100
98
|
}
|
101
|
-
|
102
|
-
|
99
|
+
set(command, Dom.rangeFromRangeObject(rangeObject), function (command, range) {
|
100
|
+
var rangeObject = rangeObjectFromRange(range);
|
101
|
+
formatFn(command, rangeObject);
|
102
|
+
Dom.setRangeFromRef(range, rangeObject);
|
103
|
+
});
|
103
104
|
// Because without doing rangeObject.select(), the
|
104
105
|
// next insertText command (see editable.js) will
|
105
106
|
// not be reached and instead the browsers default
|
@@ -117,9 +118,30 @@ define([
|
|
117
118
|
return enabled;
|
118
119
|
}
|
119
120
|
|
121
|
+
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#state-override
|
122
|
+
// "Whenever the number of ranges in the selection changes to
|
123
|
+
// something different, and whenever a boundary point of the range
|
124
|
+
// at a given index in the selection changes to something different,
|
125
|
+
// the state override and value override must be unset for every
|
126
|
+
// command."
|
127
|
+
Aloha.bind('aloha-selection-changed', function (event, range) {
|
128
|
+
if (overrideRange && !Dom.areRangesEq(overrideRange, range)) {
|
129
|
+
clear();
|
130
|
+
// Because the UI may reflect the any potentially state
|
131
|
+
// overrides that are now no longer in effect, we must
|
132
|
+
// redraw the UI according to the current selection.
|
133
|
+
PubSub.pub('aloha.selection.context-change', {
|
134
|
+
range: range,
|
135
|
+
event: event
|
136
|
+
});
|
137
|
+
}
|
138
|
+
});
|
139
|
+
|
120
140
|
return {
|
121
141
|
enabled: enabledAccessor,
|
122
142
|
keyPressHandler: keyPressHandler,
|
123
|
-
setWithRangeObject: setWithRangeObject
|
143
|
+
setWithRangeObject: setWithRangeObject,
|
144
|
+
set: set,
|
145
|
+
clear: clear
|
124
146
|
};
|
125
147
|
});
|
@@ -24,7 +24,7 @@
|
|
24
24
|
* provided you include this license notice and a URL through which
|
25
25
|
* recipients can access the Corresponding Source.
|
26
26
|
*/
|
27
|
-
define([], function () {
|
27
|
+
define(['util/functions'], function (Fn) {
|
28
28
|
'use strict';
|
29
29
|
|
30
30
|
/**
|
@@ -104,10 +104,10 @@ define([], function () {
|
|
104
104
|
}
|
105
105
|
|
106
106
|
/**
|
107
|
-
* ECMAScript map
|
107
|
+
* Emulates ECMAScript edition 5 Arrays.map
|
108
108
|
* See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
|
109
109
|
* And http://es5.github.com/#x15.4.4.19
|
110
|
-
* It's not exactly according to standard, but it does
|
110
|
+
* It's not exactly according to standard, but it does what one expects.
|
111
111
|
*/
|
112
112
|
function map(a, fn) {
|
113
113
|
var i, len, result = [];
|
@@ -169,7 +169,7 @@ define([], function () {
|
|
169
169
|
* Arrays.reduce([2, 3, 4], 1, function (a, b) { return a + b; });
|
170
170
|
* returns the result of (((1 + 2) + 3) + 4)
|
171
171
|
*
|
172
|
-
* Emulates
|
172
|
+
* Emulates ECMAScript edition 5 Array.reduce.
|
173
173
|
*
|
174
174
|
* @param a
|
175
175
|
* An array of values.
|
@@ -206,7 +206,9 @@ define([], function () {
|
|
206
206
|
}
|
207
207
|
|
208
208
|
/**
|
209
|
-
*
|
209
|
+
* For each item in xs, call cb(item, index, xs).
|
210
|
+
*
|
211
|
+
* Emulates ECMAScript edition 5 Array.forEach.
|
210
212
|
*/
|
211
213
|
function forEach(xs, cb) {
|
212
214
|
var i,
|
@@ -216,6 +218,33 @@ define([], function () {
|
|
216
218
|
}
|
217
219
|
}
|
218
220
|
|
221
|
+
/**
|
222
|
+
* Returns true if the given predicate function returns true for at
|
223
|
+
* least one item.
|
224
|
+
*
|
225
|
+
* Emulates ECMAScript edition 5 Array.some.
|
226
|
+
*/
|
227
|
+
function some(xs, pred) {
|
228
|
+
var i,
|
229
|
+
len;
|
230
|
+
for (i = 0, len = xs.length; i < len; i++) {
|
231
|
+
if (pred(xs[i])) {
|
232
|
+
return true;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
return false;
|
236
|
+
}
|
237
|
+
|
238
|
+
/**
|
239
|
+
* Returns true if the given predicate function returns true for all
|
240
|
+
* items in xs.
|
241
|
+
*
|
242
|
+
* Emulates ECMAScript edition 5 Array.every.
|
243
|
+
*/
|
244
|
+
function every(xs, pred) {
|
245
|
+
return !some(xs, Fn.complement(pred));
|
246
|
+
}
|
247
|
+
|
219
248
|
/**
|
220
249
|
* Returns all items in xs that are also contained in zs.
|
221
250
|
*/
|
@@ -225,16 +254,34 @@ define([], function () {
|
|
225
254
|
});
|
226
255
|
}
|
227
256
|
|
257
|
+
/**
|
258
|
+
* Returns the last item in xs or null.
|
259
|
+
*/
|
260
|
+
function last(xs) {
|
261
|
+
return xs.length ? xs[xs.length - 1] : null;
|
262
|
+
}
|
263
|
+
|
264
|
+
/**
|
265
|
+
* Returns the second item in xs.
|
266
|
+
*/
|
267
|
+
function second(xs) {
|
268
|
+
return xs[1];
|
269
|
+
}
|
270
|
+
|
228
271
|
return {
|
229
272
|
filter: filter,
|
230
273
|
indexOf: indexOf,
|
231
274
|
reduce: reduce,
|
232
275
|
forEach: forEach,
|
276
|
+
some: some,
|
277
|
+
every: every,
|
233
278
|
map: Array.prototype.map ? mapNative : map,
|
234
279
|
contains: contains,
|
235
280
|
equal: equal,
|
236
281
|
applyNotNull: applyNotNull,
|
237
282
|
sortUnique: sortUnique,
|
238
|
-
intersect: intersect
|
283
|
+
intersect: intersect,
|
284
|
+
second: second,
|
285
|
+
last: last
|
239
286
|
};
|
240
287
|
});
|
@@ -0,0 +1,86 @@
|
|
1
|
+
define(['util/dom2', 'util/arrays', 'util/strings'], function (Dom, Arrays, Strings) {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
function insert(range) {
|
5
|
+
var leftMarkerChar = (3 === range.startContainer.nodeType ? '[' : '{');
|
6
|
+
var rightMarkerChar = (3 === range.endContainer.nodeType ? ']' : '}');
|
7
|
+
Dom.splitTextContainers(range);
|
8
|
+
var leftMarker = document.createTextNode(leftMarkerChar);
|
9
|
+
var rightMarker = document.createTextNode(rightMarkerChar);
|
10
|
+
var start = Dom.cursorFromBoundaryPoint(range.startContainer, range.startOffset);
|
11
|
+
var end = Dom.cursorFromBoundaryPoint(range.endContainer, range.endOffset);
|
12
|
+
start.insert(leftMarker);
|
13
|
+
end.insert(rightMarker);
|
14
|
+
}
|
15
|
+
|
16
|
+
function extract(rootElem, range) {
|
17
|
+
var markers = ['[', '{', '}', ']'];
|
18
|
+
var markersFound = 0;
|
19
|
+
function setBoundaryPoint(marker, node) {
|
20
|
+
var setFn;
|
21
|
+
if (0 === markersFound) {
|
22
|
+
setFn = 'setStart';
|
23
|
+
if (marker !== '[' && marker !== '{') {
|
24
|
+
throw "end marker before start marker";
|
25
|
+
}
|
26
|
+
} else if (1 === markersFound) {
|
27
|
+
setFn = 'setEnd';
|
28
|
+
if (marker !== ']' && marker !== '}') {
|
29
|
+
throw "start marker before end marker";
|
30
|
+
}
|
31
|
+
} else {
|
32
|
+
throw "Too many markers";
|
33
|
+
}
|
34
|
+
markersFound += 1;
|
35
|
+
if (marker === '[' || marker === ']') {
|
36
|
+
var previousSibling = node.previousSibling;
|
37
|
+
if (!previousSibling || 3 !== previousSibling.nodeType) {
|
38
|
+
previousSibling = document.createTextNode('');
|
39
|
+
node.parentNode.insertBefore(previousSibling, node);
|
40
|
+
}
|
41
|
+
range[setFn].call(range, previousSibling, previousSibling.length);
|
42
|
+
// Because we have set a text offset.
|
43
|
+
return false;
|
44
|
+
} else { // marker === '{' || marker === '}'
|
45
|
+
range[setFn].call(range, node.parentNode, Dom.nodeIndex(node));
|
46
|
+
// Because we have set a non-text offset.
|
47
|
+
return true;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
function extractMarkers(node) {
|
51
|
+
if (3 !== node.nodeType) {
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
var text = node.nodeValue;
|
55
|
+
var parts = Strings.splitIncl(text, /[\[\{\}\]]/g);
|
56
|
+
// Because modifying every text node when there can be
|
57
|
+
// only two markers seems like too much overhead.
|
58
|
+
if (!Arrays.contains(markers, parts[0]) && parts.length < 2) {
|
59
|
+
return;
|
60
|
+
}
|
61
|
+
// Because non-text boundary positions must not be joined again.
|
62
|
+
var forceNextSplit = false;
|
63
|
+
Arrays.forEach(parts, function (part, i) {
|
64
|
+
// Because we don't want to join text nodes we haven't split.
|
65
|
+
forceNextSplit = forceNextSplit || (i === 0);
|
66
|
+
if (Arrays.contains(markers, part)) {
|
67
|
+
forceNextSplit = setBoundaryPoint(part, node);
|
68
|
+
} else if (!forceNextSplit && node.previousSibling && 3 === node.previousSibling.nodeType) {
|
69
|
+
node.previousSibling.insertData(node.previousSibling.length, part);
|
70
|
+
} else {
|
71
|
+
node.parentNode.insertBefore(document.createTextNode(part), node);
|
72
|
+
}
|
73
|
+
});
|
74
|
+
node.parentNode.removeChild(node);
|
75
|
+
}
|
76
|
+
Dom.walkRec(rootElem, extractMarkers);
|
77
|
+
if (2 !== markersFound) {
|
78
|
+
throw "Missing one or both markers";
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return {
|
83
|
+
insert: insert,
|
84
|
+
extract: extract
|
85
|
+
};
|
86
|
+
});
|
@@ -25,19 +25,25 @@
|
|
25
25
|
* recipients can access the Corresponding Source.
|
26
26
|
*/
|
27
27
|
define([
|
28
|
+
'aloha/core',
|
28
29
|
'jquery',
|
29
30
|
'util/functions',
|
30
31
|
'util/maps',
|
31
32
|
'util/arrays',
|
32
33
|
'util/strings',
|
33
|
-
'util/browser'
|
34
|
+
'util/browser',
|
35
|
+
'util/dom',
|
36
|
+
'util/range'
|
34
37
|
], function (
|
38
|
+
Aloha,
|
35
39
|
$,
|
36
40
|
Fn,
|
37
41
|
Maps,
|
38
42
|
Arrays,
|
39
43
|
Strings,
|
40
|
-
Browser
|
44
|
+
Browser,
|
45
|
+
Dom1,
|
46
|
+
RangeObject
|
41
47
|
) {
|
42
48
|
'use strict';
|
43
49
|
|
@@ -293,7 +299,6 @@ define([
|
|
293
299
|
return index;
|
294
300
|
}
|
295
301
|
|
296
|
-
|
297
302
|
function nodeIndex(node) {
|
298
303
|
var ret = 0;
|
299
304
|
while (node.previousSibling) {
|
@@ -304,6 +309,7 @@ define([
|
|
304
309
|
}
|
305
310
|
|
306
311
|
/**
|
312
|
+
* Can't use elem.childNodes.length because
|
307
313
|
* http://www.quirksmode.org/dom/w3c_core.html
|
308
314
|
* "IE up to 8 does not count empty text nodes."
|
309
315
|
*/
|
@@ -347,7 +353,7 @@ define([
|
|
347
353
|
return node;
|
348
354
|
}
|
349
355
|
|
350
|
-
function
|
356
|
+
function removeShallow(node) {
|
351
357
|
var parent = node.parentNode;
|
352
358
|
moveNextAll(parent, node.firstChild, node);
|
353
359
|
parent.removeChild(node);
|
@@ -506,6 +512,24 @@ define([
|
|
506
512
|
});
|
507
513
|
}
|
508
514
|
|
515
|
+
function next(node, until, arg) {
|
516
|
+
while (node && !until(node, arg)) {
|
517
|
+
node = node.nextSibling;
|
518
|
+
}
|
519
|
+
return node;
|
520
|
+
}
|
521
|
+
|
522
|
+
function parent(node, until, arg) {
|
523
|
+
while (node && !until(node, arg)) {
|
524
|
+
node = node.parentNode;
|
525
|
+
}
|
526
|
+
return node;
|
527
|
+
}
|
528
|
+
|
529
|
+
function isTextNode(node) {
|
530
|
+
return 3 === node.nodeType;
|
531
|
+
}
|
532
|
+
|
509
533
|
function splitTextNode(node, offset) {
|
510
534
|
// Because node.splitText() is buggy on IE, split it manually.
|
511
535
|
// http://www.quirksmode.org/dom/w3c_core.html
|
@@ -543,10 +567,26 @@ define([
|
|
543
567
|
range[setProp].call(range, container, offset);
|
544
568
|
}
|
545
569
|
|
546
|
-
|
570
|
+
/**
|
571
|
+
* Splits the given text node at the given offset and, if the given
|
572
|
+
* range happens to have start or end containers equal to the given
|
573
|
+
* text node, adjusts it such that start and end position will point
|
574
|
+
* at the same position in the new text nodes.
|
575
|
+
*
|
576
|
+
* It is guaranteed that an adjusted boundary point will not point
|
577
|
+
* to the end of a text node. Instead, it will point to the next
|
578
|
+
* node. This guarantee often happens to be useful.
|
579
|
+
*
|
580
|
+
* If splitNode is not a text node, does nothing.
|
581
|
+
*/
|
582
|
+
function splitTextNodeAdjustRange(splitNode, splitOffset, range) {
|
547
583
|
if (3 !== splitNode.nodeType) {
|
548
584
|
return;
|
549
585
|
}
|
586
|
+
var sc = range.startContainer;
|
587
|
+
var so = range.startOffset;
|
588
|
+
var ec = range.endContainer;
|
589
|
+
var eo = range.endOffset;
|
550
590
|
var newNodeBeforeSplit = splitTextNode(splitNode, splitOffset);
|
551
591
|
adjustRangeAfterSplit(range, sc, so, 'setStart', splitNode, newNodeBeforeSplit);
|
552
592
|
adjustRangeAfterSplit(range, ec, eo, 'setEnd', splitNode, newNodeBeforeSplit);
|
@@ -555,44 +595,47 @@ define([
|
|
555
595
|
function splitTextContainers(range) {
|
556
596
|
var sc = range.startContainer;
|
557
597
|
var so = range.startOffset;
|
598
|
+
splitTextNodeAdjustRange(sc, so, range);
|
599
|
+
// Because the range may have been adjusted.
|
558
600
|
var ec = range.endContainer;
|
559
601
|
var eo = range.endOffset;
|
560
|
-
|
561
|
-
// Because the range may have been adjusted.
|
562
|
-
sc = range.startContainer;
|
563
|
-
so = range.startOffset;
|
564
|
-
ec = range.endContainer;
|
565
|
-
eo = range.endOffset;
|
566
|
-
splitNodeAdjustRange(ec, eo, sc, so, ec, eo, range);
|
602
|
+
splitTextNodeAdjustRange(ec, eo, range);
|
567
603
|
}
|
568
604
|
|
569
605
|
function walkUntil(node, fn, until, arg) {
|
570
606
|
while (node && !until(node, arg)) {
|
571
|
-
|
607
|
+
var next = node.nextSibling;
|
608
|
+
fn(node, arg);
|
609
|
+
node = next;
|
572
610
|
}
|
573
|
-
return node;
|
574
611
|
}
|
575
612
|
|
576
613
|
function walk(node, fn, arg) {
|
577
614
|
walkUntil(node, fn, Fn.returnFalse, arg);
|
578
615
|
}
|
579
616
|
|
617
|
+
/**
|
618
|
+
* Depth-first postwalk of the given DOM node.
|
619
|
+
*/
|
580
620
|
function walkRec(node, fn, arg) {
|
581
621
|
if (1 === node.nodeType) {
|
582
622
|
walk(node.firstChild, function (node) {
|
583
|
-
|
623
|
+
walkRec(node, fn, arg);
|
584
624
|
});
|
585
625
|
}
|
586
|
-
|
626
|
+
fn(node, arg);
|
587
627
|
}
|
588
628
|
|
589
629
|
function walkUntilNode(node, fn, untilNode, arg) {
|
590
|
-
|
630
|
+
walkUntil(node, fn, function (nextNode) {
|
591
631
|
return nextNode === untilNode;
|
592
632
|
}, arg);
|
593
633
|
}
|
594
634
|
|
595
635
|
function StableRange(range) {
|
636
|
+
if (!range) {
|
637
|
+
return;
|
638
|
+
}
|
596
639
|
this.startContainer = range.startContainer;
|
597
640
|
this.startOffset = range.startOffset;
|
598
641
|
this.endContainer = range.endContainer;
|
@@ -710,6 +753,109 @@ define([
|
|
710
753
|
});
|
711
754
|
}
|
712
755
|
|
756
|
+
function areRangesEq(a, b) {
|
757
|
+
return a.startContainer === b.startContainer
|
758
|
+
&& a.startOffset === b.startOffset
|
759
|
+
&& a.endContainer === b.endContainer
|
760
|
+
&& a.endOffset === b.endOffset;
|
761
|
+
}
|
762
|
+
|
763
|
+
function insertSelectText(text, range) {
|
764
|
+
// Because empty text nodes are generally not nice and even
|
765
|
+
// cause problems with IE8 (elem.childNodes).
|
766
|
+
if (!text.length) {
|
767
|
+
return;
|
768
|
+
}
|
769
|
+
splitTextNodeAdjustRange(range.startContainer, range.startOffset, range);
|
770
|
+
var node = nodeAtOffset(range.startContainer, range.startOffset);
|
771
|
+
var atEnd = isAtEnd(range.startContainer, range.startOffset);
|
772
|
+
// Because if the node following the insert position is already
|
773
|
+
// a text node we can just reuse it.
|
774
|
+
if (!atEnd && 3 === node.nodeType) {
|
775
|
+
node.insertData(0, text);
|
776
|
+
range.setStart(node, 0);
|
777
|
+
range.setEnd(node, text.length);
|
778
|
+
return;
|
779
|
+
}
|
780
|
+
// Because if the node preceding the insert position is already
|
781
|
+
// a text node we can just reuse it.
|
782
|
+
var prev;
|
783
|
+
if (!atEnd) {
|
784
|
+
prev = node.previousSibling;
|
785
|
+
} else {
|
786
|
+
prev = node.lastChild;
|
787
|
+
}
|
788
|
+
if (prev && 3 === prev.nodeType) {
|
789
|
+
prev.insertData(prev.length, text);
|
790
|
+
range.setStart(prev, prev.length - text.length);
|
791
|
+
range.setEnd(prev, prev.length);
|
792
|
+
return;
|
793
|
+
}
|
794
|
+
// Because if we can't reuse any text nodes, we have to insert a
|
795
|
+
// new one.
|
796
|
+
var textNode = document.createTextNode(text);
|
797
|
+
insert(textNode, node, atEnd);
|
798
|
+
range.setStart(textNode, 0);
|
799
|
+
range.setEnd(textNode, textNode.length);
|
800
|
+
}
|
801
|
+
|
802
|
+
function collapseToEnd(range) {
|
803
|
+
range.setStart(range.endContainer, range.endOffset);
|
804
|
+
}
|
805
|
+
|
806
|
+
function rangeFromRangeObject(alohaRange) {
|
807
|
+
var range = Aloha.createRange();
|
808
|
+
range.setStart(alohaRange.startContainer, alohaRange.startOffset);
|
809
|
+
range.setEnd(alohaRange.endContainer, alohaRange.endOffset);
|
810
|
+
return range;
|
811
|
+
}
|
812
|
+
|
813
|
+
function extendToWord(range) {
|
814
|
+
var rangeObject = new RangeObject(range);
|
815
|
+
Dom1.extendToWord(rangeObject);
|
816
|
+
setRangeFromRef(range, rangeObject);
|
817
|
+
}
|
818
|
+
|
819
|
+
function cloneShallow(node) {
|
820
|
+
return node.cloneNode(false);
|
821
|
+
}
|
822
|
+
|
823
|
+
/**
|
824
|
+
* Sets a style on the given element by modifying it's style attribute.
|
825
|
+
*/
|
826
|
+
function setStyle(node, name, value) {
|
827
|
+
// Because only the empty string removes a style.
|
828
|
+
$(node).css(name, null == value ? '' : value);
|
829
|
+
}
|
830
|
+
|
831
|
+
/**
|
832
|
+
* Gets a style from the given element's style attribute.
|
833
|
+
* Note that this is different from the computed/inherited style.
|
834
|
+
*/
|
835
|
+
function getStyle(node, name) {
|
836
|
+
// Because IE7 needs dashesToCamelCase().
|
837
|
+
name = Strings.dashesToCamelCase(name);
|
838
|
+
return node.nodeType === 1 ? node.style[name] : null;
|
839
|
+
}
|
840
|
+
|
841
|
+
/**
|
842
|
+
* Gets the computed/inherited style of the given node.
|
843
|
+
* @param node may be a text node.
|
844
|
+
*/
|
845
|
+
function getComputedStyle(node, name) {
|
846
|
+
if (node.currentStyle) {
|
847
|
+
return node.currentStyle[name];
|
848
|
+
}
|
849
|
+
var doc = node.ownerDocument;
|
850
|
+
if (doc.defaultView && doc.defaultView.getComputedStyle) {
|
851
|
+
var styles = doc.defaultView.getComputedStyle(node, null);
|
852
|
+
if (styles) {
|
853
|
+
return styles[name] || styles.getPropertyValue(name);
|
854
|
+
}
|
855
|
+
}
|
856
|
+
return null;
|
857
|
+
}
|
858
|
+
|
713
859
|
return {
|
714
860
|
moveNextAll: moveNextAll,
|
715
861
|
attrNames: attrNames,
|
@@ -718,7 +864,7 @@ define([
|
|
718
864
|
indexByName: indexByName,
|
719
865
|
indexByClassHaveList: indexByClassHaveList,
|
720
866
|
outerHtml: outerHtml,
|
721
|
-
|
867
|
+
removeShallow: removeShallow,
|
722
868
|
wrap: wrap,
|
723
869
|
insert: insert,
|
724
870
|
cursor: cursor,
|
@@ -731,6 +877,9 @@ define([
|
|
731
877
|
childAndParentsUntilIncl: childAndParentsUntilIncl,
|
732
878
|
childAndParentsUntilNode: childAndParentsUntilNode,
|
733
879
|
childAndParentsUntilInclNode: childAndParentsUntilInclNode,
|
880
|
+
next: next,
|
881
|
+
parent: parent,
|
882
|
+
isTextNode: isTextNode,
|
734
883
|
nodeIndex: nodeIndex,
|
735
884
|
splitTextNode: splitTextNode,
|
736
885
|
splitTextContainers: splitTextContainers,
|
@@ -743,6 +892,16 @@ define([
|
|
743
892
|
trimRangeClosingOpening: trimRangeClosingOpening,
|
744
893
|
setRangeFromRef: setRangeFromRef,
|
745
894
|
setRangeStartFromCursor: setRangeStartFromCursor,
|
746
|
-
setRangeEndFromCursor: setRangeEndFromCursor
|
895
|
+
setRangeEndFromCursor: setRangeEndFromCursor,
|
896
|
+
splitTextNodeAdjustRange: splitTextNodeAdjustRange,
|
897
|
+
insertSelectText: insertSelectText,
|
898
|
+
areRangesEq: areRangesEq,
|
899
|
+
collapseToEnd: collapseToEnd,
|
900
|
+
extendToWord: extendToWord,
|
901
|
+
rangeFromRangeObject: rangeFromRangeObject,
|
902
|
+
cloneShallow: cloneShallow,
|
903
|
+
setStyle: setStyle,
|
904
|
+
getStyle: getStyle,
|
905
|
+
getComputedStyle: getComputedStyle
|
747
906
|
};
|
748
907
|
});
|