Ext.define('saas.override.form.field.HtmlEditor', {
override: 'Ext.form.field.HtmlEditor',
fontFamilies: [{
name: '微软雅黑',
value: 'Microsoft YaHei'
}, {
name: '宋体',
value: 'SimSun'
}, {
name: '新宋体',
value: 'NSimSun'
}, {
name: '仿宋',
value: 'FangSong'
}, {
name: '楷体',
value: 'KaiTi'
}, {
name: '黑体',
value: 'SimHei'
}, 'Arial', 'Arial Black', 'Courier New', 'Tahoma', 'Times New Roman', 'Verdana'],
headers: [{
block: false,
name: '普通文本',
size: '14px',
color: 'rgb(57, 57, 57)'
}, {
block: true,
name: '标题',
size: '32px',
color: 'rgb(57, 57, 57)',
bold: true
}, {
block: true,
name: '副标题',
size: '18px',
color: 'rgb(89, 89, 89)',
bold: true
}, {
block: true,
name: '标题1',
size: '28px',
color: 'rgb(57, 57, 57)',
bold: true
}, {
block: true,
name: '标题2',
size: '20px',
color: 'rgb(57, 57, 57)',
bold: true
}, {
block: true,
name: '标题3',
size: '16px',
color: 'rgb(57, 57, 57)',
bold: true
}, {
block: true,
name: '标题4',
size: '14px',
color: 'rgb(57, 57, 57)',
bold: true
}],
blocks: [{
class: 'doc-block',
name: '带背景内容'
}, {
class: 'doc-tip doc-tip-info',
name: '提示内容'
}, {
class: 'doc-tip doc-tip-warn',
name: '警告内容'
}, {
class: 'doc-tip doc-tip-error',
name: '错误内容'
}, {
class: 'doc-quote',
name: '引用内容'
}, {
class: 'doc-line',
html: '
'
}],
enableHeaders: true,
enableFontSize: false,
enableUpload: true,
enableSourceEdit: false,
enableBlocks: true,
publishes: {
textValue: 1
},
initComponent: function () {
var me = this;
me.callParent();
// 用于获取innerText
me.on('change', function () {
me.publishState('textValue', me.getTextValue());
});
},
initEditor: function () {
var me = this;
me.callParent();
/**
* 扩展监听事件
*/
var doc = me.getDoc(), docEl = Ext.get(doc);
if (docEl) {
docEl.on({
mousedown: '_onMouseDown',
keyup: '_onKeyup',
scope: me,
delegated: false
});
}
},
_onMouseDown: function (e) {
var target = e.parentEvent.target;
if (target.nodeName == 'IMG') {
e.preventDefault();
this.resizeImage(target);
}
},
_onKeyup: function (e) {
if (e.keyCode == e.ENTER && e.ctrlKey) {
e.preventDefault();
// 换行
// this.insertAtCursor(' ');
this.execCmd('insertHTML', '
');
}
},
getDocMarkup: function () {
// 添加额外样式、脚本
var me = this,
h = me.iframeEl.getHeight() - me.iframePad * 2,
extraCss = Ext.getResourcePath('css/htmleditor.css');
return Ext.String.format('' + ' ', me.iframePad, h, me.defaultFont);
},
initDefaultFont: function () {
var me = this,
selIdx = 0,
fonts, font, select, option, i, len, fontName, fontValue;
if (!me.defaultFont) {
fonts = Ext.Array.clone(me.fontFamilies);
select = me.down('#fontSelect').selectEl.dom;
for (i = 0, len = fonts.length; i < len; ++i) {
font = fonts[i];
if (Ext.isString(font)) {
fontName = font;
fontValue = font.toLowerCase();
} else {
fontName = font.name;
fontValue = font.value.toLowerCase();
}
option = new Option(fontName, fontValue);
if (i == selIdx) {
me.defaultFont = fontName;
}
option.style.fontFamily = fontValue;
if (Ext.isIE) {
select.add(option);
} else {
select.options.add(option);
}
}
// Old IE versions have a problem if we set the selected property
// in the loop, so set it after.
select.options[selIdx].selected = true;
}
},
getToolbarCfg: function () {
var me = this, cfg = me.callParent();
// 选择标题样式
if (me.enableHeaders) {
cfg.items.splice(0, 0, '-');
cfg.items.splice(0, 0, me.getHeadersBtn());
}
// 上传图片
if (me.enableUpload) {
cfg.items.push('-', Ext.merge({
xtype: 'fileuploadfield',
name: 'file',
allowBlank: false,
buttonOnly: true,
hideLabel: true,
itemId: 'insertImage',
buttonText: '',
ui: 'plain',
margin: 0,
buttonConfig: {
ui: 'plain-toolbar',
cls: 'x-btn-icon',
iconCls: 'x-fa fa-upload',
accept: 'image/*'
},
scope: me,
listeners: {
change: function (field) {
if (!field.getValue()) {
return;
}
var fileEl = field.fileInputEl.dom;
me.saveImage(fileEl.files[0]);
field.reset();
}
},
clickEvent: 'mousedown',
tooltip: '插入图片',
tabIndex: -1
}, me.buttonDefaults));
cfg.listeners.click = function (e) {
if (!e.getTarget('.x-form-file-input')) {
e.preventDefault();
}
}
}
// 自定义语句块
if (me.enableBlocks) {
cfg.items.push('-', Ext.merge(me.getBlocks(), me.buttonDefaults));
}
return cfg;
},
/**
* 保存图片方式一 - 服务端保存
* @param {*} file
*/
saveImage: function (file) {
var me = this, data = new FormData();
data.append('file', file);
Ext.Ajax.request({
url: '/api/file/upload',
cors: true,
useDefaultXhrHeader: false,
method: 'post',
headers: {
'Content-Type': null
},
rawData: data,
success: function (response) {
var res = Ext.decode(response.responseText);
if (res.success) {
if (!me.activated) {
me.onFirstFocus();
}
me.insertAtCursor(' ');
me.syncValue();
} else {
saas.util.BaseUtil.showErrorToast('上传失败: ' + res.message);
}
},
failure: function () {
saas.util.BaseUtil.showErrorToast('上传失败');
}
});
},
/**
* 保存图片方式二 - base64格式
* 这样保证文档删除时附件一并删除
* 截屏直接粘贴的图片均为base64格式
* @param {*} file
*/
saveBase64Image: function (file) {
var me = this, reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
if (!me.activated) {
me.onFirstFocus();
}
me.insertAtCursor(' ');
me.syncValue();
}
},
/**
* 选择标题
*/
getHeadersBtn: function () {
var me = this,
items = me.headers.map(h => {
var style = `color:${h.color};font-size:${h.size};font-weight:`
+ (h.bold ? 'bold' : 'normal'),
text = `${h.name} `,
value = Ext.clone(h);
return {
text: text,
value,
handler: function (item) {
var val = item.value;
me.execHeaderStyle(val);
item.ownerCt.ownerCmp.setText(val.name);
}
}
});
return {
itemId: 'headers',
width: 90,
padding: '7 0',
text: items[0].text,
tabIndex: -1,
menu: Ext.widget('menu', {
plain: true,
items
})
};
},
/**
* 选择语句块
*/
getBlocks: function () {
var me = this,
items = me.blocks.map(h => {
var text = h.html || ``,
value = Ext.clone(h);
return {
text: text,
value,
handler: function (item) {
var val = item.value;
me.execBlockStyle(val);
}
}
});
return {
itemId: 'blocks',
iconCls: 'x-fa fa-ellipsis-v',
tooltip: '插入块',
tabIndex: -1,
arrowVisible: false,
menuAlign: 'tr-br?',
menu: Ext.widget('menu', {
plain: true,
cls: 'doc-blocks__ex',
width: 180,
items
})
};
},
/**
* 解决fontSize只支持 1 - 7 的问题
*/
execHeaderStyle: function (header) {
var me = this,
win = me.getWin(),
doc = me.getDoc(),
text = win.getSelection() || me.defaultValue;
if (!me.destroyed) {
var span = doc.createElement('span');
span.innerHTML = text;
span.style.fontSize = header.size;
span.style.color = header.color;
span.style.fontWeight = header.bold ? 'bold' : 'normal';
win.focus();
me.execCmd('insertHTML', '' + span.outerHTML + '
');
}
},
/**
* 特殊样式的语句块
*/
execBlockStyle: function (block) {
var me = this,
win = me.getWin(),
text = win.getSelection() || ' ',
html = block.html;
if (!me.destroyed) {
win.focus();
if (!html) {
html = ``;
}
me.execCmd('insertHTML', ` ${html} `);
}
},
setTextValue: function () {
},
getTextValue: function () {
return this.getEditorBody().innerText;
},
/**
* 调整图片大小
* @param {*} target
*/
resizeImage: function (target) {
var me = this,
el = Ext.fly(target),
padding = 73,
width = el.getWidth(),
maxWidth = Math.min(window.innerWidth, 880),
widthPerc = width / maxWidth,
height = el.getHeight(),
maxHeight = window.innerHeight - padding,
heightPerc = height / maxHeight,
perc = Math.max(widthPerc, heightPerc);
if (perc > 1) {
width = width / perc;
height = height / perc + padding;
} else {
height += padding;
}
var win = Ext.create('Ext.window.Window', {
modal: true,
autoShow: true,
ui: 'simple',
title: '拖动改变图片大小',
maxWidth: maxWidth,
width,
height,
tabIndex: -1,
layout: 'fit',
items: {
itemId: 'image',
xtype: 'image',
src: target.src
},
buttons: [{
text: '确定',
ui: 'primary',
handler: function () {
var image = win.child('#image');
if (!target.getAttribute('data-original-width')) {
target.setAttribute('data-original-width', width);
target.setAttribute('data-original-height', height);
}
target.setAttribute('width', image.getWidth());
target.setAttribute('height', image.getHeight());
me.syncValue();
win.close();
}
}, {
text: '取消',
ui: 'simple',
handler: function () {
win.close();
}
}]
});
win.focus();
}
});