wysihtml5x-rails 0.4.17 → 0.5.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a91d08305f9e4988813586289aab3aecd9de35d3
|
4
|
+
data.tar.gz: 073f79d4f0eb77987f9d6e7f0869dbcbb4d1b19f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6b1f8f01e075964d9b42ba38d8a0787d1b822973120824e7d1186a8d13c0e467869ac2f175b4fbf52fc9222cd1b2ec6451992ab4ce9e8b2ccd044ef36121345
|
7
|
+
data.tar.gz: 167c5ea2b1b989c3dc14887fde9bd4164004a917990aac2176b7a1ce1d959a993f67d67fad184f3dc36d65fbab9e1ce7df86170f970c568f2b8fb221f7346545
|
@@ -106,7 +106,8 @@ var wysihtml5ParserRules = {
|
|
106
106
|
* - src: allows something like "/foobar.jpg", "http://google.com", ...
|
107
107
|
* - href: allows something like "mailto:bert@foo.com", "http://google.com", "/foobar.jpg"
|
108
108
|
* - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML)
|
109
|
-
* - numbers:
|
109
|
+
* - numbers: ensures that the attribute only contains numeric (integer) characters (no float values or units)
|
110
|
+
* - dimension: for with/height attributes where floating point numbrs and percentages are allowed
|
110
111
|
* - any: allows anything to pass
|
111
112
|
*/
|
112
113
|
"tags": {
|
@@ -197,10 +198,10 @@ var wysihtml5ParserRules = {
|
|
197
198
|
},
|
198
199
|
"img": {
|
199
200
|
"check_attributes": {
|
200
|
-
"width": "
|
201
|
+
"width": "dimension",
|
201
202
|
"alt": "alt",
|
202
203
|
"src": "url", // if you compiled master manually then change this from 'url' to 'src'
|
203
|
-
"height": "
|
204
|
+
"height": "dimension"
|
204
205
|
},
|
205
206
|
"add_class": {
|
206
207
|
"align": "align_img"
|
@@ -184,7 +184,8 @@ var wysihtml5ParserRules = {
|
|
184
184
|
* - src: allows something like "/foobar.jpg", "http://google.com", ...
|
185
185
|
* - href: allows something like "mailto:bert@foo.com", "http://google.com", "/foobar.jpg"
|
186
186
|
* - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML)
|
187
|
-
* - numbers:
|
187
|
+
* - numbers: ensures that the attribute only contains numeric (integer) characters (no float values or units)
|
188
|
+
* - dimension: for with/height attributes where floating point numbrs and percentages are allowed
|
188
189
|
* - any: allows anything to pass
|
189
190
|
*/
|
190
191
|
"tags": {
|
@@ -278,10 +279,10 @@ var wysihtml5ParserRules = {
|
|
278
279
|
"valid_image_src": 1
|
279
280
|
},
|
280
281
|
"check_attributes": {
|
281
|
-
"width": "
|
282
|
+
"width": "dimension",
|
282
283
|
"alt": "alt",
|
283
284
|
"src": "src", // if you compiled master manually then change this from 'url' to 'src'
|
284
|
-
"height": "
|
285
|
+
"height": "dimension"
|
285
286
|
},
|
286
287
|
"add_class": {
|
287
288
|
"align": "align_img"
|
@@ -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
|
}
|
@@ -13851,11 +14388,7 @@ wysihtml5.views.View = Base.extend(
|
|
13851
14388
|
var that = this,
|
13852
14389
|
callbackWrapper = function(event) {
|
13853
14390
|
var attributes = that._serialize();
|
13854
|
-
|
13855
|
-
that.fire("edit", attributes);
|
13856
|
-
} else {
|
13857
|
-
that.fire("save", attributes);
|
13858
|
-
}
|
14391
|
+
that.fire("save", attributes);
|
13859
14392
|
that.hide();
|
13860
14393
|
event.preventDefault();
|
13861
14394
|
event.stopPropagation();
|
@@ -13903,7 +14436,7 @@ wysihtml5.views.View = Base.extend(
|
|
13903
14436
|
* then gets returned
|
13904
14437
|
*/
|
13905
14438
|
_serialize: function() {
|
13906
|
-
var data =
|
14439
|
+
var data = {},
|
13907
14440
|
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
13908
14441
|
length = fields.length,
|
13909
14442
|
i = 0;
|
@@ -14154,11 +14687,14 @@ wysihtml5.views.View = Base.extend(
|
|
14154
14687
|
group,
|
14155
14688
|
name,
|
14156
14689
|
value,
|
14157
|
-
dialog
|
14690
|
+
dialog,
|
14691
|
+
tracksBlankValue;
|
14692
|
+
|
14158
14693
|
for (; i<length; i++) {
|
14159
14694
|
link = links[i];
|
14160
14695
|
name = link.getAttribute("data-wysihtml5-" + type);
|
14161
14696
|
value = link.getAttribute("data-wysihtml5-" + type + "-value");
|
14697
|
+
tracksBlankValue = link.getAttribute("data-wysihtml5-" + type + "-blank-value");
|
14162
14698
|
group = this.container.querySelector("[data-wysihtml5-" + type + "-group='" + name + "']");
|
14163
14699
|
dialog = this._getDialog(link, name);
|
14164
14700
|
|
@@ -14167,6 +14703,7 @@ wysihtml5.views.View = Base.extend(
|
|
14167
14703
|
group: group,
|
14168
14704
|
name: name,
|
14169
14705
|
value: value,
|
14706
|
+
tracksBlankValue: tracksBlankValue,
|
14170
14707
|
dialog: dialog,
|
14171
14708
|
state: false
|
14172
14709
|
};
|
@@ -14327,8 +14864,9 @@ wysihtml5.views.View = Base.extend(
|
|
14327
14864
|
|
14328
14865
|
_updateLinkStates: function() {
|
14329
14866
|
|
14330
|
-
var commandMapping
|
14331
|
-
|
14867
|
+
var commandMapping = this.commandMapping,
|
14868
|
+
commandblankMapping = this.commandblankMapping,
|
14869
|
+
actionMapping = this.actionMapping,
|
14332
14870
|
i,
|
14333
14871
|
state,
|
14334
14872
|
action,
|
@@ -14352,39 +14890,47 @@ wysihtml5.views.View = Base.extend(
|
|
14352
14890
|
dom.removeClass(command.group, CLASS_NAME_COMMAND_DISABLED);
|
14353
14891
|
}
|
14354
14892
|
}
|
14355
|
-
if (command.state === state) {
|
14893
|
+
if (command.state === state && !command.tracksBlankValue) {
|
14356
14894
|
continue;
|
14357
14895
|
}
|
14358
14896
|
|
14359
14897
|
command.state = state;
|
14360
14898
|
if (state) {
|
14361
|
-
|
14362
|
-
|
14363
|
-
|
14364
|
-
|
14365
|
-
|
14366
|
-
|
14367
|
-
|
14368
|
-
|
14369
|
-
|
14370
|
-
|
14371
|
-
|
14372
|
-
|
14373
|
-
|
14374
|
-
|
14899
|
+
if (command.tracksBlankValue) {
|
14900
|
+
dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
14901
|
+
} else {
|
14902
|
+
dom.addClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
14903
|
+
if (command.group) {
|
14904
|
+
dom.addClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
14905
|
+
}
|
14906
|
+
if (command.dialog) {
|
14907
|
+
if (typeof(state) === "object" || wysihtml5.lang.object(state).isArray()) {
|
14908
|
+
|
14909
|
+
if (!command.dialog.multiselect && wysihtml5.lang.object(state).isArray()) {
|
14910
|
+
// Grab first and only object/element in state array, otherwise convert state into boolean
|
14911
|
+
// to avoid showing a dialog for multiple selected elements which may have different attributes
|
14912
|
+
// eg. when two links with different href are selected, the state will be an array consisting of both link elements
|
14913
|
+
// but the dialog interface can only update one
|
14914
|
+
state = state.length === 1 ? state[0] : true;
|
14915
|
+
command.state = state;
|
14916
|
+
}
|
14917
|
+
command.dialog.show(state);
|
14918
|
+
} else {
|
14919
|
+
command.dialog.hide();
|
14375
14920
|
}
|
14376
|
-
command.dialog.show(state);
|
14377
|
-
} else {
|
14378
|
-
command.dialog.hide();
|
14379
14921
|
}
|
14380
14922
|
}
|
14381
14923
|
} else {
|
14382
|
-
|
14383
|
-
|
14384
|
-
|
14385
|
-
|
14386
|
-
|
14387
|
-
|
14924
|
+
if (command.tracksBlankValue) {
|
14925
|
+
dom.addClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
14926
|
+
} else {
|
14927
|
+
dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
14928
|
+
if (command.group) {
|
14929
|
+
dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
14930
|
+
}
|
14931
|
+
if (command.dialog) {
|
14932
|
+
command.dialog.hide();
|
14933
|
+
}
|
14388
14934
|
}
|
14389
14935
|
}
|
14390
14936
|
}
|