wysihtml-rails 0.5.0.beta11 → 0.5.0.beta12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/wysihtml/rails/version.rb +1 -1
- data/vendor/assets/javascripts/wysihtml-toolbar.js +550 -255
- data/vendor/assets/javascripts/wysihtml.js +421 -170
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64171b06f3c46b4089c9c548bb95a507de396ea4
|
4
|
+
data.tar.gz: 7559f9afd8744d42fc5d180e8df237055b35dd5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c6f3f07ac3e718c699fd894e94812c6cc06da6f099c750bf4355d85f2c4e1b1c2484f035ffe663e11c7ddfb3c09fe0cbf78c60846dc34718f369535c7cc2de8
|
7
|
+
data.tar.gz: efecb729c9262b867e0dcc0b7aaa6b85f1470f0d51e145e03aa571d641df54f19f4b523d12fc6b4a5dfd644d2e585721476fc8ef3575778d0c412382bfbdb751
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license wysihtml v0.5.0-
|
2
|
+
* @license wysihtml v0.5.0-beta12
|
3
3
|
* https://github.com/Voog/wysihtml
|
4
4
|
*
|
5
5
|
* Author: Christopher Blum (https://github.com/tiff)
|
@@ -10,7 +10,7 @@
|
|
10
10
|
*
|
11
11
|
*/
|
12
12
|
var wysihtml5 = {
|
13
|
-
version: "0.5.0-
|
13
|
+
version: "0.5.0-beta12",
|
14
14
|
|
15
15
|
// namespaces
|
16
16
|
commands: {},
|
@@ -5890,6 +5890,20 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
5890
5890
|
})(wysihtml5);
|
5891
5891
|
;// TODO: Refactor dom tree traversing here
|
5892
5892
|
(function(wysihtml5) {
|
5893
|
+
|
5894
|
+
// Finds parents of a node, returning the outermost node first in Array
|
5895
|
+
// if contain node is given parents search is stopped at the container
|
5896
|
+
function parents(node, container) {
|
5897
|
+
var nodes = [node], n = node;
|
5898
|
+
|
5899
|
+
// iterate parents while parent exists and it is not container element
|
5900
|
+
while((container && n && n !== container) || (!container && n)) {
|
5901
|
+
nodes.unshift(n);
|
5902
|
+
n = n.parentNode;
|
5903
|
+
}
|
5904
|
+
return nodes;
|
5905
|
+
}
|
5906
|
+
|
5893
5907
|
wysihtml5.dom.domNode = function(node) {
|
5894
5908
|
var defaultNodeTypes = [wysihtml5.ELEMENT_NODE, wysihtml5.TEXT_NODE];
|
5895
5909
|
|
@@ -5951,6 +5965,30 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
|
5951
5965
|
return nextNode;
|
5952
5966
|
},
|
5953
5967
|
|
5968
|
+
// Finds the common acnestor container of two nodes
|
5969
|
+
// If container given stops search at the container
|
5970
|
+
// If no common ancestor found returns null
|
5971
|
+
// var node = wysihtml5.dom.domNode(element).commonAncestor(node2, container);
|
5972
|
+
commonAncestor: function(node2, container) {
|
5973
|
+
var parents1 = parents(node, container),
|
5974
|
+
parents2 = parents(node2, container);
|
5975
|
+
|
5976
|
+
// Ensure we have found a common ancestor, which will be the first one if anything
|
5977
|
+
if (parents1[0] != parents2[0]) {
|
5978
|
+
return null;
|
5979
|
+
}
|
5980
|
+
|
5981
|
+
// Traverse up the hierarchy of parents until we reach where they're no longer
|
5982
|
+
// the same. Then return previous which was the common ancestor.
|
5983
|
+
for (var i = 0; i < parents1.length; i++) {
|
5984
|
+
if (parents1[i] != parents2[i]) {
|
5985
|
+
return parents1[i - 1];
|
5986
|
+
}
|
5987
|
+
}
|
5988
|
+
|
5989
|
+
return null;
|
5990
|
+
},
|
5991
|
+
|
5954
5992
|
// Traverses a node for last children and their chidren (including itself), and finds the last node that has no children.
|
5955
5993
|
// Array of classes for forced last-leaves (ex: uneditable-container) can be defined (options = {leafClasses: [...]})
|
5956
5994
|
// Useful for finding the actually visible element before cursor
|
@@ -7443,9 +7481,10 @@ wysihtml5.dom.removeEmptyTextNodes = function(node) {
|
|
7443
7481
|
childNodes = wysihtml5.lang.array(node.childNodes).get(),
|
7444
7482
|
childNodesLength = childNodes.length,
|
7445
7483
|
i = 0;
|
7484
|
+
|
7446
7485
|
for (; i<childNodesLength; i++) {
|
7447
7486
|
childNode = childNodes[i];
|
7448
|
-
if (childNode.nodeType === wysihtml5.TEXT_NODE && childNode.data
|
7487
|
+
if (childNode.nodeType === wysihtml5.TEXT_NODE && (/^[\n\r]*$/).test(childNode.data)) {
|
7449
7488
|
childNode.parentNode.removeChild(childNode);
|
7450
7489
|
}
|
7451
7490
|
}
|
@@ -7913,7 +7952,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7913
7952
|
|
7914
7953
|
// initiates an allready existent contenteditable
|
7915
7954
|
_bindElement: function(contentEditable) {
|
7916
|
-
contentEditable.className =
|
7955
|
+
contentEditable.className = contentEditable.className ? contentEditable.className + " wysihtml5-sandbox" : "wysihtml5-sandbox";
|
7917
7956
|
this._loadElement(contentEditable, true);
|
7918
7957
|
return contentEditable;
|
7919
7958
|
},
|
@@ -9430,71 +9469,140 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9430
9469
|
|
9431
9470
|
};
|
9432
9471
|
;(function(wysihtml5) {
|
9433
|
-
|
9434
|
-
|
9435
|
-
|
9436
|
-
|
9472
|
+
|
9473
|
+
// List of supported color format parsing methods
|
9474
|
+
// If radix is not defined 10 is expected as default
|
9475
|
+
var colorParseMethods = {
|
9476
|
+
rgba : {
|
9477
|
+
regex: /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*([\d\.]+)\s*\)/i,
|
9478
|
+
name: "rgba"
|
9479
|
+
},
|
9480
|
+
rgb : {
|
9481
|
+
regex: /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/i,
|
9482
|
+
name: "rgb"
|
9483
|
+
},
|
9484
|
+
hex6 : {
|
9485
|
+
regex: /^#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])/i,
|
9486
|
+
name: "hex",
|
9487
|
+
radix: 16
|
9488
|
+
},
|
9489
|
+
hex3 : {
|
9490
|
+
regex: /^#([0-9a-f])([0-9a-f])([0-9a-f])/i,
|
9491
|
+
name: "hex",
|
9492
|
+
radix: 16
|
9493
|
+
}
|
9494
|
+
},
|
9495
|
+
// Takes a style key name as an argument and makes a regex that can be used to the match key:value pair from style string
|
9496
|
+
makeParamRegExp = function (p) {
|
9497
|
+
return new RegExp("(^|\\s|;)" + p + "\\s*:\\s*[^;$]+", "gi");
|
9498
|
+
};
|
9437
9499
|
|
9438
|
-
|
9439
|
-
|
9440
|
-
|
9500
|
+
// Takes color string value ("#abc", "rgb(1,2,3)", ...) as an argument and returns suitable parsing method for it
|
9501
|
+
function getColorParseMethod (colorStr) {
|
9502
|
+
var prop, colorTypeConf;
|
9503
|
+
|
9504
|
+
for (prop in colorParseMethods) {
|
9505
|
+
if (!colorParseMethods.hasOwnProperty(prop)) { continue; }
|
9506
|
+
|
9507
|
+
colorTypeConf = colorParseMethods[prop];
|
9508
|
+
|
9509
|
+
if (colorTypeConf.regex.test(colorStr)) {
|
9510
|
+
return colorTypeConf;
|
9511
|
+
}
|
9512
|
+
}
|
9513
|
+
}
|
9514
|
+
|
9515
|
+
// Takes color string value ("#abc", "rgb(1,2,3)", ...) as an argument and returns the type of that color format "hex", "rgb", "rgba".
|
9516
|
+
function getColorFormat (colorStr) {
|
9517
|
+
var type = getColorParseMethod(colorStr);
|
9441
9518
|
|
9519
|
+
return type ? type.name : undefined;
|
9520
|
+
}
|
9521
|
+
|
9522
|
+
// Public API functions for styleParser
|
9442
9523
|
wysihtml5.quirks.styleParser = {
|
9443
9524
|
|
9444
|
-
|
9445
|
-
|
9446
|
-
params = stylesStr.match(paramRegex),
|
9447
|
-
radix = 10,
|
9448
|
-
str, colorMatch;
|
9525
|
+
// Takes color string value as an argument and returns suitable parsing method for it
|
9526
|
+
getColorParseMethod : getColorParseMethod,
|
9449
9527
|
|
9450
|
-
|
9451
|
-
|
9452
|
-
|
9453
|
-
|
9454
|
-
|
9455
|
-
|
9456
|
-
|
9457
|
-
|
9458
|
-
|
9459
|
-
|
9460
|
-
|
9461
|
-
|
9462
|
-
|
9463
|
-
|
9464
|
-
|
9465
|
-
|
9466
|
-
|
9467
|
-
|
9468
|
-
return (idx < 3) ? (parseInt(d, 16) * 16) + parseInt(d, 16): parseFloat(d);
|
9469
|
-
});
|
9470
|
-
}
|
9528
|
+
// Takes color string value as an argument and returns the type of that color format "hex", "rgb", "rgba".
|
9529
|
+
getColorFormat : getColorFormat,
|
9530
|
+
|
9531
|
+
/* Parses a color string to and array of [red, green, blue, alpha].
|
9532
|
+
* paramName: optional argument to parse color value directly from style string parameter
|
9533
|
+
*
|
9534
|
+
* Examples:
|
9535
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("#ABC"); // [170, 187, 204, 1]
|
9536
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("#AABBCC"); // [170, 187, 204, 1]
|
9537
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("rgb(1,2,3)"); // [1, 2, 3, 1]
|
9538
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("rgba(1,2,3,0.5)"); // [1, 2, 3, 0.5]
|
9539
|
+
*
|
9540
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("background-color: #ABC; color: #000;", "background-color"); // [170, 187, 204, 1]
|
9541
|
+
* var colorArray = wysihtml5.quirks.styleParser.parseColor("background-color: #ABC; color: #000;", "color"); // [0, 0, 0, 1]
|
9542
|
+
*/
|
9543
|
+
parseColor : function (stylesStr, paramName) {
|
9544
|
+
var paramsRegex, params, colorType, colorMatch, radix,
|
9545
|
+
colorStr = stylesStr;
|
9471
9546
|
|
9472
|
-
|
9473
|
-
|
9474
|
-
|
9475
|
-
|
9476
|
-
|
9477
|
-
|
9478
|
-
|
9479
|
-
});
|
9480
|
-
}
|
9547
|
+
if (paramName) {
|
9548
|
+
paramsRegex = makeParamRegExp(paramName);
|
9549
|
+
|
9550
|
+
if (!(params = stylesStr.match(paramsRegex))) { return false; }
|
9551
|
+
|
9552
|
+
params = params.pop().split(":")[1];
|
9553
|
+
colorStr = wysihtml5.lang.string(params).trim();
|
9481
9554
|
}
|
9482
|
-
|
9555
|
+
|
9556
|
+
if (!(colorType = getColorParseMethod(colorStr))) { return false; }
|
9557
|
+
if (!(colorMatch = colorStr.match(colorType.regex))) { return false; }
|
9558
|
+
|
9559
|
+
radix = colorType.radix || 10;
|
9560
|
+
|
9561
|
+
if (colorType === colorParseMethods.hex3) {
|
9562
|
+
colorMatch.shift();
|
9563
|
+
colorMatch.push(1);
|
9564
|
+
return wysihtml5.lang.array(colorMatch).map(function(d, idx) {
|
9565
|
+
return (idx < 3) ? (parseInt(d, radix) * radix) + parseInt(d, radix): parseFloat(d);
|
9566
|
+
});
|
9567
|
+
}
|
9568
|
+
|
9569
|
+
colorMatch.shift();
|
9570
|
+
|
9571
|
+
if (!colorMatch[3]) {
|
9572
|
+
colorMatch.push(1);
|
9573
|
+
}
|
9574
|
+
|
9575
|
+
return wysihtml5.lang.array(colorMatch).map(function(d, idx) {
|
9576
|
+
return (idx < 3) ? parseInt(d, radix): parseFloat(d);
|
9577
|
+
});
|
9483
9578
|
},
|
9484
9579
|
|
9485
|
-
|
9486
|
-
|
9487
|
-
|
9488
|
-
|
9489
|
-
|
9490
|
-
|
9491
|
-
|
9492
|
-
|
9493
|
-
|
9494
|
-
|
9495
|
-
|
9496
|
-
|
9497
|
-
|
9580
|
+
/* Takes rgba color array [r,g,b,a] as a value and formats it to color string with given format type
|
9581
|
+
* If no format is given, rgba/rgb is returned based on alpha value
|
9582
|
+
*
|
9583
|
+
* Example:
|
9584
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1], "hash"); // "#AABBCC"
|
9585
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1], "hex"); // "AABBCC"
|
9586
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1], "csv"); // "170, 187, 204, 1"
|
9587
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1], "rgba"); // "rgba(170,187,204,1)"
|
9588
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1], "rgb"); // "rgb(170,187,204)"
|
9589
|
+
*
|
9590
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 0.5]); // "rgba(170,187,204,0.5)"
|
9591
|
+
* var colorStr = wysihtml5.quirks.styleParser.unparseColor([170, 187, 204, 1]); // "rgb(170,187,204)"
|
9592
|
+
*/
|
9593
|
+
unparseColor: function(val, colorFormat) {
|
9594
|
+
var hexRadix = 16;
|
9595
|
+
|
9596
|
+
if (colorFormat === "hex") {
|
9597
|
+
return (val[0].toString(hexRadix) + val[1].toString(hexRadix) + val[2].toString(hexRadix)).toUpperCase();
|
9598
|
+
} else if (colorFormat === "hash") {
|
9599
|
+
return "#" + (val[0].toString(hexRadix) + val[1].toString(hexRadix) + val[2].toString(hexRadix)).toUpperCase();
|
9600
|
+
} else if (colorFormat === "rgb") {
|
9601
|
+
return "rgb(" + val[0] + "," + val[1] + "," + val[2] + ")";
|
9602
|
+
} else if (colorFormat === "rgba") {
|
9603
|
+
return "rgba(" + val[0] + "," + val[1] + "," + val[2] + "," + val[3] + ")";
|
9604
|
+
} else if (colorFormat === "csv") {
|
9605
|
+
return val[0] + "," + val[1] + "," + val[2] + "," + val[3];
|
9498
9606
|
}
|
9499
9607
|
|
9500
9608
|
if (val[3] && val[3] !== 1) {
|
@@ -9504,10 +9612,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9504
9612
|
}
|
9505
9613
|
},
|
9506
9614
|
|
9615
|
+
// Parses font size value from style string
|
9507
9616
|
parseFontSize: function(stylesStr) {
|
9508
|
-
var params = stylesStr.match(
|
9617
|
+
var params = stylesStr.match(makeParamRegExp("font-size"));
|
9509
9618
|
if (params) {
|
9510
|
-
return wysihtml5.lang.string(params[params.length - 1].split(
|
9619
|
+
return wysihtml5.lang.string(params[params.length - 1].split(":")[1]).trim();
|
9511
9620
|
}
|
9512
9621
|
return false;
|
9513
9622
|
}
|
@@ -9546,6 +9655,50 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
9546
9655
|
return ret;
|
9547
9656
|
}
|
9548
9657
|
|
9658
|
+
function getWebkitSelectionFixNode(container) {
|
9659
|
+
var blankNode = document.createElement('span');
|
9660
|
+
|
9661
|
+
var placeholderRemover = function(event) {
|
9662
|
+
// Self-destructs the caret and keeps the text inserted into it by user
|
9663
|
+
var lastChild;
|
9664
|
+
|
9665
|
+
container.removeEventListener('mouseup', placeholderRemover);
|
9666
|
+
container.removeEventListener('keydown', placeholderRemover);
|
9667
|
+
container.removeEventListener('touchstart', placeholderRemover);
|
9668
|
+
container.removeEventListener('focus', placeholderRemover);
|
9669
|
+
container.removeEventListener('blur', placeholderRemover);
|
9670
|
+
container.removeEventListener('paste', delayedPlaceholderRemover);
|
9671
|
+
container.removeEventListener('drop', delayedPlaceholderRemover);
|
9672
|
+
container.removeEventListener('beforepaste', delayedPlaceholderRemover);
|
9673
|
+
|
9674
|
+
if (blankNode && blankNode.parentNode) {
|
9675
|
+
blankNode.parentNode.removeChild(blankNode);
|
9676
|
+
}
|
9677
|
+
},
|
9678
|
+
delayedPlaceholderRemover = function (event) {
|
9679
|
+
if (blankNode && blankNode.parentNode) {
|
9680
|
+
setTimeout(placeholderRemover, 0);
|
9681
|
+
}
|
9682
|
+
};
|
9683
|
+
|
9684
|
+
blankNode.appendChild(document.createTextNode(wysihtml5.INVISIBLE_SPACE));
|
9685
|
+
blankNode.className = '_wysihtml5-temp-caret-fix';
|
9686
|
+
blankNode.style.display = 'block';
|
9687
|
+
blankNode.style.minWidth = '1px';
|
9688
|
+
blankNode.style.height = '0px';
|
9689
|
+
|
9690
|
+
container.addEventListener('mouseup', placeholderRemover);
|
9691
|
+
container.addEventListener('keydown', placeholderRemover);
|
9692
|
+
container.addEventListener('touchstart', placeholderRemover);
|
9693
|
+
container.addEventListener('focus', placeholderRemover);
|
9694
|
+
container.addEventListener('blur', placeholderRemover);
|
9695
|
+
container.addEventListener('paste', delayedPlaceholderRemover);
|
9696
|
+
container.addEventListener('drop', delayedPlaceholderRemover);
|
9697
|
+
container.addEventListener('beforepaste', delayedPlaceholderRemover);
|
9698
|
+
|
9699
|
+
return blankNode;
|
9700
|
+
}
|
9701
|
+
|
9549
9702
|
// Should fix the obtained ranges that cannot surrond contents normally to apply changes upon
|
9550
9703
|
// Being considerate to firefox that sets range start start out of span and end inside on doubleclick initiated selection
|
9551
9704
|
function expandRangeToSurround(range) {
|
@@ -10218,6 +10371,20 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
10218
10371
|
}
|
10219
10372
|
},
|
10220
10373
|
|
10374
|
+
canAppendChild: function (node) {
|
10375
|
+
var anchorNode, anchorNodeTagNameLower,
|
10376
|
+
voidElements = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"],
|
10377
|
+
range = this.getRange();
|
10378
|
+
|
10379
|
+
anchorNode = node || range.startContainer;
|
10380
|
+
|
10381
|
+
if (anchorNode) {
|
10382
|
+
anchorNodeTagNameLower = (anchorNode.tagName || anchorNode.nodeName).toLowerCase();
|
10383
|
+
}
|
10384
|
+
|
10385
|
+
return voidElements.indexOf(anchorNodeTagNameLower) === -1;
|
10386
|
+
},
|
10387
|
+
|
10221
10388
|
splitElementAtCaret: function (element, insertNode) {
|
10222
10389
|
var sel = this.getSelection(),
|
10223
10390
|
range, contentAfterRangeStart,
|
@@ -10598,6 +10765,52 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
10598
10765
|
return (selection && selection.anchorNode && selection.focusNode) ? selection : null;
|
10599
10766
|
},
|
10600
10767
|
|
10768
|
+
|
10769
|
+
|
10770
|
+
// Webkit has an ancient error of not selecting all contents when uneditable block element is first or last in editable area
|
10771
|
+
selectAll: function() {
|
10772
|
+
var range = this.createRange(),
|
10773
|
+
composer = this.composer,
|
10774
|
+
that = this,
|
10775
|
+
blankEndNode = getWebkitSelectionFixNode(this.composer.element),
|
10776
|
+
blankStartNode = getWebkitSelectionFixNode(this.composer.element),
|
10777
|
+
s;
|
10778
|
+
|
10779
|
+
var doSelect = function() {
|
10780
|
+
range.setStart(composer.element, 0);
|
10781
|
+
range.setEnd(composer.element, composer.element.childNodes.length);
|
10782
|
+
s = that.setSelection(range);
|
10783
|
+
};
|
10784
|
+
|
10785
|
+
var notSelected = function() {
|
10786
|
+
return !s || (s.nativeSelection && s.nativeSelection.type && (s.nativeSelection.type === "Caret" || s.nativeSelection.type === "None"));
|
10787
|
+
}
|
10788
|
+
|
10789
|
+
wysihtml5.dom.removeInvisibleSpaces(this.composer.element);
|
10790
|
+
doSelect();
|
10791
|
+
|
10792
|
+
if (this.composer.element.firstChild && notSelected()) {
|
10793
|
+
// Try fixing end
|
10794
|
+
this.composer.element.appendChild(blankEndNode);
|
10795
|
+
doSelect();
|
10796
|
+
|
10797
|
+
if (notSelected()) {
|
10798
|
+
// Remove end fix
|
10799
|
+
blankEndNode.parentNode.removeChild(blankEndNode);
|
10800
|
+
|
10801
|
+
// Try fixing beginning
|
10802
|
+
this.composer.element.insertBefore(blankStartNode, this.composer.element.firstChild);
|
10803
|
+
doSelect();
|
10804
|
+
|
10805
|
+
if (notSelected()) {
|
10806
|
+
// Try fixing both
|
10807
|
+
this.composer.element.appendChild(blankEndNode);
|
10808
|
+
doSelect();
|
10809
|
+
}
|
10810
|
+
}
|
10811
|
+
}
|
10812
|
+
},
|
10813
|
+
|
10601
10814
|
createRange: function() {
|
10602
10815
|
return rangy.createRange(this.doc);
|
10603
10816
|
},
|
@@ -10656,6 +10869,25 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
|
10656
10869
|
return (wysihtml5.lang.array(nodeNames).contains(parentElement.nodeName)) ? parentElement : false;
|
10657
10870
|
},
|
10658
10871
|
|
10872
|
+
isInThisEditable: function() {
|
10873
|
+
var sel = this.getSelection(),
|
10874
|
+
fnode = sel.focusNode,
|
10875
|
+
anode = sel.anchorNode;
|
10876
|
+
|
10877
|
+
// In IE node contains will not work for textnodes, thus taking parentNode
|
10878
|
+
if (fnode && fnode.nodeType !== 1) {
|
10879
|
+
fnode = fnode.parentNode;
|
10880
|
+
}
|
10881
|
+
|
10882
|
+
if (anode && anode.nodeType !== 1) {
|
10883
|
+
anode = anode.parentNode;
|
10884
|
+
}
|
10885
|
+
|
10886
|
+
return anode && fnode &&
|
10887
|
+
(wysihtml5.dom.contains(this.composer.element, fnode) || this.composer.element === fnode) &&
|
10888
|
+
(wysihtml5.dom.contains(this.composer.element, anode) || this.composer.element === anode);
|
10889
|
+
},
|
10890
|
+
|
10659
10891
|
deselect: function() {
|
10660
10892
|
var sel = this.getSelection();
|
10661
10893
|
sel && sel.removeAllRanges();
|
@@ -11509,12 +11741,12 @@ wysihtml5.Commands = Base.extend(
|
|
11509
11741
|
exec: function(composer, command, size) {
|
11510
11742
|
size = size.size || size;
|
11511
11743
|
if (!(/^\s*$/).test(size)) {
|
11512
|
-
wysihtml5.commands.formatInline.exec(composer, command, {styleProperty: "fontSize", styleValue: size, toggle:
|
11744
|
+
wysihtml5.commands.formatInline.exec(composer, command, {styleProperty: "fontSize", styleValue: size, toggle: false});
|
11513
11745
|
}
|
11514
11746
|
},
|
11515
11747
|
|
11516
11748
|
state: function(composer, command, size) {
|
11517
|
-
return wysihtml5.commands.formatInline.state(composer, command, {styleProperty: "fontSize", styleValue: size});
|
11749
|
+
return wysihtml5.commands.formatInline.state(composer, command, {styleProperty: "fontSize", styleValue: size || undefined});
|
11518
11750
|
},
|
11519
11751
|
|
11520
11752
|
remove: function(composer, command) {
|
@@ -11522,15 +11754,14 @@ wysihtml5.Commands = Base.extend(
|
|
11522
11754
|
},
|
11523
11755
|
|
11524
11756
|
stateValue: function(composer, command) {
|
11525
|
-
var
|
11526
|
-
|
11527
|
-
val = false;
|
11757
|
+
var styleStr,
|
11758
|
+
st = this.state(composer, command);
|
11528
11759
|
|
11529
11760
|
if (st && wysihtml5.lang.object(st).isArray()) {
|
11530
11761
|
st = st[0];
|
11531
11762
|
}
|
11532
11763
|
if (st) {
|
11533
|
-
styleStr = st.getAttribute(
|
11764
|
+
styleStr = st.getAttribute("style");
|
11534
11765
|
if (styleStr) {
|
11535
11766
|
return wysihtml5.quirks.styleParser.parseFontSize(styleStr);
|
11536
11767
|
}
|
@@ -11562,12 +11793,15 @@ wysihtml5.Commands = Base.extend(
|
|
11562
11793
|
|
11563
11794
|
wysihtml5.commands.foreColorStyle = {
|
11564
11795
|
exec: function(composer, command, color) {
|
11565
|
-
var colorVals
|
11566
|
-
|
11796
|
+
var colorVals, colString;
|
11797
|
+
|
11798
|
+
if (!color) { return; }
|
11799
|
+
|
11800
|
+
colorVals = wysihtml5.quirks.styleParser.parseColor("color:" + (color.color || color), "color");
|
11567
11801
|
|
11568
11802
|
if (colorVals) {
|
11569
|
-
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(
|
11570
|
-
wysihtml5.commands.formatInline.exec(composer, command, {styleProperty:
|
11803
|
+
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(", ") : "rgba(" + colorVals.join(', ')) + ')';
|
11804
|
+
wysihtml5.commands.formatInline.exec(composer, command, {styleProperty: "color", styleValue: colString});
|
11571
11805
|
}
|
11572
11806
|
},
|
11573
11807
|
|
@@ -11577,14 +11811,14 @@ wysihtml5.Commands = Base.extend(
|
|
11577
11811
|
|
11578
11812
|
|
11579
11813
|
if (colorVals) {
|
11580
|
-
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(
|
11814
|
+
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(", ") : "rgba(" + colorVals.join(', ')) + ')';
|
11581
11815
|
}
|
11582
11816
|
|
11583
|
-
return wysihtml5.commands.formatInline.state(composer, command, {styleProperty:
|
11817
|
+
return wysihtml5.commands.formatInline.state(composer, command, {styleProperty: "color", styleValue: colString});
|
11584
11818
|
},
|
11585
11819
|
|
11586
11820
|
remove: function(composer, command) {
|
11587
|
-
return wysihtml5.commands.formatInline.remove(composer, command, {styleProperty:
|
11821
|
+
return wysihtml5.commands.formatInline.remove(composer, command, {styleProperty: "color"});
|
11588
11822
|
},
|
11589
11823
|
|
11590
11824
|
stateValue: function(composer, command, props) {
|
@@ -11597,7 +11831,7 @@ wysihtml5.Commands = Base.extend(
|
|
11597
11831
|
}
|
11598
11832
|
|
11599
11833
|
if (st) {
|
11600
|
-
colorStr = st.getAttribute(
|
11834
|
+
colorStr = st.getAttribute("style");
|
11601
11835
|
if (colorStr) {
|
11602
11836
|
val = wysihtml5.quirks.styleParser.parseColor(colorStr, "color");
|
11603
11837
|
return wysihtml5.quirks.styleParser.unparseColor(val, props);
|
@@ -11675,6 +11909,14 @@ wysihtml5.Commands = Base.extend(
|
|
11675
11909
|
BLOCK_ELEMENTS = "h1, h2, h3, h4, h5, h6, p, pre, div, blockquote",
|
11676
11910
|
INLINE_ELEMENTS = "b, big, i, small, tt, abbr, acronym, cite, code, dfn, em, kbd, strong, samp, var, a, bdo, br, q, span, sub, sup, button, label, textarea, input, select, u";
|
11677
11911
|
|
11912
|
+
function correctOptionsForSimilarityCheck(options) {
|
11913
|
+
return {
|
11914
|
+
nodeName: options.nodeName || null,
|
11915
|
+
className: (!options.classRegExp) ? options.className || null : null,
|
11916
|
+
classRegExp: options.classRegExp || null,
|
11917
|
+
styleProperty: options.styleProperty || null
|
11918
|
+
};
|
11919
|
+
}
|
11678
11920
|
|
11679
11921
|
// Removes empty block level elements
|
11680
11922
|
function cleanup(composer) {
|
@@ -11684,7 +11926,7 @@ wysihtml5.Commands = Base.extend(
|
|
11684
11926
|
elements = wysihtml5.lang.array(allElements).without(uneditables);
|
11685
11927
|
|
11686
11928
|
for (var i = elements.length; i--;) {
|
11687
|
-
if (elements[i].innerHTML === "") {
|
11929
|
+
if (elements[i].innerHTML.replace(/[\uFEFF]/g, '') === "") {
|
11688
11930
|
elements[i].parentNode.removeChild(elements[i]);
|
11689
11931
|
}
|
11690
11932
|
}
|
@@ -11811,7 +12053,7 @@ wysihtml5.Commands = Base.extend(
|
|
11811
12053
|
|
11812
12054
|
for (var i = contentBlocks.length; i--;) {
|
11813
12055
|
if (!contentBlocks[i].nextSibling || contentBlocks[i].nextSibling.nodeType !== 1 || contentBlocks[i].nextSibling.nodeName !== 'BR') {
|
11814
|
-
if ((contentBlocks[i].innerHTML || contentBlocks[i].nodeValue).trim() !==
|
12056
|
+
if ((contentBlocks[i].innerHTML || contentBlocks[i].nodeValue || '').trim() !== '') {
|
11815
12057
|
contentBlocks[i].parentNode.insertBefore(contentBlocks[i].ownerDocument.createElement('BR'), contentBlocks[i].nextSibling);
|
11816
12058
|
}
|
11817
12059
|
}
|
@@ -11877,8 +12119,10 @@ wysihtml5.Commands = Base.extend(
|
|
11877
12119
|
rangeStartContainer = r.startContainer,
|
11878
12120
|
content = r.extractContents(),
|
11879
12121
|
fragment = composer.doc.createDocumentFragment(),
|
12122
|
+
similarOptions = defaultOptions ? correctOptionsForSimilarityCheck(defaultOptions) : null,
|
12123
|
+
similarOuterBlock = similarOptions ? wysihtml5.dom.getParentElement(rangeStartContainer, similarOptions, null, composer.element) : null,
|
11880
12124
|
splitAllBlocks = !defaultOptions || (defaultName === "BLOCKQUOTE" && defaultOptions.nodeName && defaultOptions.nodeName === "BLOCKQUOTE"),
|
11881
|
-
firstOuterBlock = findOuterBlock(rangeStartContainer, composer.element, splitAllBlocks), // The outermost un-nestable block element parent of selection start
|
12125
|
+
firstOuterBlock = similarOuterBlock || findOuterBlock(rangeStartContainer, composer.element, splitAllBlocks), // The outermost un-nestable block element parent of selection start
|
11882
12126
|
wrapper, blocks, children;
|
11883
12127
|
|
11884
12128
|
if (options && options.nodeName && options.nodeName === "BLOCKQUOTE") {
|
@@ -12003,7 +12247,7 @@ wysihtml5.Commands = Base.extend(
|
|
12003
12247
|
|
12004
12248
|
if (composer.selection.isCollapsed()) {
|
12005
12249
|
parent = wysihtml5.dom.getParentElement(composer.selection.getOwnRanges()[0].startContainer, {
|
12006
|
-
query:
|
12250
|
+
query: UNNESTABLE_BLOCK_ELEMENTS + ', ' + (options && options.nodeName ? options.nodeName.toLowerCase() : 'div'),
|
12007
12251
|
}, null, composer.element);
|
12008
12252
|
if (parent) {
|
12009
12253
|
bookmark = rangy.saveSelection(composer.win);
|
@@ -12016,7 +12260,7 @@ wysihtml5.Commands = Base.extend(
|
|
12016
12260
|
}
|
12017
12261
|
}
|
12018
12262
|
|
12019
|
-
// And get all selection ranges of current composer and
|
12263
|
+
// And get all selection ranges of current composer and iterate
|
12020
12264
|
ranges = composer.selection.getOwnRanges();
|
12021
12265
|
for (var i = ranges.length; i--;) {
|
12022
12266
|
newBlockElements = newBlockElements.concat(wrapRangeWithElement(ranges[i], options, getParentBlockNodeName(ranges[i].startContainer, composer), composer));
|
@@ -12026,6 +12270,13 @@ wysihtml5.Commands = Base.extend(
|
|
12026
12270
|
|
12027
12271
|
// Remove empty block elements that may be left behind
|
12028
12272
|
cleanup(composer);
|
12273
|
+
// If cleanup removed some new block elements. remove them from array too
|
12274
|
+
for (var e = newBlockElements.length; e--;) {
|
12275
|
+
if (!newBlockElements[e].parentNode) {
|
12276
|
+
newBlockElements.splice(e, 1);
|
12277
|
+
}
|
12278
|
+
}
|
12279
|
+
|
12029
12280
|
// Restore correct selection
|
12030
12281
|
if (bookmark) {
|
12031
12282
|
rangy.restoreSelection(bookmark);
|
@@ -12081,8 +12332,9 @@ wysihtml5.Commands = Base.extend(
|
|
12081
12332
|
wysihtml5.commands.formatCode = {
|
12082
12333
|
|
12083
12334
|
exec: function(composer, command, classname) {
|
12084
|
-
var pre = this.state(composer),
|
12335
|
+
var pre = this.state(composer)[0],
|
12085
12336
|
code, range, selectedNodes;
|
12337
|
+
|
12086
12338
|
if (pre) {
|
12087
12339
|
// caret is already within a <pre><code>...</code></pre>
|
12088
12340
|
composer.selection.executeAndRestore(function() {
|
@@ -12111,12 +12363,13 @@ wysihtml5.Commands = Base.extend(
|
|
12111
12363
|
},
|
12112
12364
|
|
12113
12365
|
state: function(composer) {
|
12114
|
-
var selectedNode = composer.selection.getSelectedNode();
|
12366
|
+
var selectedNode = composer.selection.getSelectedNode(), node;
|
12115
12367
|
if (selectedNode && selectedNode.nodeName && selectedNode.nodeName == "PRE"&&
|
12116
12368
|
selectedNode.firstChild && selectedNode.firstChild.nodeName && selectedNode.firstChild.nodeName == "CODE") {
|
12117
|
-
return selectedNode;
|
12369
|
+
return [selectedNode];
|
12118
12370
|
} else {
|
12119
|
-
|
12371
|
+
node = wysihtml5.dom.getParentElement(selectedNode, { query: "pre code" });
|
12372
|
+
return node ? [node.parentNode] : false;
|
12120
12373
|
}
|
12121
12374
|
}
|
12122
12375
|
};
|
@@ -12260,9 +12513,7 @@ wysihtml5.Commands = Base.extend(
|
|
12260
12513
|
}
|
12261
12514
|
|
12262
12515
|
function updateFormatOfElement(element, options) {
|
12263
|
-
var attr, newNode, a, newAttributes, nodeNameQuery;
|
12264
|
-
|
12265
|
-
|
12516
|
+
var attr, newNode, a, newAttributes, nodeNameQuery, nodeQueryMatch;
|
12266
12517
|
|
12267
12518
|
if (options.className) {
|
12268
12519
|
if (options.toggle !== false && element.classList.contains(options.className)) {
|
@@ -12297,30 +12548,19 @@ wysihtml5.Commands = Base.extend(
|
|
12297
12548
|
updateElementAttributes(element, newAttributes, options.toggle);
|
12298
12549
|
}
|
12299
12550
|
|
12300
|
-
|
12551
|
+
|
12552
|
+
// Handle similar semantically same elements (queryAliasMap)
|
12301
12553
|
nodeNameQuery = options.nodeName ? queryAliasMap[options.nodeName.toLowerCase()] || options.nodeName.toLowerCase() : null;
|
12554
|
+
nodeQueryMatch = nodeNameQuery ? wysihtml5.dom.domNode(element).test({ query: nodeNameQuery }) : false;
|
12302
12555
|
|
12303
|
-
|
12304
|
-
|
12305
|
-
|
12306
|
-
if (
|
12556
|
+
// Unwrap element if no attributes present and node name given
|
12557
|
+
// or no attributes and if no nodename set but node is the default
|
12558
|
+
if (!options.nodeName || options.nodeName === defaultTag || nodeQueryMatch) {
|
12559
|
+
if (
|
12560
|
+
((options.toggle !== false && nodeQueryMatch) || (!options.nodeName && element.nodeName === defaultTag)) &&
|
12561
|
+
hasNoClass(element) && hasNoStyle(element) && hasNoAttributes(element)
|
12562
|
+
) {
|
12307
12563
|
wysihtml5.dom.unwrap(element);
|
12308
|
-
} else if (!options.nodeName) {
|
12309
|
-
newNode = element.ownerDocument.createElement(defaultTag);
|
12310
|
-
|
12311
|
-
// pass present attributes
|
12312
|
-
attr = wysihtml5.dom.getAttributes(element);
|
12313
|
-
for (a in attr) {
|
12314
|
-
if (attr.hasOwnProperty(a)) {
|
12315
|
-
newNode.setAttribute(a, attr[a]);
|
12316
|
-
}
|
12317
|
-
}
|
12318
|
-
|
12319
|
-
while (element.firstChild) {
|
12320
|
-
newNode.appendChild(element.firstChild);
|
12321
|
-
}
|
12322
|
-
element.parentNode.insertBefore(newNode, element);
|
12323
|
-
element.parentNode.removeChild(element);
|
12324
12564
|
}
|
12325
12565
|
|
12326
12566
|
}
|
@@ -12425,35 +12665,39 @@ wysihtml5.Commands = Base.extend(
|
|
12425
12665
|
partial = false,
|
12426
12666
|
node, range, caretNode;
|
12427
12667
|
|
12428
|
-
if (
|
12429
|
-
|
12430
|
-
if (
|
12431
|
-
|
12432
|
-
|
12433
|
-
|
12434
|
-
|
12435
|
-
|
12436
|
-
|
12437
|
-
|
12438
|
-
|
12668
|
+
if (composer.selection.isInThisEditable()) {
|
12669
|
+
|
12670
|
+
if (searchNodes.length === 0 && composer.selection.isCollapsed()) {
|
12671
|
+
caretNode = composer.selection.getSelection().anchorNode;
|
12672
|
+
if (!caretNode) {
|
12673
|
+
// selection not in editor
|
12674
|
+
return {
|
12675
|
+
nodes: [],
|
12676
|
+
partial: false
|
12677
|
+
};
|
12678
|
+
}
|
12679
|
+
if (caretNode.nodeType === 3) {
|
12680
|
+
searchNodes = [caretNode];
|
12681
|
+
}
|
12439
12682
|
}
|
12440
|
-
}
|
12441
12683
|
|
12442
|
-
|
12443
|
-
|
12444
|
-
|
12445
|
-
|
12446
|
-
|
12684
|
+
// Handle collapsed selection caret
|
12685
|
+
if (!searchNodes.length) {
|
12686
|
+
range = composer.selection.getOwnRanges()[0];
|
12687
|
+
if (range) {
|
12688
|
+
searchNodes = [range.endContainer];
|
12689
|
+
}
|
12447
12690
|
}
|
12448
|
-
}
|
12449
12691
|
|
12450
|
-
|
12451
|
-
|
12452
|
-
|
12453
|
-
|
12454
|
-
|
12455
|
-
|
12692
|
+
for (var i = 0, maxi = searchNodes.length; i < maxi; i++) {
|
12693
|
+
node = findSimilarTextNodeWrapper(searchNodes[i], options, composer.element, exact);
|
12694
|
+
if (node) {
|
12695
|
+
nodes.push(node);
|
12696
|
+
} else {
|
12697
|
+
partial = true;
|
12698
|
+
}
|
12456
12699
|
}
|
12700
|
+
|
12457
12701
|
}
|
12458
12702
|
|
12459
12703
|
return {
|
@@ -12774,9 +13018,7 @@ wysihtml5.Commands = Base.extend(
|
|
12774
13018
|
|
12775
13019
|
state: function(composer, command, options) {
|
12776
13020
|
options = fixOptions(options);
|
12777
|
-
|
12778
13021
|
var nodes = getState(composer, options, true).nodes;
|
12779
|
-
|
12780
13022
|
return (nodes.length === 0) ? false : nodes;
|
12781
13023
|
}
|
12782
13024
|
};
|
@@ -14635,14 +14877,14 @@ wysihtml5.views.View = Base.extend(
|
|
14635
14877
|
// Deletion with caret in the beginning of headings needs special attention
|
14636
14878
|
// Heading does not concate text to previous block node correctly (browsers do unexpected miracles here especially webkit)
|
14637
14879
|
var fixDeleteInTheBeginnigOfHeading = function(composer) {
|
14638
|
-
var selection = composer.selection
|
14880
|
+
var selection = composer.selection,
|
14881
|
+
prevNode = selection.getPreviousNode();
|
14639
14882
|
|
14640
14883
|
if (selection.caretIsFirstInSelection() &&
|
14641
|
-
|
14642
|
-
|
14643
|
-
(
|
14884
|
+
prevNode &&
|
14885
|
+
prevNode.nodeType === 1 &&
|
14886
|
+
(/block/).test(composer.win.getComputedStyle(prevNode).display)
|
14644
14887
|
) {
|
14645
|
-
var prevNode = selection.getPreviousNode();
|
14646
14888
|
if ((/^\s*$/).test(prevNode.textContent || prevNode.innerText)) {
|
14647
14889
|
// If heading is empty remove the heading node
|
14648
14890
|
prevNode.parentNode.removeChild(prevNode);
|
@@ -14650,20 +14892,23 @@ wysihtml5.views.View = Base.extend(
|
|
14650
14892
|
} else {
|
14651
14893
|
if (prevNode.lastChild) {
|
14652
14894
|
var selNode = prevNode.lastChild,
|
14653
|
-
|
14654
|
-
|
14895
|
+
selectedNode = selection.getSelectedNode(),
|
14896
|
+
commonAncestorNode = wysihtml5.dom.domNode(prevNode).commonAncestor(selectedNode, composer.element);
|
14897
|
+
curNode = commonAncestorNode ? wysihtml5.dom.getParentElement(selectedNode, {
|
14898
|
+
query: "h1, h2, h3, h4, h5, h6, p, pre, div, blockquote"
|
14899
|
+
}, false, commonAncestorNode) : null;
|
14900
|
+
|
14655
14901
|
if (curNode) {
|
14656
14902
|
while (curNode.firstChild) {
|
14657
14903
|
prevNode.appendChild(curNode.firstChild);
|
14658
14904
|
}
|
14659
14905
|
selection.setAfter(selNode);
|
14660
14906
|
return true;
|
14661
|
-
} else if (
|
14662
|
-
prevNode.appendChild(
|
14907
|
+
} else if (selectedNode.nodeType === 3) {
|
14908
|
+
prevNode.appendChild(selectedNode);
|
14663
14909
|
selection.setAfter(selNode);
|
14664
14910
|
return true;
|
14665
14911
|
}
|
14666
|
-
}
|
14667
14912
|
}
|
14668
14913
|
}
|
14669
14914
|
}
|
@@ -14675,23 +14920,17 @@ wysihtml5.views.View = Base.extend(
|
|
14675
14920
|
element = composer.element;
|
14676
14921
|
|
14677
14922
|
if (selection.isCollapsed()) {
|
14678
|
-
if (
|
14679
|
-
// delete in the beginnig of LI will outdent not delete
|
14923
|
+
if (fixDeleteInTheBeginnigOfHeading(composer)) {
|
14680
14924
|
event.preventDefault();
|
14681
|
-
|
14682
|
-
}
|
14683
|
-
|
14684
|
-
|
14685
|
-
|
14686
|
-
|
14687
|
-
|
14688
|
-
|
14689
|
-
|
14690
|
-
}
|
14691
|
-
if (handleUneditableDeletion(composer)) {
|
14692
|
-
event.preventDefault();
|
14693
|
-
return;
|
14694
|
-
}
|
14925
|
+
return;
|
14926
|
+
}
|
14927
|
+
if (fixLastBrDeletionInTable(composer)) {
|
14928
|
+
event.preventDefault();
|
14929
|
+
return;
|
14930
|
+
}
|
14931
|
+
if (handleUneditableDeletion(composer)) {
|
14932
|
+
event.preventDefault();
|
14933
|
+
return;
|
14695
14934
|
}
|
14696
14935
|
} else {
|
14697
14936
|
if (selection.containsUneditable()) {
|
@@ -14701,11 +14940,15 @@ wysihtml5.views.View = Base.extend(
|
|
14701
14940
|
}
|
14702
14941
|
};
|
14703
14942
|
|
14704
|
-
var handleTabKeyDown = function(composer, element) {
|
14943
|
+
var handleTabKeyDown = function(composer, element, shiftKey) {
|
14705
14944
|
if (!composer.selection.isCollapsed()) {
|
14706
14945
|
composer.selection.deleteContents();
|
14707
14946
|
} else if (composer.selection.caretIsInTheBeginnig('li')) {
|
14708
|
-
if (
|
14947
|
+
if (shiftKey) {
|
14948
|
+
if (composer.commands.exec('outdentList')) return;
|
14949
|
+
} else {
|
14950
|
+
if (composer.commands.exec('indentList')) return;
|
14951
|
+
}
|
14709
14952
|
}
|
14710
14953
|
|
14711
14954
|
// Is   close enough to tab. Could not find enough counter arguments for now.
|
@@ -14721,9 +14964,9 @@ wysihtml5.views.View = Base.extend(
|
|
14721
14964
|
|
14722
14965
|
// Listens to "drop", "paste", "mouseup", "focus", "keyup" events and fires
|
14723
14966
|
var handleUserInteraction = function (event) {
|
14724
|
-
this.parent.fire("beforeinteraction").fire("beforeinteraction:composer");
|
14967
|
+
this.parent.fire("beforeinteraction", event).fire("beforeinteraction:composer", event);
|
14725
14968
|
setTimeout((function() {
|
14726
|
-
this.parent.fire("interaction").fire("interaction:composer");
|
14969
|
+
this.parent.fire("interaction", event).fire("interaction:composer", event);
|
14727
14970
|
}).bind(this), 0);
|
14728
14971
|
};
|
14729
14972
|
|
@@ -14837,6 +15080,13 @@ wysihtml5.views.View = Base.extend(
|
|
14837
15080
|
command = shortcuts[keyCode],
|
14838
15081
|
target, parent;
|
14839
15082
|
|
15083
|
+
// Select all (meta/ctrl + a)
|
15084
|
+
if ((event.ctrlKey || event.metaKey) && keyCode === 65) {
|
15085
|
+
this.selection.selectAll();
|
15086
|
+
event.preventDefault();
|
15087
|
+
return;
|
15088
|
+
}
|
15089
|
+
|
14840
15090
|
// Shortcut logic
|
14841
15091
|
if ((event.ctrlKey || event.metaKey) && !event.altKey && command) {
|
14842
15092
|
this.commands.exec(command);
|
@@ -14859,16 +15109,16 @@ wysihtml5.views.View = Base.extend(
|
|
14859
15109
|
if (parent.nodeName === "A" && !parent.firstChild) {
|
14860
15110
|
parent.parentNode.removeChild(parent);
|
14861
15111
|
}
|
14862
|
-
setTimeout(function() {
|
15112
|
+
setTimeout((function() {
|
14863
15113
|
wysihtml5.quirks.redraw(this.element);
|
14864
|
-
}, 0);
|
15114
|
+
}).bind(this), 0);
|
14865
15115
|
}
|
14866
15116
|
}
|
14867
15117
|
|
14868
15118
|
if (this.config.handleTabKey && keyCode === wysihtml5.TAB_KEY) {
|
14869
15119
|
// TAB key handling
|
14870
15120
|
event.preventDefault();
|
14871
|
-
handleTabKeyDown(this, this.element);
|
15121
|
+
handleTabKeyDown(this, this.element, event.shiftKey);
|
14872
15122
|
}
|
14873
15123
|
|
14874
15124
|
};
|
@@ -15227,6 +15477,8 @@ wysihtml5.views.View = Base.extend(
|
|
15227
15477
|
// Whether toolbar is displayed after init by script automatically.
|
15228
15478
|
// Can be set to false if toolobar is set to display only on editable area focus
|
15229
15479
|
showToolbarAfterInit: true,
|
15480
|
+
// With default toolbar it shows dialogs in toolbar when their related text format state becomes active (click on link in text opens link dialogue)
|
15481
|
+
showToolbarDialogsOnSelection: true,
|
15230
15482
|
// Whether urls, entered by the user should automatically become clickable-links
|
15231
15483
|
autoLink: true,
|
15232
15484
|
// Includes table editing events and cell selection tracking
|
@@ -15400,8 +15652,7 @@ wysihtml5.views.View = Base.extend(
|
|
15400
15652
|
* - Observes for paste and drop
|
15401
15653
|
*/
|
15402
15654
|
_initParser: function() {
|
15403
|
-
var oldHtml
|
15404
|
-
cleanHtml;
|
15655
|
+
var oldHtml;
|
15405
15656
|
|
15406
15657
|
if (wysihtml5.browser.supportsModernPaste()) {
|
15407
15658
|
this.on("paste:composer", function(event) {
|
@@ -15510,28 +15761,18 @@ wysihtml5.views.View = Base.extend(
|
|
15510
15761
|
callbackWrapper(event);
|
15511
15762
|
}
|
15512
15763
|
if (keyCode === wysihtml5.ESCAPE_KEY) {
|
15513
|
-
that.
|
15514
|
-
that.hide();
|
15764
|
+
that.cancel();
|
15515
15765
|
}
|
15516
15766
|
});
|
15517
15767
|
|
15518
15768
|
dom.delegate(this.container, "[data-wysihtml5-dialog-action=save]", "click", callbackWrapper);
|
15519
15769
|
|
15520
15770
|
dom.delegate(this.container, "[data-wysihtml5-dialog-action=cancel]", "click", function(event) {
|
15521
|
-
that.
|
15522
|
-
that.hide();
|
15771
|
+
that.cancel();
|
15523
15772
|
event.preventDefault();
|
15524
15773
|
event.stopPropagation();
|
15525
15774
|
});
|
15526
15775
|
|
15527
|
-
var formElements = this.container.querySelectorAll(SELECTOR_FORM_ELEMENTS),
|
15528
|
-
i = 0,
|
15529
|
-
length = formElements.length,
|
15530
|
-
_clearInterval = function() { clearInterval(that.interval); };
|
15531
|
-
for (; i<length; i++) {
|
15532
|
-
dom.observe(formElements[i], "change", _clearInterval);
|
15533
|
-
}
|
15534
|
-
|
15535
15776
|
this._observed = true;
|
15536
15777
|
},
|
15537
15778
|
|
@@ -15597,25 +15838,25 @@ wysihtml5.views.View = Base.extend(
|
|
15597
15838
|
}
|
15598
15839
|
},
|
15599
15840
|
|
15841
|
+
update: function (elementToChange) {
|
15842
|
+
this.elementToChange = elementToChange ? elementToChange : this.elementToChange;
|
15843
|
+
this._interpolate();
|
15844
|
+
},
|
15845
|
+
|
15600
15846
|
/**
|
15601
15847
|
* Show the dialog element
|
15602
15848
|
*/
|
15603
15849
|
show: function(elementToChange) {
|
15604
|
-
|
15605
|
-
return;
|
15606
|
-
}
|
15850
|
+
var firstField = this.container.querySelector(SELECTOR_FORM_ELEMENTS);
|
15607
15851
|
|
15608
|
-
var that = this,
|
15609
|
-
firstField = this.container.querySelector(SELECTOR_FORM_ELEMENTS);
|
15610
|
-
this.elementToChange = elementToChange;
|
15611
15852
|
this._observe();
|
15612
|
-
this.
|
15613
|
-
|
15614
|
-
this.interval = setInterval(function() { that._interpolate(true); }, 500);
|
15615
|
-
}
|
15853
|
+
this.update(elementToChange);
|
15854
|
+
|
15616
15855
|
dom.addClass(this.link, CLASS_NAME_OPENED);
|
15617
15856
|
this.container.style.display = "";
|
15857
|
+
this.isOpen = true;
|
15618
15858
|
this.fire("show");
|
15859
|
+
|
15619
15860
|
if (firstField && !elementToChange) {
|
15620
15861
|
try {
|
15621
15862
|
firstField.focus();
|
@@ -15626,15 +15867,24 @@ wysihtml5.views.View = Base.extend(
|
|
15626
15867
|
/**
|
15627
15868
|
* Hide the dialog element
|
15628
15869
|
*/
|
15629
|
-
|
15630
|
-
clearInterval(this.interval);
|
15870
|
+
_hide: function(focus) {
|
15631
15871
|
this.elementToChange = null;
|
15632
15872
|
dom.removeClass(this.link, CLASS_NAME_OPENED);
|
15633
15873
|
this.container.style.display = "none";
|
15874
|
+
this.isOpen = false;
|
15875
|
+
},
|
15876
|
+
|
15877
|
+
hide: function() {
|
15878
|
+
this._hide();
|
15879
|
+
this.fire("hide");
|
15880
|
+
},
|
15881
|
+
|
15882
|
+
cancel: function() {
|
15883
|
+
this._hide();
|
15634
15884
|
this.fire("cancel");
|
15635
15885
|
}
|
15636
15886
|
});
|
15637
|
-
})(wysihtml5);
|
15887
|
+
})(wysihtml5); //jshint ignore:line
|
15638
15888
|
;/**
|
15639
15889
|
* Converts speech-to-text and inserts this into the editor
|
15640
15890
|
* As of now (2011/03/25) this only is supported in Chrome >= 11
|
@@ -15817,8 +16067,7 @@ wysihtml5.views.View = Base.extend(
|
|
15817
16067
|
_getDialog: function(link, command) {
|
15818
16068
|
var that = this,
|
15819
16069
|
dialogElement = this.container.querySelector("[data-wysihtml5-dialog='" + command + "']"),
|
15820
|
-
dialog,
|
15821
|
-
caretBookmark;
|
16070
|
+
dialog, caretBookmark;
|
15822
16071
|
|
15823
16072
|
if (dialogElement) {
|
15824
16073
|
if (wysihtml5.toolbar["Dialog_" + command]) {
|
@@ -15829,7 +16078,6 @@ wysihtml5.views.View = Base.extend(
|
|
15829
16078
|
|
15830
16079
|
dialog.on("show", function() {
|
15831
16080
|
caretBookmark = that.composer.selection.getBookmark();
|
15832
|
-
|
15833
16081
|
that.editor.fire("show:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
15834
16082
|
});
|
15835
16083
|
|
@@ -15838,14 +16086,27 @@ wysihtml5.views.View = Base.extend(
|
|
15838
16086
|
that.composer.selection.setBookmark(caretBookmark);
|
15839
16087
|
}
|
15840
16088
|
that._execCommand(command, attributes);
|
15841
|
-
|
15842
16089
|
that.editor.fire("save:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
16090
|
+
that._hideAllDialogs();
|
16091
|
+
that._preventInstantFocus();
|
16092
|
+
caretBookmark = undefined;
|
16093
|
+
|
15843
16094
|
});
|
15844
16095
|
|
15845
16096
|
dialog.on("cancel", function() {
|
15846
|
-
|
16097
|
+
if (caretBookmark) {
|
16098
|
+
that.composer.selection.setBookmark(caretBookmark);
|
16099
|
+
}
|
15847
16100
|
that.editor.fire("cancel:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
16101
|
+
caretBookmark = undefined;
|
16102
|
+
that._preventInstantFocus();
|
15848
16103
|
});
|
16104
|
+
|
16105
|
+
dialog.on("hide", function() {
|
16106
|
+
that.editor.fire("hide:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
16107
|
+
caretBookmark = undefined;
|
16108
|
+
});
|
16109
|
+
|
15849
16110
|
}
|
15850
16111
|
return dialog;
|
15851
16112
|
},
|
@@ -15861,14 +16122,7 @@ wysihtml5.views.View = Base.extend(
|
|
15861
16122
|
return;
|
15862
16123
|
}
|
15863
16124
|
|
15864
|
-
|
15865
|
-
|
15866
|
-
// Show dialog when available
|
15867
|
-
if (commandObj && commandObj.dialog && !commandObj.state) {
|
15868
|
-
commandObj.dialog.show();
|
15869
|
-
} else {
|
15870
|
-
this._execCommand(command, commandValue);
|
15871
|
-
}
|
16125
|
+
this._execCommand(command, commandValue);
|
15872
16126
|
},
|
15873
16127
|
|
15874
16128
|
_execCommand: function(command, commandValue) {
|
@@ -15918,10 +16172,19 @@ wysihtml5.views.View = Base.extend(
|
|
15918
16172
|
dom.delegate(container, "[data-wysihtml5-command], [data-wysihtml5-action]", "mousedown", function(event) { event.preventDefault(); });
|
15919
16173
|
|
15920
16174
|
dom.delegate(container, "[data-wysihtml5-command]", "click", function(event) {
|
15921
|
-
var
|
16175
|
+
var state,
|
16176
|
+
link = this,
|
15922
16177
|
command = link.getAttribute("data-wysihtml5-command"),
|
15923
|
-
commandValue = link.getAttribute("data-wysihtml5-command-value")
|
15924
|
-
|
16178
|
+
commandValue = link.getAttribute("data-wysihtml5-command-value"),
|
16179
|
+
commandObj = that.commandMapping[command + ":" + commandValue];
|
16180
|
+
|
16181
|
+
if (commandValue || !commandObj.dialog) {
|
16182
|
+
that.execCommand(command, commandValue);
|
16183
|
+
} else {
|
16184
|
+
state = getCommandState(that.composer, commandObj);
|
16185
|
+
commandObj.dialog.show(state);
|
16186
|
+
}
|
16187
|
+
|
15925
16188
|
event.preventDefault();
|
15926
16189
|
});
|
15927
16190
|
|
@@ -15931,21 +16194,26 @@ wysihtml5.views.View = Base.extend(
|
|
15931
16194
|
event.preventDefault();
|
15932
16195
|
});
|
15933
16196
|
|
15934
|
-
editor.on("interaction:composer", function() {
|
16197
|
+
editor.on("interaction:composer", function(event) {
|
16198
|
+
if (!that.preventFocus) {
|
15935
16199
|
that._updateLinkStates();
|
16200
|
+
}
|
15936
16201
|
});
|
15937
16202
|
|
15938
|
-
|
15939
|
-
that.
|
15940
|
-
|
16203
|
+
this.container.ownerDocument.addEventListener("click", function(event) {
|
16204
|
+
if (!wysihtml5.dom.contains(that.container, event.target) && !wysihtml5.dom.contains(that.composer.element, event.target)) {
|
16205
|
+
that._updateLinkStates();
|
16206
|
+
that._preventInstantFocus();
|
16207
|
+
}
|
16208
|
+
}, false);
|
15941
16209
|
|
15942
16210
|
if (this.editor.config.handleTables) {
|
15943
|
-
|
15944
|
-
|
15945
|
-
|
15946
|
-
|
15947
|
-
|
15948
|
-
|
16211
|
+
editor.on("tableselect:composer", function() {
|
16212
|
+
that.container.querySelectorAll('[data-wysihtml5-hiddentools="table"]')[0].style.display = "";
|
16213
|
+
});
|
16214
|
+
editor.on("tableunselect:composer", function() {
|
16215
|
+
that.container.querySelectorAll('[data-wysihtml5-hiddentools="table"]')[0].style.display = "none";
|
16216
|
+
});
|
15949
16217
|
}
|
15950
16218
|
|
15951
16219
|
editor.on("change_view", function(currentView) {
|
@@ -15962,15 +16230,28 @@ wysihtml5.views.View = Base.extend(
|
|
15962
16230
|
});
|
15963
16231
|
},
|
15964
16232
|
|
16233
|
+
_hideAllDialogs: function() {
|
16234
|
+
var commandMapping = this.commandMapping;
|
16235
|
+
for (var i in commandMapping) {
|
16236
|
+
if (commandMapping[i].dialog) {
|
16237
|
+
commandMapping[i].dialog.hide();
|
16238
|
+
}
|
16239
|
+
}
|
16240
|
+
},
|
16241
|
+
|
16242
|
+
_preventInstantFocus: function() {
|
16243
|
+
this.preventFocus = true;
|
16244
|
+
setTimeout(function() {
|
16245
|
+
this.preventFocus = false;
|
16246
|
+
}.bind(this),0);
|
16247
|
+
},
|
16248
|
+
|
15965
16249
|
_updateLinkStates: function() {
|
15966
16250
|
|
15967
|
-
var
|
15968
|
-
|
15969
|
-
|
15970
|
-
|
15971
|
-
state,
|
15972
|
-
action,
|
15973
|
-
command;
|
16251
|
+
var i, state, action, command, displayDialogAttributeValue,
|
16252
|
+
commandMapping = this.commandMapping,
|
16253
|
+
composer = this.composer,
|
16254
|
+
actionMapping = this.actionMapping;
|
15974
16255
|
// every millisecond counts... this is executed quite often
|
15975
16256
|
for (i in commandMapping) {
|
15976
16257
|
command = commandMapping[i];
|
@@ -16003,18 +16284,21 @@ wysihtml5.views.View = Base.extend(
|
|
16003
16284
|
if (command.group) {
|
16004
16285
|
dom.addClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
16005
16286
|
}
|
16006
|
-
|
16007
|
-
|
16008
|
-
|
16009
|
-
|
16010
|
-
|
16011
|
-
|
16012
|
-
|
16013
|
-
|
16014
|
-
|
16015
|
-
|
16287
|
+
// commands with fixed value can not have a dialog.
|
16288
|
+
if (command.dialog && (typeof command.value === "undefined" || command.value === null)) {
|
16289
|
+
if (state && typeof state === "object") {
|
16290
|
+
state = getCommandState(composer, command);
|
16291
|
+
command.state = state;
|
16292
|
+
|
16293
|
+
// If dialog has dataset.showdialogonselection set as true,
|
16294
|
+
// Dialog displays on text state becoming active regardless of clobal showToolbarDialogsOnSelection options value
|
16295
|
+
displayDialogAttributeValue = command.dialog.container.dataset ? command.dialog.container.dataset.showdialogonselection : false;
|
16296
|
+
|
16297
|
+
if (composer.config.showToolbarDialogsOnSelection || displayDialogAttributeValue) {
|
16298
|
+
command.dialog.show(state);
|
16299
|
+
} else {
|
16300
|
+
command.dialog.update(state);
|
16016
16301
|
}
|
16017
|
-
command.dialog.show(state);
|
16018
16302
|
} else {
|
16019
16303
|
command.dialog.hide();
|
16020
16304
|
}
|
@@ -16028,7 +16312,8 @@ wysihtml5.views.View = Base.extend(
|
|
16028
16312
|
if (command.group) {
|
16029
16313
|
dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
16030
16314
|
}
|
16031
|
-
|
16315
|
+
// commands with fixed value can not have a dialog.
|
16316
|
+
if (command.dialog && !command.value) {
|
16032
16317
|
command.dialog.hide();
|
16033
16318
|
}
|
16034
16319
|
}
|
@@ -16058,6 +16343,20 @@ wysihtml5.views.View = Base.extend(
|
|
16058
16343
|
}
|
16059
16344
|
});
|
16060
16345
|
|
16346
|
+
function getCommandState (composer, command) {
|
16347
|
+
var state = composer.commands.state(command.name, command.value);
|
16348
|
+
|
16349
|
+
// Grab first and only object/element in state array, otherwise convert state into boolean
|
16350
|
+
// to avoid showing a dialog for multiple selected elements which may have different attributes
|
16351
|
+
// eg. when two links with different href are selected, the state will be an array consisting of both link elements
|
16352
|
+
// but the dialog interface can only update one
|
16353
|
+
if (!command.dialog.multiselect && wysihtml5.lang.object(state).isArray()) {
|
16354
|
+
state = state.length === 1 ? state[0] : true;
|
16355
|
+
}
|
16356
|
+
|
16357
|
+
return state;
|
16358
|
+
}
|
16359
|
+
|
16061
16360
|
})(wysihtml5);
|
16062
16361
|
;(function(wysihtml5) {
|
16063
16362
|
wysihtml5.toolbar.Dialog_createTable = wysihtml5.toolbar.Dialog.extend({
|
@@ -16067,8 +16366,7 @@ wysihtml5.views.View = Base.extend(
|
|
16067
16366
|
});
|
16068
16367
|
})(wysihtml5);
|
16069
16368
|
;(function(wysihtml5) {
|
16070
|
-
var
|
16071
|
-
SELECTOR_FIELDS = "[data-wysihtml5-dialog-field]",
|
16369
|
+
var SELECTOR_FIELDS = "[data-wysihtml5-dialog-field]",
|
16072
16370
|
ATTRIBUTE_FIELDS = "data-wysihtml5-dialog-field";
|
16073
16371
|
|
16074
16372
|
wysihtml5.toolbar.Dialog_foreColorStyle = wysihtml5.toolbar.Dialog.extend({
|
@@ -16087,16 +16385,15 @@ wysihtml5.views.View = Base.extend(
|
|
16087
16385
|
},
|
16088
16386
|
|
16089
16387
|
_interpolate: function(avoidHiddenFields) {
|
16090
|
-
var field,
|
16091
|
-
|
16092
|
-
newValue,
|
16388
|
+
var field, colourMode,
|
16389
|
+
styleParser = wysihtml5.quirks.styleParser,
|
16093
16390
|
focusedElement = document.querySelector(":focus"),
|
16094
16391
|
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
16095
16392
|
length = fields.length,
|
16096
16393
|
i = 0,
|
16097
16394
|
firstElement = (this.elementToChange) ? ((wysihtml5.lang.object(this.elementToChange).isArray()) ? this.elementToChange[0] : this.elementToChange) : null,
|
16098
|
-
|
16099
|
-
|
16395
|
+
colourStr = (firstElement) ? firstElement.getAttribute("style") : null,
|
16396
|
+
colour = (colourStr) ? styleParser.parseColor(colourStr, "color") : null;
|
16100
16397
|
|
16101
16398
|
for (; i<length; i++) {
|
16102
16399
|
field = fields[i];
|
@@ -16109,14 +16406,13 @@ wysihtml5.views.View = Base.extend(
|
|
16109
16406
|
continue;
|
16110
16407
|
}
|
16111
16408
|
if (field.getAttribute(ATTRIBUTE_FIELDS) === "color") {
|
16112
|
-
|
16113
|
-
|
16114
|
-
|
16115
|
-
|
16116
|
-
|
16117
|
-
}
|
16409
|
+
colourMode = (field.dataset.colormode || "rgb").toLowerCase();
|
16410
|
+
colourMode = colourMode === "hex" ? "hash" : colourMode;
|
16411
|
+
|
16412
|
+
if (colour) {
|
16413
|
+
field.value = styleParser.unparseColor(colour, colourMode);
|
16118
16414
|
} else {
|
16119
|
-
field.value =
|
16415
|
+
field.value = styleParser.unparseColor([0, 0, 0], colourMode);
|
16120
16416
|
}
|
16121
16417
|
}
|
16122
16418
|
}
|
@@ -16147,6 +16443,5 @@ wysihtml5.views.View = Base.extend(
|
|
16147
16443
|
field.value = size;
|
16148
16444
|
}
|
16149
16445
|
}
|
16150
|
-
|
16151
16446
|
});
|
16152
16447
|
})(wysihtml5);
|