forked from fanruan/fineui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
8.7 KiB
281 lines
8.7 KiB
8 years ago
|
/**
|
||
|
* 富文本编辑器
|
||
|
*
|
||
|
* Created by GUY on 2017/9/15.
|
||
|
* @class BI.NicEditor
|
||
|
* @extends BI.Widget
|
||
|
*/
|
||
|
!(function () {
|
||
|
BI.NicEditor = BI.inherit(BI.Widget, {
|
||
|
_defaultConfig: function () {
|
||
|
return BI.extend(BI.NicEditor.superclass._defaultConfig.apply(this, arguments), {
|
||
|
baseCls: "bi-nic-editor"
|
||
|
});
|
||
|
},
|
||
|
_init: function () {
|
||
|
BI.NicEditor.superclass._init.apply(this, arguments);
|
||
|
var o = this.options;
|
||
8 years ago
|
$(document).bind("mousedown." + this.getName(), BI.bind(this.selectCheck, this));
|
||
8 years ago
|
BI.createWidget({
|
||
|
type: "bi.vertical",
|
||
|
element: this,
|
||
|
items: [{
|
||
|
type: "bi.layout",
|
||
|
height: 1
|
||
|
}, this.instance = this.addInstance()]
|
||
|
})
|
||
|
},
|
||
|
|
||
|
addInstance: function () {
|
||
|
var o = this.options;
|
||
|
var conf = {
|
||
|
ne: this,
|
||
|
height: o.height - 1,
|
||
|
maxHeight: o.maxHeight ? o.maxHeight : null
|
||
|
};
|
||
|
if (this.element[0].contentEditable || !!window.opera) {
|
||
|
var newInstance = new nicEditorInstance(conf);
|
||
|
} else {
|
||
8 years ago
|
console.error("不支持此浏览器");
|
||
8 years ago
|
}
|
||
|
return newInstance;
|
||
|
},
|
||
|
|
||
|
nicCommand: function (cmd, args) {
|
||
|
if (this.selectedInstance) {
|
||
|
this.selectedInstance.nicCommand(cmd, args);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
selectCheck: function (e) {
|
||
|
var t = e.target;
|
||
|
var found = false;
|
||
|
do {
|
||
8 years ago
|
if (t.nodeName !== "svg" && t.className && t.className.indexOf(prefix) != -1) {
|
||
8 years ago
|
return;
|
||
|
// return false;
|
||
|
}
|
||
|
} while (t = t.parentNode);
|
||
8 years ago
|
this.fireEvent('blur', t);
|
||
8 years ago
|
this.lastSelectedInstance = this.selectedInstance;
|
||
|
this.selectedInstance = null;
|
||
|
// return false;
|
||
|
},
|
||
|
|
||
|
setValue: function (v) {
|
||
|
this.instance.setContent(v);
|
||
|
},
|
||
|
|
||
|
getValue: function () {
|
||
|
return this.instance.getContent();
|
||
8 years ago
|
},
|
||
|
|
||
|
destroyed: function () {
|
||
|
$(document).unbind("mousedown." + this.getName());
|
||
8 years ago
|
}
|
||
|
});
|
||
|
BI.NicEditor.EVENT_SELECTED = "selected";
|
||
|
BI.NicEditor.EVENT_BLUR = "blur";
|
||
8 years ago
|
BI.NicEditor.EVENT_KEYDOWN = "keydown";
|
||
8 years ago
|
BI.shortcut('bi.nic_editor', BI.NicEditor);
|
||
|
|
||
|
var prefix = "niceditor-";
|
||
|
|
||
|
var nicEditorInstance = BI.inherit(BI.Layout, {
|
||
|
isSelected: false,
|
||
|
_init: function () {
|
||
|
nicEditorInstance.superclass._init.apply(this, arguments);
|
||
|
var o = this.options;
|
||
|
this.ne = this.options.ne;
|
||
|
this.elm = BI.createWidget({
|
||
|
type: "bi.layout",
|
||
|
width: o.width - 8,
|
||
|
scrollable: false
|
||
|
});
|
||
|
this.elm.element.css({
|
||
|
margin: "4px",
|
||
|
minHeight: (o.height - 8) + "px",
|
||
|
outline: "none"
|
||
|
}).html(o.value);
|
||
|
|
||
|
this.element.css("maxHeight", (o.maxHeight) ? o.maxHeight + 'px' : null);
|
||
|
|
||
|
this.e = BI.createWidget({
|
||
|
type: "bi.layout",
|
||
|
invisible: true,
|
||
|
tagName: "textarea"
|
||
|
});
|
||
|
BI.createWidget({
|
||
|
type: "bi.default",
|
||
|
element: this,
|
||
|
scrolly: true,
|
||
|
items: [this.elm, this.e]
|
||
|
});
|
||
|
|
||
|
this.ne.on("blur", BI.bind(this.blur, this));
|
||
|
|
||
|
this.start();
|
||
|
this.blur();
|
||
|
},
|
||
|
|
||
|
start: function () {
|
||
|
this.elm.element.attr("contentEditable", true);
|
||
|
if (this.getContent() == "") {
|
||
8 years ago
|
// this.setContent("<br />");
|
||
8 years ago
|
}
|
||
|
this.instanceDoc = document.defaultView;
|
||
|
this.elm.element.on('mousedown', BI.bind(this.selected, this));
|
||
8 years ago
|
this.elm.element.on('keydown', BI.bind(this.keyDown, this));
|
||
8 years ago
|
this.elm.element.on('focus', BI.bind(this.selected, this));
|
||
|
this.elm.element.on('blur', BI.bind(this.blur, this));
|
||
|
this.elm.element.on('keyup', BI.bind(this.selected, this));
|
||
8 years ago
|
this.ne.fireEvent('add');
|
||
8 years ago
|
},
|
||
|
|
||
|
disable: function () {
|
||
|
this.elm.element.attr("contentEditable", false);
|
||
|
},
|
||
|
|
||
|
getSel: function () {
|
||
|
return (window.getSelection) ? window.getSelection() : document.selection;
|
||
|
},
|
||
|
|
||
|
getRng: function () {
|
||
|
var s = this.getSel();
|
||
|
if (!s || s.rangeCount === 0) {
|
||
|
return;
|
||
|
}
|
||
|
return (s.rangeCount > 0) ? s.getRangeAt(0) : s.createRange();
|
||
|
},
|
||
|
|
||
|
selRng: function (rng, s) {
|
||
|
if (window.getSelection) {
|
||
|
s.removeAllRanges();
|
||
|
s.addRange(rng);
|
||
|
} else {
|
||
|
rng.select();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
selElm: function () {
|
||
|
var r = this.getRng();
|
||
|
if (!r) {
|
||
|
return;
|
||
|
}
|
||
|
if (r.startContainer) {
|
||
|
var contain = r.startContainer;
|
||
|
if (r.cloneContents().childNodes.length == 1) {
|
||
|
for (var i = 0; i < contain.childNodes.length; i++) {
|
||
|
var rng = contain.childNodes[i].ownerDocument.createRange();
|
||
|
rng.selectNode(contain.childNodes[i]);
|
||
|
if (r.compareBoundaryPoints(Range.START_TO_START, rng) != 1 &&
|
||
|
r.compareBoundaryPoints(Range.END_TO_END, rng) != -1) {
|
||
|
return contain.childNodes[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return contain;
|
||
|
} else {
|
||
|
return (this.getSel().type == "Control") ? r.item(0) : r.parentElement();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
saveRng: function () {
|
||
|
this.savedRange = this.getRng();
|
||
|
this.savedSel = this.getSel();
|
||
|
},
|
||
|
|
||
8 years ago
|
setFocus: function (el) {
|
||
|
try {
|
||
|
el.focus();
|
||
|
} catch (e) {
|
||
|
|
||
|
}
|
||
|
if (!window.getSelection) {
|
||
|
var rng;
|
||
|
try {
|
||
|
el.focus();
|
||
|
} catch (e) {
|
||
|
|
||
|
}
|
||
|
rng = document.selection.createRange();
|
||
|
rng.moveStart('character', -el.innerText.length);
|
||
|
var text = rng.text;
|
||
|
for (var i = 0; i < el.innerText.length; i++) {
|
||
|
if (el.innerText.substring(0, i + 1) == text.substring(text.length - i - 1, text.length)) {
|
||
|
result = i + 1;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
var range = document.createRange();
|
||
|
range.selectNodeContents(el);
|
||
|
range.collapse(false);
|
||
|
var sel = window.getSelection();
|
||
|
sel.removeAllRanges();
|
||
|
sel.addRange(range);
|
||
|
}
|
||
|
},
|
||
|
|
||
8 years ago
|
restoreRng: function () {
|
||
|
if (this.savedRange) {
|
||
|
this.selRng(this.savedRange, this.savedSel);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
keyDown: function (e, t) {
|
||
8 years ago
|
this.ne.fireEvent('keydown', e);
|
||
8 years ago
|
},
|
||
|
|
||
|
selected: function (e) {
|
||
|
var t = e.target;
|
||
|
if (!t && !(t = this.selElm())) {
|
||
|
t = this.selElm();
|
||
|
}
|
||
|
if (!e.ctrlKey) {
|
||
|
var selInstance = this.ne.selectedInstance;
|
||
|
if (selInstance != this) {
|
||
|
if (selInstance) {
|
||
8 years ago
|
this.ne.fireEvent('blur', e);
|
||
8 years ago
|
}
|
||
|
this.ne.selectedInstance = this;
|
||
8 years ago
|
this.ne.fireEvent('focus', e);
|
||
8 years ago
|
}
|
||
8 years ago
|
this.ne.fireEvent('selected', e);
|
||
8 years ago
|
this.isFocused = true;
|
||
|
this.elm.element.addClass(prefix + 'selected');
|
||
|
}
|
||
|
// return false;
|
||
|
},
|
||
|
|
||
|
blur: function () {
|
||
|
this.isFocused = false;
|
||
|
this.elm.element.removeClass(prefix + 'selected');
|
||
|
},
|
||
|
|
||
|
saveContent: function () {
|
||
8 years ago
|
this.ne.fireEvent('save');
|
||
8 years ago
|
this.e.element.value(this.getContent());
|
||
|
},
|
||
|
|
||
|
getElm: function () {
|
||
|
return this.elm;
|
||
|
},
|
||
|
|
||
|
getContent: function () {
|
||
|
this.content = this.getElm().element.html();
|
||
8 years ago
|
this.ne.fireEvent('get');
|
||
8 years ago
|
return this.content;
|
||
|
},
|
||
|
|
||
|
setContent: function (e) {
|
||
|
this.content = e;
|
||
8 years ago
|
this.ne.fireEvent('set');
|
||
8 years ago
|
this.elm.element.html(this.content);
|
||
|
},
|
||
|
|
||
|
nicCommand: function (cmd, args) {
|
||
|
document.execCommand(cmd, false, args);
|
||
|
}
|
||
|
});
|
||
|
}());
|