wysihtml-rails 0.5.0.beta6 → 0.5.0.beta7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/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
|