wysihtml-rails 0.5.0.beta6 → 0.5.0.beta7
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 +79 -47
- data/vendor/assets/javascripts/wysihtml.js +79 -47
- 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: 64f3d46ae259b28d6540ada222ddc2254e450305
|
4
|
+
data.tar.gz: b6124307107e3a712ad473e5461da9ca128c1e8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d741717b1e1b496c1f3073f6b7a1ed16bd891ef69d5712342a860befc67880cef51e5e630dbd7cea70f48d7517404d065ceabb4671b0863e9a3e8088c44d8890
|
7
|
+
data.tar.gz: 1eca60fa61f5ef49a5e21873ff6a5610622b059a1e06687c0776215e489d62344fc9c43d716ff1d1343ce8bdbeca8ae880aaebeb4683948031587f8da3732dcd
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @license
|
3
|
-
* https://github.com/
|
2
|
+
* @license wysihtml v0.5.0-beta7
|
3
|
+
* https://github.com/Voog/wysihtml
|
4
4
|
*
|
5
5
|
* Author: Christopher Blum (https://github.com/tiff)
|
6
6
|
* Secondary author of extended features: Oliver Pulges (https://github.com/pulges)
|
@@ -10,7 +10,7 @@
|
|
10
10
|
*
|
11
11
|
*/
|
12
12
|
var wysihtml5 = {
|
13
|
-
version: "0.5.0-
|
13
|
+
version: "0.5.0-beta7",
|
14
14
|
|
15
15
|
// namespaces
|
16
16
|
commands: {},
|
@@ -5081,9 +5081,17 @@ wysihtml5.browser = (function() {
|
|
5081
5081
|
* wysihtml5.lang.object({ foo: 1, bar: 1 }).merge({ bar: 2, baz: 3 }).get();
|
5082
5082
|
* // => { foo: 1, bar: 2, baz: 3 }
|
5083
5083
|
*/
|
5084
|
-
merge: function(otherObj) {
|
5084
|
+
merge: function(otherObj, deep) {
|
5085
5085
|
for (var i in otherObj) {
|
5086
|
-
obj[i]
|
5086
|
+
if (deep && wysihtml5.lang.object(otherObj[i]).isPlainObject() && (typeof obj[i] === "undefined" || wysihtml5.lang.object(obj[i]).isPlainObject())) {
|
5087
|
+
if (typeof obj[i] === "undefined") {
|
5088
|
+
obj[i] = wysihtml5.lang.object(otherObj[i]).clone(true);
|
5089
|
+
} else {
|
5090
|
+
wysihtml5.lang.object(obj[i]).merge(wysihtml5.lang.object(otherObj[i]).clone(true));
|
5091
|
+
}
|
5092
|
+
} else {
|
5093
|
+
obj[i] = wysihtml5.lang.object(otherObj[i]).isPlainObject() ? wysihtml5.lang.object(otherObj[i]).clone(true) : otherObj[i];
|
5094
|
+
}
|
5087
5095
|
}
|
5088
5096
|
return this;
|
5089
5097
|
},
|
@@ -5138,7 +5146,7 @@ wysihtml5.browser = (function() {
|
|
5138
5146
|
},
|
5139
5147
|
|
5140
5148
|
isPlainObject: function () {
|
5141
|
-
return Object.prototype.toString.call(obj) === '[object Object]';
|
5149
|
+
return obj && Object.prototype.toString.call(obj) === '[object Object]';
|
5142
5150
|
}
|
5143
5151
|
};
|
5144
5152
|
};
|
@@ -6696,11 +6704,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6696
6704
|
newAttributeValue;
|
6697
6705
|
|
6698
6706
|
if (method) {
|
6699
|
-
|
6700
|
-
|
6701
|
-
|
6702
|
-
return newAttributeValue;
|
6703
|
-
}
|
6707
|
+
newAttributeValue = method(attributeValue, nodeName);
|
6708
|
+
if (typeof(newAttributeValue) === "string") {
|
6709
|
+
return newAttributeValue;
|
6704
6710
|
}
|
6705
6711
|
}
|
6706
6712
|
|
@@ -6935,9 +6941,13 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6935
6941
|
|
6936
6942
|
alt: (function() {
|
6937
6943
|
var REG_EXP = /[^ a-z0-9_\-]/gi;
|
6938
|
-
return function(attributeValue) {
|
6944
|
+
return function(attributeValue, nodeName) {
|
6939
6945
|
if (!attributeValue) {
|
6940
|
-
|
6946
|
+
if (nodeName === "IMG") {
|
6947
|
+
return "";
|
6948
|
+
} else {
|
6949
|
+
return null;
|
6950
|
+
}
|
6941
6951
|
}
|
6942
6952
|
return attributeValue.replace(REG_EXP, "");
|
6943
6953
|
};
|
@@ -6963,6 +6973,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6963
6973
|
|
6964
6974
|
any: (function() {
|
6965
6975
|
return function(attributeValue) {
|
6976
|
+
if (!attributeValue) {
|
6977
|
+
return null;
|
6978
|
+
}
|
6966
6979
|
return attributeValue;
|
6967
6980
|
};
|
6968
6981
|
})()
|
@@ -7320,6 +7333,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7320
7333
|
constructor: function(readyCallback, config) {
|
7321
7334
|
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
|
7322
7335
|
this.config = wysihtml5.lang.object({}).merge(config).get();
|
7336
|
+
if (!this.config.className) {
|
7337
|
+
this.config.className = "wysihtml5-sandbox";
|
7338
|
+
}
|
7323
7339
|
this.editableArea = this._createIframe();
|
7324
7340
|
},
|
7325
7341
|
|
@@ -7374,7 +7390,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7374
7390
|
_createIframe: function() {
|
7375
7391
|
var that = this,
|
7376
7392
|
iframe = doc.createElement("iframe");
|
7377
|
-
iframe.className =
|
7393
|
+
iframe.className = this.config.className;
|
7378
7394
|
wysihtml5.dom.setAttributes({
|
7379
7395
|
"security": "restricted",
|
7380
7396
|
"allowtransparency": "true",
|
@@ -7537,6 +7553,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7537
7553
|
constructor: function(readyCallback, config, contentEditable) {
|
7538
7554
|
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
|
7539
7555
|
this.config = wysihtml5.lang.object({}).merge(config).get();
|
7556
|
+
if (!this.config.className) {
|
7557
|
+
this.config.className = "wysihtml5-sandbox";
|
7558
|
+
}
|
7540
7559
|
if (contentEditable) {
|
7541
7560
|
this.element = this._bindElement(contentEditable);
|
7542
7561
|
} else {
|
@@ -7547,7 +7566,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7547
7566
|
// creates a new contenteditable and initiates it
|
7548
7567
|
_createElement: function() {
|
7549
7568
|
var element = doc.createElement("div");
|
7550
|
-
element.className =
|
7569
|
+
element.className = this.config.className;
|
7551
7570
|
this._loadElement(element);
|
7552
7571
|
return element;
|
7553
7572
|
},
|
@@ -7626,8 +7645,8 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7626
7645
|
* wysihtml.dom.simulatePlaceholder(this, composer, "Foobar");
|
7627
7646
|
*/
|
7628
7647
|
(function(dom) {
|
7629
|
-
dom.simulatePlaceholder = function(editor, view, placeholderText) {
|
7630
|
-
var CLASS_NAME = "placeholder",
|
7648
|
+
dom.simulatePlaceholder = function(editor, view, placeholderText, placeholderClassName) {
|
7649
|
+
var CLASS_NAME = placeholderClassName || "wysihtml5-placeholder",
|
7631
7650
|
unset = function() {
|
7632
7651
|
var composerIsVisible = view.element.offsetWidth > 0 && view.element.offsetHeight > 0;
|
7633
7652
|
if (view.hasPlaceholderSet()) {
|
@@ -11355,7 +11374,7 @@ wysihtml5.Commands = Base.extend(
|
|
11355
11374
|
function cleanup(composer) {
|
11356
11375
|
var container = composer.element,
|
11357
11376
|
allElements = container.querySelectorAll(BLOCK_ELEMENTS),
|
11358
|
-
uneditables = container.querySelectorAll(composer.config.
|
11377
|
+
uneditables = container.querySelectorAll(composer.config.classNames.uneditableContainer),
|
11359
11378
|
elements = wysihtml5.lang.array(allElements).without(uneditables);
|
11360
11379
|
|
11361
11380
|
for (var i = elements.length; i--;) {
|
@@ -11627,7 +11646,7 @@ wysihtml5.Commands = Base.extend(
|
|
11627
11646
|
state = this.state(composer, command, options);
|
11628
11647
|
if (state) {
|
11629
11648
|
bookmark = rangy.saveSelection(composer.win);
|
11630
|
-
for (var j
|
11649
|
+
for (var j = 0, jmax = state.length; j < jmax; j++) {
|
11631
11650
|
removeOptionsFromElement(state[j], options, composer);
|
11632
11651
|
}
|
11633
11652
|
}
|
@@ -11650,7 +11669,7 @@ wysihtml5.Commands = Base.extend(
|
|
11650
11669
|
composer.selection.selectLine();
|
11651
11670
|
}
|
11652
11671
|
}
|
11653
|
-
|
11672
|
+
|
11654
11673
|
// And get all selection ranges of current composer and iterat
|
11655
11674
|
ranges = composer.selection.getOwnRanges();
|
11656
11675
|
for (var i = ranges.length; i--;) {
|
@@ -12212,7 +12231,7 @@ wysihtml5.Commands = Base.extend(
|
|
12212
12231
|
|
12213
12232
|
if (tempElement) {
|
12214
12233
|
isEmpty = wysihtml5.lang.array(["", "<br>", wysihtml5.INVISIBLE_SPACE]).contains(tempElement.innerHTML);
|
12215
|
-
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.
|
12234
|
+
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.classNames.uneditableContainer);
|
12216
12235
|
if (isEmpty) {
|
12217
12236
|
composer.selection.selectNode(list.querySelector("li"), true);
|
12218
12237
|
}
|
@@ -12441,7 +12460,7 @@ wysihtml5.Commands = Base.extend(
|
|
12441
12460
|
for (row = 0; row < value.rows; row ++) {
|
12442
12461
|
html += '<tr>';
|
12443
12462
|
for (col = 0; col < value.cols; col ++) {
|
12444
|
-
html += "<td></td>";
|
12463
|
+
html += "<td><br></td>";
|
12445
12464
|
}
|
12446
12465
|
html += '</tr>';
|
12447
12466
|
}
|
@@ -13123,14 +13142,17 @@ wysihtml5.views.View = Base.extend(
|
|
13123
13142
|
|
13124
13143
|
_initContentEditableArea: function() {
|
13125
13144
|
var that = this;
|
13126
|
-
|
13127
13145
|
if (this.config.noTextarea) {
|
13128
13146
|
this.sandbox = new dom.ContentEditableArea(function() {
|
13129
13147
|
that._create();
|
13130
|
-
}, {
|
13148
|
+
}, {
|
13149
|
+
className: this.config.classNames.sandbox
|
13150
|
+
}, this.editableArea);
|
13131
13151
|
} else {
|
13132
13152
|
this.sandbox = new dom.ContentEditableArea(function() {
|
13133
13153
|
that._create();
|
13154
|
+
}, {
|
13155
|
+
className: this.config.classNames.sandbox
|
13134
13156
|
});
|
13135
13157
|
this.editableArea = this.sandbox.getContentEditable();
|
13136
13158
|
dom.insert(this.editableArea).after(this.textarea.element);
|
@@ -13140,11 +13162,11 @@ wysihtml5.views.View = Base.extend(
|
|
13140
13162
|
|
13141
13163
|
_initSandbox: function() {
|
13142
13164
|
var that = this;
|
13143
|
-
|
13144
13165
|
this.sandbox = new dom.Sandbox(function() {
|
13145
13166
|
that._create();
|
13146
13167
|
}, {
|
13147
|
-
stylesheets: this.config.stylesheets
|
13168
|
+
stylesheets: this.config.stylesheets,
|
13169
|
+
className: this.config.classNames.sandbox
|
13148
13170
|
});
|
13149
13171
|
this.editableArea = this.sandbox.getIframe();
|
13150
13172
|
|
@@ -13178,7 +13200,7 @@ wysihtml5.views.View = Base.extend(
|
|
13178
13200
|
}
|
13179
13201
|
|
13180
13202
|
// Make sure our selection handler is ready
|
13181
|
-
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.
|
13203
|
+
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.classNames.uneditableContainer);
|
13182
13204
|
|
13183
13205
|
// Make sure commands dispatcher is ready
|
13184
13206
|
this.commands = new wysihtml5.Commands(this.parent);
|
@@ -13189,7 +13211,7 @@ wysihtml5.views.View = Base.extend(
|
|
13189
13211
|
]).from(this.textarea.element).to(this.element);
|
13190
13212
|
}
|
13191
13213
|
|
13192
|
-
dom.addClass(this.element, this.config.
|
13214
|
+
dom.addClass(this.element, this.config.classNames.composer);
|
13193
13215
|
//
|
13194
13216
|
// Make the editor look like the original textarea, by syncing styles
|
13195
13217
|
if (this.config.style && !this.config.contentEditableMode) {
|
@@ -13215,7 +13237,7 @@ wysihtml5.views.View = Base.extend(
|
|
13215
13237
|
? this.config.placeholder
|
13216
13238
|
: ((this.config.noTextarea) ? this.editableArea.getAttribute("data-placeholder") : this.textarea.element.getAttribute("placeholder"));
|
13217
13239
|
if (placeholderText) {
|
13218
|
-
dom.simulatePlaceholder(this.parent, this, placeholderText);
|
13240
|
+
dom.simulatePlaceholder(this.parent, this, placeholderText, this.config.classNames.placeholder);
|
13219
13241
|
}
|
13220
13242
|
|
13221
13243
|
// Make sure that the browser avoids using inline styles whenever possible
|
@@ -13267,7 +13289,7 @@ wysihtml5.views.View = Base.extend(
|
|
13267
13289
|
this.parent.on("newword:composer", function() {
|
13268
13290
|
if (dom.getTextContent(that.element).match(dom.autoLink.URL_REG_EXP)) {
|
13269
13291
|
var nodeWithSelection = that.selection.getSelectedNode(),
|
13270
|
-
uneditables = that.element.querySelectorAll("." + that.config.
|
13292
|
+
uneditables = that.element.querySelectorAll("." + that.config.classNames.uneditableContainer),
|
13271
13293
|
isInUneditable = false;
|
13272
13294
|
|
13273
13295
|
for (var i = uneditables.length; i--;) {
|
@@ -13276,12 +13298,12 @@ wysihtml5.views.View = Base.extend(
|
|
13276
13298
|
}
|
13277
13299
|
}
|
13278
13300
|
|
13279
|
-
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.
|
13301
|
+
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.classNames.uneditableContainer]);
|
13280
13302
|
}
|
13281
13303
|
});
|
13282
13304
|
|
13283
13305
|
dom.observe(this.element, "blur", function() {
|
13284
|
-
dom.autoLink(that.element, [that.config.
|
13306
|
+
dom.autoLink(that.element, [that.config.classNames.uneditableContainer]);
|
13285
13307
|
});
|
13286
13308
|
}
|
13287
13309
|
|
@@ -13716,7 +13738,7 @@ wysihtml5.views.View = Base.extend(
|
|
13716
13738
|
// If found an uneditable before caret then notify it before deletion
|
13717
13739
|
var handleUneditableDeletion = function(composer) {
|
13718
13740
|
var before = composer.selection.getBeforeSelection(true);
|
13719
|
-
if (before && (before.type === "element" || before.type === "leafnode") && before.node.nodeType === 1 && before.node.classList.contains(composer.config.
|
13741
|
+
if (before && (before.type === "element" || before.type === "leafnode") && before.node.nodeType === 1 && before.node.classList.contains(composer.config.classNames.uneditableContainer)) {
|
13720
13742
|
if (fixLastBrDeletionInTable(composer, true)) {
|
13721
13743
|
return true;
|
13722
13744
|
}
|
@@ -13881,7 +13903,7 @@ wysihtml5.views.View = Base.extend(
|
|
13881
13903
|
// Make sure that images are selected when clicking on them
|
13882
13904
|
var target = event.target,
|
13883
13905
|
allImages = this.element.querySelectorAll('img'),
|
13884
|
-
notMyImages = this.element.querySelectorAll('.' + this.config.
|
13906
|
+
notMyImages = this.element.querySelectorAll('.' + this.config.classNames.uneditableContainer + ' img'),
|
13885
13907
|
myImages = wysihtml5.lang.array(allImages).without(notMyImages);
|
13886
13908
|
|
13887
13909
|
if (target.nodeName === "IMG" && wysihtml5.lang.array(myImages).contains(target)) {
|
@@ -13911,10 +13933,10 @@ wysihtml5.views.View = Base.extend(
|
|
13911
13933
|
};
|
13912
13934
|
|
13913
13935
|
var handleClick = function(event) {
|
13914
|
-
if (this.config.
|
13936
|
+
if (this.config.classNames.uneditableContainer) {
|
13915
13937
|
// If uneditables is configured, makes clicking on uneditable move caret after clicked element (so it can be deleted like text)
|
13916
13938
|
// If uneditable needs text selection itself event.stopPropagation can be used to prevent this behaviour
|
13917
|
-
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.
|
13939
|
+
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.classNames.uneditableContainer }, false, this.element);
|
13918
13940
|
if (uneditable) {
|
13919
13941
|
this.selection.setAfter(uneditable);
|
13920
13942
|
}
|
@@ -14338,10 +14360,6 @@ wysihtml5.views.View = Base.extend(
|
|
14338
14360
|
pasteParserRulesets: null,
|
14339
14361
|
// Parser method to use when the user inserts content
|
14340
14362
|
parser: wysihtml5.dom.parse,
|
14341
|
-
// Class name which should be set on the contentEditable element in the created sandbox iframe, can be styled via the 'stylesheets' option
|
14342
|
-
composerClassName: "wysihtml5-editor",
|
14343
|
-
// Class name to add to the body when the wysihtml5 editor is supported
|
14344
|
-
bodyClassName: "wysihtml5-supported",
|
14345
14363
|
// By default wysihtml5 will insert a <br> for line breaks, set this to false to use <p>
|
14346
14364
|
useLineBreaks: true,
|
14347
14365
|
// Array (or single string) of stylesheet urls to be loaded in the editor's iframe
|
@@ -14354,9 +14372,18 @@ wysihtml5.views.View = Base.extend(
|
|
14354
14372
|
cleanUp: true,
|
14355
14373
|
// Whether to use div instead of secure iframe
|
14356
14374
|
contentEditableMode: false,
|
14357
|
-
|
14358
|
-
|
14359
|
-
|
14375
|
+
classNames: {
|
14376
|
+
// Class name which should be set on the contentEditable element in the created sandbox iframe, can be styled via the 'stylesheets' option
|
14377
|
+
composer: "wysihtml5-editor",
|
14378
|
+
// Class name to add to the body when the wysihtml5 editor is supported
|
14379
|
+
body: "wysihtml5-supported",
|
14380
|
+
// classname added to editable area element (iframe/div) on creation
|
14381
|
+
sandbox: "wysihtml5-sandbox",
|
14382
|
+
// class on editable area with placeholder
|
14383
|
+
placeholder: "wysihtml5-placeholder",
|
14384
|
+
// Classname of container that editor should not touch and pass through
|
14385
|
+
uneditableContainer: "wysihtml5-uneditable-container"
|
14386
|
+
},
|
14360
14387
|
// Browsers that support copied source handling will get a marking of the origin of the copied source (for determinig code cleanup rules on paste)
|
14361
14388
|
// Also copied source is based directly on selection -
|
14362
14389
|
// (very useful for webkit based browsers where copy will otherwise contain a lot of code and styles based on whatever and not actually in selection).
|
@@ -14368,9 +14395,14 @@ wysihtml5.views.View = Base.extend(
|
|
14368
14395
|
/** @scope wysihtml5.Editor.prototype */ {
|
14369
14396
|
constructor: function(editableElement, config) {
|
14370
14397
|
this.editableElement = typeof(editableElement) === "string" ? document.getElementById(editableElement) : editableElement;
|
14371
|
-
this.config = wysihtml5.lang.object({}).merge(defaultConfig).merge(config).get();
|
14398
|
+
this.config = wysihtml5.lang.object({}).merge(defaultConfig).merge(config, true).get();
|
14372
14399
|
this._isCompatible = wysihtml5.browser.supported();
|
14373
14400
|
|
14401
|
+
// make sure that rules override instead of extend
|
14402
|
+
if (config && config.parserRules) {
|
14403
|
+
this.config.parserRules = wysihtml5.lang.object(config.parserRules).clone(true);
|
14404
|
+
}
|
14405
|
+
|
14374
14406
|
if (this.editableElement.nodeName.toLowerCase() != "textarea") {
|
14375
14407
|
this.config.contentEditableMode = true;
|
14376
14408
|
this.config.noTextarea = true;
|
@@ -14388,7 +14420,7 @@ wysihtml5.views.View = Base.extend(
|
|
14388
14420
|
}
|
14389
14421
|
|
14390
14422
|
// Add class name to body, to indicate that the editor is supported
|
14391
|
-
wysihtml5.dom.addClass(document.body, this.config.
|
14423
|
+
wysihtml5.dom.addClass(document.body, this.config.classNames.body);
|
14392
14424
|
|
14393
14425
|
this.composer = new wysihtml5.views.Composer(this, this.editableElement, this.config);
|
14394
14426
|
this.currentView = this.composer;
|
@@ -14474,7 +14506,7 @@ wysihtml5.views.View = Base.extend(
|
|
14474
14506
|
"rules": this.config.parserRules,
|
14475
14507
|
"cleanUp": this.config.cleanUp,
|
14476
14508
|
"context": parseContext,
|
14477
|
-
"uneditableClass": this.config.
|
14509
|
+
"uneditableClass": this.config.classNames.uneditableContainer,
|
14478
14510
|
"clearInternals" : clearInternals
|
14479
14511
|
});
|
14480
14512
|
if (typeof(htmlOrElement) === "object") {
|
@@ -14520,7 +14552,7 @@ wysihtml5.views.View = Base.extend(
|
|
14520
14552
|
var cleanHtml = wysihtml5.quirks.cleanPastedHTML(oldHtml, {
|
14521
14553
|
"referenceNode": this.composer.element,
|
14522
14554
|
"rules": this.config.pasteParserRulesets || [{"set": this.config.parserRules}],
|
14523
|
-
"uneditableClass": this.config.
|
14555
|
+
"uneditableClass": this.config.classNames.uneditableContainer
|
14524
14556
|
});
|
14525
14557
|
this.composer.selection.deleteContents();
|
14526
14558
|
this.composer.selection.insertHTML(cleanHtml);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @license
|
3
|
-
* https://github.com/
|
2
|
+
* @license wysihtml v0.5.0-beta7
|
3
|
+
* https://github.com/Voog/wysihtml
|
4
4
|
*
|
5
5
|
* Author: Christopher Blum (https://github.com/tiff)
|
6
6
|
* Secondary author of extended features: Oliver Pulges (https://github.com/pulges)
|
@@ -10,7 +10,7 @@
|
|
10
10
|
*
|
11
11
|
*/
|
12
12
|
var wysihtml5 = {
|
13
|
-
version: "0.5.0-
|
13
|
+
version: "0.5.0-beta7",
|
14
14
|
|
15
15
|
// namespaces
|
16
16
|
commands: {},
|
@@ -5081,9 +5081,17 @@ wysihtml5.browser = (function() {
|
|
5081
5081
|
* wysihtml5.lang.object({ foo: 1, bar: 1 }).merge({ bar: 2, baz: 3 }).get();
|
5082
5082
|
* // => { foo: 1, bar: 2, baz: 3 }
|
5083
5083
|
*/
|
5084
|
-
merge: function(otherObj) {
|
5084
|
+
merge: function(otherObj, deep) {
|
5085
5085
|
for (var i in otherObj) {
|
5086
|
-
obj[i]
|
5086
|
+
if (deep && wysihtml5.lang.object(otherObj[i]).isPlainObject() && (typeof obj[i] === "undefined" || wysihtml5.lang.object(obj[i]).isPlainObject())) {
|
5087
|
+
if (typeof obj[i] === "undefined") {
|
5088
|
+
obj[i] = wysihtml5.lang.object(otherObj[i]).clone(true);
|
5089
|
+
} else {
|
5090
|
+
wysihtml5.lang.object(obj[i]).merge(wysihtml5.lang.object(otherObj[i]).clone(true));
|
5091
|
+
}
|
5092
|
+
} else {
|
5093
|
+
obj[i] = wysihtml5.lang.object(otherObj[i]).isPlainObject() ? wysihtml5.lang.object(otherObj[i]).clone(true) : otherObj[i];
|
5094
|
+
}
|
5087
5095
|
}
|
5088
5096
|
return this;
|
5089
5097
|
},
|
@@ -5138,7 +5146,7 @@ wysihtml5.browser = (function() {
|
|
5138
5146
|
},
|
5139
5147
|
|
5140
5148
|
isPlainObject: function () {
|
5141
|
-
return Object.prototype.toString.call(obj) === '[object Object]';
|
5149
|
+
return obj && Object.prototype.toString.call(obj) === '[object Object]';
|
5142
5150
|
}
|
5143
5151
|
};
|
5144
5152
|
};
|
@@ -6696,11 +6704,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6696
6704
|
newAttributeValue;
|
6697
6705
|
|
6698
6706
|
if (method) {
|
6699
|
-
|
6700
|
-
|
6701
|
-
|
6702
|
-
return newAttributeValue;
|
6703
|
-
}
|
6707
|
+
newAttributeValue = method(attributeValue, nodeName);
|
6708
|
+
if (typeof(newAttributeValue) === "string") {
|
6709
|
+
return newAttributeValue;
|
6704
6710
|
}
|
6705
6711
|
}
|
6706
6712
|
|
@@ -6935,9 +6941,13 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6935
6941
|
|
6936
6942
|
alt: (function() {
|
6937
6943
|
var REG_EXP = /[^ a-z0-9_\-]/gi;
|
6938
|
-
return function(attributeValue) {
|
6944
|
+
return function(attributeValue, nodeName) {
|
6939
6945
|
if (!attributeValue) {
|
6940
|
-
|
6946
|
+
if (nodeName === "IMG") {
|
6947
|
+
return "";
|
6948
|
+
} else {
|
6949
|
+
return null;
|
6950
|
+
}
|
6941
6951
|
}
|
6942
6952
|
return attributeValue.replace(REG_EXP, "");
|
6943
6953
|
};
|
@@ -6963,6 +6973,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
|
|
6963
6973
|
|
6964
6974
|
any: (function() {
|
6965
6975
|
return function(attributeValue) {
|
6976
|
+
if (!attributeValue) {
|
6977
|
+
return null;
|
6978
|
+
}
|
6966
6979
|
return attributeValue;
|
6967
6980
|
};
|
6968
6981
|
})()
|
@@ -7320,6 +7333,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7320
7333
|
constructor: function(readyCallback, config) {
|
7321
7334
|
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
|
7322
7335
|
this.config = wysihtml5.lang.object({}).merge(config).get();
|
7336
|
+
if (!this.config.className) {
|
7337
|
+
this.config.className = "wysihtml5-sandbox";
|
7338
|
+
}
|
7323
7339
|
this.editableArea = this._createIframe();
|
7324
7340
|
},
|
7325
7341
|
|
@@ -7374,7 +7390,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7374
7390
|
_createIframe: function() {
|
7375
7391
|
var that = this,
|
7376
7392
|
iframe = doc.createElement("iframe");
|
7377
|
-
iframe.className =
|
7393
|
+
iframe.className = this.config.className;
|
7378
7394
|
wysihtml5.dom.setAttributes({
|
7379
7395
|
"security": "restricted",
|
7380
7396
|
"allowtransparency": "true",
|
@@ -7537,6 +7553,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7537
7553
|
constructor: function(readyCallback, config, contentEditable) {
|
7538
7554
|
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
|
7539
7555
|
this.config = wysihtml5.lang.object({}).merge(config).get();
|
7556
|
+
if (!this.config.className) {
|
7557
|
+
this.config.className = "wysihtml5-sandbox";
|
7558
|
+
}
|
7540
7559
|
if (contentEditable) {
|
7541
7560
|
this.element = this._bindElement(contentEditable);
|
7542
7561
|
} else {
|
@@ -7547,7 +7566,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7547
7566
|
// creates a new contenteditable and initiates it
|
7548
7567
|
_createElement: function() {
|
7549
7568
|
var element = doc.createElement("div");
|
7550
|
-
element.className =
|
7569
|
+
element.className = this.config.className;
|
7551
7570
|
this._loadElement(element);
|
7552
7571
|
return element;
|
7553
7572
|
},
|
@@ -7626,8 +7645,8 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
|
|
7626
7645
|
* wysihtml.dom.simulatePlaceholder(this, composer, "Foobar");
|
7627
7646
|
*/
|
7628
7647
|
(function(dom) {
|
7629
|
-
dom.simulatePlaceholder = function(editor, view, placeholderText) {
|
7630
|
-
var CLASS_NAME = "placeholder",
|
7648
|
+
dom.simulatePlaceholder = function(editor, view, placeholderText, placeholderClassName) {
|
7649
|
+
var CLASS_NAME = placeholderClassName || "wysihtml5-placeholder",
|
7631
7650
|
unset = function() {
|
7632
7651
|
var composerIsVisible = view.element.offsetWidth > 0 && view.element.offsetHeight > 0;
|
7633
7652
|
if (view.hasPlaceholderSet()) {
|
@@ -11355,7 +11374,7 @@ wysihtml5.Commands = Base.extend(
|
|
11355
11374
|
function cleanup(composer) {
|
11356
11375
|
var container = composer.element,
|
11357
11376
|
allElements = container.querySelectorAll(BLOCK_ELEMENTS),
|
11358
|
-
uneditables = container.querySelectorAll(composer.config.
|
11377
|
+
uneditables = container.querySelectorAll(composer.config.classNames.uneditableContainer),
|
11359
11378
|
elements = wysihtml5.lang.array(allElements).without(uneditables);
|
11360
11379
|
|
11361
11380
|
for (var i = elements.length; i--;) {
|
@@ -11627,7 +11646,7 @@ wysihtml5.Commands = Base.extend(
|
|
11627
11646
|
state = this.state(composer, command, options);
|
11628
11647
|
if (state) {
|
11629
11648
|
bookmark = rangy.saveSelection(composer.win);
|
11630
|
-
for (var j
|
11649
|
+
for (var j = 0, jmax = state.length; j < jmax; j++) {
|
11631
11650
|
removeOptionsFromElement(state[j], options, composer);
|
11632
11651
|
}
|
11633
11652
|
}
|
@@ -11650,7 +11669,7 @@ wysihtml5.Commands = Base.extend(
|
|
11650
11669
|
composer.selection.selectLine();
|
11651
11670
|
}
|
11652
11671
|
}
|
11653
|
-
|
11672
|
+
|
11654
11673
|
// And get all selection ranges of current composer and iterat
|
11655
11674
|
ranges = composer.selection.getOwnRanges();
|
11656
11675
|
for (var i = ranges.length; i--;) {
|
@@ -12212,7 +12231,7 @@ wysihtml5.Commands = Base.extend(
|
|
12212
12231
|
|
12213
12232
|
if (tempElement) {
|
12214
12233
|
isEmpty = wysihtml5.lang.array(["", "<br>", wysihtml5.INVISIBLE_SPACE]).contains(tempElement.innerHTML);
|
12215
|
-
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.
|
12234
|
+
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.classNames.uneditableContainer);
|
12216
12235
|
if (isEmpty) {
|
12217
12236
|
composer.selection.selectNode(list.querySelector("li"), true);
|
12218
12237
|
}
|
@@ -12441,7 +12460,7 @@ wysihtml5.Commands = Base.extend(
|
|
12441
12460
|
for (row = 0; row < value.rows; row ++) {
|
12442
12461
|
html += '<tr>';
|
12443
12462
|
for (col = 0; col < value.cols; col ++) {
|
12444
|
-
html += "<td></td>";
|
12463
|
+
html += "<td><br></td>";
|
12445
12464
|
}
|
12446
12465
|
html += '</tr>';
|
12447
12466
|
}
|
@@ -13123,14 +13142,17 @@ wysihtml5.views.View = Base.extend(
|
|
13123
13142
|
|
13124
13143
|
_initContentEditableArea: function() {
|
13125
13144
|
var that = this;
|
13126
|
-
|
13127
13145
|
if (this.config.noTextarea) {
|
13128
13146
|
this.sandbox = new dom.ContentEditableArea(function() {
|
13129
13147
|
that._create();
|
13130
|
-
}, {
|
13148
|
+
}, {
|
13149
|
+
className: this.config.classNames.sandbox
|
13150
|
+
}, this.editableArea);
|
13131
13151
|
} else {
|
13132
13152
|
this.sandbox = new dom.ContentEditableArea(function() {
|
13133
13153
|
that._create();
|
13154
|
+
}, {
|
13155
|
+
className: this.config.classNames.sandbox
|
13134
13156
|
});
|
13135
13157
|
this.editableArea = this.sandbox.getContentEditable();
|
13136
13158
|
dom.insert(this.editableArea).after(this.textarea.element);
|
@@ -13140,11 +13162,11 @@ wysihtml5.views.View = Base.extend(
|
|
13140
13162
|
|
13141
13163
|
_initSandbox: function() {
|
13142
13164
|
var that = this;
|
13143
|
-
|
13144
13165
|
this.sandbox = new dom.Sandbox(function() {
|
13145
13166
|
that._create();
|
13146
13167
|
}, {
|
13147
|
-
stylesheets: this.config.stylesheets
|
13168
|
+
stylesheets: this.config.stylesheets,
|
13169
|
+
className: this.config.classNames.sandbox
|
13148
13170
|
});
|
13149
13171
|
this.editableArea = this.sandbox.getIframe();
|
13150
13172
|
|
@@ -13178,7 +13200,7 @@ wysihtml5.views.View = Base.extend(
|
|
13178
13200
|
}
|
13179
13201
|
|
13180
13202
|
// Make sure our selection handler is ready
|
13181
|
-
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.
|
13203
|
+
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.classNames.uneditableContainer);
|
13182
13204
|
|
13183
13205
|
// Make sure commands dispatcher is ready
|
13184
13206
|
this.commands = new wysihtml5.Commands(this.parent);
|
@@ -13189,7 +13211,7 @@ wysihtml5.views.View = Base.extend(
|
|
13189
13211
|
]).from(this.textarea.element).to(this.element);
|
13190
13212
|
}
|
13191
13213
|
|
13192
|
-
dom.addClass(this.element, this.config.
|
13214
|
+
dom.addClass(this.element, this.config.classNames.composer);
|
13193
13215
|
//
|
13194
13216
|
// Make the editor look like the original textarea, by syncing styles
|
13195
13217
|
if (this.config.style && !this.config.contentEditableMode) {
|
@@ -13215,7 +13237,7 @@ wysihtml5.views.View = Base.extend(
|
|
13215
13237
|
? this.config.placeholder
|
13216
13238
|
: ((this.config.noTextarea) ? this.editableArea.getAttribute("data-placeholder") : this.textarea.element.getAttribute("placeholder"));
|
13217
13239
|
if (placeholderText) {
|
13218
|
-
dom.simulatePlaceholder(this.parent, this, placeholderText);
|
13240
|
+
dom.simulatePlaceholder(this.parent, this, placeholderText, this.config.classNames.placeholder);
|
13219
13241
|
}
|
13220
13242
|
|
13221
13243
|
// Make sure that the browser avoids using inline styles whenever possible
|
@@ -13267,7 +13289,7 @@ wysihtml5.views.View = Base.extend(
|
|
13267
13289
|
this.parent.on("newword:composer", function() {
|
13268
13290
|
if (dom.getTextContent(that.element).match(dom.autoLink.URL_REG_EXP)) {
|
13269
13291
|
var nodeWithSelection = that.selection.getSelectedNode(),
|
13270
|
-
uneditables = that.element.querySelectorAll("." + that.config.
|
13292
|
+
uneditables = that.element.querySelectorAll("." + that.config.classNames.uneditableContainer),
|
13271
13293
|
isInUneditable = false;
|
13272
13294
|
|
13273
13295
|
for (var i = uneditables.length; i--;) {
|
@@ -13276,12 +13298,12 @@ wysihtml5.views.View = Base.extend(
|
|
13276
13298
|
}
|
13277
13299
|
}
|
13278
13300
|
|
13279
|
-
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.
|
13301
|
+
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.classNames.uneditableContainer]);
|
13280
13302
|
}
|
13281
13303
|
});
|
13282
13304
|
|
13283
13305
|
dom.observe(this.element, "blur", function() {
|
13284
|
-
dom.autoLink(that.element, [that.config.
|
13306
|
+
dom.autoLink(that.element, [that.config.classNames.uneditableContainer]);
|
13285
13307
|
});
|
13286
13308
|
}
|
13287
13309
|
|
@@ -13716,7 +13738,7 @@ wysihtml5.views.View = Base.extend(
|
|
13716
13738
|
// If found an uneditable before caret then notify it before deletion
|
13717
13739
|
var handleUneditableDeletion = function(composer) {
|
13718
13740
|
var before = composer.selection.getBeforeSelection(true);
|
13719
|
-
if (before && (before.type === "element" || before.type === "leafnode") && before.node.nodeType === 1 && before.node.classList.contains(composer.config.
|
13741
|
+
if (before && (before.type === "element" || before.type === "leafnode") && before.node.nodeType === 1 && before.node.classList.contains(composer.config.classNames.uneditableContainer)) {
|
13720
13742
|
if (fixLastBrDeletionInTable(composer, true)) {
|
13721
13743
|
return true;
|
13722
13744
|
}
|
@@ -13881,7 +13903,7 @@ wysihtml5.views.View = Base.extend(
|
|
13881
13903
|
// Make sure that images are selected when clicking on them
|
13882
13904
|
var target = event.target,
|
13883
13905
|
allImages = this.element.querySelectorAll('img'),
|
13884
|
-
notMyImages = this.element.querySelectorAll('.' + this.config.
|
13906
|
+
notMyImages = this.element.querySelectorAll('.' + this.config.classNames.uneditableContainer + ' img'),
|
13885
13907
|
myImages = wysihtml5.lang.array(allImages).without(notMyImages);
|
13886
13908
|
|
13887
13909
|
if (target.nodeName === "IMG" && wysihtml5.lang.array(myImages).contains(target)) {
|
@@ -13911,10 +13933,10 @@ wysihtml5.views.View = Base.extend(
|
|
13911
13933
|
};
|
13912
13934
|
|
13913
13935
|
var handleClick = function(event) {
|
13914
|
-
if (this.config.
|
13936
|
+
if (this.config.classNames.uneditableContainer) {
|
13915
13937
|
// If uneditables is configured, makes clicking on uneditable move caret after clicked element (so it can be deleted like text)
|
13916
13938
|
// If uneditable needs text selection itself event.stopPropagation can be used to prevent this behaviour
|
13917
|
-
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.
|
13939
|
+
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.classNames.uneditableContainer }, false, this.element);
|
13918
13940
|
if (uneditable) {
|
13919
13941
|
this.selection.setAfter(uneditable);
|
13920
13942
|
}
|
@@ -14338,10 +14360,6 @@ wysihtml5.views.View = Base.extend(
|
|
14338
14360
|
pasteParserRulesets: null,
|
14339
14361
|
// Parser method to use when the user inserts content
|
14340
14362
|
parser: wysihtml5.dom.parse,
|
14341
|
-
// Class name which should be set on the contentEditable element in the created sandbox iframe, can be styled via the 'stylesheets' option
|
14342
|
-
composerClassName: "wysihtml5-editor",
|
14343
|
-
// Class name to add to the body when the wysihtml5 editor is supported
|
14344
|
-
bodyClassName: "wysihtml5-supported",
|
14345
14363
|
// By default wysihtml5 will insert a <br> for line breaks, set this to false to use <p>
|
14346
14364
|
useLineBreaks: true,
|
14347
14365
|
// Array (or single string) of stylesheet urls to be loaded in the editor's iframe
|
@@ -14354,9 +14372,18 @@ wysihtml5.views.View = Base.extend(
|
|
14354
14372
|
cleanUp: true,
|
14355
14373
|
// Whether to use div instead of secure iframe
|
14356
14374
|
contentEditableMode: false,
|
14357
|
-
|
14358
|
-
|
14359
|
-
|
14375
|
+
classNames: {
|
14376
|
+
// Class name which should be set on the contentEditable element in the created sandbox iframe, can be styled via the 'stylesheets' option
|
14377
|
+
composer: "wysihtml5-editor",
|
14378
|
+
// Class name to add to the body when the wysihtml5 editor is supported
|
14379
|
+
body: "wysihtml5-supported",
|
14380
|
+
// classname added to editable area element (iframe/div) on creation
|
14381
|
+
sandbox: "wysihtml5-sandbox",
|
14382
|
+
// class on editable area with placeholder
|
14383
|
+
placeholder: "wysihtml5-placeholder",
|
14384
|
+
// Classname of container that editor should not touch and pass through
|
14385
|
+
uneditableContainer: "wysihtml5-uneditable-container"
|
14386
|
+
},
|
14360
14387
|
// Browsers that support copied source handling will get a marking of the origin of the copied source (for determinig code cleanup rules on paste)
|
14361
14388
|
// Also copied source is based directly on selection -
|
14362
14389
|
// (very useful for webkit based browsers where copy will otherwise contain a lot of code and styles based on whatever and not actually in selection).
|
@@ -14368,9 +14395,14 @@ wysihtml5.views.View = Base.extend(
|
|
14368
14395
|
/** @scope wysihtml5.Editor.prototype */ {
|
14369
14396
|
constructor: function(editableElement, config) {
|
14370
14397
|
this.editableElement = typeof(editableElement) === "string" ? document.getElementById(editableElement) : editableElement;
|
14371
|
-
this.config = wysihtml5.lang.object({}).merge(defaultConfig).merge(config).get();
|
14398
|
+
this.config = wysihtml5.lang.object({}).merge(defaultConfig).merge(config, true).get();
|
14372
14399
|
this._isCompatible = wysihtml5.browser.supported();
|
14373
14400
|
|
14401
|
+
// make sure that rules override instead of extend
|
14402
|
+
if (config && config.parserRules) {
|
14403
|
+
this.config.parserRules = wysihtml5.lang.object(config.parserRules).clone(true);
|
14404
|
+
}
|
14405
|
+
|
14374
14406
|
if (this.editableElement.nodeName.toLowerCase() != "textarea") {
|
14375
14407
|
this.config.contentEditableMode = true;
|
14376
14408
|
this.config.noTextarea = true;
|
@@ -14388,7 +14420,7 @@ wysihtml5.views.View = Base.extend(
|
|
14388
14420
|
}
|
14389
14421
|
|
14390
14422
|
// Add class name to body, to indicate that the editor is supported
|
14391
|
-
wysihtml5.dom.addClass(document.body, this.config.
|
14423
|
+
wysihtml5.dom.addClass(document.body, this.config.classNames.body);
|
14392
14424
|
|
14393
14425
|
this.composer = new wysihtml5.views.Composer(this, this.editableElement, this.config);
|
14394
14426
|
this.currentView = this.composer;
|
@@ -14474,7 +14506,7 @@ wysihtml5.views.View = Base.extend(
|
|
14474
14506
|
"rules": this.config.parserRules,
|
14475
14507
|
"cleanUp": this.config.cleanUp,
|
14476
14508
|
"context": parseContext,
|
14477
|
-
"uneditableClass": this.config.
|
14509
|
+
"uneditableClass": this.config.classNames.uneditableContainer,
|
14478
14510
|
"clearInternals" : clearInternals
|
14479
14511
|
});
|
14480
14512
|
if (typeof(htmlOrElement) === "object") {
|
@@ -14520,7 +14552,7 @@ wysihtml5.views.View = Base.extend(
|
|
14520
14552
|
var cleanHtml = wysihtml5.quirks.cleanPastedHTML(oldHtml, {
|
14521
14553
|
"referenceNode": this.composer.element,
|
14522
14554
|
"rules": this.config.pasteParserRulesets || [{"set": this.config.parserRules}],
|
14523
|
-
"uneditableClass": this.config.
|
14555
|
+
"uneditableClass": this.config.classNames.uneditableContainer
|
14524
14556
|
});
|
14525
14557
|
this.composer.selection.deleteContents();
|
14526
14558
|
this.composer.selection.insertHTML(cleanHtml);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wysihtml-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.0.
|
4
|
+
version: 0.5.0.beta7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tanel Jakobsoo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|