bootstrap-wysihtml5-rails 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/lib/bootstrap-wysihtml5-rails/version.rb +1 -1
- data/vendor/assets/javascripts/bootstrap-wysihtml5.js +162 -17
- data/vendor/assets/javascripts/wysihtml5.js +364 -367
- metadata +4 -4
data/Rakefile
CHANGED
@@ -19,14 +19,54 @@
|
|
19
19
|
//,+ "<a class='btn' data-wysihtml5-command='underline' title='CTRL+U'>Underline</a>"
|
20
20
|
+ "</div>"
|
21
21
|
+ "</li>",
|
22
|
-
"lists":
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
"lists": "<li>"
|
23
|
+
+ "<div class='btn-group'>"
|
24
|
+
+ "<a class='btn' data-wysihtml5-command='insertUnorderedList' title='Unordered List'><i class='icon-list'></i></a>"
|
25
|
+
+ "<a class='btn' data-wysihtml5-command='insertOrderedList' title='Ordered List'><i class='icon-th-list'></i></a>"
|
26
|
+
+ "<a class='btn' data-wysihtml5-command='Outdent' title='Outdent'><i class='icon-indent-right'></i></a>"
|
27
|
+
+ "<a class='btn' data-wysihtml5-command='Indent' title='Indent'><i class='icon-indent-left'></i></a>"
|
28
|
+
+ "</div>"
|
29
|
+
+ "</li>",
|
30
|
+
|
31
|
+
"link": "<li>"
|
32
|
+
|
33
|
+
+ "<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>"
|
34
|
+
+ "<div class='modal-header'>"
|
35
|
+
+ "<a class='close' data-dismiss='modal'>×</a>"
|
36
|
+
+ "<h3>Insert Link</h3>"
|
37
|
+
+ "</div>"
|
38
|
+
+ "<div class='modal-body'>"
|
39
|
+
+ "<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>"
|
40
|
+
+ "</div>"
|
41
|
+
+ "<div class='modal-footer'>"
|
42
|
+
+ "<a href='#' class='btn' data-dismiss='modal'>Cancel</a>"
|
43
|
+
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>Insert link</a>"
|
44
|
+
+ "</div>"
|
45
|
+
+ "</div>"
|
46
|
+
|
47
|
+
+ "<a class='btn' data-wysihtml5-command='createLink' title='Link'><i class='icon-share'></i></a>"
|
48
|
+
|
49
|
+
+ "</li>",
|
50
|
+
|
51
|
+
"image": "<li>"
|
52
|
+
|
53
|
+
+ "<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>"
|
54
|
+
+ "<div class='modal-header'>"
|
55
|
+
+ "<a class='close' data-dismiss='modal'>×</a>"
|
56
|
+
+ "<h3>Insert Image</h3>"
|
57
|
+
+ "</div>"
|
58
|
+
+ "<div class='modal-body'>"
|
59
|
+
+ "<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>"
|
60
|
+
+ "</div>"
|
61
|
+
+ "<div class='modal-footer'>"
|
62
|
+
+ "<a href='#' class='btn' data-dismiss='modal'>Cancel</a>"
|
63
|
+
+ "<a href='#' class='btn btn-primary' data-dismiss='modal'>Insert image</a>"
|
64
|
+
+ "</div>"
|
65
|
+
+ "</div>"
|
66
|
+
|
67
|
+
+ "<a class='btn' data-wysihtml5-command='insertImage' title='Insert image'><i class='icon-picture'></i></a>"
|
68
|
+
|
69
|
+
+ "</li>",
|
30
70
|
|
31
71
|
"html":
|
32
72
|
"<li>"
|
@@ -41,6 +81,8 @@
|
|
41
81
|
"emphasis": true,
|
42
82
|
"lists": true,
|
43
83
|
"html": false,
|
84
|
+
"link": true,
|
85
|
+
"image": false,
|
44
86
|
events: {},
|
45
87
|
parserRules: {
|
46
88
|
tags: {
|
@@ -53,6 +95,14 @@
|
|
53
95
|
"h1": {},
|
54
96
|
"h2": {},
|
55
97
|
"u": 1,
|
98
|
+
"img": {
|
99
|
+
"check_attributes": {
|
100
|
+
"width": "numbers",
|
101
|
+
"alt": "alt",
|
102
|
+
"src": "url",
|
103
|
+
"height": "numbers"
|
104
|
+
}
|
105
|
+
},
|
56
106
|
"a": {
|
57
107
|
set_attributes: {
|
58
108
|
target: "_blank",
|
@@ -70,6 +120,8 @@
|
|
70
120
|
this.el = el;
|
71
121
|
this.toolbar = this.createToolbar(el, options || defaultOptions);
|
72
122
|
this.editor = this.createEditor(options);
|
123
|
+
|
124
|
+
window.editor = this.editor;
|
73
125
|
|
74
126
|
$('iframe.wysihtml5-sandbox').each(function(i, el){
|
75
127
|
$(el.contentWindow).off('focus.wysihtml5').on({
|
@@ -78,6 +130,8 @@
|
|
78
130
|
}
|
79
131
|
});
|
80
132
|
});
|
133
|
+
|
134
|
+
|
81
135
|
};
|
82
136
|
|
83
137
|
Wysihtml5.prototype = {
|
@@ -105,11 +159,12 @@
|
|
105
159
|
},
|
106
160
|
|
107
161
|
createToolbar: function(el, options) {
|
162
|
+
var self = this;
|
108
163
|
var toolbar = $("<ul/>", {
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
164
|
+
'id' : el.attr('id') + "-wysihtml5-toolbar",
|
165
|
+
'class' : "wysihtml5-toolbar",
|
166
|
+
'style': "display:none"
|
167
|
+
});
|
113
168
|
|
114
169
|
for(var key in defaultOptions) {
|
115
170
|
var value = false;
|
@@ -126,10 +181,15 @@
|
|
126
181
|
toolbar.append(templates[key]);
|
127
182
|
|
128
183
|
if(key == "html") {
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
184
|
+
this.initHtml(toolbar);
|
185
|
+
}
|
186
|
+
|
187
|
+
if(key == "link") {
|
188
|
+
this.initInsertLink(toolbar);
|
189
|
+
}
|
190
|
+
|
191
|
+
if(key == "image") {
|
192
|
+
this.initInsertImage(toolbar);
|
133
193
|
}
|
134
194
|
}
|
135
195
|
}
|
@@ -144,6 +204,91 @@
|
|
144
204
|
this.el.before(toolbar);
|
145
205
|
|
146
206
|
return toolbar;
|
207
|
+
},
|
208
|
+
|
209
|
+
initHtml: function(toolbar) {
|
210
|
+
var changeViewSelector = "a[data-wysihtml5-action='change_view']";
|
211
|
+
toolbar.find(changeViewSelector).click(function(e) {
|
212
|
+
toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled');
|
213
|
+
});
|
214
|
+
},
|
215
|
+
|
216
|
+
initInsertImage: function(toolbar) {
|
217
|
+
var self = this;
|
218
|
+
var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal');
|
219
|
+
var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url');
|
220
|
+
var insertButton = insertImageModal.find('a.btn-primary');
|
221
|
+
|
222
|
+
var insertImage = function() {
|
223
|
+
var url = urlInput.val();
|
224
|
+
urlInput.val('');
|
225
|
+
self.editor.composer.commands.exec("createLink", {
|
226
|
+
href: url,
|
227
|
+
target: "_blank",
|
228
|
+
rel: "nofollow"
|
229
|
+
});
|
230
|
+
};
|
231
|
+
|
232
|
+
urlInput.keypress(function(e) {
|
233
|
+
if(e.which == 13) {
|
234
|
+
insertImage();
|
235
|
+
insertImageModal.modal('hide');
|
236
|
+
}
|
237
|
+
});
|
238
|
+
|
239
|
+
insertButton.click(insertImage);
|
240
|
+
|
241
|
+
insertImageModal.on('shown', function() {
|
242
|
+
urlInput.focus();
|
243
|
+
});
|
244
|
+
|
245
|
+
insertImageModal.on('hide', function() {
|
246
|
+
self.editor.currentView.element.focus();
|
247
|
+
});
|
248
|
+
|
249
|
+
toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() {
|
250
|
+
insertImageModal.modal('show');
|
251
|
+
});
|
252
|
+
},
|
253
|
+
|
254
|
+
initInsertLink: function(toolbar) {
|
255
|
+
var self = this;
|
256
|
+
var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal');
|
257
|
+
var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url');
|
258
|
+
var insertButton = insertLinkModal.find('a.btn-primary');
|
259
|
+
var initialValue = urlInput.val();
|
260
|
+
|
261
|
+
var insertLink = function() {
|
262
|
+
var url = urlInput.val();
|
263
|
+
urlInput.val(initialValue);
|
264
|
+
self.editor.composer.commands.exec("createLink", {
|
265
|
+
href: url,
|
266
|
+
target: "_blank",
|
267
|
+
rel: "nofollow"
|
268
|
+
});
|
269
|
+
};
|
270
|
+
var pressedEnter = false;
|
271
|
+
|
272
|
+
urlInput.keypress(function(e) {
|
273
|
+
if(e.which == 13) {
|
274
|
+
insertLink();
|
275
|
+
insertLinkModal.modal('hide');
|
276
|
+
}
|
277
|
+
});
|
278
|
+
|
279
|
+
insertButton.click(insertLink);
|
280
|
+
|
281
|
+
insertLinkModal.on('shown', function() {
|
282
|
+
urlInput.focus();
|
283
|
+
});
|
284
|
+
|
285
|
+
insertLinkModal.on('hide', function() {
|
286
|
+
self.editor.currentView.element.focus();
|
287
|
+
});
|
288
|
+
|
289
|
+
toolbar.find('a[data-wysihtml5-command=createLink]').click(function() {
|
290
|
+
insertLinkModal.modal('show');
|
291
|
+
});
|
147
292
|
}
|
148
293
|
};
|
149
294
|
|
@@ -156,4 +301,4 @@
|
|
156
301
|
|
157
302
|
$.fn.wysihtml5.Constructor = Wysihtml5;
|
158
303
|
|
159
|
-
}(window.jQuery, window.wysihtml5);
|
304
|
+
}(window.jQuery, window.wysihtml5);
|
@@ -1,15 +1,15 @@
|
|
1
1
|
/**
|
2
|
-
* @license wysihtml5 v0.3.
|
2
|
+
* @license wysihtml5 v0.3.0_rc2
|
3
3
|
* https://github.com/xing/wysihtml5
|
4
4
|
*
|
5
5
|
* Author: Christopher Blum (https://github.com/tiff)
|
6
6
|
*
|
7
|
-
* Copyright (C)
|
8
|
-
* Licensed under
|
7
|
+
* Copyright (C) 2012 XING AG
|
8
|
+
* Licensed under the MIT license (MIT)
|
9
9
|
*
|
10
10
|
*/
|
11
11
|
var wysihtml5 = {
|
12
|
-
version: "0.3.
|
12
|
+
version: "0.3.0_rc2",
|
13
13
|
|
14
14
|
// namespaces
|
15
15
|
commands: {},
|
@@ -3383,8 +3383,6 @@ Base = Base.extend({
|
|
3383
3383
|
}
|
3384
3384
|
});/**
|
3385
3385
|
* Detect browser support for specific features
|
3386
|
-
*
|
3387
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
3388
3386
|
*/
|
3389
3387
|
wysihtml5.browser = (function() {
|
3390
3388
|
var userAgent = navigator.userAgent,
|
@@ -3393,6 +3391,7 @@ wysihtml5.browser = (function() {
|
|
3393
3391
|
isIE = userAgent.indexOf("MSIE") !== -1 && userAgent.indexOf("Opera") === -1,
|
3394
3392
|
isGecko = userAgent.indexOf("Gecko") !== -1 && userAgent.indexOf("KHTML") === -1,
|
3395
3393
|
isWebKit = userAgent.indexOf("AppleWebKit/") !== -1,
|
3394
|
+
isChrome = userAgent.indexOf("Chrome/") !== -1,
|
3396
3395
|
isOpera = userAgent.indexOf("Opera/") !== -1;
|
3397
3396
|
|
3398
3397
|
function iosVersion(userAgent) {
|
@@ -3716,6 +3715,24 @@ wysihtml5.browser = (function() {
|
|
3716
3715
|
*/
|
3717
3716
|
crashesWhenDefineProperty: function(property) {
|
3718
3717
|
return isIE && (property === "XMLHttpRequest" || property === "XDomainRequest");
|
3718
|
+
},
|
3719
|
+
|
3720
|
+
/**
|
3721
|
+
* IE is the only browser who fires the "focus" event not immediately when .focus() is called on an element
|
3722
|
+
*/
|
3723
|
+
doesAsyncFocus: function() {
|
3724
|
+
return isIE;
|
3725
|
+
},
|
3726
|
+
|
3727
|
+
/**
|
3728
|
+
* In IE it's impssible for the user and for the selection library to set the caret after an <img> when it's the lastChild in the document
|
3729
|
+
*/
|
3730
|
+
hasProblemsSettingCaretAfterImg: function() {
|
3731
|
+
return isIE;
|
3732
|
+
},
|
3733
|
+
|
3734
|
+
hasUndoInContextMenu: function() {
|
3735
|
+
return isGecko || isChrome || isOpera;
|
3719
3736
|
}
|
3720
3737
|
};
|
3721
3738
|
})();wysihtml5.lang.array = function(arr) {
|
@@ -3905,7 +3922,7 @@ wysihtml5.browser = (function() {
|
|
3905
3922
|
* Inspired by http://james.padolsey.com/javascript/find-and-replace-text-with-javascript/
|
3906
3923
|
*
|
3907
3924
|
* @param {Element} element Container element in which to search for urls
|
3908
|
-
*
|
3925
|
+
*
|
3909
3926
|
* @example
|
3910
3927
|
* <div id="text-container">Please click here: www.google.com</div>
|
3911
3928
|
* <script>wysihtml5.dom.autoLink(document.getElementById("text-container"));</script>
|
@@ -4089,7 +4106,6 @@ wysihtml5.dom.contains = (function() {
|
|
4089
4106
|
})();/**
|
4090
4107
|
* Converts an HTML fragment/element into a unordered/ordered list
|
4091
4108
|
*
|
4092
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4093
4109
|
* @param {Element} element The element which should be turned into a list
|
4094
4110
|
* @param {String} listType The list type in which to convert the tree (either "ul" or "ol")
|
4095
4111
|
* @return {Element} The created list
|
@@ -4170,8 +4186,6 @@ wysihtml5.dom.convertToList = (function() {
|
|
4170
4186
|
})();/**
|
4171
4187
|
* Copy a set of attributes from one element to another
|
4172
4188
|
*
|
4173
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4174
|
-
*
|
4175
4189
|
* @param {Array} attributesToCopy List of attributes which should be copied
|
4176
4190
|
* @return {Object} Returns an object which offers the "from" method which can be invoked with the element where to
|
4177
4191
|
* copy the attributes from., this again returns an object which provides a method named "to" which can be invoked
|
@@ -4210,8 +4224,6 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
4210
4224
|
*
|
4211
4225
|
* Interesting article on how to copy styles
|
4212
4226
|
*
|
4213
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4214
|
-
*
|
4215
4227
|
* @param {Array} stylesToCopy List of styles which should be copied
|
4216
4228
|
* @return {Object} Returns an object which offers the "from" method which can be invoked with the element where to
|
4217
4229
|
* copy the styles from., this again returns an object which provides a method named "to" which can be invoked
|
@@ -4306,7 +4318,6 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
4306
4318
|
* Fixing IE's inability to treat unknown elements (HTML5 section, article, ...) correctly
|
4307
4319
|
* when inserted via innerHTML
|
4308
4320
|
*
|
4309
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4310
4321
|
* @param {String} html The html which should be wrapped in a dom element
|
4311
4322
|
* @param {Obejct} [context] Document object of the context the html belongs to
|
4312
4323
|
*
|
@@ -4368,7 +4379,6 @@ wysihtml5.dom.getAsDom = (function() {
|
|
4368
4379
|
* Walks the dom tree from the given node up until it finds a match
|
4369
4380
|
* Designed for optimal performance.
|
4370
4381
|
*
|
4371
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4372
4382
|
* @param {Element} node The from which to check the parent nodes
|
4373
4383
|
* @param {Object} matchingSet Object to match against (possible properties: nodeName, className, classRegExp)
|
4374
4384
|
* @param {Number} [levels] How many parents should the function check up from the current node (defaults to 50)
|
@@ -4446,7 +4456,7 @@ wysihtml5.dom.getParentElement = (function() {
|
|
4446
4456
|
*
|
4447
4457
|
* @param {Element} element The element on which to retrieve the style
|
4448
4458
|
* @param {String} property The CSS property to retrieve ("float", "display", "text-align", ...)
|
4449
|
-
*
|
4459
|
+
*
|
4450
4460
|
* @example
|
4451
4461
|
* wysihtml5.dom.getStyle("display").from(document.body);
|
4452
4462
|
* // => "block"
|
@@ -4485,11 +4495,11 @@ wysihtml5.dom.getStyle = (function() {
|
|
4485
4495
|
// gives you the original "50%".
|
4486
4496
|
// Opera supports both, currentStyle and window.getComputedStyle, that's why checking for currentStyle should have higher prio
|
4487
4497
|
if (currentStyle) {
|
4488
|
-
|
4498
|
+
try {
|
4489
4499
|
return currentStyle[camelizedProperty];
|
4490
|
-
|
4491
|
-
|
4492
|
-
|
4500
|
+
} catch(e) {
|
4501
|
+
//ie will occasionally fail for unknown reasons. swallowing exception
|
4502
|
+
}
|
4493
4503
|
}
|
4494
4504
|
|
4495
4505
|
var win = doc.defaultView || doc.parentWindow,
|
@@ -4518,7 +4528,6 @@ wysihtml5.dom.getStyle = (function() {
|
|
4518
4528
|
* Optimized for being heavily executed
|
4519
4529
|
* Unleashes the power of live node lists
|
4520
4530
|
*
|
4521
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4522
4531
|
* @param {Object} doc The document object of the context where to check
|
4523
4532
|
* @param {String} tagName Upper cased tag name
|
4524
4533
|
* @example
|
@@ -4546,7 +4555,6 @@ wysihtml5.dom.hasElementWithTagName = (function() {
|
|
4546
4555
|
* Optimized for being heavily executed
|
4547
4556
|
* Unleashes the power of live node lists
|
4548
4557
|
*
|
4549
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4550
4558
|
* @param {Object} doc The document object of the context where to check
|
4551
4559
|
* @param {String} tagName Upper cased tag name
|
4552
4560
|
* @example
|
@@ -4614,8 +4622,6 @@ wysihtml5.dom.insert = function(elementToInsert) {
|
|
4614
4622
|
};/**
|
4615
4623
|
* Method to set dom events
|
4616
4624
|
*
|
4617
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4618
|
-
*
|
4619
4625
|
* @example
|
4620
4626
|
* wysihtml5.dom.observe(iframe.contentWindow.document.body, ["focus", "blur"], function() { ... });
|
4621
4627
|
*/
|
@@ -4668,8 +4674,6 @@ wysihtml5.dom.observe = function(element, eventNames, handler) {
|
|
4668
4674
|
* HTML Sanitizer
|
4669
4675
|
* Rewrites the HTML based on given rules
|
4670
4676
|
*
|
4671
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
4672
|
-
*
|
4673
4677
|
* @param {Element|String} elementOrHtml HTML String to be sanitized OR element whose content should be sanitized
|
4674
4678
|
* @param {Object} [rules] List of rules for rewriting the HTML, if there's no rule for an element it will
|
4675
4679
|
* be converted to a "span". Each rule is a key/value pair where key is the tag to convert, and value the
|
@@ -5115,7 +5119,6 @@ wysihtml5.dom.parse = (function() {
|
|
5115
5119
|
})();/**
|
5116
5120
|
* Checks for empty text node childs and removes them
|
5117
5121
|
*
|
5118
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5119
5122
|
* @param {Element} node The element in which to cleanup
|
5120
5123
|
* @example
|
5121
5124
|
* wysihtml5.dom.removeEmptyTextNodes(element);
|
@@ -5135,7 +5138,6 @@ wysihtml5.dom.removeEmptyTextNodes = function(node) {
|
|
5135
5138
|
/**
|
5136
5139
|
* Renames an element (eg. a <div> to a <p>) and keeps its childs
|
5137
5140
|
*
|
5138
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5139
5141
|
* @param {Element} element The list element which should be renamed
|
5140
5142
|
* @param {Element} newNodeName The desired tag name
|
5141
5143
|
*
|
@@ -5170,7 +5172,6 @@ wysihtml5.dom.renameElement = function(element, newNodeName) {
|
|
5170
5172
|
};/**
|
5171
5173
|
* Takes an element, removes it and replaces it with it's childs
|
5172
5174
|
*
|
5173
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5174
5175
|
* @param {Object} node The node which to replace with it's child nodes
|
5175
5176
|
* @example
|
5176
5177
|
* <div id="foo">
|
@@ -5201,7 +5202,6 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5201
5202
|
/**
|
5202
5203
|
* Unwraps an unordered/ordered list
|
5203
5204
|
*
|
5204
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5205
5205
|
* @param {Element} element The list element which should be unwrapped
|
5206
5206
|
*
|
5207
5207
|
* @example
|
@@ -5285,10 +5285,8 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5285
5285
|
* - therefore the "allow-scripts" flag is needed, which then would deactivate any security, as the js executed inside the iframe
|
5286
5286
|
* can do anything as if the sandbox attribute wasn't set
|
5287
5287
|
*
|
5288
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5289
|
-
*
|
5290
5288
|
* @param {Function} [readyCallback] Method that gets invoked when the sandbox is ready
|
5291
|
-
* @param {Object} [config] Optional parameters
|
5289
|
+
* @param {Object} [config] Optional parameters
|
5292
5290
|
*
|
5293
5291
|
* @example
|
5294
5292
|
* new wysihtml5.dom.Sandbox(function(sandbox) {
|
@@ -5299,9 +5297,6 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5299
5297
|
var /**
|
5300
5298
|
* Default configuration
|
5301
5299
|
*/
|
5302
|
-
defaultConfig = {
|
5303
|
-
uaCompatible: "IE=Edge" // X-UA-Compatible meta tag value (Document compatibility mode)
|
5304
|
-
},
|
5305
5300
|
doc = document,
|
5306
5301
|
/**
|
5307
5302
|
* Properties to unset/protect on the window object
|
@@ -5332,7 +5327,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5332
5327
|
|
5333
5328
|
constructor: function(readyCallback, config) {
|
5334
5329
|
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
|
5335
|
-
this.config = wysihtml5.lang.object({}).merge(
|
5330
|
+
this.config = wysihtml5.lang.object({}).merge(config).get();
|
5336
5331
|
this.iframe = this._createIframe();
|
5337
5332
|
},
|
5338
5333
|
|
@@ -5429,12 +5424,11 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5429
5424
|
|
5430
5425
|
var that = this,
|
5431
5426
|
iframeWindow = iframe.contentWindow,
|
5432
|
-
iframeDocument = iframe.
|
5427
|
+
iframeDocument = iframe.contentWindow.document,
|
5433
5428
|
charset = doc.characterSet || doc.charset || "utf-8",
|
5434
5429
|
sandboxHtml = this._getHtml({
|
5435
5430
|
charset: charset,
|
5436
|
-
stylesheets: this.config.stylesheets
|
5437
|
-
uaCompatible: this.config.uaCompatible
|
5431
|
+
stylesheets: this.config.stylesheets
|
5438
5432
|
});
|
5439
5433
|
|
5440
5434
|
// Create the basic dom tree including proper DOCTYPE and charset
|
@@ -5442,8 +5436,8 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5442
5436
|
iframeDocument.write(sandboxHtml);
|
5443
5437
|
iframeDocument.close();
|
5444
5438
|
|
5445
|
-
this.getWindow = function() { return
|
5446
|
-
this.getDocument = function() { return
|
5439
|
+
this.getWindow = function() { return iframe.contentWindow; };
|
5440
|
+
this.getDocument = function() { return iframe.contentWindow.document; };
|
5447
5441
|
|
5448
5442
|
// Catch js errors and pass them to the parent's onerror event
|
5449
5443
|
// addEventListener("error") doesn't work properly in some browsers
|
@@ -5496,7 +5490,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5496
5490
|
|
5497
5491
|
return wysihtml5.lang.string(
|
5498
5492
|
'<!DOCTYPE html><html><head>'
|
5499
|
-
+ '<meta
|
5493
|
+
+ '<meta charset="#{charset}">#{stylesheets}</head>'
|
5500
5494
|
+ '<body></body></html>'
|
5501
5495
|
).interpolate(templateVars);
|
5502
5496
|
},
|
@@ -5567,8 +5561,6 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
5567
5561
|
* - div[contentEditable] elements don't support it
|
5568
5562
|
* - older browsers (such as IE8 and Firefox 3.6) don't support it at all
|
5569
5563
|
*
|
5570
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5571
|
-
*
|
5572
5564
|
* @param {Object} parent Instance of main wysihtml5.Editor class
|
5573
5565
|
* @param {Element} view Instance of wysihtml5.views.* class
|
5574
5566
|
* @param {String} placeholderText
|
@@ -5679,7 +5671,6 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5679
5671
|
})();/**
|
5680
5672
|
* IE and Opera leave an empty paragraph in the contentEditable element after clearing it
|
5681
5673
|
*
|
5682
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5683
5674
|
* @param {Object} contentEditableElement The contentEditable element to observe for clearing events
|
5684
5675
|
* @exaple
|
5685
5676
|
* wysihtml5.quirks.ensureProperClearing(myContentEditableElement);
|
@@ -5699,8 +5690,8 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5699
5690
|
}, 0);
|
5700
5691
|
};
|
5701
5692
|
|
5702
|
-
return function(
|
5703
|
-
dom.observe(
|
5693
|
+
return function(composer) {
|
5694
|
+
dom.observe(composer.element, ["cut", "keydown"], clearIfNecessary);
|
5704
5695
|
};
|
5705
5696
|
})();
|
5706
5697
|
|
@@ -5709,7 +5700,6 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5709
5700
|
/**
|
5710
5701
|
* In Opera when the caret is in the first and only item of a list (<ul><li>|</li></ul>) and the list is the first child of the contentEditable element, it's impossible to delete the list by hitting backspace
|
5711
5702
|
*
|
5712
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5713
5703
|
* @param {Object} contentEditableElement The contentEditable element to observe for clearing events
|
5714
5704
|
* @exaple
|
5715
5705
|
* wysihtml5.quirks.ensureProperClearing(myContentEditableElement);
|
@@ -5745,14 +5735,14 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5745
5735
|
list.parentNode.removeChild(list);
|
5746
5736
|
};
|
5747
5737
|
|
5748
|
-
return function(
|
5749
|
-
dom.observe(
|
5738
|
+
return function(composer) {
|
5739
|
+
dom.observe(composer.element, "keydown", function(event) {
|
5750
5740
|
if (event.keyCode !== wysihtml5.BACKSPACE_KEY) {
|
5751
5741
|
return;
|
5752
5742
|
}
|
5753
5743
|
|
5754
|
-
var element =
|
5755
|
-
clearIfNecessary(element,
|
5744
|
+
var element = composer.selection.getSelectedNode();
|
5745
|
+
clearIfNecessary(element, composer.element);
|
5756
5746
|
});
|
5757
5747
|
};
|
5758
5748
|
})();
|
@@ -5792,8 +5782,6 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5792
5782
|
* - Opera & IE insert new <p> on return
|
5793
5783
|
* - Chrome & Safari insert new <div> on return
|
5794
5784
|
* - Firefox inserts <br> on return (yippie!)
|
5795
|
-
|
5796
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5797
5785
|
*
|
5798
5786
|
* @param {Element} element
|
5799
5787
|
*
|
@@ -5805,72 +5793,71 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5805
5793
|
USE_NATIVE_LINE_BREAK_WHEN_CARET_INSIDE_TAGS = ["LI", "P", "H1", "H2", "H3", "H4", "H5", "H6"],
|
5806
5794
|
LIST_TAGS = ["UL", "OL", "MENU"];
|
5807
5795
|
|
5808
|
-
function
|
5809
|
-
|
5810
|
-
|
5811
|
-
|
5812
|
-
|
5813
|
-
|
5814
|
-
|
5815
|
-
|
5816
|
-
|
5817
|
-
|
5818
|
-
|
5819
|
-
|
5820
|
-
function keyDown(event) {
|
5821
|
-
var keyCode = event.keyCode;
|
5822
|
-
if (event.shiftKey || (keyCode !== wysihtml5.ENTER_KEY && keyCode !== wysihtml5.BACKSPACE_KEY)) {
|
5823
|
-
return;
|
5796
|
+
wysihtml5.quirks.insertLineBreakOnReturn = function(composer) {
|
5797
|
+
function unwrap(selectedNode) {
|
5798
|
+
var parentElement = dom.getParentElement(selectedNode, { nodeName: ["P", "DIV"] }, 2);
|
5799
|
+
if (!parentElement) {
|
5800
|
+
return;
|
5801
|
+
}
|
5802
|
+
|
5803
|
+
var invisibleSpace = document.createTextNode(wysihtml5.INVISIBLE_SPACE);
|
5804
|
+
dom.insert(invisibleSpace).before(parentElement);
|
5805
|
+
dom.replaceWithChildNodes(parentElement);
|
5806
|
+
composer.selection.selectNode(invisibleSpace);
|
5824
5807
|
}
|
5825
|
-
|
5826
|
-
|
5827
|
-
|
5828
|
-
|
5829
|
-
|
5830
|
-
|
5831
|
-
|
5832
|
-
|
5833
|
-
|
5834
|
-
|
5835
|
-
|
5836
|
-
|
5837
|
-
|
5838
|
-
|
5839
|
-
|
5840
|
-
|
5841
|
-
|
5842
|
-
|
5843
|
-
|
5844
|
-
|
5845
|
-
|
5846
|
-
|
5847
|
-
|
5848
|
-
|
5849
|
-
|
5850
|
-
|
5851
|
-
|
5852
|
-
|
5853
|
-
|
5854
|
-
|
5855
|
-
|
5856
|
-
|
5808
|
+
|
5809
|
+
function keyDown(event) {
|
5810
|
+
var keyCode = event.keyCode;
|
5811
|
+
if (event.shiftKey || (keyCode !== wysihtml5.ENTER_KEY && keyCode !== wysihtml5.BACKSPACE_KEY)) {
|
5812
|
+
return;
|
5813
|
+
}
|
5814
|
+
|
5815
|
+
var element = event.target,
|
5816
|
+
selectedNode = composer.selection.getSelectedNode(),
|
5817
|
+
blockElement = dom.getParentElement(selectedNode, { nodeName: USE_NATIVE_LINE_BREAK_WHEN_CARET_INSIDE_TAGS }, 4);
|
5818
|
+
if (blockElement) {
|
5819
|
+
// Some browsers create <p> elements after leaving a list
|
5820
|
+
// check after keydown of backspace and return whether a <p> got inserted and unwrap it
|
5821
|
+
if (blockElement.nodeName === "LI" && (keyCode === wysihtml5.ENTER_KEY || keyCode === wysihtml5.BACKSPACE_KEY)) {
|
5822
|
+
setTimeout(function() {
|
5823
|
+
var selectedNode = composer.selection.getSelectedNode(),
|
5824
|
+
list,
|
5825
|
+
div;
|
5826
|
+
if (!selectedNode) {
|
5827
|
+
return;
|
5828
|
+
}
|
5829
|
+
|
5830
|
+
list = dom.getParentElement(selectedNode, {
|
5831
|
+
nodeName: LIST_TAGS
|
5832
|
+
}, 2);
|
5833
|
+
|
5834
|
+
if (list) {
|
5835
|
+
return;
|
5836
|
+
}
|
5837
|
+
|
5838
|
+
unwrap(selectedNode);
|
5839
|
+
}, 0);
|
5840
|
+
} else if (blockElement.nodeName.match(/H[1-6]/) && keyCode === wysihtml5.ENTER_KEY) {
|
5841
|
+
setTimeout(function() {
|
5842
|
+
unwrap(composer.selection.getSelectedNode());
|
5843
|
+
}, 0);
|
5844
|
+
}
|
5845
|
+
return;
|
5846
|
+
}
|
5847
|
+
|
5848
|
+
if (keyCode === wysihtml5.ENTER_KEY && !wysihtml5.browser.insertsLineBreaksOnReturn()) {
|
5849
|
+
composer.commands.exec("insertLineBreak");
|
5850
|
+
event.preventDefault();
|
5851
|
+
}
|
5857
5852
|
}
|
5858
5853
|
|
5859
|
-
if (keyCode === wysihtml5.ENTER_KEY && !wysihtml5.browser.insertsLineBreaksOnReturn()) {
|
5860
|
-
wysihtml5.commands.exec("insertLineBreak");
|
5861
|
-
event.preventDefault();
|
5862
|
-
}
|
5863
|
-
}
|
5864
|
-
|
5865
|
-
wysihtml5.quirks.insertLineBreakOnReturn = function(element) {
|
5866
5854
|
// keypress doesn't fire when you hit backspace
|
5867
|
-
dom.observe(element.ownerDocument, "keydown", keyDown);
|
5855
|
+
dom.observe(composer.element.ownerDocument, "keydown", keyDown);
|
5868
5856
|
};
|
5869
5857
|
})(wysihtml5);/**
|
5870
5858
|
* Force rerendering of a given element
|
5871
5859
|
* Needed to fix display misbehaviors of IE
|
5872
5860
|
*
|
5873
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
5874
5861
|
* @param {Element} element The element object which needs to be rerendered
|
5875
5862
|
* @example
|
5876
5863
|
* wysihtml5.quirks.redraw(document.body);
|
@@ -5889,7 +5876,13 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5889
5876
|
doc.execCommand("italic", false, null);
|
5890
5877
|
} catch(e) {}
|
5891
5878
|
};
|
5892
|
-
})(wysihtml5)
|
5879
|
+
})(wysihtml5);/**
|
5880
|
+
* Selection API
|
5881
|
+
*
|
5882
|
+
* @example
|
5883
|
+
* var selection = new wysihtml5.Selection(editor);
|
5884
|
+
*/
|
5885
|
+
(function(wysihtml5) {
|
5893
5886
|
var dom = wysihtml5.dom;
|
5894
5887
|
|
5895
5888
|
function _getCumulativeOffsetTop(element) {
|
@@ -5903,18 +5896,15 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5903
5896
|
return top;
|
5904
5897
|
}
|
5905
5898
|
|
5906
|
-
wysihtml5.
|
5907
|
-
|
5908
|
-
|
5909
|
-
* Setup selection for editor
|
5910
|
-
*
|
5911
|
-
* @param {Object} doc Document object of the context
|
5912
|
-
*/
|
5913
|
-
initialize: function(doc) {
|
5899
|
+
wysihtml5.Selection = Base.extend(
|
5900
|
+
/** @scope wysihtml5.Selection.prototype */ {
|
5901
|
+
constructor: function(editor) {
|
5914
5902
|
// Make sure that our external range library is initialized
|
5915
5903
|
window.rangy.init();
|
5916
5904
|
|
5917
|
-
this.
|
5905
|
+
this.editor = editor;
|
5906
|
+
this.composer = editor.composer;
|
5907
|
+
this.doc = this.composer.doc;
|
5918
5908
|
},
|
5919
5909
|
|
5920
5910
|
/**
|
@@ -5928,7 +5918,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5928
5918
|
},
|
5929
5919
|
|
5930
5920
|
/**
|
5931
|
-
* Restore a selection retrieved via wysihtml5.
|
5921
|
+
* Restore a selection retrieved via wysihtml5.Selection.prototype.getBookmark
|
5932
5922
|
*
|
5933
5923
|
* @param {Object} bookmark An object that represents the current selection
|
5934
5924
|
*/
|
@@ -5945,7 +5935,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5945
5935
|
*
|
5946
5936
|
* @param {Object} node The element or text node where to position the caret in front of
|
5947
5937
|
* @example
|
5948
|
-
*
|
5938
|
+
* selection.setBefore(myElement);
|
5949
5939
|
*/
|
5950
5940
|
setBefore: function(node) {
|
5951
5941
|
var range = rangy.createRange(this.doc);
|
@@ -5959,7 +5949,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5959
5949
|
*
|
5960
5950
|
* @param {Object} node The element or text node where to position the caret in front of
|
5961
5951
|
* @example
|
5962
|
-
*
|
5952
|
+
* selection.setBefore(myElement);
|
5963
5953
|
*/
|
5964
5954
|
setAfter: function(node) {
|
5965
5955
|
var range = rangy.createRange(this.doc);
|
@@ -5973,7 +5963,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
5973
5963
|
*
|
5974
5964
|
* @param {Element} node The node/element to select
|
5975
5965
|
* @example
|
5976
|
-
*
|
5966
|
+
* selection.selectNode(document.getElementById("my-image"));
|
5977
5967
|
*/
|
5978
5968
|
selectNode: function(node) {
|
5979
5969
|
var range = rangy.createRange(this.doc),
|
@@ -6011,7 +6001,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6011
6001
|
* @param {Boolean} [controlRange] (only IE) Whether it should return the selected ControlRange element when the selection type is a "ControlRange"
|
6012
6002
|
* @return {Object} The node that contains the caret
|
6013
6003
|
* @example
|
6014
|
-
* var nodeThatContainsCaret =
|
6004
|
+
* var nodeThatContainsCaret = selection.getSelectedNode();
|
6015
6005
|
*/
|
6016
6006
|
getSelectedNode: function(controlRange) {
|
6017
6007
|
var selection,
|
@@ -6128,7 +6118,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6128
6118
|
*
|
6129
6119
|
* @param {String} html HTML string to insert
|
6130
6120
|
* @example
|
6131
|
-
*
|
6121
|
+
* selection.insertHTML("<p>foobar</p>");
|
6132
6122
|
*/
|
6133
6123
|
insertHTML: function(html) {
|
6134
6124
|
var range = rangy.createRange(this.doc),
|
@@ -6145,7 +6135,7 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6145
6135
|
*
|
6146
6136
|
* @param {Object} node HTML string to insert
|
6147
6137
|
* @example
|
6148
|
-
*
|
6138
|
+
* selection.insertNode(document.createTextNode("foobar"));
|
6149
6139
|
*/
|
6150
6140
|
insertNode: function(node) {
|
6151
6141
|
var range = this.getRange();
|
@@ -6180,11 +6170,10 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6180
6170
|
* Scroll the current caret position into the view
|
6181
6171
|
* FIXME: This is a bit hacky, there might be a smarter way of doing this
|
6182
6172
|
*
|
6183
|
-
* @param {Object} element A scrollable element in which the caret is currently positioned
|
6184
6173
|
* @example
|
6185
|
-
*
|
6174
|
+
* selection.scrollIntoView();
|
6186
6175
|
*/
|
6187
|
-
scrollIntoView: function(
|
6176
|
+
scrollIntoView: function() {
|
6188
6177
|
var doc = this.doc,
|
6189
6178
|
hasScrollBars = doc.documentElement.scrollHeight > doc.documentElement.offsetHeight,
|
6190
6179
|
tempElement = doc._wysihtml5ScrollIntoViewElement = doc._wysihtml5ScrollIntoViewElement || (function() {
|
@@ -6199,8 +6188,8 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6199
6188
|
this.insertNode(tempElement);
|
6200
6189
|
offsetTop = _getCumulativeOffsetTop(tempElement);
|
6201
6190
|
tempElement.parentNode.removeChild(tempElement);
|
6202
|
-
if (offsetTop >
|
6203
|
-
|
6191
|
+
if (offsetTop > doc.body.scrollTop) {
|
6192
|
+
doc.body.scrollTop = offsetTop;
|
6204
6193
|
}
|
6205
6194
|
}
|
6206
6195
|
},
|
@@ -6302,18 +6291,16 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6302
6291
|
selection = rangy.getSelection(win);
|
6303
6292
|
return selection.setSingleRange(range);
|
6304
6293
|
}
|
6305
|
-
};
|
6294
|
+
});
|
6306
6295
|
|
6307
6296
|
})(wysihtml5);
|
6308
|
-
|
6309
6297
|
/**
|
6310
|
-
*
|
6311
|
-
*
|
6298
|
+
* Inspired by the rangy CSS Applier module written by Tim Down and licensed under the MIT license.
|
6299
|
+
* http://code.google.com/p/rangy/
|
6300
|
+
*
|
6301
|
+
* changed in order to be able ...
|
6312
6302
|
* - to use custom tags
|
6313
6303
|
* - to detect and replace similar css classes via reg exp
|
6314
|
-
*
|
6315
|
-
* Inspired by the rangy CSS Applier module written by Tim Down and licensed under the MIT license.
|
6316
|
-
* http://code.google.com/p/rangy/
|
6317
6304
|
*/
|
6318
6305
|
(function(wysihtml5, rangy) {
|
6319
6306
|
var defaultTagName = "span";
|
@@ -6742,22 +6729,23 @@ wysihtml5.quirks.cleanPastedHTML = (function() {
|
|
6742
6729
|
})(wysihtml5, rangy);/**
|
6743
6730
|
* Rich Text Query/Formatting Commands
|
6744
6731
|
*
|
6745
|
-
* @
|
6732
|
+
* @example
|
6733
|
+
* var commands = new wysihtml5.Commands(editor);
|
6746
6734
|
*/
|
6747
|
-
wysihtml5.
|
6748
|
-
|
6735
|
+
wysihtml5.Commands = Base.extend(
|
6736
|
+
/** @scope wysihtml5.Commands.prototype */ {
|
6737
|
+
constructor: function(editor) {
|
6749
6738
|
this.editor = editor;
|
6750
|
-
this.
|
6751
|
-
this.doc = this.
|
6739
|
+
this.composer = editor.composer;
|
6740
|
+
this.doc = this.composer.doc;
|
6752
6741
|
},
|
6753
6742
|
|
6754
6743
|
/**
|
6755
6744
|
* Check whether the browser supports the given command
|
6756
6745
|
*
|
6757
|
-
* @param {Object} element The element which has contentEditable=true
|
6758
6746
|
* @param {String} command The command string which to check (eg. "bold", "italic", "insertUnorderedList")
|
6759
6747
|
* @example
|
6760
|
-
*
|
6748
|
+
* commands.supports("createLink");
|
6761
6749
|
*/
|
6762
6750
|
support: function(command) {
|
6763
6751
|
return wysihtml5.browser.supportsCommand(this.doc, command);
|
@@ -6766,20 +6754,19 @@ wysihtml5.commands = {
|
|
6766
6754
|
/**
|
6767
6755
|
* Check whether the browser supports the given command
|
6768
6756
|
*
|
6769
|
-
* @param {Object} element The element which has contentEditable=true
|
6770
6757
|
* @param {String} command The command string which to execute (eg. "bold", "italic", "insertUnorderedList")
|
6771
6758
|
* @param {String} [value] The command value parameter, needed for some commands ("createLink", "insertImage", ...), optional for commands that don't require one ("bold", "underline", ...)
|
6772
6759
|
* @example
|
6773
|
-
*
|
6760
|
+
* commands.exec("insertImage", "http://a1.twimg.com/profile_images/113868655/schrei_twitter_reasonably_small.jpg");
|
6774
6761
|
*/
|
6775
6762
|
exec: function(command, value) {
|
6776
|
-
var obj =
|
6763
|
+
var obj = wysihtml5.commands[command],
|
6777
6764
|
method = obj && obj.exec;
|
6778
6765
|
|
6779
6766
|
this.editor.fire("beforecommand:composer");
|
6780
6767
|
|
6781
6768
|
if (method) {
|
6782
|
-
return method.call(obj, this.
|
6769
|
+
return method.call(obj, this.composer, command, value);
|
6783
6770
|
} else {
|
6784
6771
|
try {
|
6785
6772
|
// try/catch for buggy firefox
|
@@ -6794,18 +6781,17 @@ wysihtml5.commands = {
|
|
6794
6781
|
* Check whether the current command is active
|
6795
6782
|
* If the caret is within a bold text, then calling this with command "bold" should return true
|
6796
6783
|
*
|
6797
|
-
* @param {Object} element The element which has contentEditable=true
|
6798
6784
|
* @param {String} command The command string which to check (eg. "bold", "italic", "insertUnorderedList")
|
6799
6785
|
* @param {String} [commandValue] The command value parameter (eg. for "insertImage" the image src)
|
6800
6786
|
* @return {Boolean} Whether the command is active
|
6801
6787
|
* @example
|
6802
|
-
* var isCurrentSelectionBold =
|
6788
|
+
* var isCurrentSelectionBold = commands.state("bold");
|
6803
6789
|
*/
|
6804
6790
|
state: function(command, commandValue) {
|
6805
|
-
var obj =
|
6791
|
+
var obj = wysihtml5.commands[command],
|
6806
6792
|
method = obj && obj.state;
|
6807
6793
|
if (method) {
|
6808
|
-
return method.call(obj, this.
|
6794
|
+
return method.call(obj, this.composer, command, commandValue);
|
6809
6795
|
} else {
|
6810
6796
|
try {
|
6811
6797
|
// try/catch for buggy firefox
|
@@ -6819,17 +6805,16 @@ wysihtml5.commands = {
|
|
6819
6805
|
/**
|
6820
6806
|
* Get the current command's value
|
6821
6807
|
*
|
6822
|
-
* @param {Object} element The element which has contentEditable=true
|
6823
6808
|
* @param {String} command The command string which to check (eg. "formatBlock")
|
6824
6809
|
* @return {String} The command value
|
6825
6810
|
* @example
|
6826
|
-
* var currentBlockElement =
|
6811
|
+
* var currentBlockElement = commands.value("formatBlock");
|
6827
6812
|
*/
|
6828
6813
|
value: function(command) {
|
6829
|
-
var obj =
|
6814
|
+
var obj = wysihtml5.commands[command],
|
6830
6815
|
method = obj && obj.value;
|
6831
6816
|
if (method) {
|
6832
|
-
method(this.
|
6817
|
+
return method.call(obj, this.composer, command);
|
6833
6818
|
} else {
|
6834
6819
|
try {
|
6835
6820
|
// try/catch for buggy firefox
|
@@ -6839,21 +6824,21 @@ wysihtml5.commands = {
|
|
6839
6824
|
}
|
6840
6825
|
}
|
6841
6826
|
}
|
6842
|
-
};(function(wysihtml5) {
|
6827
|
+
});(function(wysihtml5) {
|
6843
6828
|
var undef;
|
6844
6829
|
|
6845
6830
|
wysihtml5.commands.bold = {
|
6846
|
-
exec: function(
|
6847
|
-
return wysihtml5.commands.formatInline.exec(
|
6831
|
+
exec: function(composer, command) {
|
6832
|
+
return wysihtml5.commands.formatInline.exec(composer, command, "b");
|
6848
6833
|
},
|
6849
6834
|
|
6850
|
-
state: function(
|
6835
|
+
state: function(composer, command, color) {
|
6851
6836
|
// element.ownerDocument.queryCommandState("bold") results:
|
6852
6837
|
// firefox: only <b>
|
6853
6838
|
// chrome: <b>, <strong>, <h1>, <h2>, ...
|
6854
6839
|
// ie: <b>, <strong>
|
6855
6840
|
// opera: <b>, <strong>
|
6856
|
-
return wysihtml5.commands.formatInline.state(
|
6841
|
+
return wysihtml5.commands.formatInline.state(composer, command, "b");
|
6857
6842
|
},
|
6858
6843
|
|
6859
6844
|
value: function() {
|
@@ -6867,9 +6852,9 @@ wysihtml5.commands = {
|
|
6867
6852
|
NODE_NAME = "A",
|
6868
6853
|
dom = wysihtml5.dom;
|
6869
6854
|
|
6870
|
-
function _removeFormat(
|
6871
|
-
var length
|
6872
|
-
i
|
6855
|
+
function _removeFormat(composer, anchors) {
|
6856
|
+
var length = anchors.length,
|
6857
|
+
i = 0,
|
6873
6858
|
anchor,
|
6874
6859
|
codeElement,
|
6875
6860
|
textContent;
|
@@ -6889,8 +6874,8 @@ wysihtml5.commands = {
|
|
6889
6874
|
}
|
6890
6875
|
}
|
6891
6876
|
|
6892
|
-
function _format(
|
6893
|
-
var doc =
|
6877
|
+
function _format(composer, attributes) {
|
6878
|
+
var doc = composer.doc,
|
6894
6879
|
tempClass = "_wysihtml5-temp-" + (+new Date()),
|
6895
6880
|
tempClassRegExp = /non-matching-class/g,
|
6896
6881
|
i = 0,
|
@@ -6903,7 +6888,7 @@ wysihtml5.commands = {
|
|
6903
6888
|
textContent,
|
6904
6889
|
whiteSpace,
|
6905
6890
|
j;
|
6906
|
-
wysihtml5.commands.formatInline.exec(
|
6891
|
+
wysihtml5.commands.formatInline.exec(composer, undef, NODE_NAME, tempClass, tempClassRegExp);
|
6907
6892
|
anchors = doc.querySelectorAll(NODE_NAME + "." + tempClass);
|
6908
6893
|
length = anchors.length;
|
6909
6894
|
for (; i<length; i++) {
|
@@ -6922,12 +6907,12 @@ wysihtml5.commands = {
|
|
6922
6907
|
if (!hasElementChild && isEmpty) {
|
6923
6908
|
dom.setTextContent(anchor, anchor.href);
|
6924
6909
|
whiteSpace = doc.createTextNode(" ");
|
6925
|
-
|
6926
|
-
|
6910
|
+
composer.selection.setAfter(anchor);
|
6911
|
+
composer.selection.insertNode(whiteSpace);
|
6927
6912
|
elementToSetCaretAfter = whiteSpace;
|
6928
6913
|
}
|
6929
6914
|
}
|
6930
|
-
|
6915
|
+
composer.selection.setAfter(elementToSetCaretAfter);
|
6931
6916
|
}
|
6932
6917
|
|
6933
6918
|
wysihtml5.commands.createLink = {
|
@@ -6940,28 +6925,26 @@ wysihtml5.commands = {
|
|
6940
6925
|
*
|
6941
6926
|
* @example
|
6942
6927
|
* // either ...
|
6943
|
-
* wysihtml5.commands.createLink.exec(
|
6928
|
+
* wysihtml5.commands.createLink.exec(composer, "createLink", "http://www.google.de");
|
6944
6929
|
* // ... or ...
|
6945
|
-
* wysihtml5.commands.createLink.exec(
|
6930
|
+
* wysihtml5.commands.createLink.exec(composer, "createLink", { href: "http://www.google.de", target: "_blank" });
|
6946
6931
|
*/
|
6947
|
-
exec: function(
|
6948
|
-
var
|
6949
|
-
anchors = this.state(element, command);
|
6950
|
-
|
6932
|
+
exec: function(composer, command, value) {
|
6933
|
+
var anchors = this.state(composer, command);
|
6951
6934
|
if (anchors) {
|
6952
6935
|
// Selection contains links
|
6953
|
-
|
6954
|
-
_removeFormat(
|
6936
|
+
composer.selection.executeAndRestore(function() {
|
6937
|
+
_removeFormat(composer, anchors);
|
6955
6938
|
});
|
6956
6939
|
} else {
|
6957
6940
|
// Create links
|
6958
6941
|
value = typeof(value) === "object" ? value : { href: value };
|
6959
|
-
_format(
|
6942
|
+
_format(composer, value);
|
6960
6943
|
}
|
6961
6944
|
},
|
6962
6945
|
|
6963
|
-
state: function(
|
6964
|
-
return wysihtml5.commands.formatInline.state(
|
6946
|
+
state: function(composer, command) {
|
6947
|
+
return wysihtml5.commands.formatInline.state(composer, command, "A");
|
6965
6948
|
},
|
6966
6949
|
|
6967
6950
|
value: function() {
|
@@ -6978,12 +6961,12 @@ wysihtml5.commands = {
|
|
6978
6961
|
REG_EXP = /wysiwyg-font-size-[a-z]+/g;
|
6979
6962
|
|
6980
6963
|
wysihtml5.commands.fontSize = {
|
6981
|
-
exec: function(
|
6982
|
-
return wysihtml5.commands.formatInline.exec(
|
6964
|
+
exec: function(composer, command, size) {
|
6965
|
+
return wysihtml5.commands.formatInline.exec(composer, command, "span", "wysiwyg-font-size-" + size, REG_EXP);
|
6983
6966
|
},
|
6984
6967
|
|
6985
|
-
state: function(
|
6986
|
-
return wysihtml5.commands.formatInline.state(
|
6968
|
+
state: function(composer, command, size) {
|
6969
|
+
return wysihtml5.commands.formatInline.state(composer, command, "span", "wysiwyg-font-size-" + size, REG_EXP);
|
6987
6970
|
},
|
6988
6971
|
|
6989
6972
|
value: function() {
|
@@ -7001,12 +6984,12 @@ wysihtml5.commands = {
|
|
7001
6984
|
REG_EXP = /wysiwyg-color-[a-z]+/g;
|
7002
6985
|
|
7003
6986
|
wysihtml5.commands.foreColor = {
|
7004
|
-
exec: function(
|
7005
|
-
return wysihtml5.commands.formatInline.exec(
|
6987
|
+
exec: function(composer, command, color) {
|
6988
|
+
return wysihtml5.commands.formatInline.exec(composer, command, "span", "wysiwyg-color-" + color, REG_EXP);
|
7006
6989
|
},
|
7007
6990
|
|
7008
|
-
state: function(
|
7009
|
-
return wysihtml5.commands.formatInline.state(
|
6991
|
+
state: function(composer, command, color) {
|
6992
|
+
return wysihtml5.commands.formatInline.state(composer, command, "span", "wysiwyg-color-" + color, REG_EXP);
|
7010
6993
|
},
|
7011
6994
|
|
7012
6995
|
value: function() {
|
@@ -7016,7 +6999,6 @@ wysihtml5.commands = {
|
|
7016
6999
|
})(wysihtml5);(function(wysihtml5) {
|
7017
7000
|
var undef,
|
7018
7001
|
dom = wysihtml5.dom,
|
7019
|
-
selection = wysihtml5.selection,
|
7020
7002
|
DEFAULT_NODE_NAME = "DIV",
|
7021
7003
|
// Following elements are grouped
|
7022
7004
|
// when the caret is within a H1 and the H4 is invoked, the H1 should turn into H4
|
@@ -7140,7 +7122,7 @@ wysihtml5.commands = {
|
|
7140
7122
|
if (target.nodeType !== wysihtml5.ELEMENT_NODE) {
|
7141
7123
|
return;
|
7142
7124
|
}
|
7143
|
-
displayStyle
|
7125
|
+
displayStyle = dom.getStyle("display").from(target);
|
7144
7126
|
if (displayStyle.substr(0, 6) !== "inline") {
|
7145
7127
|
// Make sure that only block elements receive the given class
|
7146
7128
|
target.className += " " + className;
|
@@ -7153,12 +7135,12 @@ wysihtml5.commands = {
|
|
7153
7135
|
}
|
7154
7136
|
}
|
7155
7137
|
|
7156
|
-
function _selectLineAndWrap(element) {
|
7157
|
-
selection.selectLine();
|
7158
|
-
selection.surround(element);
|
7138
|
+
function _selectLineAndWrap(composer, element) {
|
7139
|
+
composer.selection.selectLine();
|
7140
|
+
composer.selection.surround(element);
|
7159
7141
|
_removeLineBreakBeforeAndAfter(element);
|
7160
7142
|
_removeLastChildIfLineBreak(element);
|
7161
|
-
selection.selectNode(element);
|
7143
|
+
composer.selection.selectNode(element);
|
7162
7144
|
}
|
7163
7145
|
|
7164
7146
|
function _hasClasses(element) {
|
@@ -7166,15 +7148,15 @@ wysihtml5.commands = {
|
|
7166
7148
|
}
|
7167
7149
|
|
7168
7150
|
wysihtml5.commands.formatBlock = {
|
7169
|
-
exec: function(
|
7170
|
-
var doc =
|
7171
|
-
blockElement = this.state(
|
7151
|
+
exec: function(composer, command, nodeName, className, classRegExp) {
|
7152
|
+
var doc = composer.doc,
|
7153
|
+
blockElement = this.state(composer, command, nodeName, className, classRegExp),
|
7172
7154
|
selectedNode;
|
7173
7155
|
|
7174
7156
|
nodeName = typeof(nodeName) === "string" ? nodeName.toUpperCase() : nodeName;
|
7175
7157
|
|
7176
7158
|
if (blockElement) {
|
7177
|
-
selection.executeAndRestoreSimple(function() {
|
7159
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7178
7160
|
if (classRegExp) {
|
7179
7161
|
_removeClass(blockElement, classRegExp);
|
7180
7162
|
}
|
@@ -7194,13 +7176,13 @@ wysihtml5.commands = {
|
|
7194
7176
|
|
7195
7177
|
// Find similiar block element and rename it (<h2 class="foo"></h2> => <h1 class="foo"></h1>)
|
7196
7178
|
if (nodeName === null || wysihtml5.lang.array(BLOCK_ELEMENTS_GROUP).contains(nodeName)) {
|
7197
|
-
selectedNode = selection.getSelectedNode();
|
7179
|
+
selectedNode = composer.selection.getSelectedNode();
|
7198
7180
|
blockElement = dom.getParentElement(selectedNode, {
|
7199
|
-
nodeName:
|
7181
|
+
nodeName: BLOCK_ELEMENTS_GROUP
|
7200
7182
|
});
|
7201
7183
|
|
7202
7184
|
if (blockElement) {
|
7203
|
-
selection.executeAndRestoreSimple(function() {
|
7185
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7204
7186
|
// Rename current block element to new block element and add class
|
7205
7187
|
if (nodeName) {
|
7206
7188
|
blockElement = dom.renameElement(blockElement, nodeName);
|
@@ -7213,7 +7195,7 @@ wysihtml5.commands = {
|
|
7213
7195
|
}
|
7214
7196
|
}
|
7215
7197
|
|
7216
|
-
if (
|
7198
|
+
if (composer.commands.support(command)) {
|
7217
7199
|
_execCommand(doc, command, nodeName || DEFAULT_NODE_NAME, className);
|
7218
7200
|
return;
|
7219
7201
|
}
|
@@ -7222,12 +7204,12 @@ wysihtml5.commands = {
|
|
7222
7204
|
if (className) {
|
7223
7205
|
blockElement.className = className;
|
7224
7206
|
}
|
7225
|
-
_selectLineAndWrap(blockElement);
|
7207
|
+
_selectLineAndWrap(composer, blockElement);
|
7226
7208
|
},
|
7227
7209
|
|
7228
|
-
state: function(
|
7210
|
+
state: function(composer, command, nodeName, className, classRegExp) {
|
7229
7211
|
nodeName = typeof(nodeName) === "string" ? nodeName.toUpperCase() : nodeName;
|
7230
|
-
var selectedNode = selection.getSelectedNode();
|
7212
|
+
var selectedNode = composer.selection.getSelectedNode();
|
7231
7213
|
return dom.getParentElement(selectedNode, {
|
7232
7214
|
nodeName: nodeName,
|
7233
7215
|
className: className,
|
@@ -7297,17 +7279,17 @@ wysihtml5.commands = {
|
|
7297
7279
|
}
|
7298
7280
|
|
7299
7281
|
wysihtml5.commands.formatInline = {
|
7300
|
-
exec: function(
|
7301
|
-
var range =
|
7282
|
+
exec: function(composer, command, tagName, className, classRegExp) {
|
7283
|
+
var range = composer.selection.getRange();
|
7302
7284
|
if (!range) {
|
7303
7285
|
return false;
|
7304
7286
|
}
|
7305
7287
|
_getApplier(tagName, className, classRegExp).toggleRange(range);
|
7306
|
-
|
7288
|
+
composer.selection.setSelection(range);
|
7307
7289
|
},
|
7308
7290
|
|
7309
|
-
state: function(
|
7310
|
-
var doc =
|
7291
|
+
state: function(composer, command, tagName, className, classRegExp) {
|
7292
|
+
var doc = composer.doc,
|
7311
7293
|
aliasTagName = ALIAS_MAPPING[tagName] || tagName,
|
7312
7294
|
range;
|
7313
7295
|
|
@@ -7322,7 +7304,7 @@ wysihtml5.commands = {
|
|
7322
7304
|
return false;
|
7323
7305
|
}
|
7324
7306
|
|
7325
|
-
range =
|
7307
|
+
range = composer.selection.getRange();
|
7326
7308
|
if (!range) {
|
7327
7309
|
return false;
|
7328
7310
|
}
|
@@ -7338,11 +7320,11 @@ wysihtml5.commands = {
|
|
7338
7320
|
var undef;
|
7339
7321
|
|
7340
7322
|
wysihtml5.commands.insertHTML = {
|
7341
|
-
exec: function(
|
7342
|
-
if (
|
7343
|
-
|
7323
|
+
exec: function(composer, command, html) {
|
7324
|
+
if (composer.commands.support(command)) {
|
7325
|
+
composer.doc.execCommand(command, false, html);
|
7344
7326
|
} else {
|
7345
|
-
|
7327
|
+
composer.selection.insertHTML(html);
|
7346
7328
|
}
|
7347
7329
|
},
|
7348
7330
|
|
@@ -7364,33 +7346,34 @@ wysihtml5.commands = {
|
|
7364
7346
|
*
|
7365
7347
|
* @example
|
7366
7348
|
* // either ...
|
7367
|
-
* wysihtml5.commands.insertImage.exec(
|
7349
|
+
* wysihtml5.commands.insertImage.exec(composer, "insertImage", "http://www.google.de/logo.jpg");
|
7368
7350
|
* // ... or ...
|
7369
|
-
* wysihtml5.commands.insertImage.exec(
|
7351
|
+
* wysihtml5.commands.insertImage.exec(composer, "insertImage", { src: "http://www.google.de/logo.jpg", title: "foo" });
|
7370
7352
|
*/
|
7371
|
-
exec: function(
|
7353
|
+
exec: function(composer, command, value) {
|
7372
7354
|
value = typeof(value) === "object" ? value : { src: value };
|
7373
7355
|
|
7374
|
-
var doc
|
7375
|
-
image
|
7356
|
+
var doc = composer.doc,
|
7357
|
+
image = this.state(composer),
|
7358
|
+
textNode,
|
7376
7359
|
i,
|
7377
7360
|
parent;
|
7378
7361
|
|
7379
7362
|
if (image) {
|
7380
7363
|
// Image already selected, set the caret before it and delete it
|
7381
|
-
|
7364
|
+
composer.selection.setBefore(image);
|
7382
7365
|
parent = image.parentNode;
|
7383
7366
|
parent.removeChild(image);
|
7384
7367
|
|
7385
7368
|
// and it's parent <a> too if it hasn't got any other relevant child nodes
|
7386
7369
|
wysihtml5.dom.removeEmptyTextNodes(parent);
|
7387
7370
|
if (parent.nodeName === "A" && !parent.firstChild) {
|
7388
|
-
|
7371
|
+
composer.selection.setAfter(parent);
|
7389
7372
|
parent.parentNode.removeChild(parent);
|
7390
7373
|
}
|
7391
7374
|
|
7392
7375
|
// firefox and ie sometimes don't remove the image handles, even though the image got removed
|
7393
|
-
wysihtml5.quirks.redraw(element);
|
7376
|
+
wysihtml5.quirks.redraw(composer.element);
|
7394
7377
|
return;
|
7395
7378
|
}
|
7396
7379
|
|
@@ -7400,12 +7383,18 @@ wysihtml5.commands = {
|
|
7400
7383
|
image[i] = value[i];
|
7401
7384
|
}
|
7402
7385
|
|
7403
|
-
|
7404
|
-
wysihtml5.
|
7386
|
+
composer.selection.insertNode(image);
|
7387
|
+
if (wysihtml5.browser.hasProblemsSettingCaretAfterImg()) {
|
7388
|
+
textNode = doc.createTextNode(wysihtml5.INVISIBLE_SPACE);
|
7389
|
+
composer.selection.insertNode(textNode);
|
7390
|
+
composer.selection.setAfter(textNode);
|
7391
|
+
} else {
|
7392
|
+
composer.selection.setAfter(image);
|
7393
|
+
}
|
7405
7394
|
},
|
7406
7395
|
|
7407
|
-
state: function(
|
7408
|
-
var doc =
|
7396
|
+
state: function(composer) {
|
7397
|
+
var doc = composer.doc,
|
7409
7398
|
selectedNode,
|
7410
7399
|
text,
|
7411
7400
|
imagesInSelection;
|
@@ -7414,7 +7403,7 @@ wysihtml5.commands = {
|
|
7414
7403
|
return false;
|
7415
7404
|
}
|
7416
7405
|
|
7417
|
-
selectedNode =
|
7406
|
+
selectedNode = composer.selection.getSelectedNode();
|
7418
7407
|
if (!selectedNode) {
|
7419
7408
|
return false;
|
7420
7409
|
}
|
@@ -7428,13 +7417,13 @@ wysihtml5.commands = {
|
|
7428
7417
|
return false;
|
7429
7418
|
}
|
7430
7419
|
|
7431
|
-
text =
|
7420
|
+
text = composer.selection.getText();
|
7432
7421
|
text = wysihtml5.lang.string(text).trim();
|
7433
7422
|
if (text) {
|
7434
7423
|
return false;
|
7435
7424
|
}
|
7436
7425
|
|
7437
|
-
imagesInSelection =
|
7426
|
+
imagesInSelection = composer.selection.getNodes(wysihtml5.ELEMENT_NODE, function(node) {
|
7438
7427
|
return node.nodeName === "IMG";
|
7439
7428
|
});
|
7440
7429
|
|
@@ -7445,8 +7434,8 @@ wysihtml5.commands = {
|
|
7445
7434
|
return imagesInSelection[0];
|
7446
7435
|
},
|
7447
7436
|
|
7448
|
-
value: function(
|
7449
|
-
var image = this.state(
|
7437
|
+
value: function(composer) {
|
7438
|
+
var image = this.state(composer);
|
7450
7439
|
return image && image.src;
|
7451
7440
|
}
|
7452
7441
|
};
|
@@ -7455,14 +7444,14 @@ wysihtml5.commands = {
|
|
7455
7444
|
LINE_BREAK = "<br>" + (wysihtml5.browser.needsSpaceAfterLineBreak() ? " " : "");
|
7456
7445
|
|
7457
7446
|
wysihtml5.commands.insertLineBreak = {
|
7458
|
-
exec: function(
|
7459
|
-
if (
|
7460
|
-
|
7447
|
+
exec: function(composer, command) {
|
7448
|
+
if (composer.commands.support(command)) {
|
7449
|
+
composer.doc.execCommand(command, false, null);
|
7461
7450
|
if (!wysihtml5.browser.autoScrollsToCaret()) {
|
7462
|
-
|
7451
|
+
composer.selection.scrollIntoView();
|
7463
7452
|
}
|
7464
7453
|
} else {
|
7465
|
-
|
7454
|
+
composer.commands.exec("insertHTML", LINE_BREAK);
|
7466
7455
|
}
|
7467
7456
|
},
|
7468
7457
|
|
@@ -7478,33 +7467,33 @@ wysihtml5.commands = {
|
|
7478
7467
|
var undef;
|
7479
7468
|
|
7480
7469
|
wysihtml5.commands.insertOrderedList = {
|
7481
|
-
exec: function(
|
7482
|
-
var doc =
|
7470
|
+
exec: function(composer, command) {
|
7471
|
+
var doc = composer.doc,
|
7483
7472
|
selectedNode,
|
7484
7473
|
isEmpty,
|
7485
7474
|
tempElement,
|
7486
7475
|
list;
|
7487
7476
|
|
7488
|
-
if (
|
7477
|
+
if (composer.commands.support(command)) {
|
7489
7478
|
doc.execCommand(command, false, null);
|
7490
7479
|
} else {
|
7491
|
-
selectedNode =
|
7480
|
+
selectedNode = composer.selection.getSelectedNode();
|
7492
7481
|
list = wysihtml5.dom.getParentElement(selectedNode, { nodeName: ["UL", "OL"] }, 4);
|
7493
7482
|
if (!list) {
|
7494
7483
|
tempElement = doc.createElement("span");
|
7495
|
-
|
7484
|
+
composer.selection.surround(tempElement);
|
7496
7485
|
isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE;
|
7497
|
-
|
7486
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7498
7487
|
list = wysihtml5.dom.convertToList(tempElement, "ol");
|
7499
7488
|
});
|
7500
7489
|
|
7501
7490
|
if (isEmpty) {
|
7502
|
-
|
7491
|
+
composer.selection.selectNode(list.querySelector("li"));
|
7503
7492
|
}
|
7504
7493
|
return;
|
7505
7494
|
}
|
7506
7495
|
|
7507
|
-
|
7496
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7508
7497
|
if (list.nodeName === "OL") {
|
7509
7498
|
// Unwrap list
|
7510
7499
|
// <ol><li>foo</li><li>bar</li></ol>
|
@@ -7522,9 +7511,9 @@ wysihtml5.commands = {
|
|
7522
7511
|
}
|
7523
7512
|
},
|
7524
7513
|
|
7525
|
-
state: function(
|
7514
|
+
state: function(composer, command) {
|
7526
7515
|
try {
|
7527
|
-
return
|
7516
|
+
return composer.doc.queryCommandState(command);
|
7528
7517
|
} catch(e) {
|
7529
7518
|
return false;
|
7530
7519
|
}
|
@@ -7538,34 +7527,34 @@ wysihtml5.commands = {
|
|
7538
7527
|
var undef;
|
7539
7528
|
|
7540
7529
|
wysihtml5.commands.insertUnorderedList = {
|
7541
|
-
exec: function(
|
7542
|
-
var doc =
|
7530
|
+
exec: function(composer, command) {
|
7531
|
+
var doc = composer.doc,
|
7543
7532
|
selectedNode,
|
7544
7533
|
isEmpty,
|
7545
7534
|
tempElement,
|
7546
7535
|
list;
|
7547
7536
|
|
7548
|
-
if (
|
7537
|
+
if (composer.commands.support(command)) {
|
7549
7538
|
doc.execCommand(command, false, null);
|
7550
7539
|
} else {
|
7551
|
-
selectedNode =
|
7540
|
+
selectedNode = composer.selection.getSelectedNode();
|
7552
7541
|
list = wysihtml5.dom.getParentElement(selectedNode, { nodeName: ["UL", "OL"] });
|
7553
7542
|
|
7554
7543
|
if (!list) {
|
7555
7544
|
tempElement = doc.createElement("span");
|
7556
|
-
|
7545
|
+
composer.selection.surround(tempElement);
|
7557
7546
|
isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE;
|
7558
|
-
|
7547
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7559
7548
|
list = wysihtml5.dom.convertToList(tempElement, "ul");
|
7560
7549
|
});
|
7561
7550
|
|
7562
7551
|
if (isEmpty) {
|
7563
|
-
|
7552
|
+
composer.selection.selectNode(list.querySelector("li"));
|
7564
7553
|
}
|
7565
7554
|
return;
|
7566
7555
|
}
|
7567
7556
|
|
7568
|
-
|
7557
|
+
composer.selection.executeAndRestoreSimple(function() {
|
7569
7558
|
if (list.nodeName === "UL") {
|
7570
7559
|
// Unwrap list
|
7571
7560
|
// <ul><li>foo</li><li>bar</li></ul>
|
@@ -7583,9 +7572,9 @@ wysihtml5.commands = {
|
|
7583
7572
|
}
|
7584
7573
|
},
|
7585
7574
|
|
7586
|
-
state: function(
|
7575
|
+
state: function(composer, command) {
|
7587
7576
|
try {
|
7588
|
-
return
|
7577
|
+
return composer.doc.queryCommandState(command);
|
7589
7578
|
} catch(e) {
|
7590
7579
|
return false;
|
7591
7580
|
}
|
@@ -7599,17 +7588,17 @@ wysihtml5.commands = {
|
|
7599
7588
|
var undef;
|
7600
7589
|
|
7601
7590
|
wysihtml5.commands.italic = {
|
7602
|
-
exec: function(
|
7603
|
-
return wysihtml5.commands.formatInline.exec(
|
7591
|
+
exec: function(composer, command) {
|
7592
|
+
return wysihtml5.commands.formatInline.exec(composer, command, "i");
|
7604
7593
|
},
|
7605
7594
|
|
7606
|
-
state: function(
|
7595
|
+
state: function(composer, command, color) {
|
7607
7596
|
// element.ownerDocument.queryCommandState("italic") results:
|
7608
7597
|
// firefox: only <i>
|
7609
7598
|
// chrome: <i>, <em>, <blockquote>, ...
|
7610
7599
|
// ie: <i>, <em>
|
7611
7600
|
// opera: only <i>
|
7612
|
-
return wysihtml5.commands.formatInline.state(
|
7601
|
+
return wysihtml5.commands.formatInline.state(composer, command, "i");
|
7613
7602
|
},
|
7614
7603
|
|
7615
7604
|
value: function() {
|
@@ -7622,12 +7611,12 @@ wysihtml5.commands = {
|
|
7622
7611
|
REG_EXP = /wysiwyg-text-align-[a-z]+/g;
|
7623
7612
|
|
7624
7613
|
wysihtml5.commands.justifyCenter = {
|
7625
|
-
exec: function(
|
7626
|
-
return wysihtml5.commands.formatBlock.exec(
|
7614
|
+
exec: function(composer, command) {
|
7615
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7627
7616
|
},
|
7628
7617
|
|
7629
|
-
state: function(
|
7630
|
-
return wysihtml5.commands.formatBlock.state(
|
7618
|
+
state: function(composer, command) {
|
7619
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7631
7620
|
},
|
7632
7621
|
|
7633
7622
|
value: function() {
|
@@ -7640,12 +7629,12 @@ wysihtml5.commands = {
|
|
7640
7629
|
REG_EXP = /wysiwyg-text-align-[a-z]+/g;
|
7641
7630
|
|
7642
7631
|
wysihtml5.commands.justifyLeft = {
|
7643
|
-
exec: function(
|
7644
|
-
return wysihtml5.commands.formatBlock.exec(
|
7632
|
+
exec: function(composer, command) {
|
7633
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7645
7634
|
},
|
7646
7635
|
|
7647
|
-
state: function(
|
7648
|
-
return wysihtml5.commands.formatBlock.state(
|
7636
|
+
state: function(composer, command) {
|
7637
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7649
7638
|
},
|
7650
7639
|
|
7651
7640
|
value: function() {
|
@@ -7658,12 +7647,12 @@ wysihtml5.commands = {
|
|
7658
7647
|
REG_EXP = /wysiwyg-text-align-[a-z]+/g;
|
7659
7648
|
|
7660
7649
|
wysihtml5.commands.justifyRight = {
|
7661
|
-
exec: function(
|
7662
|
-
return wysihtml5.commands.formatBlock.exec(
|
7650
|
+
exec: function(composer, command) {
|
7651
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7663
7652
|
},
|
7664
7653
|
|
7665
|
-
state: function(
|
7666
|
-
return wysihtml5.commands.formatBlock.state(
|
7654
|
+
state: function(composer, command) {
|
7655
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP);
|
7667
7656
|
},
|
7668
7657
|
|
7669
7658
|
value: function() {
|
@@ -7676,12 +7665,12 @@ wysihtml5.commands = {
|
|
7676
7665
|
CLASS_NAME = "wysiwyg-text-decoration-underline";
|
7677
7666
|
|
7678
7667
|
wysihtml5.commands.underline = {
|
7679
|
-
exec: function(
|
7680
|
-
return wysihtml5.commands.formatInline.exec(
|
7668
|
+
exec: function(composer, command) {
|
7669
|
+
return wysihtml5.commands.formatInline.exec(composer, command, "span", CLASS_NAME, REG_EXP);
|
7681
7670
|
},
|
7682
7671
|
|
7683
|
-
state: function(
|
7684
|
-
return wysihtml5.commands.formatInline.state(
|
7672
|
+
state: function(composer, command) {
|
7673
|
+
return wysihtml5.commands.formatInline.state(composer, command, "span", CLASS_NAME, REG_EXP);
|
7685
7674
|
},
|
7686
7675
|
|
7687
7676
|
value: function() {
|
@@ -7713,24 +7702,25 @@ wysihtml5.commands = {
|
|
7713
7702
|
/** @scope wysihtml5.UndoManager.prototype */ {
|
7714
7703
|
constructor: function(editor) {
|
7715
7704
|
this.editor = editor;
|
7716
|
-
this.
|
7717
|
-
this.
|
7705
|
+
this.composer = editor.composer;
|
7706
|
+
this.element = this.composer.element;
|
7707
|
+
this.history = [this.composer.getValue()];
|
7718
7708
|
this.position = 1;
|
7719
7709
|
|
7720
7710
|
// Undo manager currently only supported in browsers who have the insertHTML command (not IE)
|
7721
|
-
if (
|
7711
|
+
if (this.composer.commands.support("insertHTML")) {
|
7722
7712
|
this._observe();
|
7723
7713
|
}
|
7724
7714
|
},
|
7725
7715
|
|
7726
7716
|
_observe: function() {
|
7727
|
-
var that
|
7728
|
-
doc
|
7717
|
+
var that = this,
|
7718
|
+
doc = this.composer.sandbox.getDocument(),
|
7729
7719
|
lastKey;
|
7730
7720
|
|
7731
7721
|
// Catch CTRL+Z and CTRL+Y
|
7732
|
-
dom.observe(this.
|
7733
|
-
if (!event.ctrlKey && !event.metaKey) {
|
7722
|
+
dom.observe(this.element, "keydown", function(event) {
|
7723
|
+
if (event.altKey || (!event.ctrlKey && !event.metaKey)) {
|
7734
7724
|
return;
|
7735
7725
|
}
|
7736
7726
|
|
@@ -7748,7 +7738,7 @@ wysihtml5.commands = {
|
|
7748
7738
|
});
|
7749
7739
|
|
7750
7740
|
// Catch delete and backspace
|
7751
|
-
dom.observe(this.
|
7741
|
+
dom.observe(this.element, "keydown", function(event) {
|
7752
7742
|
var keyCode = event.keyCode;
|
7753
7743
|
if (keyCode === lastKey) {
|
7754
7744
|
return;
|
@@ -7761,12 +7751,6 @@ wysihtml5.commands = {
|
|
7761
7751
|
}
|
7762
7752
|
});
|
7763
7753
|
|
7764
|
-
var interval, observed, cleanUp = function() {
|
7765
|
-
cleanTempElements(doc);
|
7766
|
-
clearInterval(interval);
|
7767
|
-
};
|
7768
|
-
|
7769
|
-
|
7770
7754
|
// Now this is very hacky:
|
7771
7755
|
// These days browsers don't offer a undo/redo event which we could hook into
|
7772
7756
|
// to be notified when the user hits undo/redo in the contextmenu.
|
@@ -7774,36 +7758,43 @@ wysihtml5.commands = {
|
|
7774
7758
|
// The last element being inserted will be immediately be removed again by a exexCommand("undo")
|
7775
7759
|
// => When the second element appears in the dom tree then we know the user clicked "redo" in the context menu
|
7776
7760
|
// => When the first element disappears from the dom tree then we know the user clicked "undo" in the context menu
|
7777
|
-
|
7778
|
-
cleanUp()
|
7779
|
-
|
7780
|
-
|
7781
|
-
|
7782
|
-
}
|
7783
|
-
|
7784
|
-
// enable undo button in context menu
|
7785
|
-
doc.execCommand("insertHTML", false, UNDO_HTML);
|
7786
|
-
// enable redo button in context menu
|
7787
|
-
doc.execCommand("insertHTML", false, REDO_HTML);
|
7788
|
-
doc.execCommand("undo", false, null);
|
7789
|
-
});
|
7761
|
+
if (wysihtml5.browser.hasUndoInContextMenu()) {
|
7762
|
+
var interval, observed, cleanUp = function() {
|
7763
|
+
cleanTempElements(doc);
|
7764
|
+
clearInterval(interval);
|
7765
|
+
};
|
7790
7766
|
|
7791
|
-
|
7792
|
-
|
7793
|
-
|
7794
|
-
that.
|
7795
|
-
|
7796
|
-
|
7797
|
-
|
7767
|
+
dom.observe(this.element, "contextmenu", function() {
|
7768
|
+
cleanUp();
|
7769
|
+
that.composer.selection.executeAndRestoreSimple(function() {
|
7770
|
+
if (that.element.lastChild) {
|
7771
|
+
that.composer.selection.setAfter(that.element.lastChild);
|
7772
|
+
}
|
7773
|
+
|
7774
|
+
// enable undo button in context menu
|
7775
|
+
doc.execCommand("insertHTML", false, UNDO_HTML);
|
7776
|
+
// enable redo button in context menu
|
7777
|
+
doc.execCommand("insertHTML", false, REDO_HTML);
|
7778
|
+
doc.execCommand("undo", false, null);
|
7779
|
+
});
|
7780
|
+
|
7781
|
+
interval = setInterval(function() {
|
7782
|
+
if (doc.getElementById("_wysihtml5-redo")) {
|
7783
|
+
cleanUp();
|
7784
|
+
that.redo();
|
7785
|
+
} else if (!doc.getElementById("_wysihtml5-undo")) {
|
7786
|
+
cleanUp();
|
7787
|
+
that.undo();
|
7788
|
+
}
|
7789
|
+
}, 400);
|
7790
|
+
|
7791
|
+
if (!observed) {
|
7792
|
+
observed = true;
|
7793
|
+
dom.observe(document, "mousedown", cleanUp);
|
7794
|
+
dom.observe(doc, ["mousedown", "paste", "cut", "copy"], cleanUp);
|
7798
7795
|
}
|
7799
|
-
}
|
7800
|
-
|
7801
|
-
if (!observed) {
|
7802
|
-
observed = true;
|
7803
|
-
dom.observe(document, "mousedown", cleanUp);
|
7804
|
-
dom.observe(doc, ["mousedown", "paste", "cut", "copy"], cleanUp);
|
7805
|
-
}
|
7806
|
-
});
|
7796
|
+
});
|
7797
|
+
}
|
7807
7798
|
|
7808
7799
|
this.editor
|
7809
7800
|
.observe("newword:composer", function() {
|
@@ -7817,7 +7808,7 @@ wysihtml5.commands = {
|
|
7817
7808
|
|
7818
7809
|
transact: function() {
|
7819
7810
|
var previousHtml = this.history[this.position - 1],
|
7820
|
-
currentHtml = this.
|
7811
|
+
currentHtml = this.composer.getValue();
|
7821
7812
|
|
7822
7813
|
if (currentHtml == previousHtml) {
|
7823
7814
|
return;
|
@@ -7854,7 +7845,7 @@ wysihtml5.commands = {
|
|
7854
7845
|
},
|
7855
7846
|
|
7856
7847
|
set: function(html) {
|
7857
|
-
this.
|
7848
|
+
this.composer.setValue(html);
|
7858
7849
|
this.editor.focus(true);
|
7859
7850
|
}
|
7860
7851
|
});
|
@@ -7913,9 +7904,7 @@ wysihtml5.views.View = Base.extend(
|
|
7913
7904
|
}
|
7914
7905
|
});(function(wysihtml5) {
|
7915
7906
|
var dom = wysihtml5.dom,
|
7916
|
-
browser = wysihtml5.browser
|
7917
|
-
selection = wysihtml5.selection,
|
7918
|
-
commands = wysihtml5.commands;
|
7907
|
+
browser = wysihtml5.browser;
|
7919
7908
|
|
7920
7909
|
wysihtml5.views.Composer = wysihtml5.views.View.extend(
|
7921
7910
|
/** @scope wysihtml5.views.Composer.prototype */ {
|
@@ -7983,14 +7972,21 @@ wysihtml5.views.View = Base.extend(
|
|
7983
7972
|
},
|
7984
7973
|
|
7985
7974
|
focus: function(setToEnd) {
|
7975
|
+
// IE 8 fires the focus event after .focus()
|
7976
|
+
// This is needed by our simulate_placeholder.js to work
|
7977
|
+
// therefore we clear it ourselves this time
|
7978
|
+
if (wysihtml5.browser.doesAsyncFocus() && this.hasPlaceholderSet()) {
|
7979
|
+
this.clear();
|
7980
|
+
}
|
7981
|
+
|
7986
7982
|
this.base();
|
7987
7983
|
|
7988
7984
|
var lastChild = this.element.lastChild;
|
7989
7985
|
if (setToEnd && lastChild) {
|
7990
7986
|
if (lastChild.nodeName === "BR") {
|
7991
|
-
selection.setBefore(this.element.lastChild);
|
7987
|
+
this.selection.setBefore(this.element.lastChild);
|
7992
7988
|
} else {
|
7993
|
-
selection.setAfter(this.element.lastChild);
|
7989
|
+
this.selection.setAfter(this.element.lastChild);
|
7994
7990
|
}
|
7995
7991
|
}
|
7996
7992
|
},
|
@@ -8018,8 +8014,7 @@ wysihtml5.views.View = Base.extend(
|
|
8018
8014
|
this.sandbox = new dom.Sandbox(function() {
|
8019
8015
|
that._create();
|
8020
8016
|
}, {
|
8021
|
-
stylesheets: this.config.stylesheets
|
8022
|
-
uaCompatible: "IE=7"
|
8017
|
+
stylesheets: this.config.stylesheets
|
8023
8018
|
});
|
8024
8019
|
this.iframe = this.sandbox.getIframe();
|
8025
8020
|
|
@@ -8038,16 +8033,17 @@ wysihtml5.views.View = Base.extend(
|
|
8038
8033
|
_create: function() {
|
8039
8034
|
var that = this;
|
8040
8035
|
|
8041
|
-
this.
|
8036
|
+
this.doc = this.sandbox.getDocument();
|
8037
|
+
this.element = this.doc.body;
|
8042
8038
|
this.textarea = this.parent.textarea;
|
8043
8039
|
this.element.innerHTML = this.textarea.getValue(true);
|
8044
8040
|
this.enable();
|
8045
8041
|
|
8046
8042
|
// Make sure our selection handler is ready
|
8047
|
-
selection.
|
8043
|
+
this.selection = new wysihtml5.Selection(this.parent);
|
8048
8044
|
|
8049
|
-
// Make sure commands
|
8050
|
-
commands.
|
8045
|
+
// Make sure commands dispatcher is ready
|
8046
|
+
this.commands = new wysihtml5.Commands(this.parent);
|
8051
8047
|
|
8052
8048
|
dom.copyAttributes([
|
8053
8049
|
"className", "spellcheck", "title", "lang", "dir", "accessKey"
|
@@ -8077,7 +8073,7 @@ wysihtml5.views.View = Base.extend(
|
|
8077
8073
|
}
|
8078
8074
|
|
8079
8075
|
// Make sure that the browser avoids using inline styles whenever possible
|
8080
|
-
commands.exec("styleWithCSS", false);
|
8076
|
+
this.commands.exec("styleWithCSS", false);
|
8081
8077
|
|
8082
8078
|
this._initAutoLinking();
|
8083
8079
|
this._initObjectResizing();
|
@@ -8088,15 +8084,15 @@ wysihtml5.views.View = Base.extend(
|
|
8088
8084
|
setTimeout(function() { that.focus(); }, 100);
|
8089
8085
|
}
|
8090
8086
|
|
8091
|
-
wysihtml5.quirks.insertLineBreakOnReturn(this
|
8087
|
+
wysihtml5.quirks.insertLineBreakOnReturn(this);
|
8092
8088
|
|
8093
8089
|
// IE sometimes leaves a single paragraph, which can't be removed by the user
|
8094
8090
|
if (!browser.clearsContentEditableCorrectly()) {
|
8095
|
-
wysihtml5.quirks.ensureProperClearing(this
|
8091
|
+
wysihtml5.quirks.ensureProperClearing(this);
|
8096
8092
|
}
|
8097
8093
|
|
8098
8094
|
if (!browser.clearsListsInContentEditableCorrectly()) {
|
8099
|
-
wysihtml5.quirks.ensureProperClearingOfLists(this
|
8095
|
+
wysihtml5.quirks.ensureProperClearingOfLists(this);
|
8100
8096
|
}
|
8101
8097
|
|
8102
8098
|
// Set up a sync that makes sure that textarea and editor have the same content
|
@@ -8112,10 +8108,11 @@ wysihtml5.views.View = Base.extend(
|
|
8112
8108
|
},
|
8113
8109
|
|
8114
8110
|
_initAutoLinking: function() {
|
8115
|
-
var
|
8111
|
+
var that = this,
|
8112
|
+
supportsDisablingOfAutoLinking = browser.canDisableAutoLinking(),
|
8116
8113
|
supportsAutoLinking = browser.doesAutoLinkingInContentEditable();
|
8117
8114
|
if (supportsDisablingOfAutoLinking) {
|
8118
|
-
commands.exec("autoUrlDetect", false);
|
8115
|
+
this.commands.exec("autoUrlDetect", false);
|
8119
8116
|
}
|
8120
8117
|
|
8121
8118
|
if (!this.config.autoLink) {
|
@@ -8126,7 +8123,7 @@ wysihtml5.views.View = Base.extend(
|
|
8126
8123
|
// OR when he supports auto linking but we were able to turn it off (IE9+)
|
8127
8124
|
if (!supportsAutoLinking || (supportsAutoLinking && supportsDisablingOfAutoLinking)) {
|
8128
8125
|
this.parent.observe("newword:composer", function() {
|
8129
|
-
selection.executeAndRestore(function(startContainer, endContainer) {
|
8126
|
+
that.selection.executeAndRestore(function(startContainer, endContainer) {
|
8130
8127
|
dom.autoLink(endContainer.parentNode);
|
8131
8128
|
});
|
8132
8129
|
});
|
@@ -8153,7 +8150,7 @@ wysihtml5.views.View = Base.extend(
|
|
8153
8150
|
return;
|
8154
8151
|
}
|
8155
8152
|
|
8156
|
-
var selectedNode = selection.getSelectedNode(event.target.ownerDocument),
|
8153
|
+
var selectedNode = that.selection.getSelectedNode(event.target.ownerDocument),
|
8157
8154
|
link = dom.getParentElement(selectedNode, { nodeName: "A" }, 4),
|
8158
8155
|
textContent;
|
8159
8156
|
|
@@ -8183,8 +8180,8 @@ wysihtml5.views.View = Base.extend(
|
|
8183
8180
|
propertiesLength = properties.length,
|
8184
8181
|
element = this.element;
|
8185
8182
|
|
8186
|
-
commands.exec("enableObjectResizing", this.config.allowObjectResizing);
|
8187
|
-
|
8183
|
+
this.commands.exec("enableObjectResizing", this.config.allowObjectResizing);
|
8184
|
+
|
8188
8185
|
if (this.config.allowObjectResizing) {
|
8189
8186
|
// IE sets inline styles after resizing objects
|
8190
8187
|
// The following lines make sure that the width/height css properties
|
@@ -8406,8 +8403,6 @@ wysihtml5.views.View = Base.extend(
|
|
8406
8403
|
* - Catch paste events
|
8407
8404
|
* - Dispatch proprietary newword:composer event
|
8408
8405
|
* - Keyboard shortcuts
|
8409
|
-
*
|
8410
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
8411
8406
|
*/
|
8412
8407
|
(function(wysihtml5) {
|
8413
8408
|
var dom = wysihtml5.dom,
|
@@ -8470,7 +8465,7 @@ wysihtml5.views.View = Base.extend(
|
|
8470
8465
|
originalScrollTop = document.documentElement.scrollTop || document.body.scrollTop,
|
8471
8466
|
originalScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
|
8472
8467
|
try {
|
8473
|
-
|
8468
|
+
that.selection.insertNode(input);
|
8474
8469
|
} catch(e) {
|
8475
8470
|
element.appendChild(input);
|
8476
8471
|
}
|
@@ -8501,7 +8496,7 @@ wysihtml5.views.View = Base.extend(
|
|
8501
8496
|
}
|
8502
8497
|
if (data) {
|
8503
8498
|
element.focus();
|
8504
|
-
|
8499
|
+
that.commands.exec("insertHTML", data);
|
8505
8500
|
that.parent.fire("paste").fire("paste:composer");
|
8506
8501
|
event.stopPropagation();
|
8507
8502
|
event.preventDefault();
|
@@ -8529,7 +8524,7 @@ wysihtml5.views.View = Base.extend(
|
|
8529
8524
|
dom.observe(element, "mousedown", function(event) {
|
8530
8525
|
var target = event.target;
|
8531
8526
|
if (target.nodeName === "IMG") {
|
8532
|
-
|
8527
|
+
that.selection.selectNode(target);
|
8533
8528
|
event.preventDefault();
|
8534
8529
|
}
|
8535
8530
|
});
|
@@ -8540,14 +8535,14 @@ wysihtml5.views.View = Base.extend(
|
|
8540
8535
|
var keyCode = event.keyCode,
|
8541
8536
|
command = shortcuts[keyCode];
|
8542
8537
|
if ((event.ctrlKey || event.metaKey) && command) {
|
8543
|
-
|
8538
|
+
that.commands.exec(command);
|
8544
8539
|
event.preventDefault();
|
8545
8540
|
}
|
8546
8541
|
});
|
8547
8542
|
|
8548
8543
|
// --------- Make sure that when pressing backspace/delete on selected images deletes the image and it's anchor ---------
|
8549
8544
|
dom.observe(element, "keydown", function(event) {
|
8550
|
-
var target =
|
8545
|
+
var target = that.selection.getSelectedNode(true),
|
8551
8546
|
keyCode = event.keyCode,
|
8552
8547
|
parent;
|
8553
8548
|
if (target && target.nodeName === "IMG" && (keyCode === wysihtml5.BACKSPACE_KEY || keyCode === wysihtml5.DELETE_KEY)) { // 8 => backspace, 46 => delete
|
@@ -8747,7 +8742,6 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
8747
8742
|
});/**
|
8748
8743
|
* Toolbar Dialog
|
8749
8744
|
*
|
8750
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
8751
8745
|
* @param {Element} link The toolbar link which causes the dialog to show up
|
8752
8746
|
* @param {Element} container The dialog container
|
8753
8747
|
*
|
@@ -8877,7 +8871,7 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
8877
8871
|
* Basically it adopted the attribute values into the corresponding input fields
|
8878
8872
|
*
|
8879
8873
|
*/
|
8880
|
-
_interpolate: function() {
|
8874
|
+
_interpolate: function(avoidHiddenFields) {
|
8881
8875
|
var field,
|
8882
8876
|
fieldName,
|
8883
8877
|
newValue,
|
@@ -8887,10 +8881,18 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
8887
8881
|
i = 0;
|
8888
8882
|
for (; i<length; i++) {
|
8889
8883
|
field = fields[i];
|
8884
|
+
|
8890
8885
|
// Never change elements where the user is currently typing in
|
8891
8886
|
if (field === focusedElement) {
|
8892
8887
|
continue;
|
8893
8888
|
}
|
8889
|
+
|
8890
|
+
// Don't update hidden fields
|
8891
|
+
// See https://github.com/xing/wysihtml5/pull/14
|
8892
|
+
if (avoidHiddenFields && field.type === "hidden") {
|
8893
|
+
continue;
|
8894
|
+
}
|
8895
|
+
|
8894
8896
|
fieldName = field.getAttribute(ATTRIBUTE_FIELDS);
|
8895
8897
|
newValue = this.elementToChange ? (this.elementToChange[fieldName] || "") : field.defaultValue;
|
8896
8898
|
field.value = newValue;
|
@@ -8907,7 +8909,7 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
8907
8909
|
this._observe();
|
8908
8910
|
this._interpolate();
|
8909
8911
|
if (elementToChange) {
|
8910
|
-
this.interval = setInterval(function() { that._interpolate(); }, 500);
|
8912
|
+
this.interval = setInterval(function() { that._interpolate(true); }, 500);
|
8911
8913
|
}
|
8912
8914
|
dom.addClass(this.link, CLASS_NAME_OPENED);
|
8913
8915
|
this.container.style.display = "";
|
@@ -8943,8 +8945,6 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
8943
8945
|
*
|
8944
8946
|
* "Accessing Google Speech API Chrome 11"
|
8945
8947
|
* http://mikepultz.com/2011/03/accessing-google-speech-api-chrome-11/
|
8946
|
-
*
|
8947
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
8948
8948
|
*/
|
8949
8949
|
(function(wysihtml5) {
|
8950
8950
|
var dom = wysihtml5.dom;
|
@@ -9021,7 +9021,6 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9021
9021
|
})(wysihtml5);/**
|
9022
9022
|
* Toolbar
|
9023
9023
|
*
|
9024
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
9025
9024
|
* @param {Object} parent Reference to instance of Editor instance
|
9026
9025
|
* @param {Element} container Reference to the toolbar container element
|
9027
9026
|
*
|
@@ -9092,20 +9091,19 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9092
9091
|
dialogElement = this.container.querySelector("[data-wysihtml5-dialog='" + command + "']"),
|
9093
9092
|
dialog,
|
9094
9093
|
caretBookmark;
|
9094
|
+
|
9095
9095
|
if (dialogElement) {
|
9096
9096
|
dialog = new wysihtml5.toolbar.Dialog(link, dialogElement);
|
9097
9097
|
|
9098
9098
|
dialog.observe("show", function() {
|
9099
|
-
caretBookmark =
|
9099
|
+
caretBookmark = that.composer.selection.getBookmark();
|
9100
9100
|
|
9101
9101
|
that.editor.fire("show:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
9102
9102
|
});
|
9103
9103
|
|
9104
9104
|
dialog.observe("save", function(attributes) {
|
9105
|
-
that.editor.focus(false);
|
9106
|
-
|
9107
9105
|
if (caretBookmark) {
|
9108
|
-
|
9106
|
+
that.composer.selection.setBookmark(caretBookmark);
|
9109
9107
|
}
|
9110
9108
|
that._execCommand(command, attributes);
|
9111
9109
|
|
@@ -9145,7 +9143,7 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9145
9143
|
// Make sure that composer is focussed (false => don't move caret to the end)
|
9146
9144
|
this.editor.focus(false);
|
9147
9145
|
|
9148
|
-
|
9146
|
+
this.composer.commands.exec(command, commandValue);
|
9149
9147
|
this._updateLinkStates();
|
9150
9148
|
},
|
9151
9149
|
|
@@ -9240,7 +9238,7 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9240
9238
|
command.dialog.hide();
|
9241
9239
|
}
|
9242
9240
|
} else {
|
9243
|
-
state =
|
9241
|
+
state = this.composer.commands.state(command.name, command.value);
|
9244
9242
|
if (wysihtml5.lang.object(state).isArray()) {
|
9245
9243
|
// Grab first and only object/element in state array, otherwise convert state into boolean
|
9246
9244
|
// to avoid showing a dialog for multiple selected elements which may have different attributes
|
@@ -9287,7 +9285,6 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9287
9285
|
/**
|
9288
9286
|
* WYSIHTML5 Editor
|
9289
9287
|
*
|
9290
|
-
* @author Christopher Blum <christopher.blum@xing.com>
|
9291
9288
|
* @param {Element} textareaElement Reference to the textarea which should be turned into a rich text interface
|
9292
9289
|
* @param {Object} [config] See defaultConfig object below for explanation of each individual config option
|
9293
9290
|
*
|
@@ -9449,7 +9446,7 @@ wysihtml5.views.Textarea = wysihtml5.views.View.extend(
|
|
9449
9446
|
this.observe("paste:composer", function() {
|
9450
9447
|
var keepScrollPosition = true,
|
9451
9448
|
that = this;
|
9452
|
-
|
9449
|
+
that.composer.selection.executeAndRestore(function() {
|
9453
9450
|
wysihtml5.quirks.cleanPastedHTML(that.composer.element);
|
9454
9451
|
that.parse(that.composer.element);
|
9455
9452
|
}, keepScrollPosition);
|