Browse Source

Pull request #3396: KERNEL-14076 refact: es6 脚本识别循环依赖。完成 base 处理。

Merge in VISUAL/fineui from ~TREECAT/fineui:es6 to es6

* commit 'ef32e98be6b3b78cb7581568bd78e88f29dace30':
  KERNEL-14076 refact: es6 脚本识别循环依赖。完成 base 处理。
es6
treecat-罗群 2 years ago
parent
commit
db4fe44a0e
  1. 61
      es6.js
  2. 12
      src/base/0.base.js
  3. 91
      src/base/1.pane.js
  4. 119
      src/base/collection/collection.js
  5. 249
      src/base/combination/bubble.js
  6. 475
      src/base/combination/combo.js
  7. 166
      src/base/combination/expander.js
  8. 85
      src/base/combination/group.button.js
  9. 55
      src/base/combination/group.combo.js
  10. 67
      src/base/combination/group.virtual.js
  11. 2
      src/base/combination/index.js
  12. 184
      src/base/combination/loader.js
  13. 48
      src/base/combination/navigation.js
  14. 159
      src/base/combination/searcher.js
  15. 163
      src/base/combination/switcher.js
  16. 55
      src/base/combination/tab.js
  17. 9
      src/base/combination/tree.button.js
  18. 57
      src/base/context.js
  19. 48
      src/base/el.js
  20. 175
      src/base/foundation/message.js
  21. 164
      src/base/grid/grid.js
  22. 9
      src/base/index.js
  23. 457
      src/base/layer/layer.drawer.js
  24. 552
      src/base/layer/layer.popover.js
  25. 875
      src/base/layer/layer.popup.js
  26. 259
      src/base/layer/layer.searcher.js
  27. 221
      src/base/list/listview.js
  28. 331
      src/base/list/virtualgrouplist.js
  29. 71
      src/base/list/virtuallist.js
  30. 149
      src/base/pager/pager.js
  31. 39
      src/base/single/0.single.js
  32. 64
      src/base/single/1.text.js
  33. 52
      src/base/single/a/a.js
  34. 19
      src/base/single/bar/bar.loading.js
  35. 333
      src/base/single/button/button.basic.js
  36. 2
      src/base/single/button/button.node.js
  37. 9
      src/base/single/button/buttons/button.icon.js
  38. 10
      src/base/single/button/buttons/button.image.js
  39. 41
      src/base/single/button/buttons/button.js
  40. 5
      src/base/single/button/buttons/button.text.js
  41. 34
      src/base/single/button/index.js
  42. 74
      src/base/single/button/listitem/blankiconicontextitem.js
  43. 75
      src/base/single/button/listitem/blankicontexticonitem.js
  44. 61
      src/base/single/button/listitem/blankicontextitem.js
  45. 67
      src/base/single/button/listitem/icontexticonitem.js
  46. 54
      src/base/single/button/listitem/icontextitem.js
  47. 56
      src/base/single/button/listitem/texticonitem.js
  48. 5
      src/base/single/button/listitem/textitem.js
  49. 67
      src/base/single/button/node/icontexticonnode.js
  50. 55
      src/base/single/button/node/icontextnode.js
  51. 55
      src/base/single/button/node/texticonnode.js
  52. 10
      src/base/single/button/node/textnode.js
  53. 67
      src/base/single/editor/editor.js
  54. 35
      src/base/single/editor/editor.multifile.js
  55. 109
      src/base/single/editor/editor.textarea.js
  56. 6
      src/base/single/editor/index.js
  57. 29
      src/base/single/html/html.js
  58. 7
      src/base/single/icon/icon.js
  59. 23
      src/base/single/iframe/iframe.js
  60. 20
      src/base/single/img/img.js
  61. 9
      src/base/single/input/checkbox/checkbox.image.js
  62. 29
      src/base/single/input/checkbox/checkbox.js
  63. 369
      src/base/single/input/file.js
  64. 12
      src/base/single/input/index.js
  65. 71
      src/base/single/input/input.js
  66. 9
      src/base/single/input/radio/radio.image.js
  67. 31
      src/base/single/input/radio/radio.js
  68. 16
      src/base/single/instruction/instruction.js
  69. 179
      src/base/single/label/abstract.label.js
  70. 10
      src/base/single/label/html.label.js
  71. 14
      src/base/single/label/icon.label.js
  72. 8
      src/base/single/label/index.js
  73. 7
      src/base/single/label/label.js
  74. 10
      src/base/single/link/link.js
  75. 19
      src/base/single/text.pure.js
  76. 8
      src/base/single/tip/0.tip.js
  77. 221
      src/base/single/tip/tip.toast.js
  78. 146
      src/base/single/tip/tip.tooltip.js
  79. 13
      src/base/single/trigger/trigger.js
  80. 72
      src/base/tree/customtree.js
  81. 3
      src/case/combo/bubblecombo/popup.bubble.js

61
es6.js

@ -8,6 +8,9 @@ const _ = require("lodash");
// const XTYPE_ONLY = false; // const XTYPE_ONLY = false;
// const THIS_REPLACE = false; // const THIS_REPLACE = false;
const ConflictImport = [];
const CircularDependency = [];
function objHaveFunction(obj) { function objHaveFunction(obj) {
return Object.keys(obj).some(key => { return Object.keys(obj).some(key => {
const value = obj[key]; const value = obj[key];
@ -44,6 +47,7 @@ async function saveAndFixCode(path, code) {
const prettierCode = prettier.format(_code, { const prettierCode = prettier.format(_code, {
tabWidth: 4, tabWidth: 4,
parser: 'babel', parser: 'babel',
printWidth: 120,
}); });
fs.writeFileSync(path, prettierCode); fs.writeFileSync(path, prettierCode);
@ -138,7 +142,13 @@ async function handleFile(srcName) {
const result = /BI\.(.*?)\s=\sBI\.inherit\(/.exec(sourceCode); const result = /BI\.(.*?)\s=\sBI\.inherit\(/.exec(sourceCode);
if (!result) { if (!result) {
console.log(`已经es6过,替换 xtype => ${srcName}`); // console.log(`已经es6过,替换 xtype => ${srcName}`);
if (!/export class/.test(sourceCode)) {
console.log("忽略文件", srcName);
return;
}
// 处理 xtype // 处理 xtype
const noXtypeCode = sourceCode.replace(/type:\s?"bi\.(.*?)"/g, v => { const noXtypeCode = sourceCode.replace(/type:\s?"bi\.(.*?)"/g, v => {
const matchedSentence = v.replace(/type:\s?/, ""); const matchedSentence = v.replace(/type:\s?/, "");
@ -181,12 +191,37 @@ async function handleFile(srcName) {
}); });
const tmpG = {}; const tmpG = {};
_.forEach(G, (depts, module)=> { _.forEach(G, (depts, module) => {
const flag = _.some(crossPackages, crosspackage => module.indexOf(crosspackage) >= 0 && !module.startsWith("@")) const flag = _.some(crossPackages, crosspackage => module.indexOf(crosspackage) >= 0 && !module.startsWith("@"));
if (!flag) { if (!flag) {
tmpG[module] = depts; tmpG[module] = depts;
} }
}); });
// 较验手工 import 错误
const map = {};
let conflict = false;
let circle = false;
_.forEach(tmpG, (imports, fromStr) => {
if (srcName.indexOf("base") >= 0) {
if (fromStr === "@/case" || fromStr === "@/base") {
circle = true;
}
}
_.forEach(imports, (bools, _import) => {
if (map[_import] && map[_import] !== fromStr) {
conflict = true;
}
map[_import] = fromStr;
});
});
conflict && ConflictImport.push(srcName);
circle && CircularDependency.push(srcName);
G = tmpG; G = tmpG;
const noImportCode = noXtypeCode.replace(/import {([\s\S]*?)} from "(.*?)";/g, ""); const noImportCode = noXtypeCode.replace(/import {([\s\S]*?)} from "(.*?)";/g, "");
@ -314,7 +349,7 @@ async function handleFile(srcName) {
// 换 super._defaultConfig // 换 super._defaultConfig
f = f.replace( f = f.replace(
/super\._defaultConfig\.apply\(this,\sarguments\)/g, /super\._defaultConfig\.apply\(this,\sarguments\)/g,
"super._defaultConfig(...arguments)" "super._defaultConfig(...arguments)",
); );
// 换 super.xxx.apply // 换 super.xxx.apply
f = f.replace(/super\.(.*?)\.apply\(this,\sarguments\)/g, a => { f = f.replace(/super\.(.*?)\.apply\(this,\sarguments\)/g, a => {
@ -427,19 +462,27 @@ async function traverse(srcName) {
const srcName = process.argv[2]; const srcName = process.argv[2];
initDepts().then(() => { initDepts().then(async () => {
const content = fs.readFileSync("src/core/2.base.js").toString(); const content = fs.readFileSync("src/core/2.base.js").toString();
let result = content.match(/export function (.*?)\(/g); let result = content.match(/export function (.*?)\(/g);
target.push( target.push(
...result.map(el => ...result.map(el =>
el.replace("export function ", "").replace("(", "") el.replace("export function ", "").replace("(", ""),
) ),
); );
result = content.match(/export const (.*?) =/g); result = content.match(/export const (.*?) =/g);
target.push( target.push(
...result.map(el => el.replace("export const ", "").replace(" =", "")) ...result.map(el => el.replace("export const ", "").replace(" =", "")),
); );
traverse(srcName); await traverse(srcName);
// 对数据处理
ConflictImport.forEach(el => {
console.log(`导入冲突 ${el}`);
});
CircularDependency.forEach(el => {
console.log(`出现循环依赖 ${el}`);
});
}); });

12
src/base/0.base.js

@ -20,14 +20,4 @@ const Drawers = new DrawerController();
const Broadcasts = new BroadcastController(); const Broadcasts = new BroadcastController();
const StyleLoaders = new StyleLoaderManager(); const StyleLoaders = new StyleLoaderManager();
export { export { Resizers, Layers, Maskers, Bubbles, Tooltips, Popovers, Drawers, Broadcasts, StyleLoaders };
Resizers,
Layers,
Maskers,
Bubbles,
Tooltips,
Popovers,
Drawers,
Broadcasts,
StyleLoaders
};

91
src/base/1.pane.js

@ -1,3 +1,19 @@
import { Label, Text } from "./single";
import {
CenterAdaptLayout,
HorizontalAdaptLayout,
VerticalLayout,
Widget,
shortcut,
isNotEmptyString,
extend,
isNull,
isEmpty,
createWidget,
Providers
} from "@/core";
import { Layers } from "@/base";
/** /**
* 当没有元素时有提示信息的view * 当没有元素时有提示信息的view
* *
@ -6,8 +22,6 @@
* @extends BI.Widget * @extends BI.Widget
* @abstract * @abstract
*/ */
import { Widget, shortcut, isNotEmptyString, extend, isNull, isEmpty, createWidget, Providers } from "../core";
import { Layers } from "./0.base";
@shortcut() @shortcut()
export class Pane extends Widget { export class Pane extends Widget {
@ -31,32 +45,36 @@ export class Pane extends Widget {
createWidget({ createWidget({
type: "bi.absolute_center_adapt", type: "bi.absolute_center_adapt",
element: this, element: this,
items: [{ items: [
type: "bi.label", {
ref: _ref => { type: Label.xtype,
this._tipText = _ref; ref: _ref => {
}, this._tipText = _ref;
cls: "bi-tips", },
text: this.options.tipText, cls: "bi-tips",
height: 25, text: this.options.tipText,
}], height: 25,
}
],
}); });
} }
} }
loading() { loading() {
const o = this.options; const o = this.options;
const loadingAnimation = createWidget(Providers.getProvider("bi.provider.system").getLoading({ const loadingAnimation = createWidget(
loadingSize: o.loadingSize, Providers.getProvider("bi.provider.system").getLoading({
context: this, loadingSize: o.loadingSize,
})); context: this,
})
);
// pane在同步方式下由items决定tipText的显示与否 // pane在同步方式下由items决定tipText的显示与否
// loading的异步情况下由loaded后对面板的populate的时机决定 // loading的异步情况下由loaded后对面板的populate的时机决定
this.setTipVisible(false); this.setTipVisible(false);
if (o.overlap === true) { if (o.overlap === true) {
if (!Layers.has(`${this.getName()}-loading`)) { if (!Layers.has(`${this.getName()}-loading`)) {
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
cls: "loading-container", cls: "loading-container",
items: this._getLoadingTipItems(loadingAnimation), items: this._getLoadingTipItems(loadingAnimation),
element: Layers.make(`${this.getName()}-loading`, this), element: Layers.make(`${this.getName()}-loading`, this),
@ -66,7 +84,7 @@ export class Pane extends Widget {
} else if (isNull(this._loading)) { } else if (isNull(this._loading)) {
loadingAnimation.element.css("zIndex", 1); loadingAnimation.element.css("zIndex", 1);
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
element: this, element: this,
cls: "loading-container", cls: "loading-container",
items: this._getLoadingTipItems(loadingAnimation), items: this._getLoadingTipItems(loadingAnimation),
@ -82,23 +100,28 @@ export class Pane extends Widget {
_getLoadingTipItems(loadingTip) { _getLoadingTipItems(loadingTip) {
const o = this.options; const o = this.options;
const loadingTipItems = [{ const loadingTipItems = [
type: "bi.horizontal_adapt", {
items: [loadingTip], type: HorizontalAdaptLayout.xtype,
}]; items: [loadingTip],
isNotEmptyString(o.loadingText) && loadingTipItems.push({ }
type: "bi.text", ];
text: o.loadingText, isNotEmptyString(o.loadingText) &&
tgap: this._getSize(10), loadingTipItems.push({
}); type: Text.xtype,
text: o.loadingText,
tgap: this._getSize(10),
});
return [{ return [
type: "bi.vertical", {
ref: _ref => { type: VerticalLayout.xtype,
this._loading = _ref; ref: _ref => {
}, this._loading = _ref;
items: loadingTipItems, },
}]; items: loadingTipItems,
}
];
} }
loaded() { loaded() {

119
src/base/collection/collection.js

@ -1,3 +1,25 @@
import {
VerticalLayout,
AbsoluteLayout,
Widget,
shortcut,
extend,
emptyFn,
debounce,
_lazyCreateWidget,
isFunction,
SectionManager,
isNull,
each,
clamp,
toArray,
invert,
min,
max,
nextTick
} from "@/core";
import { Label } from "../single";
/** /**
* CollectionView * CollectionView
* *
@ -5,7 +27,7 @@
* @class BI.CollectionView * @class BI.CollectionView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, emptyFn, debounce, _lazyCreateWidget, isFunction, SectionManager, isNull, each, clamp, toArray, invert, min, max, nextTick } from "../../core";
@shortcut() @shortcut()
export class CollectionView extends Widget { export class CollectionView extends Widget {
_defaultConfig() { _defaultConfig() {
@ -19,7 +41,7 @@ export class CollectionView extends Widget {
overflowX: true, overflowX: true,
overflowY: true, overflowY: true,
el: { el: {
type: "bi.vertical", type: VerticalLayout.xtype,
}, },
cellSizeAndPositionGetter: emptyFn, cellSizeAndPositionGetter: emptyFn,
horizontalOverscanSize: 0, horizontalOverscanSize: 0,
@ -45,7 +67,7 @@ export class CollectionView extends Widget {
this._scrollLock = false; this._scrollLock = false;
}, 1000 / 60); }, 1000 / 60);
this.container = _lazyCreateWidget({ this.container = _lazyCreateWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
}); });
this.element.scroll(() => { this.element.scroll(() => {
if (this._scrollLock === true) { if (this._scrollLock === true) {
@ -61,7 +83,8 @@ export class CollectionView extends Widget {
}); });
// 兼容一下 // 兼容一下
let scrollable = o.scrollable; let scrollable = o.scrollable;
const scrollx = o.scrollx, scrolly = o.scrolly; const scrollx = o.scrollx,
scrolly = o.scrolly;
if (overflowX === false) { if (overflowX === false) {
if (overflowY === false) { if (overflowY === false) {
scrollable = false; scrollable = false;
@ -74,16 +97,18 @@ export class CollectionView extends Widget {
} }
} }
_lazyCreateWidget(el, { _lazyCreateWidget(el, {
type: "bi.vertical", type: VerticalLayout.xtype,
element: this, element: this,
scrollable, scrollable,
scrolly, scrolly,
scrollx, scrollx,
items: [this.container], items: [this.container],
}); });
o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items)
this.populate(newValue); ? this.__watch(o.items, (context, newValue) => {
}) : o.items; this.populate(newValue);
})
: o.items;
if (o.items.length > 0) { if (o.items.length > 0) {
this._calculateSizeAndPositionData(); this._calculateSizeAndPositionData();
this._populate(); this._populate();
@ -109,10 +134,16 @@ export class CollectionView extends Widget {
for (let index = 0, len = items.length; index < len; index++) { for (let index = 0, len = items.length; index < len; index++) {
const cellMetadatum = cellSizeAndPositionGetter(index); const cellMetadatum = cellSizeAndPositionGetter(index);
if (isNull(cellMetadatum.height) || isNaN(cellMetadatum.height) || if (
isNull(cellMetadatum.width) || isNaN(cellMetadatum.width) || isNull(cellMetadatum.height) ||
isNull(cellMetadatum.x) || isNaN(cellMetadatum.x) || isNaN(cellMetadatum.height) ||
isNull(cellMetadatum.y) || isNaN(cellMetadatum.y)) { isNull(cellMetadatum.width) ||
isNaN(cellMetadatum.width) ||
isNull(cellMetadatum.x) ||
isNaN(cellMetadatum.x) ||
isNull(cellMetadatum.y) ||
isNaN(cellMetadatum.y)
) {
throw Error(); throw Error();
} }
@ -157,13 +188,21 @@ export class CollectionView extends Widget {
const bottom = Math.min(this._height, scrollTop + height + verticalOverscanSize); const bottom = Math.min(this._height, scrollTop + height + verticalOverscanSize);
if (right > 0 && bottom > 0) { if (right > 0 && bottom > 0) {
// 如果滚动的区间并没有超出渲染的范围 // 如果滚动的区间并没有超出渲染的范围
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) { if (
top >= this.renderRange.minY &&
bottom <= this.renderRange.maxY &&
left >= this.renderRange.minX &&
right <= this.renderRange.maxX
) {
return; return;
} }
const childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top); const childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top);
const renderedCells = [], renderedKeys = {}, renderedWidgets = {}; const renderedCells = [],
renderedKeys = {},
renderedWidgets = {};
// 存储所有的left和top // 存储所有的left和top
let lefts = {}, tops = {}; let lefts = {},
tops = {};
for (let i = 0, len = childrenToDisplay.length; i < len; i++) { for (let i = 0, len = childrenToDisplay.length; i < len; i++) {
const datum = childrenToDisplay[i]; const datum = childrenToDisplay[i];
lefts[datum.x] = datum.x; lefts[datum.x] = datum.x;
@ -176,7 +215,10 @@ export class CollectionView extends Widget {
const leftMap = invert(lefts); const leftMap = invert(lefts);
const topMap = invert(tops); const topMap = invert(tops);
// 存储上下左右四个边界 // 存储上下左右四个边界
const leftBorder = {}, rightBorder = {}, topBorder = {}, bottomBorder = {}; const leftBorder = {},
rightBorder = {},
topBorder = {},
bottomBorder = {};
function assertMinBorder(border, offset) { function assertMinBorder(border, offset) {
if (isNull(border[offset])) { if (isNull(border[offset])) {
border[offset] = Number.MAX_VALUE; border[offset] = Number.MAX_VALUE;
@ -197,18 +239,26 @@ export class CollectionView extends Widget {
// 这里只使用px // 这里只使用px
this.renderedCells[index].el.element.css("left", `${datum.x}px`); this.renderedCells[index].el.element.css("left", `${datum.x}px`);
this.renderedCells[index].el.element.css("top", `${datum.y}px`); this.renderedCells[index].el.element.css("top", `${datum.y}px`);
renderedCells.push(child = this.renderedCells[index]); renderedCells.push((child = this.renderedCells[index]));
} else { } else {
const item = itemFormatter(items[datum.index], datum.index); const item = itemFormatter(items[datum.index], datum.index);
child = _lazyCreateWidget(extend({ child = _lazyCreateWidget(
type: "bi.label", extend(
width: datum.width, {
height: datum.height, type: Label.xtype,
}, item, { width: datum.width,
cls: `${item.cls || ""} collection-cell${datum.y === 0 ? " first-row" : ""}${datum.x === 0 ? " first-col" : ""}`, height: datum.height,
_left: datum.x, },
_top: datum.y, item,
})); {
cls: `${item.cls || ""} collection-cell${datum.y === 0 ? " first-row" : ""}${
datum.x === 0 ? " first-col" : ""
}`,
_left: datum.x,
_top: datum.y,
}
)
);
renderedCells.push({ renderedCells.push({
el: child, el: child,
left: `${datum.x}px`, left: `${datum.x}px`,
@ -242,7 +292,9 @@ export class CollectionView extends Widget {
renderedWidgets[i] = child; renderedWidgets[i] = child;
} }
// 已存在的, 需要添加的和需要删除的 // 已存在的, 需要添加的和需要删除的
const existSet = {}, addSet = {}, deleteArray = []; const existSet = {},
addSet = {},
deleteArray = [];
each(renderedKeys, (i, key) => { each(renderedKeys, (i, key) => {
if (this.renderedKeys[i]) { if (this.renderedKeys[i]) {
existSet[i] = key; existSet[i] = key;
@ -289,7 +341,8 @@ export class CollectionView extends Widget {
const o = this.options; const o = this.options;
const { overflowX } = this.options; const { overflowX } = this.options;
// 兼容一下 // 兼容一下
const scrollable = o.scrollable, scrollx = o.scrollx; const scrollable = o.scrollable,
scrollx = o.scrollx;
if (overflowX === false) { if (overflowX === false) {
return false; return false;
} }
@ -299,7 +352,7 @@ export class CollectionView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "x") { if (scrollable === true || scrollable === "xy" || scrollable === "x") {
return true; return true;
} }
return false; return false;
} }
@ -307,7 +360,8 @@ export class CollectionView extends Widget {
const o = this.options; const o = this.options;
const { overflowX } = this.options; const { overflowX } = this.options;
// 兼容一下 // 兼容一下
const scrollable = o.scrollable, scrolly = o.scrolly; const scrollable = o.scrollable,
scrolly = o.scrolly;
if (overflowX === false) { if (overflowX === false) {
return false; return false;
} }
@ -317,7 +371,7 @@ export class CollectionView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "y") { if (scrollable === true || scrollable === "xy" || scrollable === "y") {
return true; return true;
} }
return false; return false;
} }
@ -344,8 +398,7 @@ export class CollectionView extends Widget {
try { try {
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
this.element.scrollLeft(scrollLeft); this.element.scrollLeft(scrollLeft);
} catch (e) { } catch (e) {}
}
this._calculateChildrenToRender(); this._calculateChildrenToRender();
} }
setScrollLeft(scrollLeft) { setScrollLeft(scrollLeft) {

249
src/base/combination/bubble.js

@ -1,8 +1,26 @@
import { BubblePopupView } from "@/case/combo/bubblecombo/popup.bubble";
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
nextTick,
createWidget,
each,
defer,
debounce,
delay,
isNull,
isFunction,
contains,
bind
} from "@/core";
/** /**
* @class BI.Bubble * @class BI.Bubble
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, nextTick, createWidget, each, defer, debounce, delay, isNull, isFunction, contains, bind } from "../../core";
@shortcut() @shortcut()
export class Bubble extends Widget { export class Bubble extends Widget {
@ -23,7 +41,7 @@ export class Bubble extends Widget {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-popper", baseCls: `${conf.baseCls || ""} bi-popper`,
attributes: { attributes: {
tabIndex: -1, tabIndex: -1,
}, },
@ -85,26 +103,32 @@ export class Bubble extends Widget {
} }
}); });
this.element.on("mouseenter." + this.getName(), (e) => { this.element.on(`mouseenter.${this.getName()}`, (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this.element.addClass(hoverClass); this.element.addClass(hoverClass);
} }
}); });
this.element.on("mouseleave." + this.getName(), (e) => { this.element.on(`mouseleave.${this.getName()}`, (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this.element.removeClass(hoverClass); this.element.removeClass(hoverClass);
} }
}); });
createWidget(extend({ createWidget(
element: this, extend(
scrolly: false, {
}, BI.LogicFactory.createLogic("vertical", extend(logic, { element: this,
items: [ scrolly: false,
{ el: this.combo } },
], BI.LogicFactory.createLogic(
})))); "vertical",
isDefaultInit && (this._assertPopupView()); extend(logic, {
items: [{ el: this.combo }],
})
)
)
);
isDefaultInit && this._assertPopupView();
} }
_toggle(e) { _toggle(e) {
@ -129,39 +153,46 @@ export class Bubble extends Widget {
if (stopPropagation) { if (stopPropagation) {
e.stopPropagation(); e.stopPropagation();
} }
} };
let enterPopup = false; let enterPopup = false;
const hide = (e) => { const hide = (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid() && toggle === true) { if (
this.isEnabled() &&
this.isValid() &&
this.combo.isEnabled() &&
this.combo.isValid() &&
toggle === true
) {
this._hideView(e); this._hideView(e);
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.combo); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.combo);
this.fireEvent(Bubble.EVENT_COLLAPSE); this.fireEvent(Bubble.EVENT_COLLAPSE);
} }
this.popupView && this.popupView.element.off("mouseenter." + this.getName()).off("mouseleave." + this.getName()); this.popupView &&
this.popupView.element.off(`mouseenter.${this.getName()}`).off(`mouseleave.${this.getName()}`);
enterPopup = false; enterPopup = false;
} };
each(evs, (i, ev) => { each(evs, (i, ev) => {
let debounced; let debounced;
switch (ev) { switch (ev) {
case "hover": case "hover":
this.element.on("mouseenter." + this.getName(), (e) => { this.element.on(`mouseenter.${this.getName()}`, (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this._popupView(e); this._popupView(e);
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo);
this.fireEvent(Bubble.EVENT_EXPAND); this.fireEvent(Bubble.EVENT_EXPAND);
} }
}); });
this.element.on("mouseleave." + this.getName(), (e) => { this.element.on(`mouseleave.${this.getName()}`, (e) => {
if (this.popupView) { if (this.popupView) {
this.popupView.element.on("mouseenter." + this.getName(), (e) => { this.popupView.element.on(`mouseenter.${this.getName()}`, (e) => {
enterPopup = true; enterPopup = true;
this.popupView.element.on("mouseleave." + this.getName(), (e) => { this.popupView.element.on(`mouseleave.${this.getName()}`, (e) => {
hide(e); hide(e);
}); });
this.popupView.element.off("mouseenter." + this.getName()); this.popupView.element.off(`mouseenter.${this.getName()}`);
}); });
defer(() => { defer(() => {
if (!enterPopup) { if (!enterPopup) {
@ -172,61 +203,79 @@ export class Bubble extends Widget {
}); });
break; break;
case "click": case "click":
debounced = debounce((e) => { debounced = debounce(
if (this.combo.element.__isMouseInBounds__(e)) { (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.combo.element.__isMouseInBounds__(e)) {
// if (!o.toggle && this.isViewVisible()) { if (
// return; this.isEnabled() &&
// } this.isValid() &&
toggle ? this._toggle(e) : this._popupView(e); this.combo.isEnabled() &&
if (this.isViewVisible()) { this.combo.isValid()
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo); ) {
this.fireEvent(Bubble.EVENT_EXPAND); // if (!o.toggle && this.isViewVisible()) {
} else { // return;
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.combo); // }
this.fireEvent(Bubble.EVENT_COLLAPSE); toggle ? this._toggle(e) : this._popupView(e);
if (this.isViewVisible()) {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo);
this.fireEvent(Bubble.EVENT_EXPAND);
} else {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.combo);
this.fireEvent(Bubble.EVENT_COLLAPSE);
}
} }
} }
},
BI.EVENT_RESPONSE_TIME,
{
leading: true,
trailing: false,
} }
}, BI.EVENT_RESPONSE_TIME, { );
"leading": true, this.element.off(`${ev}.${this.getName()}`).on(`${ev}.${this.getName()}`, (e) => {
"trailing": false,
});
this.element.off(ev + "." + this.getName()).on(ev + "." + this.getName(), (e) => {
debounced(e); debounced(e);
st(e); st(e);
}); });
break; break;
case "click-hover": case "click-hover":
debounced = debounce((e) => { debounced = debounce(
if (this.combo.element.__isMouseInBounds__(e)) { (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.combo.element.__isMouseInBounds__(e)) {
// if (this.isViewVisible()) { if (
// return; this.isEnabled() &&
// } this.isValid() &&
this._popupView(e); this.combo.isEnabled() &&
if (this.isViewVisible()) { this.combo.isValid()
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo); ) {
this.fireEvent(Bubble.EVENT_EXPAND); // if (this.isViewVisible()) {
// return;
// }
this._popupView(e);
if (this.isViewVisible()) {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo);
this.fireEvent(Bubble.EVENT_EXPAND);
}
} }
} }
},
BI.EVENT_RESPONSE_TIME,
{
leading: true,
trailing: false,
} }
}, BI.EVENT_RESPONSE_TIME, { );
"leading": true, this.element.off(`click.${this.getName()}`).on(`click.${this.getName()}`, (e) => {
"trailing": false,
});
this.element.off("click." + this.getName()).on("click." + this.getName(), (e) => {
debounced(e); debounced(e);
st(e); st(e);
}); });
this.element.on("mouseleave." + this.getName(), (e) => { this.element.on(`mouseleave.${this.getName()}`, (e) => {
if (this.popupView) { if (this.popupView) {
this.popupView.element.on("mouseenter." + this.getName(), (e) => { this.popupView.element.on(`mouseenter.${this.getName()}`, (e) => {
enterPopup = true; enterPopup = true;
this.popupView.element.on("mouseleave." + this.getName(), (e) => { this.popupView.element.on(`mouseleave.${this.getName()}`, (e) => {
hide(e); hide(e);
}); });
this.popupView.element.off("mouseenter." + this.getName()); this.popupView.element.off(`mouseenter.${this.getName()}`);
}); });
delay(() => { delay(() => {
if (!enterPopup) { if (!enterPopup) {
@ -237,7 +286,7 @@ export class Bubble extends Widget {
}); });
break; break;
case "hover-click": case "hover-click":
this.element.on("mouseenter." + this.getName(), (e) => { this.element.on(`mouseenter.${this.getName()}`, (e) => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this._popupView(e); this._popupView(e);
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.combo);
@ -260,11 +309,15 @@ export class Bubble extends Widget {
_assertPopupView() { _assertPopupView() {
const { showArrow, value } = this.options; const { showArrow, value } = this.options;
if (isNull(this.popupView)) { if (isNull(this.popupView)) {
this.popupView = createWidget(isFunction(this.options.popup) ? this.options.popup() : this.options.popup, { this.popupView = createWidget(
type: "bi.bubble_popup_view", isFunction(this.options.popup) ? this.options.popup() : this.options.popup,
showArrow, {
value, type: BubblePopupView.xtype,
}, this); showArrow,
value,
},
this
);
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this.combo.setValue(this.getValue()); this.combo.setValue(this.getValue());
@ -283,12 +336,10 @@ export class Bubble extends Widget {
this._assertPopupView(); this._assertPopupView();
if (!this._rendered) { if (!this._rendered) {
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
scrolly: false, scrolly: false,
element: isFunction(this.options.container) ? this.options.container() : (this.options.container || this), element: isFunction(this.options.container) ? this.options.container() : this.options.container || this,
items: [ items: [{ el: this.popupView }],
{ el: this.popupView }
],
}); });
this._rendered = true; this._rendered = true;
} }
@ -299,9 +350,14 @@ export class Bubble extends Widget {
// return; // return;
// } // }
// BI-10290 公式combo双击公式内容会收起 // BI-10290 公式combo双击公式内容会收起
if (e && ((skipTriggerChecker !== true && this.element.find(e.target).length > 0) if (
|| (this.popupView && this.popupView.element.find(e.target).length > 0) e &&
|| e.target.className === "CodeMirror-cursor" || Widget._renderEngine.createElement(e.target).closest(".CodeMirror-hints").length > 0)) {// BI-9887 CodeMirror的公式弹框需要特殊处理下 ((skipTriggerChecker !== true && this.element.find(e.target).length > 0) ||
(this.popupView && this.popupView.element.find(e.target).length > 0) ||
e.target.className === "CodeMirror-cursor" ||
Widget._renderEngine.createElement(e.target).closest(".CodeMirror-hints").length > 0)
) {
// BI-9887 CodeMirror的公式弹框需要特殊处理下
const directions = this.options.direction.split(","); const directions = this.options.direction.split(",");
if (contains(directions, "innerLeft") || contains(directions, "innerRight")) { if (contains(directions, "innerLeft") || contains(directions, "innerRight")) {
// popup可以出现在trigger内部的combo,滚动时不需要消失,而是调整位置 // popup可以出现在trigger内部的combo,滚动时不需要消失,而是调整位置
@ -344,13 +400,17 @@ export class Bubble extends Widget {
this.element.removeClass(this.options.comboClass); this.element.removeClass(this.options.comboClass);
Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName()); Widget._renderEngine
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind("blur." + this.getName()); .createElement(document)
.unbind(`mousedown.${this.getName()}`)
.unbind(`mousewheel.${this.getName()}`);
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
this.fireEvent(Bubble.EVENT_AFTER_HIDEVIEW); this.fireEvent(Bubble.EVENT_AFTER_HIDEVIEW);
} }
_popupView(e) { _popupView(e) {
const { adjustXOffset, showArrow, adjustYOffset, adjustLength, placement, hideWhenClickOutside, hideWhenBlur } = this.options; const { adjustXOffset, showArrow, adjustYOffset, adjustLength, placement, hideWhenClickOutside, hideWhenBlur } =
this.options;
this._assertPopupViewRender(); this._assertPopupViewRender();
this.fireEvent(Bubble.EVENT_BEFORE_POPUPVIEW); this.fireEvent(Bubble.EVENT_BEFORE_POPUPVIEW);
// popupVisible是为了获取其宽高, 放到可视范围之外以防止在IE下闪一下 // popupVisible是为了获取其宽高, 放到可视范围之外以防止在IE下闪一下
@ -365,11 +425,9 @@ export class Bubble extends Widget {
{ {
name: "offset", name: "offset",
options: { options: {
offset: () => { offset: () => [adjustXOffset, (showArrow ? 12 : 0) + (adjustYOffset + adjustLength)],
return [adjustXOffset, (showArrow ? 12 : 0) + (adjustYOffset + adjustLength)];
},
}, },
} },
]; ];
if (this.options.showArrow) { if (this.options.showArrow) {
modifiers.push({ modifiers.push({
@ -389,11 +447,14 @@ export class Bubble extends Widget {
// this.adjustHeight(e); // this.adjustHeight(e);
this.element.addClass(this.options.comboClass); this.element.addClass(this.options.comboClass);
hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()); hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind(`mousedown.${this.getName()}`);
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind("blur." + this.getName()); BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
hideWhenClickOutside && Widget._renderEngine.createElement(document).bind("mousedown." + this.getName(), bind(this._hideIf, this)); hideWhenClickOutside &&
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).bind("blur." + this.getName(), bind(this._hideIf, this)); Widget._renderEngine.createElement(document).bind(`mousedown.${this.getName()}`, bind(this._hideIf, this));
BI.EVENT_BLUR &&
hideWhenBlur &&
Widget._renderEngine.createElement(window).bind(`blur.${this.getName()}`, bind(this._hideIf, this));
this.fireEvent(Bubble.EVENT_AFTER_POPUPVIEW); this.fireEvent(Bubble.EVENT_AFTER_POPUPVIEW);
} }
@ -425,9 +486,7 @@ export class Bubble extends Widget {
} }
} }
adjustHeight() { adjustHeight() {}
}
resetListHeight(h) { resetListHeight(h) {
this._assertPopupView(); this._assertPopupView();
@ -501,13 +560,13 @@ export class Bubble extends Widget {
} }
destroyed() { destroyed() {
Widget._renderEngine.createElement(document) Widget._renderEngine
.unbind("click." + this.getName()) .createElement(document)
.unbind("mousedown." + this.getName()) .unbind(`click.${this.getName()}`)
.unbind("mouseenter." + this.getName()) .unbind(`mousedown.${this.getName()}`)
.unbind("mouseleave." + this.getName()); .unbind(`mouseenter.${this.getName()}`)
Widget._renderEngine.createElement(window) .unbind(`mouseleave.${this.getName()}`);
.unbind("blur." + this.getName()); Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
this.popper && this.popper.destroy(); this.popper && this.popper.destroy();
this.popper = null; this.popper = null;
this.popupView && this.popupView._destroy(); this.popupView && this.popupView._destroy();

475
src/base/combination/combo.js

@ -1,12 +1,25 @@
import { PopupView } from "../layer";
import { Bubble } from "./bubble";
import {
shortcut,
Widget,
Controller,
extend,
createWidget,
nextTick,
bind,
isNotNull,
isNull,
isFunction,
each
} from "@/core";
import { Resizers } from "@/base/0.base";
/** /**
* @class BI.Combo * @class BI.Combo
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, createWidget, nextTick, bind, isNotNull, isNull, isFunction, each } from "../../core";
import { Bubble } from "./bubble";
import { Resizers } from "../0.base";
let needHideWhenAnotherComboOpen = {}; let needHideWhenAnotherComboOpen = {};
let currentOpenedCombos = {}; let currentOpenedCombos = {};
@ -29,7 +42,7 @@ export class Combo extends Bubble {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-combo" + (BI.isIE() ? " hack" : ""), baseCls: `${conf.baseCls || ""} bi-combo${BI.isIE() ? " hack" : ""}`,
attributes: { attributes: {
tabIndex: -1, tabIndex: -1,
}, },
@ -96,42 +109,55 @@ export class Combo extends Bubble {
} }
}); });
this.element.on("mouseenter." + this.getName(), (e) => { this.element.on(`mouseenter.${this.getName()}`, e => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this.element.addClass(hoverClass); this.element.addClass(hoverClass);
} }
}); });
this.element.on("mouseleave." + this.getName(), (e) => { this.element.on(`mouseleave.${this.getName()}`, e => {
if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) { if (this.isEnabled() && this.isValid() && this.combo.isEnabled() && this.combo.isValid()) {
this.element.removeClass(hoverClass); this.element.removeClass(hoverClass);
} }
}); });
createWidget(extend({ createWidget(
element: this, extend(
scrolly: false, {
}, BI.LogicFactory.createLogic("vertical", extend(logic, { element: this,
items: [ scrolly: false,
{ el: this.combo } },
], BI.LogicFactory.createLogic(
})))); "vertical",
isDefaultInit && (this._assertPopupView()); extend(logic, {
Resizers.add(this.getName(), bind((e) => { items: [{ el: this.combo }],
// 如果resize对象是combo的子元素,则不应该收起,或交由hideChecker去处理 })
if (this.isViewVisible()) { )
isNotNull(e) ? this._hideIf(e) : this._hideView(); )
} );
}, this)); isDefaultInit && this._assertPopupView();
Resizers.add(
this.getName(),
bind(e => {
// 如果resize对象是combo的子元素,则不应该收起,或交由hideChecker去处理
if (this.isViewVisible()) {
isNotNull(e) ? this._hideIf(e) : this._hideView();
}
}, this)
);
} }
_assertPopupView() { _assertPopupView() {
const { showArrow, value, hideWhenClickOutside, hideWhenBlur } = this.options; const { showArrow, value, hideWhenClickOutside, hideWhenBlur } = this.options;
if (isNull(this.popupView)) { if (isNull(this.popupView)) {
this.popupView = createWidget(isFunction(this.options.popup) ? this.options.popup() : this.options.popup, { this.popupView = createWidget(
type: "bi.popup_view", isFunction(this.options.popup) ? this.options.popup() : this.options.popup,
showArrow, {
value, type: PopupView.xtype,
}, this); showArrow,
value,
},
this
);
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this.combo.setValue(this.getValue()); this.combo.setValue(this.getValue());
@ -167,8 +193,12 @@ export class Combo extends Bubble {
delete needHideWhenAnotherComboOpen[this.getName()]; delete needHideWhenAnotherComboOpen[this.getName()];
delete currentOpenedCombos[this.getName()]; delete currentOpenedCombos[this.getName()];
hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName()); hideWhenClickOutside &&
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind("blur." + this.getName()); Widget._renderEngine
.createElement(document)
.unbind(`mousedown.${this.getName()}`)
.unbind(`mousewheel.${this.getName()}`);
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
this.fireEvent(Combo.EVENT_AFTER_HIDEVIEW, e); this.fireEvent(Combo.EVENT_AFTER_HIDEVIEW, e);
} }
@ -192,119 +222,272 @@ export class Combo extends Bubble {
this.adjustHeight(e); this.adjustHeight(e);
this.element.addClass(this.options.comboClass); this.element.addClass(this.options.comboClass);
hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName()); hideWhenClickOutside &&
hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind("mousewheel." + this.getName()); Widget._renderEngine
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind("blur." + this.getName()); .createElement(document)
.unbind(`mousedown.${this.getName()}`)
.unbind(`mousewheel.${this.getName()}`);
hideWhenClickOutside && Widget._renderEngine.createElement(document).unbind(`mousewheel.${this.getName()}`);
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
hideWhenClickOutside && Widget._renderEngine.createElement(document).bind("mousewheel." + this.getName(), bind(this._hideIf, this)); hideWhenClickOutside &&
hideWhenClickOutside && Widget._renderEngine.createElement(document).bind("mousedown." + this.getName(), bind(this._hideIf, this)).bind("mousewheel." + this.getName(), bind(this._hideIf, this)); Widget._renderEngine.createElement(document).bind(`mousewheel.${this.getName()}`, bind(this._hideIf, this));
BI.EVENT_BLUR && hideWhenBlur && Widget._renderEngine.createElement(window).bind("blur." + this.getName(), bind(this._hideIf, this)); hideWhenClickOutside &&
Widget._renderEngine
.createElement(document)
.bind(`mousedown.${this.getName()}`, bind(this._hideIf, this))
.bind(`mousewheel.${this.getName()}`, bind(this._hideIf, this));
BI.EVENT_BLUR &&
hideWhenBlur &&
Widget._renderEngine.createElement(window).bind(`blur.${this.getName()}`, bind(this._hideIf, this));
this.fireEvent(Combo.EVENT_AFTER_POPUPVIEW); this.fireEvent(Combo.EVENT_AFTER_POPUPVIEW);
} }
adjustHeight(e) { adjustHeight(e) {
const { belowMouse, supportCSSTransform, container, direction, adjustXOffset, adjustYOffset, adjustLength, showArrow, isNeedAdjustHeight, offsetStyle } = this.options; const {
belowMouse,
supportCSSTransform,
container,
direction,
adjustXOffset,
adjustYOffset,
adjustLength,
showArrow,
isNeedAdjustHeight,
offsetStyle,
} = this.options;
let p = {}; let p = {};
if (!this.popupView) { if (!this.popupView) {
return; return;
} }
const isVisible = this.popupView.isVisible(); const isVisible = this.popupView.isVisible();
this.popupView.visible(); this.popupView.visible();
const combo = (belowMouse && isNotNull(e)) ? { const combo =
element: { belowMouse && isNotNull(e)
0: e.target, ? {
offset: () => { element: {
return { 0: e.target,
left: e.pageX, offset: () => {
top: e.pageY, return {
}; left: e.pageX,
}, top: e.pageY,
bounds: () => { };
// offset为其相对于父定位元素的偏移 },
return { bounds: () => {
x: e.offsetX, // offset为其相对于父定位元素的偏移
y: e.offsetY, return {
width: 0, x: e.offsetX,
height: 24, y: e.offsetY,
}; width: 0,
}, height: 24,
outerWidth: () => { };
return 0; },
}, outerWidth: () => 0,
outerHeight: () => { outerHeight: () => 24,
return 24; },
}, }
}, : this.combo;
} : this.combo; const positionRelativeElement = supportCSSTransform
const positionRelativeElement = supportCSSTransform ? BI.DOM.getPositionRelativeContainingBlock(isNull(container) ? this.element[0] : Widget._renderEngine.createElement(isFunction(container) ? container() : container)[0]) : null; ? BI.DOM.getPositionRelativeContainingBlock(
isNull(container)
? this.element[0]
: Widget._renderEngine.createElement(isFunction(container) ? container() : container)[0]
)
: null;
const TRIANGLE_LENGTH = 12; const TRIANGLE_LENGTH = 12;
switch (direction) { switch (direction) {
case "bottom": case "bottom":
case "bottom,right": case "bottom,right":
p = BI.DOM.getComboPosition(combo, this.popupView, adjustXOffset, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight, ["bottom", "top", "right", "left"], offsetStyle, positionRelativeElement); p = BI.DOM.getComboPosition(
break; combo,
case "top": this.popupView,
case "top,right": adjustXOffset,
p = BI.DOM.getComboPosition(combo, this.popupView, adjustXOffset, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight, ["top", "bottom", "right", "left"], offsetStyle, positionRelativeElement); adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
break; isNeedAdjustHeight,
case "left": ["bottom", "top", "right", "left"],
case "left,bottom": offsetStyle,
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["left", "right", "bottom", "top"], offsetStyle, positionRelativeElement); positionRelativeElement
break; );
case "right": break;
case "right,bottom": case "top":
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["right", "left", "bottom", "top"], offsetStyle, positionRelativeElement); case "top,right":
break; p = BI.DOM.getComboPosition(
case "top,left": combo,
p = BI.DOM.getComboPosition(combo, this.popupView, adjustXOffset, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight, ["top", "bottom", "left", "right"], offsetStyle, positionRelativeElement); this.popupView,
break; adjustXOffset,
case "bottom,left": adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
p = BI.DOM.getComboPosition(combo, this.popupView, adjustXOffset, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight, ["bottom", "top", "left", "right"], offsetStyle, positionRelativeElement); isNeedAdjustHeight,
break; ["top", "bottom", "right", "left"],
case "left,top": offsetStyle,
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["left", "right", "top", "bottom"], offsetStyle, positionRelativeElement); positionRelativeElement
break; );
case "right,top": break;
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["right", "left", "top", "bottom"], offsetStyle, positionRelativeElement); case "left":
break; case "left,bottom":
case "right,innerRight": p = BI.DOM.getComboPosition(
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["right", "left", "innerRight", "innerLeft", "bottom", "top"], offsetStyle, positionRelativeElement); combo,
break; this.popupView,
case "right,innerLeft": adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["right", "left", "innerLeft", "innerRight", "bottom", "top"], offsetStyle, positionRelativeElement); adjustYOffset,
break; isNeedAdjustHeight,
case "innerRight": ["left", "right", "bottom", "top"],
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["innerRight", "innerLeft", "right", "left", "bottom", "top"], offsetStyle, positionRelativeElement); offsetStyle,
break; positionRelativeElement
case "innerLeft": );
p = BI.DOM.getComboPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), adjustYOffset, isNeedAdjustHeight, ["innerLeft", "innerRight", "left", "right", "bottom", "top"], offsetStyle, positionRelativeElement); break;
break; case "right":
case "top,custom": case "right,bottom":
case "custom,top": p = BI.DOM.getComboPosition(
p = BI.DOM.getTopAdaptPosition(combo, this.popupView, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight); combo,
p.dir = "top"; this.popupView,
break; adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
case "custom,bottom": adjustYOffset,
case "bottom,custom": isNeedAdjustHeight,
p = BI.DOM.getBottomAdaptPosition(combo, this.popupView, (adjustYOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0), isNeedAdjustHeight); ["right", "left", "bottom", "top"],
p.dir = "bottom"; offsetStyle,
break; positionRelativeElement
case "left,custom": );
case "custom,left": break;
p = BI.DOM.getLeftAdaptPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0)); case "top,left":
delete p.top; p = BI.DOM.getComboPosition(
delete p.adaptHeight; combo,
p.dir = "left"; this.popupView,
break; adjustXOffset,
case "custom,right": adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
case "right,custom": isNeedAdjustHeight,
p = BI.DOM.getRightAdaptPosition(combo, this.popupView, (adjustXOffset + adjustLength) + (showArrow ? TRIANGLE_LENGTH : 0)); ["top", "bottom", "left", "right"],
delete p.top; offsetStyle,
delete p.adaptHeight; positionRelativeElement
p.dir = "right"; );
break; break;
default: case "bottom,left":
break; p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset,
adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
isNeedAdjustHeight,
["bottom", "top", "left", "right"],
offsetStyle,
positionRelativeElement
);
break;
case "left,top":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["left", "right", "top", "bottom"],
offsetStyle,
positionRelativeElement
);
break;
case "right,top":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["right", "left", "top", "bottom"],
offsetStyle,
positionRelativeElement
);
break;
case "right,innerRight":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["right", "left", "innerRight", "innerLeft", "bottom", "top"],
offsetStyle,
positionRelativeElement
);
break;
case "right,innerLeft":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["right", "left", "innerLeft", "innerRight", "bottom", "top"],
offsetStyle,
positionRelativeElement
);
break;
case "innerRight":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["innerRight", "innerLeft", "right", "left", "bottom", "top"],
offsetStyle,
positionRelativeElement
);
break;
case "innerLeft":
p = BI.DOM.getComboPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
adjustYOffset,
isNeedAdjustHeight,
["innerLeft", "innerRight", "left", "right", "bottom", "top"],
offsetStyle,
positionRelativeElement
);
break;
case "top,custom":
case "custom,top":
p = BI.DOM.getTopAdaptPosition(
combo,
this.popupView,
adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
isNeedAdjustHeight
);
p.dir = "top";
break;
case "custom,bottom":
case "bottom,custom":
p = BI.DOM.getBottomAdaptPosition(
combo,
this.popupView,
adjustYOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0),
isNeedAdjustHeight
);
p.dir = "bottom";
break;
case "left,custom":
case "custom,left":
p = BI.DOM.getLeftAdaptPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0)
);
delete p.top;
delete p.adaptHeight;
p.dir = "left";
break;
case "custom,right":
case "right,custom":
p = BI.DOM.getRightAdaptPosition(
combo,
this.popupView,
adjustXOffset + adjustLength + (showArrow ? TRIANGLE_LENGTH : 0)
);
delete p.top;
delete p.adaptHeight;
p.dir = "right";
break;
default:
break;
} }
if ("adaptHeight" in p) { if ("adaptHeight" in p) {
@ -313,17 +496,17 @@ export class Combo extends Bubble {
const width = this.combo.element.outerWidth(); const width = this.combo.element.outerWidth();
const height = this.combo.element.outerHeight(); const height = this.combo.element.outerHeight();
this.popupView.setDirection && this.popupView.setDirection(p.dir, { this.popupView.setDirection &&
width, this.popupView.setDirection(p.dir, {
height, width,
offsetStyle, height,
adjustXOffset, offsetStyle,
adjustYOffset, adjustXOffset,
offset: this.combo.element.offset(), adjustYOffset,
}); offset: this.combo.element.offset(),
});
if (supportCSSTransform) { if (supportCSSTransform) {
const positonedRect = positionRelativeElement.getBoundingClientRect(); const positonedRect = positionRelativeElement.getBoundingClientRect();
const scaleX = positonedRect.width / positionRelativeElement.offsetWidth; const scaleX = positonedRect.width / positionRelativeElement.offsetWidth;
@ -348,14 +531,14 @@ export class Combo extends Bubble {
} }
destroyed() { destroyed() {
Widget._renderEngine.createElement(document) Widget._renderEngine
.unbind("click." + this.getName()) .createElement(document)
.unbind("mousedown." + this.getName()) .unbind(`click.${this.getName()}`)
.unbind("mousewheel." + this.getName()) .unbind(`mousedown.${this.getName()}`)
.unbind("mouseenter." + this.getName()) .unbind(`mousewheel.${this.getName()}`)
.unbind("mouseleave." + this.getName()); .unbind(`mouseenter.${this.getName()}`)
Widget._renderEngine.createElement(window) .unbind(`mouseleave.${this.getName()}`);
.unbind("blur." + this.getName()); Widget._renderEngine.createElement(window).unbind(`blur.${this.getName()}`);
Resizers.remove(this.getName()); Resizers.remove(this.getName());
this.popupView && this.popupView._destroy(); this.popupView && this.popupView._destroy();
delete needHideWhenAnotherComboOpen[this.getName()]; delete needHideWhenAnotherComboOpen[this.getName()];

166
src/base/combination/expander.js

@ -1,3 +1,17 @@
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
nextTick,
each,
debounce,
isNull,
createWidget
} from "@/core";
import { ButtonGroup } from "./group.button";
/** /**
* *
* 某个可以展开的节点 * 某个可以展开的节点
@ -6,7 +20,6 @@
* @class BI.Expander * @class BI.Expander
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, nextTick, each, debounce, isNull, createWidget } from "../../core";
@shortcut() @shortcut()
export class Expander extends Widget { export class Expander extends Widget {
@ -67,22 +80,23 @@ export class Expander extends Widget {
} }
}); });
this.element.hover(() => { this.element.hover(
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) { () => {
this.element.addClass(hoverClass); if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) {
} this.element.addClass(hoverClass);
}, () => { }
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) { },
this.element.removeClass(hoverClass); () => {
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) {
this.element.removeClass(hoverClass);
}
} }
}); );
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
scrolly: false, scrolly: false,
element: this, element: this,
items: [ items: [{ el: this.expander }],
{ el: this.expander }
],
}); });
isDefaultInit && this._assertPopupView(); isDefaultInit && this._assertPopupView();
if (this.expander.isOpened() === true) { if (this.expander.isOpened() === true) {
@ -106,44 +120,80 @@ export class Expander extends Widget {
const evs = this.options.trigger.split(","); const evs = this.options.trigger.split(",");
each(evs, (i, e) => { each(evs, (i, e) => {
switch (e) { switch (e) {
case "hover": case "hover":
this.element[e]((e) => { this.element[e](
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) { e => {
if (
this.isEnabled() &&
this.isValid() &&
this.expander.isEnabled() &&
this.expander.isValid()
) {
this._popupView(); this._popupView();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.expander); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.expander);
this.fireEvent(Expander.EVENT_EXPAND); this.fireEvent(Expander.EVENT_EXPAND);
} }
}, () => { },
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid() && toggle) { () => {
if (
this.isEnabled() &&
this.isValid() &&
this.expander.isEnabled() &&
this.expander.isValid() &&
toggle
) {
this._hideView(); this._hideView();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.expander); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.expander);
this.fireEvent(Expander.EVENT_COLLAPSE); this.fireEvent(Expander.EVENT_COLLAPSE);
} }
}); }
break; );
case "click": break;
if (e) { case "click":
this.element.off(e + "." + this.getName()).on(e + "." + this.getName(), debounce((e) => { if (e) {
if (this.expander.element.__isMouseInBounds__(e)) { this.element.off(`${e}.${this.getName()}`).on(
if (this.isEnabled() && this.isValid() && this.expander.isEnabled() && this.expander.isValid()) { `${e}.${this.getName()}`,
toggle ? this._toggle() : this._popupView(); debounce(
if (this.isExpanded()) { e => {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.expander); if (this.expander.element.__isMouseInBounds__(e)) {
this.fireEvent(Expander.EVENT_EXPAND); if (
} else { this.isEnabled() &&
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.expander); this.isValid() &&
this.fireEvent(Expander.EVENT_COLLAPSE); this.expander.isEnabled() &&
this.expander.isValid()
) {
toggle ? this._toggle() : this._popupView();
if (this.isExpanded()) {
this.fireEvent(
Controller.EVENT_CHANGE,
BI.Events.EXPAND,
"",
this.expander
);
this.fireEvent(Expander.EVENT_EXPAND);
} else {
this.fireEvent(
Controller.EVENT_CHANGE,
BI.Events.COLLAPSE,
"",
this.expander
);
this.fireEvent(Expander.EVENT_COLLAPSE);
}
} }
} }
},
BI.EVENT_RESPONSE_TIME,
{
leading: true,
trailing: false,
} }
}, BI.EVENT_RESPONSE_TIME, { )
"leading": true, );
"trailing": false, }
})); break;
} default:
break; break;
default:
break;
} }
}); });
} }
@ -155,17 +205,23 @@ export class Expander extends Widget {
_assertPopupView() { _assertPopupView() {
const { value } = this.options; const { value } = this.options;
if (isNull(this.popupView)) { if (isNull(this.popupView)) {
this.popupView = createWidget(this.options.popup, { this.popupView = createWidget(
type: "bi.button_group", this.options.popup,
cls: "expander-popup", {
layouts: [{ type: ButtonGroup.xtype,
type: "bi.vertical", cls: "expander-popup",
hgap: 0, layouts: [
vgap: 0, {
}], type: VerticalLayout.xtype,
value, hgap: 0,
}, this); vgap: 0,
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args)=> { }
],
value,
},
this
);
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args); this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
// self.setValue(self.getValue()); // self.setValue(self.getValue());
@ -183,12 +239,10 @@ export class Expander extends Widget {
this._assertPopupView(); this._assertPopupView();
if (!this._rendered) { if (!this._rendered) {
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
scrolly: false, scrolly: false,
element: this, element: this,
items: [ items: [{ el: this.popupView }],
{ el: this.popupView }
],
}); });
this._rendered = true; this._rendered = true;
} }
@ -281,7 +335,7 @@ export class Expander extends Widget {
if (this.expander.getValue() === value) { if (this.expander.getValue() === value) {
return this.expander; return this.expander;
} }
return this.popupView && this.popupView.getNodeByValue(value); return this.popupView && this.popupView.getNodeByValue(value);
} }

85
src/base/combination/group.button.js

@ -1,9 +1,38 @@
import {
CenterLayout,
shortcut,
Widget,
Controller,
extend,
createWidget,
createWidgets,
each,
isFunction,
isKey,
isNotEmptyArray,
createItems,
isArray,
remove,
map,
stripEL,
makeArrayByArray,
clone,
deepClone,
formatEL,
isEmpty,
concat,
removeAt,
deepContains,
has,
any
} from "@/core";
import { TextButton } from "../single";
/** /**
* Created by GUY on 2015/6/26. * Created by GUY on 2015/6/26.
* @class BI.ButtonGroup * @class BI.ButtonGroup
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, createWidget, createWidgets, each, isFunction, isKey, isNotEmptyArray, createItems, isArray, remove, map, stripEL, makeArrayByArray, clone, deepClone, formatEL, isEmpty, concat, removeAt, deepContains, has, any } from "../../core";
@shortcut() @shortcut()
export class ButtonGroup extends Widget { export class ButtonGroup extends Widget {
@ -18,11 +47,13 @@ export class ButtonGroup extends Widget {
items: [], items: [],
value: "", value: "",
chooseType: BI.Selection.Single, chooseType: BI.Selection.Single,
layouts: [{ layouts: [
type: "bi.center", {
hgap: 0, type: CenterLayout.xtype,
vgap: 0, hgap: 0,
}], vgap: 0,
}
],
}); });
} }
@ -35,13 +66,17 @@ export class ButtonGroup extends Widget {
}); });
}); });
this.behaviors = behaviors; this.behaviors = behaviors;
const items = isFunction(optionsItems) ? this.__watch(optionsItems, (context, newValue) => { const items = isFunction(optionsItems)
this.populate(newValue); ? this.__watch(optionsItems, (context, newValue) => {
}) : optionsItems; this.populate(newValue);
})
: optionsItems;
this.populate(items); this.populate(items);
this.options.value = isFunction(value) ? this.__watch(value, (context, newValue) => { this.options.value = isFunction(value)
this.setValue(newValue); ? this.__watch(value, (context, newValue) => {
}) : value; this.setValue(newValue);
})
: value;
if (isKey(value) || isNotEmptyArray(value)) { if (isKey(value) || isNotEmptyArray(value)) {
this.setValue(value); this.setValue(value);
} }
@ -50,9 +85,11 @@ export class ButtonGroup extends Widget {
_createBtns(items) { _createBtns(items) {
let btns; let btns;
Widget.execWithContext(this, () => { Widget.execWithContext(this, () => {
btns = createWidgets(createItems(items, { btns = createWidgets(
type: "bi.text_button", createItems(items, {
})); type: TextButton.xtype,
})
);
}); });
return btns; return btns;
@ -99,13 +136,15 @@ export class ButtonGroup extends Widget {
const { layouts: optionsLayouts } = this.options; const { layouts: optionsLayouts } = this.options;
const layouts = isArray(optionsLayouts) ? optionsLayouts : [optionsLayouts]; const layouts = isArray(optionsLayouts) ? optionsLayouts : [optionsLayouts];
for (let i = layouts.length - 1; i > 0; i--) { for (let i = layouts.length - 1; i > 0; i--) {
btns = map(btns, (k, it) => extend({}, layouts[i], { btns = map(btns, (k, it) =>
items: [ extend({}, layouts[i], {
extend({}, layouts[i].el, { items: [
el: it, extend({}, layouts[i].el, {
}) el: it,
], })
})); ],
})
);
} }
return btns; return btns;
@ -146,7 +185,7 @@ export class ButtonGroup extends Widget {
_isSimpleLayout() { _isSimpleLayout() {
const { layouts, items } = this.options; const { layouts, items } = this.options;
return isArray(layouts) ? (layouts.length === 1 && !isArray(items[0])) : true; return isArray(layouts) ? layouts.length === 1 && !isArray(items[0]) : true;
} }
doBehavior() { doBehavior() {

55
src/base/combination/group.combo.js

@ -1,9 +1,23 @@
import { TextButton } from "../single";
import { ButtonTree } from "./tree.button";
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
isEmpty,
each,
formatEL,
clone,
createWidget
} from "@/core";
import { Combo } from "./combo";
/** /**
* Created by GUY on 2015/8/10. * Created by GUY on 2015/8/10.
*/ */
import { shortcut, Widget, Controller, extend, isEmpty, each, formatEL, clone, createWidget } from "../../core";
@shortcut() @shortcut()
export class ComboGroup extends Widget { export class ComboGroup extends Widget {
static xtype = "bi.combo_group"; static xtype = "bi.combo_group";
@ -22,16 +36,18 @@ export class ComboGroup extends Widget {
isNeedAdjustHeight: false, isNeedAdjustHeight: false,
isNeedAdjustWidth: false, isNeedAdjustWidth: false,
el: { type: "bi.text_button", text: "", value: "" }, el: { type: TextButton.xtype, text: "", value: "" },
items: [], items: [],
popup: { popup: {
el: { el: {
type: "bi.button_tree", type: ButtonTree.xtype,
chooseType: 0, chooseType: 0,
layouts: [{ layouts: [
type: "bi.vertical", {
}], type: VerticalLayout.xtype,
}
],
}, },
}, },
}); });
@ -42,7 +58,19 @@ export class ComboGroup extends Widget {
} }
_populate(item) { _populate(item) {
const { items, action, height, direction, isDefaultInit, isNeedAdjustHeight, isNeedAdjustWidth, adjustLength, popup, container, trigger } = this.options; const {
items,
action,
height,
direction,
isDefaultInit,
isNeedAdjustHeight,
isNeedAdjustWidth,
adjustLength,
popup,
container,
trigger,
} = this.options;
const children = items; const children = items;
if (isEmpty(children)) { if (isEmpty(children)) {
throw new Error("ComboGroup构造错误"); throw new Error("ComboGroup构造错误");
@ -65,7 +93,7 @@ export class ComboGroup extends Widget {
} }
}); });
this.combo = createWidget({ this.combo = createWidget({
type: "bi.combo", type: Combo.xtype,
element: this, element: this,
container, container,
height, height,
@ -77,9 +105,12 @@ export class ComboGroup extends Widget {
adjustLength, adjustLength,
el: item, el: item,
popup: extend({}, popup, { popup: extend({}, popup, {
el: extend({ el: extend(
items: children, {
}, popup.el), items: children,
},
popup.el
),
}), }),
}); });
this.combo.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.combo.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {

67
src/base/combination/group.virtual.js

@ -1,32 +1,54 @@
import { shortcut, Widget, Controller, extend, isFunction, isKey, isArray, map, stripEL, deepClone, formatEL, isEmpty, each, createWidget } from "../../core"; import {
CenterLayout,
shortcut,
Widget,
Controller,
extend,
isFunction,
isKey,
isArray,
map,
stripEL,
deepClone,
formatEL,
isEmpty,
each,
createWidget
} from "@/core";
@shortcut() @shortcut()
export class VirtualGroup extends Widget { export class VirtualGroup extends Widget {
static xtype = "bi.virtual_group"; static xtype = "bi.virtual_group";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
return extend(super._defaultConfig(...arguments), { return extend(super._defaultConfig(...arguments), {
baseCls: "bi-virtual-group", baseCls: "bi-virtual-group",
items: [], items: [],
layouts: [{ layouts: [
type: "bi.center", {
hgap: 0, type: CenterLayout.xtype,
vgap: 0, hgap: 0,
}], vgap: 0,
}
],
}); });
} }
render() { render() {
const { items: optionsItems, value } = this.options; const { items: optionsItems, value } = this.options;
const items = isFunction(optionsItems) ? this.__watch(optionsItems, (context, newValue) => { const items = isFunction(optionsItems)
this.populate(newValue); ? this.__watch(optionsItems, (context, newValue) => {
}) : optionsItems; this.populate(newValue);
})
: optionsItems;
this.populate(items); this.populate(items);
this.options.value = isFunction(value) ? this.__watch(value, (context, newValue) => { this.options.value = isFunction(value)
this.setValue(newValue); ? this.__watch(value, (context, newValue) => {
}) : value; this.setValue(newValue);
})
: value;
if (isKey(value)) { if (isKey(value)) {
this.setValue(value); this.setValue(value);
} }
@ -34,7 +56,7 @@ export class VirtualGroup extends Widget {
_packageBtns(items) { _packageBtns(items) {
const o = this.options; const o = this.options;
const map = this.buttonMap = {}; const map = (this.buttonMap = {});
const layouts = isArray(o.layouts) ? o.layouts : [o.layouts]; const layouts = isArray(o.layouts) ? o.layouts : [o.layouts];
for (let i = layouts.length - 1; i > 0; i--) { for (let i = layouts.length - 1; i > 0; i--) {
items = map(items, (k, it) => { items = map(items, (k, it) => {
@ -43,19 +65,22 @@ export class VirtualGroup extends Widget {
return extend({}, layouts[i], { return extend({}, layouts[i], {
items: [ items: [
extend({}, layouts[i].el, { extend({}, layouts[i].el, {
el: extend({ el: extend(
ref: (_ref) => { {
if (isKey(map[el.value])) { ref: _ref => {
map[el.value] = _ref; if (isKey(map[el.value])) {
} map[el.value] = _ref;
}
},
}, },
}, el), el
),
}) })
], ],
}); });
}); });
} }
return items; return items;
} }

2
src/base/combination/index.js

@ -9,4 +9,4 @@ export { Navigation } from "./navigation";
export { Searcher } from "./searcher"; export { Searcher } from "./searcher";
export { Switcher } from "./switcher"; export { Switcher } from "./switcher";
export { Tab } from "./tab"; export { Tab } from "./tab";
export { ButtonTree } from "./tree.button"; export { ButtonTree } from "./tree.button";

184
src/base/combination/loader.js

@ -1,3 +1,22 @@
import { ButtonGroup } from "./group.button";
import { LoadingBar } from "../single";
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
createWidget,
isEmpty,
nextTick,
bind,
isFunction,
isNotEmptyArray,
isNumber,
isObject,
each
} from "@/core";
/** /**
* 加载控件 * 加载控件
* *
@ -5,12 +24,11 @@
* @class BI.Loader * @class BI.Loader
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, createWidget, isEmpty, nextTick, bind, isFunction, isNotEmptyArray, isNumber, isObject, each } from "../../core";
@shortcut() @shortcut()
export class Loader extends Widget { export class Loader extends Widget {
static xtype = "bi.loader"; static xtype = "bi.loader";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
@ -26,7 +44,7 @@ export class Loader extends Widget {
// 下面是button_group的属性 // 下面是button_group的属性
el: { el: {
type: "bi.button_group", type: ButtonGroup.xtype,
}, },
items: [], items: [],
@ -45,32 +63,53 @@ export class Loader extends Widget {
_prevLoad() { _prevLoad() {
const o = this.options; const o = this.options;
this.prev.setLoading(); this.prev.setLoading();
o.itemsCreator.apply(this, [{ times: --this.times }, (...args) => { o.itemsCreator.apply(this, [
this.prev.setLoaded(); { times: --this.times },
this.prependItems.apply(this, args); (...args) => {
}]); this.prev.setLoaded();
this.prependItems.apply(this, args);
}
]);
} }
_nextLoad() { _nextLoad() {
const o = this.options; const o = this.options;
this.next.setLoading(); this.next.setLoading();
o.itemsCreator.apply(this, [{ times: ++this.times }, (...args) => { o.itemsCreator.apply(this, [
this.next.setLoaded(); { times: ++this.times },
this.addItems.apply(this, args); (...args) => {
}]); this.next.setLoaded();
this.addItems.apply(this, args);
}
]);
} }
render() { render() {
const { itemsCreator, prev, next, el, items: optionsItems, value, direction, logic, isDefaultInit } = this.options; const {
itemsCreator,
prev,
next,
el,
items: optionsItems,
value,
direction,
logic,
isDefaultInit,
} = this.options;
if (itemsCreator === false) { if (itemsCreator === false) {
prev = false; prev = false;
next = false; next = false;
} }
if (prev !== false) { if (prev !== false) {
this.prev = createWidget(extend({ this.prev = createWidget(
type: "bi.loading_bar", extend(
}, prev)); {
this.prev.on(Controller.EVENT_CHANGE, (type) => { type: LoadingBar.xtype,
},
prev
)
);
this.prev.on(Controller.EVENT_CHANGE, type => {
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this._prevLoad(); this._prevLoad();
} }
@ -78,13 +117,15 @@ export class Loader extends Widget {
} }
this.button_group = createWidget(el, { this.button_group = createWidget(el, {
type: "bi.button_group", type: ButtonGroup.xtype,
chooseType: 0, chooseType: 0,
items: optionsItems, items: optionsItems,
behaviors: {}, behaviors: {},
layouts: [{ layouts: [
type: "bi.vertical", {
}], type: VerticalLayout.xtype,
}
],
value, value,
}); });
this.button_group.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.button_group.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
@ -95,30 +136,58 @@ export class Loader extends Widget {
}); });
if (next !== false) { if (next !== false) {
this.next = createWidget(extend({ this.next = createWidget(
type: "bi.loading_bar", extend(
}, next)); {
this.next.on(Controller.EVENT_CHANGE, (type) => { type: LoadingBar.xtype,
},
next
)
);
this.next.on(Controller.EVENT_CHANGE, type => {
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this._nextLoad(); this._nextLoad();
} }
}); });
} }
createWidget(extend({ createWidget(
element: this, extend(
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({ {
scrolly: true, element: this,
}, logic, { },
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.prev, this.button_group, this.next), BI.LogicFactory.createLogic(
})))); BI.LogicFactory.createLogicTypeByDirection(direction),
extend(
isDefaultInit && isEmpty(optionsItems) && nextTick(bind(() => { {
isDefaultInit && isEmpty(optionsItems) && this._populate(); scrolly: true,
}, this)); },
const items = isFunction(optionsItems) ? this.__watch(optionsItems, (context, newValue) => { logic,
this.populate(newValue); {
}) : optionsItems; items: BI.LogicFactory.createLogicItemsByDirection(
direction,
this.prev,
this.button_group,
this.next
),
}
)
)
)
);
isDefaultInit &&
isEmpty(optionsItems) &&
nextTick(
bind(() => {
isDefaultInit && isEmpty(optionsItems) && this._populate();
}, this)
);
const items = isFunction(optionsItems)
? this.__watch(optionsItems, (context, newValue) => {
this.populate(newValue);
})
: optionsItems;
if (isNotEmptyArray(items)) { if (isNotEmptyArray(items)) {
this._populate(items); this._populate(items);
} }
@ -130,10 +199,12 @@ export class Loader extends Widget {
return this.count < count; return this.count < count;
} }
return !!hasPrev.apply(this, [{ return !!hasPrev.apply(this, [
times: this.times, {
count: this.count, times: this.times,
}]); count: this.count,
}
]);
} }
hasNext() { hasNext() {
@ -142,10 +213,12 @@ export class Loader extends Widget {
return this.count < count; return this.count < count;
} }
return !!hasNext.apply(this, [{ return !!hasNext.apply(this, [
times: this.times, {
count: this.count, times: this.times,
}]); count: this.count,
}
]);
} }
prependItems(items) { prependItems(items) {
@ -176,14 +249,17 @@ export class Loader extends Widget {
_populate(items) { _populate(items) {
const o = this.options; const o = this.options;
if (arguments.length === 0 && (isFunction(o.itemsCreator))) { if (arguments.length === 0 && isFunction(o.itemsCreator)) {
o.itemsCreator.apply(this, [{ times: 1 }, (...args) => { o.itemsCreator.apply(this, [
if (args.length === 0) { { times: 1 },
throw new Error("参数不能为空"); (...args) => {
if (args.length === 0) {
throw new Error("参数不能为空");
}
this.populate.apply(this, args);
o.onLoaded();
} }
this.populate.apply(this, args); ]);
o.onLoaded();
}]);
return false; return false;
} }
@ -205,7 +281,7 @@ export class Loader extends Widget {
this.prev.invisible(); this.prev.invisible();
} }
} }
return true; return true;
} }

48
src/base/combination/navigation.js

@ -1,12 +1,28 @@
import { ButtonGroup } from "./group.button";
import {
CardLayout,
shortcut,
Widget,
Controller,
extend,
createWidget,
bind,
ShowListener,
isFunction,
each,
nextTick,
isKey,
values
} from "@/core";
/** /**
* Created by GUY on 2015/6/26. * Created by GUY on 2015/6/26.
*/ */
import { shortcut, Widget, Controller, extend, createWidget, bind, ShowListener, isFunction, each, nextTick, isKey, values } from "../../core";
@shortcut() @shortcut()
export class Navigation extends Widget { export class Navigation extends Widget {
static xtype = "bi.navigation"; static xtype = "bi.navigation";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
@ -27,18 +43,25 @@ export class Navigation extends Widget {
render() { render() {
const { direction, logic, cardCreator, showIndex } = this.options; const { direction, logic, cardCreator, showIndex } = this.options;
this.tab = createWidget(this.options.tab, { type: "bi.button_group" }); this.tab = createWidget(this.options.tab, { type: ButtonGroup.xtype });
this.cardMap = {}; this.cardMap = {};
this.showIndex = 0; this.showIndex = 0;
this.layout = createWidget({ this.layout = createWidget({
type: "bi.card", type: CardLayout.xtype,
}); });
createWidget(extend({ createWidget(
element: this, extend(
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, { {
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tab, this.layout), element: this,
})))); },
BI.LogicFactory.createLogic(
BI.LogicFactory.createLogicTypeByDirection(direction),
extend({}, logic, {
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tab, this.layout),
})
)
)
);
new ShowListener({ new ShowListener({
eventObj: this.tab, eventObj: this.tab,
@ -48,7 +71,7 @@ export class Navigation extends Widget {
Widget.execWithContext(this, () => { Widget.execWithContext(this, () => {
this.cardMap[v] = cardCreator(v); this.cardMap[v] = cardCreator(v);
}); });
return this.cardMap[v]; return this.cardMap[v];
}, },
afterCardCreated: bind(this.afterCardCreated, this), afterCardCreated: bind(this.afterCardCreated, this),
@ -73,7 +96,7 @@ export class Navigation extends Widget {
const { single } = this.options; const { single } = this.options;
if (single === true) { if (single === true) {
each(this.cardMap, (name, card) => { each(this.cardMap, (name, card) => {
if (name !== (`${currCardName}`)) { if (name !== `${currCardName}`) {
this.layout.deleteCardByName(name); this.layout.deleteCardByName(name);
delete this.cardMap[name]; delete this.cardMap[name];
} }
@ -168,4 +191,3 @@ export class Navigation extends Widget {
super.destroy(arguments); super.destroy(arguments);
} }
} }

159
src/base/combination/searcher.js

@ -1,11 +1,7 @@
/** import { SearchEditor } from "@/widget/editor/editor.search.js";
* 搜索逻辑控件 import { SearcherView } from "../layer";
*
* Created by GUY on 2015/9/28.
* @class BI.Searcher
* @extends BI.Widget
*/
import { import {
VerticalLayout,
shortcut, shortcut,
Widget, Widget,
Controller, Controller,
@ -18,9 +14,17 @@ import {
nextTick, nextTick,
isEmptyString, isEmptyString,
isNull isNull
} from "../../core"; } from "@/core";
import { ButtonGroup } from "./group.button"; import { ButtonGroup } from "./group.button";
import { Maskers } from "../0.base"; import { Maskers } from "@/base/0.base";
/**
* 搜索逻辑控件
*
* Created by GUY on 2015/9/28.
* @class BI.Searcher
* @extends BI.Widget
*/
@shortcut() @shortcut()
export class Searcher extends Widget { export class Searcher extends Widget {
@ -54,15 +58,16 @@ export class Searcher extends Widget {
}, },
el: { el: {
type: "bi.search_editor", type: SearchEditor.xtype,
}, },
popup: { popup: {
type: "bi.searcher_view", type: SearcherView.xtype,
}, },
adapter: null, adapter: null,
masker: { // masker层 masker: {
// masker层
offset: {}, offset: {},
}, },
}); });
@ -72,11 +77,11 @@ export class Searcher extends Widget {
const { el, lgap, rgap, tgap, bgap, vgap, hgap, isDefaultInit } = this.options; const { el, lgap, rgap, tgap, bgap, vgap, hgap, isDefaultInit } = this.options;
this.editor = createWidget(el, { this.editor = createWidget(el, {
type: "bi.search_editor", type: SearchEditor.xtype,
}); });
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
element: this, element: this,
lgap, lgap,
rgap, rgap,
@ -86,30 +91,30 @@ export class Searcher extends Widget {
hgap, hgap,
items: [this.editor], items: [this.editor],
}); });
isDefaultInit && (this._assertPopupView()); isDefaultInit && this._assertPopupView();
const search = debounce(bind(this._search, this), BI.EVENT_RESPONSE_TIME, { const search = debounce(bind(this._search, this), BI.EVENT_RESPONSE_TIME, {
"leading": true, leading: true,
"trailing": false, trailing: false,
}); });
this.editor.on(Controller.EVENT_CHANGE, (type) => { this.editor.on(Controller.EVENT_CHANGE, type => {
switch (type) { switch (type) {
case BI.Events.STARTEDIT: case BI.Events.STARTEDIT:
this._startSearch(); this._startSearch();
break; break;
case BI.Events.EMPTY: case BI.Events.EMPTY:
this._stopSearch(); this._stopSearch();
break; break;
case BI.Events.CHANGE: case BI.Events.CHANGE:
search(); search();
break; break;
case BI.Events.PAUSE: case BI.Events.PAUSE:
if (endWith(this.getValue(), BI.BlankSplitChar)) { if (endWith(this.getValue(), BI.BlankSplitChar)) {
this._pauseSearch(); this._pauseSearch();
} }
break; break;
default: default:
break; break;
} }
}); });
} }
@ -118,8 +123,8 @@ export class Searcher extends Widget {
const { masker, popup, chooseType, isAutoSync, adapter } = this.options; const { masker, popup, chooseType, isAutoSync, adapter } = this.options;
if ((masker && !Maskers.has(this.getName())) || (masker === false && !this.popupView)) { if ((masker && !Maskers.has(this.getName())) || (masker === false && !this.popupView)) {
this.popupView = createWidget(popup, { this.popupView = createWidget(popup, {
type: "bi.searcher_view", type: SearcherView.xtype,
chooseType: chooseType, chooseType,
}); });
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args); this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
@ -127,18 +132,18 @@ export class Searcher extends Widget {
if (isAutoSync) { if (isAutoSync) {
const values = adapter && adapter.getValue(); const values = adapter && adapter.getValue();
switch (chooseType) { switch (chooseType) {
case ButtonGroup.CHOOSE_TYPE_SINGLE: case ButtonGroup.CHOOSE_TYPE_SINGLE:
adapter && adapter.setValue([obj.getValue()]); adapter && adapter.setValue([obj.getValue()]);
break; break;
case ButtonGroup.CHOOSE_TYPE_MULTI: case ButtonGroup.CHOOSE_TYPE_MULTI:
if (!obj.isSelected()) { if (!obj.isSelected()) {
adapter && adapter.setValue(deepWithout(values, obj.getValue())); adapter && adapter.setValue(deepWithout(values, obj.getValue()));
} }
values.push(obj.getValue()); values.push(obj.getValue());
adapter && adapter.setValue(values); adapter && adapter.setValue(values);
break; break;
default: default:
break; break;
} }
} }
this.fireEvent(Searcher.EVENT_CHANGE, value, obj); this.fireEvent(Searcher.EVENT_CHANGE, value, obj);
@ -149,10 +154,18 @@ export class Searcher extends Widget {
}); });
} }
if (masker && !Maskers.has(this.getName())) { if (masker && !Maskers.has(this.getName())) {
Maskers.create(this.getName(), adapter, extend({ Maskers.create(
container: this, this.getName(),
render: this.popupView, adapter,
}, masker), this); extend(
{
container: this,
render: this.popupView,
},
masker
),
this
);
} }
} }
@ -164,14 +177,14 @@ export class Searcher extends Widget {
this.popupView.startSearch && this.popupView.startSearch(); this.popupView.startSearch && this.popupView.startSearch();
// 搜索前先清空dom // 搜索前先清空dom
// BI.Maskers.get(this.getName()).empty(); // BI.Maskers.get(this.getName()).empty();
nextTick((name) => { nextTick(name => {
Maskers.show(name); Maskers.show(name);
}, this.getName()); }, this.getName());
} }
_pauseSearch() { _pauseSearch() {
this._stop = true; this._stop = true;
nextTick((name) => { nextTick(name => {
Maskers.hide(name); Maskers.hide(name);
}, this.getName()); }, this.getName());
if (this._isSearching === true) { if (this._isSearching === true) {
@ -201,7 +214,8 @@ export class Searcher extends Widget {
if (isAutoSearch) { if (isAutoSearch) {
const items = (adapter && ((adapter.getItems && adapter.getItems()) || adapter.attr("items"))) || []; const items = (adapter && ((adapter.getItems && adapter.getItems()) || adapter.attr("items"))) || [];
const finding = BI.Func.getSearchResult(items, keyword); const finding = BI.Func.getSearchResult(items, keyword);
const match = finding.match, find = finding.find; const match = finding.match,
find = finding.find;
this.popupView.populate(find, match, keyword); this.popupView.populate(find, match, keyword);
isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue()); isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue());
this.fireEvent(Searcher.EVENT_SEARCHING); this.fireEvent(Searcher.EVENT_SEARCHING);
@ -209,23 +223,26 @@ export class Searcher extends Widget {
return; return;
} }
this.popupView.loading && this.popupView.loading(); this.popupView.loading && this.popupView.loading();
onSearch({ onSearch(
times: 1, {
keyword: keyword, times: 1,
selectedValues: adapter && adapter.getValue(), keyword,
}, (searchResult, matchResult, ...arg) => { selectedValues: adapter && adapter.getValue(),
if (!this._stop && keyword === this.editor.getValue()) { },
const args = [searchResult, matchResult, ...arg]; (searchResult, matchResult, ...arg) => {
if (args.length > 0) { if (!this._stop && keyword === this.editor.getValue()) {
args.push(keyword); const args = [searchResult, matchResult, ...arg];
if (args.length > 0) {
args.push(keyword);
}
Maskers.show(this.getName());
this.popupView.populate.apply(this.popupView, args);
isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue());
this.popupView.loaded && this.popupView.loaded();
this.fireEvent(Searcher.EVENT_SEARCHING);
} }
Maskers.show(this.getName());
this.popupView.populate.apply(this.popupView, args);
isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue());
this.popupView.loaded && this.popupView.loaded();
this.fireEvent(Searcher.EVENT_SEARCHING);
} }
}); );
} }
_getLastSearchKeyword() { _getLastSearchKeyword() {
@ -251,7 +268,7 @@ export class Searcher extends Widget {
} }
stopSearch() { stopSearch() {
this._stopSearch();// 先停止搜索,然后再去设置editor为空 this._stopSearch(); // 先停止搜索,然后再去设置editor为空
// important:停止搜索必须退出编辑状态,这里必须加上try(input框不显示时blur会抛异常) // important:停止搜索必须退出编辑状态,这里必须加上try(input框不显示时blur会抛异常)
try { try {
this.editor.blur(); this.editor.blur();

163
src/base/combination/switcher.js

@ -1,3 +1,18 @@
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
nextTick,
createWidget,
each,
debounce,
isNull
} from "@/core";
import { ButtonGroup } from "./group.button";
import { Maskers } from "@/base/0.base";
/** /**
* *
* 切换显示或隐藏面板 * 切换显示或隐藏面板
@ -6,13 +21,11 @@
* @class BI.Switcher * @class BI.Switcher
* @extends BI.Widget * @extends BI.Widget
*/ */
import { shortcut, Widget, Controller, extend, nextTick, createWidget, each, debounce, isNull } from "../../core";
import { Maskers } from "../0.base";
@shortcut() @shortcut()
export class Switcher extends Widget { export class Switcher extends Widget {
static xtype = "bi.switcher"; static xtype = "bi.switcher";
static EVENT_EXPAND = "EVENT_EXPAND"; static EVENT_EXPAND = "EVENT_EXPAND";
static EVENT_COLLAPSE = "EVENT_COLLAPSE"; static EVENT_COLLAPSE = "EVENT_COLLAPSE";
static EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE"; static EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE";
@ -68,24 +81,25 @@ export class Switcher extends Widget {
} }
}); });
this.element.hover(() => { this.element.hover(
if (this.isEnabled() && this.switcher.isEnabled()) { () => {
this.element.addClass(hoverClass); if (this.isEnabled() && this.switcher.isEnabled()) {
} this.element.addClass(hoverClass);
}, () => { }
if (this.isEnabled() && this.switcher.isEnabled()) { },
this.element.removeClass(hoverClass); () => {
if (this.isEnabled() && this.switcher.isEnabled()) {
this.element.removeClass(hoverClass);
}
} }
}); );
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
scrolly: false, scrolly: false,
element: this, element: this,
items: [ items: [{ el: this.switcher }],
{ el: this.switcher }
],
}); });
isDefaultInit && (this._assertPopupView()); isDefaultInit && this._assertPopupView();
} }
_toggle() { _toggle() {
@ -104,42 +118,62 @@ export class Switcher extends Widget {
const evs = this.options.trigger.split(","); const evs = this.options.trigger.split(",");
each(evs, (i, e) => { each(evs, (i, e) => {
switch (e) { switch (e) {
case "hover": case "hover":
this.element[e]((e) => { this.element[e](
e => {
if (this.isEnabled() && this.switcher.isEnabled()) { if (this.isEnabled() && this.switcher.isEnabled()) {
this._popupView(); this._popupView();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.switcher); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.switcher);
this.fireEvent(Switcher.EVENT_EXPAND); this.fireEvent(Switcher.EVENT_EXPAND);
} }
}, () => { },
() => {
if (this.isEnabled() && this.switcher.isEnabled() && toggle) { if (this.isEnabled() && this.switcher.isEnabled() && toggle) {
this._hideView(); this._hideView();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.switcher); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.switcher);
this.fireEvent(Switcher.EVENT_COLLAPSE); this.fireEvent(Switcher.EVENT_COLLAPSE);
} }
}); }
break; );
default : break;
if (e) { default:
this.element.off(e + "." + this.getName()).on(e + "." + this.getName(), debounce((e) => { if (e) {
if (this.switcher.element.__isMouseInBounds__(e)) { this.element.off(`${e}.${this.getName()}`).on(
if (this.isEnabled() && this.switcher.isEnabled()) { `${e}.${this.getName()}`,
toggle ? this._toggle() : this._popupView(); debounce(
if (this.isExpanded()) { e => {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.EXPAND, "", this.switcher); if (this.switcher.element.__isMouseInBounds__(e)) {
this.fireEvent(Switcher.EVENT_EXPAND); if (this.isEnabled() && this.switcher.isEnabled()) {
} else { toggle ? this._toggle() : this._popupView();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", this.switcher); if (this.isExpanded()) {
this.fireEvent(Switcher.EVENT_COLLAPSE); this.fireEvent(
Controller.EVENT_CHANGE,
BI.Events.EXPAND,
"",
this.switcher
);
this.fireEvent(Switcher.EVENT_EXPAND);
} else {
this.fireEvent(
Controller.EVENT_CHANGE,
BI.Events.COLLAPSE,
"",
this.switcher
);
this.fireEvent(Switcher.EVENT_COLLAPSE);
}
} }
} }
},
BI.EVENT_RESPONSE_TIME,
{
leading: true,
trailing: false,
} }
}, BI.EVENT_RESPONSE_TIME, { )
"leading": true, );
"trailing": false, }
})); break;
}
break;
} }
}); });
} }
@ -153,18 +187,24 @@ export class Switcher extends Widget {
_assertPopupView() { _assertPopupView() {
const { popup, adapter, masker, value, direction } = this.options; const { popup, adapter, masker, value, direction } = this.options;
if (!this._created) { if (!this._created) {
this.popupView = createWidget(popup, { this.popupView = createWidget(
type: "bi.button_group", popup,
element: adapter && Maskers.create(this.getName(), adapter, extend({ container: this }, masker)), {
cls: "switcher-popup", type: ButtonGroup.xtype,
layouts: [{ element: adapter && Maskers.create(this.getName(), adapter, extend({ container: this }, masker)),
type: "bi.vertical", cls: "switcher-popup",
hgap: 0, layouts: [
vgap: 0, {
}], type: VerticalLayout.xtype,
value, hgap: 0,
}, this); vgap: 0,
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { }
],
value,
},
this
);
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args); this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this.fireEvent(Switcher.EVENT_CHANGE, value, obj); this.fireEvent(Switcher.EVENT_CHANGE, value, obj);
@ -172,12 +212,10 @@ export class Switcher extends Widget {
}); });
if (direction !== BI.Direction.Custom && !adapter) { if (direction !== BI.Direction.Custom && !adapter) {
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
scrolly: false, scrolly: false,
element: this, element: this,
items: [ items: [{ el: this.popupView }],
{ el: this.popupView }
],
}); });
} }
this._created = true; this._created = true;
@ -190,9 +228,9 @@ export class Switcher extends Widget {
_hideView() { _hideView() {
this.fireEvent(Switcher.EVENT_BEFORE_HIDEVIEW); this.fireEvent(Switcher.EVENT_BEFORE_HIDEVIEW);
const { adapter, switcherClass } = this.options; const { adapter, switcherClass } = this.options;
adapter ? Maskers.hide(this.getName()) : (this.popupView && this.popupView.setVisible(false)); adapter ? Maskers.hide(this.getName()) : this.popupView && this.popupView.setVisible(false);
nextTick(() => { nextTick(() => {
adapter ? Maskers.hide(this.getName()) : (this.popupView && this.popupView.setVisible(false)); adapter ? Maskers.hide(this.getName()) : this.popupView && this.popupView.setVisible(false);
this.element.removeClass(switcherClass); this.element.removeClass(switcherClass);
this.fireEvent(Switcher.EVENT_AFTER_HIDEVIEW); this.fireEvent(Switcher.EVENT_AFTER_HIDEVIEW);
}); });
@ -203,7 +241,7 @@ export class Switcher extends Widget {
this._assertPopupView(); this._assertPopupView();
this.fireEvent(Switcher.EVENT_BEFORE_POPUPVIEW); this.fireEvent(Switcher.EVENT_BEFORE_POPUPVIEW);
adapter ? Maskers.show(this.getName()) : this.popupView.setVisible(true); adapter ? Maskers.show(this.getName()) : this.popupView.setVisible(true);
nextTick((name) => { nextTick(name => {
adapter ? Maskers.show(name) : this.popupView.setVisible(true); adapter ? Maskers.show(name) : this.popupView.setVisible(true);
this.element.addClass(switcherClass); this.element.addClass(switcherClass);
this.fireEvent(Switcher.EVENT_AFTER_POPUPVIEW); this.fireEvent(Switcher.EVENT_AFTER_POPUPVIEW);
@ -248,8 +286,11 @@ export class Switcher extends Widget {
} }
isViewVisible() { isViewVisible() {
return this.isEnabled() && this.switcher.isEnabled() && return (
(this.options.adapter ? Maskers.isVisible(this.getName()) : (this.popupView && this.popupView.isVisible())); this.isEnabled() &&
this.switcher.isEnabled() &&
(this.options.adapter ? Maskers.isVisible(this.getName()) : this.popupView && this.popupView.isVisible())
);
} }
isExpanded() { isExpanded() {
@ -290,7 +331,7 @@ export class Switcher extends Widget {
if (this.switcher.getValue() === value) { if (this.switcher.getValue() === value) {
return this.switcher; return this.switcher;
} }
return this.popupView && this.popupView.getNodeByValue(value); return this.popupView && this.popupView.getNodeByValue(value);
} }

55
src/base/combination/tab.js

@ -1,7 +1,23 @@
import { ButtonGroup } from "./group.button";
import {
CardLayout,
shortcut,
Widget,
Controller,
ShowListener,
extend,
createWidget,
isObject,
each,
isFunction,
contains,
any,
isEqual
} from "@/core";
/** /**
* Created by GUY on 2015/6/26. * Created by GUY on 2015/6/26.
*/ */
import { shortcut, Widget, Controller, ShowListener, extend, createWidget, isObject, each, isFunction, contains, any, isEqual } from "../../core";
@shortcut() @shortcut()
export class Tab extends Widget { export class Tab extends Widget {
@ -19,9 +35,7 @@ export class Tab extends Widget {
}, },
showIndex: false, showIndex: false,
tab: false, tab: false,
cardCreator: (v) => { cardCreator: v => createWidget(),
return createWidget();
},
keepAlives: [], keepAlives: [],
}); });
} }
@ -29,38 +43,46 @@ export class Tab extends Widget {
render() { render() {
const { tab, direction, logic, cardCreator } = this.options; const { tab, direction, logic, cardCreator } = this.options;
if (isObject(tab)) { if (isObject(tab)) {
this.tab = createWidget(this.options.tab, { type: "bi.button_group" }); this.tab = createWidget(this.options.tab, { type: ButtonGroup.xtype });
this.tab.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => { this.tab.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args); this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
}); });
} }
this.cardMap = {}; this.cardMap = {};
this.layout = createWidget({ this.layout = createWidget({
type: "bi.card", type: CardLayout.xtype,
}); });
createWidget(extend({ createWidget(
element: this, extend(
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, { {
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tab, this.layout), element: this,
})))); },
BI.LogicFactory.createLogic(
BI.LogicFactory.createLogicTypeByDirection(direction),
extend({}, logic, {
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tab, this.layout),
})
)
)
);
const listener = new ShowListener({ const listener = new ShowListener({
eventObj: this.tab, eventObj: this.tab,
cardLayout: this.layout, cardLayout: this.layout,
cardCreator: (v) => { cardCreator: v => {
Widget.execWithContext(this, () => { Widget.execWithContext(this, () => {
this.cardMap[v] = cardCreator(v); this.cardMap[v] = cardCreator(v);
}); });
return this.cardMap[v]; return this.cardMap[v];
}, },
afterCardShow: (v) => { afterCardShow: v => {
this._deleteOtherCards(v); this._deleteOtherCards(v);
this.curr = v; this.curr = v;
}, },
}); });
listener.on(ShowListener.EVENT_CHANGE, (value) => { listener.on(ShowListener.EVENT_CHANGE, value => {
this.fireEvent(Tab.EVENT_CHANGE, value, this); this.fireEvent(Tab.EVENT_CHANGE, value, this);
}); });
} }
@ -69,7 +91,7 @@ export class Tab extends Widget {
const { single } = this.options; const { single } = this.options;
if (single === true) { if (single === true) {
each(this.cardMap, (name, card) => { each(this.cardMap, (name, card) => {
if (name !== (currCardName + "") && this._keepAlive(name) !== true) { if (name !== `${currCardName}` && this._keepAlive(name) !== true) {
this.layout.deleteCardByName(name); this.layout.deleteCardByName(name);
delete this.cardMap[name]; delete this.cardMap[name];
} }
@ -122,7 +144,7 @@ export class Tab extends Widget {
removeTab(cardname) { removeTab(cardname) {
any(this.cardMap, (name, card) => { any(this.cardMap, (name, card) => {
if (isEqual(name, (cardname + ""))) { if (isEqual(name, `${cardname}`)) {
this.layout.deleteCardByName(name); this.layout.deleteCardByName(name);
delete this.cardMap[name]; delete this.cardMap[name];
@ -179,5 +201,4 @@ export class Tab extends Widget {
this.cardMap = {}; this.cardMap = {};
super.destroy(arguments); super.destroy(arguments);
} }
} }

9
src/base/combination/tree.button.js

@ -1,10 +1,11 @@
import { ButtonGroup } from "./group.button";
import { shortcut, Widget, extend, isArray, each, isFunction, deepContains, concat, any, contains } from "@/core";
/** /**
* Created by GUY on 2015/8/10. * Created by GUY on 2015/8/10.
* @class BI.ButtonTree * @class BI.ButtonTree
* @extends BI.ButtonGroup * @extends BI.ButtonGroup
*/ */
import { shortcut, Widget, extend, isArray, each, isFunction, deepContains, concat, any, contains } from "../../core";
import { ButtonGroup } from "./group.button";
@shortcut() @shortcut()
export class ButtonTree extends ButtonGroup { export class ButtonTree extends ButtonGroup {
@ -119,7 +120,7 @@ export class ButtonTree extends ButtonGroup {
each(this.buttons, (i, item) => { each(this.buttons, (i, item) => {
if (item.isEnabled() && !isFunction(item.setSelected)) { if (item.isEnabled() && !isFunction(item.setSelected)) {
btns = btns.concat(item.getNotSelectedButtons()); btns = btns.concat(item.getNotSelectedButtons());
return; return;
} }
if (item.isSelected && !item.isSelected()) { if (item.isSelected && !item.isSelected()) {
@ -167,7 +168,7 @@ export class ButtonTree extends ButtonGroup {
if (item.isEnabled()) { if (item.isEnabled()) {
if (item.attr("id") === id) { if (item.attr("id") === id) {
node = item; node = item;
return true; return true;
} else if (isFunction(item.getNodeById)) { } else if (isFunction(item.getNodeById)) {
node = item.getNodeById(id); node = item.getNodeById(id);

57
src/base/context.js

@ -1,47 +1,40 @@
/** import { shortcut, Widget, createWidget, Controller } from "@/core";
* 表示当前对象
*
* Created by GUY on 2015/9/7.
* @class BI.EL
* @extends BI.Widget
*/
BI.Context = BI.inherit(BI.Widget, {
props: {
context: "",
watch: {},
el: {},
items: [],
},
render: function () { @shortcut()
var self = this, o = this.options; export class Context extends Widget {
static xtype = "bi.context";
props = { context: "", watch: {}, el: {}, items: [] };
render() {
const self = this,
o = this.options;
if (o.context) { if (o.context) {
this.context = BI.useContext(o.context); this.context = BI.useContext(o.context);
} }
this.widget = BI.createWidget((o.items[0] || o.el)(this.context), { this.widget = createWidget((o.items[0] || o.el)(this.context), {
element: this, element: this,
}); });
this.widget.on(BI.Controller.EVENT_CHANGE, function () { this.widget.on(Controller.EVENT_CHANGE, function () {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); self.fireEvent(Controller.EVENT_CHANGE, arguments);
}); });
}, }
__initWatch: function () { __initWatch() {
BI.Context.superclass.__initWatch.call(this); super.__initWatch.call(this);
var o = this.options; const o = this.options;
BI.watch(this.context, o.context, o.watch); BI.watch(this.context, o.context, o.watch);
}, }
setValue: function (v) { setValue(v) {
this.widget.setValue(v); this.widget.setValue(v);
}, }
getValue: function () { getValue() {
return this.widget.getValue(); return this.widget.getValue();
}, }
populate: function () { populate() {
this.widget.populate.apply(this, arguments); this.widget.populate.apply(this, arguments);
}, }
}); }
BI.shortcut("bi.context", BI.Context);

48
src/base/el.js

@ -1,38 +1,36 @@
/** import { shortcut, Widget, extend, createWidget, Controller } from "@/core";
* 表示当前对象
* @shortcut()
* Created by GUY on 2015/9/7. export class EL extends Widget {
* @class BI.EL static xtype = "bi.el";
* @extends BI.Widget
*/ _defaultConfig() {
BI.EL = BI.inherit(BI.Widget, { return extend(super._defaultConfig(...arguments), {
_defaultConfig: function () {
return BI.extend(BI.EL.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-el", baseCls: "bi-el",
el: {}, el: {},
}); });
}, }
render: function () { render() {
var self = this, o = this.options; const self = this,
this.ele = BI.createWidget(o.el, { o = this.options;
this.ele = createWidget(o.el, {
element: this, element: this,
}); });
this.ele.on(BI.Controller.EVENT_CHANGE, function () { this.ele.on(Controller.EVENT_CHANGE, function () {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments); self.fireEvent(Controller.EVENT_CHANGE, arguments);
}); });
}, }
setValue: function (v) { setValue(v) {
this.ele.setValue(v); this.ele.setValue(v);
}, }
getValue: function () { getValue() {
return this.ele.getValue(); return this.ele.getValue();
}, }
populate: function () { populate() {
this.ele.populate.apply(this, arguments); this.ele.populate.apply(this, arguments);
}, }
}); }
BI.shortcut("bi.el", BI.EL);

175
src/base/foundation/message.js

@ -3,26 +3,26 @@
* 弹出提示消息框用于模拟阻塞操作通过回调函数实现 * 弹出提示消息框用于模拟阻塞操作通过回调函数实现
* @class BI.Msg * @class BI.Msg
*/ */
import { Widget, isString, isNull, isFunction, createWidget, remove, each } from "../../core" import { Widget, isString, isNull, isFunction, createWidget, remove, each } from "../../core";
export const Msg = ((() => { export const Msg = (() => {
let $mask, $pop; let $mask, $pop;
let messageShows = []; const messageShows = [];
let toastStack = []; const toastStack = [];
return { return {
alert: function (title, message, callback) { alert (title, message, callback) {
this._show(false, title, message, callback); this._show(false, title, message, callback);
}, },
confirm: function (title, message, callback) { confirm (title, message, callback) {
this._show(true, title, message, callback); this._show(true, title, message, callback);
}, },
prompt: function (title, message, value, callback, min_width) { prompt (title, message, value, callback, min_width) {
// BI.Msg.prompt(title, message, value, callback, min_width); // BI.Msg.prompt(title, message, value, callback, min_width);
}, },
toast: function (message, options, context) { toast (message, options, context) {
isString(options) && (options = { level: options }); isString(options) && (options = { level: options });
options = options || {}; options = options || {};
context = context || Widget._renderEngine.createElement("body"); context = context || Widget._renderEngine.createElement("body");
@ -32,69 +32,81 @@ export const Msg = ((() => {
const toast = createWidget({ const toast = createWidget({
type: "bi.toast", type: "bi.toast",
cls: "bi-message-animate bi-message-leave", cls: "bi-message-animate bi-message-leave",
level: level, level,
autoClose: autoClose, autoClose,
closable: options.closable, closable: options.closable,
text: message, text: message,
listeners: [{ listeners: [
eventName: BI.Toast.EVENT_DESTORY, {
action: function () { eventName: BI.Toast.EVENT_DESTORY,
remove(toastStack, toast.element); action () {
let _height = BI.SIZE_CONSANTS.TOAST_TOP; remove(toastStack, toast.element);
each(toastStack, function (i, element) { let _height = BI.SIZE_CONSANTS.TOAST_TOP;
element.css({ "top": _height }); each(toastStack, (i, element) => {
_height += element.outerHeight() + 10; element.css({ top: _height });
}); _height += element.outerHeight() + 10;
callback(); });
}, callback();
}], },
}
],
}); });
let height = BI.SIZE_CONSANTS.TOAST_TOP; let height = BI.SIZE_CONSANTS.TOAST_TOP;
each(toastStack, function (i, element) { each(toastStack, (i, element) => {
height += element.outerHeight() + 10; height += element.outerHeight() + 10;
}); });
createWidget({ createWidget({
type: "bi.absolute", type: "bi.absolute",
element: context, element: context,
items: [{ items: [
el: toast, {
left: "50%", el: toast,
top: height, left: "50%",
}], top: height,
}
],
}); });
toastStack.push(toast.element); toastStack.push(toast.element);
toast.element.css({ "margin-left": -1 * toast.element.outerWidth() / 2 }); toast.element.css({ "margin-left": (-1 * toast.element.outerWidth()) / 2 });
toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); toast.element.removeClass("bi-message-leave").addClass("bi-message-enter");
autoClose && BI.delay(function () { autoClose &&
toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); BI.delay(() => {
toast.destroy?.(); toast.element.removeClass("bi-message-enter").addClass("bi-message-leave");
}, 5000); toast.destroy?.();
}, 5000);
return function () { return function () {
toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); toast.element.removeClass("bi-message-enter").addClass("bi-message-leave");
toast.destroy?.(); toast.destroy?.();
}; };
}, },
_show: function (hasCancel, title, message, callback) { _show (hasCancel, title, message, callback) {
isNull($mask) && ($mask = Widget._renderEngine.createElement("<div class=\"bi-z-index-mask\">").css({ isNull($mask) &&
position: "absolute", ($mask = Widget._renderEngine
zIndex: BI.zIndex_tip - 2, .createElement("<div class=\"bi-z-index-mask\">")
top: 0, .css({
left: 0, position: "absolute",
right: 0, zIndex: BI.zIndex_tip - 2,
bottom: 0, top: 0,
opacity: 0.5, left: 0,
}).appendTo("body")); right: 0,
$pop = Widget._renderEngine.createElement("<div class=\"bi-message-depend\">").css({ bottom: 0,
position: "absolute", opacity: 0.5,
zIndex: BI.zIndex_tip - 1, })
top: 0, .appendTo("body"));
left: 0, $pop = Widget._renderEngine
right: 0, .createElement("<div class=\"bi-message-depend\">")
bottom: 0, .css({
}).appendTo("body"); position: "absolute",
function close () { zIndex: BI.zIndex_tip - 1,
top: 0,
left: 0,
right: 0,
bottom: 0,
})
.appendTo("body");
function close() {
messageShows[messageShows.length - 1].destroy(); messageShows[messageShows.length - 1].destroy();
messageShows.pop(); messageShows.pop();
if (messageShows.length === 0) { if (messageShows.length === 0) {
@ -102,14 +114,14 @@ export const Msg = ((() => {
$mask = null; $mask = null;
} }
} }
let controlItems = []; const controlItems = [];
if (hasCancel === true) { if (hasCancel === true) {
controlItems.push({ controlItems.push({
el: { el: {
type: "bi.button", type: "bi.button",
text: BI.i18nText("BI-Basic_Cancel"), text: BI.i18nText("BI-Basic_Cancel"),
level: "ignore", level: "ignore",
handler: function () { handler () {
close(); close();
if (isFunction(callback)) { if (isFunction(callback)) {
callback.apply(null, [false]); callback.apply(null, [false]);
@ -122,7 +134,7 @@ export const Msg = ((() => {
el: { el: {
type: "bi.button", type: "bi.button",
text: BI.i18nText("BI-Basic_OK"), text: BI.i18nText("BI-Basic_OK"),
handler: function () { handler () {
close(); close();
if (isFunction(callback)) { if (isFunction(callback)) {
callback.apply(null, [true]); callback.apply(null, [true]);
@ -139,8 +151,8 @@ export const Msg = ((() => {
attributes: { attributes: {
tabIndex: 1, tabIndex: 1,
}, },
mounted: function () { mounted () {
this.element.keyup(function (e) { this.element.keyup(e => {
if (e.keyCode === BI.KeyCode.ENTER) { if (e.keyCode === BI.KeyCode.ENTER) {
close(); close();
if (isFunction(callback)) { if (isFunction(callback)) {
@ -157,9 +169,7 @@ export const Msg = ((() => {
}); });
try { try {
this.element.focus(); this.element.focus();
} catch (e) { } catch (e) {}
}
}, },
cls: "bi-card", cls: "bi-card",
items: { items: {
@ -183,7 +193,7 @@ export const Msg = ((() => {
type: "bi.icon_button", type: "bi.icon_button",
cls: "bi-message-close close-font", cls: "bi-message-close close-font",
// height: 50, // height: 50,
handler: function () { handler () {
close(); close();
if (isFunction(callback)) { if (isFunction(callback)) {
callback.apply(null, [false]); callback.apply(null, [false]);
@ -197,29 +207,32 @@ export const Msg = ((() => {
height: 40, height: 40,
}, },
center: { center: {
el: BI.isPlainObject(message) ? message : { el: BI.isPlainObject(message)
type: "bi.label", ? message
vgap: 10, : {
hgap: 20, type: "bi.label",
whiteSpace: "normal", vgap: 10,
text: message, hgap: 20,
}, whiteSpace: "normal",
text: message,
},
}, },
south: { south: {
el: { el: {
type: "bi.absolute", type: "bi.absolute",
items: [{ items: [
el: { {
type: "bi.right_vertical_adapt", el: {
lgap: 10, type: "bi.right_vertical_adapt",
items: controlItems, lgap: 10,
}, items: controlItems,
top: 0, },
left: 20, top: 0,
right: 20, left: 20,
bottom: 0, right: 20,
}], bottom: 0,
}
],
}, },
height: 44, height: 44,
}, },
@ -233,4 +246,4 @@ export const Msg = ((() => {
messageShows[messageShows.length] = createWidget(conf); messageShows[messageShows.length] = createWidget(conf);
}, },
}; };
})()); })();

164
src/base/grid/grid.js

@ -1,3 +1,22 @@
import {
VerticalLayout,
AbsoluteLayout,
Widget,
shortcut,
extend,
emptyFn,
debounce,
_lazyCreateWidget,
isFunction,
each,
isNumber,
ScalingCellSizeAndPositionManager,
clamp,
isEmpty,
nextTick
} from "@/core";
import { Label } from "../single";
/** /**
* GridView * GridView
* *
@ -5,7 +24,7 @@
* @class BI.GridView * @class BI.GridView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, emptyFn, debounce, _lazyCreateWidget, isFunction, each, isNumber, ScalingCellSizeAndPositionManager, clamp, isEmpty, nextTick } from "../../core";
@shortcut() @shortcut()
export class GridView extends Widget { export class GridView extends Widget {
_defaultConfig() { _defaultConfig() {
@ -19,7 +38,7 @@ export class GridView extends Widget {
overflowX: true, overflowX: true,
overflowY: true, overflowY: true,
el: { el: {
type: "bi.vertical", type: VerticalLayout.xtype,
}, },
overscanColumnCount: 0, overscanColumnCount: 0,
overscanRowCount: 0, overscanRowCount: 0,
@ -48,7 +67,7 @@ export class GridView extends Widget {
this._scrollLock = false; this._scrollLock = false;
}, 1000 / 60); }, 1000 / 60);
this.container = _lazyCreateWidget({ this.container = _lazyCreateWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
}); });
this.element.scroll(() => { this.element.scroll(() => {
if (this._scrollLock === true) { if (this._scrollLock === true) {
@ -64,7 +83,8 @@ export class GridView extends Widget {
}); });
// 兼容一下 // 兼容一下
let scrollable = o.scrollable; let scrollable = o.scrollable;
const scrollx = o.scrollx, scrolly = o.scrolly; const scrollx = o.scrollx,
scrolly = o.scrolly;
if (overflowX === false) { if (overflowX === false) {
if (overflowY === false) { if (overflowY === false) {
scrollable = false; scrollable = false;
@ -77,16 +97,18 @@ export class GridView extends Widget {
} }
} }
_lazyCreateWidget(el, { _lazyCreateWidget(el, {
type: "bi.vertical", type: VerticalLayout.xtype,
element: this, element: this,
scrollable, scrollable,
scrolly, scrolly,
scrollx, scrollx,
items: [this.container], items: [this.container],
}); });
o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items)
this.populate(newValue); ? this.__watch(o.items, (context, newValue) => {
}) : o.items; this.populate(newValue);
})
: o.items;
if (o.items.length > 0) { if (o.items.length > 0) {
this._calculateSizeAndPositionData(); this._calculateSizeAndPositionData();
this._populate(); this._populate();
@ -109,7 +131,15 @@ export class GridView extends Widget {
} }
_calculateSizeAndPositionData() { _calculateSizeAndPositionData() {
const { columnCount, items, rowCount, columnWidthGetter, estimatedColumnSize, rowHeightGetter, estimatedRowSize } = this.options; const {
columnCount,
items,
rowCount,
columnWidthGetter,
estimatedColumnSize,
rowHeightGetter,
estimatedRowSize,
} = this.options;
this.rowCount = 0; this.rowCount = 0;
this.columnCount = 0; this.columnCount = 0;
if (isNumber(columnCount)) { if (isNumber(columnCount)) {
@ -122,8 +152,16 @@ export class GridView extends Widget {
} else { } else {
this.rowCount = items.length; this.rowCount = items.length;
} }
this._columnSizeAndPositionManager = new ScalingCellSizeAndPositionManager(this.columnCount, columnWidthGetter, estimatedColumnSize); this._columnSizeAndPositionManager = new ScalingCellSizeAndPositionManager(
this._rowSizeAndPositionManager = new ScalingCellSizeAndPositionManager(this.rowCount, rowHeightGetter, estimatedRowSize); this.columnCount,
columnWidthGetter,
estimatedColumnSize
);
this._rowSizeAndPositionManager = new ScalingCellSizeAndPositionManager(
this.rowCount,
rowHeightGetter,
estimatedRowSize
);
} }
_getOverscanIndices(cellCount, overscanCellsCount, startIndex, stopIndex) { _getOverscanIndices(cellCount, overscanCellsCount, startIndex, stopIndex) {
@ -138,19 +176,30 @@ export class GridView extends Widget {
const { itemFormatter, items } = this.options; const { itemFormatter, items } = this.options;
const width = o.width, height = o.height, scrollLeft = clamp(o.scrollLeft, 0, this._getMaxScrollLeft()), const width = o.width,
height = o.height,
scrollLeft = clamp(o.scrollLeft, 0, this._getMaxScrollLeft()),
scrollTop = clamp(o.scrollTop, 0, this._getMaxScrollTop()), scrollTop = clamp(o.scrollTop, 0, this._getMaxScrollTop()),
overscanColumnCount = o.overscanColumnCount, overscanRowCount = o.overscanRowCount; overscanColumnCount = o.overscanColumnCount,
overscanRowCount = o.overscanRowCount;
if (height > 0 && width > 0) { if (height > 0 && width > 0) {
const visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange(width, scrollLeft); const visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange(width, scrollLeft);
const visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange(height, scrollTop); const visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange(height, scrollTop);
const renderedCells = [], renderedKeys = {}, renderedWidgets = {}; const renderedCells = [],
let minX = this._getMaxScrollLeft(), minY = this._getMaxScrollTop(), maxX = 0, maxY = 0; renderedKeys = {},
renderedWidgets = {};
let minX = this._getMaxScrollLeft(),
minY = this._getMaxScrollTop(),
maxX = 0,
maxY = 0;
// 没有可见的单元格就干掉所有渲染过的 // 没有可见的单元格就干掉所有渲染过的
if (!isEmpty(visibleColumnIndices) && !isEmpty(visibleRowIndices)) { if (!isEmpty(visibleColumnIndices) && !isEmpty(visibleRowIndices)) {
const horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(width, scrollLeft); const horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(
width,
scrollLeft
);
const verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop); const verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop);
this._renderedColumnStartIndex = visibleColumnIndices.start; this._renderedColumnStartIndex = visibleColumnIndices.start;
@ -158,9 +207,19 @@ export class GridView extends Widget {
this._renderedRowStartIndex = visibleRowIndices.start; this._renderedRowStartIndex = visibleRowIndices.start;
this._renderedRowStopIndex = visibleRowIndices.stop; this._renderedRowStopIndex = visibleRowIndices.stop;
const overscanColumnIndices = this._getOverscanIndices(this.columnCount, overscanColumnCount, this._renderedColumnStartIndex, this._renderedColumnStopIndex); const overscanColumnIndices = this._getOverscanIndices(
this.columnCount,
overscanColumnCount,
this._renderedColumnStartIndex,
this._renderedColumnStopIndex
);
const overscanRowIndices = this._getOverscanIndices(this.rowCount, overscanRowCount, this._renderedRowStartIndex, this._renderedRowStopIndex); const overscanRowIndices = this._getOverscanIndices(
this.rowCount,
overscanRowCount,
this._renderedRowStartIndex,
this._renderedRowStopIndex
);
const columnStartIndex = overscanColumnIndices.overscanStartIndex; const columnStartIndex = overscanColumnIndices.overscanStartIndex;
const columnStopIndex = overscanColumnIndices.overscanStopIndex; const columnStopIndex = overscanColumnIndices.overscanStopIndex;
@ -177,7 +236,12 @@ export class GridView extends Widget {
const bottom = maxRowDatum.offset + verticalOffsetAdjustment + maxRowDatum.size; const bottom = maxRowDatum.offset + verticalOffsetAdjustment + maxRowDatum.size;
const right = maxColumnDatum.offset + horizontalOffsetAdjustment + maxColumnDatum.size; const right = maxColumnDatum.offset + horizontalOffsetAdjustment + maxColumnDatum.size;
// 如果滚动的区间并没有超出渲染的范围 // 如果滚动的区间并没有超出渲染的范围
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) { if (
top >= this.renderRange.minY &&
bottom <= this.renderRange.maxY &&
left >= this.renderRange.minX &&
right <= this.renderRange.maxX
) {
return; return;
} }
@ -195,23 +259,38 @@ export class GridView extends Widget {
this.renderedCells[index].el.setWidth(columnDatum.size); this.renderedCells[index].el.setWidth(columnDatum.size);
this.renderedCells[index].el.setHeight(rowDatum.size); this.renderedCells[index].el.setHeight(rowDatum.size);
// 这里只使用px // 这里只使用px
this.renderedCells[index].el.element.css("left", `${columnDatum.offset + horizontalOffsetAdjustment}px`); this.renderedCells[index].el.element.css(
this.renderedCells[index].el.element.css("top", `${rowDatum.offset + verticalOffsetAdjustment}px`); "left",
`${columnDatum.offset + horizontalOffsetAdjustment}px`
);
this.renderedCells[index].el.element.css(
"top",
`${rowDatum.offset + verticalOffsetAdjustment}px`
);
child = this.renderedCells[index].el; child = this.renderedCells[index].el;
renderedCells.push(this.renderedCells[index]); renderedCells.push(this.renderedCells[index]);
} else { } else {
const item = itemFormatter(items[rowIndex][columnIndex], rowIndex, columnIndex); const item = itemFormatter(items[rowIndex][columnIndex], rowIndex, columnIndex);
child = _lazyCreateWidget(extend({ child = _lazyCreateWidget(
type: "bi.label", extend(
width: columnDatum.size, {
height: rowDatum.size, type: Label.xtype,
}, item, { width: columnDatum.size,
cls: `${item.cls || ""} grid-cell${rowIndex === 0 ? " first-row" : ""}${columnIndex === 0 ? " first-col" : ""}`, height: rowDatum.size,
_rowIndex: rowIndex, },
_columnIndex: columnIndex, item,
_left: columnDatum.offset + horizontalOffsetAdjustment, {
_top: rowDatum.offset + verticalOffsetAdjustment, cls: `${item.cls || ""} grid-cell${rowIndex === 0 ? " first-row" : ""}${
}), this); columnIndex === 0 ? " first-col" : ""
}`,
_rowIndex: rowIndex,
_columnIndex: columnIndex,
_left: columnDatum.offset + horizontalOffsetAdjustment,
_top: rowDatum.offset + verticalOffsetAdjustment,
}
),
this
);
renderedCells.push({ renderedCells.push({
el: child, el: child,
left: `${columnDatum.offset + horizontalOffsetAdjustment}px`, left: `${columnDatum.offset + horizontalOffsetAdjustment}px`,
@ -233,7 +312,9 @@ export class GridView extends Widget {
} }
} }
// 已存在的, 需要添加的和需要删除的 // 已存在的, 需要添加的和需要删除的
const existSet = {}, addSet = {}, deleteArray = []; const existSet = {},
addSet = {},
deleteArray = [];
each(renderedKeys, (i, key) => { each(renderedKeys, (i, key) => {
if (this.renderedKeys[i]) { if (this.renderedKeys[i]) {
existSet[i] = key; existSet[i] = key;
@ -281,7 +362,7 @@ export class GridView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "x") { if (scrollable === true || scrollable === "xy" || scrollable === "x") {
return true; return true;
} }
return false; return false;
} }
@ -298,16 +379,22 @@ export class GridView extends Widget {
if (scrollable === true || scrollable === "xy" || scrollable === "y") { if (scrollable === true || scrollable === "xy" || scrollable === "y") {
return true; return true;
} }
return false; return false;
} }
_getMaxScrollLeft() { _getMaxScrollLeft() {
return Math.max(0, this._getContainerWidth() - this.options.width + (this._isOverflowX() ? BI.DOM.getScrollWidth() : 0)); return Math.max(
0,
this._getContainerWidth() - this.options.width + (this._isOverflowX() ? BI.DOM.getScrollWidth() : 0)
);
} }
_getMaxScrollTop() { _getMaxScrollTop() {
return Math.max(0, this._getContainerHeight() - this.options.height + (this._isOverflowY() ? BI.DOM.getScrollWidth() : 0)); return Math.max(
0,
this._getContainerHeight() - this.options.height + (this._isOverflowY() ? BI.DOM.getScrollWidth() : 0)
);
} }
_getContainerWidth() { _getContainerWidth() {
@ -333,8 +420,7 @@ export class GridView extends Widget {
try { try {
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
this.element.scrollLeft(scrollLeft); this.element.scrollLeft(scrollLeft);
} catch (e) { } catch (e) {}
}
this._calculateChildrenToRender(); this._calculateChildrenToRender();
} }

9
src/base/index.js

@ -29,11 +29,4 @@ export * from "./combination";
export * from "./layer"; export * from "./layer";
export * from "./list"; export * from "./list";
export * from "./single"; export * from "./single";
export { export { Pane, GridView, Pager, Msg, CollectionView, CustomTree };
Pane,
GridView,
Pager,
Msg,
CollectionView,
CustomTree
};

457
src/base/layer/layer.drawer.js

@ -1,236 +1,253 @@
import { HTapeLayout, AbsoluteLayout, Layout, VerticalLayout, Widget, shortcut, isPlainObject, extend } from "@/core";
import { Label, IconButton } from "../single";
/** /**
* Popover弹出层 * Popover弹出层
* @class BI.Popover * @class BI.Popover
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, isPlainObject, extend } from "../../core";
@shortcut() @shortcut()
export class Drawer extends Widget { export class Drawer extends Widget {
SIZE = { SIZE = {
SMALL: "small", SMALL: "small",
NORMAL: "normal", NORMAL: "normal",
BIG: "big", BIG: "big",
} };
props = { props = {
baseCls: "bi-drawer bi-card", baseCls: "bi-drawer bi-card",
size: "normal", size: "normal",
placement: "right", // top/bottom/left/right placement: "right", // top/bottom/left/right
header: null, header: null,
headerHeight: 40, headerHeight: 40,
body: null, body: null,
closable: true, // BI-40839 是否显示右上角的关闭按钮 closable: true, // BI-40839 是否显示右上角的关闭按钮
bodyHgap: 20, bodyHgap: 20,
bodyTgap: 10, bodyTgap: 10,
bodyBgap: 10, bodyBgap: 10,
} };
static xtype = "bi.drawer"; static xtype = "bi.drawer";
static EVENT_CLOSE = "EVENT_CLOSE"; static EVENT_CLOSE = "EVENT_CLOSE";
static EVENT_OPEN = "EVENT_OPEN"; static EVENT_OPEN = "EVENT_OPEN";
_getSuitableSize() { _getSuitableSize() {
const { size, height, placement, width } = this.options; const { size, height, placement, width } = this.options;
let sizeValue = 0; let sizeValue = 0;
switch (size) { switch (size) {
case "big": case "big":
sizeValue = 736; sizeValue = 736;
break; break;
case "small": case "small":
sizeValue = 200; sizeValue = 200;
break; break;
case "normal": case "normal":
default: default:
sizeValue = 378; sizeValue = 378;
break; break;
} }
if (placement === "top" || placement === "bottom") { if (placement === "top" || placement === "bottom") {
return { return {
height: height || sizeValue, height: height || sizeValue,
}; };
} }
if (placement === "left" || placement === "right") { if (placement === "left" || placement === "right") {
return { return {
width: width || sizeValue, width: width || sizeValue,
}; };
} }
} }
render() { render() {
const { header, headerHeight, closable, body, bodyHgap, bodyTgap, bodyBgap } = this.options; const { header, headerHeight, closable, body, bodyHgap, bodyTgap, bodyBgap } = this.options;
const items = [{ const items = [
el: { {
type: "bi.htape", el: {
cls: "bi-message-title bi-header-background", type: HTapeLayout.xtype,
items: [{ cls: "bi-message-title bi-header-background",
type: "bi.absolute", items: [
items: [{ {
el: isPlainObject(header) ? extend({}, header, { type: AbsoluteLayout.xtype,
extraCls: "bi-font-bold", items: [
}) : { {
type: "bi.label", el: isPlainObject(header)
cls: "bi-font-bold", ? extend({}, header, {
height: headerHeight, extraCls: "bi-font-bold",
text: header, })
title: header, : {
textAlign: "left", type: Label.xtype,
}, cls: "bi-font-bold",
left: 20, height: headerHeight,
top: 0, text: header,
right: 0, title: header,
bottom: 0, textAlign: "left",
}], },
}, { left: 20,
el: closable ? { top: 0,
type: "bi.icon_button", right: 0,
cls: "bi-message-close close-font", bottom: 0,
height: headerHeight, }
handler: () => { ],
this.close(); },
}, {
} : { el: closable
type: "bi.layout", ? {
}, type: IconButton.xtype,
width: 56, cls: "bi-message-close close-font",
}], height: headerHeight,
height: headerHeight, handler: () => {
}, this.close();
height: headerHeight, },
}, { }
el: { : {
type: "bi.vertical", type: Layout.xtype,
scrolly: true, },
cls: "drawer-body", width: 56,
ref: _ref => { }
this.body = _ref; ],
}, height: headerHeight,
items: [{ },
el: body, height: headerHeight,
}], },
}, {
hgap: bodyHgap, el: {
tgap: bodyTgap, type: VerticalLayout.xtype,
bgap: bodyBgap, scrolly: true,
}]; cls: "drawer-body",
ref: _ref => {
this.body = _ref;
},
items: [
{
el: body,
}
],
},
hgap: bodyHgap,
tgap: bodyTgap,
bgap: bodyBgap,
}
];
return extend({ return extend(
type: "bi.vtape", {
items, type: "bi.vtape",
}, this._getSuitableSize()); items,
} },
mounted() { this._getSuitableSize()
const { placement } = this.options; );
switch (placement) { }
case "right": mounted() {
this.element.css({ const { placement } = this.options;
top: 0, switch (placement) {
left: "100%", case "right":
bottom: 0, this.element.css({
}); top: 0,
break; left: "100%",
case "left": bottom: 0,
this.element.css({ });
top: 0, break;
right: "100%", case "left":
bottom: 0, this.element.css({
}); top: 0,
break; right: "100%",
case "top": bottom: 0,
this.element.css({ });
left: 0, break;
right: 0, case "top":
bottom: "100%", this.element.css({
}); left: 0,
break; right: 0,
case "bottom": bottom: "100%",
this.element.css({ });
left: 0, break;
right: 0, case "bottom":
top: "100%", this.element.css({
}); left: 0,
break; right: 0,
default: top: "100%",
break; });
} break;
} default:
break;
}
}
show(callback) { show(callback) {
const { placement } = this.options; const { placement } = this.options;
requestAnimationFrame(() => { requestAnimationFrame(() => {
const size = this._getSuitableSize(); const size = this._getSuitableSize();
switch (placement) { switch (placement) {
case "right": case "right":
this.element.css({ this.element.css({
left: `calc(100% - ${size.width}px)`, left: `calc(100% - ${size.width}px)`,
}); });
break; break;
case "left": case "left":
this.element.css({ this.element.css({
right: `calc(100% - ${size.width}px)`, right: `calc(100% - ${size.width}px)`,
}); });
break; break;
case "top": case "top":
this.element.css({ this.element.css({
bottom: `calc(100% - ${size.height}px)`, bottom: `calc(100% - ${size.height}px)`,
}); });
break; break;
case "bottom": case "bottom":
this.element.css({ this.element.css({
top: `calc(100% - ${size.height}px)`, top: `calc(100% - ${size.height}px)`,
}); });
break; break;
default: default:
break; break;
} }
callback && callback(); callback && callback();
}); });
} }
hide(callback) { hide(callback) {
const { placement } = this.options; const { placement } = this.options;
requestAnimationFrame(() => { requestAnimationFrame(() => {
switch (placement) { switch (placement) {
case "right": case "right":
this.element.css({ this.element.css({
left: "100%", left: "100%",
}); });
break; break;
case "left": case "left":
this.element.css({ this.element.css({
right: "100%", right: "100%",
}); });
break; break;
case "top": case "top":
this.element.css({ this.element.css({
bottom: "100%", bottom: "100%",
}); });
break; break;
case "bottom": case "bottom":
this.element.css({ this.element.css({
top: "100%", top: "100%",
}); });
break; break;
default: default:
break; break;
} }
setTimeout(callback, 300); setTimeout(callback, 300);
}); });
} }
open() { open() {
this.show(() => { this.show(() => {
this.fireEvent(Drawer.EVENT_OPEN); this.fireEvent(Drawer.EVENT_OPEN);
}); });
} }
close() { close() {
this.hide(() => { this.hide(() => {
this.fireEvent(Drawer.EVENT_CLOSE); this.fireEvent(Drawer.EVENT_CLOSE);
}); });
} }
setZindex(zindex) { setZindex(zindex) {
this.element.css({ "z-index": zindex }); this.element.css({ "z-index": zindex });
} }
destroyed() { destroyed() {}
}
} }

552
src/base/layer/layer.popover.js

@ -1,279 +1,331 @@
import {
HTapeLayout,
AbsoluteLayout,
VerticalLayout,
Widget,
shortcut,
clamp,
isPlainObject,
extend,
isNotNull
} from "@/core";
import { Label, IconButton, Button } from "../single";
/** /**
* Popover弹出层 * Popover弹出层
* @class BI.Popover * @class BI.Popover
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, clamp, isPlainObject, extend, isNotNull } from "../../core";
@shortcut() @shortcut()
export class Popover extends Widget { export class Popover extends Widget {
_constant = { _constant = {
SIZE: { SIZE: {
SMALL: "small", SMALL: "small",
NORMAL: "normal", NORMAL: "normal",
BIG: "big", BIG: "big",
}, },
MAX_HEIGHT: 600, MAX_HEIGHT: 600,
} };
props() {
return {
baseCls: "bi-popover bi-card bi-border-radius",
size: "normal", // small, normal, big
logic: {
dynamic: false,
},
header: null,
headerHeight: 40,
body: null,
footer: null,
footerHeight: 44,
closable: true, // BI-40839 是否显示右上角的关闭按钮
bodyHgap: BI.SIZE_CONSANTS.H_GAP_SIZE,
bodyTgap: BI.SIZE_CONSANTS.V_GAP_SIZE,
};
}
static xtype = "bi.popover"; props() {
static EVENT_CLOSE = "EVENT_CLOSE"; return {
static EVENT_OPEN = "EVENT_OPEN"; baseCls: "bi-popover bi-card bi-border-radius",
static EVENT_CANCEL = "EVENT_CANCEL"; size: "normal", // small, normal, big
static EVENT_CONFIRM = "EVENT_CONFIRM"; logic: {
dynamic: false,
},
header: null,
headerHeight: 40,
body: null,
footer: null,
footerHeight: 44,
closable: true, // BI-40839 是否显示右上角的关闭按钮
bodyHgap: BI.SIZE_CONSANTS.H_GAP_SIZE,
bodyTgap: BI.SIZE_CONSANTS.V_GAP_SIZE,
};
}
render() { static xtype = "bi.popover";
// var self = this; static EVENT_CLOSE = "EVENT_CLOSE";
const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options; static EVENT_OPEN = "EVENT_OPEN";
const c = this._constant; static EVENT_CANCEL = "EVENT_CANCEL";
this.startX = 0; static EVENT_CONFIRM = "EVENT_CONFIRM";
this.startY = 0;
const size = this._calculateSize();
this.tracker = new BI.MouseMoveTracker((deltaX, deltaY) => {
const W = Widget._renderEngine.createElement("body").width();
const H = Widget._renderEngine.createElement("body").height();
this.startX += deltaX;
this.startY += deltaY;
this.element.css({
left: `${clamp(this.startX, 0, W - this.element.width())}px`,
top: `${clamp(this.startY, 0, H - this.element.height())}px`,
});
// BI-12134 没有什么特别好的方法
BI.Resizers._resize({
target: this.element[0],
});
}, () => {
this.tracker.releaseMouseMoves();
}, _global);
const items = [{
el: {
type: "bi.htape",
cls: "bi-message-title bi-header-background",
items: [{
el: {
type: "bi.absolute",
ref: _ref => {
this.dragger = _ref;
},
items: [{
el: isPlainObject(header) ? extend({}, header, {
extraCls: "bi-font-bold",
}) : {
type: "bi.label",
cls: "bi-font-bold",
height: headerHeight,
text: header,
title: header,
textAlign: "left",
},
top: 0,
bottom: 0,
left: BI.SIZE_CONSANTS.H_GAP_SIZE,
right: closable ? 0 : BI.SIZE_CONSANTS.H_GAP_SIZE,
}],
},
}, closable ? {
el: {
type: "bi.icon_button",
cls: "bi-message-close close-font",
height: headerHeight,
handler: () => {
this.close();
},
},
width: 56,
} : null],
height: headerHeight,
},
height: headerHeight,
}, logic.dynamic ? {
el: {
type: "bi.vertical",
scrolly: true,
cls: "popover-body",
ref: _ref => {
this.body = _ref;
},
css: {
"max-height": this._getSuitableBodyHeight(c.MAX_HEIGHT - headerHeight - (footer ? footerHeight : 0) - bodyTgap),
"min-height": this._getSuitableBodyHeight(size.height - headerHeight - (footer ? footerHeight : 0) - bodyTgap),
},
items: [{
el: body,
}],
hgap: bodyHgap,
tgap: bodyTgap,
},
} : {
el: {
type: "bi.absolute",
items: [{
el: body,
left: bodyHgap,
top: bodyTgap,
right: bodyHgap,
bottom: 0,
}],
},
}];
if (footer) {
items.push({
el: {
type: "bi.absolute",
items: [{
el: footer,
left: BI.SIZE_CONSANTS.H_GAP_SIZE,
top: 0,
right: BI.SIZE_CONSANTS.H_GAP_SIZE,
bottom: 0,
}],
height: footerHeight,
},
height: footerHeight,
});
}
return extend({ render() {
items, // var self = this;
width: this._getSuitableWidth(size.width), const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options;
}, logic.dynamic ? { const c = this._constant;
type: "bi.vertical", this.startX = 0;
scrolly: false, this.startY = 0;
} : { const size = this._calculateSize();
type: "bi.vtape", this.tracker = new BI.MouseMoveTracker(
height: this._getSuitableHeight(size.height), (deltaX, deltaY) => {
}); const W = Widget._renderEngine.createElement("body").width();
} const H = Widget._renderEngine.createElement("body").height();
// mounted之后绑定事件 this.startX += deltaX;
mounted() { this.startY += deltaY;
this.dragger.element.mousedown(e => { this.element.css({
if (this.options.draggable !== false) { left: `${clamp(this.startX, 0, W - this.element.width())}px`,
this.startX = this.element[0].offsetLeft; top: `${clamp(this.startY, 0, H - this.element.height())}px`,
this.startY = this.element[0].offsetTop; });
this.tracker.captureMouseMoves(e); // BI-12134 没有什么特别好的方法
} BI.Resizers._resize({
}); target: this.element[0],
} });
},
() => {
this.tracker.releaseMouseMoves();
},
_global
);
const items = [
{
el: {
type: HTapeLayout.xtype,
cls: "bi-message-title bi-header-background",
items: [
{
el: {
type: AbsoluteLayout.xtype,
ref: _ref => {
this.dragger = _ref;
},
items: [
{
el: isPlainObject(header)
? extend({}, header, {
extraCls: "bi-font-bold",
})
: {
type: Label.xtype,
cls: "bi-font-bold",
height: headerHeight,
text: header,
title: header,
textAlign: "left",
},
top: 0,
bottom: 0,
left: BI.SIZE_CONSANTS.H_GAP_SIZE,
right: closable ? 0 : BI.SIZE_CONSANTS.H_GAP_SIZE,
}
],
},
},
closable
? {
el: {
type: IconButton.xtype,
cls: "bi-message-close close-font",
height: headerHeight,
handler: () => {
this.close();
},
},
width: 56,
}
: null
],
height: headerHeight,
},
height: headerHeight,
},
logic.dynamic
? {
el: {
type: VerticalLayout.xtype,
scrolly: true,
cls: "popover-body",
ref: _ref => {
this.body = _ref;
},
css: {
"max-height": this._getSuitableBodyHeight(
c.MAX_HEIGHT - headerHeight - (footer ? footerHeight : 0) - bodyTgap
),
"min-height": this._getSuitableBodyHeight(
size.height - headerHeight - (footer ? footerHeight : 0) - bodyTgap
),
},
items: [
{
el: body,
}
],
hgap: bodyHgap,
tgap: bodyTgap,
},
}
: {
el: {
type: AbsoluteLayout.xtype,
items: [
{
el: body,
left: bodyHgap,
top: bodyTgap,
right: bodyHgap,
bottom: 0,
}
],
},
}
];
if (footer) {
items.push({
el: {
type: AbsoluteLayout.xtype,
items: [
{
el: footer,
left: BI.SIZE_CONSANTS.H_GAP_SIZE,
top: 0,
right: BI.SIZE_CONSANTS.H_GAP_SIZE,
bottom: 0,
}
],
height: footerHeight,
},
height: footerHeight,
});
}
_getSuitableBodyHeight(height) { return extend(
const { headerHeight, footer, footerHeight, bodyTgap } = this.options; {
items,
width: this._getSuitableWidth(size.width),
},
logic.dynamic
? {
type: VerticalLayout.xtype,
scrolly: false,
}
: {
type: "bi.vtape",
height: this._getSuitableHeight(size.height),
}
);
}
// mounted之后绑定事件
mounted() {
this.dragger.element.mousedown(e => {
if (this.options.draggable !== false) {
this.startX = this.element[0].offsetLeft;
this.startY = this.element[0].offsetTop;
this.tracker.captureMouseMoves(e);
}
});
}
return clamp(height, 0, Widget._renderEngine.createElement("body")[0].clientHeight - headerHeight - (footer ? footerHeight : 0) - bodyTgap); _getSuitableBodyHeight(height) {
} const { headerHeight, footer, footerHeight, bodyTgap } = this.options;
_getSuitableHeight(height) { return clamp(
return clamp(height, 0, Widget._renderEngine.createElement("body")[0].clientHeight); height,
} 0,
Widget._renderEngine.createElement("body")[0].clientHeight -
headerHeight -
(footer ? footerHeight : 0) -
bodyTgap
);
}
_getSuitableWidth(width) { _getSuitableHeight(height) {
return clamp(width, 0, Widget._renderEngine.createElement("body").width()); return clamp(height, 0, Widget._renderEngine.createElement("body")[0].clientHeight);
} }
_calculateSize() { _getSuitableWidth(width) {
const { size, width, height } = this.options; return clamp(width, 0, Widget._renderEngine.createElement("body").width());
const sizeValue = {}; }
if (isNotNull(size)) {
switch (size) {
case this._constant.SIZE.SMALL:
sizeValue.width = 450;
sizeValue.height = 200;
sizeValue.type = "small";
break;
case this._constant.SIZE.BIG:
sizeValue.width = 900;
sizeValue.height = 500;
sizeValue.type = "big";
break;
default:
sizeValue.width = 550;
sizeValue.height = 500;
sizeValue.type = "default";
}
}
return { _calculateSize() {
width: width || sizeValue.width, const { size, width, height } = this.options;
height: height || sizeValue.height, const sizeValue = {};
type: sizeValue.type || "default", if (isNotNull(size)) {
}; switch (size) {
} case this._constant.SIZE.SMALL:
setDraggable(b) { sizeValue.width = 450;
this.options.draggable = b; sizeValue.height = 200;
} sizeValue.type = "small";
break;
case this._constant.SIZE.BIG:
sizeValue.width = 900;
sizeValue.height = 500;
sizeValue.type = "big";
break;
default:
sizeValue.width = 550;
sizeValue.height = 500;
sizeValue.type = "default";
}
}
hide() { return {
width: width || sizeValue.width,
height: height || sizeValue.height,
type: sizeValue.type || "default",
};
}
setDraggable(b) {
this.options.draggable = b;
}
} hide() {}
open() { open() {
this.show(); this.show();
this.fireEvent(Popover.EVENT_OPEN, arguments); this.fireEvent(Popover.EVENT_OPEN, arguments);
} }
close() { close() {
this.hide(); this.hide();
this.fireEvent(Popover.EVENT_CLOSE, arguments); this.fireEvent(Popover.EVENT_CLOSE, arguments);
} }
setZindex(zindex) { setZindex(zindex) {
this.element.css({ "z-index": zindex }); this.element.css({ "z-index": zindex });
} }
} }
@shortcut() @shortcut()
export class BarPopover extends Popover { export class BarPopover extends Popover {
static xtype = "bi.bar_popover"; static xtype = "bi.bar_popover";
_defaultConfig() { _defaultConfig() {
return extend(super._defaultConfig(...arguments), { return extend(super._defaultConfig(...arguments), {
btns: [BI.i18nText("BI-Basic_OK"), BI.i18nText("BI-Basic_Cancel")], btns: [BI.i18nText("BI-Basic_OK"), BI.i18nText("BI-Basic_Cancel")],
}); });
} }
beforeCreate() { beforeCreate() {
const { footer, warningTitle } = this.options; const { footer, warningTitle } = this.options;
footer || (this.options.footer = { footer ||
type: "bi.right_vertical_adapt", (this.options.footer = {
lgap: 10, type: "bi.right_vertical_adapt",
items: [{ lgap: 10,
type: "bi.button", items: [
text: this.options.btns[1], {
value: 1, type: Button.xtype,
level: "ignore", text: this.options.btns[1],
handler: v => { value: 1,
this.fireEvent(Popover.EVENT_CANCEL, v); level: "ignore",
this.close(v); handler: v => {
}, this.fireEvent(Popover.EVENT_CANCEL, v);
}, { this.close(v);
type: "bi.button", },
text: this.options.btns[0], },
warningTitle, {
value: 0, type: Button.xtype,
handler: v => { text: this.options.btns[0],
this.fireEvent(Popover.EVENT_CONFIRM, v); warningTitle,
this.close(v); value: 0,
}, handler: v => {
}], this.fireEvent(Popover.EVENT_CONFIRM, v);
}); this.close(v);
} },
}
],
});
}
} }

875
src/base/layer/layer.popup.js

@ -1,432 +1,511 @@
import { ButtonGroup } from "../combination/group.button";
import {
VerticalLayout,
AbsoluteLayout,
Layout,
CenterLayout,
Widget,
shortcut,
extend,
Controller,
createWidget,
createItems,
clamp
} from "@/core";
/** /**
* 下拉框弹出层, zIndex在1000w * 下拉框弹出层, zIndex在1000w
* @class BI.PopupView * @class BI.PopupView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, Controller, createWidget, createItems, clamp } from "../../core";
@shortcut() @shortcut()
export class PopupView extends Widget { export class PopupView extends Widget {
_const = { _const = {
TRIANGLE_LENGTH: 12, TRIANGLE_LENGTH: 12,
} };
static xtype = "bi.popup_view"; static xtype = "bi.popup_view";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig(props) { _defaultConfig(props) {
return extend(super._defaultConfig(...arguments), { return extend(super._defaultConfig(...arguments), {
_baseCls: `bi-popup-view${props.primary ? " bi-primary" : ""}`, _baseCls: `bi-popup-view${props.primary ? " bi-primary" : ""}`,
// 品牌色 // 品牌色
primary: false, primary: false,
maxWidth: "auto", maxWidth: "auto",
minWidth: 100, minWidth: 100,
// maxHeight: 200, // maxHeight: 200,
minHeight: 24, minHeight: 24,
lgap: 0, lgap: 0,
rgap: 0, rgap: 0,
tgap: 0, tgap: 0,
bgap: 0, bgap: 0,
vgap: 0, vgap: 0,
hgap: 0, hgap: 0,
innerVgap: 0, innerVgap: 0,
innerHgap: 0, innerHgap: 0,
showArrow: false, showArrow: false,
direction: BI.Direction.Top, // 工具栏的方向 direction: BI.Direction.Top, // 工具栏的方向
stopEvent: false, // 是否停止mousedown、mouseup事件 stopEvent: false, // 是否停止mousedown、mouseup事件
stopPropagation: false, // 是否停止mousedown、mouseup向上冒泡 stopPropagation: false, // 是否停止mousedown、mouseup向上冒泡
logic: { logic: {
dynamic: true, dynamic: true,
}, },
tool: false, // 自定义工具栏 tool: false, // 自定义工具栏
tabs: [], // 导航栏 tabs: [], // 导航栏
buttons: [], // toolbar栏 buttons: [], // toolbar栏
el: { el: {
type: "bi.button_group", type: ButtonGroup.xtype,
items: [], items: [],
chooseType: 0, chooseType: 0,
behaviors: {}, behaviors: {},
layouts: [{ layouts: [
type: "bi.vertical", {
}], type: VerticalLayout.xtype,
}, }
}); ],
} },
render() { });
const { minWidth, maxWidth, stopPropagation, stopEvent, }
direction, logic, lgap, rgap, tgap, bgap, vgap, hgap, primary, showArrow } = this.options; render() {
function fn (e) { const {
e.stopPropagation(); minWidth,
} maxWidth,
function stop (e) { stopPropagation,
e.stopEvent(); stopEvent,
direction,
logic,
lgap,
rgap,
tgap,
bgap,
vgap,
hgap,
primary,
showArrow,
} = this.options;
function fn(e) {
e.stopPropagation();
}
function stop(e) {
e.stopEvent();
return false; return false;
} }
this.element.css({ this.element
"z-index": BI.zIndex_popup, .css({
"min-width": BI.pixFormat(minWidth), "z-index": BI.zIndex_popup,
"max-width": BI.pixFormat(maxWidth), "min-width": BI.pixFormat(minWidth),
}).bind({ click: fn }); "max-width": BI.pixFormat(maxWidth),
})
.bind({ click: fn });
this.element.bind("mousewheel", fn); this.element.bind("mousewheel", fn);
stopPropagation && this.element.bind({ mousedown: fn, mouseup: fn, mouseover: fn }); stopPropagation && this.element.bind({ mousedown: fn, mouseup: fn, mouseover: fn });
stopEvent && this.element.bind({ mousedown: stop, mouseup: stop, mouseover: stop }); stopEvent && this.element.bind({ mousedown: stop, mouseup: stop, mouseover: stop });
this.tool = this._createTool(); this.tool = this._createTool();
this.tab = this._createTab(); this.tab = this._createTab();
this.view = this._createView(); this.view = this._createView();
this.toolbar = this._createToolBar(); this.toolbar = this._createToolBar();
this.view.on(Controller.EVENT_CHANGE, (type, ...args) => { this.view.on(Controller.EVENT_CHANGE, (type, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, ...args); this.fireEvent(Controller.EVENT_CHANGE, type, ...args);
if (type === BI.Events.CLICK) { if (type === BI.Events.CLICK) {
this.fireEvent(PopupView.EVENT_CHANGE); this.fireEvent(PopupView.EVENT_CHANGE);
} }
}); });
createWidget(extend({ createWidget(
element: this, extend(
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, { {
scrolly: false, element: this,
lgap, },
rgap, BI.LogicFactory.createLogic(
tgap, BI.LogicFactory.createLogicTypeByDirection(direction),
bgap, extend({}, logic, {
vgap, scrolly: false,
hgap, lgap,
items: BI.LogicFactory.createLogicItemsByDirection(direction, extend({ rgap,
cls: `list-view-outer bi-card list-view-shadow${primary ? " bi-primary" : ""}`, tgap,
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(direction), extend({}, logic, { bgap,
items: BI.LogicFactory.createLogicItemsByDirection(direction, this.tool, this.tab, this.view, this.toolbar), vgap,
}))) hgap,
), items: BI.LogicFactory.createLogicItemsByDirection(
})))); direction,
if (showArrow) { extend(
this.arrow = createWidget({ {
type: "bi.absolute", cls: `list-view-outer bi-card list-view-shadow${primary ? " bi-primary" : ""}`,
cls: "bi-bubble-arrow", },
items: [{ BI.LogicFactory.createLogic(
type: "bi.layout", BI.LogicFactory.createLogicTypeByDirection(direction),
cls: "bubble-arrow", extend({}, logic, {
}], items: BI.LogicFactory.createLogicItemsByDirection(
}); direction,
this.arrowWrapper = createWidget({ this.tool,
type: "bi.absolute", this.tab,
cls: "bi-bubble-arrow-wrapper", this.view,
items: [{ this.toolbar
el: this.arrow, ),
}], })
}); )
// 因为三角符号的原因位置变大了,需要占位 )
this.placeholder = createWidget({ ),
type: "bi.layout", })
}); )
createWidget({ )
type: "bi.absolute", );
element: this, if (showArrow) {
items: [{ this.arrow = createWidget({
el: this.arrowWrapper, type: AbsoluteLayout.xtype,
left: 0, cls: "bi-bubble-arrow",
top: 0, items: [
}, { {
el: this.placeholder, type: Layout.xtype,
}], cls: "bubble-arrow",
}); }
} ],
} });
_createView() { this.arrowWrapper = createWidget({
const { el, value, minHeight, innerVgap, innerHgap } = this.options; type: AbsoluteLayout.xtype,
this.button_group = createWidget(el, { type: "bi.button_group", value }); cls: "bi-bubble-arrow-wrapper",
this.button_group.element.css({ items: [
"min-height": BI.pixFormat(minHeight), {
"padding-top": BI.pixFormat(innerVgap), el: this.arrow,
"padding-bottom": BI.pixFormat(innerVgap), }
"padding-left": BI.pixFormat(innerHgap), ],
"padding-right": BI.pixFormat(innerHgap), });
}); // 因为三角符号的原因位置变大了,需要占位
this.placeholder = createWidget({
type: Layout.xtype,
});
createWidget({
type: AbsoluteLayout.xtype,
element: this,
items: [
{
el: this.arrowWrapper,
left: 0,
top: 0,
},
{
el: this.placeholder,
}
],
});
}
}
_createView() {
const { el, value, minHeight, innerVgap, innerHgap } = this.options;
this.button_group = createWidget(el, { type: ButtonGroup.xtype, value });
this.button_group.element.css({
"min-height": BI.pixFormat(minHeight),
"padding-top": BI.pixFormat(innerVgap),
"padding-bottom": BI.pixFormat(innerVgap),
"padding-left": BI.pixFormat(innerHgap),
"padding-right": BI.pixFormat(innerHgap),
});
return this.button_group; return this.button_group;
} }
_createTool() { _createTool() {
const { tool } = this.options; const { tool } = this.options;
if (false === tool) { if (false === tool) {
return; return;
} }
return createWidget(tool); return createWidget(tool);
} }
_createTab() { _createTab() {
const { tabs, value } = this.options; const { tabs, value } = this.options;
if (tabs.length === 0) { if (tabs.length === 0) {
return; return;
} }
return createWidget({ return createWidget({
type: "bi.center", type: CenterLayout.xtype,
cls: "list-view-tab", cls: "list-view-tab",
height: 25, height: 25,
items: tabs, items: tabs,
value, value,
}); });
} }
_createToolBar() { _createToolBar() {
const { buttons } = this.options; const { buttons } = this.options;
if (buttons.length === 0) { if (buttons.length === 0) {
return; return;
} }
return createWidget({ return createWidget({
type: "bi.center", type: CenterLayout.xtype,
cls: "list-view-toolbar bi-high-light bi-split-top", cls: "list-view-toolbar bi-high-light bi-split-top",
height: 24, height: 24,
items: createItems(buttons, { items: createItems(buttons, {
once: false, once: false,
shadow: true, shadow: true,
isShadowShowingOnSelected: true, isShadowShowingOnSelected: true,
}), }),
}); });
} }
setDirection(direction, position) { setDirection(direction, position) {
const { showArrow, tgap, vgap, bgap, rgap, hgap, lgap } = this.options; const { showArrow, tgap, vgap, bgap, rgap, hgap, lgap } = this.options;
if (showArrow) { if (showArrow) {
let style = {}, wrapperStyle = {}, placeholderStyle = {}; let style = {},
const adjustXOffset = position.adjustXOffset || 0; wrapperStyle = {},
const adjustYOffset = position.adjustYOffset || 0; placeholderStyle = {};
const bodyBounds = Widget._renderEngine.createElement("body").bounds(); const adjustXOffset = position.adjustXOffset || 0;
const bodyWidth = bodyBounds.width; const adjustYOffset = position.adjustYOffset || 0;
const bodyHeight = bodyBounds.height; const bodyBounds = Widget._renderEngine.createElement("body").bounds();
const popupWidth = this.element.outerWidth(); const bodyWidth = bodyBounds.width;
const popupHeight = this.element.outerHeight(); const bodyHeight = bodyBounds.height;
const offset = position.offset; const popupWidth = this.element.outerWidth();
const offsetStyle = position.offsetStyle; const popupHeight = this.element.outerHeight();
const middle = offsetStyle === "center" || offsetStyle === "middle"; const offset = position.offset;
const offsetStyle = position.offsetStyle;
const middle = offsetStyle === "center" || offsetStyle === "middle";
const minLeft = Math.max(4, offset.left + 4 + popupWidth - bodyWidth); const minLeft = Math.max(4, offset.left + 4 + popupWidth - bodyWidth);
const minRight = Math.max(4, popupWidth - (offset.left + 4)); const minRight = Math.max(4, popupWidth - (offset.left + 4));
const minTop = Math.max(4, offset.top + 4 + popupHeight - bodyHeight); const minTop = Math.max(4, offset.top + 4 + popupHeight - bodyHeight);
const minBottom = Math.max(4, popupHeight - (offset.top + 4)); const minBottom = Math.max(4, popupHeight - (offset.top + 4));
const maxLeft = Math.min(popupWidth - 16 - 4, offset.left + position.width - 16 - 4); const maxLeft = Math.min(popupWidth - 16 - 4, offset.left + position.width - 16 - 4);
const maxRight = Math.min(popupWidth - 16 - 4, bodyWidth - (offset.left + position.width - 16 - 4)); const maxRight = Math.min(popupWidth - 16 - 4, bodyWidth - (offset.left + position.width - 16 - 4));
const maxTop = Math.min(popupHeight - 16 - 4, offset.top + position.height - 16 - 4); const maxTop = Math.min(popupHeight - 16 - 4, offset.top + position.height - 16 - 4);
const maxBottom = Math.min(popupHeight - 16 - 4, bodyHeight - (offset.top + position.height - 16 - 4)); const maxBottom = Math.min(popupHeight - 16 - 4, bodyHeight - (offset.top + position.height - 16 - 4));
switch (direction) { switch (direction) {
case "bottom": case "bottom":
case "bottom,right": case "bottom,right":
direction = "bottom"; direction = "bottom";
style = { style = {
// 5表示留出一定的空间 // 5表示留出一定的空间
left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft), left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft),
}; };
wrapperStyle = { wrapperStyle = {
top: tgap + vgap, top: tgap + vgap,
left: 0, left: 0,
right: "", right: "",
bottom: "", bottom: "",
}; };
placeholderStyle = { placeholderStyle = {
left: 0, left: 0,
right: 0, right: 0,
height: this._const.TRIANGLE_LENGTH, height: this._const.TRIANGLE_LENGTH,
top: -this._const.TRIANGLE_LENGTH, top: -this._const.TRIANGLE_LENGTH,
bottom: "", bottom: "",
}; };
break; break;
case "bottom,left": case "bottom,left":
direction = "bottom"; direction = "bottom";
style = { style = {
right: clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight), right: clamp(
}; ((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8,
wrapperStyle = { minRight,
top: bgap + vgap, maxRight
left: "", ),
right: 0, };
bottom: "", wrapperStyle = {
}; top: bgap + vgap,
placeholderStyle = { left: "",
left: 0, right: 0,
right: 0, bottom: "",
height: this._const.TRIANGLE_LENGTH, };
top: -this._const.TRIANGLE_LENGTH, placeholderStyle = {
bottom: "", left: 0,
}; right: 0,
break; height: this._const.TRIANGLE_LENGTH,
case "top": top: -this._const.TRIANGLE_LENGTH,
case "top,right": bottom: "",
direction = "top"; };
style = { break;
left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft), case "top":
}; case "top,right":
wrapperStyle = { direction = "top";
bottom: bgap + vgap, style = {
left: 0, left: clamp(((middle ? popupWidth : position.width) - adjustXOffset) / 2 - 8, minLeft, maxLeft),
right: "", };
top: "", wrapperStyle = {
}; bottom: bgap + vgap,
placeholderStyle = { left: 0,
left: 0, right: "",
right: 0, top: "",
height: this._const.TRIANGLE_LENGTH, };
top: "", placeholderStyle = {
bottom: -this._const.TRIANGLE_LENGTH, left: 0,
}; right: 0,
break; height: this._const.TRIANGLE_LENGTH,
case "top,left": top: "",
direction = "top"; bottom: -this._const.TRIANGLE_LENGTH,
style = { };
right: clamp(((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8, minRight, maxRight), break;
}; case "top,left":
wrapperStyle = { direction = "top";
bottom: bgap + vgap, style = {
right: 0, right: clamp(
left: "", ((middle ? popupWidth : position.width) + adjustXOffset) / 2 - 8,
top: "", minRight,
}; maxRight
placeholderStyle = { ),
left: 0, };
right: 0, wrapperStyle = {
height: this._const.TRIANGLE_LENGTH, bottom: bgap + vgap,
top: "", right: 0,
bottom: -this._const.TRIANGLE_LENGTH, left: "",
}; top: "",
break; };
case "left": placeholderStyle = {
case "left,bottom": left: 0,
direction = "left"; right: 0,
style = { height: this._const.TRIANGLE_LENGTH,
top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop), top: "",
}; bottom: -this._const.TRIANGLE_LENGTH,
wrapperStyle = { };
right: rgap + hgap, break;
top: 0, case "left":
bottom: "", case "left,bottom":
left: "", direction = "left";
}; style = {
placeholderStyle = { top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop),
top: 0, };
bottom: 0, wrapperStyle = {
width: this._const.TRIANGLE_LENGTH, right: rgap + hgap,
right: -this._const.TRIANGLE_LENGTH, top: 0,
left: "", bottom: "",
}; left: "",
break; };
case "left,top": placeholderStyle = {
direction = "left"; top: 0,
style = { bottom: 0,
bottom: clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom), width: this._const.TRIANGLE_LENGTH,
}; right: -this._const.TRIANGLE_LENGTH,
wrapperStyle = { left: "",
right: rgap + hgap, };
bottom: 0, break;
top: "", case "left,top":
left: "", direction = "left";
}; style = {
placeholderStyle = { bottom: clamp(
top: 0, ((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8,
bottom: 0, minBottom,
width: this._const.TRIANGLE_LENGTH, maxBottom
right: -this._const.TRIANGLE_LENGTH, ),
left: "", };
}; wrapperStyle = {
break; right: rgap + hgap,
case "right": bottom: 0,
case "right,bottom": top: "",
direction = "right"; left: "",
style = { };
top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop), placeholderStyle = {
}; top: 0,
wrapperStyle = { bottom: 0,
left: lgap + hgap, width: this._const.TRIANGLE_LENGTH,
top: 0, right: -this._const.TRIANGLE_LENGTH,
bottom: "", left: "",
right: "", };
}; break;
placeholderStyle = { case "right":
top: 0, case "right,bottom":
bottom: 0, direction = "right";
width: this._const.TRIANGLE_LENGTH, style = {
left: -this._const.TRIANGLE_LENGTH, top: clamp(((middle ? popupHeight : position.height) - adjustYOffset) / 2 - 8, minTop, maxTop),
right: "", };
}; wrapperStyle = {
break; left: lgap + hgap,
case "right,top": top: 0,
direction = "right"; bottom: "",
style = { right: "",
bottom: clamp(((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8, minBottom, maxBottom), };
}; placeholderStyle = {
wrapperStyle = { top: 0,
left: lgap + hgap, bottom: 0,
bottom: 0, width: this._const.TRIANGLE_LENGTH,
top: "", left: -this._const.TRIANGLE_LENGTH,
right: "", right: "",
}; };
placeholderStyle = { break;
top: 0, case "right,top":
bottom: 0, direction = "right";
width: this._const.TRIANGLE_LENGTH, style = {
left: -this._const.TRIANGLE_LENGTH, bottom: clamp(
right: "", ((middle ? popupHeight : position.height) + adjustYOffset) / 2 - 8,
}; minBottom,
break; maxBottom
case "right,innerRight": ),
break; };
case "right,innerLeft": wrapperStyle = {
break; left: lgap + hgap,
case "innerRight": bottom: 0,
break; top: "",
case "innerLeft": right: "",
break; };
default: placeholderStyle = {
break; top: 0,
} bottom: 0,
this.element width: this._const.TRIANGLE_LENGTH,
.removeClass("left") left: -this._const.TRIANGLE_LENGTH,
.removeClass("right") right: "",
.removeClass("top") };
.removeClass("bottom") break;
.addClass(direction); case "right,innerRight":
this.arrow.element.css(style); break;
this.arrowWrapper.element.css(wrapperStyle); case "right,innerLeft":
this.placeholder.element.css(placeholderStyle); break;
} case "innerRight":
} break;
case "innerLeft":
break;
default:
break;
}
this.element
.removeClass("left")
.removeClass("right")
.removeClass("top")
.removeClass("bottom")
.addClass(direction);
this.arrow.element.css(style);
this.arrowWrapper.element.css(wrapperStyle);
this.placeholder.element.css(placeholderStyle);
}
}
getView() { getView() {
return this.view; return this.view;
} }
populate(items) { populate(items) {
this.view.populate(...arguments); this.view.populate(...arguments);
} }
resetWidth(w) { resetWidth(w) {
this.options.width = w; this.options.width = w;
this.element.width(w); this.element.width(w);
} }
resetHeight(h) { resetHeight(h) {
const tbHeight = this.toolbar ? (this.toolbar.attr("height") || 24) : 0, const tbHeight = this.toolbar ? this.toolbar.attr("height") || 24 : 0,
tabHeight = this.tab ? (this.tab.attr("height") || 24) : 0, tabHeight = this.tab ? this.tab.attr("height") || 24 : 0,
toolHeight = ((this.tool && this.tool.attr("height")) || 24) * ((this.tool && this.tool.isVisible()) ? 1 : 0); toolHeight = ((this.tool && this.tool.attr("height")) || 24) * (this.tool && this.tool.isVisible() ? 1 : 0);
const resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVgap; const resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVgap;
this.view.resetHeight ? this.view.resetHeight(resetHeight) : this.view.resetHeight
this.view.element.css({ "max-height": BI.pixFormat(resetHeight) }); ? this.view.resetHeight(resetHeight)
} : this.view.element.css({ "max-height": BI.pixFormat(resetHeight) });
}
setValue(selectedValues) { setValue(selectedValues) {
this.tab && this.tab.setValue(selectedValues); this.tab && this.tab.setValue(selectedValues);
this.view.setValue(selectedValues); this.view.setValue(selectedValues);
} }
getValue() { getValue() {
return this.view.getValue(); return this.view.getValue();
} }
} }

259
src/base/layer/layer.searcher.js

@ -1,3 +1,7 @@
import { ButtonGroup } from "../combination";
import { VerticalLayout, Layout, shortcut, extend, createWidget, Controller, isNotEmptyArray } from "@/core";
import { Pane } from "../1.pane";
/** /**
* 搜索面板 * 搜索面板
* *
@ -6,132 +10,135 @@
* @extends BI.Pane * @extends BI.Pane
*/ */
import { shortcut, extend, createWidget, Controller, isNotEmptyArray } from "../../core";
import { Pane } from "../1.pane";
@shortcut() @shortcut()
export class SearcherView extends Pane { export class SearcherView extends Pane {
static xtype = "bi.searcher_view"; static xtype = "bi.searcher_view";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: `${conf.baseCls || ""} bi-searcher-view bi-card`, baseCls: `${conf.baseCls || ""} bi-searcher-view bi-card`,
tipText: BI.i18nText("BI-No_Select"), tipText: BI.i18nText("BI-No_Select"),
chooseType: BI.Selection.Single, chooseType: BI.Selection.Single,
matcher: { // 完全匹配的构造器 matcher: {
type: "bi.button_group", // 完全匹配的构造器
behaviors: { type: ButtonGroup.xtype,
redmark: () => true, behaviors: {
}, redmark: () => true,
items: [], },
layouts: [{ items: [],
type: "bi.vertical", layouts: [
}], {
}, type: VerticalLayout.xtype,
searcher: { }
type: "bi.button_group", ],
behaviors: { },
redmark: () => true, searcher: {
}, type: ButtonGroup.xtype,
items: [], behaviors: {
layouts: [{ redmark: () => true,
type: "bi.vertical", },
}], items: [],
}, layouts: [
}); {
} type: VerticalLayout.xtype,
render() { }
const { matcher, chooseType, value, searcher } = this.options; ],
},
this.matcher = createWidget(matcher, { });
type: "bi.button_group", }
chooseType, render() {
behaviors: { const { matcher, chooseType, value, searcher } = this.options;
redmark: () => true,
}, this.matcher = createWidget(matcher, {
layouts: [{ type: ButtonGroup.xtype,
type: "bi.vertical", chooseType,
}], behaviors: {
value, redmark: () => true,
}); },
this.matcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => { layouts: [
this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args); {
if (type === BI.Events.CLICK) { type: VerticalLayout.xtype,
this.fireEvent(SearcherView.EVENT_CHANGE, val, ob); }
} ],
}); value,
this.spliter = createWidget({ });
type: "bi.vertical", this.matcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => {
height: 1, this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args);
hgap: 10, if (type === BI.Events.CLICK) {
items: [{ this.fireEvent(SearcherView.EVENT_CHANGE, val, ob);
type: "bi.layout", }
height: 1, });
cls: "searcher-view-spliter bi-background", this.spliter = createWidget({
}], type: VerticalLayout.xtype,
}); height: 1,
this.searcher = createWidget(searcher, { hgap: 10,
type: "bi.button_group", items: [
chooseType, {
behaviors: { type: Layout.xtype,
redmark: () => true, height: 1,
}, cls: "searcher-view-spliter bi-background",
layouts: [{ }
type: "bi.vertical", ],
}], });
value, this.searcher = createWidget(searcher, {
}); type: ButtonGroup.xtype,
this.searcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => { chooseType,
this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args); behaviors: {
if (type === BI.Events.CLICK) { redmark: () => true,
this.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob); },
} layouts: [
}); {
type: VerticalLayout.xtype,
createWidget({ }
type: "bi.vertical", ],
element: this, value,
items: [this.matcher, this.spliter, this.searcher], });
}); this.searcher.on(Controller.EVENT_CHANGE, (type, val, ob, ...args) => {
} this.fireEvent(Controller.EVENT_CHANGE, type, val, ob, ...args);
if (type === BI.Events.CLICK) {
startSearch() { this.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob);
}
} });
stopSearch() { createWidget({
type: VerticalLayout.xtype,
} element: this,
items: [this.matcher, this.spliter, this.searcher],
setValue(v) { });
this.matcher.setValue(v); }
this.searcher.setValue(v);
} startSearch() {}
getValue() { stopSearch() {}
return this.matcher.getValue().concat(this.searcher.getValue());
} setValue(v) {
this.matcher.setValue(v);
populate(searchResult, matchResult, keyword) { this.searcher.setValue(v);
searchResult || (searchResult = []); }
matchResult || (matchResult = []);
this.setTipVisible(searchResult.length + matchResult.length === 0); getValue() {
this.spliter.setVisible(isNotEmptyArray(matchResult) && isNotEmptyArray(searchResult)); return this.matcher.getValue().concat(this.searcher.getValue());
this.matcher.populate(matchResult, keyword); }
this.searcher.populate(searchResult, keyword);
} populate(searchResult, matchResult, keyword) {
searchResult || (searchResult = []);
empty() { matchResult || (matchResult = []);
this.searcher.empty(); this.setTipVisible(searchResult.length + matchResult.length === 0);
this.matcher.empty(); this.spliter.setVisible(isNotEmptyArray(matchResult) && isNotEmptyArray(searchResult));
} this.matcher.populate(matchResult, keyword);
this.searcher.populate(searchResult, keyword);
hasMatched() { }
return this.matcher.getAllButtons().length > 0;
} empty() {
this.searcher.empty();
this.matcher.empty();
}
hasMatched() {
return this.matcher.getAllButtons().length > 0;
}
} }

221
src/base/list/listview.js

@ -1,3 +1,5 @@
import { VerticalLayout, Widget, shortcut, extend, isFunction } from "@/core";
/** /**
* 边滚动边加载的列表控件 * 边滚动边加载的列表控件
* *
@ -5,7 +7,7 @@
* @class BI.ListView * @class BI.ListView
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, isFunction } from "../../core";
@shortcut() @shortcut()
export class ListView extends Widget { export class ListView extends Widget {
props() { props() {
@ -25,119 +27,128 @@ export class ListView extends Widget {
this.cache = {}; this.cache = {};
} }
static xtype = "bi.list_view"; static xtype = "bi.list_view";
render() { render() {
const { el } = this.options; const { el } = this.options;
return { return {
type: "bi.vertical", type: VerticalLayout.xtype,
items: [extend({ items: [
type: "bi.vertical", extend(
scrolly: false, {
ref: _ref => { type: VerticalLayout.xtype,
this.container = _ref; scrolly: false,
}, ref: _ref => {
}, el)], this.container = _ref;
element: this, },
}; },
} el
)
],
element: this,
};
}
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
const o = this.options; const o = this.options;
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items)
this.populate(newValue); ? this.__watch(o.items, (context, newValue) => {
}) : o.items; this.populate(newValue);
this._populate(); })
this.element.scroll(e => { : o.items;
o.scrollTop = this.element.scrollTop(); this._populate();
this._calculateBlocksToRender(); this.element.scroll(e => {
}); o.scrollTop = this.element.scrollTop();
let lastWidth = this.element.width(), this._calculateBlocksToRender();
lastHeight = this.element.height(); });
BI.ResizeDetector.addResizeListener(this, () => { let lastWidth = this.element.width(),
if (!this.element.is(":visible")) { lastHeight = this.element.height();
return; BI.ResizeDetector.addResizeListener(this, () => {
} if (!this.element.is(":visible")) {
const width = this.element.width(), return;
height = this.element.height(); }
if (width !== lastWidth || height !== lastHeight) { const width = this.element.width(),
lastWidth = width; height = this.element.height();
lastHeight = height; if (width !== lastWidth || height !== lastHeight) {
this._calculateBlocksToRender(); lastWidth = width;
} lastHeight = height;
}); this._calculateBlocksToRender();
} }
});
}
_renderMoreIf() { _renderMoreIf() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + blockSize)) || 0; let index = (this.cache[this.renderedIndex] && this.cache[this.renderedIndex].index + blockSize) || 0;
let cnt = this.renderedIndex + 1; let cnt = this.renderedIndex + 1;
let lastHeight; let lastHeight;
const getElementHeight = () => this.container.element.height(); const getElementHeight = () => this.container.element.height();
lastHeight = getElementHeight(); lastHeight = getElementHeight();
while ((lastHeight) < minContentHeight && index < items.length) { while (lastHeight < minContentHeight && index < items.length) {
const itemsArr = items.slice(index, index + blockSize); const itemsArr = items.slice(index, index + blockSize);
// eslint-disable-next-line no-loop-func // eslint-disable-next-line no-loop-func
this.container.addItems(itemsArr.map((item, i) => itemFormatter(item, index + i)), this); this.container.addItems(
const addedHeight = getElementHeight() - lastHeight; itemsArr.map((item, i) => itemFormatter(item, index + i)),
this.cache[cnt] = { this
index, );
scrollTop: lastHeight, const addedHeight = getElementHeight() - lastHeight;
height: addedHeight, this.cache[cnt] = {
}; index,
this.renderedIndex = cnt; scrollTop: lastHeight,
cnt++; height: addedHeight,
index += blockSize; };
lastHeight = getElementHeight(); this.renderedIndex = cnt;
} cnt++;
} index += blockSize;
_calculateBlocksToRender() { lastHeight = getElementHeight();
// BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。 }
// 这样从不可见状态变为可见状态能够重新触发线段树初始化 }
if (!this.element.is(":visible")) { _calculateBlocksToRender() {
return; // BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
} // 这样从不可见状态变为可见状态能够重新触发线段树初始化
this._renderMoreIf(); if (!this.element.is(":visible")) {
} return;
}
this._renderMoreIf();
}
_populate(items) { _populate(items) {
const { scrollTop } = this.options; const { scrollTop } = this.options;
if (items && this.options.items !== items) { if (items && this.options.items !== items) {
this.options.items = items; this.options.items = items;
} }
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} }
restore() { restore() {
this.renderedIndex = -1; this.renderedIndex = -1;
this.container.empty(); this.container.empty();
this.cache = {}; this.cache = {};
} }
scrollTo(scrollTop) { scrollTo(scrollTop) {
this.options.scrollTop = scrollTop; this.options.scrollTop = scrollTop;
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} }
populate(items) { populate(items) {
if (items && this.options.items !== items) { if (items && this.options.items !== items) {
this.restore(); this.restore();
} }
this._populate(items); this._populate(items);
} }
beforeDestroy() { beforeDestroy() {
BI.ResizeDetector.removeResizeListener(this); BI.ResizeDetector.removeResizeListener(this);
this.restore(); this.restore();
} }
} }

331
src/base/list/virtualgrouplist.js

@ -1,3 +1,6 @@
import { VerticalLayout, Layout, Widget, shortcut, extend, isFunction, isNumber, PrefixIntervalTree } from "@/core";
import { VirtualGroup } from "../combination";
/** /**
* 同时用于virtualGroup和virtualList特性的虚拟列表 * 同时用于virtualGroup和virtualList特性的虚拟列表
* *
@ -6,7 +9,6 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, isFunction, isNumber, PrefixIntervalTree } from "../../core";
@shortcut() @shortcut()
export class VirtualGroupList extends Widget { export class VirtualGroupList extends Widget {
props() { props() {
@ -26,167 +28,190 @@ export class VirtualGroupList extends Widget {
this.renderedIndex = -1; this.renderedIndex = -1;
} }
static xtype = "bi.virtual_group_list"; static xtype = "bi.virtual_group_list";
render() { render() {
const { rowHeight, items, el } = this.options; const { rowHeight, items, el } = this.options;
return { return {
type: "bi.vertical", type: VerticalLayout.xtype,
items: [{ items: [
type: "bi.layout", {
ref: () => { type: Layout.xtype,
this.topBlank = this; ref: () => {
}, this.topBlank = this;
}, { },
type: "bi.virtual_group", },
height: rowHeight * items.length, {
ref: () => { type: VirtualGroup.xtype,
this.container = this; height: rowHeight * items.length,
}, ref: () => {
layouts: [extend({ this.container = this;
type: "bi.vertical", },
scrolly: false, layouts: [
}, el)], extend(
}, { {
type: "bi.layout", type: VerticalLayout.xtype,
ref: () => { scrolly: false,
this.bottomBlank = this; },
}, el
}], )
element: this, ],
}; },
} {
// mounted之后绑定事件 type: Layout.xtype,
mounted() { ref: () => {
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 this.bottomBlank = this;
const o = this.options; },
o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { }
this.populate(newValue); ],
}) : o.items; element: this,
this._populate(); };
this.ticking = false; }
this.element.scroll(() => { // mounted之后绑定事件
o.scrollTop = this.element.scrollTop(); mounted() {
if (!this.ticking) { // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
requestAnimationFrame(() => { const o = this.options;
this._calculateBlocksToRender(); o.items = isFunction(o.items)
this.ticking = false; ? this.__watch(o.items, (context, newValue) => {
}); this.populate(newValue);
this.ticking = true; })
} : o.items;
}); this._populate();
BI.ResizeDetector.addResizeListener(this, () => { this.ticking = false;
if (this.element.is(":visible")) { this.element.scroll(() => {
this._calculateBlocksToRender(); o.scrollTop = this.element.scrollTop();
} if (!this.ticking) {
}); requestAnimationFrame(() => {
} this._calculateBlocksToRender();
this.ticking = false;
});
this.ticking = true;
}
});
BI.ResizeDetector.addResizeListener(this, () => {
if (this.element.is(":visible")) {
this._calculateBlocksToRender();
}
});
}
_isAutoHeight() { _isAutoHeight() {
return !isNumber(this.options.rowHeight); return !isNumber(this.options.rowHeight);
} }
_renderMoreIf() { _renderMoreIf() {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1; let index = (this.renderedIndex + 1) * blockSize,
let lastHeight; cnt = this.renderedIndex + 1;
const getElementHeight = () => this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height(); let lastHeight;
lastHeight = this.renderedIndex === -1 ? 0 : getElementHeight(); const getElementHeight = () =>
while (lastHeight < minContentHeight && index < items.length) { this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height();
const itemsArr = items.slice(index, index + blockSize); lastHeight = this.renderedIndex === -1 ? 0 : getElementHeight();
// eslint-disable-next-line no-loop-func while (lastHeight < minContentHeight && index < items.length) {
this.container[this.renderedIndex === -1 ? "populate" : "addItems"](itemsArr.map((item, i) => itemFormatter(item, index + i)), this); const itemsArr = items.slice(index, index + blockSize);
const elementHeight = getElementHeight(); // eslint-disable-next-line no-loop-func
const addedHeight = elementHeight - lastHeight; this.container[this.renderedIndex === -1 ? "populate" : "addItems"](
this.tree.set(cnt, addedHeight); itemsArr.map((item, i) => itemFormatter(item, index + i)),
this.renderedIndex = cnt; this
cnt++; );
index += blockSize; const elementHeight = getElementHeight();
lastHeight = this.renderedIndex === -1 ? 0 : elementHeight; const addedHeight = elementHeight - lastHeight;
} this.tree.set(cnt, addedHeight);
} this.renderedIndex = cnt;
cnt++;
index += blockSize;
lastHeight = this.renderedIndex === -1 ? 0 : elementHeight;
}
}
_calculateBlocksToRender() { _calculateBlocksToRender() {
// BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。 // BI-115750 不可见状态下依赖元素实际尺寸构造的线段树会分段错误,所以不进行后续计算和线段树的初始化。
// 这样从不可见状态变为可见状态能够重新触发线段树初始化 // 这样从不可见状态变为可见状态能够重新触发线段树初始化
if (!this.element.is(":visible")) { if (!this.element.is(":visible")) {
return; return;
} }
const { scrollTop, overscanHeight, blockSize, items, itemFormatter, rowHeight } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter, rowHeight } = this.options;
this._isAutoHeight() && this._renderMoreIf(); this._isAutoHeight() && this._renderMoreIf();
const height = this.element.height(); const height = this.element.height();
const minContentHeightFrom = scrollTop - overscanHeight; const minContentHeightFrom = scrollTop - overscanHeight;
const minContentHeightTo = scrollTop + height + overscanHeight; const minContentHeightTo = scrollTop + height + overscanHeight;
const start = this.tree.greatestLowerBound(minContentHeightFrom); const start = this.tree.greatestLowerBound(minContentHeightFrom);
const end = this.tree.leastUpperBound(minContentHeightTo); const end = this.tree.leastUpperBound(minContentHeightTo);
const itemsArr = []; const itemsArr = [];
const topHeight = this.tree.sumTo(Math.max(-1, start - 1)); const topHeight = this.tree.sumTo(Math.max(-1, start - 1));
this.topBlank.setHeight(`${topHeight}px`); this.topBlank.setHeight(`${topHeight}px`);
if (this._isAutoHeight()) { if (this._isAutoHeight()) {
for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) { for (let i = start < 0 ? 0 : start; i <= end && i <= this.renderedIndex; i++) {
const index = i * blockSize; const index = i * blockSize;
for (let j = index; j < index + blockSize && j < items.length; j++) { for (let j = index; j < index + blockSize && j < items.length; j++) {
itemsArr.push(items[j]); itemsArr.push(items[j]);
} }
} }
this.bottomBlank.setHeight(`${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`); this.bottomBlank.setHeight(
this.container.populate(itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i))); `${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`
} else { );
for (let i = (start < 0 ? 0 : start); i <= end; i++) { this.container.populate(
const index = i * blockSize; itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i))
for (let j = index; j < index + blockSize && j < items.length; j++) { );
itemsArr.push(items[j]); } else {
} for (let i = start < 0 ? 0 : start; i <= end; i++) {
} const index = i * blockSize;
this.container.element.height(rowHeight * items.length - topHeight); for (let j = index; j < index + blockSize && j < items.length; j++) {
this.container.populate(itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i))); itemsArr.push(items[j]);
} }
} }
_populate(items) { this.container.element.height(rowHeight * items.length - topHeight);
const { blockSize, rowHeight, scrollTop } = this.options; this.container.populate(
if (items && this.options.items !== items) { itemsArr.map((item, i) => itemFormatter(item, (start < 0 ? 0 : start) * blockSize + i))
// 重新populate一组items,需要重新对线段树分块 );
this.options.items = items; }
this._restore(); }
} _populate(items) {
this.tree = PrefixIntervalTree.uniform(Math.ceil(this.options.items.length / blockSize), this._isAutoHeight() ? 0 : rowHeight * blockSize); const { blockSize, rowHeight, scrollTop } = this.options;
if (items && this.options.items !== items) {
// 重新populate一组items,需要重新对线段树分块
this.options.items = items;
this._restore();
}
this.tree = PrefixIntervalTree.uniform(
Math.ceil(this.options.items.length / blockSize),
this._isAutoHeight() ? 0 : rowHeight * blockSize
);
this._calculateBlocksToRender(); this._calculateBlocksToRender();
try { try {
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} catch (e) { } catch (e) {}
} }
}
_restore() { _restore() {
this.renderedIndex = -1; this.renderedIndex = -1;
// 依赖于cache的占位元素也要初始化 // 依赖于cache的占位元素也要初始化
this.topBlank.setHeight(0); this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0); this.bottomBlank.setHeight(0);
} }
// 暂时只支持固定行高的场景 // 暂时只支持固定行高的场景
scrollTo(scrollTop) { scrollTo(scrollTop) {
this.options.scrollTop = scrollTop; this.options.scrollTop = scrollTop;
this._calculateBlocksToRender(); this._calculateBlocksToRender();
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} }
restore() { restore() {
this.options.scrollTop = 0; this.options.scrollTop = 0;
this._restore(); this._restore();
} }
populate(items) { populate(items) {
this._populate(items); this._populate(items);
} }
beforeDestroy() { beforeDestroy() {
BI.ResizeDetector.removeResizeListener(this); BI.ResizeDetector.removeResizeListener(this);
this.restore(); this.restore();
} }
} }

71
src/base/list/virtuallist.js

@ -1,3 +1,5 @@
import { VerticalLayout, Layout, Widget, shortcut, isFunction, each, PrefixIntervalTree } from "@/core";
/** /**
* 虚拟列表 * 虚拟列表
* *
@ -6,7 +8,6 @@
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, isFunction, each, PrefixIntervalTree } from "../../core";
@shortcut() @shortcut()
export class VirtualList extends Widget { export class VirtualList extends Widget {
props() { props() {
@ -29,33 +30,39 @@ export class VirtualList extends Widget {
render() { render() {
return { return {
type: "bi.vertical", type: VerticalLayout.xtype,
items: [{ items: [
type: "bi.layout", {
ref: _ref => { type: Layout.xtype,
this.topBlank = _ref; ref: _ref => {
}, this.topBlank = _ref;
}, { },
type: "bi.vertical",
scrolly: false,
ref: _ref => {
this.container = _ref;
}, },
}, { {
type: "bi.layout", type: VerticalLayout.xtype,
ref: _ref => { scrolly: false,
this.bottomBlank = _ref; ref: _ref => {
this.container = _ref;
},
}, },
}], {
type: Layout.xtype,
ref: _ref => {
this.bottomBlank = _ref;
},
}
],
}; };
} }
// mounted之后绑定事件 // mounted之后绑定事件
mounted() { mounted() {
// 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化 // 这里无法进行结构,因为存在赋值操作,如果使用结构则this.options的值不会跟随变化
const o = this.options; const o = this.options;
o.items = isFunction(o.items) ? this.__watch(o.items, (context, newValue) => { o.items = isFunction(o.items)
this.populate(newValue); ? this.__watch(o.items, (context, newValue) => {
}) : o.items; this.populate(newValue);
})
: o.items;
this._populate(); this._populate();
this.element.scroll(e => { this.element.scroll(e => {
o.scrollTop = this.element.scrollTop(); o.scrollTop = this.element.scrollTop();
@ -72,14 +79,19 @@ export class VirtualList extends Widget {
const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options; const { scrollTop, overscanHeight, blockSize, items, itemFormatter } = this.options;
const height = this.element.height(); const height = this.element.height();
const minContentHeight = scrollTop + height + overscanHeight; const minContentHeight = scrollTop + height + overscanHeight;
let index = (this.renderedIndex + 1) * blockSize, cnt = this.renderedIndex + 1; let index = (this.renderedIndex + 1) * blockSize,
cnt = this.renderedIndex + 1;
let lastHeight; let lastHeight;
const getElementHeight = () => this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height(); const getElementHeight = () =>
this.container.element.height() + this.topBlank.element.height() + this.bottomBlank.element.height();
lastHeight = getElementHeight(); lastHeight = getElementHeight();
while (lastHeight < minContentHeight && index < items.length) { while (lastHeight < minContentHeight && index < items.length) {
const itemsArr = items.slice(index, index + blockSize); const itemsArr = items.slice(index, index + blockSize);
// eslint-disable-next-line no-loop-func // eslint-disable-next-line no-loop-func
this.container.addItems(itemsArr.map((item, i) => itemFormatter(item, index + i)), this); this.container.addItems(
itemsArr.map((item, i) => itemFormatter(item, index + i)),
this
);
const addedHeight = getElementHeight() - lastHeight; const addedHeight = getElementHeight() - lastHeight;
this.tree.set(cnt, addedHeight); this.tree.set(cnt, addedHeight);
this.renderedIndex = cnt; this.renderedIndex = cnt;
@ -102,7 +114,8 @@ export class VirtualList extends Widget {
const minContentHeightTo = scrollTop + height + overscanHeight; const minContentHeightTo = scrollTop + height + overscanHeight;
const start = this.tree.greatestLowerBound(minContentHeightFrom); const start = this.tree.greatestLowerBound(minContentHeightFrom);
const end = this.tree.leastUpperBound(minContentHeightTo); const end = this.tree.leastUpperBound(minContentHeightTo);
const needDestroyed = [], needMount = []; const needDestroyed = [],
needMount = [];
for (let i = 0; i < start; i++) { for (let i = 0; i < start; i++) {
const index = i * blockSize; const index = i * blockSize;
if (!this.cache[i]) { if (!this.cache[i]) {
@ -132,7 +145,7 @@ export class VirtualList extends Widget {
const firstFragment = Widget._renderEngine.createFragment(), const firstFragment = Widget._renderEngine.createFragment(),
lastFragment = Widget._renderEngine.createFragment(); lastFragment = Widget._renderEngine.createFragment();
let currentFragment = firstFragment; let currentFragment = firstFragment;
for (let i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) { for (let i = start < 0 ? 0 : start; i <= end && i <= this.renderedIndex; i++) {
const index = i * blockSize; const index = i * blockSize;
if (!this.cache[i]) { if (!this.cache[i]) {
this.cache[i] = {}; this.cache[i] = {};
@ -152,7 +165,9 @@ export class VirtualList extends Widget {
this.container.element.prepend(firstFragment); this.container.element.prepend(firstFragment);
this.container.element.append(lastFragment); this.container.element.append(lastFragment);
this.topBlank.setHeight(`${this.tree.sumTo(Math.max(-1, start - 1))}px`); this.topBlank.setHeight(`${this.tree.sumTo(Math.max(-1, start - 1))}px`);
this.bottomBlank.setHeight(`${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`); this.bottomBlank.setHeight(
`${this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))}px`
);
each(needMount, (i, child) => { each(needMount, (i, child) => {
child && child._mount(); child && child._mount();
}); });
@ -170,8 +185,7 @@ export class VirtualList extends Widget {
this._calculateBlocksToRender(); this._calculateBlocksToRender();
try { try {
this.element.scrollTop(scrollTop); this.element.scrollTop(scrollTop);
} catch (e) { } catch (e) {}
}
} }
_clearChildren() { _clearChildren() {
@ -210,4 +224,3 @@ export class VirtualList extends Widget {
this.restore(); this.restore();
} }
} }

149
src/base/pager/pager.js

@ -1,3 +1,20 @@
import {
HorizontalLayout,
Widget,
shortcut,
extend,
emptyFn,
result,
isKey,
createWidget,
map,
stripEL,
formatEL,
Controller
} from "@/core";
import { Label } from "../single";
import { ButtonGroup } from "../combination";
/** /**
* 分页控件 * 分页控件
* *
@ -5,18 +22,20 @@
* @class BI.Pager * @class BI.Pager
* @extends BI.Widget * @extends BI.Widget
*/ */
import { Widget, shortcut, extend, emptyFn, result, isKey, createWidget, map, stripEL, formatEL, Controller } from "../../core";
@shortcut() @shortcut()
export class Pager extends Widget { export class Pager extends Widget {
_defaultConfig() { _defaultConfig() {
return extend(super._defaultConfig(...arguments), { return extend(super._defaultConfig(...arguments), {
baseCls: "bi-pager", baseCls: "bi-pager",
behaviors: {}, behaviors: {},
layouts: [{ layouts: [
type: "bi.horizontal", {
hgap: 10, type: HorizontalLayout.xtype,
vgap: 0, hgap: 10,
}], vgap: 0,
}
],
dynamicShow: true, // 是否动态显示上一页、下一页、首页、尾页, 若为false,则指对其设置使能状态 dynamicShow: true, // 是否动态显示上一页、下一页、首页、尾页, 若为false,则指对其设置使能状态
// dynamicShow为false时以下两个有用 // dynamicShow为false时以下两个有用
@ -32,7 +51,8 @@ export class Pager extends Widget {
next: "下一页", next: "下一页",
firstPage: 1, firstPage: 1,
lastPage: () => // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法 lastPage: () =>
// 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法
1, 1,
hasPrev: emptyFn, // pages不可用时有效 hasPrev: emptyFn, // pages不可用时有效
hasNext: emptyFn, // pages不可用时有效 hasNext: emptyFn, // pages不可用时有效
@ -53,8 +73,11 @@ export class Pager extends Widget {
} }
_populate() { _populate() {
const o = this.options, view = [], dict = {}; const o = this.options,
const { dynamicShow, dynamicShowPrevNext, hasPrev, dynamicShowFirstLast, hasNext, behaviors, layouts, jump } = this.options; view = [],
dict = {};
const { dynamicShow, dynamicShowPrevNext, hasPrev, dynamicShowFirstLast, hasNext, behaviors, layouts, jump } =
this.options;
this.empty(); this.empty();
const pages = result(o, "pages"); const pages = result(o, "pages");
const curr = result(this, "currPage"); const curr = result(this, "currPage");
@ -73,7 +96,7 @@ export class Pager extends Widget {
} }
// 计算当前组 // 计算当前组
dict.index = Math.ceil((curr + ((groups > 1 && groups !== pages) ? 1 : 0)) / (groups === 0 ? 1 : groups)); dict.index = Math.ceil((curr + (groups > 1 && groups !== pages ? 1 : 0)) / (groups === 0 ? 1 : groups));
// 当前页非首页,则输出上一页 // 当前页非首页,则输出上一页
if (((!dynamicShow && !dynamicShowPrevNext) || curr > 1) && prev !== false) { if (((!dynamicShow && !dynamicShowPrevNext) || curr > 1) && prev !== false) {
@ -85,9 +108,12 @@ export class Pager extends Widget {
}); });
} else { } else {
view.push({ view.push({
el: extend({ el: extend(
disabled: pages === false ? hasPrev(curr) === false : !(curr > 1 && prev !== false), {
}, prev), disabled: pages === false ? hasPrev(curr) === false : !(curr > 1 && prev !== false),
},
prev
),
}); });
} }
} }
@ -101,7 +127,7 @@ export class Pager extends Widget {
}); });
if (dict.index > 1 && groups !== 0 && groups !== pages - 1) { if (dict.index > 1 && groups !== 0 && groups !== pages - 1) {
view.push({ view.push({
type: "bi.label", type: Label.xtype,
cls: "page-ellipsis", cls: "page-ellipsis",
text: "\u2026", text: "\u2026",
}); });
@ -111,16 +137,21 @@ export class Pager extends Widget {
// 输出当前页组 // 输出当前页组
dict.poor = Math.floor((groups - 1) / 2); dict.poor = Math.floor((groups - 1) / 2);
dict.start = dict.index > 1 ? curr - dict.poor : 1; dict.start = dict.index > 1 ? curr - dict.poor : 1;
dict.end = dict.index > 1 ? (function () { dict.end =
const max = curr + (groups - dict.poor - 1); dict.index > 1
? (function () {
const max = curr + (groups - dict.poor - 1);
return max > pages ? pages : max; return max > pages ? pages : max;
}()) : groups; }())
if (dict.end - dict.start < groups - 1) { // 最后一组状态 : groups;
if (dict.end - dict.start < groups - 1) {
// 最后一组状态
dict.start = dict.end - groups + 1; dict.start = dict.end - groups + 1;
} }
let s = dict.start, e = dict.end; let s = dict.start,
if (first && last && (dict.index > 1 && groups !== 0) && (pages > groups && dict.end < pages && groups !== 0)) { e = dict.end;
if (first && last && dict.index > 1 && groups !== 0 && pages > groups && dict.end < pages && groups !== 0) {
s++; s++;
e--; e--;
} }
@ -143,7 +174,7 @@ export class Pager extends Widget {
if (((!dynamicShow && !dynamicShowFirstLast) || (pages > groups && dict.end < pages && groups !== 0)) && last) { if (((!dynamicShow && !dynamicShowFirstLast) || (pages > groups && dict.end < pages && groups !== 0)) && last) {
if (pages > groups && dict.end < pages && groups !== 0 && groups !== pages - 1) { if (pages > groups && dict.end < pages && groups !== 0 && groups !== pages - 1) {
view.push({ view.push({
type: "bi.label", type: Label.xtype,
cls: "page-ellipsis", cls: "page-ellipsis",
text: "\u2026", text: "\u2026",
}); });
@ -157,38 +188,47 @@ export class Pager extends Widget {
// 当前页不为尾页时,输出下一页 // 当前页不为尾页时,输出下一页
dict.flow = !prev && groups === 0; dict.flow = !prev && groups === 0;
if (((!dynamicShow && !dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) { if ((!dynamicShow && !dynamicShowPrevNext && next) || (curr !== pages && next) || dict.flow) {
view.push((function () { view.push(
if (isKey(next)) { (function () {
if (pages === false) { if (isKey(next)) {
return { text: next, value: "next", disabled: hasNext(curr) === false }; if (pages === false) {
} return { text: next, value: "next", disabled: hasNext(curr) === false };
}
return (dict.flow && curr === pages) return dict.flow && curr === pages
? ? { text: next, value: "next", disabled: true }
{ text: next, value: "next", disabled: true } : { text: next, value: "next", disabled: !((curr !== pages && next) || dict.flow) };
: }
{ text: next, value: "next", disabled: !(curr !== pages && next || dict.flow) };
}
return { return {
el: extend({ el: extend(
disabled: pages === false ? hasNext(curr) === false : !(curr !== pages && next || dict.flow), {
}, next), disabled:
}; pages === false
}())); ? hasNext(curr) === false
: !((curr !== pages && next) || dict.flow),
},
next
),
};
})()
);
} }
this.button_group = createWidget({ this.button_group = createWidget({
type: "bi.button_group", type: ButtonGroup.xtype,
element: this, element: this,
items: map(view, (idx, v) => { items: map(view, (idx, v) => {
v = extend({ v = extend(
cls: "bi-list-item-select bi-border-radius", {
height: 23, cls: "bi-list-item-select bi-border-radius",
hgap: v.el ? 0 : 10, height: 23,
stopPropagation: true, hgap: v.el ? 0 : 10,
}, stripEL(v)); stopPropagation: true,
},
stripEL(v)
);
return formatEL(v); return formatEL(v);
}), }),
@ -220,10 +260,12 @@ export class Pager extends Widget {
this.currPage = v; this.currPage = v;
break; break;
} }
jump.apply(this, [{ jump.apply(this, [
pages, {
curr: this.currPage, pages,
}]); curr: this.currPage,
}
]);
this._populate(); this._populate();
this.fireEvent(Pager.EVENT_CHANGE, obj); this.fireEvent(Pager.EVENT_CHANGE, obj);
} }
@ -251,7 +293,7 @@ export class Pager extends Widget {
hasNext(v) { hasNext(v) {
v || (v = 1); v || (v = 1);
const { pages, hasNext } = this.options; const { pages, hasNext } = this.options;
return pages === false ? hasNext(v) : v < pages; return pages === false ? hasNext(v) : v < pages;
} }
@ -263,7 +305,8 @@ export class Pager extends Widget {
if (pages === false) { if (pages === false) {
const lastPage = result(o, "lastPage"); const lastPage = result(o, "lastPage");
let firstPage = 1; let firstPage = 1;
this.currPage = v > lastPage ? lastPage : ((firstPage = result(o, "firstPage")), (v < firstPage ? firstPage : v)); this.currPage =
v > lastPage ? lastPage : ((firstPage = result(o, "firstPage")), v < firstPage ? firstPage : v);
} else { } else {
v = v > pages ? pages : v; v = v > pages ? pages : v;
this.currPage = v; this.currPage = v;

39
src/base/single/0.single.js

@ -1,3 +1,6 @@
import { Widget, shortcut, Actions, extend, isKey, isNotNull, isFunction, isPlainObject, isNull, delay } from "@/core";
import { Tooltips } from "@/base";
/** /**
* guy * guy
* 这仅仅只是一个超类, 所有简单控件的基类 * 这仅仅只是一个超类, 所有简单控件的基类
@ -10,13 +13,10 @@
* @abstract * @abstract
*/ */
import { Widget, shortcut, Actions, extend, isKey, isNotNull, isFunction, isPlainObject, isNull, delay } from "../../core";
import { Tooltips } from "../0.base";
@shortcut() @shortcut()
export class Single extends Widget { export class Single extends Widget {
static xtype = "bi.single"; static xtype = "bi.single";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
@ -35,7 +35,7 @@ export class Single extends Widget {
const { action } = this.options; const { action } = this.options;
const title = this.getTitle(); const title = this.getTitle();
const showToolTip = (tooltipOpt) => { const showToolTip = tooltipOpt => {
if (isKey(tooltipOpt.text) && !Tooltips.has(this.getName())) { if (isKey(tooltipOpt.text) && !Tooltips.has(this.getName())) {
Tooltips.show(e, this.getName(), tooltipOpt, this, opt); Tooltips.show(e, this.getName(), tooltipOpt, this, opt);
if (action) { if (action) {
@ -43,7 +43,7 @@ export class Single extends Widget {
} }
Actions.runGlobalAction("hover", this.options, this); Actions.runGlobalAction("hover", this.options, this);
} }
} };
if (title instanceof Promise) { if (title instanceof Promise) {
this.requestingTitle = title; this.requestingTitle = title;
@ -54,7 +54,6 @@ export class Single extends Widget {
} else { } else {
showToolTip(this._getTooltipOptions(title)); showToolTip(this._getTooltipOptions(title));
} }
} }
_hideTooltip() { _hideTooltip() {
@ -68,16 +67,17 @@ export class Single extends Widget {
_init() { _init() {
const { value } = this.options; const { value } = this.options;
this.options.value = isFunction(value) ? this.__watch(value, (context, newValue) => { this.options.value = isFunction(value)
this.setValue(newValue); ? this.__watch(value, (context, newValue) => {
}) : value; this.setValue(newValue);
})
: value;
super._init(arguments); super._init(arguments);
} }
_mounted() { _mounted() {
const { enableHover, title, warningTitle, belowMouse, container } = this.options; const { enableHover, title, warningTitle, belowMouse, container } = this.options;
if (enableHover || isKey(title) || isKey(warningTitle) if (enableHover || isKey(title) || isKey(warningTitle) || isFunction(title) || isFunction(warningTitle)) {
|| isFunction(title) || isFunction(warningTitle)) {
this.enableHover({ this.enableHover({
belowMouse, belowMouse,
container, container,
@ -105,11 +105,12 @@ export class Single extends Widget {
tooltipOpt.level = this.getTipType() || "success"; tooltipOpt.level = this.getTipType() || "success";
// 由于以前的用法,存在大量disabled:true搭配warningTitle的情况,所以这里做一个兼容,disabled:true的情况下,依然优先显示warningTitle,避免只设置了warningTitle而没有设置title的情况 // 由于以前的用法,存在大量disabled:true搭配warningTitle的情况,所以这里做一个兼容,disabled:true的情况下,依然优先显示warningTitle,避免只设置了warningTitle而没有设置title的情况
if (isNull(tipType) && !this.isEnabled()) { if (isNull(tipType) && !this.isEnabled()) {
tooltipOpt.text = (this.getWarningTitle() || title); tooltipOpt.text = this.getWarningTitle() || title;
} else { } else {
tooltipOpt.text = tooltipOpt.level === "success" ? title : (this.getWarningTitle() || title); tooltipOpt.text = tooltipOpt.level === "success" ? title : this.getWarningTitle() || title;
} }
} }
return tooltipOpt; return tooltipOpt;
} }
@ -117,7 +118,7 @@ export class Single extends Widget {
opt || (opt = {}); opt || (opt = {});
let delayingTooltips; let delayingTooltips;
if (!this._hoverBinded) { if (!this._hoverBinded) {
this.element.unbind("mouseenter.title").on("mouseenter.title", (e) => { this.element.unbind("mouseenter.title").on("mouseenter.title", e => {
this._e = e; this._e = e;
this.mouseOver = true; this.mouseOver = true;
if (this.getTipType() === "warning" || (isKey(this.getWarningTitle()) && !this.isEnabled())) { if (this.getTipType() === "warning" || (isKey(this.getWarningTitle()) && !this.isEnabled())) {
@ -136,7 +137,7 @@ export class Single extends Widget {
}, 500); }, 500);
} }
}); });
this.element.unbind("mousemove.title").on("mousemove.title", (e) => { this.element.unbind("mousemove.title").on("mousemove.title", e => {
this._e = e; this._e = e;
if (isNotNull(this.showTimeout)) { if (isNotNull(this.showTimeout)) {
clearTimeout(this.showTimeout); clearTimeout(this.showTimeout);
@ -165,7 +166,7 @@ export class Single extends Widget {
} }
}, 500); }, 500);
}); });
this.element.unbind("mouseleave.title").on("mouseleave.title", (e) => { this.element.unbind("mouseleave.title").on("mouseleave.title", e => {
this._e = null; this._e = null;
this.mouseOver = false; this.mouseOver = false;
this._clearTimeOut(); this._clearTimeOut();
@ -179,9 +180,7 @@ export class Single extends Widget {
// 取消hover事件 // 取消hover事件
this._clearTimeOut(); this._clearTimeOut();
this._hideTooltip(); this._hideTooltip();
this.element.unbind("mouseenter.title") this.element.unbind("mouseenter.title").unbind("mousemove.title").unbind("mouseleave.title");
.unbind("mousemove.title")
.unbind("mouseleave.title");
this._hoverBinded = false; this._hoverBinded = false;
} }

64
src/base/single/1.text.js

@ -1,10 +1,11 @@
import { Layout, DefaultLayout, shortcut } from "@/core";
import { Single } from "./0.single";
/** /**
* guy 表示一行数据通过position来定位位置的数据 * guy 表示一行数据通过position来定位位置的数据
* @class BI.Text * @class BI.Text
* @extends BI.Single * @extends BI.Single
*/ */
import { shortcut } from "../../core";
import { Single } from "./0.single";
@shortcut() @shortcut()
export class Text extends Single { export class Text extends Single {
@ -24,10 +25,29 @@ export class Text extends Single {
bgap: 0, bgap: 0,
py: "", py: "",
highLight: false, highLight: false,
} };
render() { render() {
const { vgap, hgap, lgap, rgap, tgap, bgap, height, lineHeight, maxWidth, textAlign, whiteSpace, handler, disabled, invalid, text: optionsText, value, keyword, highLight } = this.options; const {
vgap,
hgap,
lgap,
rgap,
tgap,
bgap,
height,
lineHeight,
maxWidth,
textAlign,
whiteSpace,
handler,
disabled,
invalid,
text: optionsText,
value,
keyword,
highLight,
} = this.options;
if (hgap + lgap > 0) { if (hgap + lgap > 0) {
this.element.css({ this.element.css({
"padding-left": BI.pixFormat(hgap + lgap), "padding-left": BI.pixFormat(hgap + lgap),
@ -58,21 +78,21 @@ export class Text extends Single {
this.element.css({ maxWidth: BI.pixFormat(maxWidth) }); this.element.css({ maxWidth: BI.pixFormat(maxWidth) });
} }
this.element.css({ this.element.css({
textAlign: textAlign, textAlign,
whiteSpace: this._getTextWrap(), whiteSpace: this._getTextWrap(),
textOverflow: whiteSpace === "nowrap" ? "ellipsis" : "", textOverflow: whiteSpace === "nowrap" ? "ellipsis" : "",
overflow: whiteSpace === "nowrap" ? "" : (BI.isWidthOrHeight(height) ? "auto" : ""), overflow: whiteSpace === "nowrap" ? "" : BI.isWidthOrHeight(height) ? "auto" : "",
}); });
if (handler && handler !== BI.emptyFn) { if (handler && handler !== BI.emptyFn) {
this.text = BI.createWidget({ this.text = BI.createWidget({
type: "bi.layout", type: Layout.xtype,
tagName: "span", tagName: "span",
}); });
this.text.element.click((e) => { this.text.element.click(e => {
!disabled && !invalid && handler.call(this, this.getValue(), this, e); !disabled && !invalid && handler.call(this, this.getValue(), this, e);
}); });
BI.createWidget({ BI.createWidget({
type: "bi.default", type: DefaultLayout.xtype,
element: this, element: this,
items: [this.text], items: [this.text],
}); });
@ -80,9 +100,11 @@ export class Text extends Single {
this.text = this; this.text = this;
} }
const text = BI.isFunction(optionsText) ? this.__watch(optionsText, (context, newValue) => { const text = BI.isFunction(optionsText)
this.setText(newValue); ? this.__watch(optionsText, (context, newValue) => {
}) : optionsText; this.setText(newValue);
})
: optionsText;
// 只要不是undefined就可以显示text值,否则显示value // 只要不是undefined就可以显示text值,否则显示value
if (!BI.isUndefined(text)) { if (!BI.isUndefined(text)) {
this.setText(text); this.setText(text);
@ -100,12 +122,12 @@ export class Text extends Single {
_getTextWrap() { _getTextWrap() {
const { whiteSpace } = this.options; const { whiteSpace } = this.options;
switch (whiteSpace) { switch (whiteSpace) {
case "nowrap": case "nowrap":
return "pre"; return "pre";
case "normal": case "normal":
return "pre-wrap"; return "pre-wrap";
default: default:
return whiteSpace; return whiteSpace;
} }
} }
@ -113,7 +135,7 @@ export class Text extends Single {
const { text: optionsText } = this.options; const { text: optionsText } = this.options;
const text = BI.isFunction(optionsText) ? optionsText() : optionsText; const text = BI.isFunction(optionsText) ? optionsText() : optionsText;
return BI.isKey(text) ? Text.formatText(text + "") : text; return BI.isKey(text) ? Text.formatText(`${text}`) : text;
} }
_doRedMark(keyword) { _doRedMark(keyword) {
@ -162,10 +184,10 @@ export class Text extends Single {
} }
const formatters = []; const formatters = [];
Text.addTextFormatter = (formatter) => { Text.addTextFormatter = formatter => {
formatters.push(formatter); formatters.push(formatter);
}; };
Text.formatText = (text) => { Text.formatText = text => {
if (formatters.length > 0) { if (formatters.length > 0) {
for (let i = 0; i < formatters.length; i++) { for (let i = 0; i < formatters.length; i++) {
text = formatters[i](text); text = formatters[i](text);

52
src/base/single/a/a.js

@ -1,3 +1,6 @@
import { Text } from "../1.text";
import { shortcut, extend, createWidget } from "@/core";
/** /**
* 超链接 * 超链接
* *
@ -6,32 +9,31 @@
* @extends BI.Text * @extends BI.Text
* @abstract * @abstract
*/ */
import { shortcut, extend, createWidget } from "../../../core";
import { Text } from "../1.text";
@shortcut() @shortcut()
export class A extends Text { export class A extends Text {
static xtype = "bi.a"; static xtype = "bi.a";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: `${conf.baseCls || ""} bi-a display-block`, baseCls: `${conf.baseCls || ""} bi-a display-block`,
href: "", href: "",
target: "_blank", target: "_blank",
el: null, el: null,
tagName: "a", tagName: "a",
}); });
} }
render() { render() {
const { href, target, el } = this.options; const { href, target, el } = this.options;
super.render(); super.render();
this.element.attr({ href, target }); this.element.attr({ href, target });
if (el) { if (el) {
createWidget(el, { createWidget(el, {
element: this, element: this,
}); });
} }
} }
} }

19
src/base/single/bar/bar.loading.js

@ -1,8 +1,9 @@
import { shortcut, emptyFn } from "@/core"; import { TextButton } from "../button";
import { Layout, CenterAdaptLayout, CardLayout, shortcut, emptyFn } from "@/core";
import { Single } from "../0.single"; import { Single } from "../0.single";
@shortcut() @shortcut()
class LoadingBar extends Single { export class LoadingBar extends Single {
static xtype = "bi.loading_bar"; static xtype = "bi.loading_bar";
_defaultConfig() { _defaultConfig() {
@ -18,7 +19,7 @@ class LoadingBar extends Single {
render() { render() {
this.loaded = BI.createWidget({ this.loaded = BI.createWidget({
type: "bi.text_button", type: TextButton.xtype,
cls: "loading-text bi-list-item-simple", cls: "loading-text bi-list-item-simple",
text: BI.i18nText("BI-Load_More"), text: BI.i18nText("BI-Load_More"),
width: 120, width: 120,
@ -29,27 +30,28 @@ class LoadingBar extends Single {
}); });
this.loading = BI.createWidget({ this.loading = BI.createWidget({
type: "bi.layout", type: Layout.xtype,
width: this.options.height, width: this.options.height,
height: this.options.height, height: this.options.height,
cls: "loading-background cursor-default", cls: "loading-background cursor-default",
}); });
const loaded = BI.createWidget({ const loaded = BI.createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
items: [this.loaded], items: [this.loaded],
}); });
const loading = BI.createWidget({ const loading = BI.createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
items: [this.loading], items: [this.loading],
}); });
this.cardLayout = BI.createWidget({ this.cardLayout = BI.createWidget({
type: "bi.card", type: CardLayout.xtype,
element: this, element: this,
items: [ items: [
{ {
el: loaded, el: loaded,
cardName: "loaded", cardName: "loaded",
}, { },
{
el: loading, el: loading,
cardName: "loading", cardName: "loading",
} }
@ -80,4 +82,3 @@ class LoadingBar extends Single {
this.cardLayout.showCardByName("loading"); this.cardLayout.showCardByName("loading");
} }
} }

333
src/base/single/button/button.basic.js

@ -1,5 +1,17 @@
import {
Layout,
AbsoluteLayout,
emptyFn,
shortcut,
extend,
isFunction,
createWidget,
Widget,
isObject,
Controller
} from "@/core";
import { BubbleCombo } from "@/case/combo/bubblecombo/combo.bubble";
import { Single } from "../0.single"; import { Single } from "../0.single";
import { emptyFn, shortcut, extend, isFunction, createWidget, Widget, isObject, Controller } from "../../../core";
/** /**
* guy * guy
@ -18,7 +30,9 @@ export class BasicButton extends Single {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
_baseCls: `${conf._baseCls || ""} bi-basic-button${conf.invalid ? "" : " cursor-pointer"}${(BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""}`, _baseCls: `${conf._baseCls || ""} bi-basic-button${conf.invalid ? "" : " cursor-pointer"}${
BI.isIE() && BI.getIEVersion() < 10 ? " hack" : ""
}`,
// el: {} // 可以通过el来创建button元素 // el: {} // 可以通过el来创建button元素
value: "", value: "",
stopEvent: false, stopEvent: false,
@ -40,9 +54,11 @@ export class BasicButton extends Single {
_init() { _init() {
const opts = this.options; const opts = this.options;
opts.selected = isFunction(opts.selected) ? this.__watch(opts.selected, (context, newValue) => { opts.selected = isFunction(opts.selected)
this.setSelected(newValue); ? this.__watch(opts.selected, (context, newValue) => {
}) : opts.selected; this.setSelected(newValue);
})
: opts.selected;
super._init(arguments); super._init(arguments);
if (opts.shadow) { if (opts.shadow) {
@ -75,20 +91,22 @@ export class BasicButton extends Single {
const assertMask = () => { const assertMask = () => {
if (!this.$mask) { if (!this.$mask) {
this.$mask = createWidget(isObject(o.shadow) ? o.shadow : {}, { this.$mask = createWidget(isObject(o.shadow) ? o.shadow : {}, {
type: "bi.layout", type: Layout.xtype,
cls: "bi-button-mask", cls: "bi-button-mask",
}); });
this.$mask.invisible(); this.$mask.invisible();
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items: [{ items: [
el: this.$mask, {
left: 0, el: this.$mask,
right: 0, left: 0,
top: 0, right: 0,
bottom: 0, top: 0,
}], bottom: 0,
},
],
}); });
} }
}; };
@ -99,7 +117,7 @@ export class BasicButton extends Single {
this.$mask.invisible(); this.$mask.invisible();
} }
}); });
this.element.on(`mouseenter.${this.getName()}`, e => { this.element.on(`mouseenter.${this.getName()}`, (e) => {
if (this.element.__isMouseInBounds__(e)) { if (this.element.__isMouseInBounds__(e)) {
if (this.isEnabled() && !this._hover && (o.isShadowShowingOnSelected || !this.isSelected())) { if (this.isEnabled() && !this._hover && (o.isShadowShowingOnSelected || !this.isSelected())) {
assertMask(); assertMask();
@ -107,7 +125,7 @@ export class BasicButton extends Single {
} }
} }
}); });
this.element.on(`mousemove.${this.getName()}`, e => { this.element.on(`mousemove.${this.getName()}`, (e) => {
if (!this.element.__isMouseInBounds__(e)) { if (!this.element.__isMouseInBounds__(e)) {
if (this.isEnabled() && !this._hover) { if (this.isEnabled() && !this._hover) {
assertMask(); assertMask();
@ -140,7 +158,7 @@ export class BasicButton extends Single {
return bubble; return bubble;
}; };
const clk = e => { const clk = (e) => {
ev(e); ev(e);
if (!this.isEnabled() || !this.isValid()) { if (!this.isEnabled() || !this.isValid()) {
return; return;
@ -152,50 +170,56 @@ export class BasicButton extends Single {
if (BI.isNull(this.combo)) { if (BI.isNull(this.combo)) {
let popup; let popup;
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items: [{ items: [
el: { {
type: "bi.bubble_combo",
trigger: "",
// bubble的提示不需要一直存在在界面上
destroyWhenHide: true,
ref: _ref => {
this.combo = _ref;
},
el: { el: {
type: "bi.layout", type: BubbleCombo.xtype,
height: "100%", trigger: "",
}, // bubble的提示不需要一直存在在界面上
popup: { destroyWhenHide: true,
type: "bi.text_bubble_bar_popup_view", ref: (_ref) => {
text: getBubble(), this.combo = _ref;
ref: _ref => { },
popup = _ref; el: {
type: Layout.xtype,
height: "100%",
}, },
listeners: [{ popup: {
eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON, type: "bi.text_bubble_bar_popup_view",
action: (...args) => { text: getBubble(),
const [v] = args; ref: (_ref) => {
this.combo.hideView(); popup = _ref;
if (v) {
onClick.apply(this, args);
}
}, },
}], listeners: [
}, {
listeners: [{ eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON,
eventName: BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW, action: (...args) => {
action () { const [v] = args;
popup.populate(getBubble()); this.combo.hideView();
if (v) {
onClick.apply(this, args);
}
},
},
],
}, },
}], listeners: [
{
eventName: BubbleCombo.EVENT_BEFORE_POPUPVIEW,
action() {
popup.populate(getBubble());
},
},
],
},
left: 0,
right: 0,
bottom: 0,
top: 0,
}, },
left: 0, ],
right: 0,
bottom: 0,
top: 0,
}],
}); });
} }
if (this.combo.isViewVisible()) { if (this.combo.isViewVisible()) {
@ -209,112 +233,119 @@ export class BasicButton extends Single {
onClick.apply(this, arguments); onClick.apply(this, arguments);
}; };
const triggerArr = (o.trigger || "").split(","); const triggerArr = (o.trigger || "").split(",");
triggerArr.forEach(trigger => { triggerArr.forEach((trigger) => {
let mouseDown = false; let mouseDown = false;
let selected = false; let selected = false;
let interval; let interval;
switch (trigger) { switch (trigger) {
case "mouseup": case "mouseup":
hand.mousedown(() => { hand.mousedown(() => {
mouseDown = true; mouseDown = true;
}); });
hand.mouseup(e => { hand.mouseup((e) => {
if (mouseDown === true) { if (mouseDown === true) {
clk(e); clk(e);
}
mouseDown = false;
ev(e);
});
break;
case "mousedown":
// let mouseDown = false;
hand.mousedown(e => {
// if (e.button === 0) {
Widget._renderEngine.createElement(document).bind(`mouseup.${this.getName()}`, e => {
// if (e.button === 0) {
if (BI.DOM.isExist(this) && !hand.__isMouseInBounds__(e) && mouseDown === true && !selected) {
// self.setSelected(!self.isSelected());
this._trigger();
} }
mouseDown = false; mouseDown = false;
Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`); ev(e);
});
break;
case "mousedown":
// let mouseDown = false;
hand.mousedown((e) => {
// if (e.button === 0) {
Widget._renderEngine.createElement(document).bind(`mouseup.${this.getName()}`, (e) => {
// if (e.button === 0) {
if (
BI.DOM.isExist(this) &&
!hand.__isMouseInBounds__(e) &&
mouseDown === true &&
!selected
) {
// self.setSelected(!self.isSelected());
this._trigger();
}
mouseDown = false;
Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`);
// }
});
if (mouseDown === true) {
return;
}
if (this.isSelected()) {
selected = true;
} else {
clk(e);
}
mouseDown = true;
ev(e);
// } // }
}); });
if (mouseDown === true) { hand.mouseup((e) => {
return; // if (e.button === 0) {
} if (BI.DOM.isExist(this) && mouseDown === true && selected === true) {
if (this.isSelected()) { clk(e);
selected = true; }
} else {
clk(e);
}
mouseDown = true;
ev(e);
// }
});
hand.mouseup(e => {
// if (e.button === 0) {
if (BI.DOM.isExist(this) && mouseDown === true && selected === true) {
clk(e);
}
mouseDown = false;
selected = false;
Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`);
// }
});
break;
case "dblclick":
hand.dblclick(clk);
break;
case "lclick":
hand.mousedown(e => {
Widget._renderEngine.createElement(document).bind(`mouseup.${this.getName()}`, () => {
interval && clearInterval(interval);
interval = null;
mouseDown = false; mouseDown = false;
selected = false;
Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`); Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`);
// }
}); });
if (mouseDown === true) { break;
return; case "dblclick":
} hand.dblclick(clk);
if (!this.isEnabled() || !this.isValid()) { break;
return; case "lclick":
} hand.mousedown((e) => {
if (this.isOnce() && this.isSelected()) { Widget._renderEngine.createElement(document).bind(`mouseup.${this.getName()}`, () => {
return; interval && clearInterval(interval);
} interval = null;
interval = setInterval(() => { mouseDown = false;
clk(e); Widget._renderEngine.createElement(document).unbind(`mouseup.${this.getName()}`);
}, 180); });
mouseDown = true; if (mouseDown === true) {
ev(e); return;
}); }
break; if (!this.isEnabled() || !this.isValid()) {
default: return;
if (o.stopEvent || o.stopPropagation) { }
hand.mousedown(e => { if (this.isOnce() && this.isSelected()) {
return;
}
interval = setInterval(() => {
clk(e);
}, 180);
mouseDown = true;
ev(e); ev(e);
}); });
} break;
hand.click(clk); default:
// enter键等同于点击 if (o.stopEvent || o.stopPropagation) {
o.attributes && o.attributes.zIndex >= 0 && hand.keyup(e => { hand.mousedown((e) => {
if (e.keyCode === BI.KeyCode.ENTER) { ev(e);
clk(e); });
} }
}); hand.click(clk);
break; // enter键等同于点击
o.attributes &&
o.attributes.zIndex >= 0 &&
hand.keyup((e) => {
if (e.keyCode === BI.KeyCode.ENTER) {
clk(e);
}
});
break;
} }
}); });
// 之后的300ms点击无效 // 之后的300ms点击无效
const onClick = o.debounce ? BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, { const onClick = o.debounce
leading: true, ? BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, {
trailing: false, leading: true,
}) : this._doClick; trailing: false,
})
: this._doClick;
function ev(e) { function ev(e) {
if (o.stopEvent) { if (o.stopEvent) {
@ -332,9 +363,11 @@ export class BasicButton extends Single {
return; return;
} }
if (!this.isDisableSelected()) { if (!this.isDisableSelected()) {
this.isForceSelected() ? this.setSelected(true) : this.isForceSelected()
(this.isForceNotSelected() ? this.setSelected(false) : ? this.setSelected(true)
this.setSelected(!this.isSelected())); : this.isForceNotSelected()
? this.setSelected(false)
: this.setSelected(!this.isSelected());
} }
if (this.isValid()) { if (this.isValid()) {
const v = this.getValue(); const v = this.getValue();
@ -367,13 +400,9 @@ export class BasicButton extends Single {
/** /**
* 子类可以得写这个方法如果返回为 true则可以阻止 handler 的触发 * 子类可以得写这个方法如果返回为 true则可以阻止 handler 的触发
*/ */
beforeClick() { beforeClick() {}
} doClick() {}
doClick() {
}
handle() { handle() {
return this; return this;
@ -457,5 +486,3 @@ export class BasicButton extends Single {
super.empty(...arguments); super.empty(...arguments);
} }
} }

2
src/base/single/button/button.node.js

@ -1,5 +1,5 @@
import { BasicButton } from "./button.basic"; import { BasicButton } from "./button.basic";
import { shortcut, extend, Controller } from "../../../core"; import { shortcut, extend, Controller } from "@/core";
/** /**
* 表示一个可以展开的节点, 不仅有选中状态而且有展开状态 * 表示一个可以展开的节点, 不仅有选中状态而且有展开状态

9
src/base/single/button/buttons/button.icon.js

@ -1,5 +1,6 @@
import { Icon } from "../../icon/icon";
import { DefaultLayout, CenterAdaptLayout, shortcut, extend, isNumber, createWidget, isNull } from "@/core";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { shortcut, extend, isNumber, createWidget, isNull } from "../../../../core";
/** /**
* @class IconButton * @class IconButton
@ -33,14 +34,14 @@ export class IconButton extends BasicButton {
textAlign: "center", textAlign: "center",
}); });
this.icon = createWidget({ this.icon = createWidget({
type: "bi.icon", type: Icon.xtype,
width: o.iconWidth, width: o.iconWidth,
height: o.iconHeight, height: o.iconHeight,
}); });
if (isNumber(o.height) && o.height > 0 && isNull(o.iconWidth) && isNull(o.iconHeight)) { if (isNumber(o.height) && o.height > 0 && isNull(o.iconWidth) && isNull(o.iconHeight)) {
this.element.css("lineHeight", BI.pixFormat(o.height)); this.element.css("lineHeight", BI.pixFormat(o.height));
createWidget({ createWidget({
type: "bi.default", type: DefaultLayout.xtype,
element: this, element: this,
hgap: o.hgap, hgap: o.hgap,
vgap: o.vgap, vgap: o.vgap,
@ -54,7 +55,7 @@ export class IconButton extends BasicButton {
this.element.css("lineHeight", "1"); this.element.css("lineHeight", "1");
createWidget({ createWidget({
element: this, element: this,
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
hgap: o.hgap, hgap: o.hgap,
vgap: o.vgap, vgap: o.vgap,
lgap: o.lgap, lgap: o.lgap,

10
src/base/single/button/buttons/button.image.js

@ -1,6 +1,6 @@
import { Img } from "../../img/img";
import { CenterAdaptLayout, AdaptiveLayout, shortcut, extend, isNumber, createWidget } from "@/core";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { shortcut, extend, isNumber, createWidget } from "../../../../core";
/** /**
* 图片的button * 图片的button
@ -28,20 +28,20 @@ export class ImageButton extends BasicButton {
render() { render() {
const o = this.options; const o = this.options;
this.image = createWidget({ this.image = createWidget({
type: "bi.img", type: Img.xtype,
width: o.iconWidth, width: o.iconWidth,
height: o.iconHeight, height: o.iconHeight,
src: o.src, src: o.src,
}); });
if (isNumber(o.iconWidth) || isNumber(o.iconHeight)) { if (isNumber(o.iconWidth) || isNumber(o.iconHeight)) {
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
element: this, element: this,
items: [this.image], items: [this.image],
}); });
} else { } else {
createWidget({ createWidget({
type: "bi.adaptive", type: AdaptiveLayout.xtype,
element: this, element: this,
items: [this.image], items: [this.image],
scrollable: false, scrollable: false,

41
src/base/single/button/buttons/button.js

@ -1,5 +1,6 @@
import { CenterAdaptLayout, isNumber, shortcut, isPlainObject, createWidget } from "@/core";
import { Label, IconLabel } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { isNumber, shortcut, isPlainObject, createWidget } from "../../../../core";
function isVertical(position) { function isVertical(position) {
return position === "top" || position === "bottom"; return position === "top" || position === "bottom";
@ -19,7 +20,7 @@ const loadingCls = "button-loading-font anim-rotate";
export class Button extends BasicButton { export class Button extends BasicButton {
_const = { _const = {
iconWidth: 18, iconWidth: 18,
} };
static xtype = "bi.button"; static xtype = "bi.button";
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
@ -34,14 +35,14 @@ export class Button extends BasicButton {
adaptiveHeight += props.iconGap || 0; adaptiveHeight += props.iconGap || 0;
const tGap = props.tgap || props.vgap || 2; const tGap = props.tgap || props.vgap || 2;
const bGap = props.bgap || props.vgap || 2; const bGap = props.bgap || props.vgap || 2;
adaptiveHeight += (tGap + bGap); adaptiveHeight += tGap + bGap;
} }
const clearMinWidth = props.block === true || props.clear === true || props.plain; const clearMinWidth = props.block === true || props.clear === true || props.plain;
return { return {
...conf, ...conf,
baseCls: `${conf.baseCls || ""} bi-button${(BI.isIE() && BI.isIE9Below()) ? " hack" : ""}`, baseCls: `${conf.baseCls || ""} bi-button${BI.isIE() && BI.isIE9Below() ? " hack" : ""}`,
attributes: { attributes: {
tabIndex: 1, tabIndex: 1,
}, },
@ -62,7 +63,7 @@ export class Button extends BasicButton {
whiteSpace: "nowrap", whiteSpace: "nowrap",
textWidth: null, textWidth: null,
textHeight: null, textHeight: null,
hgap: props.clear ? 0 : (props.plain && !props.text ? 4 : 10), hgap: props.clear ? 0 : props.plain && !props.text ? 4 : 10,
vgap: 0, vgap: 0,
tgap: 0, tgap: 0,
bgap: 0, bgap: 0,
@ -79,7 +80,7 @@ export class Button extends BasicButton {
// bi.center_adapt 作用:让 hgap 不影响 iconGap。 // bi.center_adapt 作用:让 hgap 不影响 iconGap。
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
horizontalAlign: o.textAlign, horizontalAlign: o.textAlign,
element: this, element: this,
ref: ref => { ref: ref => {
@ -107,7 +108,8 @@ export class Button extends BasicButton {
const o = this.options; const o = this.options;
// 由于button默认情况下有个边框,所以要主动算行高 // 由于button默认情况下有个边框,所以要主动算行高
let lineHeight, textHeight = o.textHeight; let lineHeight,
textHeight = o.textHeight;
let hasBorder = false; let hasBorder = false;
if (isNumber(o.height)) { if (isNumber(o.height)) {
if (!isVertical(o.iconPosition)) { if (!isVertical(o.iconPosition)) {
@ -128,13 +130,13 @@ export class Button extends BasicButton {
const iconInvisible = !(o.loading || o.iconCls || o.icon || defaultRenderIcon); const iconInvisible = !(o.loading || o.iconCls || o.icon || defaultRenderIcon);
let maxTextWidth = Math.max(o.minWidth, o.width); let maxTextWidth = Math.max(o.minWidth, o.width);
maxTextWidth -= (o.hgap * 2 + o.iconGap); maxTextWidth -= o.hgap * 2 + o.iconGap;
// 减去图标水平占位宽度 // 减去图标水平占位宽度
maxTextWidth -= iconInvisible || isVertical(o.iconPosition) ? 0 : this._const.iconWidth; maxTextWidth -= iconInvisible || isVertical(o.iconPosition) ? 0 : this._const.iconWidth;
const textWidth = BI.isNull(o.textWidth) ? maxTextWidth : Math.min(o.textWidth, maxTextWidth); const textWidth = BI.isNull(o.textWidth) ? maxTextWidth : Math.min(o.textWidth, maxTextWidth);
this.text = createWidget({ this.text = createWidget({
type: "bi.label", type: Label.xtype,
text: o.text, text: o.text,
whiteSpace: o.whiteSpace, whiteSpace: o.whiteSpace,
textAlign: o.textAlign, textAlign: o.textAlign,
@ -155,8 +157,8 @@ export class Button extends BasicButton {
this.icon = createWidget(o.icon); this.icon = createWidget(o.icon);
} else { } else {
this.icon = createWidget({ this.icon = createWidget({
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.loading ? loadingCls : (o.iconCls || o.icon), cls: o.loading ? loadingCls : o.iconCls || o.icon,
width: this._const.iconWidth, width: this._const.iconWidth,
height: BI.toPix(lineHeight, hasBorder ? 2 : 0), height: BI.toPix(lineHeight, hasBorder ? 2 : 0),
lineHeight: BI.toPix(lineHeight, hasBorder ? 2 : 0), lineHeight: BI.toPix(lineHeight, hasBorder ? 2 : 0),
@ -179,12 +181,14 @@ export class Button extends BasicButton {
items.reverse(); items.reverse();
} }
return [{ return [
type: isVertical(o.iconPosition) ? "bi.vertical" : "bi.horizontal", {
horizontalAlign: "center", type: isVertical(o.iconPosition) ? "bi.vertical" : "bi.horizontal",
verticalAlign: "middle", horizontalAlign: "center",
items, verticalAlign: "middle",
}]; items,
}
];
} }
doClick() { doClick() {
@ -272,4 +276,3 @@ export class Button extends BasicButton {
this.text.unHighLight(...arguments); this.text.unHighLight(...arguments);
} }
} }

5
src/base/single/button/buttons/button.text.js

@ -1,5 +1,6 @@
import { Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { shortcut, extend, createWidget, isArray } from "../../../../core"; import { shortcut, extend, createWidget, isArray } from "@/core";
/** /**
* guy * guy
@ -33,7 +34,7 @@ export class TextButton extends BasicButton {
render() { render() {
const o = this.options; const o = this.options;
this.text = createWidget({ this.text = createWidget({
type: "bi.label", type: Label.xtype,
element: this, element: this,
textAlign: o.textAlign, textAlign: o.textAlign,
whiteSpace: o.whiteSpace, whiteSpace: o.whiteSpace,

34
src/base/single/button/index.js

@ -1,17 +1,17 @@
export { BasicButton } from "./button.basic"; export { BasicButton } from "./button.basic";
export { NodeButton } from "./button.node"; export { NodeButton } from "./button.node";
export { Button } from "./buttons/button"; export { Button } from "./buttons/button";
export { IconButton } from "./buttons/button.icon"; export { IconButton } from "./buttons/button.icon";
export { ImageButton } from "./buttons/button.image"; export { ImageButton } from "./buttons/button.image";
export { TextButton } from "./buttons/button.text"; export { TextButton } from "./buttons/button.text";
export { BlankIconIconTextItem } from "./listitem/blankiconicontextitem"; export { BlankIconIconTextItem } from "./listitem/blankiconicontextitem";
export { BlankIconTextIconItem } from "./listitem/blankicontexticonitem"; export { BlankIconTextIconItem } from "./listitem/blankicontexticonitem";
export { BlankIconTextItem } from "./listitem/blankicontextitem"; export { BlankIconTextItem } from "./listitem/blankicontextitem";
export { IconTextIconItem } from "./listitem/icontexticonitem"; export { IconTextIconItem } from "./listitem/icontexticonitem";
export { IconTextItem } from "./listitem/icontextitem"; export { IconTextItem } from "./listitem/icontextitem";
export { TextIconItem } from "./listitem/texticonitem"; export { TextIconItem } from "./listitem/texticonitem";
export { TextItem } from "./listitem/textitem"; export { TextItem } from "./listitem/textitem";
export { IconTextIconNode } from "./node/icontexticonnode"; export { IconTextIconNode } from "./node/icontexticonnode";
export { IconTextNode } from "./node/icontextnode"; export { IconTextNode } from "./node/icontextnode";
export { TextIconNode } from "./node/texticonnode"; export { TextIconNode } from "./node/texticonnode";
export { TextNode } from "./node/textnode"; export { TextNode } from "./node/textnode";

74
src/base/single/button/listitem/blankiconicontextitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, Layout, shortcut, extend } from "@/core";
import { IconLabel, Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { shortcut, extend } from "../../../../core";
/** /**
* 带有一个占位 * 带有一个占位
@ -34,42 +35,47 @@ export class BlankIconIconTextItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.blankWidth, o.leftIconWrapperWidth || o.height, o.rightIconWrapperWidth || o.height, "fill"], columnSize: [o.blankWidth, o.leftIconWrapperWidth || o.height, o.rightIconWrapperWidth || o.height, "fill"],
items: [{ items: [
type: "bi.layout", {
width: o.blankWidth, type: Layout.xtype,
}, { width: o.blankWidth,
type: "bi.icon_label", },
cls: o.iconCls1, {
width: o.leftIconWrapperWidth || o.height, type: IconLabel.xtype,
height: o.height, cls: o.iconCls1,
iconWidth: o.iconWidth, width: o.leftIconWrapperWidth || o.height,
iconHeight: o.iconHeight,
}, {
type: "bi.icon_label",
cls: o.iconCls2,
width: o.rightIconWrapperWidth || o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, },
}], {
type: IconLabel.xtype,
cls: o.iconCls2,
width: o.rightIconWrapperWidth || o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
},
{
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}
],
}; };
} }

75
src/base/single/button/listitem/blankicontexticonitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, Layout, shortcut, extend } from "@/core";
import { IconLabel, Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { shortcut, extend } from "../../../../core";
/** /**
* guy * guy
@ -35,42 +36,47 @@ export class BlankIconTextIconItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.blankWidth, o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height], columnSize: [o.blankWidth, o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height],
items: [{ items: [
type: "bi.layout", {
width: o.blankWidth, type: Layout.xtype,
}, { width: o.blankWidth,
type: "bi.icon_label", },
cls: o.iconCls1, {
width: o.leftIconWrapperWidth || o.height, type: IconLabel.xtype,
height: o.height, cls: o.iconCls1,
iconWidth: o.iconWidth, width: o.leftIconWrapperWidth || o.height,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
},
{
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}, },
}, { {
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.iconCls2, cls: o.iconCls2,
width: o.rightIconWrapperWidth || o.height, width: o.rightIconWrapperWidth || o.height,
height: o.height, height: o.height,
iconWidth: o.iconWidth, iconWidth: o.iconWidth,
iconHeight: o.iconHeight, iconHeight: o.iconHeight,
}], }
],
}; };
} }
@ -115,4 +121,3 @@ export class BlankIconTextIconItem extends BasicButton {
return this.text.getText(); return this.text.getText();
} }
} }

61
src/base/single/button/listitem/blankicontextitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, Layout, extend, shortcut } from "@/core";
import { IconLabel, Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { extend, shortcut } from "../../../../core";
/** /**
* 带有一个占位 * 带有一个占位
@ -33,36 +34,40 @@ export class BlankIconTextItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.blankWidth, o.iconWrapperWidth || o.height, "fill"], columnSize: [o.blankWidth, o.iconWrapperWidth || o.height, "fill"],
items: [{ items: [
type: "bi.layout", {
width: o.blankWidth, type: Layout.xtype,
}, { width: o.blankWidth,
type: "bi.icon_label", },
cls: o.iconCls, {
width: o.iconWrapperWidth || o.height, type: IconLabel.xtype,
height: o.height, cls: o.iconCls,
iconWidth: o.iconWidth, width: o.iconWrapperWidth || o.height,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, },
}], {
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}
],
}; };
} }

67
src/base/single/button/listitem/icontexticonitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { IconLabel, Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { extend, shortcut } from "../../../../core";
/** /**
* guy * guy
@ -35,39 +36,43 @@ export class IconTextIconItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height], columnSize: [o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height],
items: [{ items: [
type: "bi.icon_label", {
cls: o.iconCls1, type: IconLabel.xtype,
width: o.leftIconWrapperWidth || o.height, cls: o.iconCls1,
height: o.height, width: o.leftIconWrapperWidth || o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
},
{
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}, },
}, { {
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.iconCls2, cls: o.iconCls2,
width: o.rightIconWrapperWidth || o.height, width: o.rightIconWrapperWidth || o.height,
height: o.height, height: o.height,
iconWidth: o.iconWidth, iconWidth: o.iconWidth,
iconHeight: o.iconHeight, iconHeight: o.iconHeight,
}], }
],
}; };
} }

54
src/base/single/button/listitem/icontextitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { IconLabel, Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { extend, shortcut } from "../../../../core";
/** /**
* guy * guy
@ -34,33 +35,36 @@ export class IconTextItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.iconWrapperWidth || o.height, "fill"], columnSize: [o.iconWrapperWidth || o.height, "fill"],
items: [{ items: [
type: "bi.icon_label", {
cls: o.iconCls, type: IconLabel.xtype,
width: o.iconWrapperWidth || o.height, cls: o.iconCls,
height: o.height, width: o.iconWrapperWidth || o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, },
}], {
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}
],
}; };
} }

56
src/base/single/button/listitem/texticonitem.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { Label, IconLabel } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { extend, shortcut } from "../../../../core";
/** /**
* *
@ -12,7 +13,7 @@ import { extend, shortcut } from "../../../../core";
@shortcut() @shortcut()
export class TextIconItem extends BasicButton { export class TextIconItem extends BasicButton {
static xtype = "bi.text_icon_item"; static xtype = "bi.text_icon_item";
static EVENT_CHANGE = "EVENT_CHANGE" static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
@ -34,33 +35,36 @@ export class TextIconItem extends BasicButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: ["fill", o.iconWrapperWidth || o.height], columnSize: ["fill", o.iconWrapperWidth || o.height],
items: [{ items: [
el: { {
type: "bi.label", el: {
ref: _ref => { type: Label.xtype,
this.text = _ref; ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
}, },
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
}, },
}, { {
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.iconCls, cls: o.iconCls,
width: o.iconWrapperWidth || o.height, width: o.iconWrapperWidth || o.height,
height: o.height, height: o.height,
iconWidth: o.iconWidth, iconWidth: o.iconWidth,
iconHeight: o.iconHeight, iconHeight: o.iconHeight,
}], }
],
}; };
} }

5
src/base/single/button/listitem/textitem.js

@ -1,5 +1,6 @@
import { Label } from "../../label";
import { BasicButton } from "../button.basic"; import { BasicButton } from "../button.basic";
import { extend, shortcut, createWidget } from "../../../../core"; import { extend, shortcut, createWidget } from "@/core";
/** /**
* guy * guy
@ -31,7 +32,7 @@ export class TextItem extends BasicButton {
render() { render() {
const o = this.options; const o = this.options;
this.text = createWidget({ this.text = createWidget({
type: "bi.label", type: Label.xtype,
element: this, element: this,
textAlign: o.textAlign, textAlign: o.textAlign,
whiteSpace: o.whiteSpace, whiteSpace: o.whiteSpace,

67
src/base/single/button/node/icontexticonnode.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { IconLabel, Label } from "../../label";
import { NodeButton } from "../button.node"; import { NodeButton } from "../button.node";
import { extend, shortcut } from "../../../../core";
/** /**
* guy * guy
@ -32,39 +33,43 @@ export class IconTextIconNode extends NodeButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height], columnSize: [o.leftIconWrapperWidth || o.height, "fill", o.rightIconWrapperWidth || o.height],
items: [{ items: [
type: "bi.icon_label", {
cls: o.iconCls1, type: IconLabel.xtype,
width: o.leftIconWrapperWidth || o.height, cls: o.iconCls1,
height: o.height, width: o.leftIconWrapperWidth || o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
},
{
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}, },
}, { {
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.iconCls2, cls: o.iconCls2,
width: o.rightIconWrapperWidth || o.height, width: o.rightIconWrapperWidth || o.height,
height: o.height, height: o.height,
iconWidth: o.iconWidth, iconWidth: o.iconWidth,
iconHeight: o.iconHeight, iconHeight: o.iconHeight,
}], }
],
}; };
} }

55
src/base/single/button/node/icontextnode.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { IconLabel, Label } from "../../label";
import { NodeButton } from "../button.node"; import { NodeButton } from "../button.node";
import { extend, shortcut } from "../../../../core";
/** /**
* guy * guy
@ -31,33 +32,36 @@ export class IconTextNode extends NodeButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: [o.iconWrapperWidth || o.height, "fill"], columnSize: [o.iconWrapperWidth || o.height, "fill"],
items: [{ items: [
type: "bi.icon_label", {
cls: o.iconCls, type: IconLabel.xtype,
width: o.iconWrapperWidth || o.height, cls: o.iconCls,
height: o.height, width: o.iconWrapperWidth || o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, {
el: {
type: "bi.label",
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height, height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight,
}, },
}], {
el: {
type: Label.xtype,
ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
},
}
],
}; };
} }
@ -94,4 +98,3 @@ export class IconTextNode extends NodeButton {
this.text.unRedMark(...arguments); this.text.unRedMark(...arguments);
} }
} }

55
src/base/single/button/node/texticonnode.js

@ -1,5 +1,6 @@
import { VerticalAdaptLayout, extend, shortcut } from "@/core";
import { Label, IconLabel } from "../../label";
import { NodeButton } from "../button.node"; import { NodeButton } from "../button.node";
import { extend, shortcut } from "../../../../core";
/** /**
* Created by GUY on 2015/9/9. * Created by GUY on 2015/9/9.
@ -8,7 +9,6 @@ import { extend, shortcut } from "../../../../core";
*/ */
@shortcut() @shortcut()
export class TextIconNode extends NodeButton { export class TextIconNode extends NodeButton {
static EVENT_CHANGE = "EVENT_CHANGE"; static EVENT_CHANGE = "EVENT_CHANGE";
static xtype = "bi.text_icon_node"; static xtype = "bi.text_icon_node";
@ -31,33 +31,36 @@ export class TextIconNode extends NodeButton {
const o = this.options; const o = this.options;
return { return {
type: "bi.vertical_adapt", type: VerticalAdaptLayout.xtype,
columnSize: ["fill", o.iconWrapperWidth || o.height], columnSize: ["fill", o.iconWrapperWidth || o.height],
items: [{ items: [
el: { {
type: "bi.label", el: {
ref: _ref => { type: Label.xtype,
this.text = _ref; ref: _ref => {
this.text = _ref;
},
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
}, },
cls: "list-item-text",
textAlign: "left",
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
height: o.height,
}, },
}, { {
type: "bi.icon_label", type: IconLabel.xtype,
cls: o.iconCls, cls: o.iconCls,
width: o.iconWrapperWidth || o.height, width: o.iconWrapperWidth || o.height,
height: o.height, height: o.height,
iconWidth: o.iconWidth, iconWidth: o.iconWidth,
iconHeight: o.iconHeight, iconHeight: o.iconHeight,
}], }
],
}; };
} }

10
src/base/single/button/node/textnode.js

@ -1,5 +1,6 @@
import { Label } from "../../label";
import { NodeButton } from "../button.node"; import { NodeButton } from "../button.node";
import { extend, shortcut, createWidget } from "../../../../core"; import { extend, shortcut, createWidget } from "@/core";
/** /**
* guy * guy
@ -10,10 +11,9 @@ import { extend, shortcut, createWidget } from "../../../../core";
*/ */
@shortcut() @shortcut()
export class TextNode extends NodeButton { export class TextNode extends NodeButton {
static xtype = "bi.text_node" static xtype = "bi.text_node";
static EVENT_CHANGE = "EVENT_CHANGE"
static EVENT_CHANGE = "EVENT_CHANGE";
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
@ -32,7 +32,7 @@ export class TextNode extends NodeButton {
render() { render() {
const o = this.options; const o = this.options;
this.text = createWidget({ this.text = createWidget({
type: "bi.label", type: Label.xtype,
element: this, element: this,
textAlign: o.textAlign, textAlign: o.textAlign,
whiteSpace: o.whiteSpace, whiteSpace: o.whiteSpace,

67
src/base/single/editor/editor.js

@ -1,12 +1,25 @@
import { Input } from "../input";
import {
AbsoluteLayout,
shortcut,
Controller,
extend,
createWidget,
isKey,
isEmptyString,
isFunction,
isNull,
trim
} from "@/core";
import { Label } from "../label";
import { Single } from "../0.single";
import { Bubbles } from "@/base";
/** /**
* Created by GUY on 2015/4/15. * Created by GUY on 2015/4/15.
* @class BI.Editor * @class BI.Editor
* @extends BI.Single * @extends BI.Single
*/ */
import { shortcut, Controller, extend, createWidget, isKey, isEmptyString, isFunction, isNull, trim } from "../../../core";
import { Single } from "../0.single";
import { Input } from "../input/input";
import { Bubbles } from "../../0.base";
@shortcut() @shortcut()
export class Editor extends Single { export class Editor extends Single {
@ -57,19 +70,34 @@ export class Editor extends Single {
} }
render() { render() {
const { value, watermark, validationChecker, quitChecker, allowBlank, inputType, hgap, vgap, lgap, rgap, tgap, bgap } = this.options; const {
// 密码输入框设置autocomplete="new-password"的情况下Firefox和chrome不会自动填充密码
const autocomplete = this.options.autocomplete ? ` autocomplete=${this.options.autocomplete}` : "";
this.editor = this.addWidget(createWidget({
type: "bi.input",
element: `<input type='${inputType}'${autocomplete} />`,
root: true,
value, value,
watermark, watermark,
validationChecker, validationChecker,
quitChecker, quitChecker,
allowBlank, allowBlank,
})); inputType,
hgap,
vgap,
lgap,
rgap,
tgap,
bgap,
} = this.options;
// 密码输入框设置autocomplete="new-password"的情况下Firefox和chrome不会自动填充密码
const autocomplete = this.options.autocomplete ? ` autocomplete=${this.options.autocomplete}` : "";
this.editor = this.addWidget(
createWidget({
type: Input.xtype,
element: `<input type='${inputType}'${autocomplete} />`,
root: true,
value,
watermark,
validationChecker,
quitChecker,
allowBlank,
})
);
this.editor.element.css({ this.editor.element.css({
width: "100%", width: "100%",
height: "100%", height: "100%",
@ -82,7 +110,7 @@ export class Editor extends Single {
const items = [ const items = [
{ {
el: { el: {
type: "bi.absolute", type: AbsoluteLayout.xtype,
ref: _ref => { ref: _ref => {
this.contentWrapper = _ref; this.contentWrapper = _ref;
}, },
@ -104,7 +132,7 @@ export class Editor extends Single {
]; ];
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items, items,
}); });
@ -157,9 +185,10 @@ export class Editor extends Single {
this.editor.on(Input.EVENT_RESTRICT, (...args) => { this.editor.on(Input.EVENT_RESTRICT, (...args) => {
this._checkWaterMark(); this._checkWaterMark();
const tip = this._setErrorVisible(true); const tip = this._setErrorVisible(true);
tip && tip.element.fadeOut(100, () => { tip &&
tip.element.fadeIn(100); tip.element.fadeOut(100, () => {
}); tip.element.fadeIn(100);
});
this.fireEvent(Editor.EVENT_RESTRICT, ...args); this.fireEvent(Editor.EVENT_RESTRICT, ...args);
}); });
this.editor.on(Input.EVENT_EMPTY, (...args) => { this.editor.on(Input.EVENT_EMPTY, (...args) => {
@ -224,7 +253,7 @@ export class Editor extends Single {
const { height, vgap, tgap } = this.options; const { height, vgap, tgap } = this.options;
if (isNull(this.watermark)) { if (isNull(this.watermark)) {
this.watermark = createWidget({ this.watermark = createWidget({
type: "bi.label", type: Label.xtype,
cls: "bi-water-mark", cls: "bi-water-mark",
text: this.options.watermark, text: this.options.watermark,
height: height - 2 * vgap - tgap, height: height - 2 * vgap - tgap,
@ -281,7 +310,7 @@ export class Editor extends Single {
if (isNull(this.watermark)) { if (isNull(this.watermark)) {
this._assertWaterMark(); this._assertWaterMark();
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this.contentWrapper, element: this.contentWrapper,
items: [ items: [
{ {

35
src/base/single/editor/editor.multifile.js

@ -1,3 +1,6 @@
import { File } from "../input";
import { AbsoluteLayout, AdaptiveLayout, shortcut, Widget, createWidget, extend } from "@/core";
/** /**
* 多文件 * 多文件
* *
@ -6,8 +9,6 @@
* @extends BI.Single * @extends BI.Single
* @abstract * @abstract
*/ */
import { shortcut, Widget, createWidget, extend } from "../../../core";
import { File } from "../input/file";
@shortcut() @shortcut()
export class MultifileEditor extends Widget { export class MultifileEditor extends Widget {
@ -23,7 +24,7 @@ export class MultifileEditor extends Widget {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-multifile-editor", baseCls: `${conf.baseCls || ""} bi-multifile-editor`,
multiple: false, multiple: false,
maxSize: -1, // 1024 * 1024 maxSize: -1, // 1024 * 1024
accept: "", accept: "",
@ -34,7 +35,7 @@ export class MultifileEditor extends Widget {
render() { render() {
const { name, url, multiple, accept, maxSize, maxLength, title, errorText } = this.options; const { name, url, multiple, accept, maxSize, maxLength, title, errorText } = this.options;
this.file = createWidget({ this.file = createWidget({
type: "bi.file", type: File.xtype,
cls: "multifile-editor", cls: "multifile-editor",
width: "100%", width: "100%",
height: "100%", height: "100%",
@ -64,19 +65,21 @@ export class MultifileEditor extends Widget {
}); });
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items: [{ items: [
el: { {
type: "bi.adaptive", el: {
scrollable: false, type: AdaptiveLayout.xtype,
items: [this.file], scrollable: false,
}, items: [this.file],
top: 0, },
right: 0, top: 0,
left: 0, right: 0,
bottom: 0, left: 0,
}], bottom: 0,
}
],
}); });
} }

109
src/base/single/editor/editor.textarea.js

@ -1,12 +1,29 @@
import {
Layout,
AbsoluteLayout,
AdaptiveLayout,
shortcut,
Widget,
Controller,
createWidget,
extend,
isEmptyString,
isKey,
isNotEmptyString,
isNotNull,
trim,
isFunction
} from "@/core";
import { Label } from "../label";
import { Single } from "../0.single";
import { Bubbles } from "@/base";
/** /**
* *
* Created by GUY on 2016/1/18. * Created by GUY on 2016/1/18.
* @class BI.TextAreaEditor * @class BI.TextAreaEditor
* @extends BI.Single * @extends BI.Single
*/ */
import { shortcut, Widget, Controller, createWidget, extend, isEmptyString, isKey, isNotEmptyString, isNotNull, trim, isFunction } from "../../../core";
import { Single } from "../0.single";
import { Bubbles } from "../../0.base";
@shortcut() @shortcut()
export class TextAreaEditor extends Single { export class TextAreaEditor extends Single {
@ -27,9 +44,7 @@ export class TextAreaEditor extends Single {
adjustYOffset: conf.simple ? 0 : 2, adjustYOffset: conf.simple ? 0 : 2,
adjustXOffset: 0, adjustXOffset: 0,
offsetStyle: "left", offsetStyle: "left",
validationChecker: () => { validationChecker: () => true,
return true;
},
scrolly: true, scrolly: true,
}); });
} }
@ -37,32 +52,36 @@ export class TextAreaEditor extends Single {
render() { render() {
const { scrolly, value, style } = this.options; const { scrolly, value, style } = this.options;
this.content = createWidget({ this.content = createWidget({
type: "bi.layout", type: Layout.xtype,
tagName: "textarea", tagName: "textarea",
width: "100%", width: "100%",
height: "100%", height: "100%",
cls: "bi-textarea textarea-editor-content display-block", cls: "bi-textarea textarea-editor-content display-block",
css: scrolly ? null : { css: scrolly
overflowY: "hidden", ? null
}, : {
overflowY: "hidden",
},
}); });
this.content.element.css({ resize: "none" }); this.content.element.css({ resize: "none" });
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items: [{ items: [
el: { {
type: "bi.adaptive", el: {
items: [this.content], type: AdaptiveLayout.xtype,
}, items: [this.content],
left: 4, },
right: 4, left: 4,
top: 2, right: 4,
bottom: 2, top: 2,
}], bottom: 2,
}
],
}); });
this.content.element.on("input propertychange", (e) => { this.content.element.on("input propertychange", e => {
this._checkError(); this._checkError();
this._checkWaterMark(); this._checkWaterMark();
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.CHANGE, this.getValue(), this); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.CHANGE, this.getValue(), this);
@ -76,9 +95,9 @@ export class TextAreaEditor extends Single {
this._checkError(); this._checkError();
this._focus(); this._focus();
this.fireEvent(TextAreaEditor.EVENT_FOCUS); this.fireEvent(TextAreaEditor.EVENT_FOCUS);
Widget._renderEngine.createElement(document).bind("mousedown." + this.getName(), (e) => { Widget._renderEngine.createElement(document).bind(`mousedown.${this.getName()}`, e => {
if (BI.DOM.isExist(this) && !this.element.__isMouseInBounds__(e)) { if (BI.DOM.isExist(this) && !this.element.__isMouseInBounds__(e)) {
Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()); Widget._renderEngine.createElement(document).unbind(`mousedown.${this.getName()}`);
this.content.element.blur(); this.content.element.blur();
} }
}); });
@ -90,16 +109,16 @@ export class TextAreaEditor extends Single {
this.fireEvent(TextAreaEditor.EVENT_CONFIRM); this.fireEvent(TextAreaEditor.EVENT_CONFIRM);
} }
this.fireEvent(TextAreaEditor.EVENT_BLUR); this.fireEvent(TextAreaEditor.EVENT_BLUR);
Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()); Widget._renderEngine.createElement(document).unbind(`mousedown.${this.getName()}`);
}); });
this.content.element.keydown(() => { this.content.element.keydown(() => {
// 水印快速消失 // 水印快速消失
this._checkWaterMark(); this._checkWaterMark();
}); });
this.content.element.keyup((e) => { this.content.element.keyup(e => {
this.fireEvent(TextAreaEditor.EVENT_KEY_DOWN, e.keyCode); this.fireEvent(TextAreaEditor.EVENT_KEY_DOWN, e.keyCode);
}); });
this.content.element.click((e) => { this.content.element.click(e => {
e.stopPropagation(); e.stopPropagation();
}); });
if (isKey(value)) { if (isKey(value)) {
@ -121,7 +140,7 @@ export class TextAreaEditor extends Single {
if (isNotEmptyString(watermark)) { if (isNotEmptyString(watermark)) {
if (!this.watermark) { if (!this.watermark) {
this.watermark = createWidget({ this.watermark = createWidget({
type: "bi.label", type: Label.xtype,
cls: "bi-water-mark textarea-watermark", cls: "bi-water-mark textarea-watermark",
textAlign: "left", textAlign: "left",
whiteSpace: scrolly ? "normal" : "nowrap", whiteSpace: scrolly ? "normal" : "nowrap",
@ -133,7 +152,7 @@ export class TextAreaEditor extends Single {
height: height > 24 ? "" : height, height: height > 24 ? "" : height,
}); });
this.watermark.element.bind({ this.watermark.element.bind({
mousedown: (e) => { mousedown: e => {
if (this.isEnabled()) { if (this.isEnabled()) {
this.focus(); this.focus();
} else { } else {
@ -141,19 +160,21 @@ export class TextAreaEditor extends Single {
} }
e.stopEvent(); e.stopEvent();
}, },
click: (e) => { click: e => {
e.stopPropagation(); e.stopPropagation();
}, },
}); });
createWidget({ createWidget({
type: "bi.absolute", type: AbsoluteLayout.xtype,
element: this, element: this,
items: [{ items: [
el: this.watermark, {
left: 0, el: this.watermark,
top: 0, left: 0,
right: 0, top: 0,
}], right: 0,
}
],
}); });
} else { } else {
this.watermark.setText(watermark); this.watermark.setText(watermark);
@ -232,9 +253,17 @@ export class TextAreaEditor extends Single {
setStyle(style) { setStyle(style) {
this.style = style; this.style = style;
this.element.css(style); this.element.css(style);
this.content.element.css(extend({}, style, { this.content.element.css(
color: style.color || BI.DOM.getContrastColor(BI.DOM.isRGBColor(style.backgroundColor) ? BI.DOM.rgb2hex(style.backgroundColor) : style.backgroundColor), extend({}, style, {
})); color:
style.color ||
BI.DOM.getContrastColor(
BI.DOM.isRGBColor(style.backgroundColor)
? BI.DOM.rgb2hex(style.backgroundColor)
: style.backgroundColor
),
})
);
} }
getStyle() { getStyle() {

6
src/base/single/editor/index.js

@ -1,3 +1,3 @@
export { Editor } from "./editor"; export { Editor } from "./editor";
export { MultifileEditor } from "./editor.multifile"; export { MultifileEditor } from "./editor.multifile";
export { TextAreaEditor } from "./editor.textarea"; export { TextAreaEditor } from "./editor.textarea";

29
src/base/single/html/html.js

@ -1,10 +1,11 @@
import { Layout, DefaultLayout, shortcut, isNumber, createWidget, isWidthOrHeight, isKey } from "@/core";
import { Single } from "../0.single";
/** /**
* guy 表示一行数据通过position来定位位置的数据 * guy 表示一行数据通过position来定位位置的数据
* @class BI.Html * @class BI.Html
* @extends BI.Single * @extends BI.Single
*/ */
import { shortcut, isNumber, createWidget, isWidthOrHeight, isKey } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class Html extends Single { export class Html extends Single {
@ -24,10 +25,26 @@ export class Html extends Single {
bgap: 0, bgap: 0,
text: "", text: "",
highLight: false, highLight: false,
} };
render() { render() {
const { vgap, hgap, lgap, rgap, tgap, bgap, height, lineHeight, maxWidth, textAlign, whiteSpace, handler, text, value, highLight } = this.options; const {
vgap,
hgap,
lgap,
rgap,
tgap,
bgap,
height,
lineHeight,
maxWidth,
textAlign,
whiteSpace,
handler,
text,
value,
highLight,
} = this.options;
if (hgap + lgap > 0) { if (hgap + lgap > 0) {
this.element.css({ this.element.css({
"padding-left": BI.pixFormat(hgap + lgap), "padding-left": BI.pixFormat(hgap + lgap),
@ -68,14 +85,14 @@ export class Html extends Single {
}); });
if (handler) { if (handler) {
this.text = createWidget({ this.text = createWidget({
type: "bi.layout", type: Layout.xtype,
tagName: "span", tagName: "span",
}); });
this.text.element.click(() => { this.text.element.click(() => {
handler(this.getValue()); handler(this.getValue());
}); });
createWidget({ createWidget({
type: "bi.default", type: DefaultLayout.xtype,
element: this, element: this,
items: [this.text], items: [this.text],
}); });

7
src/base/single/icon/icon.js

@ -1,10 +1,11 @@
import { Single } from "../0.single";
import { shortcut, extend } from "@/core";
/** /**
* guy 图标 * guy 图标
* @class BI.Icon * @class BI.Icon
* @extends BI.Single * @extends BI.Single
*/ */
import { shortcut, extend } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class Icon extends Single { export class Icon extends Single {
@ -15,7 +16,7 @@ export class Icon extends Single {
return extend(conf, { return extend(conf, {
tagName: "i", tagName: "i",
baseCls: (conf.baseCls || "") + " x-icon b-font horizon-center display-block", baseCls: `${conf.baseCls || ""} x-icon b-font horizon-center display-block`,
}); });
} }

23
src/base/single/iframe/iframe.js

@ -1,11 +1,12 @@
import { Single } from "../0.single";
import { shortcut, extend } from "@/core";
/** /**
* @class Iframe * @class Iframe
* @extends Single * @extends Single
* @abstract * @abstract
* Created by GameJian on 2016/3/2. * Created by GameJian on 2016/3/2.
*/ */
import { shortcut, extend } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class Iframe extends Single { export class Iframe extends Single {
@ -13,9 +14,10 @@ export class Iframe extends Single {
_defaultConfig(config) { _defaultConfig(config) {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
tagName: "iframe", tagName: "iframe",
baseCls: (conf.baseCls || "") + " bi-iframe", baseCls: `${conf.baseCls || ""} bi-iframe`,
src: "", src: "",
name: "", name: "",
attributes: {}, attributes: {},
@ -31,13 +33,16 @@ export class Iframe extends Single {
} }
_initProps() { _initProps() {
super._initProps(...arguments) super._initProps(...arguments);
const { src, name } = this.options; const { src, name } = this.options;
this.options.attributes = extend({ this.options.attributes = extend(
frameborder: 0, {
src, frameborder: 0,
name, src,
}, this.options.attributes); name,
},
this.options.attributes
);
} }
setSrc(src) { setSrc(src) {

20
src/base/single/img/img.js

@ -1,3 +1,6 @@
import { Single } from "../0.single";
import { shortcut, extend } from "@/core";
/** /**
* ͼƬ * ͼƬ
* *
@ -6,8 +9,6 @@
* @extends BI.Single * @extends BI.Single
* @abstract * @abstract
*/ */
import { shortcut, extend } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class Img extends Single { export class Img extends Single {
@ -18,7 +19,7 @@ export class Img extends Single {
return extend(conf, { return extend(conf, {
tagName: "img", tagName: "img",
baseCls: (conf.baseCls || "") + " bi-img display-block", baseCls: `${conf.baseCls || ""} bi-img display-block`,
src: "", src: "",
attributes: config.src ? { src: config.src } : {}, attributes: config.src ? { src: config.src } : {},
width: "100%", width: "100%",
@ -27,13 +28,16 @@ export class Img extends Single {
} }
_initProps() { _initProps() {
super._initProps(...arguments) super._initProps(...arguments);
const { src } = this.options; const { src } = this.options;
this.options.attributes = extend({ this.options.attributes = extend(
src, {
}, this.options.attributes); src,
},
this.options.attributes
);
} }
setSrc(src) { setSrc(src) {
this.options.src = src; this.options.src = src;
this.element.attr("src", src); this.element.attr("src", src);

9
src/base/single/input/checkbox/checkbox.image.js

@ -1,22 +1,23 @@
import { IconButton } from "../../button";
import { shortcut, extend } from "@/core";
/** /**
* guy * guy
* @extends Single * @extends Single
* @type {*|void|Object} * @type {*|void|Object}
*/ */
import { shortcut, extend } from "../../../../core";
import { IconButton } from "../../button";
@shortcut() @shortcut()
export class ImageCheckbox extends IconButton { export class ImageCheckbox extends IconButton {
static xtype = "bi.image_checkbox"; static xtype = "bi.image_checkbox";
static EVENT_CHANGE = IconButton.EVENT_CHANGE; static EVENT_CHANGE = IconButton.EVENT_CHANGE;
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-image-checkbox check-box-icon", baseCls: `${conf.baseCls || ""} bi-image-checkbox check-box-icon`,
selected: false, selected: false,
handler: BI.emptyFn, handler: BI.emptyFn,
width: 16, width: 16,

29
src/base/single/input/checkbox/checkbox.js

@ -1,10 +1,11 @@
import { CenterAdaptLayout, DefaultLayout, shortcut } from "@/core";
import { BasicButton } from "../../button";
/** /**
* guy * guy
* @extends Single * @extends Single
* @type {*|void|Object} * @type {*|void|Object}
*/ */
import { shortcut } from "../../../../core";
import { BasicButton } from "../../button";
@shortcut() @shortcut()
export class Checkbox extends BasicButton { export class Checkbox extends BasicButton {
@ -20,22 +21,24 @@ export class Checkbox extends BasicButton {
height: 14, height: 14,
iconWidth: 14, iconWidth: 14,
iconHeight: 14, iconHeight: 14,
} };
render() { render() {
const { iconWidth, iconHeight } = this.options; const { iconWidth, iconHeight } = this.options;
return { return {
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
items: [{ items: [
type: "bi.default", {
ref: (_ref) => { type: DefaultLayout.xtype,
this.checkbox = _ref; ref: _ref => {
}, this.checkbox = _ref;
cls: "checkbox-content", },
width: iconWidth, cls: "checkbox-content",
height: iconHeight, width: iconWidth,
}], height: iconHeight,
}
],
}; };
} }

369
src/base/single/input/file.js

@ -1,3 +1,6 @@
import { Msg } from "../../foundation/message";
import { shortcut, Widget, some, extend } from "@/core";
/** /**
* 文件 * 文件
* *
@ -6,27 +9,22 @@
* @extends BI.Single * @extends BI.Single
* @abstract * @abstract
*/ */
import { shortcut, Widget, some, extend } from "../../../core";
import { Msg } from "../../foundation/message";
const document = _global.document || {}; const document = _global.document || {};
/** /**
* @description normalize input.files. create if not present, add item method if not present * @description normalize input.files. create if not present, add item method if not present
* @param Object generated wrap object * @param Object generated wrap object
* @return Object the wrap object itself * @return Object the wrap object itself
*/ */
const F = (((item) => { const F = (item => input => {
return (input) => { const files = input.files || [input];
const files = input.files || [input]; if (!files.item) {
if (!files.item) { files.item = item;
files.item = item; }
}
return files; return files;
}; })(i => this[i]);
})((i) => {
return this[i];
}));
const event = { const event = {
@ -37,14 +35,14 @@ const event = {
* @param Function the callback to associate as event * @param Function the callback to associate as event
* @return Object noswfupload.event * @return Object noswfupload.event
*/ */
add: document.addEventListener ? add: document.addEventListener
(node, name, callback) => { ? (node, name, callback) => {
node.addEventListener(name, callback, false); node.addEventListener(name, callback, false);
return this; return this;
} : }
(node, name, callback) => { : (node, name, callback) => {
node.attachEvent("on" + name, callback); node.attachEvent(`on${name}`, callback);
return this; return this;
}, },
@ -56,14 +54,14 @@ const event = {
* @param Function the callback associated as event * @param Function the callback associated as event
* @return Object noswfupload.event * @return Object noswfupload.event
*/ */
del: document.removeEventListener ? del: document.removeEventListener
(node, name, callback) => { ? (node, name, callback) => {
node.removeEventListener(name, callback, false); node.removeEventListener(name, callback, false);
return this; return this;
} : }
(node, name, callback) => { : (node, name, callback) => {
node.detachEvent("on" + name, callback); node.detachEvent(`on${name}`, callback);
return this; return this;
}, },
@ -79,34 +77,41 @@ const event = {
event.returnValue = !(event.cancelBubble = true); event.returnValue = !(event.cancelBubble = true);
} }
} else { } else {
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true);
e.preventDefault ? e.preventDefault() : e.returnValue = false; e.preventDefault ? e.preventDefault() : (e.returnValue = false);
} }
return false; return false;
}, },
}; };
const sendFile = (((toString) => { const sendFile = (toString => {
const split = "onabort.onerror.onloadstart.onprogress".split("."), const split = "onabort.onerror.onloadstart.onprogress".split("."),
length = split.length, length = split.length,
CRLF = "\r\n"; CRLF = "\r\n";
let xhr = new XMLHttpRequest, let xhr = new XMLHttpRequest(),
sendFile; sendFile;
const multipart = (boundary, name, file) => { const multipart = (boundary, name, file) =>
return "--".concat( "--".concat(
boundary, CRLF, boundary,
"Content-Disposition: form-data; name=\"", name, "\"; filename=\"", _global.encodeURIComponent(file.fileName), "\"", CRLF, CRLF,
"Content-Type: application/octet-stream", CRLF, "Content-Disposition: form-data; name=\"",
name,
"\"; filename=\"",
_global.encodeURIComponent(file.fileName),
"\"",
CRLF,
"Content-Type: application/octet-stream",
CRLF, CRLF,
file.getAsBinary(), CRLF, CRLF,
"--", boundary, "--", CRLF file.getAsBinary(),
CRLF,
"--",
boundary,
"--",
CRLF
); );
} const isFunction = Function => toString.call(Function) === "[object Function]";
const isFunction = (Function) => {
return toString.call(Function) === "[object Function]";
}
// FireFox 3+, Safari 4 beta (Chrome 2 beta file is buggy and will not work) // FireFox 3+, Safari 4 beta (Chrome 2 beta file is buggy and will not work)
if (xhr.upload || xhr.sendAsBinary) { if (xhr.upload || xhr.sendAsBinary) {
@ -116,32 +121,30 @@ const sendFile = (((toString) => {
if (isFunction(handler.onerror)) { if (isFunction(handler.onerror)) {
handler.onerror(); handler.onerror();
} }
return; return;
} }
const xhr = new XMLHttpRequest, const xhr = new XMLHttpRequest(),
upload = xhr.upload || { upload = xhr.upload || {
addEventListener(event, callback) { addEventListener(event, callback) {
this["on" + event] = callback; this[`on${event}`] = callback;
}, },
}; };
for (let i = 0;i < length;i++) { for (let i = 0; i < length; i++) {
upload.addEventListener( upload.addEventListener(
split[i].substring(2), split[i].substring(2),
// eslint-disable-next-line no-loop-func // eslint-disable-next-line no-loop-func
(((event) => { (event => rpe => {
return (rpe) => { if (isFunction(handler[event])) {
if (isFunction(handler[event])) { handler[event](rpe, xhr);
handler[event](rpe, xhr); }
} })(split[i]),
};
})(split[i])),
false false
); );
} }
upload.addEventListener( upload.addEventListener(
"load", "load",
(rpe) => { rpe => {
if (handler.onreadystatechange === false) { if (handler.onreadystatechange === false) {
if (isFunction(handler.onload)) { if (isFunction(handler.onload)) {
handler.onload(rpe, xhr); handler.onload(rpe, xhr);
@ -155,15 +158,19 @@ const sendFile = (((toString) => {
} else { } else {
setTimeout(callback, 15); setTimeout(callback, 15);
} }
} };
setTimeout(callback, 15); setTimeout(callback, 15);
} }
}, },
false false
); );
xhr.open("post", BI.appendQuery(handler.url, { xhr.open(
filename: _global.encodeURIComponent(handler.file.fileName), "post",
}), true); BI.appendQuery(handler.url, {
filename: _global.encodeURIComponent(handler.file.fileName),
}),
true
);
if (!xhr.upload) { if (!xhr.upload) {
const rpe = { loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true }; const rpe = { loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true };
rpe.interval = setInterval(() => { rpe.interval = setInterval(() => {
@ -181,61 +188,61 @@ const sendFile = (((toString) => {
}; };
xhr.onreadystatechange = () => { xhr.onreadystatechange = () => {
switch (xhr.readyState) { switch (xhr.readyState) {
case 2: case 2:
case 3: case 3:
if (rpe.total <= rpe.loaded) { if (rpe.total <= rpe.loaded) {
rpe.loaded = rpe.total;
}
upload.onprogress(rpe);
break;
case 4:
clearInterval(rpe.interval);
rpe.interval = 0;
rpe.loaded = rpe.total; rpe.loaded = rpe.total;
upload.onprogress(rpe); }
if (199 < xhr.status && xhr.status < 400) { upload.onprogress(rpe);
upload.onload({}); break;
const attachO = BI.jsonDecode(xhr.responseText); case 4:
attachO.filename = handler.file.fileName; clearInterval(rpe.interval);
if (handler.file.type.indexOf("image") !== -1) { rpe.interval = 0;
attachO.attach_type = "image"; rpe.loaded = rpe.total;
} upload.onprogress(rpe);
handler.attach_array[current] = attachO; if (199 < xhr.status && xhr.status < 400) {
} else { upload.onload({});
upload.onerror({}); const attachO = BI.jsonDecode(xhr.responseText);
attachO.filename = handler.file.fileName;
if (handler.file.type.indexOf("image") !== -1) {
attachO.attach_type = "image";
} }
break; handler.attach_array[current] = attachO;
default: } else {
break; upload.onerror({});
}
break;
default:
break;
} }
}; };
upload.onloadstart(rpe); upload.onloadstart(rpe);
} else { } else {
xhr.onreadystatechange = () => { xhr.onreadystatechange = () => {
switch (xhr.readyState) { switch (xhr.readyState) {
case 4: case 4:
const attachO = BI.jsonDecode(xhr.responseText); const attachO = BI.jsonDecode(xhr.responseText);
if (handler.file.type.indexOf("image") !== -1) { if (handler.file.type.indexOf("image") !== -1) {
attachO.attach_type = "image"; attachO.attach_type = "image";
} }
attachO.filename = handler.file.fileName; attachO.filename = handler.file.fileName;
if (handler.maxLength === 1) { if (handler.maxLength === 1) {
handler.attach_array[0] = attachO; handler.attach_array[0] = attachO;
// handler.attach_array.push(attachO); // handler.attach_array.push(attachO);
} else { } else {
handler.attach_array[current] = attachO; handler.attach_array[current] = attachO;
} }
break; break;
default: default:
break; break;
} }
}; };
if (isFunction(upload.onloadstart)) { if (isFunction(upload.onloadstart)) {
upload.onloadstart(); upload.onloadstart();
} }
} }
const boundary = "AjaxUploadBoundary" + (new Date).getTime(); const boundary = `AjaxUploadBoundary${new Date().getTime()}`;
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary); xhr.setRequestHeader("Content-Type", `multipart/form-data; boundary=${boundary}`);
if (handler.file.getAsBinary) { if (handler.file.getAsBinary) {
xhr[xhr.sendAsBinary ? "sendAsBinary" : "send"](multipart(boundary, handler.name, handler.file)); xhr[xhr.sendAsBinary ? "sendAsBinary" : "send"](multipart(boundary, handler.name, handler.file));
} else { } else {
@ -246,7 +253,7 @@ const sendFile = (((toString) => {
form.append("FileData", handler.file); form.append("FileData", handler.file);
xhr.send(form); xhr.send(form);
} }
return handler; return handler;
}; };
} else { } else {
@ -256,7 +263,10 @@ const sendFile = (((toString) => {
let iframe, form; let iframe, form;
const url = handler.url.concat(-1 === handler.url.indexOf("?") ? "?" : "&", "AjaxUploadFrame=true"), const url = handler.url.concat(-1 === handler.url.indexOf("?") ? "?" : "&", "AjaxUploadFrame=true"),
rpe = { rpe = {
loaded: 1, total: 100, simulation: true, interval: setInterval(() => { loaded: 1,
total: 100,
simulation: true,
interval: setInterval(() => {
if (rpe.loaded < rpe.total) { if (rpe.loaded < rpe.total) {
++rpe.loaded; ++rpe.loaded;
} }
@ -265,56 +275,62 @@ const sendFile = (((toString) => {
} }
}, 100), }, 100),
}, },
target = ["AjaxUpload", (new Date).getTime(), String(Math.random()).substring(2)].join("_"); target = ["AjaxUpload", new Date().getTime(), String(Math.random()).substring(2)].join("_");
const onload = () => { const onload = () => {
iframe.onreadystatechange = iframe.onload = iframe.onerror = null; iframe.onreadystatechange = iframe.onload = iframe.onerror = null;
form.parentNode.removeChild(form); form.parentNode.removeChild(form);
form = null; form = null;
clearInterval(rpe.interval); clearInterval(rpe.interval);
// rpe.loaded = rpe.total; // rpe.loaded = rpe.total;
const responseText = (iframe.contentWindow.document || iframe.contentWindow.contentDocument).body.innerHTML; const responseText = (iframe.contentWindow.document || iframe.contentWindow.contentDocument).body
try { .innerHTML;
const attachO = BI.jsonDecode(responseText); try {
if (handler.file.type.indexOf("image") !== -1) { const attachO = BI.jsonDecode(responseText);
attachO.attach_type = "image"; if (handler.file.type.indexOf("image") !== -1) {
} attachO.attach_type = "image";
}
// attachO.fileSize = responseText.length; // attachO.fileSize = responseText.length;
try { try {
// decodeURIComponent特殊字符可能有问题, catch一下,保证能正常上传 // decodeURIComponent特殊字符可能有问题, catch一下,保证能正常上传
attachO.filename = _global.decodeURIComponent(handler.file.fileName); attachO.filename = _global.decodeURIComponent(handler.file.fileName);
} catch (e) {
attachO.filename = handler.file.fileName;
}
if (handler.maxLength === 1) {
handler.attach_array[0] = attachO;
} else {
handler.attach_array[current] = attachO;
}
} catch (e) { } catch (e) {
if (isFunction(handler.onerror)) { attachO.filename = handler.file.fileName;
handler.onerror(rpe, event || _global.event);
}
} }
if (isFunction(handler.onload)) { if (handler.maxLength === 1) {
handler.onload(rpe, { responseText: responseText }); handler.attach_array[0] = attachO;
} else {
handler.attach_array[current] = attachO;
}
} catch (e) {
if (isFunction(handler.onerror)) {
handler.onerror(rpe, event || _global.event);
} }
} }
if (isFunction(handler.onload)) {
try { // IE < 8 does not accept enctype attribute ... handler.onload(rpe, { responseText });
}
};
try {
// IE < 8 does not accept enctype attribute ...
const form = document.createElement("<form enctype=\"multipart/form-data\"></form>"), const form = document.createElement("<form enctype=\"multipart/form-data\"></form>"),
iframe = handler.iframe || (handler.iframe = document.createElement("<iframe id=\"" + target + "\" name=\"" + target + "\" src=\"" + url + "\"></iframe>")); iframe =
handler.iframe ||
(handler.iframe = document.createElement(
`<iframe id="${target}" name="${target}" src="${url}"></iframe>`
));
} catch (e) { } catch (e) {
const form = document.createElement("form"), const form = document.createElement("form"),
iframe = handler.iframe || (handler.iframe = document.createElement("iframe")); iframe = handler.iframe || (handler.iframe = document.createElement("iframe"));
form.setAttribute("enctype", "multipart/form-data"); form.setAttribute("enctype", "multipart/form-data");
iframe.setAttribute("name", iframe.id = target); iframe.setAttribute("name", (iframe.id = target));
iframe.setAttribute("src", url); iframe.setAttribute("src", url);
} }
iframe.style.position = "absolute"; iframe.style.position = "absolute";
iframe.style.left = iframe.style.top = "-10000px"; iframe.style.left = iframe.style.top = "-10000px";
iframe.onload = onload; iframe.onload = onload;
iframe.onerror = (event) => { iframe.onerror = event => {
if (isFunction(handler.onerror)) { if (isFunction(handler.onerror)) {
handler.onerror(rpe, event || _global.event); handler.onerror(rpe, event || _global.event);
} }
@ -329,16 +345,17 @@ const sendFile = (((toString) => {
++rpe.loaded; ++rpe.loaded;
} }
handler.onloadprogress(rpe, { handler.onloadprogress(rpe, {
readyState: { readyState:
loading: 2, {
interactive: 3, loading: 2,
loaded: 4, interactive: 3,
complete: 4, loaded: 4,
}[iframe.readyState] || 1, complete: 4,
}[iframe.readyState] || 1,
}); });
} }
}; };
form.setAttribute("action", handler.url + "&filename=" + _global.encodeURIComponent(handler.file.fileName)); form.setAttribute("action", `${handler.url}&filename=${_global.encodeURIComponent(handler.file.fileName)}`);
form.setAttribute("target", iframe.id); form.setAttribute("target", iframe.id);
form.setAttribute("method", "post"); form.setAttribute("method", "post");
form.appendChild(handler.file); form.appendChild(handler.file);
@ -355,19 +372,19 @@ const sendFile = (((toString) => {
}; };
} }
xhr = null; xhr = null;
return sendFile; return sendFile;
})(Object.prototype.toString)); })(Object.prototype.toString);
const sendFiles = (handler, maxSize, width, height) => { const sendFiles = (handler, maxSize, width, height) => {
const length = handler.files.length, const length = handler.files.length,
onload = handler.onload, onload = handler.onload,
onloadstart = handler.onloadstart; onloadstart = handler.onloadstart;
handler.current = 0; handler.current = 0;
handler.total = 0; handler.total = 0;
handler.sent = 0; handler.sent = 0;
while (handler.current < length) { while (handler.current < length) {
handler.total += (handler.files[handler.current].fileSize || handler.files[handler.current].size); handler.total += handler.files[handler.current].fileSize || handler.files[handler.current].size;
handler.current++; handler.current++;
} }
handler.current = 0; handler.current = 0;
@ -375,7 +392,7 @@ const sendFiles = (handler, maxSize, width, height) => {
handler.file = handler.files[handler.current]; handler.file = handler.files[handler.current];
const callback = (rpe, xhr) => { const callback = (rpe, xhr) => {
handler.onloadstart = null; handler.onloadstart = null;
handler.sent += (handler.files[handler.current].fileSize || handler.files[handler.current].size); handler.sent += handler.files[handler.current].fileSize || handler.files[handler.current].size;
if (++handler.current < length) { if (++handler.current < length) {
handler.file = handler.files[handler.current]; handler.file = handler.files[handler.current];
sendFile(handler, maxSize, width, height).onload = callback; sendFile(handler, maxSize, width, height).onload = callback;
@ -415,7 +432,7 @@ const sendFiles = (handler, maxSize, width, height) => {
} }
return handler; return handler;
} };
const r1 = /\.([^.]+)$/; // .png const r1 = /\.([^.]+)$/; // .png
const r2 = /\/([^/]+)$/; // image/png const r2 = /\/([^/]+)$/; // image/png
@ -432,7 +449,7 @@ const fileTypeValidate = (fileName, fileType) => {
} }
const mimes = fileType.split(","); const mimes = fileType.split(",");
if (mimes[0] === fileType) { if (mimes[0] === fileType) {
mimes = (fileType + "").split(";"); mimes = `${fileType}`.split(";");
} }
return some(mimes, (index, mime) => { return some(mimes, (index, mime) => {
@ -446,7 +463,7 @@ const fileTypeValidate = (fileName, fileType) => {
return matches[1] === "*" ? true : fileName.toLowerCase().indexOf(matches[1]) > -1; return matches[1] === "*" ? true : fileName.toLowerCase().indexOf(matches[1]) > -1;
} }
}); });
} };
@shortcut() @shortcut()
export class File extends Widget { export class File extends Widget {
@ -462,7 +479,7 @@ export class File extends Widget {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-file display-block", baseCls: `${conf.baseCls || ""} bi-file display-block`,
tagName: "input", tagName: "input",
attributes: { attributes: {
type: "file", type: "file",
@ -492,14 +509,14 @@ export class File extends Widget {
// create the noswfupload.wrap Object // create the noswfupload.wrap Object
// wrap.maxSize 文件大小限制 // wrap.maxSize 文件大小限制
// wrap.maxLength 文件个数限制 // wrap.maxLength 文件个数限制
const _wrap = this.wrap = this._wrap(this.element[0], maxSize); const _wrap = (this.wrap = this._wrap(this.element[0], maxSize));
// fileType could contain whatever text but filter checks *.{extension} // fileType could contain whatever text but filter checks *.{extension}
// if present // if present
// handlerszhe // handlerszhe
_wrap.onloadstart = (...args) => { _wrap.onloadstart = (...args) => {
this.fireEvent(File.EVENT_UPLOADSTART, ...args); this.fireEvent(File.EVENT_UPLOADSTART, ...args);
}; };
_wrap.onprogress = (rpe, xhr) => { _wrap.onprogress = (rpe, xhr) => {
@ -586,20 +603,26 @@ export class File extends Widget {
const validateFileType = fileTypeValidate(value, wrap.fileType); const validateFileType = fileTypeValidate(value, wrap.fileType);
if (!validateFileType) { if (!validateFileType) {
// 文件类型不支持 // 文件类型不支持
Msg.toast(errorText({ Msg.toast(
errorType: 0, errorText({
file: item, errorType: 0,
}) || BI.i18nText("BI-Upload_File_Type_Error", wrap.fileType), { level: "error" }); file: item,
}) || BI.i18nText("BI-Upload_File_Type_Error", wrap.fileType),
{ level: "error" }
);
this.fireEvent(File.EVENT_ERROR, { this.fireEvent(File.EVENT_ERROR, {
errorType: 0, errorType: 0,
file: item, file: item,
}); });
} else if (wrap.maxSize !== -1 && size && wrap.maxSize < size) { } else if (wrap.maxSize !== -1 && size && wrap.maxSize < size) {
// 文件大小不支持 // 文件大小不支持
Msg.toast(errorText({ Msg.toast(
errorType: 1, errorText({
file: item, errorType: 1,
}) || BI.i18nText("BI-Upload_File_Size_Error", Math.ceil(wrap.maxSize / 1024 / 1024)), { level: "error" }); file: item,
}) || BI.i18nText("BI-Upload_File_Size_Error", Math.ceil(wrap.maxSize / 1024 / 1024)),
{ level: "error" }
);
this.fireEvent(File.EVENT_ERROR, { this.fireEvent(File.EVENT_ERROR, {
errorType: 1, errorType: 1,
file: item, file: item,
@ -609,14 +632,15 @@ export class File extends Widget {
} }
} }
} }
wrap.files.length > 0 && this.fireEvent(File.EVENT_CHANGE, { wrap.files.length > 0 &&
files: wrap.files, this.fireEvent(File.EVENT_CHANGE, {
}); files: wrap.files,
});
input.value = ""; input.value = "";
wrap.dom.input.parentNode.replaceChild(input, wrap.dom.input); wrap.dom.input.parentNode.replaceChild(input, wrap.dom.input);
wrap.dom.input = input; wrap.dom.input = input;
event.add(wrap.dom.input, "change", callback); event.add(wrap.dom.input, "change", callback);
} };
event.add(wrap.dom.input, "change", callback); event.add(wrap.dom.input, "change", callback);
return wrap; return wrap;
@ -633,10 +657,9 @@ export class File extends Widget {
// wrap Object // wrap Object
return this._events({ return this._events({
// DOM namespace // DOM namespace
dom: { dom: {
input: input, // input file input, // input file
disabled: false, // internal use, checks input file state disabled: false, // internal use, checks input file state
}, },
name: input.name, // name to send for each file ($_FILES[{name}] in the server) name: input.name, // name to send for each file ($_FILES[{name}] in the server)
@ -655,7 +678,7 @@ export class File extends Widget {
// something like {onload:function(){alert("OK")},onerror:function(){alert("Error")}, etc ...} // something like {onload:function(){alert("OK")},onerror:function(){alert("Error")}, etc ...}
upload(handler) { upload(handler) {
if (handler) { if (handler) {
for (let key in handler) { for (const key in handler) {
this[key] = handler[key]; this[key] = handler[key];
} }
} }

12
src/base/single/input/index.js

@ -1,6 +1,6 @@
export { Input } from "./input"; export { Input } from "./input";
export { File } from "./file"; export { File } from "./file";
export { Checkbox } from "./checkbox/checkbox"; export { Checkbox } from "./checkbox/checkbox";
export { ImageCheckbox } from "./checkbox/checkbox.image"; export { ImageCheckbox } from "./checkbox/checkbox.image";
export { Radio } from "./radio/radio"; export { Radio } from "./radio/radio";
export { ImageRadio } from "./radio/radio.image"; export { ImageRadio } from "./radio/radio.image";

71
src/base/single/input/input.js

@ -1,11 +1,26 @@
import { Single } from "../0.single";
import {
shortcut,
Controller,
extend,
debounce,
bind,
isNull,
isEmptyString,
isKey,
delay,
trim,
isEqual,
nextTick,
isEndWithBlank
} from "@/core";
/** /**
* guy * guy
* @class BI.Input 一个button和一行数 组成的一行listitem * @class BI.Input 一个button和一行数 组成的一行listitem
* @extends BI.Single * @extends BI.Single
* @type {*|void|Object} * @type {*|void|Object}
*/ */
import { shortcut, Controller, extend, debounce, bind, isNull, isEmptyString, isKey, delay, trim, isEqual, nextTick, isEndWithBlank } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class Input extends Single { export class Input extends Single {
@ -37,7 +52,7 @@ export class Input extends Single {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-input display-block overflow-dot", baseCls: `${conf.baseCls || ""} bi-input display-block overflow-dot`,
tagName: "input", tagName: "input",
validationChecker: BI.emptyFn, validationChecker: BI.emptyFn,
quitChecker: BI.emptyFn, // 按确定键能否退出编辑 quitChecker: BI.emptyFn, // 按确定键能否退出编辑
@ -49,37 +64,37 @@ export class Input extends Single {
let ctrlKey = false; let ctrlKey = false;
let keyCode = null; let keyCode = null;
let inputEventValid = false; let inputEventValid = false;
const _keydown = debounce((keyCode) => { const _keydown = debounce(keyCode => {
this.onKeyDown(keyCode, ctrlKey); this.onKeyDown(keyCode, ctrlKey);
this._keydown_ = false; this._keydown_ = false;
}, BI.EVENT_RESPONSE_TIME); }, BI.EVENT_RESPONSE_TIME);
const _clk = debounce(bind(this._click, this), BI.EVENT_RESPONSE_TIME, { const _clk = debounce(bind(this._click, this), BI.EVENT_RESPONSE_TIME, {
"leading": true, leading: true,
"trailing": false, trailing: false,
}); });
this._focusDebounce = debounce(bind(this._focus, this), BI.EVENT_RESPONSE_TIME, { this._focusDebounce = debounce(bind(this._focus, this), BI.EVENT_RESPONSE_TIME, {
"leading": true, leading: true,
"trailing": false, trailing: false,
}); });
this._blurDebounce = debounce(bind(this._blur, this), BI.EVENT_RESPONSE_TIME, { this._blurDebounce = debounce(bind(this._blur, this), BI.EVENT_RESPONSE_TIME, {
"leading": true, leading: true,
"trailing": false, trailing: false,
}); });
this.element this.element
.keydown((e) => { .keydown(e => {
inputEventValid = false; inputEventValid = false;
ctrlKey = e.ctrlKey || e.metaKey; // mac的cmd支持一下 ctrlKey = e.ctrlKey || e.metaKey; // mac的cmd支持一下
keyCode = e.keyCode; keyCode = e.keyCode;
this.fireEvent(Input.EVENT_QUICK_DOWN, e); this.fireEvent(Input.EVENT_QUICK_DOWN, e);
}) })
.keyup((e) => { .keyup(e => {
keyCode = null; keyCode = null;
if (!(inputEventValid && e.keyCode === BI.KeyCode.ENTER)) { if (!(inputEventValid && e.keyCode === BI.KeyCode.ENTER)) {
this._keydown_ = true; this._keydown_ = true;
_keydown(e.keyCode); _keydown(e.keyCode);
} }
}) })
.on("input propertychange", (e) => { .on("input propertychange", e => {
// 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了 // 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了
// 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8 // 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8
// 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓) // 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓)
@ -91,17 +106,18 @@ export class Input extends Single {
keyCode = null; keyCode = null;
} }
}) })
.click((e) => { .click(e => {
e.stopPropagation(); e.stopPropagation();
_clk(); _clk();
}) })
.mousedown((e) => { .mousedown(e => {
this.element.val(this.element.val()); this.element.val(this.element.val());
}) })
.focus((e) => { // 可以不用冒泡 .focus(e => {
// 可以不用冒泡
this._focusDebounce(); this._focusDebounce();
}) })
.blur((e) => { .blur(e => {
// DEC-14919 IE11在浏览器重新获得焦点之后会先触发focusout再触发focus,要保持先获得焦点再失去焦点的顺序不变,因此采用blur // DEC-14919 IE11在浏览器重新获得焦点之后会先触发focusout再触发focus,要保持先获得焦点再失去焦点的顺序不变,因此采用blur
this._blurDebounce(); this._blurDebounce();
}); });
@ -141,8 +157,8 @@ export class Input extends Single {
} }
} }
this.fireEvent(Input.EVENT_BLUR); this.fireEvent(Input.EVENT_BLUR);
} };
if (this._keydown_ === true) { if (this._keydown_ === true) {
delay(blur, BI.EVENT_RESPONSE_TIME); delay(blur, BI.EVENT_RESPONSE_TIME);
} else { } else {
@ -166,8 +182,11 @@ export class Input extends Single {
this._checkValidationOnValueChange(); this._checkValidationOnValueChange();
} }
if (this.isValid() && trim(this.getValue()) !== "") { if (this.isValid() && trim(this.getValue()) !== "") {
if (trim(this.getValue()) !== this._lastValue && (!this._start || isNull(this._lastValue) || this._lastValue === "") if (
|| (this._pause === true && !/(\s|\u00A0)$/.test(this.getValue()))) { (trim(this.getValue()) !== this._lastValue &&
(!this._start || isNull(this._lastValue) || this._lastValue === "")) ||
(this._pause === true && !/(\s|\u00A0)$/.test(this.getValue()))
) {
this._start = true; this._start = true;
this._pause = false; this._pause = false;
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this);
@ -203,8 +222,12 @@ export class Input extends Single {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this);
this.fireEvent(Input.EVENT_PAUSE); this.fireEvent(Input.EVENT_PAUSE);
this._defaultState(); this._defaultState();
} else if ((keyCode === BI.KeyCode.BACKSPACE || keyCode === BI.KeyCode.DELETE) && } else if (
trim(this.getValue()) === "" && (lastValue !== null && trim(lastValue) !== "")) { (keyCode === BI.KeyCode.BACKSPACE || keyCode === BI.KeyCode.DELETE) &&
trim(this.getValue()) === "" &&
lastValue !== null &&
trim(lastValue) !== ""
) {
this.fireEvent(Controller.EVENT_CHANGE, BI.Events.STOPEDIT, this.getValue(), this); this.fireEvent(Controller.EVENT_CHANGE, BI.Events.STOPEDIT, this.getValue(), this);
this.fireEvent(Input.EVENT_STOP); this.fireEvent(Input.EVENT_STOP);
} }
@ -250,7 +273,7 @@ export class Input extends Single {
} }
const checker = validationChecker.apply(this, [trim(v)]); const checker = validationChecker.apply(this, [trim(v)]);
if (checker instanceof Promise) { if (checker instanceof Promise) {
checker.then((validate) => { checker.then(validate => {
this.setValid(validate !== false); this.setValid(validate !== false);
callback && callback(); callback && callback();
}); });

9
src/base/single/input/radio/radio.image.js

@ -1,22 +1,23 @@
import { IconButton } from "../../button";
import { shortcut, extend } from "@/core";
/** /**
* guy * guy
* @extends Single * @extends Single
* @type {*|void|Object} * @type {*|void|Object}
*/ */
import { shortcut, extend } from "../../../../core";
import { IconButton } from "../../button";
@shortcut() @shortcut()
export class ImageRadio extends IconButton { export class ImageRadio extends IconButton {
static xtype = "bi.image_radio"; static xtype = "bi.image_radio";
static EVENT_CHANGE = IconButton.EVENT_CHANGE; static EVENT_CHANGE = IconButton.EVENT_CHANGE;
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-radio radio-icon", baseCls: `${conf.baseCls || ""} bi-radio radio-icon`,
selected: false, selected: false,
handler: BI.emptyFn, handler: BI.emptyFn,
width: 16, width: 16,

31
src/base/single/input/radio/radio.js

@ -1,10 +1,11 @@
import { CenterAdaptLayout, Layout, shortcut } from "@/core";
import { BasicButton } from "../../button";
/** /**
* guy * guy
* @extends Single * @extends Single
* @type {*|void|Object} * @type {*|void|Object}
*/ */
import { shortcut } from "../../../../core";
import { BasicButton } from "../../button";
@shortcut() @shortcut()
export class Radio extends BasicButton { export class Radio extends BasicButton {
@ -18,23 +19,25 @@ export class Radio extends BasicButton {
width: 16, width: 16,
height: 16, height: 16,
iconWidth: 16, iconWidth: 16,
iconHeight: 16 iconHeight: 16,
} };
render() { render() {
const { iconWidth, iconHeight } = this.options; const { iconWidth, iconHeight } = this.options;
return { return {
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
items: [{ items: [
type: "bi.layout", {
cls: "radio-content", type: Layout.xtype,
ref: (_ref) => { cls: "radio-content",
this.radio = _ref; ref: _ref => {
}, this.radio = _ref;
width: iconWidth, },
height: iconHeight, width: iconWidth,
}], height: iconHeight,
}
],
}; };
} }

16
src/base/single/instruction/instruction.js

@ -1,4 +1,5 @@
import { shortcut, Widget, extend } from "../../../core"; import { Label } from "../label";
import { shortcut, Widget, extend } from "@/core";
@shortcut() @shortcut()
export class Instruction extends Widget { export class Instruction extends Widget {
@ -6,13 +7,14 @@ export class Instruction extends Widget {
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-instruction", baseCls: `${conf.baseCls || ""} bi-instruction`,
height: 20, height: 20,
level: "error", level: "error",
textAlign: "left", textAlign: "left",
whiteSpace: "nowrap", whiteSpace: "nowrap",
hgap: 5 hgap: 5,
}); });
} }
@ -20,11 +22,11 @@ export class Instruction extends Widget {
const { level, textAlign, whiteSpace, height, hgap, rgap, lgap, vgap, text, keyword, value, py } = this.options; const { level, textAlign, whiteSpace, height, hgap, rgap, lgap, vgap, text, keyword, value, py } = this.options;
return { return {
type: "bi.label", type: Label.xtype,
ref: (_ref) => { ref: _ref => {
this.text = _ref; this.text = _ref;
}, },
cls: "instruction-" + level, cls: `instruction-${level}`,
textAlign, textAlign,
whiteSpace, whiteSpace,
textHeight: height, textHeight: height,
@ -36,7 +38,7 @@ export class Instruction extends Widget {
text, text,
keyword, keyword,
value, value,
py py,
}; };
} }

179
src/base/single/label/abstract.label.js

@ -1,11 +1,12 @@
import { Text } from "../1.text";
import { CenterAdaptLayout, isNumber, createWidget, extend } from "@/core";
import { Single } from "../0.single";
/** /**
* Created by dailer on 2019/6/19. * Created by dailer on 2019/6/19.
*/ */
import { isNumber, createWidget, extend } from "../../../core";
import { Single } from "../0.single";
export class AbstractLabel extends Single { export class AbstractLabel extends Single {
_defaultConfig(props) { _defaultConfig(props) {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
@ -30,7 +31,7 @@ export class AbstractLabel extends Single {
const { textAlign, whiteSpace, textHeight, text, value, py, keyword, highLight, handler } = this.options; const { textAlign, whiteSpace, textHeight, text, value, py, keyword, highLight, handler } = this.options;
return { return {
type: "bi.text", type: Text.xtype,
textAlign, textAlign,
whiteSpace, whiteSpace,
lineHeight: textHeight, lineHeight: textHeight,
@ -59,9 +60,10 @@ export class AbstractLabel extends Single {
if (isNumber(width) && width > 0) { if (isNumber(width) && width > 0) {
if (isNumber(textWidth) && textWidth > 0) { if (isNumber(textWidth) && textWidth > 0) {
json.maxWidth = textWidth; json.maxWidth = textWidth;
if (isNumber(height) && height > 0) { // 1.1 if (isNumber(height) && height > 0) {
// 1.1
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
height, height,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: whiteSpace === "normal", scrollable: whiteSpace === "normal",
@ -75,8 +77,9 @@ export class AbstractLabel extends Single {
return; return;
} }
createWidget({ // 1.2 createWidget({
type: "bi.center_adapt", // 1.2
type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: whiteSpace === "normal", scrollable: whiteSpace === "normal",
element: this, element: this,
@ -89,7 +92,8 @@ export class AbstractLabel extends Single {
return; return;
} }
if (whiteSpace === "normal") { // 1.3 if (whiteSpace === "normal") {
// 1.3
extend(json, { extend(json, {
hgap, hgap,
vgap, vgap,
@ -100,7 +104,7 @@ export class AbstractLabel extends Single {
}); });
this.text = createWidget(json); this.text = createWidget(json);
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: whiteSpace === "normal", scrollable: whiteSpace === "normal",
element: this, element: this,
@ -109,25 +113,29 @@ export class AbstractLabel extends Single {
return; return;
} }
if (isNumber(height) && height > 0) { // 1.4 if (isNumber(height) && height > 0) {
// 1.4
this.element.css({ this.element.css({
"line-height": BI.pixFormat(height), "line-height": BI.pixFormat(height),
}); });
json.textAlign = textAlign; json.textAlign = textAlign;
delete json.maxWidth; delete json.maxWidth;
this.text = createWidget(extend(json, { this.text = createWidget(
element: this, extend(json, {
hgap, element: this,
vgap, hgap,
lgap, vgap,
rgap, lgap,
tgap, rgap,
bgap, tgap,
})); bgap,
})
);
return; return;
} }
extend(json, { // 1.5 extend(json, {
// 1.5
hgap, hgap,
vgap, vgap,
lgap, lgap,
@ -138,7 +146,7 @@ export class AbstractLabel extends Single {
}); });
this.text = createWidget(json); this.text = createWidget(json);
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: whiteSpace === "normal", scrollable: whiteSpace === "normal",
element: this, element: this,
@ -147,10 +155,11 @@ export class AbstractLabel extends Single {
return; return;
} }
if (isNumber(textWidth) && textWidth > 0) { // 1.6 if (isNumber(textWidth) && textWidth > 0) {
// 1.6
json.maxWidth = textWidth; json.maxWidth = textWidth;
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: whiteSpace === "normal", scrollable: whiteSpace === "normal",
element: this, element: this,
@ -163,7 +172,8 @@ export class AbstractLabel extends Single {
return; return;
} }
if (whiteSpace === "normal") { // 1.7 if (whiteSpace === "normal") {
// 1.7
extend(json, { extend(json, {
hgap, hgap,
vgap, vgap,
@ -174,7 +184,7 @@ export class AbstractLabel extends Single {
}); });
this.text = createWidget(json); this.text = createWidget(json);
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: true, scrollable: true,
element: this, element: this,
@ -183,34 +193,39 @@ export class AbstractLabel extends Single {
return; return;
} }
if (isNumber(height) && height > 0) { // 1.8 if (isNumber(height) && height > 0) {
// 1.8
this.element.css({ this.element.css({
"line-height": BI.pixFormat(height), "line-height": BI.pixFormat(height),
}); });
json.textAlign = textAlign; json.textAlign = textAlign;
delete json.maxWidth; delete json.maxWidth;
this.text = createWidget(extend(json, { this.text = createWidget(
element: this, extend(json, {
element: this,
hgap,
vgap,
lgap,
rgap,
tgap,
bgap,
})
);
return;
}
this.text = createWidget(
extend(json, {
hgap, hgap,
vgap, vgap,
lgap, lgap,
rgap, rgap,
tgap, tgap,
bgap, bgap,
})); })
);
return;
}
this.text = createWidget(extend(json, {
hgap,
vgap,
lgap,
rgap,
tgap,
bgap,
}));
createWidget({ createWidget({
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
element: this, element: this,
items: [this.text], items: [this.text],
@ -224,7 +239,8 @@ export class AbstractLabel extends Single {
if (isNumber(width) && width > 0) { if (isNumber(width) && width > 0) {
if (isNumber(textWidth) && textWidth > 0) { if (isNumber(textWidth) && textWidth > 0) {
json.maxWidth = textWidth; json.maxWidth = textWidth;
if (isNumber(height) && height > 0) { // 2.1 if (isNumber(height) && height > 0) {
// 2.1
createWidget({ createWidget({
type: adaptLayout, type: adaptLayout,
horizontalAlign: textAlign, horizontalAlign: textAlign,
@ -241,7 +257,8 @@ export class AbstractLabel extends Single {
return; return;
} }
createWidget({ // 2.2 createWidget({
// 2.2
type: adaptLayout, type: adaptLayout,
horizontalAlign: textAlign, horizontalAlign: textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
@ -262,27 +279,31 @@ export class AbstractLabel extends Single {
return; return;
} }
if (isNumber(height) && height > 0) { // 2.3 if (isNumber(height) && height > 0) {
// 2.3
if (whiteSpace !== "normal") { if (whiteSpace !== "normal") {
this.element.css({ this.element.css({
"line-height": BI.pixFormat(height - (vgap * 2)), "line-height": BI.pixFormat(height - vgap * 2),
}); });
} }
delete json.maxWidth; delete json.maxWidth;
this.text = createWidget(extend(json, { this.text = createWidget(
element: this, extend(json, {
hgap, element: this,
vgap, hgap,
lgap, vgap,
rgap, lgap,
tgap, rgap,
bgap, tgap,
})); bgap,
})
);
return; return;
} }
json.maxWidth = width - 2 * hgap - lgap - rgap; json.maxWidth = width - 2 * hgap - lgap - rgap;
createWidget({ // 2.4 createWidget({
// 2.4
type: adaptLayout, type: adaptLayout,
horizontalAlign: textAlign, horizontalAlign: textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
@ -294,16 +315,19 @@ export class AbstractLabel extends Single {
tgap, tgap,
bgap, bgap,
element: this, element: this,
items: [{ items: [
el: (this.text = createWidget(json)), {
}], el: (this.text = createWidget(json)),
}
],
}); });
return; return;
} }
if (isNumber(textWidth) && textWidth > 0) { if (isNumber(textWidth) && textWidth > 0) {
json.maxWidth = textWidth; json.maxWidth = textWidth;
createWidget({ // 2.5 createWidget({
// 2.5
type: adaptLayout, type: adaptLayout,
horizontalAlign: textAlign, horizontalAlign: textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1 columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
@ -327,30 +351,35 @@ export class AbstractLabel extends Single {
if (isNumber(height) && height > 0) { if (isNumber(height) && height > 0) {
if (whiteSpace !== "normal") { if (whiteSpace !== "normal") {
this.element.css({ this.element.css({
"line-height": BI.pixFormat(height - (vgap * 2)), "line-height": BI.pixFormat(height - vgap * 2),
}); });
} }
delete json.maxWidth; delete json.maxWidth;
this.text = createWidget(extend(json, { // 2.6 this.text = createWidget(
element: this, extend(json, {
// 2.6
element: this,
hgap,
vgap,
lgap,
rgap,
tgap,
bgap,
})
);
return;
}
this.text = createWidget(
extend(json, {
hgap, hgap,
vgap, vgap,
lgap, lgap,
rgap, rgap,
tgap, tgap,
bgap, bgap,
})); })
);
return;
}
this.text = createWidget(extend(json, {
hgap,
vgap,
lgap,
rgap,
tgap,
bgap,
}));
createWidget({ createWidget({
type: adaptLayout, type: adaptLayout,
horizontalAlign: textAlign, horizontalAlign: textAlign,

10
src/base/single/label/html.label.js

@ -1,8 +1,10 @@
import { Html } from "../html/html";
import { AbstractLabel } from "./abstract.label";
import { shortcut } from "@/core";
/** /**
* Created by GUY on 2015/6/26. * Created by GUY on 2015/6/26.
*/ */
import { shortcut } from "../../../core";
import { AbstractLabel } from "./abstract.label";
@shortcut() @shortcut()
export class HtmlLabel extends AbstractLabel { export class HtmlLabel extends AbstractLabel {
@ -10,13 +12,13 @@ export class HtmlLabel extends AbstractLabel {
props = { props = {
baseCls: "bi-html-label", baseCls: "bi-html-label",
} };
_createJson() { _createJson() {
const { textAlign, whiteSpace, textHeight, text, value, handler } = this.options; const { textAlign, whiteSpace, textHeight, text, value, handler } = this.options;
return { return {
type: "bi.html", type: Html.xtype,
textAlign, textAlign,
whiteSpace, whiteSpace,
lineHeight: textHeight, lineHeight: textHeight,

14
src/base/single/label/icon.label.js

@ -1,10 +1,12 @@
import { Icon } from "../icon/icon";
import { DefaultLayout, CenterAdaptLayout, shortcut, createWidget, isNumber, isNull } from "@/core";
import { Single } from "../0.single";
/** /**
* @class BI.IconLabel * @class BI.IconLabel
* @extends BI.Single * @extends BI.Single
* 图标标签 * 图标标签
*/ */
import { shortcut, createWidget, isNumber, isNull } from "../../../core";
import { Single } from "../0.single";
@shortcut() @shortcut()
export class IconLabel extends Single { export class IconLabel extends Single {
@ -21,7 +23,7 @@ export class IconLabel extends Single {
iconWidth: null, iconWidth: null,
iconHeight: null, iconHeight: null,
lineHeight: null, lineHeight: null,
} };
render() { render() {
const { iconWidth, iconHeight, height, lineHeight, hgap, vgap, lgap, rgap, tgap, bgap } = this.options; const { iconWidth, iconHeight, height, lineHeight, hgap, vgap, lgap, rgap, tgap, bgap } = this.options;
@ -29,14 +31,14 @@ export class IconLabel extends Single {
textAlign: "center", textAlign: "center",
}); });
this.icon = createWidget({ this.icon = createWidget({
type: "bi.icon", type: Icon.xtype,
width: iconWidth, width: iconWidth,
height: iconHeight, height: iconHeight,
}); });
if (isNumber(height) && height > 0 && isNull(iconWidth) && isNull(iconHeight)) { if (isNumber(height) && height > 0 && isNull(iconWidth) && isNull(iconHeight)) {
this.element.css("lineHeight", BI.pixFormat(lineHeight || height)); this.element.css("lineHeight", BI.pixFormat(lineHeight || height));
createWidget({ createWidget({
type: "bi.default", type: DefaultLayout.xtype,
element: this, element: this,
hgap, hgap,
vgap, vgap,
@ -50,7 +52,7 @@ export class IconLabel extends Single {
this.element.css("lineHeight", "1"); this.element.css("lineHeight", "1");
createWidget({ createWidget({
element: this, element: this,
type: "bi.center_adapt", type: CenterAdaptLayout.xtype,
hgap, hgap,
vgap, vgap,
lgap, lgap,

8
src/base/single/label/index.js

@ -1,4 +1,4 @@
export { AbstractLabel } from "./abstract.label"; export { AbstractLabel } from "./abstract.label";
export { HtmlLabel } from "./html.label"; export { HtmlLabel } from "./html.label";
export { IconLabel } from "./icon.label"; export { IconLabel } from "./icon.label";
export { Label } from "./label"; export { Label } from "./label";

7
src/base/single/label/label.js

@ -1,8 +1,9 @@
import { AbstractLabel } from "./abstract.label";
import { shortcut, isFunction, isNotNull } from "@/core";
/** /**
* Created by GUY on 2015/6/26. * Created by GUY on 2015/6/26.
*/ */
import { shortcut, isFunction, isNotNull } from "../../../core";
import { AbstractLabel } from "./abstract.label";
@shortcut() @shortcut()
export class Label extends AbstractLabel { export class Label extends AbstractLabel {
@ -12,7 +13,7 @@ export class Label extends AbstractLabel {
baseCls: "bi-label", baseCls: "bi-label",
py: "", py: "",
keyword: "", keyword: "",
} };
getTitle() { getTitle() {
const title = this.options.title; const title = this.options.title;

10
src/base/single/link/link.js

@ -1,10 +1,12 @@
import { A } from "../a/a";
import { Label } from "../label/label";
import { shortcut, extend } from "@/core";
/** /**
* guy a元素 * guy a元素
* @class BI.Link * @class BI.Link
* @extends BI.Text * @extends BI.Text
*/ */
import { shortcut, extend } from "../../../core";
import { Label } from "../label/label";
@shortcut() @shortcut()
export class Link extends Label { export class Link extends Label {
@ -14,7 +16,7 @@ export class Link extends Label {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
baseCls: (conf.baseCls || "") + " bi-link display-block", baseCls: `${conf.baseCls || ""} bi-link display-block`,
tagName: "a", tagName: "a",
href: "", href: "",
target: "_blank", target: "_blank",
@ -25,7 +27,7 @@ export class Link extends Label {
const { textAlign, whiteSpace, textHeight, text, keyword, value, py, href, target } = this.options; const { textAlign, whiteSpace, textHeight, text, keyword, value, py, href, target } = this.options;
return { return {
type: "bi.a", type: A.xtype,
textAlign, textAlign,
whiteSpace, whiteSpace,
lineHeight: textHeight, lineHeight: textHeight,

19
src/base/single/text.pure.js

@ -1,22 +1,25 @@
import { Text } from "./1.text";
import { Widget, shortcut, isFunction, isKey, isNotNull } from "@/core";
/** /**
* 没有html标签的纯文本 * 没有html标签的纯文本
*/ */
import { Widget, shortcut, isFunction, isKey, isNotNull } from "../../core";
import { Text } from "./1.text";
@shortcut() @shortcut()
export class PureText extends Widget { export class PureText extends Widget {
static xtype = "bi.pure_text"; static xtype = "bi.pure_text";
props = { props = {
tagName: null, tagName: null,
} };
render() { render() {
const { text: optionsText, value } = this.options; const { text: optionsText, value } = this.options;
const text = isFunction(optionsText) ? this.__watch(optionsText, (context, newValue) => { const text = isFunction(optionsText)
this.setText(newValue); ? this.__watch(optionsText, (context, newValue) => {
}) : optionsText; this.setText(newValue);
})
: optionsText;
if (isKey(text)) { if (isKey(text)) {
this.setText(text); this.setText(text);
} else if (isKey(value)) { } else if (isKey(value)) {
@ -32,7 +35,7 @@ export class PureText extends Widget {
return ""; return "";
} }
return Text.formatText(text + ""); return Text.formatText(`${text}`);
} }
setValue(value) { setValue(value) {

8
src/base/single/tip/0.tip.js

@ -1,3 +1,6 @@
import { Single } from "../0.single";
import { extend } from "@/core";
/** /**
* guy * guy
* tip提示 * tip提示
@ -7,12 +10,10 @@
* @abstract * @abstract
*/ */
import { Single } from "../0.single";
import { extend } from "../../../core";
export class Tip extends Single { export class Tip extends Single {
_defaultConfig() { _defaultConfig() {
const conf = super._defaultConfig(...arguments); const conf = super._defaultConfig(...arguments);
return extend(conf, { return extend(conf, {
_baseCls: `${conf._baseCls || ""} bi-tip`, _baseCls: `${conf._baseCls || ""} bi-tip`,
zIndex: BI.zIndex_tip, zIndex: BI.zIndex_tip,
@ -24,4 +25,3 @@ export class Tip extends Single {
this.element.css({ zIndex: this.options.zIndex }); this.element.css({ zIndex: this.options.zIndex });
} }
} }

221
src/base/single/tip/tip.toast.js

@ -1,3 +1,8 @@
import { IconLabel, Label } from "../label";
import { IconButton } from "../button";
import { HorizontalLayout, shortcut, extend, isPlainObject } from "@/core";
import { Tip } from "./0.tip";
/** /**
* toast提示 * toast提示
* *
@ -6,121 +11,123 @@
* @extends BI.Tip * @extends BI.Tip
*/ */
import { shortcut, extend, isPlainObject } from "../../../core";
import { Tip } from "./0.tip";
@shortcut() @shortcut()
export class Toast extends Tip { export class Toast extends Tip {
_const= { _const = {
closableMinWidth: 146, closableMinWidth: 146,
minWidth: 100, minWidth: 100,
closableMaxWidth: 410, closableMaxWidth: 410,
maxWidth: 400, maxWidth: 400,
} };
static EVENT_DESTORY = "EVENT_DESTORY"; static EVENT_DESTORY = "EVENT_DESTORY";
static xtype = "bi.toast"; static xtype = "bi.toast";
_defaultConfig() { _defaultConfig() {
return extend(super._defaultConfig(...arguments), { return extend(super._defaultConfig(...arguments), {
extraCls: "bi-toast", extraCls: "bi-toast",
text: "", text: "",
level: "success", // success或warning level: "success", // success或warning
autoClose: true, autoClose: true,
closable: null, closable: null,
textHeight: 20, textHeight: 20,
vgap: 10, vgap: 10,
innerHgap: 4, innerHgap: 4,
hgap: 8, hgap: 8,
}); });
} }
render() { render() {
const { closable, level, autoClose, textHeight, text, hgap, vgap, innerHgap } = this.options; const { closable, level, autoClose, textHeight, text, hgap, vgap, innerHgap } = this.options;
const { closableMinWidth, minWidth, maxWidth, closableMaxWidth } = this._const; const { closableMinWidth, minWidth, maxWidth, closableMaxWidth } = this._const;
this.element.css({ this.element.css({
minWidth: BI.pixFormat(closable ? closableMinWidth : minWidth), minWidth: BI.pixFormat(closable ? closableMinWidth : minWidth),
maxWidth: BI.pixFormat(closable ? closableMaxWidth : maxWidth), maxWidth: BI.pixFormat(closable ? closableMaxWidth : maxWidth),
}); });
this.element.addClass(`toast-${level}`); this.element.addClass(`toast-${level}`);
function fn(e) { function fn(e) {
e.stopPropagation(); e.stopPropagation();
e.stopEvent(); e.stopEvent();
return false;
}
this.element.bind({
click: fn,
mousedown: fn,
mouseup: fn,
mouseover: fn,
mouseenter: fn,
mouseleave: fn,
mousemove: fn,
});
let cls;
switch (level) {
case "success":
cls = "toast-success-font";
break;
case "error":
cls = "toast-error-font";
break;
case "warning":
cls = "toast-warning-font";
break;
case "loading":
cls = "toast-loading-font anim-rotate";
break;
case "normal":
default:
cls = "toast-message-font";
break;
}
function hasCloseIcon() { return false;
return closable === true || (closable === null && autoClose === false); }
} this.element.bind({
const items = [{ click: fn,
type: "bi.icon_label", mousedown: fn,
cls: `${cls} toast-icon`, mouseup: fn,
height: textHeight, mouseover: fn,
}, { mouseenter: fn,
el: isPlainObject(text) ? text : { mouseleave: fn,
type: "bi.label", mousemove: fn,
whiteSpace: "normal", });
text, let cls;
textHeight, switch (level) {
textAlign: "left", case "success":
}, cls = "toast-success-font";
}]; break;
case "error":
cls = "toast-error-font";
break;
case "warning":
cls = "toast-warning-font";
break;
case "loading":
cls = "toast-loading-font anim-rotate";
break;
case "normal":
default:
cls = "toast-message-font";
break;
}
const columnSize = ["", "fill"]; function hasCloseIcon() {
return closable === true || (closable === null && autoClose === false);
}
const items = [
{
type: IconLabel.xtype,
cls: `${cls} toast-icon`,
height: textHeight,
},
{
el: isPlainObject(text)
? text
: {
type: Label.xtype,
whiteSpace: "normal",
text,
textHeight,
textAlign: "left",
},
}
];
if (hasCloseIcon()) { const columnSize = ["", "fill"];
items.push({
type: "bi.icon_button",
cls: "close-font toast-icon",
handler: () => {
this.destroy();
},
height: textHeight,
});
columnSize.push("");
}
return { if (hasCloseIcon()) {
type: "bi.horizontal", items.push({
horizontalAlign: BI.HorizontalAlign.Stretch, type: IconButton.xtype,
items, cls: "close-font toast-icon",
hgap, handler: () => {
vgap, this.destroy();
innerHgap, },
columnSize, height: textHeight,
}; });
} columnSize.push("");
}
beforeDestroy() { return {
this.fireEvent(Toast.EVENT_DESTORY); type: HorizontalLayout.xtype,
} horizontalAlign: BI.HorizontalAlign.Stretch,
} items,
hgap,
vgap,
innerHgap,
columnSize,
};
}
beforeDestroy() {
this.fireEvent(Toast.EVENT_DESTORY);
}
}

146
src/base/single/tip/tip.tooltip.js

@ -1,3 +1,7 @@
import { VerticalLayout, shortcut, extend, createWidget, map } from "@/core";
import { Label } from "../label";
import { Tip } from "./0.tip";
/** /**
* title提示 * title提示
* *
@ -6,87 +10,85 @@
* @extends BI.Tip * @extends BI.Tip
*/ */
import { shortcut, extend, createWidget, map } from "../../../core";
import { Tip } from "./0.tip";
@shortcut() @shortcut()
export class Tooltip extends Tip { export class Tooltip extends Tip {
_const = { _const = {
hgap: 8, hgap: 8,
vgap: 4, vgap: 4,
};
static xtype = "bi.tooltip";
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
extraCls: "bi-tooltip",
text: "",
level: "success", // success或warning
stopEvent: false,
stopPropagation: false,
textAlign: "left",
});
} }
static xtype = "bi.tooltip";
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
extraCls: "bi-tooltip",
text: "",
level: "success", // success或warning
stopEvent: false,
stopPropagation: false,
textAlign: "left",
});
}
render () { render() {
const { level, stopPropagation, stopEvent, text, textAlign } = this.options; const { level, stopPropagation, stopEvent, text, textAlign } = this.options;
this.element.addClass(`tooltip-${level}`); this.element.addClass(`tooltip-${level}`);
function fn(e) { function fn(e) {
stopPropagation && e.stopPropagation(); stopPropagation && e.stopPropagation();
stopEvent && e.stopEvent(); stopEvent && e.stopEvent();
} }
this.element.bind({ this.element.bind({
click: fn, click: fn,
mousedown: fn, mousedown: fn,
mouseup: fn, mouseup: fn,
mouseover: fn, mouseover: fn,
mouseenter: fn, mouseenter: fn,
mouseleave: fn, mouseleave: fn,
mousemove: fn, mousemove: fn,
}); });
const texts = (`${text}`).split("\n"); const texts = `${text}`.split("\n");
if (texts.length > 1) { if (texts.length > 1) {
createWidget({ createWidget({
type: "bi.vertical", type: VerticalLayout.xtype,
element: this, element: this,
hgap: this._const.hgap, hgap: this._const.hgap,
innerVgap: this._const.vgap, innerVgap: this._const.vgap,
items: map(texts, (i, text) => { items: map(texts, (i, text) => {
return { return {
type: "bi.label", type: Label.xtype,
textAlign, textAlign,
whiteSpace: "normal", whiteSpace: "normal",
text, text,
textHeight: 18, textHeight: 18,
title: null, title: null,
}; };
}), }),
}); });
} else { } else {
this.text = createWidget({ this.text = createWidget({
type: "bi.label", type: Label.xtype,
element: this, element: this,
textAlign, textAlign,
whiteSpace: "normal", whiteSpace: "normal",
text, text,
title: null, title: null,
textHeight: 18, textHeight: 18,
hgap: this._const.hgap, hgap: this._const.hgap,
vgap: this._const.vgap, vgap: this._const.vgap,
}); });
} }
} }
setWidth(width) { setWidth(width) {
this.element.width(BI.pixFormat(width - 2 * this._const.hgap)); this.element.width(BI.pixFormat(width - 2 * this._const.hgap));
} }
setText(text) { setText(text) {
this.text && this.text.setText(text); this.text && this.text.setText(text);
} }
setLevel(level) { setLevel(level) {
this.element.removeClass("tooltip-success").removeClass("tooltip-warning"); this.element.removeClass("tooltip-success").removeClass("tooltip-warning");
this.element.addClass(`tooltip-${level}`); this.element.addClass(`tooltip-${level}`);
} }
} }

13
src/base/single/trigger/trigger.js

@ -1,11 +1,12 @@
import { Single } from "../0.single";
import { extend } from "@/core";
/** /**
* 下拉 * 下拉
* @class BI.Trigger * @class BI.Trigger
* @extends BI.Single * @extends BI.Single
* @abstract * @abstract
*/ */
import { extend } from "../../../core";
import { Single } from "../0.single";
export class Trigger extends Single { export class Trigger extends Single {
_defaultConfig() { _defaultConfig() {
@ -17,11 +18,7 @@ export class Trigger extends Single {
}); });
} }
setKey() { setKey() {}
} getKey() {}
getKey() {
}
} }

72
src/base/tree/customtree.js

@ -1,3 +1,23 @@
import { ButtonTree, Expander } from "../combination";
import {
VerticalLayout,
Widget,
shortcut,
extend,
emptyFn,
Tree,
each,
isNotEmptyArray,
deepClone,
stripEL,
isWidget,
clone,
isNotNull,
isNull,
createWidget,
Controller
} from "@/core";
/** /**
* *
* 自定义树 * 自定义树
@ -6,7 +26,7 @@
* @class BI.CustomTree * @class BI.CustomTree
* @extends BI.Single * @extends BI.Single
*/ */
import { Widget, shortcut, extend, emptyFn, Tree, each, isNotEmptyArray, deepClone, stripEL, isWidget, clone, isNotNull, isNull, createWidget, Controller } from "../../core";
@shortcut() @shortcut()
export class CustomTree extends Widget { export class CustomTree extends Widget {
static xtype = "bi.custom_tree"; static xtype = "bi.custom_tree";
@ -18,7 +38,7 @@ export class CustomTree extends Widget {
expander: { expander: {
el: {}, el: {},
popup: { popup: {
type: "bi.custom_tree", type: CustomTree.xtype,
}, },
}, },
@ -26,11 +46,13 @@ export class CustomTree extends Widget {
itemsCreator: emptyFn, itemsCreator: emptyFn,
el: { el: {
type: "bi.button_tree", type: ButtonTree.xtype,
chooseType: 0, chooseType: 0,
layouts: [{ layouts: [
type: "bi.vertical", {
}], type: VerticalLayout.xtype,
}
],
}, },
}); });
} }
@ -46,16 +68,20 @@ export class CustomTree extends Widget {
const items = []; const items = [];
each(nodes, (i, node) => { each(nodes, (i, node) => {
if (isNotEmptyArray(node.children) || node.isParent === true) { if (isNotEmptyArray(node.children) || node.isParent === true) {
const item = extend({ const item = extend(
type: "bi.expander", {
el: { type: Expander.xtype,
value: node.value, el: {
value: node.value,
},
popup: { type: CustomTree.xtype },
}, },
popup: { type: "bi.custom_tree" }, deepClone(expander),
}, deepClone(expander), { {
id: node.id, id: node.id,
pId: node.pId, pId: node.pId,
}); }
);
let el = stripEL(node); let el = stripEL(node);
if (!isWidget(el)) { if (!isWidget(el)) {
el = clone(el); el = clone(el);
@ -67,7 +93,8 @@ export class CustomTree extends Widget {
item.popup.expander = deepClone(expander); item.popup.expander = deepClone(expander);
item.items = item.popup.items = node.children; item.items = item.popup.items = node.children;
item.itemsCreator = item.popup.itemsCreator = (op, ...arg) => { item.itemsCreator = item.popup.itemsCreator = (op, ...arg) => {
if (isNotNull(op.node)) {// 从子节点传过来的itemsCreator直接向上传递 if (isNotNull(op.node)) {
// 从子节点传过来的itemsCreator直接向上传递
return itemsCreator(op, ...arg); return itemsCreator(op, ...arg);
} }
const args = Array.prototype.slice.call([op, ...arg], 0); const args = Array.prototype.slice.call([op, ...arg], 0);
@ -91,11 +118,14 @@ export class CustomTree extends Widget {
element: this, element: this,
items: this._formatItems(nodes), items: this._formatItems(nodes),
itemsCreator: (op, callback) => { itemsCreator: (op, callback) => {
itemsCreator.apply(this, [op, items => { itemsCreator.apply(this, [
const args = Array.prototype.slice.call(arguments, 0); op,
args[0] = this._formatItems(items); items => {
callback(...args); const args = Array.prototype.slice.call(arguments, 0);
}]); args[0] = this._formatItems(items);
callback(...args);
}
]);
}, },
value, value,
}); });

3
src/case/combo/bubblecombo/popup.bubble.js

@ -1,5 +1,6 @@
import { shortcut, extend } from "@/core"; import { shortcut, extend } from "@/core";
import { PopupView, Label } from "@/base"; import { PopupView } from "@/base/layer/layer.popup";
import { Label } from "@/base/single/label/label";
@shortcut() @shortcut()
export class BubblePopupView extends PopupView { export class BubblePopupView extends PopupView {

Loading…
Cancel
Save