fineui是帆软报表和BI产品线所使用的前端框架。
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.
 
 
 

324 lines
11 KiB

/**
* 富文本编辑器
*
* 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;
$(document.body).mousedown(BI.bind(this.selectCheck, this));
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 {
var newInstance = new nicEditorIFrameInstance(conf);
}
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 {
if (t.className && t.className.indexOf(prefix) != -1) {
return;
// return false;
}
} while (t = t.parentNode);
this.fireEvent('blur', this.selectedInstance, t);
this.lastSelectedInstance = this.selectedInstance;
this.selectedInstance = null;
// return false;
},
setValue: function (v) {
this.instance.setContent(v);
},
getValue: function () {
return this.instance.getContent();
}
});
BI.NicEditor.EVENT_SELECTED = "selected";
BI.NicEditor.EVENT_BLUR = "blur";
BI.NicEditor.EVENT_KEY = "key";
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() == "") {
this.setContent("<br />");
}
this.instanceDoc = document.defaultView;
this.elm.element.on('mousedown', BI.bind(this.selected, this));
this.elm.element.on('keypress', BI.bind(this.keyDown, this));
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));
this.ne.fireEvent('add', this);
},
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();
},
restoreRng: function () {
if (this.savedRange) {
this.selRng(this.savedRange, this.savedSel);
}
},
keyDown: function (e, t) {
if (e.ctrlKey) {
this.ne.fireEvent('key', this, e);
}
},
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) {
this.ne.fireEvent('blur', selInstance, t);
}
this.ne.selectedInstance = this;
this.ne.fireEvent('focus', selInstance, t);
}
this.ne.fireEvent('selected', selInstance, t);
this.isFocused = true;
this.elm.element.addClass(prefix + 'selected');
}
// return false;
},
blur: function () {
this.isFocused = false;
this.elm.element.removeClass(prefix + 'selected');
},
saveContent: function () {
this.ne.fireEvent('save', this);
this.e.element.value(this.getContent());
},
getElm: function () {
return this.elm;
},
getContent: function () {
this.content = this.getElm().element.html();
this.ne.fireEvent('get', this);
return this.content;
},
setContent: function (e) {
this.content = e;
this.ne.fireEvent('set', this);
this.elm.element.html(this.content);
},
nicCommand: function (cmd, args) {
document.execCommand(cmd, false, args);
}
});
var nicEditorIFrameInstance = BI.inherit(nicEditorInstance, {
savedStyles: [],
start: function () {
var o = this.options;
var c = this.elm.element.html().replace(/^\s+|\s+$/g, '');
this.elm.element.html("");
(!c) ? c = "<br />" : c;
this.initialContent = c;
this.elmFrame = $('iframe').attr({
'src': 'javascript:;',
'frameBorder': 0,
'allowTransparency': 'true',
'scrolling': 'no'
}).css({height: '100px', width: '100%'}).addClass(prefix + 'frame').appendTo(this.elm.element);
this.elmFrame.css({width: (o.width - 4) + 'px'});
var styleList = ['font-size', 'font-family', 'font-weight', 'color'];
for (var item in styleList) {
this.savedStyles[BI.camelize(item)] = this.elm.element.css(item);
}
setTimeout(BI.bind(this.initFrame, this), 50);
},
disable: function () {
this.elm.element.html(this.getContent());
},
initFrame: function () {
var fd = $(this.elmFrame.contentWindow.document)[0];
fd.designMode = "on";
fd.open();
var css = this.ne.options.externalCSS;
fd.write('<html><head>' + ((css) ? '<link href="' + css + '" rel="stylesheet" type="text/css" />' : '') + '</head><body id="nicEditContent" style="margin: 0 !important; background-color: transparent !important;">' + this.initialContent + '</body></html>');
fd.close();
this.frameDoc = $(fd);
this.frameWin = $(this.elmFrame[0].contentWindow);
this.frameContent = $(this.frameWin[0].document.body).css(this.savedStyles);
this.instanceDoc = this.frameWin[0].document.defaultView;
this.heightUpdate();
this.frameDoc.on('mousedown', BI.bind(this.selected, this));
this.frameDoc.on('keyup', BI.bind(this.heightUpdate, this));
this.frameDoc.on('keydown', BI.bind(this.keyDown, this));
this.frameDoc.on('keyup', BI.bind(this.selected, this));
this.ne.fireEvent('add', this);
},
getElm: function () {
return this.frameContent;
},
setContent: function (c) {
this.content = c;
this.ne.fireEvent('set', this);
this.frameContent.html(this.content);
this.heightUpdate();
},
getSel: function () {
return (this.frameWin[0]) ? this.frameWin[0].getSelection() : this.frameDoc[0].selection;
},
heightUpdate: function () {
this.elmFrame[0].style.height = Math.max(this.frameContent[0].offsetHeight, this.options.height - 8) + 'px';
},
nicCommand: function (cmd, args) {
this.frameDoc.execCommand(cmd, false, args);
setTimeout(BI.bind(this.heightUpdate, this), 100);
}
})
}());