Skip to content

Commit bf9243a

Browse files
author
Oliver Pulges
committed
Update to v0.5.0.beta7
1 parent e4ff9bb commit bf9243a

File tree

3 files changed

+159
-95
lines changed

3 files changed

+159
-95
lines changed

lib/wysihtml/rails/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Wysihtml
22
module Rails
3-
VERSION = "0.5.0.beta6"
3+
VERSION = "0.5.0.beta7"
44
end
55
end

vendor/assets/javascripts/wysihtml-toolbar.js

Lines changed: 79 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
* @license wysihtml5x v0.5.0-beta6
3-
* https://github.com/Edicy/wysihtml5
2+
* @license wysihtml v0.5.0-beta7
3+
* https://github.com/Voog/wysihtml
44
*
55
* Author: Christopher Blum (https://github.com/tiff)
66
* Secondary author of extended features: Oliver Pulges (https://github.com/pulges)
@@ -10,7 +10,7 @@
1010
*
1111
*/
1212
var wysihtml5 = {
13-
version: "0.5.0-beta6",
13+
version: "0.5.0-beta7",
1414

1515
// namespaces
1616
commands: {},
@@ -5081,9 +5081,17 @@ wysihtml5.browser = (function() {
50815081
* wysihtml5.lang.object({ foo: 1, bar: 1 }).merge({ bar: 2, baz: 3 }).get();
50825082
* // => { foo: 1, bar: 2, baz: 3 }
50835083
*/
5084-
merge: function(otherObj) {
5084+
merge: function(otherObj, deep) {
50855085
for (var i in otherObj) {
5086-
obj[i] = otherObj[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+
}
50875095
}
50885096
return this;
50895097
},
@@ -5138,7 +5146,7 @@ wysihtml5.browser = (function() {
51385146
},
51395147

51405148
isPlainObject: function () {
5141-
return Object.prototype.toString.call(obj) === '[object Object]';
5149+
return obj && Object.prototype.toString.call(obj) === '[object Object]';
51425150
}
51435151
};
51445152
};
@@ -6696,11 +6704,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
66966704
newAttributeValue;
66976705

66986706
if (method) {
6699-
if (attributeValue || (attributeName === "alt" && nodeName == "IMG")) {
6700-
newAttributeValue = method(attributeValue);
6701-
if (typeof(newAttributeValue) === "string") {
6702-
return newAttributeValue;
6703-
}
6707+
newAttributeValue = method(attributeValue, nodeName);
6708+
if (typeof(newAttributeValue) === "string") {
6709+
return newAttributeValue;
67046710
}
67056711
}
67066712

@@ -6935,9 +6941,13 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
69356941

69366942
alt: (function() {
69376943
var REG_EXP = /[^ a-z0-9_\-]/gi;
6938-
return function(attributeValue) {
6944+
return function(attributeValue, nodeName) {
69396945
if (!attributeValue) {
6940-
return "";
6946+
if (nodeName === "IMG") {
6947+
return "";
6948+
} else {
6949+
return null;
6950+
}
69416951
}
69426952
return attributeValue.replace(REG_EXP, "");
69436953
};
@@ -6963,6 +6973,9 @@ wysihtml5.dom.parse = function(elementOrHtml_current, config_current) {
69636973

69646974
any: (function() {
69656975
return function(attributeValue) {
6976+
if (!attributeValue) {
6977+
return null;
6978+
}
69666979
return attributeValue;
69676980
};
69686981
})()
@@ -7320,6 +7333,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
73207333
constructor: function(readyCallback, config) {
73217334
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
73227335
this.config = wysihtml5.lang.object({}).merge(config).get();
7336+
if (!this.config.className) {
7337+
this.config.className = "wysihtml5-sandbox";
7338+
}
73237339
this.editableArea = this._createIframe();
73247340
},
73257341

@@ -7374,7 +7390,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
73747390
_createIframe: function() {
73757391
var that = this,
73767392
iframe = doc.createElement("iframe");
7377-
iframe.className = "wysihtml5-sandbox";
7393+
iframe.className = this.config.className;
73787394
wysihtml5.dom.setAttributes({
73797395
"security": "restricted",
73807396
"allowtransparency": "true",
@@ -7537,6 +7553,9 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
75377553
constructor: function(readyCallback, config, contentEditable) {
75387554
this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION;
75397555
this.config = wysihtml5.lang.object({}).merge(config).get();
7556+
if (!this.config.className) {
7557+
this.config.className = "wysihtml5-sandbox";
7558+
}
75407559
if (contentEditable) {
75417560
this.element = this._bindElement(contentEditable);
75427561
} else {
@@ -7547,7 +7566,7 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
75477566
// creates a new contenteditable and initiates it
75487567
_createElement: function() {
75497568
var element = doc.createElement("div");
7550-
element.className = "wysihtml5-sandbox";
7569+
element.className = this.config.className;
75517570
this._loadElement(element);
75527571
return element;
75537572
},
@@ -7626,8 +7645,8 @@ wysihtml5.dom.replaceWithChildNodes = function(node) {
76267645
* wysihtml.dom.simulatePlaceholder(this, composer, "Foobar");
76277646
*/
76287647
(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",
76317650
unset = function() {
76327651
var composerIsVisible = view.element.offsetWidth > 0 && view.element.offsetHeight > 0;
76337652
if (view.hasPlaceholderSet()) {
@@ -11355,7 +11374,7 @@ wysihtml5.Commands = Base.extend(
1135511374
function cleanup(composer) {
1135611375
var container = composer.element,
1135711376
allElements = container.querySelectorAll(BLOCK_ELEMENTS),
11358-
uneditables = container.querySelectorAll(composer.config.uneditableContainerClassname),
11377+
uneditables = container.querySelectorAll(composer.config.classNames.uneditableContainer),
1135911378
elements = wysihtml5.lang.array(allElements).without(uneditables);
1136011379

1136111380
for (var i = elements.length; i--;) {
@@ -11627,7 +11646,7 @@ wysihtml5.Commands = Base.extend(
1162711646
state = this.state(composer, command, options);
1162811647
if (state) {
1162911648
bookmark = rangy.saveSelection(composer.win);
11630-
for (var j in state) {
11649+
for (var j = 0, jmax = state.length; j < jmax; j++) {
1163111650
removeOptionsFromElement(state[j], options, composer);
1163211651
}
1163311652
}
@@ -11650,7 +11669,7 @@ wysihtml5.Commands = Base.extend(
1165011669
composer.selection.selectLine();
1165111670
}
1165211671
}
11653-
11672+
1165411673
// And get all selection ranges of current composer and iterat
1165511674
ranges = composer.selection.getOwnRanges();
1165611675
for (var i = ranges.length; i--;) {
@@ -12212,7 +12231,7 @@ wysihtml5.Commands = Base.extend(
1221212231

1221312232
if (tempElement) {
1221412233
isEmpty = wysihtml5.lang.array(["", "<br>", wysihtml5.INVISIBLE_SPACE]).contains(tempElement.innerHTML);
12215-
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.uneditableContainerClassname);
12234+
list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.classNames.uneditableContainer);
1221612235
if (isEmpty) {
1221712236
composer.selection.selectNode(list.querySelector("li"), true);
1221812237
}
@@ -12441,7 +12460,7 @@ wysihtml5.Commands = Base.extend(
1244112460
for (row = 0; row < value.rows; row ++) {
1244212461
html += '<tr>';
1244312462
for (col = 0; col < value.cols; col ++) {
12444-
html += "<td></td>";
12463+
html += "<td><br></td>";
1244512464
}
1244612465
html += '</tr>';
1244712466
}
@@ -13123,14 +13142,17 @@ wysihtml5.views.View = Base.extend(
1312313142

1312413143
_initContentEditableArea: function() {
1312513144
var that = this;
13126-
1312713145
if (this.config.noTextarea) {
1312813146
this.sandbox = new dom.ContentEditableArea(function() {
1312913147
that._create();
13130-
}, {}, this.editableArea);
13148+
}, {
13149+
className: this.config.classNames.sandbox
13150+
}, this.editableArea);
1313113151
} else {
1313213152
this.sandbox = new dom.ContentEditableArea(function() {
1313313153
that._create();
13154+
}, {
13155+
className: this.config.classNames.sandbox
1313413156
});
1313513157
this.editableArea = this.sandbox.getContentEditable();
1313613158
dom.insert(this.editableArea).after(this.textarea.element);
@@ -13140,11 +13162,11 @@ wysihtml5.views.View = Base.extend(
1314013162

1314113163
_initSandbox: function() {
1314213164
var that = this;
13143-
1314413165
this.sandbox = new dom.Sandbox(function() {
1314513166
that._create();
1314613167
}, {
13147-
stylesheets: this.config.stylesheets
13168+
stylesheets: this.config.stylesheets,
13169+
className: this.config.classNames.sandbox
1314813170
});
1314913171
this.editableArea = this.sandbox.getIframe();
1315013172

@@ -13178,7 +13200,7 @@ wysihtml5.views.View = Base.extend(
1317813200
}
1317913201

1318013202
// Make sure our selection handler is ready
13181-
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.uneditableContainerClassname);
13203+
this.selection = new wysihtml5.Selection(this.parent, this.element, this.config.classNames.uneditableContainer);
1318213204

1318313205
// Make sure commands dispatcher is ready
1318413206
this.commands = new wysihtml5.Commands(this.parent);
@@ -13189,7 +13211,7 @@ wysihtml5.views.View = Base.extend(
1318913211
]).from(this.textarea.element).to(this.element);
1319013212
}
1319113213

13192-
dom.addClass(this.element, this.config.composerClassName);
13214+
dom.addClass(this.element, this.config.classNames.composer);
1319313215
//
1319413216
// Make the editor look like the original textarea, by syncing styles
1319513217
if (this.config.style && !this.config.contentEditableMode) {
@@ -13215,7 +13237,7 @@ wysihtml5.views.View = Base.extend(
1321513237
? this.config.placeholder
1321613238
: ((this.config.noTextarea) ? this.editableArea.getAttribute("data-placeholder") : this.textarea.element.getAttribute("placeholder"));
1321713239
if (placeholderText) {
13218-
dom.simulatePlaceholder(this.parent, this, placeholderText);
13240+
dom.simulatePlaceholder(this.parent, this, placeholderText, this.config.classNames.placeholder);
1321913241
}
1322013242

1322113243
// Make sure that the browser avoids using inline styles whenever possible
@@ -13267,7 +13289,7 @@ wysihtml5.views.View = Base.extend(
1326713289
this.parent.on("newword:composer", function() {
1326813290
if (dom.getTextContent(that.element).match(dom.autoLink.URL_REG_EXP)) {
1326913291
var nodeWithSelection = that.selection.getSelectedNode(),
13270-
uneditables = that.element.querySelectorAll("." + that.config.uneditableContainerClassname),
13292+
uneditables = that.element.querySelectorAll("." + that.config.classNames.uneditableContainer),
1327113293
isInUneditable = false;
1327213294

1327313295
for (var i = uneditables.length; i--;) {
@@ -13276,12 +13298,12 @@ wysihtml5.views.View = Base.extend(
1327613298
}
1327713299
}
1327813300

13279-
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.uneditableContainerClassname]);
13301+
if (!isInUneditable) dom.autoLink(nodeWithSelection, [that.config.classNames.uneditableContainer]);
1328013302
}
1328113303
});
1328213304

1328313305
dom.observe(this.element, "blur", function() {
13284-
dom.autoLink(that.element, [that.config.uneditableContainerClassname]);
13306+
dom.autoLink(that.element, [that.config.classNames.uneditableContainer]);
1328513307
});
1328613308
}
1328713309

@@ -13716,7 +13738,7 @@ wysihtml5.views.View = Base.extend(
1371613738
// If found an uneditable before caret then notify it before deletion
1371713739
var handleUneditableDeletion = function(composer) {
1371813740
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.uneditableContainerClassname)) {
13741+
if (before && (before.type === "element" || before.type === "leafnode") && before.node.nodeType === 1 && before.node.classList.contains(composer.config.classNames.uneditableContainer)) {
1372013742
if (fixLastBrDeletionInTable(composer, true)) {
1372113743
return true;
1372213744
}
@@ -13881,7 +13903,7 @@ wysihtml5.views.View = Base.extend(
1388113903
// Make sure that images are selected when clicking on them
1388213904
var target = event.target,
1388313905
allImages = this.element.querySelectorAll('img'),
13884-
notMyImages = this.element.querySelectorAll('.' + this.config.uneditableContainerClassname + ' img'),
13906+
notMyImages = this.element.querySelectorAll('.' + this.config.classNames.uneditableContainer + ' img'),
1388513907
myImages = wysihtml5.lang.array(allImages).without(notMyImages);
1388613908

1388713909
if (target.nodeName === "IMG" && wysihtml5.lang.array(myImages).contains(target)) {
@@ -13911,10 +13933,10 @@ wysihtml5.views.View = Base.extend(
1391113933
};
1391213934

1391313935
var handleClick = function(event) {
13914-
if (this.config.uneditableContainerClassname) {
13936+
if (this.config.classNames.uneditableContainer) {
1391513937
// If uneditables is configured, makes clicking on uneditable move caret after clicked element (so it can be deleted like text)
1391613938
// 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.uneditableContainerClassname }, false, this.element);
13939+
var uneditable = wysihtml5.dom.getParentElement(event.target, { query: "." + this.config.classNames.uneditableContainer }, false, this.element);
1391813940
if (uneditable) {
1391913941
this.selection.setAfter(uneditable);
1392013942
}
@@ -14338,10 +14360,6 @@ wysihtml5.views.View = Base.extend(
1433814360
pasteParserRulesets: null,
1433914361
// Parser method to use when the user inserts content
1434014362
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",
1434514363
// By default wysihtml5 will insert a <br> for line breaks, set this to false to use <p>
1434614364
useLineBreaks: true,
1434714365
// Array (or single string) of stylesheet urls to be loaded in the editor's iframe
@@ -14354,9 +14372,18 @@ wysihtml5.views.View = Base.extend(
1435414372
cleanUp: true,
1435514373
// Whether to use div instead of secure iframe
1435614374
contentEditableMode: false,
14357-
// Classname of container that editor should not touch and pass through
14358-
// Pass false to disable
14359-
uneditableContainerClassname: "wysihtml5-uneditable-container",
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+
},
1436014387
// Browsers that support copied source handling will get a marking of the origin of the copied source (for determinig code cleanup rules on paste)
1436114388
// Also copied source is based directly on selection -
1436214389
// (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(
1436814395
/** @scope wysihtml5.Editor.prototype */ {
1436914396
constructor: function(editableElement, config) {
1437014397
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();
1437214399
this._isCompatible = wysihtml5.browser.supported();
1437314400

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+
1437414406
if (this.editableElement.nodeName.toLowerCase() != "textarea") {
1437514407
this.config.contentEditableMode = true;
1437614408
this.config.noTextarea = true;
@@ -14388,7 +14420,7 @@ wysihtml5.views.View = Base.extend(
1438814420
}
1438914421

1439014422
// Add class name to body, to indicate that the editor is supported
14391-
wysihtml5.dom.addClass(document.body, this.config.bodyClassName);
14423+
wysihtml5.dom.addClass(document.body, this.config.classNames.body);
1439214424

1439314425
this.composer = new wysihtml5.views.Composer(this, this.editableElement, this.config);
1439414426
this.currentView = this.composer;
@@ -14474,7 +14506,7 @@ wysihtml5.views.View = Base.extend(
1447414506
"rules": this.config.parserRules,
1447514507
"cleanUp": this.config.cleanUp,
1447614508
"context": parseContext,
14477-
"uneditableClass": this.config.uneditableContainerClassname,
14509+
"uneditableClass": this.config.classNames.uneditableContainer,
1447814510
"clearInternals" : clearInternals
1447914511
});
1448014512
if (typeof(htmlOrElement) === "object") {
@@ -14520,7 +14552,7 @@ wysihtml5.views.View = Base.extend(
1452014552
var cleanHtml = wysihtml5.quirks.cleanPastedHTML(oldHtml, {
1452114553
"referenceNode": this.composer.element,
1452214554
"rules": this.config.pasteParserRulesets || [{"set": this.config.parserRules}],
14523-
"uneditableClass": this.config.uneditableContainerClassname
14555+
"uneditableClass": this.config.classNames.uneditableContainer
1452414556
});
1452514557
this.composer.selection.deleteContents();
1452614558
this.composer.selection.insertHTML(cleanHtml);

0 commit comments

Comments
 (0)