mirror of
https://github.com/janickiy/yii2-nomer
synced 2025-03-09 15:39:59 +00:00
add files to project
This commit is contained in:
commit
5cac498444
3729 changed files with 836998 additions and 0 deletions
139
web/metronic/global/plugins/wysihtml/lib/base/base.js
Normal file
139
web/metronic/global/plugins/wysihtml/lib/base/base.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
Base.js, version 1.1a
|
||||
Copyright 2006-2010, Dean Edwards
|
||||
License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
var Base = function() {
|
||||
// dummy
|
||||
};
|
||||
|
||||
Base.extend = function(_instance, _static) { // subclass
|
||||
var extend = Base.prototype.extend;
|
||||
|
||||
// build the prototype
|
||||
Base._prototyping = true;
|
||||
var proto = new this;
|
||||
extend.call(proto, _instance);
|
||||
proto.base = function() {
|
||||
// call this method from any other method to invoke that method's ancestor
|
||||
};
|
||||
delete Base._prototyping;
|
||||
|
||||
// create the wrapper for the constructor function
|
||||
//var constructor = proto.constructor.valueOf(); //-dean
|
||||
var constructor = proto.constructor;
|
||||
var klass = proto.constructor = function() {
|
||||
if (!Base._prototyping) {
|
||||
if (this._constructing || this.constructor == klass) { // instantiation
|
||||
this._constructing = true;
|
||||
constructor.apply(this, arguments);
|
||||
delete this._constructing;
|
||||
} else if (arguments[0] != null) { // casting
|
||||
return (arguments[0].extend || extend).call(arguments[0], proto);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// build the class interface
|
||||
klass.ancestor = this;
|
||||
klass.extend = this.extend;
|
||||
klass.forEach = this.forEach;
|
||||
klass.implement = this.implement;
|
||||
klass.prototype = proto;
|
||||
klass.toString = this.toString;
|
||||
klass.valueOf = function(type) {
|
||||
//return (type == "object") ? klass : constructor; //-dean
|
||||
return (type == "object") ? klass : constructor.valueOf();
|
||||
};
|
||||
extend.call(klass, _static);
|
||||
// class initialisation
|
||||
if (typeof klass.init == "function") klass.init();
|
||||
return klass;
|
||||
};
|
||||
|
||||
Base.prototype = {
|
||||
extend: function(source, value) {
|
||||
if (arguments.length > 1) { // extending with a name/value pair
|
||||
var ancestor = this[source];
|
||||
if (ancestor && (typeof value == "function") && // overriding a method?
|
||||
// the valueOf() comparison is to avoid circular references
|
||||
(!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) &&
|
||||
/\bbase\b/.test(value)) {
|
||||
// get the underlying method
|
||||
var method = value.valueOf();
|
||||
// override
|
||||
value = function() {
|
||||
var previous = this.base || Base.prototype.base;
|
||||
this.base = ancestor;
|
||||
var returnValue = method.apply(this, arguments);
|
||||
this.base = previous;
|
||||
return returnValue;
|
||||
};
|
||||
// point to the underlying method
|
||||
value.valueOf = function(type) {
|
||||
return (type == "object") ? value : method;
|
||||
};
|
||||
value.toString = Base.toString;
|
||||
}
|
||||
this[source] = value;
|
||||
} else if (source) { // extending with an object literal
|
||||
var extend = Base.prototype.extend;
|
||||
// if this object has a customised extend method then use it
|
||||
if (!Base._prototyping && typeof this != "function") {
|
||||
extend = this.extend || extend;
|
||||
}
|
||||
var proto = {toSource: null};
|
||||
// do the "toString" and other methods manually
|
||||
var hidden = ["constructor", "toString", "valueOf"];
|
||||
// if we are prototyping then include the constructor
|
||||
var i = Base._prototyping ? 0 : 1;
|
||||
while (key = hidden[i++]) {
|
||||
if (source[key] != proto[key]) {
|
||||
extend.call(this, key, source[key]);
|
||||
|
||||
}
|
||||
}
|
||||
// copy each of the source object's properties to this object
|
||||
for (var key in source) {
|
||||
if (!proto[key]) extend.call(this, key, source[key]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// initialise
|
||||
Base = Base.extend({
|
||||
constructor: function() {
|
||||
this.extend(arguments[0]);
|
||||
}
|
||||
}, {
|
||||
ancestor: Object,
|
||||
version: "1.1",
|
||||
|
||||
forEach: function(object, block, context) {
|
||||
for (var key in object) {
|
||||
if (this.prototype[key] === undefined) {
|
||||
block.call(context, object[key], key, object);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
implement: function() {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (typeof arguments[i] == "function") {
|
||||
// if it's a function, call it
|
||||
arguments[i](this.prototype);
|
||||
} else {
|
||||
// add the interface using the extend method
|
||||
this.prototype.extend(arguments[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return String(this.valueOf());
|
||||
}
|
||||
});
|
3836
web/metronic/global/plugins/wysihtml/lib/rangy/rangy-core.js
Normal file
3836
web/metronic/global/plugins/wysihtml/lib/rangy/rangy-core.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,239 @@
|
|||
/**
|
||||
* Selection save and restore module for Rangy.
|
||||
* Saves and restores user selections using marker invisible elements in the DOM.
|
||||
*
|
||||
* Part of Rangy, a cross-browser JavaScript range and selection library
|
||||
* https://github.com/timdown/rangy
|
||||
*
|
||||
* Depends on Rangy core.
|
||||
*
|
||||
* Copyright 2015, Tim Down
|
||||
* Licensed under the MIT license.
|
||||
* Version: 1.3.1-dev
|
||||
* Build date: 20 May 2015
|
||||
*
|
||||
* NOTE: UMD wrapper removed manually for bundling (Oliver Pulges)
|
||||
*/
|
||||
rangy.createModule("SaveRestore", ["WrappedRange"], function(api, module) {
|
||||
var dom = api.dom;
|
||||
var removeNode = dom.removeNode;
|
||||
var isDirectionBackward = api.Selection.isDirectionBackward;
|
||||
var markerTextChar = "\ufeff";
|
||||
|
||||
function gEBI(id, doc) {
|
||||
return (doc || document).getElementById(id);
|
||||
}
|
||||
|
||||
function insertRangeBoundaryMarker(range, atStart) {
|
||||
var markerId = "selectionBoundary_" + (+new Date()) + "_" + ("" + Math.random()).slice(2);
|
||||
var markerEl;
|
||||
var doc = dom.getDocument(range.startContainer);
|
||||
|
||||
// Clone the Range and collapse to the appropriate boundary point
|
||||
var boundaryRange = range.cloneRange();
|
||||
boundaryRange.collapse(atStart);
|
||||
|
||||
// Create the marker element containing a single invisible character using DOM methods and insert it
|
||||
markerEl = doc.createElement("span");
|
||||
markerEl.id = markerId;
|
||||
markerEl.style.lineHeight = "0";
|
||||
markerEl.style.display = "none";
|
||||
markerEl.className = "rangySelectionBoundary";
|
||||
markerEl.appendChild(doc.createTextNode(markerTextChar));
|
||||
|
||||
boundaryRange.insertNode(markerEl);
|
||||
return markerEl;
|
||||
}
|
||||
|
||||
function setRangeBoundary(doc, range, markerId, atStart) {
|
||||
var markerEl = gEBI(markerId, doc);
|
||||
if (markerEl) {
|
||||
range[atStart ? "setStartBefore" : "setEndBefore"](markerEl);
|
||||
removeNode(markerEl);
|
||||
} else {
|
||||
module.warn("Marker element has been removed. Cannot restore selection.");
|
||||
}
|
||||
}
|
||||
|
||||
function compareRanges(r1, r2) {
|
||||
return r2.compareBoundaryPoints(r1.START_TO_START, r1);
|
||||
}
|
||||
|
||||
function saveRange(range, direction) {
|
||||
var startEl, endEl, doc = api.DomRange.getRangeDocument(range), text = range.toString();
|
||||
var backward = isDirectionBackward(direction);
|
||||
|
||||
if (range.collapsed) {
|
||||
endEl = insertRangeBoundaryMarker(range, false);
|
||||
return {
|
||||
document: doc,
|
||||
markerId: endEl.id,
|
||||
collapsed: true
|
||||
};
|
||||
} else {
|
||||
endEl = insertRangeBoundaryMarker(range, false);
|
||||
startEl = insertRangeBoundaryMarker(range, true);
|
||||
|
||||
return {
|
||||
document: doc,
|
||||
startMarkerId: startEl.id,
|
||||
endMarkerId: endEl.id,
|
||||
collapsed: false,
|
||||
backward: backward,
|
||||
toString: function() {
|
||||
return "original text: '" + text + "', new text: '" + range.toString() + "'";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function restoreRange(rangeInfo, normalize) {
|
||||
var doc = rangeInfo.document;
|
||||
if (typeof normalize == "undefined") {
|
||||
normalize = true;
|
||||
}
|
||||
var range = api.createRange(doc);
|
||||
if (rangeInfo.collapsed) {
|
||||
var markerEl = gEBI(rangeInfo.markerId, doc);
|
||||
if (markerEl) {
|
||||
markerEl.style.display = "inline";
|
||||
var previousNode = markerEl.previousSibling;
|
||||
|
||||
// Workaround for issue 17
|
||||
if (previousNode && previousNode.nodeType == 3) {
|
||||
removeNode(markerEl);
|
||||
range.collapseToPoint(previousNode, previousNode.length);
|
||||
} else {
|
||||
range.collapseBefore(markerEl);
|
||||
removeNode(markerEl);
|
||||
}
|
||||
} else {
|
||||
module.warn("Marker element has been removed. Cannot restore selection.");
|
||||
}
|
||||
} else {
|
||||
setRangeBoundary(doc, range, rangeInfo.startMarkerId, true);
|
||||
setRangeBoundary(doc, range, rangeInfo.endMarkerId, false);
|
||||
}
|
||||
|
||||
if (normalize) {
|
||||
range.normalizeBoundaries();
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
function saveRanges(ranges, direction) {
|
||||
var rangeInfos = [], range, doc;
|
||||
var backward = isDirectionBackward(direction);
|
||||
|
||||
// Order the ranges by position within the DOM, latest first, cloning the array to leave the original untouched
|
||||
ranges = ranges.slice(0);
|
||||
ranges.sort(compareRanges);
|
||||
|
||||
for (var i = 0, len = ranges.length; i < len; ++i) {
|
||||
rangeInfos[i] = saveRange(ranges[i], backward);
|
||||
}
|
||||
|
||||
// Now that all the markers are in place and DOM manipulation over, adjust each range's boundaries to lie
|
||||
// between its markers
|
||||
for (i = len - 1; i >= 0; --i) {
|
||||
range = ranges[i];
|
||||
doc = api.DomRange.getRangeDocument(range);
|
||||
if (range.collapsed) {
|
||||
range.collapseAfter(gEBI(rangeInfos[i].markerId, doc));
|
||||
} else {
|
||||
range.setEndBefore(gEBI(rangeInfos[i].endMarkerId, doc));
|
||||
range.setStartAfter(gEBI(rangeInfos[i].startMarkerId, doc));
|
||||
}
|
||||
}
|
||||
|
||||
return rangeInfos;
|
||||
}
|
||||
|
||||
function saveSelection(win) {
|
||||
if (!api.isSelectionValid(win)) {
|
||||
module.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus.");
|
||||
return null;
|
||||
}
|
||||
var sel = api.getSelection(win);
|
||||
var ranges = sel.getAllRanges();
|
||||
var backward = (ranges.length == 1 && sel.isBackward());
|
||||
|
||||
var rangeInfos = saveRanges(ranges, backward);
|
||||
|
||||
// Ensure current selection is unaffected
|
||||
if (backward) {
|
||||
sel.setSingleRange(ranges[0], backward);
|
||||
} else {
|
||||
sel.setRanges(ranges);
|
||||
}
|
||||
|
||||
return {
|
||||
win: win,
|
||||
rangeInfos: rangeInfos,
|
||||
restored: false
|
||||
};
|
||||
}
|
||||
|
||||
function restoreRanges(rangeInfos) {
|
||||
var ranges = [];
|
||||
|
||||
// Ranges are in reverse order of appearance in the DOM. We want to restore earliest first to avoid
|
||||
// normalization affecting previously restored ranges.
|
||||
var rangeCount = rangeInfos.length;
|
||||
|
||||
for (var i = rangeCount - 1; i >= 0; i--) {
|
||||
ranges[i] = restoreRange(rangeInfos[i], true);
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
function restoreSelection(savedSelection, preserveDirection) {
|
||||
if (!savedSelection.restored) {
|
||||
var rangeInfos = savedSelection.rangeInfos;
|
||||
var sel = api.getSelection(savedSelection.win);
|
||||
var ranges = restoreRanges(rangeInfos), rangeCount = rangeInfos.length;
|
||||
|
||||
if (rangeCount == 1 && preserveDirection && api.features.selectionHasExtend && rangeInfos[0].backward) {
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(ranges[0], true);
|
||||
} else {
|
||||
sel.setRanges(ranges);
|
||||
}
|
||||
|
||||
savedSelection.restored = true;
|
||||
}
|
||||
}
|
||||
|
||||
function removeMarkerElement(doc, markerId) {
|
||||
var markerEl = gEBI(markerId, doc);
|
||||
if (markerEl) {
|
||||
removeNode(markerEl);
|
||||
}
|
||||
}
|
||||
|
||||
function removeMarkers(savedSelection) {
|
||||
var rangeInfos = savedSelection.rangeInfos;
|
||||
for (var i = 0, len = rangeInfos.length, rangeInfo; i < len; ++i) {
|
||||
rangeInfo = rangeInfos[i];
|
||||
if (rangeInfo.collapsed) {
|
||||
removeMarkerElement(savedSelection.doc, rangeInfo.markerId);
|
||||
} else {
|
||||
removeMarkerElement(savedSelection.doc, rangeInfo.startMarkerId);
|
||||
removeMarkerElement(savedSelection.doc, rangeInfo.endMarkerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
api.util.extend(api, {
|
||||
saveRange: saveRange,
|
||||
restoreRange: restoreRange,
|
||||
saveRanges: saveRanges,
|
||||
restoreRanges: restoreRanges,
|
||||
saveSelection: saveSelection,
|
||||
restoreSelection: restoreSelection,
|
||||
removeMarkerElement: removeMarkerElement,
|
||||
removeMarkers: removeMarkers
|
||||
});
|
||||
});
|
1917
web/metronic/global/plugins/wysihtml/lib/rangy/rangy-textrange.js
Normal file
1917
web/metronic/global/plugins/wysihtml/lib/rangy/rangy-textrange.js
Normal file
File diff suppressed because it is too large
Load diff
4
web/metronic/global/plugins/wysihtml/minified/wysihtml.all-commands.min.js
vendored
Normal file
4
web/metronic/global/plugins/wysihtml/minified/wysihtml.all-commands.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
10
web/metronic/global/plugins/wysihtml/minified/wysihtml.min.js
vendored
Normal file
10
web/metronic/global/plugins/wysihtml/minified/wysihtml.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
web/metronic/global/plugins/wysihtml/minified/wysihtml.table_editing.min.js
vendored
Normal file
2
web/metronic/global/plugins/wysihtml/minified/wysihtml.table_editing.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
web/metronic/global/plugins/wysihtml/minified/wysihtml.toolbar.min.js
vendored
Normal file
2
web/metronic/global/plugins/wysihtml/minified/wysihtml.toolbar.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
558
web/metronic/global/plugins/wysihtml/parser_rules/advanced.js
Normal file
558
web/metronic/global/plugins/wysihtml/parser_rules/advanced.js
Normal file
|
@ -0,0 +1,558 @@
|
|||
/**
|
||||
* Full HTML5 compatibility rule set
|
||||
* These rules define which tags and CSS classes are supported and which tags should be specially treated.
|
||||
*
|
||||
* Examples based on this rule set:
|
||||
*
|
||||
* <a href="http://foobar.com">foo</a>
|
||||
* ... becomes ...
|
||||
* <a href="http://foobar.com" target="_blank" rel="nofollow">foo</a>
|
||||
*
|
||||
* <img align="left" src="http://foobar.com/image.png">
|
||||
* ... becomes ...
|
||||
* <img class="wysiwyg-float-left" src="http://foobar.com/image.png" alt="">
|
||||
*
|
||||
* <div>foo<script>alert(document.cookie)</script></div>
|
||||
* ... becomes ...
|
||||
* <div>foo</div>
|
||||
*
|
||||
* <marquee>foo</marquee>
|
||||
* ... becomes ...
|
||||
* <span>foo</span>
|
||||
*
|
||||
* foo <br clear="both"> bar
|
||||
* ... becomes ...
|
||||
* foo <br class="wysiwyg-clear-both"> bar
|
||||
*
|
||||
* <div>hello <iframe src="http://google.com"></iframe></div>
|
||||
* ... becomes ...
|
||||
* <div>hello </div>
|
||||
*
|
||||
* <center>hello</center>
|
||||
* ... becomes ...
|
||||
* <div class="wysiwyg-text-align-center">hello</div>
|
||||
*/
|
||||
var wysihtmlParserRules = {
|
||||
/**
|
||||
* CSS Class white-list
|
||||
* Following CSS classes won't be removed when parsed by the wysihtml HTML parser
|
||||
*/
|
||||
"classes": {
|
||||
"wysiwyg-clear-both": 1,
|
||||
"wysiwyg-clear-left": 1,
|
||||
"wysiwyg-clear-right": 1,
|
||||
"wysiwyg-color-aqua": 1,
|
||||
"wysiwyg-color-black": 1,
|
||||
"wysiwyg-color-blue": 1,
|
||||
"wysiwyg-color-fuchsia": 1,
|
||||
"wysiwyg-color-gray": 1,
|
||||
"wysiwyg-color-green": 1,
|
||||
"wysiwyg-color-lime": 1,
|
||||
"wysiwyg-color-maroon": 1,
|
||||
"wysiwyg-color-navy": 1,
|
||||
"wysiwyg-color-olive": 1,
|
||||
"wysiwyg-color-purple": 1,
|
||||
"wysiwyg-color-red": 1,
|
||||
"wysiwyg-color-silver": 1,
|
||||
"wysiwyg-color-teal": 1,
|
||||
"wysiwyg-color-white": 1,
|
||||
"wysiwyg-color-yellow": 1,
|
||||
"wysiwyg-float-left": 1,
|
||||
"wysiwyg-float-right": 1,
|
||||
"wysiwyg-font-size-large": 1,
|
||||
"wysiwyg-font-size-larger": 1,
|
||||
"wysiwyg-font-size-medium": 1,
|
||||
"wysiwyg-font-size-small": 1,
|
||||
"wysiwyg-font-size-smaller": 1,
|
||||
"wysiwyg-font-size-x-large": 1,
|
||||
"wysiwyg-font-size-x-small": 1,
|
||||
"wysiwyg-font-size-xx-large": 1,
|
||||
"wysiwyg-font-size-xx-small": 1,
|
||||
"wysiwyg-text-align-center": 1,
|
||||
"wysiwyg-text-align-justify": 1,
|
||||
"wysiwyg-text-align-left": 1,
|
||||
"wysiwyg-text-align-right": 1
|
||||
},
|
||||
/**
|
||||
* Tag list
|
||||
*
|
||||
* The following options are available:
|
||||
*
|
||||
* - add_class: converts and deletes the given HTML4 attribute (align, clear, ...) via the given method to a css class
|
||||
* The following methods are implemented in wysihtml.dom.parse:
|
||||
* - align_text: converts align attribute values (right/left/center/justify) to their corresponding css class "wysiwyg-text-align-*")
|
||||
* <p align="center">foo</p> ... becomes ... <p class="wysiwyg-text-align-center">foo</p>
|
||||
* - clear_br: converts clear attribute values left/right/all/both to their corresponding css class "wysiwyg-clear-*"
|
||||
* <br clear="all"> ... becomes ... <br class="wysiwyg-clear-both">
|
||||
* - align_img: converts align attribute values (right/left) on <img> to their corresponding css class "wysiwyg-float-*"
|
||||
*
|
||||
* - add_style: converts and deletes the given HTML4 attribute (align) via the given method to a css style
|
||||
* The following methods are implemented in wysihtml.dom.parse:
|
||||
* - align_text: converts align attribute values (right/left/center) to their corresponding css style)
|
||||
* <p align="center">foo</p> ... becomes ... <p style="text-align:center">foo</p>
|
||||
*
|
||||
* - remove: removes the element and its content
|
||||
*
|
||||
* - unwrap removes element but leaves content
|
||||
*
|
||||
* - rename_tag: renames the element to the given tag
|
||||
*
|
||||
* - set_class: adds the given class to the element (note: make sure that the class is in the "classes" white list above)
|
||||
*
|
||||
* - set_attributes: sets/overrides the given attributes
|
||||
*
|
||||
* - check_attributes: checks the given HTML attribute via the given method
|
||||
* - url: allows only valid urls (starting with http:// or https://)
|
||||
* - src: allows something like "/foobar.jpg", "http://google.com", ...
|
||||
* - href: allows something like "mailto:bert@foo.com", "http://google.com", "/foobar.jpg"
|
||||
* - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML)
|
||||
* - numbers: ensures that the attribute only contains numeric (integer) characters (no float values or units)
|
||||
* - dimension: for with/height attributes where floating point numbrs and percentages are allowed
|
||||
* - any: allows anything to pass
|
||||
*/
|
||||
"tags": {
|
||||
"tr": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"strike": {
|
||||
"remove": 1
|
||||
},
|
||||
"form": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"rt": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"code": {},
|
||||
"acronym": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"br": {
|
||||
"add_class": {
|
||||
"clear": "clear_br"
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"h4": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"em": {},
|
||||
"title": {
|
||||
"remove": 1
|
||||
},
|
||||
"multicol": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"figure": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"xmp": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"small": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-smaller"
|
||||
},
|
||||
"area": {
|
||||
"remove": 1
|
||||
},
|
||||
"time": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"dir": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"bdi": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"command": {
|
||||
"remove": 1
|
||||
},
|
||||
"ul": {},
|
||||
"progress": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"dfn": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"iframe": {
|
||||
"remove": 1
|
||||
},
|
||||
"figcaption": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"a": {
|
||||
"check_attributes": {
|
||||
"target": "any",
|
||||
"href": "url" // if you compiled master manually then change this from 'url' to 'href'
|
||||
},
|
||||
"set_attributes": {
|
||||
"rel": "nofollow"
|
||||
}
|
||||
},
|
||||
"img": {
|
||||
"check_attributes": {
|
||||
"width": "dimension",
|
||||
"alt": "alt",
|
||||
"src": "url", // if you compiled master manually then change this from 'url' to 'src'
|
||||
"height": "dimension"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_img"
|
||||
}
|
||||
},
|
||||
"rb": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"footer": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"noframes": {
|
||||
"remove": 1
|
||||
},
|
||||
"abbr": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"u": {},
|
||||
"bgsound": {
|
||||
"remove": 1
|
||||
},
|
||||
"address": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"basefont": {
|
||||
"remove": 1
|
||||
},
|
||||
"nav": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"h1": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"remove": 1
|
||||
},
|
||||
"tbody": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"dd": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"s": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"li": {},
|
||||
"td": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"remove": 1
|
||||
},
|
||||
"div": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"option": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"select": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"i": {},
|
||||
"track": {
|
||||
"remove": 1
|
||||
},
|
||||
"wbr": {
|
||||
"remove": 1
|
||||
},
|
||||
"fieldset": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"big": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-larger"
|
||||
},
|
||||
"button": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"noscript": {
|
||||
"remove": 1
|
||||
},
|
||||
"svg": {
|
||||
"remove": 1
|
||||
},
|
||||
"input": {
|
||||
"remove": 1
|
||||
},
|
||||
"table": {},
|
||||
"keygen": {
|
||||
"remove": 1
|
||||
},
|
||||
"h5": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"remove": 1
|
||||
},
|
||||
"map": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"isindex": {
|
||||
"remove": 1
|
||||
},
|
||||
"mark": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"caption": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"tfoot": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"remove": 1
|
||||
},
|
||||
"video": {
|
||||
"remove": 1
|
||||
},
|
||||
"strong": {},
|
||||
"canvas": {
|
||||
"remove": 1
|
||||
},
|
||||
"output": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"marquee": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"b": {},
|
||||
"q": {
|
||||
"check_attributes": {
|
||||
"cite": "url"
|
||||
}
|
||||
},
|
||||
"applet": {
|
||||
"remove": 1
|
||||
},
|
||||
"span": {},
|
||||
"rp": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"spacer": {
|
||||
"remove": 1
|
||||
},
|
||||
"source": {
|
||||
"remove": 1
|
||||
},
|
||||
"aside": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"frame": {
|
||||
"remove": 1
|
||||
},
|
||||
"section": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"body": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"ol": {},
|
||||
"nobr": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"html": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"summary": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"var": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"del": {
|
||||
"remove": 1
|
||||
},
|
||||
"blockquote": {
|
||||
"check_attributes": {
|
||||
"cite": "url"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"remove": 1
|
||||
},
|
||||
"device": {
|
||||
"remove": 1
|
||||
},
|
||||
"meter": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"h3": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"textarea": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"embed": {
|
||||
"remove": 1
|
||||
},
|
||||
"hgroup": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"font": {
|
||||
"rename_tag": "span",
|
||||
"add_class": {
|
||||
"size": "size_font"
|
||||
}
|
||||
},
|
||||
"tt": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"noembed": {
|
||||
"remove": 1
|
||||
},
|
||||
"thead": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"blink": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"plaintext": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"xml": {
|
||||
"remove": 1
|
||||
},
|
||||
"h6": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"param": {
|
||||
"remove": 1
|
||||
},
|
||||
"th": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"hr": {},
|
||||
"label": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"dl": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"kbd": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"listing": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"dt": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"nextid": {
|
||||
"remove": 1
|
||||
},
|
||||
"pre": {},
|
||||
"center": {
|
||||
"rename_tag": "div",
|
||||
"set_class": "wysiwyg-text-align-center"
|
||||
},
|
||||
"audio": {
|
||||
"remove": 1
|
||||
},
|
||||
"datalist": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"samp": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"col": {
|
||||
"remove": 1
|
||||
},
|
||||
"article": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"cite": {},
|
||||
"link": {
|
||||
"remove": 1
|
||||
},
|
||||
"script": {
|
||||
"remove": 1
|
||||
},
|
||||
"bdo": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"menu": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"colgroup": {
|
||||
"remove": 1
|
||||
},
|
||||
"ruby": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"h2": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"ins": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"p": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"sub": {},
|
||||
"comment": {
|
||||
"remove": 1
|
||||
},
|
||||
"frameset": {
|
||||
"remove": 1
|
||||
},
|
||||
"optgroup": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"header": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"sup": {}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,680 @@
|
|||
/**
|
||||
* Full HTML5 compatibility rule set
|
||||
* Loosened and extended ruleset. Allows more freedom on user side
|
||||
* These rules define which tags and CSS classes are supported and which tags should be specially treated.
|
||||
*/
|
||||
|
||||
var wysihtmlParserRulesDefaults = {
|
||||
"blockLevelEl": {
|
||||
"keep_styles": {
|
||||
"textAlign": /^((left)|(right)|(center)|(justify))$/i,
|
||||
"float": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
|
||||
"makeDiv": {
|
||||
"rename_tag": "div",
|
||||
"one_of_type": {
|
||||
"alignment_object": 1
|
||||
},
|
||||
"remove_action": "unwrap",
|
||||
"keep_styles": {
|
||||
"textAlign": 1,
|
||||
"float": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var wysihtmlParserRules = {
|
||||
/**
|
||||
* CSS Class white-list
|
||||
* Following CSS classes won't be removed when parsed by the wysihtml HTML parser
|
||||
* If all classes should pass "any" as classes value. Ex: "classes": "any"
|
||||
*/
|
||||
"classes": "any",
|
||||
|
||||
/* blacklist of classes is only available if classes is set to any */
|
||||
"classes_blacklist": {
|
||||
"Apple-interchange-newline": 1,
|
||||
"MsoNormal": 1,
|
||||
"MsoPlainText": 1
|
||||
},
|
||||
|
||||
"type_definitions": {
|
||||
|
||||
"alignment_object": {
|
||||
"classes": {
|
||||
"wysiwyg-text-align-center": 1,
|
||||
"wysiwyg-text-align-justify": 1,
|
||||
"wysiwyg-text-align-left": 1,
|
||||
"wysiwyg-text-align-right": 1,
|
||||
"wysiwyg-float-left": 1,
|
||||
"wysiwyg-float-right": 1
|
||||
},
|
||||
"styles": {
|
||||
"float": ["left", "right"],
|
||||
"text-align": ["left", "right", "center"]
|
||||
}
|
||||
},
|
||||
|
||||
"valid_image_src": {
|
||||
"attrs": {
|
||||
"src": /^[^data\:]/i
|
||||
}
|
||||
},
|
||||
|
||||
"text_color_object": {
|
||||
"styles": {
|
||||
"color": true,
|
||||
"background-color": true
|
||||
}
|
||||
},
|
||||
|
||||
"text_fontsize_object": {
|
||||
"styles": {
|
||||
"font-size": true
|
||||
}
|
||||
},
|
||||
|
||||
"text_formatting_object": {
|
||||
"classes": {
|
||||
"wysiwyg-color-aqua": 1,
|
||||
"wysiwyg-color-black": 1,
|
||||
"wysiwyg-color-blue": 1,
|
||||
"wysiwyg-color-fuchsia": 1,
|
||||
"wysiwyg-color-gray": 1,
|
||||
"wysiwyg-color-green": 1,
|
||||
"wysiwyg-color-lime": 1,
|
||||
"wysiwyg-color-maroon": 1,
|
||||
"wysiwyg-color-navy": 1,
|
||||
"wysiwyg-color-olive": 1,
|
||||
"wysiwyg-color-purple": 1,
|
||||
"wysiwyg-color-red": 1,
|
||||
"wysiwyg-color-silver": 1,
|
||||
"wysiwyg-color-teal": 1,
|
||||
"wysiwyg-color-white": 1,
|
||||
"wysiwyg-color-yellow": 1,
|
||||
"wysiwyg-font-size-large": 1,
|
||||
"wysiwyg-font-size-larger": 1,
|
||||
"wysiwyg-font-size-medium": 1,
|
||||
"wysiwyg-font-size-small": 1,
|
||||
"wysiwyg-font-size-smaller": 1,
|
||||
"wysiwyg-font-size-x-large": 1,
|
||||
"wysiwyg-font-size-x-small": 1,
|
||||
"wysiwyg-font-size-xx-large": 1,
|
||||
"wysiwyg-font-size-xx-small": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"comments": 1, // if set allows comments to pass
|
||||
|
||||
/**
|
||||
* Tag list
|
||||
*
|
||||
* The following options are available:
|
||||
*
|
||||
* - add_class: converts and deletes the given HTML4 attribute (align, clear, ...) via the given method to a css class
|
||||
* The following methods are implemented in wysihtml.dom.parse:
|
||||
* - align_text: converts align attribute values (right/left/center/justify) to their corresponding css class "wysiwyg-text-align-*")
|
||||
* <p align="center">foo</p> ... becomes ... <p> class="wysiwyg-text-align-center">foo</p>
|
||||
* - clear_br: converts clear attribute values left/right/all/both to their corresponding css class "wysiwyg-clear-*"
|
||||
* <br clear="all"> ... becomes ... <br class="wysiwyg-clear-both">
|
||||
* - align_img: converts align attribute values (right/left) on <img> to their corresponding css class "wysiwyg-float-*"
|
||||
*
|
||||
* - remove: removes the element and its content
|
||||
*
|
||||
* - unwrap removes element but leaves content
|
||||
*
|
||||
* - rename_tag: renames the element to the given tag
|
||||
*
|
||||
* - set_class: adds the given class to the element (note: make sure that the class is in the "classes" white list above)
|
||||
*
|
||||
* - set_attributes: sets/overrides the given attributes
|
||||
*
|
||||
* - check_attributes: checks the given HTML attribute via the given method
|
||||
* - url: allows only valid urls (starting with http:// or https://)
|
||||
* - src: allows something like "/foobar.jpg", "http://google.com", ...
|
||||
* - href: allows something like "mailto:bert@foo.com", "http://google.com", "/foobar.jpg"
|
||||
* - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML)
|
||||
* - numbers: ensures that the attribute only contains numeric (integer) characters (no float values or units)
|
||||
* - dimension: for with/height attributes where floating point numbrs and percentages are allowed
|
||||
* - any: allows anything to pass
|
||||
*/
|
||||
"tags": {
|
||||
"tr": {
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"strike": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"form": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"rt": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"code": {},
|
||||
"acronym": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"br": {
|
||||
"add_class": {
|
||||
"clear": "clear_br"
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h4": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"em": {},
|
||||
"title": {
|
||||
"remove": 1
|
||||
},
|
||||
"multicol": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"figure": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"xmp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"small": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-smaller"
|
||||
},
|
||||
"area": {
|
||||
"remove": 1
|
||||
},
|
||||
"time": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dir": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"bdi": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"command": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"ul": {
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"progress": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"dfn": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"iframe": {
|
||||
"check_attributes": {
|
||||
"src": "any",
|
||||
"width": "any",
|
||||
"height": "any",
|
||||
"frameborder": "any",
|
||||
"style": "any",
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"figcaption": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"a": {
|
||||
"check_attributes": {
|
||||
"href": "href", // if you compiled master manually then change this from 'url' to 'href'
|
||||
"rel": "any",
|
||||
"target": "any",
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"img": {
|
||||
"one_of_type": {
|
||||
"valid_image_src": 1
|
||||
},
|
||||
"check_attributes": {
|
||||
"width": "dimension",
|
||||
"alt": "alt",
|
||||
"src": "src", // if you compiled master manually then change this from 'url' to 'src'
|
||||
"height": "dimension",
|
||||
"id": "any"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_img"
|
||||
}
|
||||
},
|
||||
"rb": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"footer": wysihtmlParserRulesDefaults.makeDiv,
|
||||
"noframes": {
|
||||
"remove": 1
|
||||
},
|
||||
"abbr": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"u": {},
|
||||
"bgsound": {
|
||||
"remove": 1
|
||||
},
|
||||
"sup": {},
|
||||
"address": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"basefont": {
|
||||
"remove": 1
|
||||
},
|
||||
"nav": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h1": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"head": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"tbody": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"dd": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"s": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"li": {},
|
||||
"td": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers",
|
||||
"valign": "any",
|
||||
"align": "any",
|
||||
"id": "any",
|
||||
"class": "any"
|
||||
},
|
||||
"keep_styles": {
|
||||
"backgroundColor": 1,
|
||||
"width": 1,
|
||||
"height": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"remove": 1
|
||||
},
|
||||
|
||||
"div": {
|
||||
"one_of_type": {
|
||||
"alignment_object": 1
|
||||
},
|
||||
"remove_action": "unwrap",
|
||||
"keep_styles": {
|
||||
"textAlign": 1,
|
||||
"float": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any",
|
||||
"contenteditable": "any"
|
||||
}
|
||||
},
|
||||
|
||||
"option": {
|
||||
"remove":1
|
||||
},
|
||||
"select": {
|
||||
"remove":1
|
||||
},
|
||||
"i": {},
|
||||
"track": {
|
||||
"remove": 1
|
||||
},
|
||||
"wbr": {
|
||||
"remove": 1
|
||||
},
|
||||
"fieldset": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"big": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-larger"
|
||||
},
|
||||
"button": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"noscript": {
|
||||
"remove": 1
|
||||
},
|
||||
"svg": {
|
||||
"remove": 1
|
||||
},
|
||||
"input": {
|
||||
"remove": 1
|
||||
},
|
||||
"table": {
|
||||
"keep_styles": {
|
||||
"width": 1,
|
||||
"textAlign": 1,
|
||||
"float": 1
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"keygen": {
|
||||
"remove": 1
|
||||
},
|
||||
"h5": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"meta": {
|
||||
"remove": 1
|
||||
},
|
||||
"map": {
|
||||
"remove": 1
|
||||
},
|
||||
"isindex": {
|
||||
"remove": 1
|
||||
},
|
||||
"mark": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"caption": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"tfoot": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"base": {
|
||||
"remove": 1
|
||||
},
|
||||
"video": {
|
||||
"remove": 1
|
||||
},
|
||||
"strong": {},
|
||||
"canvas": {
|
||||
"remove": 1
|
||||
},
|
||||
"output": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"marquee": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"b": {},
|
||||
"q": {
|
||||
"check_attributes": {
|
||||
"cite": "url",
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"applet": {
|
||||
"remove": 1
|
||||
},
|
||||
"span": {
|
||||
"one_of_type": {
|
||||
"text_formatting_object": 1,
|
||||
"text_color_object": 1,
|
||||
"text_fontsize_object": 1
|
||||
},
|
||||
"keep_styles": {
|
||||
"color": 1,
|
||||
"backgroundColor": 1,
|
||||
"fontSize": 1
|
||||
},
|
||||
"remove_action": "unwrap",
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"rp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"spacer": {
|
||||
"remove": 1
|
||||
},
|
||||
"source": {
|
||||
"remove": 1
|
||||
},
|
||||
"aside": wysihtmlParserRulesDefaults.makeDiv,
|
||||
"frame": {
|
||||
"remove": 1
|
||||
},
|
||||
"section": wysihtmlParserRulesDefaults.makeDiv,
|
||||
"body": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"ol": {},
|
||||
"nobr": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"html": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"summary": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"var": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"del": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"blockquote": {
|
||||
"keep_styles": {
|
||||
"textAlign": 1,
|
||||
"float": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"cite": "url",
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"check_attributes": {
|
||||
"type": "any",
|
||||
"src": "any",
|
||||
"charset": "any"
|
||||
}
|
||||
},
|
||||
"device": {
|
||||
"remove": 1
|
||||
},
|
||||
"meter": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h3": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"textarea": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"embed": {
|
||||
"remove": 1
|
||||
},
|
||||
"hgroup": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"font": {
|
||||
"rename_tag": "span",
|
||||
"add_class": {
|
||||
"size": "size_font"
|
||||
}
|
||||
},
|
||||
"tt": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"noembed": {
|
||||
"remove": 1
|
||||
},
|
||||
"thead": {
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
},
|
||||
"check_attributes": {
|
||||
"id": "any"
|
||||
}
|
||||
},
|
||||
"blink": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"plaintext": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"xml": {
|
||||
"remove": 1
|
||||
},
|
||||
"h6": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"param": {
|
||||
"remove": 1
|
||||
},
|
||||
"th": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers",
|
||||
"valign": "any",
|
||||
"align": "any",
|
||||
"id": "any"
|
||||
},
|
||||
"keep_styles": {
|
||||
"backgroundColor": 1,
|
||||
"width": 1,
|
||||
"height": 1
|
||||
},
|
||||
"add_style": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"hr": {},
|
||||
"label": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dl": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"kbd": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"listing": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dt": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"nextid": {
|
||||
"remove": 1
|
||||
},
|
||||
"pre": {},
|
||||
"center": wysihtmlParserRulesDefaults.makeDiv,
|
||||
"audio": {
|
||||
"remove": 1
|
||||
},
|
||||
"datalist": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"samp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"col": {
|
||||
"remove": 1
|
||||
},
|
||||
"article": wysihtmlParserRulesDefaults.makeDiv,
|
||||
"cite": {},
|
||||
"link": {
|
||||
"remove": 1
|
||||
},
|
||||
"script": {
|
||||
"check_attributes": {
|
||||
"type": "any",
|
||||
"src": "any",
|
||||
"charset": "any"
|
||||
}
|
||||
},
|
||||
"bdo": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"menu": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"colgroup": {
|
||||
"remove": 1
|
||||
},
|
||||
"ruby": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h2": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"ins": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"p": wysihtmlParserRulesDefaults.blockLevelEl,
|
||||
"sub": {},
|
||||
"comment": {
|
||||
"remove": 1
|
||||
},
|
||||
"frameset": {
|
||||
"remove": 1
|
||||
},
|
||||
"optgroup": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"header": wysihtmlParserRulesDefaults.makeDiv
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
(function() {
|
||||
// Paste cleanup rules universal for all rules (also applied to content copied from editor)
|
||||
var commonRules = wysihtml.lang.object(wysihtmlParserRules).clone(true);
|
||||
commonRules.comments = false;
|
||||
commonRules.selectors = { "a u": "unwrap"};
|
||||
commonRules.tags.style = { "remove": 1 };
|
||||
commonRules.tags.script = { "remove": 1 };
|
||||
commonRules.tags.head = { "remove": 1 };
|
||||
|
||||
// Paste cleanup for unindentified source
|
||||
var universalRules = wysihtml.lang.object(commonRules).clone(true);
|
||||
universalRules.tags.div.one_of_type.alignment_object = 1;
|
||||
universalRules.tags.div.remove_action = "unwrap";
|
||||
universalRules.tags.div.check_attributes.style = false;
|
||||
universalRules.tags.div.keep_styles = {
|
||||
"textAlign": /^((left)|(right)|(center)|(justify))$/i,
|
||||
"float": 1
|
||||
};
|
||||
universalRules.tags.span.keep_styles = false;
|
||||
|
||||
// Paste cleanup for MS Office
|
||||
// TODO: should be extended to stricter ruleset, as current set will probably not cover all Office bizarreness
|
||||
var msOfficeRules = wysihtml.lang.object(universalRules).clone(true);
|
||||
msOfficeRules.classes = {};
|
||||
|
||||
window.wysihtmlParserPasteRulesets = [
|
||||
{
|
||||
condition: /<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument|class="OutlineElement|id="?docs\-internal\-guid\-/i,
|
||||
set: msOfficeRules
|
||||
},{
|
||||
condition: /<meta name="copied-from" content="wysihtml">/i,
|
||||
set: commonRules
|
||||
},{
|
||||
set: universalRules
|
||||
}
|
||||
];
|
||||
|
||||
})();
|
|
@ -0,0 +1,663 @@
|
|||
/**
|
||||
* Full HTML5 compatibility rule set
|
||||
* These rules define which tags and CSS classes are supported and which tags should be specially treated.
|
||||
*
|
||||
* Examples based on this rule set:
|
||||
*
|
||||
* <a href="http://foobar.com">foo</a>
|
||||
* ... becomes ...
|
||||
* <a href="http://foobar.com" target="_blank" rel="nofollow">foo</a>
|
||||
*
|
||||
* <img align="left" src="http://foobar.com/image.png">
|
||||
* ... becomes ...
|
||||
* <img class="wysiwyg-float-left" src="http://foobar.com/image.png" alt="">
|
||||
*
|
||||
* <div>foo<script>alert(document.cookie);</script></div>
|
||||
* ... becomes ...
|
||||
* <div>foo</div>
|
||||
*
|
||||
* <marquee>foo</marquee>
|
||||
* ... becomes ...
|
||||
* <span>foo</span>
|
||||
*
|
||||
* foo <br clear="both"> bar
|
||||
* ... becomes ...
|
||||
* foo <br class="wysiwyg-clear-both"> bar
|
||||
*
|
||||
* <div>hello <iframe src="http://google.com"></iframe></div>
|
||||
* ... becomes ...
|
||||
* <div>hello </div>
|
||||
*
|
||||
* <center>hello</center>
|
||||
* ... becomes ...
|
||||
* <div class="wysiwyg-text-align-center">hello</div>
|
||||
*/
|
||||
var wysihtmlParserRules = {
|
||||
/**
|
||||
* CSS Class white-list
|
||||
* Following CSS classes won't be removed when parsed by the wysihtml HTML parser
|
||||
* If all classes should pass "any" as classes value. Ex: "classes": "any"
|
||||
*/
|
||||
"classes": {
|
||||
"wysiwyg-clear-both": 1,
|
||||
"wysiwyg-clear-left": 1,
|
||||
"wysiwyg-clear-right": 1,
|
||||
"wysiwyg-color-aqua": 1,
|
||||
"wysiwyg-color-black": 1,
|
||||
"wysiwyg-color-blue": 1,
|
||||
"wysiwyg-color-fuchsia": 1,
|
||||
"wysiwyg-color-gray": 1,
|
||||
"wysiwyg-color-green": 1,
|
||||
"wysiwyg-color-lime": 1,
|
||||
"wysiwyg-color-maroon": 1,
|
||||
"wysiwyg-color-navy": 1,
|
||||
"wysiwyg-color-olive": 1,
|
||||
"wysiwyg-color-purple": 1,
|
||||
"wysiwyg-color-red": 1,
|
||||
"wysiwyg-color-silver": 1,
|
||||
"wysiwyg-color-teal": 1,
|
||||
"wysiwyg-color-white": 1,
|
||||
"wysiwyg-color-yellow": 1,
|
||||
"wysiwyg-float-left": 1,
|
||||
"wysiwyg-float-right": 1,
|
||||
"wysiwyg-font-size-large": 1,
|
||||
"wysiwyg-font-size-larger": 1,
|
||||
"wysiwyg-font-size-medium": 1,
|
||||
"wysiwyg-font-size-small": 1,
|
||||
"wysiwyg-font-size-smaller": 1,
|
||||
"wysiwyg-font-size-x-large": 1,
|
||||
"wysiwyg-font-size-x-small": 1,
|
||||
"wysiwyg-font-size-xx-large": 1,
|
||||
"wysiwyg-font-size-xx-small": 1,
|
||||
"wysiwyg-text-align-center": 1,
|
||||
"wysiwyg-text-align-justify": 1,
|
||||
"wysiwyg-text-align-left": 1,
|
||||
"wysiwyg-text-align-right": 1
|
||||
},
|
||||
|
||||
|
||||
"type_definitions": {
|
||||
|
||||
"visible_content_object": {
|
||||
"methods": {
|
||||
"has_visible_contet": 1
|
||||
}
|
||||
},
|
||||
|
||||
"alignment_object": {
|
||||
"classes": {
|
||||
"wysiwyg-text-align-center": 1,
|
||||
"wysiwyg-text-align-justify": 1,
|
||||
"wysiwyg-text-align-left": 1,
|
||||
"wysiwyg-text-align-right": 1,
|
||||
"wysiwyg-float-left": 1,
|
||||
"wysiwyg-float-right": 1
|
||||
},
|
||||
"styles": {
|
||||
"float": ["left", "right"],
|
||||
"text-align": ["left", "right", "center"]
|
||||
}
|
||||
},
|
||||
|
||||
"valid_image_src": {
|
||||
"attrs": {
|
||||
"src": /^[^data\:]/i
|
||||
}
|
||||
},
|
||||
|
||||
"text_color_object": {
|
||||
"styles": {
|
||||
"color": true,
|
||||
"background-color": true
|
||||
}
|
||||
},
|
||||
|
||||
"text_fontsize_object": {
|
||||
"styles": {
|
||||
"font-size": true
|
||||
}
|
||||
},
|
||||
|
||||
"text_formatting_object": {
|
||||
"classes": {
|
||||
"wysiwyg-color-aqua": 1,
|
||||
"wysiwyg-color-black": 1,
|
||||
"wysiwyg-color-blue": 1,
|
||||
"wysiwyg-color-fuchsia": 1,
|
||||
"wysiwyg-color-gray": 1,
|
||||
"wysiwyg-color-green": 1,
|
||||
"wysiwyg-color-lime": 1,
|
||||
"wysiwyg-color-maroon": 1,
|
||||
"wysiwyg-color-navy": 1,
|
||||
"wysiwyg-color-olive": 1,
|
||||
"wysiwyg-color-purple": 1,
|
||||
"wysiwyg-color-red": 1,
|
||||
"wysiwyg-color-silver": 1,
|
||||
"wysiwyg-color-teal": 1,
|
||||
"wysiwyg-color-white": 1,
|
||||
"wysiwyg-color-yellow": 1,
|
||||
"wysiwyg-font-size-large": 1,
|
||||
"wysiwyg-font-size-larger": 1,
|
||||
"wysiwyg-font-size-medium": 1,
|
||||
"wysiwyg-font-size-small": 1,
|
||||
"wysiwyg-font-size-smaller": 1,
|
||||
"wysiwyg-font-size-x-large": 1,
|
||||
"wysiwyg-font-size-x-small": 1,
|
||||
"wysiwyg-font-size-xx-large": 1,
|
||||
"wysiwyg-font-size-xx-small": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"comments": 1, // if set allows comments to pass
|
||||
|
||||
/**
|
||||
* Tag list
|
||||
*
|
||||
* The following options are available:
|
||||
*
|
||||
* - add_class: converts and deletes the given HTML4 attribute (align, clear, ...) via the given method to a css class
|
||||
* The following methods are implemented in wysihtml.dom.parse:
|
||||
* - align_text: converts align attribute values (right/left/center/justify) to their corresponding css class "wysiwyg-text-align-*")
|
||||
* <p align="center">foo</p> ... becomes ... <p class="wysiwyg-text-align-center">foo</p>
|
||||
* - clear_br: converts clear attribute values left/right/all/both to their corresponding css class "wysiwyg-clear-*"
|
||||
* <br clear="all"> ... becomes ... <br class="wysiwyg-clear-both">
|
||||
* - align_img: converts align attribute values (right/left) on <img> to their corresponding css class "wysiwyg-float-*"
|
||||
*
|
||||
* - add_style: converts and deletes the given HTML4 attribute (align) via the given method to a css style
|
||||
* The following methods are implemented in wysihtml.dom.parse:
|
||||
* - align_text: converts align attribute values (right/left/center) to their corresponding css style)
|
||||
* <p align="center">foo</p> ... becomes ... <p style="text-align:center">foo</p>
|
||||
*
|
||||
* - remove: removes the element and its content
|
||||
*
|
||||
* - unwrap removes element but leaves content
|
||||
*
|
||||
* - rename_tag: renames the element to the given tag
|
||||
*
|
||||
* - set_class: adds the given class to the element (note: make sure that the class is in the "classes" white list above)
|
||||
*
|
||||
* - set_attributes: sets/overrides the given attributes
|
||||
*
|
||||
* - check_attributes: checks the given HTML attribute via the given method
|
||||
* - url: allows only valid urls (starting with http:// or https://)
|
||||
* - src: allows something like "/foobar.jpg", "http://google.com", ...
|
||||
* - href: allows something like "mailto:bert@foo.com", "http://google.com", "/foobar.jpg"
|
||||
* - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML)
|
||||
* - numbers: ensures that the attribute only contains numeric (integer) characters (no float values or units)
|
||||
* - dimension: for with/height attributes where floating point numbrs and percentages are allowed
|
||||
* - any: allows anything to pass
|
||||
*/
|
||||
"tags": {
|
||||
"tr": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"strike": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"form": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"rt": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"code": {},
|
||||
"acronym": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"br": {
|
||||
"add_class": {
|
||||
"clear": "clear_br"
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h4": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"em": {},
|
||||
"title": {
|
||||
"remove": 1
|
||||
},
|
||||
"multicol": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"figure": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"xmp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"small": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-smaller"
|
||||
},
|
||||
"area": {
|
||||
"remove": 1
|
||||
},
|
||||
"time": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dir": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"bdi": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"command": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"ul": {},
|
||||
"progress": {
|
||||
"rename_tag": "span"
|
||||
},
|
||||
"dfn": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"iframe": {
|
||||
"remove": 1
|
||||
},
|
||||
"figcaption": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"a": {
|
||||
"check_attributes": {
|
||||
"href": "href", // if you compiled master manually then change this from 'url' to 'href'
|
||||
"target": "any"
|
||||
},
|
||||
"set_attributes": {
|
||||
"rel": "nofollow"
|
||||
}
|
||||
},
|
||||
"img": {
|
||||
"one_of_type": {
|
||||
"valid_image_src": 1
|
||||
},
|
||||
"check_attributes": {
|
||||
"width": "dimension",
|
||||
"alt": "alt",
|
||||
"src": "src", // if you compiled master manually then change this from 'url' to 'src'
|
||||
"height": "dimension"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_img"
|
||||
}
|
||||
},
|
||||
"rb": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"footer": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"noframes": {
|
||||
"remove": 1
|
||||
},
|
||||
"abbr": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"u": {},
|
||||
"bgsound": {
|
||||
"remove": 1
|
||||
},
|
||||
"sup": {},
|
||||
"address": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"basefont": {
|
||||
"remove": 1
|
||||
},
|
||||
"nav": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h1": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"tbody": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"dd": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"s": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"li": {},
|
||||
"td": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers",
|
||||
"valign": "any",
|
||||
"align": "any"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"remove": 1
|
||||
},
|
||||
|
||||
"div": {
|
||||
"one_of_type": {
|
||||
"visible_content_object": 1
|
||||
},
|
||||
"remove_action": "unwrap",
|
||||
"keep_styles": {
|
||||
"textAlign": 1,
|
||||
"float": 1
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
|
||||
"option": {
|
||||
"remove":1
|
||||
},
|
||||
"select": {
|
||||
"remove":1
|
||||
},
|
||||
"i": {},
|
||||
"track": {
|
||||
"remove": 1
|
||||
},
|
||||
"wbr": {
|
||||
"remove": 1
|
||||
},
|
||||
"fieldset": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"big": {
|
||||
"rename_tag": "span",
|
||||
"set_class": "wysiwyg-font-size-larger"
|
||||
},
|
||||
"button": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"noscript": {
|
||||
"remove": 1
|
||||
},
|
||||
"svg": {
|
||||
"remove": 1
|
||||
},
|
||||
"input": {
|
||||
"remove": 1
|
||||
},
|
||||
"table": {},
|
||||
"keygen": {
|
||||
"remove": 1
|
||||
},
|
||||
"h5": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"remove": 1
|
||||
},
|
||||
"map": {
|
||||
"remove": 1
|
||||
},
|
||||
"isindex": {
|
||||
"remove": 1
|
||||
},
|
||||
"mark": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"caption": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"tfoot": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"remove": 1
|
||||
},
|
||||
"video": {
|
||||
"remove": 1
|
||||
},
|
||||
"strong": {},
|
||||
"canvas": {
|
||||
"remove": 1
|
||||
},
|
||||
"output": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"marquee": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"b": {},
|
||||
"q": {
|
||||
"check_attributes": {
|
||||
"cite": "url"
|
||||
}
|
||||
},
|
||||
"applet": {
|
||||
"remove": 1
|
||||
},
|
||||
"span": {
|
||||
"one_of_type": {
|
||||
"text_formatting_object": 1,
|
||||
"text_color_object": 1,
|
||||
"text_fontsize_object": 1
|
||||
},
|
||||
"keep_styles": {
|
||||
"color": 1,
|
||||
"backgroundColor": 1,
|
||||
"fontSize": 1
|
||||
},
|
||||
"remove_action": "unwrap"
|
||||
},
|
||||
"rp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"spacer": {
|
||||
"remove": 1
|
||||
},
|
||||
"source": {
|
||||
"remove": 1
|
||||
},
|
||||
"aside": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"frame": {
|
||||
"remove": 1
|
||||
},
|
||||
"section": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"body": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"ol": {},
|
||||
"nobr": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"html": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"summary": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"var": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"del": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"blockquote": {
|
||||
"check_attributes": {
|
||||
"cite": "url"
|
||||
}
|
||||
},
|
||||
"style": {
|
||||
"remove": 1
|
||||
},
|
||||
"device": {
|
||||
"remove": 1
|
||||
},
|
||||
"meter": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h3": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"textarea": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"embed": {
|
||||
"remove": 1
|
||||
},
|
||||
"hgroup": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"font": {
|
||||
"rename_tag": "span",
|
||||
"add_class": {
|
||||
"size": "size_font"
|
||||
}
|
||||
},
|
||||
"tt": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"noembed": {
|
||||
"remove": 1
|
||||
},
|
||||
"thead": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"blink": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"plaintext": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"xml": {
|
||||
"remove": 1
|
||||
},
|
||||
"h6": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"param": {
|
||||
"remove": 1
|
||||
},
|
||||
"th": {
|
||||
"check_attributes": {
|
||||
"rowspan": "numbers",
|
||||
"colspan": "numbers"
|
||||
},
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"hr": {},
|
||||
"label": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dl": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"kbd": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"listing": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"dt": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"nextid": {
|
||||
"remove": 1
|
||||
},
|
||||
"pre": {},
|
||||
"center": {
|
||||
"rename_tag": "div",
|
||||
"set_class": "wysiwyg-text-align-center"
|
||||
},
|
||||
"audio": {
|
||||
"remove": 1
|
||||
},
|
||||
"datalist": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"samp": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"col": {
|
||||
"remove": 1
|
||||
},
|
||||
"article": {
|
||||
"rename_tag": "div"
|
||||
},
|
||||
"cite": {},
|
||||
"link": {
|
||||
"remove": 1
|
||||
},
|
||||
"script": {
|
||||
"remove": 1
|
||||
},
|
||||
"bdo": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"menu": {
|
||||
"rename_tag": "ul"
|
||||
},
|
||||
"colgroup": {
|
||||
"remove": 1
|
||||
},
|
||||
"ruby": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"h2": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"ins": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"p": {
|
||||
"add_class": {
|
||||
"align": "align_text"
|
||||
}
|
||||
},
|
||||
"sub": {},
|
||||
"comment": {
|
||||
"remove": 1
|
||||
},
|
||||
"frameset": {
|
||||
"remove": 1
|
||||
},
|
||||
"optgroup": {
|
||||
"unwrap": 1
|
||||
},
|
||||
"header": {
|
||||
"rename_tag": "div"
|
||||
}
|
||||
}
|
||||
};
|
32
web/metronic/global/plugins/wysihtml/parser_rules/simple.js
Normal file
32
web/metronic/global/plugins/wysihtml/parser_rules/simple.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Very simple basic rule set
|
||||
*
|
||||
* Allows
|
||||
* <i>, <em>, <b>, <strong>, <p>, <div>, <a href="http://foo"></a>, <br>, <span>, <ol>, <ul>, <li>
|
||||
*
|
||||
* For a proper documentation of the format check advanced.js
|
||||
*/
|
||||
var wysihtmlParserRules = {
|
||||
tags: {
|
||||
strong: {},
|
||||
b: {},
|
||||
i: {},
|
||||
em: {},
|
||||
br: {},
|
||||
p: {},
|
||||
div: {},
|
||||
span: {},
|
||||
ul: {},
|
||||
ol: {},
|
||||
li: {},
|
||||
a: {
|
||||
set_attributes: {
|
||||
target: "_blank",
|
||||
rel: "nofollow"
|
||||
},
|
||||
check_attributes: {
|
||||
href: "url" // important to avoid XSS
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
602
web/metronic/global/plugins/wysihtml/wysihtml.all-commands.js
Normal file
602
web/metronic/global/plugins/wysihtml/wysihtml.all-commands.js
Normal file
|
@ -0,0 +1,602 @@
|
|||
wysihtml.commands.alignCenterStyle = (function() {
|
||||
var nodeOptions = {
|
||||
styleProperty: "textAlign",
|
||||
styleValue: "center",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.alignJustifyStyle = (function() {
|
||||
var nodeOptions = {
|
||||
styleProperty: "textAlign",
|
||||
styleValue: "justify",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.alignLeftStyle = (function() {
|
||||
var nodeOptions = {
|
||||
styleProperty: "textAlign",
|
||||
styleValue: "left",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.alignRightStyle = (function() {
|
||||
var nodeOptions = {
|
||||
styleProperty: "textAlign",
|
||||
styleValue: "right",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/* Sets text background color by inline styles */
|
||||
wysihtml.commands.bgColorStyle = (function() {
|
||||
return {
|
||||
exec: function(composer, command, color) {
|
||||
var colorVals = wysihtml.quirks.styleParser.parseColor("background-color:" + (color.color || color), "background-color"),
|
||||
colString;
|
||||
|
||||
if (colorVals) {
|
||||
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(', ') : "rgba(" + colorVals.join(', ')) + ')';
|
||||
wysihtml.commands.formatInline.exec(composer, command, {styleProperty: 'backgroundColor', styleValue: colString});
|
||||
}
|
||||
},
|
||||
|
||||
state: function(composer, command, color) {
|
||||
var colorVals = color ? wysihtml.quirks.styleParser.parseColor("background-color:" + (color.color || color), "background-color") : null,
|
||||
colString;
|
||||
|
||||
if (colorVals) {
|
||||
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(', ') : "rgba(" + colorVals.join(', ')) + ')';
|
||||
}
|
||||
|
||||
return wysihtml.commands.formatInline.state(composer, command, {styleProperty: 'backgroundColor', styleValue: colString});
|
||||
},
|
||||
|
||||
remove: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.remove(composer, command, {styleProperty: 'backgroundColor'});
|
||||
},
|
||||
|
||||
stateValue: function(composer, command, props) {
|
||||
var st = this.state(composer, command),
|
||||
colorStr,
|
||||
val = false;
|
||||
|
||||
if (st && wysihtml.lang.object(st).isArray()) {
|
||||
st = st[0];
|
||||
}
|
||||
|
||||
if (st) {
|
||||
colorStr = st.getAttribute('style');
|
||||
if (colorStr) {
|
||||
val = wysihtml.quirks.styleParser.parseColor(colorStr, "background-color");
|
||||
return wysihtml.quirks.styleParser.unparseColor(val, props);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.bold = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "B",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/* Formats block for as a <pre><code class="classname"></code></pre> block
|
||||
* Useful in conjuction for sytax highlight utility: highlight.js
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* editorInstance.composer.commands.exec("formatCode", "language-html");
|
||||
*/
|
||||
wysihtml.commands.formatCode = (function() {
|
||||
return {
|
||||
exec: function(composer, command, classname) {
|
||||
var pre = this.state(composer)[0],
|
||||
code, range, selectedNodes;
|
||||
|
||||
if (pre) {
|
||||
// caret is already within a <pre><code>...</code></pre>
|
||||
composer.selection.executeAndRestore(function() {
|
||||
code = pre.querySelector("code");
|
||||
wysihtml.dom.replaceWithChildNodes(pre);
|
||||
if (code) {
|
||||
wysihtml.dom.replaceWithChildNodes(code);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Wrap in <pre><code>...</code></pre>
|
||||
range = composer.selection.getRange();
|
||||
selectedNodes = range.extractContents();
|
||||
pre = composer.doc.createElement("pre");
|
||||
code = composer.doc.createElement("code");
|
||||
|
||||
if (classname) {
|
||||
code.className = classname;
|
||||
}
|
||||
|
||||
pre.appendChild(code);
|
||||
code.appendChild(selectedNodes);
|
||||
range.insertNode(pre);
|
||||
composer.selection.selectNode(pre);
|
||||
}
|
||||
},
|
||||
|
||||
state: function(composer) {
|
||||
var selectedNode = composer.selection.getSelectedNode(), node;
|
||||
if (selectedNode && selectedNode.nodeName && selectedNode.nodeName == "PRE"&&
|
||||
selectedNode.firstChild && selectedNode.firstChild.nodeName && selectedNode.firstChild.nodeName == "CODE") {
|
||||
return [selectedNode];
|
||||
} else {
|
||||
node = wysihtml.dom.getParentElement(selectedNode, { query: "pre code" });
|
||||
return node ? [node.parentNode] : false;
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Inserts an <img>
|
||||
* If selection is already an image link, it removes it
|
||||
*
|
||||
* @example
|
||||
* // either ...
|
||||
* wysihtml.commands.insertImage.exec(composer, "insertImage", "http://www.google.de/logo.jpg");
|
||||
* // ... or ...
|
||||
* wysihtml.commands.insertImage.exec(composer, "insertImage", { src: "http://www.google.de/logo.jpg", title: "foo" });
|
||||
*/
|
||||
wysihtml.commands.insertImage = (function() {
|
||||
var NODE_NAME = "IMG";
|
||||
return {
|
||||
exec: function(composer, command, value) {
|
||||
value = typeof(value) === "object" ? value : { src: value };
|
||||
|
||||
var doc = composer.doc,
|
||||
image = this.state(composer),
|
||||
textNode,
|
||||
parent;
|
||||
|
||||
// If image is selected and src ie empty, set the caret before it and delete the image
|
||||
if (image && !value.src) {
|
||||
composer.selection.setBefore(image);
|
||||
parent = image.parentNode;
|
||||
parent.removeChild(image);
|
||||
|
||||
// and it's parent <a> too if it hasn't got any other relevant child nodes
|
||||
wysihtml.dom.removeEmptyTextNodes(parent);
|
||||
if (parent.nodeName === "A" && !parent.firstChild) {
|
||||
composer.selection.setAfter(parent);
|
||||
parent.parentNode.removeChild(parent);
|
||||
}
|
||||
|
||||
// firefox and ie sometimes don't remove the image handles, even though the image got removed
|
||||
wysihtml.quirks.redraw(composer.element);
|
||||
return;
|
||||
}
|
||||
|
||||
// If image selected change attributes accordingly
|
||||
if (image) {
|
||||
for (var key in value) {
|
||||
if (value.hasOwnProperty(key)) {
|
||||
image.setAttribute(key === "className" ? "class" : key, value[key]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise lets create the image
|
||||
image = doc.createElement(NODE_NAME);
|
||||
|
||||
for (var i in value) {
|
||||
image.setAttribute(i === "className" ? "class" : i, value[i]);
|
||||
}
|
||||
|
||||
composer.selection.insertNode(image);
|
||||
if (wysihtml.browser.hasProblemsSettingCaretAfterImg()) {
|
||||
textNode = doc.createTextNode(wysihtml.INVISIBLE_SPACE);
|
||||
composer.selection.insertNode(textNode);
|
||||
composer.selection.setAfter(textNode);
|
||||
} else {
|
||||
composer.selection.setAfter(image);
|
||||
}
|
||||
},
|
||||
|
||||
state: function(composer) {
|
||||
var doc = composer.doc,
|
||||
selectedNode,
|
||||
text,
|
||||
imagesInSelection;
|
||||
|
||||
if (!wysihtml.dom.hasElementWithTagName(doc, NODE_NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
selectedNode = composer.selection.getSelectedNode();
|
||||
if (!selectedNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedNode.nodeName === NODE_NAME) {
|
||||
// This works perfectly in IE
|
||||
return selectedNode;
|
||||
}
|
||||
|
||||
if (selectedNode.nodeType !== wysihtml.ELEMENT_NODE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
text = composer.selection.getText();
|
||||
text = wysihtml.lang.string(text).trim();
|
||||
if (text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
imagesInSelection = composer.selection.getNodes(wysihtml.ELEMENT_NODE, function(node) {
|
||||
return node.nodeName === "IMG";
|
||||
});
|
||||
|
||||
if (imagesInSelection.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return imagesInSelection[0];
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.fontSize = (function() {
|
||||
var REG_EXP = /wysiwyg-font-size-[0-9a-z\-]+/g;
|
||||
|
||||
return {
|
||||
exec: function(composer, command, size) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, {className: "wysiwyg-font-size-" + size, classRegExp: REG_EXP, toggle: true});
|
||||
},
|
||||
|
||||
state: function(composer, command, size) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, {className: "wysiwyg-font-size-" + size});
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/* Set font size by inline style */
|
||||
wysihtml.commands.fontSizeStyle = (function() {
|
||||
return {
|
||||
exec: function(composer, command, size) {
|
||||
size = size.size || size;
|
||||
if (!(/^\s*$/).test(size)) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, {styleProperty: "fontSize", styleValue: size, toggle: false});
|
||||
}
|
||||
},
|
||||
|
||||
state: function(composer, command, size) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, {styleProperty: "fontSize", styleValue: size || undefined});
|
||||
},
|
||||
|
||||
remove: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.remove(composer, command, {styleProperty: "fontSize"});
|
||||
},
|
||||
|
||||
stateValue: function(composer, command) {
|
||||
var styleStr,
|
||||
st = this.state(composer, command);
|
||||
|
||||
if (st && wysihtml.lang.object(st).isArray()) {
|
||||
st = st[0];
|
||||
}
|
||||
if (st) {
|
||||
styleStr = st.getAttribute("style");
|
||||
if (styleStr) {
|
||||
return wysihtml.quirks.styleParser.parseFontSize(styleStr);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.foreColor = (function() {
|
||||
var REG_EXP = /wysiwyg-color-[0-9a-z]+/g;
|
||||
|
||||
return {
|
||||
exec: function(composer, command, color) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, {className: "wysiwyg-color-" + color, classRegExp: REG_EXP, toggle: true});
|
||||
},
|
||||
|
||||
state: function(composer, command, color) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, {className: "wysiwyg-color-" + color});
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/* Sets text color by inline styles */
|
||||
wysihtml.commands.foreColorStyle = (function() {
|
||||
return {
|
||||
exec: function(composer, command, color) {
|
||||
var colorVals, colString;
|
||||
|
||||
if (!color) { return; }
|
||||
|
||||
colorVals = wysihtml.quirks.styleParser.parseColor("color:" + (color.color || color), "color");
|
||||
|
||||
if (colorVals) {
|
||||
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(", ") : "rgba(" + colorVals.join(', ')) + ')';
|
||||
wysihtml.commands.formatInline.exec(composer, command, {styleProperty: "color", styleValue: colString});
|
||||
}
|
||||
},
|
||||
|
||||
state: function(composer, command, color) {
|
||||
var colorVals = color ? wysihtml.quirks.styleParser.parseColor("color:" + (color.color || color), "color") : null,
|
||||
colString;
|
||||
|
||||
|
||||
if (colorVals) {
|
||||
colString = (colorVals[3] === 1 ? "rgb(" + [colorVals[0], colorVals[1], colorVals[2]].join(", ") : "rgba(" + colorVals.join(', ')) + ')';
|
||||
}
|
||||
|
||||
return wysihtml.commands.formatInline.state(composer, command, {styleProperty: "color", styleValue: colString});
|
||||
},
|
||||
|
||||
remove: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.remove(composer, command, {styleProperty: "color"});
|
||||
},
|
||||
|
||||
stateValue: function(composer, command, props) {
|
||||
var st = this.state(composer, command),
|
||||
colorStr,
|
||||
val = false;
|
||||
|
||||
if (st && wysihtml.lang.object(st).isArray()) {
|
||||
st = st[0];
|
||||
}
|
||||
|
||||
if (st) {
|
||||
colorStr = st.getAttribute("style");
|
||||
if (colorStr) {
|
||||
val = wysihtml.quirks.styleParser.parseColor(colorStr, "color");
|
||||
return wysihtml.quirks.styleParser.unparseColor(val, props);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.insertBlockQuote = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "BLOCKQUOTE",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.insertOrderedList = (function() {
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.insertList.exec(composer, command, "OL");
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.insertList.state(composer, command, "OL");
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.insertUnorderedList = (function() {
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.insertList.exec(composer, command, "UL");
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.insertList.state(composer, command, "UL");
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.italic = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "I",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, nodeOptions);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
wysihtml.commands.justifyCenter = (function() {
|
||||
var nodeOptions = {
|
||||
className: "wysiwyg-text-align-center",
|
||||
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
wysihtml.commands.justifyFull = (function() {
|
||||
var nodeOptions = {
|
||||
className: "wysiwyg-text-align-justify",
|
||||
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.justifyLeft = (function() {
|
||||
var nodeOptions = {
|
||||
className: "wysiwyg-text-align-left",
|
||||
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.justifyRight = (function() {
|
||||
var nodeOptions = {
|
||||
className: "wysiwyg-text-align-right",
|
||||
classRegExp: /wysiwyg-text-align-[0-9a-z]+/g,
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.exec(composer, "formatBlock", nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatBlock.state(composer, "formatBlock", nodeOptions);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
wysihtml.commands.subscript = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "SUB",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, nodeOptions);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
wysihtml.commands.superscript = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "SUP",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, nodeOptions);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
wysihtml.commands.underline = (function() {
|
||||
var nodeOptions = {
|
||||
nodeName: "U",
|
||||
toggle: true
|
||||
};
|
||||
|
||||
return {
|
||||
exec: function(composer, command) {
|
||||
wysihtml.commands.formatInline.exec(composer, command, nodeOptions);
|
||||
},
|
||||
|
||||
state: function(composer, command) {
|
||||
return wysihtml.commands.formatInline.state(composer, command, nodeOptions);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
15937
web/metronic/global/plugins/wysihtml/wysihtml.js
Normal file
15937
web/metronic/global/plugins/wysihtml/wysihtml.js
Normal file
File diff suppressed because it is too large
Load diff
1163
web/metronic/global/plugins/wysihtml/wysihtml.table_editing.js
Normal file
1163
web/metronic/global/plugins/wysihtml/wysihtml.table_editing.js
Normal file
File diff suppressed because it is too large
Load diff
850
web/metronic/global/plugins/wysihtml/wysihtml.toolbar.js
Normal file
850
web/metronic/global/plugins/wysihtml/wysihtml.toolbar.js
Normal file
|
@ -0,0 +1,850 @@
|
|||
/**
|
||||
* Toolbar Dialog
|
||||
*
|
||||
* @param {Element} link The toolbar link which causes the dialog to show up
|
||||
* @param {Element} container The dialog container
|
||||
*
|
||||
* @example
|
||||
* <!-- Toolbar link -->
|
||||
* <a data-wysihtml-command="insertImage">insert an image</a>
|
||||
*
|
||||
* <!-- Dialog -->
|
||||
* <div data-wysihtml-dialog="insertImage" style="display: none;">
|
||||
* <label>
|
||||
* URL: <input data-wysihtml-dialog-field="src" value="http://">
|
||||
* </label>
|
||||
* <label>
|
||||
* Alternative text: <input data-wysihtml-dialog-field="alt" value="">
|
||||
* </label>
|
||||
* </div>
|
||||
*
|
||||
* <script>
|
||||
* var dialog = new wysihtml.toolbar.Dialog(
|
||||
* document.querySelector("[data-wysihtml-command='insertImage']"),
|
||||
* document.querySelector("[data-wysihtml-dialog='insertImage']")
|
||||
* );
|
||||
* dialog.observe("save", function(attributes) {
|
||||
* // do something
|
||||
* });
|
||||
* </script>
|
||||
*/
|
||||
(function(wysihtml) {
|
||||
var dom = wysihtml.dom,
|
||||
CLASS_NAME_OPENED = "wysihtml-command-dialog-opened",
|
||||
SELECTOR_FORM_ELEMENTS = "input, select, textarea",
|
||||
SELECTOR_FIELDS = "[data-wysihtml-dialog-field]",
|
||||
ATTRIBUTE_FIELDS = "data-wysihtml-dialog-field";
|
||||
|
||||
|
||||
wysihtml.toolbar.Dialog = wysihtml.lang.Dispatcher.extend(
|
||||
/** @scope wysihtml.toolbar.Dialog.prototype */ {
|
||||
constructor: function(link, container) {
|
||||
this.link = link;
|
||||
this.container = container;
|
||||
},
|
||||
|
||||
_observe: function() {
|
||||
if (this._observed) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this,
|
||||
callbackWrapper = function(event) {
|
||||
var attributes = that._serialize();
|
||||
that.fire("save", attributes);
|
||||
that.hide();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
dom.observe(that.link, "click", function() {
|
||||
if (dom.hasClass(that.link, CLASS_NAME_OPENED)) {
|
||||
setTimeout(function() { that.hide(); }, 0);
|
||||
}
|
||||
});
|
||||
|
||||
dom.observe(this.container, "keydown", function(event) {
|
||||
var keyCode = event.keyCode;
|
||||
if (keyCode === wysihtml.ENTER_KEY) {
|
||||
callbackWrapper(event);
|
||||
}
|
||||
if (keyCode === wysihtml.ESCAPE_KEY) {
|
||||
that.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
dom.delegate(this.container, "[data-wysihtml-dialog-action=save]", "click", callbackWrapper);
|
||||
|
||||
dom.delegate(this.container, "[data-wysihtml-dialog-action=cancel]", "click", function(event) {
|
||||
that.cancel();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
this._observed = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Grabs all fields in the dialog and puts them in key=>value style in an object which
|
||||
* then gets returned
|
||||
*/
|
||||
_serialize: function() {
|
||||
var data = {},
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0;
|
||||
|
||||
for (; i<length; i++) {
|
||||
data[fields[i].getAttribute(ATTRIBUTE_FIELDS)] = fields[i].value;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes the attributes of the "elementToChange"
|
||||
* and inserts them in their corresponding dialog input fields
|
||||
*
|
||||
* Assume the "elementToChange" looks like this:
|
||||
* <a href="http://www.google.com" target="_blank">foo</a>
|
||||
*
|
||||
* and we have the following dialog:
|
||||
* <input type="text" data-wysihtml-dialog-field="href" value="">
|
||||
* <input type="text" data-wysihtml-dialog-field="target" value="">
|
||||
*
|
||||
* after calling _interpolate() the dialog will look like this
|
||||
* <input type="text" data-wysihtml-dialog-field="href" value="http://www.google.com">
|
||||
* <input type="text" data-wysihtml-dialog-field="target" value="_blank">
|
||||
*
|
||||
* Basically it adopted the attribute values into the corresponding input fields
|
||||
*
|
||||
*/
|
||||
_interpolate: function(avoidHiddenFields) {
|
||||
var field,
|
||||
fieldName,
|
||||
newValue,
|
||||
focusedElement = document.querySelector(":focus"),
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0;
|
||||
for (; i<length; i++) {
|
||||
field = fields[i];
|
||||
|
||||
// Never change elements where the user is currently typing in
|
||||
if (field === focusedElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't update hidden fields
|
||||
// See https://github.com/xing/wysihtml5/pull/14
|
||||
if (avoidHiddenFields && field.type === "hidden") {
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldName = field.getAttribute(ATTRIBUTE_FIELDS);
|
||||
newValue = (this.elementToChange && typeof(this.elementToChange) !== 'boolean') ? (this.elementToChange.getAttribute(fieldName) || "") : field.defaultValue;
|
||||
field.value = newValue;
|
||||
}
|
||||
},
|
||||
|
||||
update: function (elementToChange) {
|
||||
this.elementToChange = elementToChange ? elementToChange : this.elementToChange;
|
||||
this._interpolate();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the dialog element
|
||||
*/
|
||||
show: function(elementToChange) {
|
||||
var firstField = this.container.querySelector(SELECTOR_FORM_ELEMENTS);
|
||||
|
||||
this._observe();
|
||||
this.update(elementToChange);
|
||||
|
||||
dom.addClass(this.link, CLASS_NAME_OPENED);
|
||||
this.container.style.display = "";
|
||||
this.isOpen = true;
|
||||
this.fire("show");
|
||||
|
||||
if (firstField && !elementToChange) {
|
||||
try {
|
||||
firstField.focus();
|
||||
} catch(e) {}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the dialog element
|
||||
*/
|
||||
_hide: function(focus) {
|
||||
this.elementToChange = null;
|
||||
dom.removeClass(this.link, CLASS_NAME_OPENED);
|
||||
this.container.style.display = "none";
|
||||
this.isOpen = false;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._hide();
|
||||
this.fire("hide");
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._hide();
|
||||
this.fire("cancel");
|
||||
}
|
||||
});
|
||||
})(wysihtml); //jshint ignore:line
|
||||
|
||||
(function(wysihtml) {
|
||||
var dom = wysihtml.dom,
|
||||
SELECTOR_FIELDS = "[data-wysihtml-dialog-field]",
|
||||
ATTRIBUTE_FIELDS = "data-wysihtml-dialog-field";
|
||||
|
||||
wysihtml.toolbar.Dialog_bgColorStyle = wysihtml.toolbar.Dialog.extend({
|
||||
multiselect: true,
|
||||
|
||||
_serialize: function() {
|
||||
var data = {},
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0;
|
||||
|
||||
for (; i<length; i++) {
|
||||
data[fields[i].getAttribute(ATTRIBUTE_FIELDS)] = fields[i].value;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
_interpolate: function(avoidHiddenFields) {
|
||||
var field,
|
||||
fieldName,
|
||||
newValue,
|
||||
focusedElement = document.querySelector(":focus"),
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0,
|
||||
firstElement = (this.elementToChange) ? ((wysihtml.lang.object(this.elementToChange).isArray()) ? this.elementToChange[0] : this.elementToChange) : null,
|
||||
colorStr = (firstElement) ? firstElement.getAttribute('style') : null,
|
||||
color = (colorStr) ? wysihtml.quirks.styleParser.parseColor(colorStr, "background-color") : null;
|
||||
|
||||
for (; i<length; i++) {
|
||||
field = fields[i];
|
||||
// Never change elements where the user is currently typing in
|
||||
if (field === focusedElement) {
|
||||
continue;
|
||||
}
|
||||
// Don't update hidden fields3
|
||||
if (avoidHiddenFields && field.type === "hidden") {
|
||||
continue;
|
||||
}
|
||||
if (field.getAttribute(ATTRIBUTE_FIELDS) === "color") {
|
||||
if (color) {
|
||||
if (color[3] && color[3] != 1) {
|
||||
field.value = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ");";
|
||||
} else {
|
||||
field.value = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ");";
|
||||
}
|
||||
} else {
|
||||
field.value = "rgb(0,0,0);";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
})(wysihtml);
|
||||
|
||||
(function(wysihtml) {
|
||||
wysihtml.toolbar.Dialog_createTable = wysihtml.toolbar.Dialog.extend({
|
||||
show: function(elementToChange) {
|
||||
this.base(elementToChange);
|
||||
}
|
||||
});
|
||||
})(wysihtml);
|
||||
|
||||
(function(wysihtml) {
|
||||
var dom = wysihtml.dom,
|
||||
SELECTOR_FIELDS = "[data-wysihtml-dialog-field]",
|
||||
ATTRIBUTE_FIELDS = "data-wysihtml-dialog-field";
|
||||
|
||||
wysihtml.toolbar.Dialog_fontSizeStyle = wysihtml.toolbar.Dialog.extend({
|
||||
multiselect: true,
|
||||
|
||||
_serialize: function() {
|
||||
return {"size" : this.container.querySelector('[data-wysihtml-dialog-field="size"]').value};
|
||||
},
|
||||
|
||||
_interpolate: function(avoidHiddenFields) {
|
||||
var focusedElement = document.querySelector(":focus"),
|
||||
field = this.container.querySelector("[data-wysihtml-dialog-field='size']"),
|
||||
firstElement = (this.elementToChange) ? ((wysihtml.lang.object(this.elementToChange).isArray()) ? this.elementToChange[0] : this.elementToChange) : null,
|
||||
styleStr = (firstElement) ? firstElement.getAttribute('style') : null,
|
||||
size = (styleStr) ? wysihtml.quirks.styleParser.parseFontSize(styleStr) : null;
|
||||
|
||||
if (field && field !== focusedElement && size && !(/^\s*$/).test(size)) {
|
||||
field.value = size;
|
||||
}
|
||||
}
|
||||
});
|
||||
})(wysihtml);
|
||||
|
||||
(function(wysihtml) {
|
||||
var SELECTOR_FIELDS = "[data-wysihtml-dialog-field]",
|
||||
ATTRIBUTE_FIELDS = "data-wysihtml-dialog-field";
|
||||
|
||||
wysihtml.toolbar.Dialog_foreColorStyle = wysihtml.toolbar.Dialog.extend({
|
||||
multiselect: true,
|
||||
|
||||
_serialize: function() {
|
||||
var data = {},
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0;
|
||||
|
||||
for (; i<length; i++) {
|
||||
data[fields[i].getAttribute(ATTRIBUTE_FIELDS)] = fields[i].value;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
_interpolate: function(avoidHiddenFields) {
|
||||
var field, colourMode,
|
||||
styleParser = wysihtml.quirks.styleParser,
|
||||
focusedElement = document.querySelector(":focus"),
|
||||
fields = this.container.querySelectorAll(SELECTOR_FIELDS),
|
||||
length = fields.length,
|
||||
i = 0,
|
||||
firstElement = (this.elementToChange) ? ((wysihtml.lang.object(this.elementToChange).isArray()) ? this.elementToChange[0] : this.elementToChange) : null,
|
||||
colourStr = (firstElement) ? firstElement.getAttribute("style") : null,
|
||||
colour = (colourStr) ? styleParser.parseColor(colourStr, "color") : null;
|
||||
|
||||
for (; i<length; i++) {
|
||||
field = fields[i];
|
||||
// Never change elements where the user is currently typing in
|
||||
if (field === focusedElement) {
|
||||
continue;
|
||||
}
|
||||
// Don't update hidden fields3
|
||||
if (avoidHiddenFields && field.type === "hidden") {
|
||||
continue;
|
||||
}
|
||||
if (field.getAttribute(ATTRIBUTE_FIELDS) === "color") {
|
||||
colourMode = (field.dataset.colormode || "rgb").toLowerCase();
|
||||
colourMode = colourMode === "hex" ? "hash" : colourMode;
|
||||
|
||||
if (colour) {
|
||||
field.value = styleParser.unparseColor(colour, colourMode);
|
||||
} else {
|
||||
field.value = styleParser.unparseColor([0, 0, 0], colourMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
})(wysihtml);
|
||||
|
||||
/**
|
||||
* Converts speech-to-text and inserts this into the editor
|
||||
* As of now (2011/03/25) this only is supported in Chrome >= 11
|
||||
*
|
||||
* Note that it sends the recorded audio to the google speech recognition api:
|
||||
* http://stackoverflow.com/questions/4361826/does-chrome-have-buil-in-speech-recognition-for-input-type-text-x-webkit-speec
|
||||
*
|
||||
* Current HTML5 draft can be found here
|
||||
* http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html
|
||||
*
|
||||
* "Accessing Google Speech API Chrome 11"
|
||||
* http://mikepultz.com/2011/03/accessing-google-speech-api-chrome-11/
|
||||
*/
|
||||
(function(wysihtml) {
|
||||
var dom = wysihtml.dom;
|
||||
|
||||
var linkStyles = {
|
||||
position: "relative"
|
||||
};
|
||||
|
||||
var wrapperStyles = {
|
||||
left: 0,
|
||||
margin: 0,
|
||||
opacity: 0,
|
||||
overflow: "hidden",
|
||||
padding: 0,
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
zIndex: 1
|
||||
};
|
||||
|
||||
var inputStyles = {
|
||||
cursor: "inherit",
|
||||
fontSize: "50px",
|
||||
height: "50px",
|
||||
marginTop: "-25px",
|
||||
outline: 0,
|
||||
padding: 0,
|
||||
position: "absolute",
|
||||
right: "-4px",
|
||||
top: "50%"
|
||||
};
|
||||
|
||||
var inputAttributes = {
|
||||
"x-webkit-speech": "",
|
||||
"speech": ""
|
||||
};
|
||||
|
||||
wysihtml.toolbar.Speech = function(parent, link) {
|
||||
var input = document.createElement("input");
|
||||
if (!wysihtml.browser.supportsSpeechApiOn(input)) {
|
||||
link.style.display = "none";
|
||||
return;
|
||||
}
|
||||
var lang = parent.editor.textarea.element.getAttribute("lang");
|
||||
if (lang) {
|
||||
inputAttributes.lang = lang;
|
||||
}
|
||||
|
||||
var wrapper = document.createElement("div");
|
||||
|
||||
wysihtml.lang.object(wrapperStyles).merge({
|
||||
width: link.offsetWidth + "px",
|
||||
height: link.offsetHeight + "px"
|
||||
});
|
||||
|
||||
dom.insert(input).into(wrapper);
|
||||
dom.insert(wrapper).into(link);
|
||||
|
||||
dom.setStyles(inputStyles).on(input);
|
||||
dom.setAttributes(inputAttributes).on(input);
|
||||
|
||||
dom.setStyles(wrapperStyles).on(wrapper);
|
||||
dom.setStyles(linkStyles).on(link);
|
||||
|
||||
var eventName = "onwebkitspeechchange" in input ? "webkitspeechchange" : "speechchange";
|
||||
dom.observe(input, eventName, function() {
|
||||
parent.execCommand("insertText", input.value);
|
||||
input.value = "";
|
||||
});
|
||||
|
||||
dom.observe(input, "click", function(event) {
|
||||
if (dom.hasClass(link, "wysihtml-command-disabled")) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
};
|
||||
})(wysihtml);
|
||||
|
||||
/**
|
||||
* Toolbar
|
||||
*
|
||||
* @param {Object} parent Reference to instance of Editor instance
|
||||
* @param {Element} container Reference to the toolbar container element
|
||||
*
|
||||
* @example
|
||||
* <div id="toolbar">
|
||||
* <a data-wysihtml-command="createLink">insert link</a>
|
||||
* <a data-wysihtml-command="formatBlock" data-wysihtml-command-value="h1">insert h1</a>
|
||||
* </div>
|
||||
*
|
||||
* <script>
|
||||
* var toolbar = new wysihtml.toolbar.Toolbar(editor, document.getElementById("toolbar"));
|
||||
* </script>
|
||||
*/
|
||||
(function(wysihtml) {
|
||||
var CLASS_NAME_COMMAND_DISABLED = "wysihtml-command-disabled",
|
||||
CLASS_NAME_COMMANDS_DISABLED = "wysihtml-commands-disabled",
|
||||
CLASS_NAME_COMMAND_ACTIVE = "wysihtml-command-active",
|
||||
CLASS_NAME_ACTION_ACTIVE = "wysihtml-action-active",
|
||||
dom = wysihtml.dom;
|
||||
|
||||
wysihtml.toolbar.Toolbar = Base.extend(
|
||||
/** @scope wysihtml.toolbar.Toolbar.prototype */ {
|
||||
constructor: function(editor, container, showOnInit) {
|
||||
this.editor = editor;
|
||||
this.container = typeof(container) === "string" ? document.getElementById(container) : container;
|
||||
this.composer = editor.composer;
|
||||
|
||||
this._getLinks("command");
|
||||
this._getLinks("action");
|
||||
|
||||
this._observe();
|
||||
if (showOnInit) { this.show(); }
|
||||
|
||||
if (editor.config.classNameCommandDisabled != null) {
|
||||
CLASS_NAME_COMMAND_DISABLED = editor.config.classNameCommandDisabled;
|
||||
}
|
||||
if (editor.config.classNameCommandsDisabled != null) {
|
||||
CLASS_NAME_COMMANDS_DISABLED = editor.config.classNameCommandsDisabled;
|
||||
}
|
||||
if (editor.config.classNameCommandActive != null) {
|
||||
CLASS_NAME_COMMAND_ACTIVE = editor.config.classNameCommandActive;
|
||||
}
|
||||
if (editor.config.classNameActionActive != null) {
|
||||
CLASS_NAME_ACTION_ACTIVE = editor.config.classNameActionActive;
|
||||
}
|
||||
|
||||
var speechInputLinks = this.container.querySelectorAll("[data-wysihtml-command=insertSpeech]"),
|
||||
length = speechInputLinks.length,
|
||||
i = 0;
|
||||
for (; i<length; i++) {
|
||||
new wysihtml.toolbar.Speech(this, speechInputLinks[i]);
|
||||
}
|
||||
},
|
||||
|
||||
_getLinks: function(type) {
|
||||
var links = this[type + "Links"] = wysihtml.lang.array(this.container.querySelectorAll("[data-wysihtml-" + type + "]")).get(),
|
||||
length = links.length,
|
||||
i = 0,
|
||||
mapping = this[type + "Mapping"] = {},
|
||||
link,
|
||||
group,
|
||||
name,
|
||||
value,
|
||||
dialog,
|
||||
tracksBlankValue;
|
||||
|
||||
for (; i<length; i++) {
|
||||
link = links[i];
|
||||
name = link.getAttribute("data-wysihtml-" + type);
|
||||
value = link.getAttribute("data-wysihtml-" + type + "-value");
|
||||
tracksBlankValue = link.getAttribute("data-wysihtml-" + type + "-blank-value");
|
||||
group = this.container.querySelector("[data-wysihtml-" + type + "-group='" + name + "']");
|
||||
dialog = this._getDialog(link, name);
|
||||
|
||||
mapping[name + ":" + value] = {
|
||||
link: link,
|
||||
group: group,
|
||||
name: name,
|
||||
value: value,
|
||||
tracksBlankValue: tracksBlankValue,
|
||||
dialog: dialog,
|
||||
state: false
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
_getDialog: function(link, command) {
|
||||
var that = this,
|
||||
dialogElement = this.container.querySelector("[data-wysihtml-dialog='" + command + "']"),
|
||||
dialog, caretBookmark;
|
||||
|
||||
if (dialogElement) {
|
||||
if (wysihtml.toolbar["Dialog_" + command]) {
|
||||
dialog = new wysihtml.toolbar["Dialog_" + command](link, dialogElement);
|
||||
} else {
|
||||
dialog = new wysihtml.toolbar.Dialog(link, dialogElement);
|
||||
}
|
||||
|
||||
dialog.on("show", function() {
|
||||
caretBookmark = that.composer.selection.getBookmark();
|
||||
that.editor.fire("show:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
||||
});
|
||||
|
||||
dialog.on("save", function(attributes) {
|
||||
if (caretBookmark) {
|
||||
that.composer.selection.setBookmark(caretBookmark);
|
||||
}
|
||||
that._execCommand(command, attributes);
|
||||
that.editor.fire("save:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
||||
that._hideAllDialogs();
|
||||
that._preventInstantFocus();
|
||||
caretBookmark = undefined;
|
||||
|
||||
});
|
||||
|
||||
dialog.on("cancel", function() {
|
||||
if (caretBookmark) {
|
||||
that.composer.selection.setBookmark(caretBookmark);
|
||||
}
|
||||
that.editor.fire("cancel:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
||||
caretBookmark = undefined;
|
||||
that._preventInstantFocus();
|
||||
});
|
||||
|
||||
dialog.on("hide", function() {
|
||||
that.editor.fire("hide:dialog", { command: command, dialogContainer: dialogElement, commandLink: link });
|
||||
caretBookmark = undefined;
|
||||
});
|
||||
|
||||
}
|
||||
return dialog;
|
||||
},
|
||||
|
||||
/**
|
||||
* @example
|
||||
* var toolbar = new wysihtml.Toolbar();
|
||||
* // Insert a <blockquote> element or wrap current selection in <blockquote>
|
||||
* toolbar.execCommand("formatBlock", "blockquote");
|
||||
*/
|
||||
execCommand: function(command, commandValue) {
|
||||
if (this.commandsDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._execCommand(command, commandValue);
|
||||
},
|
||||
|
||||
_execCommand: function(command, commandValue) {
|
||||
// Make sure that composer is focussed (false => don't move caret to the end)
|
||||
this.editor.focus(false);
|
||||
|
||||
this.composer.commands.exec(command, commandValue);
|
||||
this._updateLinkStates();
|
||||
},
|
||||
|
||||
execAction: function(action) {
|
||||
var editor = this.editor;
|
||||
if (action === "change_view") {
|
||||
if (editor.currentView === editor.textarea || editor.currentView === "source") {
|
||||
editor.fire("change_view", "composer");
|
||||
} else {
|
||||
editor.fire("change_view", "textarea");
|
||||
}
|
||||
}
|
||||
if (action == "showSource") {
|
||||
editor.fire("showSource");
|
||||
}
|
||||
},
|
||||
|
||||
_observe: function() {
|
||||
var that = this,
|
||||
editor = this.editor,
|
||||
container = this.container,
|
||||
links = this.commandLinks.concat(this.actionLinks),
|
||||
length = links.length,
|
||||
i = 0;
|
||||
|
||||
for (; i<length; i++) {
|
||||
// 'javascript:;' and unselectable=on Needed for IE, but done in all browsers to make sure that all get the same css applied
|
||||
// (you know, a:link { ... } doesn't match anchors with missing href attribute)
|
||||
if (links[i].nodeName === "A") {
|
||||
dom.setAttributes({
|
||||
href: "javascript:;",
|
||||
unselectable: "on"
|
||||
}).on(links[i]);
|
||||
} else {
|
||||
dom.setAttributes({ unselectable: "on" }).on(links[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Needed for opera and chrome
|
||||
dom.delegate(container, "[data-wysihtml-command], [data-wysihtml-action]", "mousedown", function(event) { event.preventDefault(); });
|
||||
|
||||
dom.delegate(container, "[data-wysihtml-command]", "click", function(event) {
|
||||
var state,
|
||||
link = this,
|
||||
command = link.getAttribute("data-wysihtml-command"),
|
||||
commandValue = link.getAttribute("data-wysihtml-command-value"),
|
||||
commandObj = that.commandMapping[command + ":" + commandValue];
|
||||
|
||||
if (commandValue || !commandObj.dialog) {
|
||||
that.execCommand(command, commandValue);
|
||||
} else {
|
||||
state = getCommandState(that.composer, commandObj);
|
||||
commandObj.dialog.show(state);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
dom.delegate(container, "[data-wysihtml-action]", "click", function(event) {
|
||||
var action = this.getAttribute("data-wysihtml-action");
|
||||
that.execAction(action);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
editor.on("interaction:composer", function(event) {
|
||||
if (!that.preventFocus) {
|
||||
that._updateLinkStates();
|
||||
}
|
||||
});
|
||||
|
||||
this._ownerDocumentClick = function(event) {
|
||||
if (!wysihtml.dom.contains(that.container, event.target) && !wysihtml.dom.contains(that.composer.element, event.target)) {
|
||||
that._updateLinkStates();
|
||||
that._preventInstantFocus();
|
||||
}
|
||||
};
|
||||
|
||||
this.container.ownerDocument.addEventListener("click", this._ownerDocumentClick, false);
|
||||
this.editor.on("destroy:composer", this.destroy.bind(this));
|
||||
|
||||
if (this.editor.config.handleTables) {
|
||||
editor.on("tableselect:composer", function() {
|
||||
that.container.querySelectorAll('[data-wysihtml-hiddentools="table"]')[0].style.display = "";
|
||||
});
|
||||
editor.on("tableunselect:composer", function() {
|
||||
that.container.querySelectorAll('[data-wysihtml-hiddentools="table"]')[0].style.display = "none";
|
||||
});
|
||||
}
|
||||
|
||||
editor.on("change_view", function(currentView) {
|
||||
// Set timeout needed in order to let the blur event fire first
|
||||
setTimeout(function() {
|
||||
that.commandsDisabled = (currentView !== "composer");
|
||||
that._updateLinkStates();
|
||||
if (that.commandsDisabled) {
|
||||
dom.addClass(container, CLASS_NAME_COMMANDS_DISABLED);
|
||||
} else {
|
||||
dom.removeClass(container, CLASS_NAME_COMMANDS_DISABLED);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.container.ownerDocument.removeEventListener("click", this._ownerDocumentClick, false);
|
||||
},
|
||||
|
||||
_hideAllDialogs: function() {
|
||||
var commandMapping = this.commandMapping;
|
||||
for (var i in commandMapping) {
|
||||
if (commandMapping[i].dialog) {
|
||||
commandMapping[i].dialog.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_preventInstantFocus: function() {
|
||||
this.preventFocus = true;
|
||||
setTimeout(function() {
|
||||
this.preventFocus = false;
|
||||
}.bind(this),0);
|
||||
},
|
||||
|
||||
_updateLinkStates: function() {
|
||||
|
||||
var i, state, action, command, displayDialogAttributeValue,
|
||||
commandMapping = this.commandMapping,
|
||||
composer = this.composer,
|
||||
actionMapping = this.actionMapping;
|
||||
// every millisecond counts... this is executed quite often
|
||||
for (i in commandMapping) {
|
||||
command = commandMapping[i];
|
||||
if (this.commandsDisabled) {
|
||||
state = false;
|
||||
dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
||||
if (command.group) {
|
||||
dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
||||
}
|
||||
if (command.dialog) {
|
||||
command.dialog.hide();
|
||||
}
|
||||
} else {
|
||||
state = this.composer.commands.state(command.name, command.value);
|
||||
dom.removeClass(command.link, CLASS_NAME_COMMAND_DISABLED);
|
||||
if (command.group) {
|
||||
dom.removeClass(command.group, CLASS_NAME_COMMAND_DISABLED);
|
||||
}
|
||||
}
|
||||
if (command.state === state && !command.tracksBlankValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
command.state = state;
|
||||
if (state) {
|
||||
if (command.tracksBlankValue) {
|
||||
dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
||||
} else {
|
||||
dom.addClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
||||
if (command.group) {
|
||||
dom.addClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
||||
}
|
||||
// commands with fixed value can not have a dialog.
|
||||
if (command.dialog && (typeof command.value === "undefined" || command.value === null)) {
|
||||
if (state && typeof state === "object") {
|
||||
state = getCommandState(composer, command);
|
||||
command.state = state;
|
||||
|
||||
// If dialog has dataset.showdialogonselection set as true,
|
||||
// Dialog displays on text state becoming active regardless of clobal showToolbarDialogsOnSelection options value
|
||||
displayDialogAttributeValue = command.dialog.container.dataset ? command.dialog.container.dataset.showdialogonselection : false;
|
||||
|
||||
if (composer.config.showToolbarDialogsOnSelection || displayDialogAttributeValue) {
|
||||
command.dialog.show(state);
|
||||
} else {
|
||||
command.dialog.update(state);
|
||||
}
|
||||
} else {
|
||||
command.dialog.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (command.tracksBlankValue) {
|
||||
dom.addClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
||||
} else {
|
||||
dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE);
|
||||
if (command.group) {
|
||||
dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE);
|
||||
}
|
||||
// commands with fixed value can not have a dialog.
|
||||
if (command.dialog && !command.value) {
|
||||
command.dialog.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i in actionMapping) {
|
||||
action = actionMapping[i];
|
||||
|
||||
if (action.name === "change_view") {
|
||||
action.state = this.editor.currentView === this.editor.textarea || this.editor.currentView === "source";
|
||||
if (action.state) {
|
||||
dom.addClass(action.link, CLASS_NAME_ACTION_ACTIVE);
|
||||
} else {
|
||||
dom.removeClass(action.link, CLASS_NAME_ACTION_ACTIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.container.style.display = "";
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.container.style.display = "none";
|
||||
}
|
||||
});
|
||||
|
||||
function getCommandState (composer, command) {
|
||||
var state = composer.commands.state(command.name, command.value);
|
||||
|
||||
// Grab first and only object/element in state array, otherwise convert state into boolean
|
||||
// to avoid showing a dialog for multiple selected elements which may have different attributes
|
||||
// eg. when two links with different href are selected, the state will be an array consisting of both link elements
|
||||
// but the dialog interface can only update one
|
||||
if (!command.dialog.multiselect && wysihtml.lang.object(state).isArray()) {
|
||||
state = state.length === 1 ? state[0] : true;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Extend defaults
|
||||
|
||||
// Id of the toolbar element, pass falsey value if you don't want any toolbar logic
|
||||
wysihtml.Editor.prototype.defaults.toolbar = undefined;
|
||||
|
||||
// Whether toolbar is displayed after init by script automatically.
|
||||
// Can be set to false if toolobar is set to display only on editable area focus
|
||||
wysihtml.Editor.prototype.defaults.showToolbarAfterInit = true;
|
||||
|
||||
// With default toolbar it shows dialogs in toolbar when their related text format state becomes active (click on link in text opens link dialogue)
|
||||
wysihtml.Editor.prototype.defaults.showToolbarDialogsOnSelection= true;
|
||||
|
||||
// Bind toolbar initiation on editor instance creation
|
||||
wysihtml.extendEditor(function(editor) {
|
||||
if (editor.config.toolbar) {
|
||||
editor.toolbar = new wysihtml.toolbar.Toolbar(editor, editor.config.toolbar, editor.config.showToolbarAfterInit);
|
||||
editor.on('destroy:composer', function() {
|
||||
if (editor && editor.toolbar) {
|
||||
editor.toolbar.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(wysihtml);
|
Loading…
Add table
Add a link
Reference in a new issue