wysihtml5x-rails 0.4.17 → 0.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/wysihtml5x/rails/version.rb +1 -1
- data/vendor/assets/javascripts/parser_rules/advanced.js +4 -3
- data/vendor/assets/javascripts/parser_rules/advanced_unwrap.js +4 -3
- data/vendor/assets/javascripts/wysihtml5x-toolbar.js +952 -406
- data/vendor/assets/javascripts/wysihtml5x.js +910 -373
- metadata +4 -4
@@ -3,6 +3,17 @@
|
|
3
3
|
// IE8 SUPPORT BLOCK
|
4
4
|
// You can compile wuthout all this if IE8 is not needed
|
5
5
|
|
6
|
+
// String trim for ie8
|
7
|
+
if (!String.prototype.trim) {
|
8
|
+
(function() {
|
9
|
+
// Make sure we trim BOM and NBSP
|
10
|
+
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
|
11
|
+
String.prototype.trim = function() {
|
12
|
+
return this.replace(rtrim, '');
|
13
|
+
};
|
14
|
+
})();
|
15
|
+
}
|
16
|
+
|
6
17
|
// addEventListener, removeEventListener
|
7
18
|
// TODO: make usage of wysihtml5.dom.observe obsolete
|
8
19
|
(function() {
|
@@ -102,6 +113,14 @@ if(!Array.isArray) {
|
|
102
113
|
};
|
103
114
|
}
|
104
115
|
|
116
|
+
// Array indexOf for ie8
|
117
|
+
if (!Array.prototype.indexOf) {
|
118
|
+
Array.prototype.indexOf = function(a,f) {
|
119
|
+
for(var c=this.length,r=-1,d=f>>>0; ~(c-d); r=this[--c]===a?c:r);
|
120
|
+
return r;
|
121
|
+
};
|
122
|
+
}
|
123
|
+
|
105
124
|
// Function.prototype.bind()
|
106
125
|
// TODO: clean the code from variable 'that' as it can be confusing
|
107
126
|
if (!Function.prototype.bind) {
|
@@ -127,8 +146,237 @@ if (!Function.prototype.bind) {
|
|
127
146
|
|
128
147
|
return fBound;
|
129
148
|
};
|
130
|
-
}
|
131
|
-
|
149
|
+
}
|
150
|
+
|
151
|
+
// Element.matches Adds ie8 support and unifies nonstandard function names in other browsers
|
152
|
+
this.Element && function(ElementPrototype) {
|
153
|
+
ElementPrototype.matches = ElementPrototype.matches ||
|
154
|
+
ElementPrototype.matchesSelector ||
|
155
|
+
ElementPrototype.mozMatchesSelector ||
|
156
|
+
ElementPrototype.msMatchesSelector ||
|
157
|
+
ElementPrototype.oMatchesSelector ||
|
158
|
+
ElementPrototype.webkitMatchesSelector ||
|
159
|
+
function (selector) {
|
160
|
+
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
|
161
|
+
while (nodes[++i] && nodes[i] != node);
|
162
|
+
return !!nodes[i];
|
163
|
+
};
|
164
|
+
}(Element.prototype);
|
165
|
+
|
166
|
+
// Element.classList for ie8-9 (toggle all IE)
|
167
|
+
// source http://purl.eligrey.com/github/classList.js/blob/master/classList.js
|
168
|
+
|
169
|
+
if ("document" in self) {
|
170
|
+
// Full polyfill for browsers with no classList support
|
171
|
+
if (!("classList" in document.createElement("_"))) {
|
172
|
+
(function(view) {
|
173
|
+
"use strict";
|
174
|
+
if (!('Element' in view)) return;
|
175
|
+
|
176
|
+
var
|
177
|
+
classListProp = "classList",
|
178
|
+
protoProp = "prototype",
|
179
|
+
elemCtrProto = view.Element[protoProp],
|
180
|
+
objCtr = Object,
|
181
|
+
strTrim = String[protoProp].trim || function() {
|
182
|
+
return this.replace(/^\s+|\s+$/g, "");
|
183
|
+
},
|
184
|
+
arrIndexOf = Array[protoProp].indexOf || function(item) {
|
185
|
+
var
|
186
|
+
i = 0,
|
187
|
+
len = this.length;
|
188
|
+
for (; i < len; i++) {
|
189
|
+
if (i in this && this[i] === item) {
|
190
|
+
return i;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
return -1;
|
194
|
+
}, // Vendors: please allow content code to instantiate DOMExceptions
|
195
|
+
DOMEx = function(type, message) {
|
196
|
+
this.name = type;
|
197
|
+
this.code = DOMException[type];
|
198
|
+
this.message = message;
|
199
|
+
},
|
200
|
+
checkTokenAndGetIndex = function(classList, token) {
|
201
|
+
if (token === "") {
|
202
|
+
throw new DOMEx(
|
203
|
+
"SYNTAX_ERR", "An invalid or illegal string was specified"
|
204
|
+
);
|
205
|
+
}
|
206
|
+
if (/\s/.test(token)) {
|
207
|
+
throw new DOMEx(
|
208
|
+
"INVALID_CHARACTER_ERR", "String contains an invalid character"
|
209
|
+
);
|
210
|
+
}
|
211
|
+
return arrIndexOf.call(classList, token);
|
212
|
+
},
|
213
|
+
ClassList = function(elem) {
|
214
|
+
var
|
215
|
+
trimmedClasses = strTrim.call(elem.getAttribute("class") || ""),
|
216
|
+
classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [],
|
217
|
+
i = 0,
|
218
|
+
len = classes.length;
|
219
|
+
for (; i < len; i++) {
|
220
|
+
this.push(classes[i]);
|
221
|
+
}
|
222
|
+
this._updateClassName = function() {
|
223
|
+
elem.setAttribute("class", this.toString());
|
224
|
+
};
|
225
|
+
},
|
226
|
+
classListProto = ClassList[protoProp] = [],
|
227
|
+
classListGetter = function() {
|
228
|
+
return new ClassList(this);
|
229
|
+
};
|
230
|
+
// Most DOMException implementations don't allow calling DOMException's toString()
|
231
|
+
// on non-DOMExceptions. Error's toString() is sufficient here.
|
232
|
+
DOMEx[protoProp] = Error[protoProp];
|
233
|
+
classListProto.item = function(i) {
|
234
|
+
return this[i] || null;
|
235
|
+
};
|
236
|
+
classListProto.contains = function(token) {
|
237
|
+
token += "";
|
238
|
+
return checkTokenAndGetIndex(this, token) !== -1;
|
239
|
+
};
|
240
|
+
classListProto.add = function() {
|
241
|
+
var
|
242
|
+
tokens = arguments,
|
243
|
+
i = 0,
|
244
|
+
l = tokens.length,
|
245
|
+
token, updated = false;
|
246
|
+
do {
|
247
|
+
token = tokens[i] + "";
|
248
|
+
if (checkTokenAndGetIndex(this, token) === -1) {
|
249
|
+
this.push(token);
|
250
|
+
updated = true;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
while (++i < l);
|
254
|
+
|
255
|
+
if (updated) {
|
256
|
+
this._updateClassName();
|
257
|
+
}
|
258
|
+
};
|
259
|
+
classListProto.remove = function() {
|
260
|
+
var
|
261
|
+
tokens = arguments,
|
262
|
+
i = 0,
|
263
|
+
l = tokens.length,
|
264
|
+
token, updated = false,
|
265
|
+
index;
|
266
|
+
do {
|
267
|
+
token = tokens[i] + "";
|
268
|
+
index = checkTokenAndGetIndex(this, token);
|
269
|
+
while (index !== -1) {
|
270
|
+
this.splice(index, 1);
|
271
|
+
updated = true;
|
272
|
+
index = checkTokenAndGetIndex(this, token);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
while (++i < l);
|
276
|
+
|
277
|
+
if (updated) {
|
278
|
+
this._updateClassName();
|
279
|
+
}
|
280
|
+
};
|
281
|
+
classListProto.toggle = function(token, force) {
|
282
|
+
token += "";
|
283
|
+
|
284
|
+
var
|
285
|
+
result = this.contains(token),
|
286
|
+
method = result ?
|
287
|
+
force !== true && "remove" :
|
288
|
+
force !== false && "add";
|
289
|
+
|
290
|
+
if (method) {
|
291
|
+
this[method](token);
|
292
|
+
}
|
293
|
+
|
294
|
+
if (force === true || force === false) {
|
295
|
+
return force;
|
296
|
+
} else {
|
297
|
+
return !result;
|
298
|
+
}
|
299
|
+
};
|
300
|
+
classListProto.toString = function() {
|
301
|
+
return this.join(" ");
|
302
|
+
};
|
303
|
+
|
304
|
+
if (objCtr.defineProperty) {
|
305
|
+
var classListPropDesc = {
|
306
|
+
get: classListGetter,
|
307
|
+
enumerable: true,
|
308
|
+
configurable: true
|
309
|
+
};
|
310
|
+
try {
|
311
|
+
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
|
312
|
+
} catch (ex) { // IE 8 doesn't support enumerable:true
|
313
|
+
if (ex.number === -0x7FF5EC54) {
|
314
|
+
classListPropDesc.enumerable = false;
|
315
|
+
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
|
316
|
+
}
|
317
|
+
}
|
318
|
+
} else if (objCtr[protoProp].__defineGetter__) {
|
319
|
+
elemCtrProto.__defineGetter__(classListProp, classListGetter);
|
320
|
+
}
|
321
|
+
|
322
|
+
}(self));
|
323
|
+
|
324
|
+
} else {
|
325
|
+
// There is full or partial native classList support, so just check if we need
|
326
|
+
// to normalize the add/remove and toggle APIs.
|
327
|
+
|
328
|
+
(function() {
|
329
|
+
"use strict";
|
330
|
+
|
331
|
+
var testElement = document.createElement("_");
|
332
|
+
|
333
|
+
testElement.classList.add("c1", "c2");
|
334
|
+
|
335
|
+
// Polyfill for IE 10/11 and Firefox <26, where classList.add and
|
336
|
+
// classList.remove exist but support only one argument at a time.
|
337
|
+
if (!testElement.classList.contains("c2")) {
|
338
|
+
var createMethod = function(method) {
|
339
|
+
var original = DOMTokenList.prototype[method];
|
340
|
+
|
341
|
+
DOMTokenList.prototype[method] = function(token) {
|
342
|
+
var i, len = arguments.length;
|
343
|
+
|
344
|
+
for (i = 0; i < len; i++) {
|
345
|
+
token = arguments[i];
|
346
|
+
original.call(this, token);
|
347
|
+
}
|
348
|
+
};
|
349
|
+
};
|
350
|
+
createMethod('add');
|
351
|
+
createMethod('remove');
|
352
|
+
}
|
353
|
+
|
354
|
+
testElement.classList.toggle("c3", false);
|
355
|
+
|
356
|
+
// Polyfill for IE 10 and Firefox <24, where classList.toggle does not
|
357
|
+
// support the second argument.
|
358
|
+
if (testElement.classList.contains("c3")) {
|
359
|
+
var _toggle = DOMTokenList.prototype.toggle;
|
360
|
+
|
361
|
+
DOMTokenList.prototype.toggle = function(token, force) {
|
362
|
+
if (1 in arguments && !this.contains(token) === !force) {
|
363
|
+
return force;
|
364
|
+
} else {
|
365
|
+
return _toggle.call(this, token);
|
366
|
+
}
|
367
|
+
};
|
368
|
+
|
369
|
+
}
|
370
|
+
|
371
|
+
testElement = null;
|
372
|
+
}());
|
373
|
+
|
374
|
+
}
|
375
|
+
|
376
|
+
}
|
377
|
+
|
378
|
+
;/**
|
379
|
+
* @license wysihtml5x v0.5.0-beta1
|
132
380
|
* https://github.com/Edicy/wysihtml5
|
133
381
|
*
|
134
382
|
* Author: Christopher Blum (https://github.com/tiff)
|
@@ -139,7 +387,7 @@ if (!Function.prototype.bind) {
|
|
139
387
|
*
|
140
388
|
*/
|
141
389
|
var wysihtml5 = {
|
142
|
-
version: "0.
|
390
|
+
version: "0.5.0-beta1",
|
143
391
|
|
144
392
|
// namespaces
|
145
393
|
commands: {},
|
@@ -4688,6 +4936,15 @@ wysihtml5.browser = (function() {
|
|
4688
4936
|
*/
|
4689
4937
|
supportsModenPaste: function () {
|
4690
4938
|
return !("clipboardData" in window);
|
4939
|
+
},
|
4940
|
+
|
4941
|
+
// Unifies the property names of element.style by returning the suitable property name for current browser
|
4942
|
+
// Input property key must be the standard
|
4943
|
+
fixStyleKey: function(key) {
|
4944
|
+
if (key === "cssFloat") {
|
4945
|
+
return ("styleFloat" in document.createElement("div").style) ? "styleFloat" : "cssFloat";
|
4946
|
+
}
|
4947
|
+
return key;
|
4691
4948
|
}
|
4692
4949
|
};
|
4693
4950
|
})();
|
@@ -5422,22 +5679,26 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
5422
5679
|
* });
|
5423
5680
|
*/
|
5424
5681
|
(function(wysihtml5) {
|
5425
|
-
|
5426
5682
|
wysihtml5.dom.delegate = function(container, selector, eventName, handler) {
|
5427
|
-
|
5428
|
-
var target
|
5429
|
-
|
5683
|
+
var callback = function(event) {
|
5684
|
+
var target = event.target,
|
5685
|
+
element = (target.nodeType === 3) ? target.parentNode : target, // IE has .contains only seeing elements not textnodes
|
5686
|
+
matches = container.querySelectorAll(selector);
|
5430
5687
|
|
5431
|
-
|
5432
|
-
if (
|
5433
|
-
handler.call(
|
5434
|
-
break;
|
5688
|
+
for (var i = 0, max = matches.length; i < max; i++) {
|
5689
|
+
if (matches[i].contains(element)) {
|
5690
|
+
handler.call(matches[i], event);
|
5435
5691
|
}
|
5436
|
-
target = target.parentNode;
|
5437
5692
|
}
|
5438
|
-
}
|
5439
|
-
};
|
5693
|
+
};
|
5440
5694
|
|
5695
|
+
container.addEventListener(eventName, callback, false);
|
5696
|
+
return {
|
5697
|
+
stop: function() {
|
5698
|
+
container.removeEventListener(eventName, callback, false);
|
5699
|
+
}
|
5700
|
+
};
|
5701
|
+
};
|
5441
5702
|
})(wysihtml5);
|
5442
5703
|
;// TODO: Refactor dom tree traversing here
|
5443
5704
|
(function(wysihtml5) {
|
@@ -5515,6 +5776,103 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
5515
5776
|
}
|
5516
5777
|
|
5517
5778
|
return wysihtml5.dom.domNode(lastChild).lastLeafNode(options);
|
5779
|
+
},
|
5780
|
+
|
5781
|
+
/*
|
5782
|
+
Tests a node against properties, and returns true if matches.
|
5783
|
+
Tests on principle that all properties defined must have at least one match.
|
5784
|
+
styleValue parameter works in context of styleProperty and has no effect otherwise.
|
5785
|
+
Returns true if element matches and false if it does not.
|
5786
|
+
|
5787
|
+
Properties for filtering element:
|
5788
|
+
{
|
5789
|
+
query: selector string,
|
5790
|
+
nodeName: string (uppercase),
|
5791
|
+
className: string,
|
5792
|
+
classRegExp: regex,
|
5793
|
+
styleProperty: string or [],
|
5794
|
+
styleValue: string, [] or regex
|
5795
|
+
}
|
5796
|
+
|
5797
|
+
Example:
|
5798
|
+
var node = wysihtml5.dom.domNode(element).test({})
|
5799
|
+
*/
|
5800
|
+
test: function(properties) {
|
5801
|
+
var prop;
|
5802
|
+
|
5803
|
+
// retuern false if properties object is not defined
|
5804
|
+
if (!properties) {
|
5805
|
+
return false;
|
5806
|
+
}
|
5807
|
+
|
5808
|
+
// Only element nodes can be tested for these properties
|
5809
|
+
if (node.nodeType !== 1) {
|
5810
|
+
return false;
|
5811
|
+
}
|
5812
|
+
|
5813
|
+
if (properties.query) {
|
5814
|
+
if (!node.matches(properties.query)) {
|
5815
|
+
return false;
|
5816
|
+
}
|
5817
|
+
}
|
5818
|
+
|
5819
|
+
if (properties.nodeName && node.nodeName !== properties.nodeName) {
|
5820
|
+
return false;
|
5821
|
+
}
|
5822
|
+
|
5823
|
+
if (properties.className && !node.classList.contains(properties.className)) {
|
5824
|
+
return false;
|
5825
|
+
}
|
5826
|
+
|
5827
|
+
// classRegExp check (useful for classname begins with logic)
|
5828
|
+
if (properties.classRegExp) {
|
5829
|
+
var matches = (node.className || "").match(properties.classRegExp) || [];
|
5830
|
+
if (matches.length === 0) {
|
5831
|
+
return false;
|
5832
|
+
}
|
5833
|
+
}
|
5834
|
+
|
5835
|
+
// styleProperty check
|
5836
|
+
if (properties.styleProperty && properties.styleProperty.length > 0) {
|
5837
|
+
var hasOneStyle = false,
|
5838
|
+
styles = (Array.isArray(properties.styleProperty)) ? properties.styleProperty : [properties.styleProperty];
|
5839
|
+
for (var j = 0, maxStyleP = styles.length; j < maxStyleP; j++) {
|
5840
|
+
// Some old IE-s have different property name for cssFloat
|
5841
|
+
prop = wysihtml5.browser.fixStyleKey(styles[j]);
|
5842
|
+
if (node.style[prop]) {
|
5843
|
+
if (properties.styleValue) {
|
5844
|
+
// Style value as additional parameter
|
5845
|
+
if (properties.styleValue instanceof RegExp) {
|
5846
|
+
// style value as Regexp
|
5847
|
+
if (node.style[prop].trim().match(properties.styleValue).length > 0) {
|
5848
|
+
hasOneStyle = true;
|
5849
|
+
break;
|
5850
|
+
}
|
5851
|
+
} else if (Array.isArray(properties.styleValue)) {
|
5852
|
+
// style value as array
|
5853
|
+
if (properties.styleValue.indexOf(node.style[prop].trim())) {
|
5854
|
+
hasOneStyle = true;
|
5855
|
+
break;
|
5856
|
+
}
|
5857
|
+
} else {
|
5858
|
+
// style value as string
|
5859
|
+
if (properties.styleValue === node.style[prop].trim()) {
|
5860
|
+
hasOneStyle = true;
|
5861
|
+
break;
|
5862
|
+
}
|
5863
|
+
}
|
5864
|
+
} else {
|
5865
|
+
hasOneStyle = true;
|
5866
|
+
break;
|
5867
|
+
}
|
5868
|
+
}
|
5869
|
+
if (!hasOneStyle) {
|
5870
|
+
return false;
|
5871
|
+
}
|
5872
|
+
}
|
5873
|
+
}
|
5874
|
+
|
5875
|
+
return true;
|
5518
5876
|
}
|
5519
5877
|
|
5520
5878
|
};
|
@@ -5585,77 +5943,35 @@ wysihtml5.dom.getAsDom = (function() {
|
|
5585
5943
|
})();
|
5586
5944
|
;/**
|
5587
5945
|
* Walks the dom tree from the given node up until it finds a match
|
5588
|
-
* Designed for optimal performance.
|
5589
5946
|
*
|
5590
5947
|
* @param {Element} node The from which to check the parent nodes
|
5591
|
-
* @param {Object} matchingSet Object to match against
|
5948
|
+
* @param {Object} matchingSet Object to match against, Properties for filtering element:
|
5949
|
+
* {
|
5950
|
+
* query: selector string,
|
5951
|
+
* classRegExp: regex,
|
5952
|
+
* styleProperty: string or [],
|
5953
|
+
* styleValue: string, [] or regex
|
5954
|
+
* }
|
5592
5955
|
* @param {Number} [levels] How many parents should the function check up from the current node (defaults to 50)
|
5956
|
+
* @param {Element} Optional, defines the container that limits the search
|
5957
|
+
*
|
5593
5958
|
* @return {null|Element} Returns the first element that matched the desiredNodeName(s)
|
5594
|
-
|
5595
|
-
* var listElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: ["MENU", "UL", "OL"] });
|
5596
|
-
* // ... or ...
|
5597
|
-
* var unorderedListElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: "UL" });
|
5598
|
-
* // ... or ...
|
5599
|
-
* var coloredElement = wysihtml5.dom.getParentElement(myTextNode, { nodeName: "SPAN", className: "wysiwyg-color-red", classRegExp: /wysiwyg-color-[a-z]/g });
|
5600
|
-
*/
|
5601
|
-
wysihtml5.dom.getParentElement = (function() {
|
5602
|
-
|
5603
|
-
function _isSameNodeName(nodeName, desiredNodeNames) {
|
5604
|
-
if (!desiredNodeNames || !desiredNodeNames.length) {
|
5605
|
-
return true;
|
5606
|
-
}
|
5607
|
-
|
5608
|
-
if (typeof(desiredNodeNames) === "string") {
|
5609
|
-
return nodeName === desiredNodeNames;
|
5610
|
-
} else {
|
5611
|
-
return wysihtml5.lang.array(desiredNodeNames).contains(nodeName);
|
5612
|
-
}
|
5613
|
-
}
|
5614
|
-
|
5615
|
-
function _isElement(node) {
|
5616
|
-
return node.nodeType === wysihtml5.ELEMENT_NODE;
|
5617
|
-
}
|
5618
|
-
|
5619
|
-
function _hasClassName(element, className, classRegExp) {
|
5620
|
-
var classNames = (element.className || "").match(classRegExp) || [];
|
5621
|
-
if (!className) {
|
5622
|
-
return !!classNames.length;
|
5623
|
-
}
|
5624
|
-
return classNames[classNames.length - 1] === className;
|
5625
|
-
}
|
5626
|
-
|
5627
|
-
function _hasStyle(element, cssStyle, styleRegExp) {
|
5628
|
-
var styles = (element.getAttribute('style') || "").match(styleRegExp) || [];
|
5629
|
-
if (!cssStyle) {
|
5630
|
-
return !!styles.length;
|
5631
|
-
}
|
5632
|
-
return styles[styles.length - 1] === cssStyle;
|
5633
|
-
}
|
5634
|
-
|
5635
|
-
return function(node, matchingSet, levels, container) {
|
5636
|
-
var findByStyle = (matchingSet.cssStyle || matchingSet.styleRegExp),
|
5637
|
-
findByClass = (matchingSet.className || matchingSet.classRegExp);
|
5638
|
-
|
5639
|
-
levels = levels || 50; // Go max 50 nodes upwards from current node
|
5959
|
+
*/
|
5640
5960
|
|
5641
|
-
|
5642
|
-
if (findByClass && !matchingSet.classRegExp) {
|
5643
|
-
matchingSet.classRegExp = new RegExp(matchingSet.className);
|
5644
|
-
}
|
5961
|
+
wysihtml5.dom.getParentElement = (function() {
|
5645
5962
|
|
5963
|
+
return function(node, properties, levels, container) {
|
5964
|
+
levels = levels || 50;
|
5646
5965
|
while (levels-- && node && node.nodeName !== "BODY" && (!container || node !== container)) {
|
5647
|
-
if (
|
5648
|
-
(!findByStyle || _hasStyle(node, matchingSet.cssStyle, matchingSet.styleRegExp)) &&
|
5649
|
-
(!findByClass || _hasClassName(node, matchingSet.className, matchingSet.classRegExp))
|
5650
|
-
) {
|
5966
|
+
if (wysihtml5.dom.domNode(node).test(properties)) {
|
5651
5967
|
return node;
|
5652
5968
|
}
|
5653
5969
|
node = node.parentNode;
|
5654
5970
|
}
|
5655
5971
|
return null;
|
5656
5972
|
};
|
5657
|
-
|
5658
|
-
|
5973
|
+
|
5974
|
+
})();;/**
|
5659
5975
|
* Get element's style for a specific css property
|
5660
5976
|
*
|
5661
5977
|
* @param {Element} element The element on which to retrieve the style
|
@@ -6653,7 +6969,7 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6653
6969
|
})(),
|
6654
6970
|
|
6655
6971
|
href: (function() {
|
6656
|
-
var REG_EXP = /^(#|\/|https?:\/\/|mailto:)/i;
|
6972
|
+
var REG_EXP = /^(#|\/|https?:\/\/|mailto:|tel:)/i;
|
6657
6973
|
return function(attributeValue) {
|
6658
6974
|
if (!attributeValue || !attributeValue.match(REG_EXP)) {
|
6659
6975
|
return null;
|
@@ -6674,6 +6990,7 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6674
6990
|
};
|
6675
6991
|
})(),
|
6676
6992
|
|
6993
|
+
// Integers. Does not work with floating point numbers and units
|
6677
6994
|
numbers: (function() {
|
6678
6995
|
var REG_EXP = /\D/g;
|
6679
6996
|
return function(attributeValue) {
|
@@ -6682,6 +6999,15 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6682
6999
|
};
|
6683
7000
|
})(),
|
6684
7001
|
|
7002
|
+
// Useful for with/height attributes where floating points and percentages are allowed
|
7003
|
+
dimension: (function() {
|
7004
|
+
var REG_EXP = /\D*(\d+)(\.\d+)?\s?(%)?\D*/;
|
7005
|
+
return function(attributeValue) {
|
7006
|
+
attributeValue = (attributeValue || "").replace(REG_EXP, "$1$2$3");
|
7007
|
+
return attributeValue || null;
|
7008
|
+
};
|
7009
|
+
})(),
|
7010
|
+
|
6685
7011
|
any: (function() {
|
6686
7012
|
return function(attributeValue) {
|
6687
7013
|
return attributeValue;
|
@@ -7512,7 +7838,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
7512
7838
|
var TableModifyerByCell = function (cell, table) {
|
7513
7839
|
if (cell) {
|
7514
7840
|
this.cell = cell;
|
7515
|
-
this.table = api.getParentElement(cell, {
|
7841
|
+
this.table = api.getParentElement(cell, { query: "table" });
|
7516
7842
|
} else if (table) {
|
7517
7843
|
this.table = table;
|
7518
7844
|
this.cell = this.table.querySelectorAll('th, td')[0];
|
@@ -7791,7 +8117,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
7791
8117
|
for (var cidx = 0, cmax = this.map[idx.row].length; cidx < cmax; cidx++) {
|
7792
8118
|
c = this.map[idx.row][cidx];
|
7793
8119
|
if (c.isReal) {
|
7794
|
-
r = api.getParentElement(c.el, {
|
8120
|
+
r = api.getParentElement(c.el, { query: "tr" });
|
7795
8121
|
if (r) {
|
7796
8122
|
return r;
|
7797
8123
|
}
|
@@ -7799,7 +8125,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
7799
8125
|
}
|
7800
8126
|
|
7801
8127
|
if (r === null && force) {
|
7802
|
-
r = api.getParentElement(this.map[idx.row][idx.col].el, {
|
8128
|
+
r = api.getParentElement(this.map[idx.row][idx.col].el, { query: "tr" }) || null;
|
7803
8129
|
}
|
7804
8130
|
|
7805
8131
|
return r;
|
@@ -7819,7 +8145,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
7819
8145
|
} else {
|
7820
8146
|
var rr = this.table.ownerDocument.createElement('tr');
|
7821
8147
|
rr.appendChild(new_cells);
|
7822
|
-
insertAfter(api.getParentElement(c.el, {
|
8148
|
+
insertAfter(api.getParentElement(c.el, { query: "tr" }), rr);
|
7823
8149
|
}
|
7824
8150
|
},
|
7825
8151
|
|
@@ -8091,7 +8417,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
8091
8417
|
|
8092
8418
|
// Removes the row of selected cell
|
8093
8419
|
removeRow: function() {
|
8094
|
-
var oldRow = api.getParentElement(this.cell, {
|
8420
|
+
var oldRow = api.getParentElement(this.cell, { query: "tr" });
|
8095
8421
|
if (oldRow) {
|
8096
8422
|
this.setTableMap();
|
8097
8423
|
this.idx = this.getMapIndex(this.cell);
|
@@ -8173,7 +8499,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
8173
8499
|
insertAfter(this.getRealRowEl(true), newRow);
|
8174
8500
|
break;
|
8175
8501
|
case 'above':
|
8176
|
-
var cr = api.getParentElement(this.map[this.idx.row][this.idx.col].el, {
|
8502
|
+
var cr = api.getParentElement(this.map[this.idx.row][this.idx.col].el, { query: "tr" });
|
8177
8503
|
if (cr) {
|
8178
8504
|
cr.parentNode.insertBefore(newRow, cr);
|
8179
8505
|
}
|
@@ -8272,7 +8598,7 @@ wysihtml5.dom.isLoadedImage = function (node) {
|
|
8272
8598
|
|
8273
8599
|
handleCellAddWithRowspan: function (cell, ridx, where) {
|
8274
8600
|
var addRowsNr = parseInt(api.getAttribute(this.cell, 'rowspan'), 10) - 1,
|
8275
|
-
crow = api.getParentElement(cell.el, {
|
8601
|
+
crow = api.getParentElement(cell.el, { query: "tr" }),
|
8276
8602
|
cType = cell.el.tagName.toLowerCase(),
|
8277
8603
|
cidx, temp_r_cells,
|
8278
8604
|
doc = this.table.ownerDocument,
|
@@ -8452,13 +8778,22 @@ wysihtml5.dom.query = function(elements, query) {
|
|
8452
8778
|
};
|
8453
8779
|
}
|
8454
8780
|
})();
|
8455
|
-
|
8781
|
+
;/* Unwraps element and returns list of childNodes that the node contained.
|
8782
|
+
*
|
8783
|
+
* Example:
|
8784
|
+
* var childnodes = wysihtml5.dom.unwrap(document.querySelector('.unwrap-me'));
|
8785
|
+
*/
|
8786
|
+
|
8787
|
+
wysihtml5.dom.unwrap = function(node) {
|
8788
|
+
var children = [];
|
8456
8789
|
if (node.parentNode) {
|
8457
8790
|
while (node.lastChild) {
|
8791
|
+
children.unshift(node.lastChild);
|
8458
8792
|
wysihtml5.dom.insert(node.lastChild).after(node);
|
8459
8793
|
}
|
8460
8794
|
node.parentNode.removeChild(node);
|
8461
8795
|
}
|
8796
|
+
return children;
|
8462
8797
|
};;/*
|
8463
8798
|
* Methods for fetching pasted html before it gets inserted into content
|
8464
8799
|
**/
|
@@ -8499,6 +8834,11 @@ wysihtml5.dom.getPastedHtmlWithDiv = function (composer, f) {
|
|
8499
8834
|
f(cleanerDiv.innerHTML);
|
8500
8835
|
cleanerDiv.parentNode.removeChild(cleanerDiv);
|
8501
8836
|
}, 0);
|
8837
|
+
};;wysihtml5.dom.removeInvisibleSpaces = function(node) {
|
8838
|
+
var textNodes = wysihtml5.dom.getTextNodes(node);
|
8839
|
+
for (var n = textNodes.length; n--;) {
|
8840
|
+
textNodes[n].nodeValue = textNodes[n].nodeValue.replace(wysihtml5.INVISIBLE_SPACE_REG_EXP, "");
|
8841
|
+
}
|
8502
8842
|
};;/**
|
8503
8843
|
* Fix most common html formatting misbehaviors of browsers implementation when inserting
|
8504
8844
|
* content via copy & paste contentEditable
|
@@ -8668,7 +9008,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8668
9008
|
function init () {
|
8669
9009
|
|
8670
9010
|
dom.observe(editable, "mousedown", function(event) {
|
8671
|
-
var target = wysihtml5.dom.getParentElement(event.target, {
|
9011
|
+
var target = wysihtml5.dom.getParentElement(event.target, { query: "td, th" });
|
8672
9012
|
if (target) {
|
8673
9013
|
handleSelectionMousedown(target);
|
8674
9014
|
}
|
@@ -8681,7 +9021,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8681
9021
|
select.start = target;
|
8682
9022
|
select.end = target;
|
8683
9023
|
select.cells = [target];
|
8684
|
-
select.table = dom.getParentElement(select.start, {
|
9024
|
+
select.table = dom.getParentElement(select.start, { query: "table" });
|
8685
9025
|
|
8686
9026
|
if (select.table) {
|
8687
9027
|
removeCellSelections();
|
@@ -8712,11 +9052,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8712
9052
|
|
8713
9053
|
function handleMouseMove (event) {
|
8714
9054
|
var curTable = null,
|
8715
|
-
cell = dom.getParentElement(event.target, { nodeName:
|
9055
|
+
cell = dom.getParentElement(event.target, { nodeName: "td, th" }),
|
8716
9056
|
oldEnd;
|
8717
9057
|
|
8718
9058
|
if (cell && select.table && select.start) {
|
8719
|
-
curTable = dom.getParentElement(cell, {
|
9059
|
+
curTable = dom.getParentElement(cell, { query: "table" });
|
8720
9060
|
if (curTable && curTable === select.table) {
|
8721
9061
|
removeCellSelections();
|
8722
9062
|
oldEnd = select.end;
|
@@ -8745,7 +9085,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8745
9085
|
function bindSideclick () {
|
8746
9086
|
var sideClickHandler = dom.observe(editable.ownerDocument, "click", function(event) {
|
8747
9087
|
sideClickHandler.stop();
|
8748
|
-
if (dom.getParentElement(event.target, {
|
9088
|
+
if (dom.getParentElement(event.target, { query: "table" }) != select.table) {
|
8749
9089
|
removeCellSelections();
|
8750
9090
|
select.table = null;
|
8751
9091
|
select.start = null;
|
@@ -8758,7 +9098,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8758
9098
|
function selectCells (start, end) {
|
8759
9099
|
select.start = start;
|
8760
9100
|
select.end = end;
|
8761
|
-
select.table = dom.getParentElement(select.start, {
|
9101
|
+
select.table = dom.getParentElement(select.start, { query: "table" });
|
8762
9102
|
selectedCells = dom.table.getCellsBetween(select.start, select.end);
|
8763
9103
|
addSelections(selectedCells);
|
8764
9104
|
bindSideclick();
|
@@ -8960,7 +9300,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
8960
9300
|
|
8961
9301
|
// Constructs a self removing whitespace (ain absolute positioned span) for placing selection caret when normal methods fail.
|
8962
9302
|
// Webkit has an issue with placing caret into places where there are no textnodes near by.
|
8963
|
-
|
9303
|
+
createTemporaryCaretSpaceAfter: function (node) {
|
8964
9304
|
var caretPlaceholder = this.doc.createElement('span'),
|
8965
9305
|
caretPlaceholderText = this.doc.createTextNode(wysihtml5.INVISIBLE_SPACE),
|
8966
9306
|
placeholderRemover = (function(event) {
|
@@ -9030,7 +9370,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9030
9370
|
* @example
|
9031
9371
|
* selection.setBefore(myElement);
|
9032
9372
|
*/
|
9033
|
-
setAfter: function(node) {
|
9373
|
+
setAfter: function(node, notVisual) {
|
9034
9374
|
var range = rangy.createRange(this.doc),
|
9035
9375
|
originalScrollTop = this.doc.documentElement.scrollTop || this.doc.body.scrollTop || this.doc.defaultView.pageYOffset,
|
9036
9376
|
originalScrollLeft = this.doc.documentElement.scrollLeft || this.doc.body.scrollLeft || this.doc.defaultView.pageXOffset,
|
@@ -9045,7 +9385,20 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9045
9385
|
// Webkit fails to add selection if there are no textnodes in that region
|
9046
9386
|
// (like an uneditable container at the end of content).
|
9047
9387
|
if (!sel) {
|
9048
|
-
|
9388
|
+
if (notVisual) {
|
9389
|
+
// If setAfter is used as internal between actions, self-removing caretPlaceholder has simpler implementation
|
9390
|
+
// and remove itself in call stack end instead on user interaction
|
9391
|
+
var caretPlaceholder = this.doc.createTextNode(wysihtml5.INVISIBLE_SPACE);
|
9392
|
+
node.parentNode.insertBefore(caretPlaceholder, node.nextSibling);
|
9393
|
+
this.selectNode(caretPlaceholder);
|
9394
|
+
setTimeout(function() {
|
9395
|
+
if (caretPlaceholder && caretPlaceholder.parentNode) {
|
9396
|
+
caretPlaceholder.parentNode.removeChild(caretPlaceholder);
|
9397
|
+
}
|
9398
|
+
}, 0);
|
9399
|
+
} else {
|
9400
|
+
this.createTemporaryCaretSpaceAfter(node);
|
9401
|
+
}
|
9049
9402
|
}
|
9050
9403
|
return sel;
|
9051
9404
|
},
|
@@ -9070,7 +9423,6 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9070
9423
|
// Make sure that caret is visible in node by inserting a zero width no breaking space
|
9071
9424
|
try { node.innerHTML = wysihtml5.INVISIBLE_SPACE; } catch(e) {}
|
9072
9425
|
}
|
9073
|
-
|
9074
9426
|
if (canHaveHTML) {
|
9075
9427
|
range.selectNodeContents(node);
|
9076
9428
|
} else {
|
@@ -9144,6 +9496,19 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9144
9496
|
return nodes;
|
9145
9497
|
},
|
9146
9498
|
|
9499
|
+
filterElements: function(filter) {
|
9500
|
+
var ranges = this.getOwnRanges(),
|
9501
|
+
nodes = [], curNodes;
|
9502
|
+
|
9503
|
+
for (var i = 0, maxi = ranges.length; i < maxi; i++) {
|
9504
|
+
curNodes = ranges[i].getNodes([1], function(element){
|
9505
|
+
return filter(element, ranges[i]);
|
9506
|
+
});
|
9507
|
+
nodes = nodes.concat(curNodes);
|
9508
|
+
}
|
9509
|
+
return nodes;
|
9510
|
+
},
|
9511
|
+
|
9147
9512
|
containsUneditable: function() {
|
9148
9513
|
var uneditables = this.getOwnUneditables(),
|
9149
9514
|
selection = this.getSelection();
|
@@ -9164,10 +9529,10 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9164
9529
|
startParent, endParent, uneditables, ev;
|
9165
9530
|
|
9166
9531
|
if (this.unselectableClass) {
|
9167
|
-
if ((startParent = wysihtml5.dom.getParentElement(range.startContainer, {
|
9532
|
+
if ((startParent = wysihtml5.dom.getParentElement(range.startContainer, { query: "." + this.unselectableClass }, false, this.contain))) {
|
9168
9533
|
range.setStartBefore(startParent);
|
9169
9534
|
}
|
9170
|
-
if ((endParent = wysihtml5.dom.getParentElement(range.endContainer, {
|
9535
|
+
if ((endParent = wysihtml5.dom.getParentElement(range.endContainer, { query: "." + this.unselectableClass }, false, this.contain))) {
|
9171
9536
|
range.setEndAfter(endParent);
|
9172
9537
|
}
|
9173
9538
|
|
@@ -9237,7 +9602,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9237
9602
|
curEl, parents = [];
|
9238
9603
|
|
9239
9604
|
for (var i = 0, maxi = nodes.length; i < maxi; i++) {
|
9240
|
-
curEl = (nodes[i].nodeName && nodes[i].nodeName === 'LI') ? nodes[i] : wysihtml5.dom.getParentElement(nodes[i], {
|
9605
|
+
curEl = (nodes[i].nodeName && nodes[i].nodeName === 'LI') ? nodes[i] : wysihtml5.dom.getParentElement(nodes[i], { query: 'li'}, false, this.contain);
|
9241
9606
|
if (curEl) {
|
9242
9607
|
parents.push(curEl);
|
9243
9608
|
}
|
@@ -9289,7 +9654,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9289
9654
|
node = selection.anchorNode,
|
9290
9655
|
offset = selection.anchorOffset;
|
9291
9656
|
if (ofNode && node) {
|
9292
|
-
return (offset === 0 && (node.nodeName && node.nodeName === ofNode.toUpperCase() || wysihtml5.dom.getParentElement(node.parentNode, {
|
9657
|
+
return (offset === 0 && (node.nodeName && node.nodeName === ofNode.toUpperCase() || wysihtml5.dom.getParentElement(node.parentNode, { query: ofNode }, 1)));
|
9293
9658
|
} else if (node) {
|
9294
9659
|
return (offset === 0 && !this.getPreviousNode(node, true));
|
9295
9660
|
}
|
@@ -9480,6 +9845,33 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9480
9845
|
}
|
9481
9846
|
},
|
9482
9847
|
|
9848
|
+
splitElementAtCaret: function (element, insertNode) {
|
9849
|
+
var sel = this.getSelection(),
|
9850
|
+
range, contentAfterRangeStart,
|
9851
|
+
firstChild, lastChild;
|
9852
|
+
|
9853
|
+
if (sel.rangeCount > 0) {
|
9854
|
+
range = sel.getRangeAt(0).cloneRange(); // Create a copy of the selection range to work with
|
9855
|
+
|
9856
|
+
range.setEndAfter(element); // Place the end of the range after the element
|
9857
|
+
contentAfterRangeStart = range.extractContents(); // Extract the contents of the element after the caret into a fragment
|
9858
|
+
|
9859
|
+
element.parentNode.insertBefore(contentAfterRangeStart, element.nextSibling);
|
9860
|
+
|
9861
|
+
firstChild = insertNode.firstChild;
|
9862
|
+
lastChild = insertNode.lastChild;
|
9863
|
+
|
9864
|
+
element.parentNode.insertBefore(insertNode, element.nextSibling);
|
9865
|
+
|
9866
|
+
// Select inserted node contents
|
9867
|
+
if (firstChild && lastChild) {
|
9868
|
+
range.setStartBefore(firstChild);
|
9869
|
+
range.setEndAfter(lastChild);
|
9870
|
+
this.setSelection(range);
|
9871
|
+
}
|
9872
|
+
}
|
9873
|
+
},
|
9874
|
+
|
9483
9875
|
/**
|
9484
9876
|
* Wraps current selection with the given node
|
9485
9877
|
*
|
@@ -9523,7 +9915,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9523
9915
|
|
9524
9916
|
tempElement.className = nodeOptions.className;
|
9525
9917
|
|
9526
|
-
this.composer.commands.exec("formatBlock", nodeOptions
|
9918
|
+
this.composer.commands.exec("formatBlock", nodeOptions);
|
9527
9919
|
tempDivElements = this.contain.querySelectorAll("." + nodeOptions.className);
|
9528
9920
|
if (tempDivElements[0]) {
|
9529
9921
|
tempDivElements[0].parentNode.insertBefore(tempElement, tempDivElements[0]);
|
@@ -9674,7 +10066,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9674
10066
|
getNodes: function(nodeType, filter) {
|
9675
10067
|
var range = this.getRange();
|
9676
10068
|
if (range) {
|
9677
|
-
return range.getNodes([nodeType], filter);
|
10069
|
+
return range.getNodes(Array.isArray(nodeType) ? nodeType : [nodeType], filter);
|
9678
10070
|
} else {
|
9679
10071
|
return [];
|
9680
10072
|
}
|
@@ -10706,19 +11098,31 @@ wysihtml5.Commands = Base.extend(
|
|
10706
11098
|
exec: function(composer, command, value) {
|
10707
11099
|
var anchors = this.state(composer, command);
|
10708
11100
|
if (anchors) {
|
11101
|
+
// remove <a> tag if there's no attributes provided.
|
11102
|
+
if ((!value || !value.href) && anchors.length !== null && anchors.length !== undefined && anchors.length > 0)
|
11103
|
+
{
|
11104
|
+
for(var i=0; i < anchors.length; i++)
|
11105
|
+
{
|
11106
|
+
wysihtml5.dom.unwrap(anchors[i]);
|
11107
|
+
}
|
11108
|
+
return;
|
11109
|
+
}
|
11110
|
+
|
10709
11111
|
// Selection contains links then change attributes of these links
|
10710
11112
|
composer.selection.executeAndRestore(function() {
|
10711
11113
|
_changeLinks(composer, anchors, value);
|
10712
11114
|
});
|
10713
11115
|
} else {
|
10714
11116
|
// Create links
|
10715
|
-
|
10716
|
-
|
11117
|
+
if (value && value.href) {
|
11118
|
+
value = typeof(value) === "object" ? value : { href: value };
|
11119
|
+
_format(composer, value);
|
11120
|
+
}
|
10717
11121
|
}
|
10718
11122
|
},
|
10719
11123
|
|
10720
11124
|
state: function(composer, command) {
|
10721
|
-
return wysihtml5.commands.formatInline.state(composer, command, "
|
11125
|
+
return wysihtml5.commands.formatInline.state(composer, command, "a");
|
10722
11126
|
}
|
10723
11127
|
};
|
10724
11128
|
})(wysihtml5);
|
@@ -10733,7 +11137,7 @@ wysihtml5.Commands = Base.extend(
|
|
10733
11137
|
textContent;
|
10734
11138
|
for (; i<length; i++) {
|
10735
11139
|
anchor = anchors[i];
|
10736
|
-
codeElement = dom.getParentElement(anchor, {
|
11140
|
+
codeElement = dom.getParentElement(anchor, { query: "code" });
|
10737
11141
|
textContent = dom.getTextContent(anchor);
|
10738
11142
|
|
10739
11143
|
// if <a> contains url-like text content, rename it to <code> to prevent re-autolinking
|
@@ -10931,224 +11335,368 @@ wysihtml5.Commands = Base.extend(
|
|
10931
11335
|
|
10932
11336
|
};
|
10933
11337
|
})(wysihtml5);
|
10934
|
-
|
10935
|
-
|
10936
|
-
|
10937
|
-
|
11338
|
+
;/* Formatblock
|
11339
|
+
* Is used to insert block level elements
|
11340
|
+
* It tries to solve the case that some block elements should not contain other block level elements (h1-6, p, ...)
|
11341
|
+
*
|
11342
|
+
*/
|
11343
|
+
(function(wysihtml5) {
|
11344
|
+
|
11345
|
+
var dom = wysihtml5.dom,
|
11346
|
+
// When the caret is within a H1 and the H4 is invoked, the H1 should turn into H4
|
10938
11347
|
// instead of creating a H4 within a H1 which would result in semantically invalid html
|
10939
|
-
|
11348
|
+
UNNESTABLE_BLOCK_ELEMENTS = "h1, h2, h3, h4, h5, h6, p, pre";
|
11349
|
+
BLOCK_ELEMENTS = "h1, h2, h3, h4, h5, h6, p, pre, div, blockquote";
|
10940
11350
|
|
10941
|
-
|
10942
|
-
|
10943
|
-
|
10944
|
-
|
10945
|
-
|
10946
|
-
|
10947
|
-
|
10948
|
-
|
10949
|
-
|
10950
|
-
|
11351
|
+
// Removes empty block level elements
|
11352
|
+
function cleanup(composer) {
|
11353
|
+
var container = composer.element,
|
11354
|
+
allElements = container.querySelectorAll(BLOCK_ELEMENTS),
|
11355
|
+
uneditables = container.querySelectorAll(composer.config.uneditableContainerClassname),
|
11356
|
+
elements = wysihtml5.lang.array(allElements).without(uneditables);
|
11357
|
+
|
11358
|
+
for (var i = elements.length; i--;) {
|
11359
|
+
if (elements[i].innerHTML === "") {
|
11360
|
+
elements[i].parentNode.removeChild(elements[i]);
|
11361
|
+
}
|
10951
11362
|
}
|
10952
11363
|
}
|
10953
11364
|
|
10954
|
-
function
|
10955
|
-
|
10956
|
-
|
10957
|
-
|
10958
|
-
|
10959
|
-
|
11365
|
+
function defaultNodeName(composer) {
|
11366
|
+
return composer.config.useLineBreaks ? "DIV" : "P";
|
11367
|
+
}
|
11368
|
+
|
11369
|
+
// The outermost un-nestable block element parent of from node
|
11370
|
+
function findOuterBlock(node, container, allBlocks) {
|
11371
|
+
var n = node,
|
11372
|
+
block = null;
|
11373
|
+
|
11374
|
+
while (n && container && n !== container) {
|
11375
|
+
if (n.nodeType === 1 && n.matches(allBlocks ? BLOCK_ELEMENTS : UNNESTABLE_BLOCK_ELEMENTS)) {
|
11376
|
+
block = n;
|
11377
|
+
}
|
11378
|
+
n = n.parentNode;
|
10960
11379
|
}
|
11380
|
+
|
11381
|
+
return block;
|
10961
11382
|
}
|
10962
11383
|
|
10963
|
-
|
10964
|
-
|
10965
|
-
|
10966
|
-
|
10967
|
-
|
11384
|
+
// Formats an element according to options nodeName, className, styleProperty, styleValue
|
11385
|
+
// If element is not defined, creates new element
|
11386
|
+
// if opotions is null, remove format instead
|
11387
|
+
function applyOptionsToElement(element, options, composer) {
|
11388
|
+
|
11389
|
+
if (!element) {
|
11390
|
+
element = composer.doc.createElement(options.nodeName || defaultNodeName(composer));
|
11391
|
+
// Add invisible space as otherwise webkit cannot set selection or range to it correctly
|
11392
|
+
element.appendChild(composer.doc.createTextNode(wysihtml5.INVISIBLE_SPACE));
|
10968
11393
|
}
|
10969
|
-
|
11394
|
+
|
11395
|
+
if (options.nodeName && element.nodeName !== options.nodeName) {
|
11396
|
+
element = dom.renameElement(element, options.nodeName);
|
11397
|
+
}
|
11398
|
+
|
11399
|
+
// Remove similar classes before applying className
|
11400
|
+
if (options.classRegExp) {
|
11401
|
+
element.className = element.className.replace(options.classRegExp, "");
|
11402
|
+
}
|
11403
|
+
if (options.className) {
|
11404
|
+
element.classList.add(options.className);
|
11405
|
+
}
|
11406
|
+
|
11407
|
+
if (options.styleProperty && typeof options.styleValue !== "undefined") {
|
11408
|
+
element.style[wysihtml5.browser.fixStyleKey(options.styleProperty)] = options.styleValue;
|
11409
|
+
}
|
11410
|
+
|
11411
|
+
return element;
|
10970
11412
|
}
|
10971
11413
|
|
10972
|
-
|
10973
|
-
|
10974
|
-
|
10975
|
-
|
11414
|
+
// Unsets element properties by options
|
11415
|
+
// If nodename given and matches current element, element is unwrapped or converted to default node (depending on presence of class and style attributes)
|
11416
|
+
function removeOptionsFromElement(element, options, composer) {
|
11417
|
+
var style, classes;
|
11418
|
+
|
11419
|
+
if (options.styleProperty) {
|
11420
|
+
element.style[wysihtml5.browser.fixStyleKey(options.styleProperty)] = '';
|
11421
|
+
}
|
11422
|
+
if (options.className) {
|
11423
|
+
element.classList.remove(options.className);
|
11424
|
+
}
|
11425
|
+
|
11426
|
+
if (options.classRegExp) {
|
11427
|
+
element.className = element.className.replace(options.classRegExp, "");
|
11428
|
+
}
|
11429
|
+
|
11430
|
+
// Clean up blank class attribute
|
11431
|
+
if (element.getAttribute('class') !== null && element.getAttribute('class').trim() === "") {
|
11432
|
+
element.removeAttribute('class');
|
11433
|
+
}
|
11434
|
+
|
11435
|
+
if (options.nodeName && element.nodeName === options.nodeName) {
|
11436
|
+
style = element.getAttribute('style');
|
11437
|
+
if (!style || style.trim() === '') {
|
11438
|
+
dom.unwrap(element);
|
11439
|
+
} else {
|
11440
|
+
element = dom.renameElement(element, defaultNodeName(composer));
|
11441
|
+
}
|
11442
|
+
}
|
11443
|
+
|
11444
|
+
// Clean up blank style attribute
|
11445
|
+
if (element.getAttribute('style') !== null && element.getAttribute('style').trim() === "") {
|
10976
11446
|
element.removeAttribute('style');
|
10977
11447
|
}
|
10978
|
-
return ret;
|
10979
11448
|
}
|
10980
11449
|
|
10981
|
-
|
10982
|
-
|
10983
|
-
|
10984
|
-
|
11450
|
+
// Unwraps block level elements from inside content
|
11451
|
+
// Useful as not all block level elements can contain other block-levels
|
11452
|
+
function unwrapBlocksFromContent(element) {
|
11453
|
+
var contentBlocks = element.querySelectorAll(BLOCK_ELEMENTS) || []; // Find unnestable block elements in extracted contents
|
11454
|
+
|
11455
|
+
for (var i = contentBlocks.length; i--;) {
|
11456
|
+
if (!contentBlocks[i].nextSibling || contentBlocks[i].nextSibling.nodeType !== 1 || contentBlocks[i].nextSibling.nodeName !== 'BR') {
|
11457
|
+
if ((contentBlocks[i].innerHTML || contentBlocks[i].nodeValue).trim() !== "") {
|
11458
|
+
contentBlocks[i].parentNode.insertBefore(contentBlocks[i].ownerDocument.createElement('BR'), contentBlocks[i].nextSibling);
|
11459
|
+
}
|
11460
|
+
}
|
11461
|
+
wysihtml5.dom.unwrap(contentBlocks[i]);
|
10985
11462
|
}
|
10986
11463
|
}
|
10987
11464
|
|
10988
|
-
|
10989
|
-
|
10990
|
-
|
11465
|
+
// Fix ranges that visually cover whole block element to actually cover the block
|
11466
|
+
function fixRangeCoverage(range, composer) {
|
11467
|
+
var node;
|
10991
11468
|
|
10992
|
-
|
10993
|
-
|
10994
|
-
|
10995
|
-
|
10996
|
-
|
10997
|
-
|
10998
|
-
for (var i = ranges.length; i--;){
|
10999
|
-
composer.selection.getSelection().removeAllRanges();
|
11000
|
-
composer.selection.setSelection(ranges[i]);
|
11001
|
-
if (className) {
|
11002
|
-
var eventListener = dom.observe(doc, "DOMNodeInserted", function(event) {
|
11003
|
-
var target = event.target,
|
11004
|
-
displayStyle;
|
11005
|
-
if (target.nodeType !== wysihtml5.ELEMENT_NODE) {
|
11006
|
-
return;
|
11007
|
-
}
|
11008
|
-
displayStyle = dom.getStyle("display").from(target);
|
11009
|
-
if (displayStyle.substr(0, 6) !== "inline") {
|
11010
|
-
// Make sure that only block elements receive the given class
|
11011
|
-
target.className += " " + className;
|
11012
|
-
}
|
11013
|
-
});
|
11469
|
+
if (range.startContainer && range.startContainer.nodeType === 1 && range.startContainer === range.endContainer) {
|
11470
|
+
if (range.startContainer.firstChild === range.startContainer.lastChild && range.endOffset === 1) {
|
11471
|
+
if (range.startContainer !== composer.element) {
|
11472
|
+
range.setStartBefore(range.startContainer);
|
11473
|
+
range.setEndAfter(range.endContainer);
|
11474
|
+
}
|
11014
11475
|
}
|
11015
|
-
|
11476
|
+
return;
|
11477
|
+
}
|
11016
11478
|
|
11017
|
-
|
11018
|
-
|
11479
|
+
if (range.startContainer && range.startContainer.nodeType === 1 && range.endContainer.nodeType === 3) {
|
11480
|
+
if (range.startContainer.firstChild === range.endContainer && range.endOffset === 1) {
|
11481
|
+
if (range.startContainer !== composer.element) {
|
11482
|
+
range.setEndAfter(range.startContainer);
|
11483
|
+
}
|
11019
11484
|
}
|
11485
|
+
return;
|
11020
11486
|
}
|
11021
|
-
}
|
11022
11487
|
|
11023
|
-
|
11024
|
-
|
11025
|
-
composer.
|
11488
|
+
if (range.endContainer && range.endContainer.nodeType === 1 && range.startContainer.nodeType === 3) {
|
11489
|
+
if (range.endContainer.firstChild === range.startContainer && range.endOffset === 1) {
|
11490
|
+
if (range.endContainer !== composer.element) {
|
11491
|
+
range.setStartBefore(range.endContainer);
|
11492
|
+
}
|
11493
|
+
}
|
11494
|
+
return;
|
11026
11495
|
}
|
11027
11496
|
|
11028
|
-
var surroundedNodes = composer.selection.surround(options);
|
11029
|
-
for (var i = 0, imax = surroundedNodes.length; i < imax; i++) {
|
11030
|
-
wysihtml5.dom.lineBreaks(surroundedNodes[i]).remove();
|
11031
|
-
_removeLastChildIfLineBreak(surroundedNodes[i]);
|
11032
|
-
}
|
11033
11497
|
|
11034
|
-
|
11035
|
-
|
11498
|
+
if (range.startContainer && range.startContainer.nodeType === 3 && range.startContainer === range.endContainer && range.startContainer.parentNode) {
|
11499
|
+
if (range.startContainer.parentNode.firstChild === range.startContainer && range.endOffset == range.endContainer.length && range.startOffset === 0) {
|
11500
|
+
node = range.startContainer.parentNode;
|
11501
|
+
if (node !== composer.element) {
|
11502
|
+
range.setStartBefore(node);
|
11503
|
+
range.setEndAfter(node);
|
11504
|
+
}
|
11505
|
+
}
|
11506
|
+
return;
|
11507
|
+
}
|
11036
11508
|
}
|
11037
11509
|
|
11038
|
-
|
11039
|
-
|
11040
|
-
|
11510
|
+
// Wrap the range with a block level element
|
11511
|
+
// If element is one of unnestable block elements (ex: h2 inside h1), split nodes and insert between so nesting does not occur
|
11512
|
+
function wrapRangeWithElement(range, options, defaultName, composer) {
|
11513
|
+
var defaultOptions = (options) ? wysihtml5.lang.object(options).clone(true) : null;
|
11514
|
+
if (defaultOptions) {
|
11515
|
+
defaultOptions.nodeName = defaultOptions.nodeName || defaultName || defaultNodeName(composer);
|
11516
|
+
}
|
11517
|
+
fixRangeCoverage(range, composer);
|
11518
|
+
|
11519
|
+
var r = range.cloneRange(),
|
11520
|
+
rangeStartContainer = r.startContainer,
|
11521
|
+
content = r.extractContents(),
|
11522
|
+
fragment = composer.doc.createDocumentFragment(),
|
11523
|
+
splitAllBlocks = !defaultOptions || (defaultName === "BLOCKQUOTE" && defaultOptions.nodeName && defaultOptions.nodeName === "BLOCKQUOTE"),
|
11524
|
+
firstOuterBlock = findOuterBlock(rangeStartContainer, composer.element, splitAllBlocks), // The outermost un-nestable block element parent of selection start
|
11525
|
+
wrapper, blocks, children;
|
11526
|
+
|
11527
|
+
if (options && options.nodeName && options.nodeName === "BLOCKQUOTE") {
|
11528
|
+
var tmpEl = applyOptionsToElement(null, options, composer);
|
11529
|
+
tmpEl.appendChild(content);
|
11530
|
+
fragment.appendChild(tmpEl);
|
11531
|
+
blocks = [tmpEl];
|
11532
|
+
} else {
|
11041
11533
|
|
11042
|
-
|
11043
|
-
|
11044
|
-
|
11534
|
+
if (!content.firstChild) {
|
11535
|
+
fragment.appendChild(applyOptionsToElement(null, options, composer));
|
11536
|
+
} else {
|
11045
11537
|
|
11046
|
-
|
11047
|
-
|
11048
|
-
|
11049
|
-
|
11050
|
-
|
11051
|
-
|
11052
|
-
|
11053
|
-
|
11054
|
-
|
11055
|
-
|
11056
|
-
|
11057
|
-
|
11058
|
-
|
11059
|
-
|
11060
|
-
|
11061
|
-
|
11062
|
-
|
11063
|
-
|
11538
|
+
while(content.firstChild) {
|
11539
|
+
|
11540
|
+
if (content.firstChild.nodeType == 1 && content.firstChild.matches(BLOCK_ELEMENTS)) {
|
11541
|
+
|
11542
|
+
if (options) {
|
11543
|
+
// Escape(split) block formatting at caret
|
11544
|
+
applyOptionsToElement(content.firstChild, options, composer);
|
11545
|
+
if (content.firstChild.matches(UNNESTABLE_BLOCK_ELEMENTS)) {
|
11546
|
+
unwrapBlocksFromContent(content.firstChild);
|
11547
|
+
}
|
11548
|
+
fragment.appendChild(content.firstChild);
|
11549
|
+
|
11550
|
+
} else {
|
11551
|
+
// Split block formating and add new block to wrap caret
|
11552
|
+
unwrapBlocksFromContent(content.firstChild);
|
11553
|
+
children = wysihtml5.dom.unwrap(content.firstChild);
|
11554
|
+
for (var c = 0, cmax = children.length; c < cmax; c++) {
|
11555
|
+
fragment.appendChild(children[c]);
|
11556
|
+
}
|
11064
11557
|
|
11065
|
-
|
11066
|
-
|
11067
|
-
|
11558
|
+
if (fragment.childNodes.length > 0) {
|
11559
|
+
fragment.appendChild(composer.doc.createElement('BR'));
|
11560
|
+
}
|
11068
11561
|
}
|
11562
|
+
} else {
|
11069
11563
|
|
11070
|
-
|
11071
|
-
|
11072
|
-
|
11073
|
-
|
11074
|
-
|
11075
|
-
|
11076
|
-
|
11077
|
-
|
11564
|
+
if (options) {
|
11565
|
+
// Wrap subsequent non-block nodes inside new block element
|
11566
|
+
wrapper = applyOptionsToElement(null, defaultOptions, composer);
|
11567
|
+
while(content.firstChild && (content.firstChild.nodeType !== 1 || !content.firstChild.matches(BLOCK_ELEMENTS))) {
|
11568
|
+
if (content.firstChild.nodeType == 1 && wrapper.matches(UNNESTABLE_BLOCK_ELEMENTS)) {
|
11569
|
+
unwrapBlocksFromContent(content.firstChild);
|
11570
|
+
}
|
11571
|
+
wrapper.appendChild(content.firstChild);
|
11572
|
+
}
|
11573
|
+
fragment.appendChild(wrapper);
|
11574
|
+
|
11078
11575
|
} else {
|
11079
|
-
//
|
11080
|
-
|
11576
|
+
// Escape(split) block formatting at selection
|
11577
|
+
if (content.firstChild.nodeType == 1) {
|
11578
|
+
unwrapBlocksFromContent(content.firstChild);
|
11579
|
+
}
|
11580
|
+
fragment.appendChild(content.firstChild);
|
11081
11581
|
}
|
11582
|
+
|
11082
11583
|
}
|
11083
|
-
}
|
11584
|
+
}
|
11585
|
+
}
|
11084
11586
|
|
11085
|
-
|
11587
|
+
blocks = wysihtml5.lang.array(fragment.childNodes).get();
|
11588
|
+
}
|
11589
|
+
|
11590
|
+
if (firstOuterBlock) {
|
11591
|
+
// If selection starts inside un-nestable block, split-escape the unnestable point and insert node between
|
11592
|
+
composer.selection.splitElementAtCaret(firstOuterBlock, fragment);
|
11593
|
+
} else {
|
11594
|
+
// Otherwise just insert
|
11595
|
+
r.insertNode(fragment);
|
11596
|
+
}
|
11597
|
+
|
11598
|
+
return blocks;
|
11599
|
+
}
|
11600
|
+
|
11601
|
+
// Find closest block level element
|
11602
|
+
function getParentBlockNodeName(element, composer) {
|
11603
|
+
var parentNode = wysihtml5.dom.getParentElement(element, {
|
11604
|
+
query: BLOCK_ELEMENTS
|
11605
|
+
}, null, composer.element);
|
11606
|
+
|
11607
|
+
return (parentNode) ? parentNode.nodeName : null;
|
11608
|
+
}
|
11609
|
+
|
11610
|
+
wysihtml5.commands.formatBlock = {
|
11611
|
+
exec: function(composer, command, options) {
|
11612
|
+
var newBlockElements = [],
|
11613
|
+
placeholder, ranges, range, parent, bookmark, state;
|
11614
|
+
|
11615
|
+
// If properties is passed as a string, look for tag with that tagName/query
|
11616
|
+
if (typeof options === "string") {
|
11617
|
+
options = {
|
11618
|
+
nodeName: options.toUpperCase()
|
11619
|
+
};
|
11086
11620
|
}
|
11087
11621
|
|
11088
|
-
//
|
11089
|
-
if (
|
11090
|
-
|
11091
|
-
|
11092
|
-
|
11093
|
-
|
11094
|
-
|
11095
|
-
});
|
11096
|
-
if (blockElement == composer.element) {
|
11097
|
-
blockElement = null;
|
11098
|
-
}
|
11099
|
-
if (blockElement) {
|
11100
|
-
// Rename current block element to new block element and add class
|
11101
|
-
if (nodeName) {
|
11102
|
-
blockElement = dom.renameElement(blockElement, nodeName);
|
11103
|
-
}
|
11104
|
-
if (className) {
|
11105
|
-
_addClass(blockElement, className, classRegExp);
|
11106
|
-
}
|
11107
|
-
if (cssStyle) {
|
11108
|
-
_addStyle(blockElement, cssStyle, styleRegExp);
|
11109
|
-
}
|
11110
|
-
blockRenameFound = true;
|
11111
|
-
}
|
11622
|
+
// Remove state if toggle set and state on and selection is collapsed
|
11623
|
+
if (options && options.toggle) {
|
11624
|
+
state = this.state(composer, command, options);
|
11625
|
+
if (state) {
|
11626
|
+
bookmark = rangy.saveSelection(composer.doc.defaultView || composer.doc.parentWindow);
|
11627
|
+
for (var j in state) {
|
11628
|
+
removeOptionsFromElement(state[j], options, composer);
|
11112
11629
|
}
|
11630
|
+
}
|
11631
|
+
}
|
11113
11632
|
|
11114
|
-
|
11633
|
+
// Otherwise expand selection so it will cover closest block if option caretSelectsBlock is true and selection is collapsed
|
11634
|
+
if (!state) {
|
11115
11635
|
|
11116
|
-
if (
|
11117
|
-
|
11636
|
+
if (composer.selection.isCollapsed()) {
|
11637
|
+
parent = wysihtml5.dom.getParentElement(composer.selection.getOwnRanges()[0].startContainer, {
|
11638
|
+
query: BLOCK_ELEMENTS
|
11639
|
+
}, null, composer.element);
|
11640
|
+
if (parent) {
|
11641
|
+
bookmark = rangy.saveSelection(composer.doc.defaultView || composer.doc.parentWindow);
|
11642
|
+
range = composer.selection.createRange();
|
11643
|
+
range.selectNode(parent);
|
11644
|
+
composer.selection.setSelection(range);
|
11645
|
+
} else if (!composer.isEmpty()) {
|
11646
|
+
bookmark = rangy.saveSelection(composer.doc.defaultView || composer.doc.parentWindow);
|
11647
|
+
composer.selection.selectLine();
|
11648
|
+
}
|
11118
11649
|
}
|
11650
|
+
|
11651
|
+
// And get all selection ranges of current composer and iterat
|
11652
|
+
ranges = composer.selection.getOwnRanges();
|
11653
|
+
for (var i = ranges.length; i--;) {
|
11654
|
+
newBlockElements = newBlockElements.concat(wrapRangeWithElement(ranges[i], options, getParentBlockNodeName(ranges[i].startContainer, composer), composer));
|
11655
|
+
}
|
11656
|
+
|
11119
11657
|
}
|
11120
11658
|
|
11121
|
-
|
11122
|
-
|
11123
|
-
|
11124
|
-
|
11125
|
-
|
11659
|
+
// Remove empty block elements that may be left behind
|
11660
|
+
cleanup(composer);
|
11661
|
+
// Restore correct selection
|
11662
|
+
if (bookmark) {
|
11663
|
+
rangy.restoreSelection(bookmark);
|
11664
|
+
} else {
|
11665
|
+
range = composer.selection.createRange();
|
11666
|
+
range.setStartBefore(newBlockElements[0]);
|
11667
|
+
range.setEndAfter(newBlockElements[newBlockElements.length - 1]);
|
11668
|
+
composer.selection.setSelection(range);
|
11669
|
+
}
|
11670
|
+
|
11671
|
+
wysihtml5.dom.removeInvisibleSpaces(composer.element);
|
11672
|
+
|
11126
11673
|
},
|
11127
11674
|
|
11128
|
-
|
11129
|
-
|
11130
|
-
|
11131
|
-
|
11675
|
+
// If properties as null is passed returns status describing all block level elements
|
11676
|
+
state: function(composer, command, properties) {
|
11677
|
+
|
11678
|
+
// If properties is passed as a string, look for tag with that tagName/query
|
11679
|
+
if (typeof properties === "string") {
|
11680
|
+
properties = {
|
11681
|
+
query: properties
|
11682
|
+
};
|
11683
|
+
}
|
11132
11684
|
|
11133
|
-
|
11685
|
+
var nodes = composer.selection.filterElements((function (element) { // Finds matching elements inside selection
|
11686
|
+
return wysihtml5.dom.domNode(element).test(properties || { query: BLOCK_ELEMENTS });
|
11687
|
+
}).bind(this)),
|
11688
|
+
parentNodes = composer.selection.getSelectedOwnNodes(),
|
11689
|
+
parent;
|
11134
11690
|
|
11135
|
-
//
|
11136
|
-
for (var i = 0, maxi =
|
11137
|
-
parent = dom.getParentElement(
|
11138
|
-
|
11139
|
-
|
11140
|
-
classRegExp: classRegExp,
|
11141
|
-
cssStyle: cssStyle,
|
11142
|
-
styleRegExp: styleRegExp
|
11143
|
-
});
|
11144
|
-
if (parent && wysihtml5.lang.array(parents).indexOf(parent) == -1) {
|
11145
|
-
parents.push(parent);
|
11691
|
+
// Finds matching elements that are parents of selection and adds to nodes list
|
11692
|
+
for (var i = 0, maxi = parentNodes.length; i < maxi; i++) {
|
11693
|
+
parent = dom.getParentElement(parentNodes[i], properties || { query: BLOCK_ELEMENTS }, null, composer.element);
|
11694
|
+
if (parent && nodes.indexOf(parent) === -1) {
|
11695
|
+
nodes.push(parent);
|
11146
11696
|
}
|
11147
11697
|
}
|
11148
|
-
|
11149
|
-
|
11150
|
-
}
|
11151
|
-
return parents;
|
11698
|
+
|
11699
|
+
return (nodes.length === 0) ? false : nodes;
|
11152
11700
|
}
|
11153
11701
|
|
11154
11702
|
|
@@ -11200,7 +11748,7 @@ wysihtml5.commands.formatCode = {
|
|
11200
11748
|
selectedNode.firstChild && selectedNode.firstChild.nodeName && selectedNode.firstChild.nodeName == "CODE") {
|
11201
11749
|
return selectedNode;
|
11202
11750
|
} else {
|
11203
|
-
return wysihtml5.dom.getParentElement(selectedNode, {
|
11751
|
+
return wysihtml5.dom.getParentElement(selectedNode, { query: "pre code" });
|
11204
11752
|
}
|
11205
11753
|
}
|
11206
11754
|
};;/**
|
@@ -11355,42 +11903,23 @@ wysihtml5.commands.formatCode = {
|
|
11355
11903
|
})(wysihtml5);
|
11356
11904
|
;(function(wysihtml5) {
|
11357
11905
|
|
11906
|
+
var nodeOptions = {
|
11907
|
+
nodeName: "BLOCKQUOTE",
|
11908
|
+
toggle: true
|
11909
|
+
};
|
11910
|
+
|
11358
11911
|
wysihtml5.commands.insertBlockQuote = {
|
11359
11912
|
exec: function(composer, command) {
|
11360
|
-
|
11361
|
-
endToEndParent = composer.selection.isEndToEndInNode(['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P']),
|
11362
|
-
prevNode, nextNode;
|
11363
|
-
|
11364
|
-
composer.selection.executeAndRestore(function() {
|
11365
|
-
if (state) {
|
11366
|
-
if (composer.config.useLineBreaks) {
|
11367
|
-
wysihtml5.dom.lineBreaks(state).add();
|
11368
|
-
}
|
11369
|
-
wysihtml5.dom.unwrap(state);
|
11370
|
-
} else {
|
11371
|
-
if (composer.selection.isCollapsed()) {
|
11372
|
-
composer.selection.selectLine();
|
11373
|
-
}
|
11374
|
-
|
11375
|
-
if (endToEndParent) {
|
11376
|
-
var qouteEl = endToEndParent.ownerDocument.createElement('blockquote');
|
11377
|
-
wysihtml5.dom.insert(qouteEl).after(endToEndParent);
|
11378
|
-
qouteEl.appendChild(endToEndParent);
|
11379
|
-
} else {
|
11380
|
-
composer.selection.surround({nodeName: "blockquote"});
|
11381
|
-
}
|
11382
|
-
}
|
11383
|
-
});
|
11913
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11384
11914
|
},
|
11385
|
-
state: function(composer, command) {
|
11386
|
-
var selectedNode = composer.selection.getSelectedNode(),
|
11387
|
-
node = wysihtml5.dom.getParentElement(selectedNode, { nodeName: "BLOCKQUOTE" }, false, composer.element);
|
11388
11915
|
|
11389
|
-
|
11916
|
+
state: function(composer, command) {
|
11917
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11390
11918
|
}
|
11391
11919
|
};
|
11392
11920
|
|
11393
|
-
})(wysihtml5)
|
11921
|
+
})(wysihtml5);
|
11922
|
+
;wysihtml5.commands.insertHTML = {
|
11394
11923
|
exec: function(composer, command, html) {
|
11395
11924
|
if (composer.commands.support(command)) {
|
11396
11925
|
composer.doc.execCommand(command, false, html);
|
@@ -11425,8 +11954,8 @@ wysihtml5.commands.formatCode = {
|
|
11425
11954
|
textNode,
|
11426
11955
|
parent;
|
11427
11956
|
|
11428
|
-
|
11429
|
-
|
11957
|
+
// If image is selected and src ie empty, set the caret before it and delete the image
|
11958
|
+
if (image && !value.src) {
|
11430
11959
|
composer.selection.setBefore(image);
|
11431
11960
|
parent = image.parentNode;
|
11432
11961
|
parent.removeChild(image);
|
@@ -11443,6 +11972,17 @@ wysihtml5.commands.formatCode = {
|
|
11443
11972
|
return;
|
11444
11973
|
}
|
11445
11974
|
|
11975
|
+
// If image selected change attributes accordingly
|
11976
|
+
if (image) {
|
11977
|
+
for (var key in value) {
|
11978
|
+
if (value.hasOwnProperty(key)) {
|
11979
|
+
image.setAttribute(key === "className" ? "class" : key, value[key]);
|
11980
|
+
}
|
11981
|
+
}
|
11982
|
+
return;
|
11983
|
+
}
|
11984
|
+
|
11985
|
+
// Otherwise lets create the image
|
11446
11986
|
image = doc.createElement(NODE_NAME);
|
11447
11987
|
|
11448
11988
|
for (var i in value) {
|
@@ -11562,7 +12102,7 @@ wysihtml5.commands.formatCode = {
|
|
11562
12102
|
};
|
11563
12103
|
|
11564
12104
|
if (node) {
|
11565
|
-
var parentLi = wysihtml5.dom.getParentElement(node, {
|
12105
|
+
var parentLi = wysihtml5.dom.getParentElement(node, { query: "li" }),
|
11566
12106
|
otherNodeName = (nodeName === "UL") ? "OL" : "UL";
|
11567
12107
|
|
11568
12108
|
if (isNode(node, nodeName)) {
|
@@ -11712,102 +12252,133 @@ wysihtml5.commands.formatCode = {
|
|
11712
12252
|
}
|
11713
12253
|
};
|
11714
12254
|
;(function(wysihtml5) {
|
11715
|
-
|
11716
|
-
|
12255
|
+
|
12256
|
+
var nodeOptions = {
|
12257
|
+
className: "wysiwyg-text-align-center",
|
12258
|
+
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
12259
|
+
toggle: true
|
12260
|
+
};
|
11717
12261
|
|
11718
12262
|
wysihtml5.commands.justifyCenter = {
|
11719
12263
|
exec: function(composer, command) {
|
11720
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12264
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11721
12265
|
},
|
11722
12266
|
|
11723
12267
|
state: function(composer, command) {
|
11724
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12268
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11725
12269
|
}
|
11726
12270
|
};
|
12271
|
+
|
11727
12272
|
})(wysihtml5);
|
11728
12273
|
;(function(wysihtml5) {
|
11729
|
-
|
11730
|
-
|
12274
|
+
|
12275
|
+
var nodeOptions = {
|
12276
|
+
className: "wysiwyg-text-align-left",
|
12277
|
+
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
12278
|
+
toggle: true
|
12279
|
+
};
|
11731
12280
|
|
11732
12281
|
wysihtml5.commands.justifyLeft = {
|
11733
12282
|
exec: function(composer, command) {
|
11734
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12283
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11735
12284
|
},
|
11736
12285
|
|
11737
12286
|
state: function(composer, command) {
|
11738
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12287
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11739
12288
|
}
|
11740
12289
|
};
|
11741
12290
|
})(wysihtml5);
|
11742
12291
|
;(function(wysihtml5) {
|
11743
|
-
|
11744
|
-
|
12292
|
+
|
12293
|
+
var nodeOptions = {
|
12294
|
+
className: "wysiwyg-text-align-right",
|
12295
|
+
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
12296
|
+
toggle: true
|
12297
|
+
};
|
11745
12298
|
|
11746
12299
|
wysihtml5.commands.justifyRight = {
|
11747
12300
|
exec: function(composer, command) {
|
11748
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12301
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11749
12302
|
},
|
11750
12303
|
|
11751
12304
|
state: function(composer, command) {
|
11752
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12305
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11753
12306
|
}
|
11754
12307
|
};
|
11755
12308
|
})(wysihtml5);
|
11756
12309
|
;(function(wysihtml5) {
|
11757
|
-
|
11758
|
-
|
12310
|
+
|
12311
|
+
var nodeOptions = {
|
12312
|
+
className: "wysiwyg-text-align-justify",
|
12313
|
+
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
12314
|
+
toggle: true
|
12315
|
+
};
|
11759
12316
|
|
11760
12317
|
wysihtml5.commands.justifyFull = {
|
11761
12318
|
exec: function(composer, command) {
|
11762
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12319
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11763
12320
|
},
|
11764
12321
|
|
11765
12322
|
state: function(composer, command) {
|
11766
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12323
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11767
12324
|
}
|
11768
12325
|
};
|
11769
12326
|
})(wysihtml5);
|
11770
12327
|
;(function(wysihtml5) {
|
11771
|
-
|
11772
|
-
|
12328
|
+
|
12329
|
+
var nodeOptions = {
|
12330
|
+
styleProperty: "textAlign",
|
12331
|
+
styleValue: "right",
|
12332
|
+
toggle: true
|
12333
|
+
};
|
11773
12334
|
|
11774
12335
|
wysihtml5.commands.alignRightStyle = {
|
11775
12336
|
exec: function(composer, command) {
|
11776
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12337
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11777
12338
|
},
|
11778
12339
|
|
11779
12340
|
state: function(composer, command) {
|
11780
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12341
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11781
12342
|
}
|
11782
12343
|
};
|
11783
12344
|
})(wysihtml5);
|
11784
12345
|
;(function(wysihtml5) {
|
11785
|
-
|
11786
|
-
|
12346
|
+
|
12347
|
+
var nodeOptions = {
|
12348
|
+
styleProperty: "textAlign",
|
12349
|
+
styleValue: "left",
|
12350
|
+
toggle: true
|
12351
|
+
};
|
11787
12352
|
|
11788
12353
|
wysihtml5.commands.alignLeftStyle = {
|
11789
12354
|
exec: function(composer, command) {
|
11790
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12355
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11791
12356
|
},
|
11792
12357
|
|
11793
12358
|
state: function(composer, command) {
|
11794
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12359
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11795
12360
|
}
|
11796
12361
|
};
|
12362
|
+
|
11797
12363
|
})(wysihtml5);
|
11798
12364
|
;(function(wysihtml5) {
|
11799
|
-
|
11800
|
-
|
12365
|
+
|
12366
|
+
var nodeOptions = {
|
12367
|
+
styleProperty: "textAlign",
|
12368
|
+
styleValue: "center",
|
12369
|
+
toggle: true
|
12370
|
+
};
|
11801
12371
|
|
11802
12372
|
wysihtml5.commands.alignCenterStyle = {
|
11803
12373
|
exec: function(composer, command) {
|
11804
|
-
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock",
|
12374
|
+
return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
11805
12375
|
},
|
11806
12376
|
|
11807
12377
|
state: function(composer, command) {
|
11808
|
-
return wysihtml5.commands.formatBlock.state(composer, "formatBlock",
|
12378
|
+
return wysihtml5.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
11809
12379
|
}
|
11810
12380
|
};
|
12381
|
+
|
11811
12382
|
})(wysihtml5);
|
11812
12383
|
;wysihtml5.commands.redo = {
|
11813
12384
|
exec: function(composer) {
|
@@ -12025,8 +12596,8 @@ wysihtml5.commands.formatCode = {
|
|
12025
12596
|
if (listNode.tagName === 'OL' || listNode.tagName === 'UL') {
|
12026
12597
|
found = true;
|
12027
12598
|
|
12028
|
-
outerListNode = wysihtml5.dom.getParentElement(listNode.parentNode, {
|
12029
|
-
outerLiNode = wysihtml5.dom.getParentElement(listNode.parentNode, {
|
12599
|
+
outerListNode = wysihtml5.dom.getParentElement(listNode.parentNode, { query: 'ol, ul' }, false, composer.element);
|
12600
|
+
outerLiNode = wysihtml5.dom.getParentElement(listNode.parentNode, { query: 'li' }, false, composer.element);
|
12030
12601
|
|
12031
12602
|
if (outerListNode && outerLiNode) {
|
12032
12603
|
|
@@ -12648,7 +13219,7 @@ wysihtml5.views.View = Base.extend(
|
|
12648
13219
|
}
|
12649
13220
|
|
12650
13221
|
var selectedNode = that.selection.getSelectedNode(event.target.ownerDocument),
|
12651
|
-
link = dom.getParentElement(selectedNode, {
|
13222
|
+
link = dom.getParentElement(selectedNode, { query: "a" }, 4),
|
12652
13223
|
textContent;
|
12653
13224
|
|
12654
13225
|
if (!link) {
|
@@ -12713,11 +13284,11 @@ wysihtml5.views.View = Base.extend(
|
|
12713
13284
|
|
12714
13285
|
_initLineBreaking: function() {
|
12715
13286
|
var that = this,
|
12716
|
-
USE_NATIVE_LINE_BREAK_INSIDE_TAGS =
|
12717
|
-
LIST_TAGS =
|
13287
|
+
USE_NATIVE_LINE_BREAK_INSIDE_TAGS = "li, p, h1, h2, h3, h4, h5, h6",
|
13288
|
+
LIST_TAGS = "ul, ol, menu";
|
12718
13289
|
|
12719
13290
|
function adjust(selectedNode) {
|
12720
|
-
var parentElement = dom.getParentElement(selectedNode, {
|
13291
|
+
var parentElement = dom.getParentElement(selectedNode, { query: "p, div" }, 2);
|
12721
13292
|
if (parentElement && dom.contains(that.element, parentElement)) {
|
12722
13293
|
that.selection.executeAndRestore(function() {
|
12723
13294
|
if (that.config.useLineBreaks) {
|
@@ -12766,7 +13337,7 @@ wysihtml5.views.View = Base.extend(
|
|
12766
13337
|
if (keyCode !== wysihtml5.ENTER_KEY && keyCode !== wysihtml5.BACKSPACE_KEY) {
|
12767
13338
|
return;
|
12768
13339
|
}
|
12769
|
-
var blockElement = dom.getParentElement(that.selection.getSelectedNode(), {
|
13340
|
+
var blockElement = dom.getParentElement(that.selection.getSelectedNode(), { query: USE_NATIVE_LINE_BREAK_INSIDE_TAGS }, 4);
|
12770
13341
|
if (blockElement) {
|
12771
13342
|
setTimeout(function() {
|
12772
13343
|
// Unwrap paragraph after leaving a list or a H1-6
|
@@ -12778,7 +13349,7 @@ wysihtml5.views.View = Base.extend(
|
|
12778
13349
|
return;
|
12779
13350
|
}
|
12780
13351
|
|
12781
|
-
list = dom.getParentElement(selectedNode, {
|
13352
|
+
list = dom.getParentElement(selectedNode, { query: LIST_TAGS }, 2);
|
12782
13353
|
|
12783
13354
|
if (!list) {
|
12784
13355
|
adjust(selectedNode);
|
@@ -13038,46 +13609,12 @@ wysihtml5.views.View = Base.extend(
|
|
13038
13609
|
}
|
13039
13610
|
};
|
13040
13611
|
|
13041
|
-
var deleteAroundEditable = function(selection, uneditable, element) {
|
13042
|
-
// merge node with previous node from uneditable
|
13043
|
-
var prevNode = selection.getPreviousNode(uneditable, true),
|
13044
|
-
curNode = selection.getSelectedNode();
|
13045
|
-
|
13046
|
-
if (curNode.nodeType !== 1 && curNode.parentNode !== element) { curNode = curNode.parentNode; }
|
13047
|
-
if (prevNode) {
|
13048
|
-
if (curNode.nodeType == 1) {
|
13049
|
-
var first = curNode.firstChild;
|
13050
|
-
|
13051
|
-
if (prevNode.nodeType == 1) {
|
13052
|
-
while (curNode.firstChild) {
|
13053
|
-
prevNode.appendChild(curNode.firstChild);
|
13054
|
-
}
|
13055
|
-
} else {
|
13056
|
-
while (curNode.firstChild) {
|
13057
|
-
uneditable.parentNode.insertBefore(curNode.firstChild, uneditable);
|
13058
|
-
}
|
13059
|
-
}
|
13060
|
-
if (curNode.parentNode) {
|
13061
|
-
curNode.parentNode.removeChild(curNode);
|
13062
|
-
}
|
13063
|
-
selection.setBefore(first);
|
13064
|
-
} else {
|
13065
|
-
if (prevNode.nodeType == 1) {
|
13066
|
-
prevNode.appendChild(curNode);
|
13067
|
-
} else {
|
13068
|
-
uneditable.parentNode.insertBefore(curNode, uneditable);
|
13069
|
-
}
|
13070
|
-
selection.setBefore(curNode);
|
13071
|
-
}
|
13072
|
-
}
|
13073
|
-
};
|
13074
|
-
|
13075
13612
|
var handleDeleteKeyPress = function(event, composer) {
|
13076
13613
|
var selection = composer.selection,
|
13077
13614
|
element = composer.element;
|
13078
13615
|
|
13079
13616
|
if (selection.isCollapsed()) {
|
13080
|
-
if (selection.caretIsInTheBeginnig('
|
13617
|
+
if (selection.caretIsInTheBeginnig('li')) {
|
13081
13618
|
event.preventDefault();
|
13082
13619
|
composer.commands.exec('outdentList');
|
13083
13620
|
} else if (selection.caretIsInTheBeginnig()) {
|
@@ -13126,7 +13663,7 @@ wysihtml5.views.View = Base.extend(
|
|
13126
13663
|
var handleTabKeyDown = function(composer, element) {
|
13127
13664
|
if (!composer.selection.isCollapsed()) {
|
13128
13665
|
composer.selection.deleteContents();
|
13129
|
-
} else if (composer.selection.caretIsInTheBeginnig('
|
13666
|
+
} else if (composer.selection.caretIsInTheBeginnig('li')) {
|
13130
13667
|
if (composer.commands.exec('indentList')) return;
|
13131
13668
|
}
|
13132
13669
|
|
@@ -13238,7 +13775,7 @@ wysihtml5.views.View = Base.extend(
|
|
13238
13775
|
if (this.config.uneditableContainerClassname) {
|
13239
13776
|
// If uneditables is configured, makes clicking on uneditable move caret after clicked element (so it can be deleted like text)
|
13240
13777
|
// If uneditable needs text selection itself event.stopPropagation can be used to prevent this behaviour
|
13241
|
-
var uneditable = wysihtml5.dom.getParentElement(event.target, {
|
13778
|
+
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.uneditableContainerClassname }, false, this.element);
|
13242
13779
|
if (uneditable) {
|
13243
13780
|
this.selection.setAfter(uneditable);
|
13244
13781
|
}
|