Browse Source

提交核心代码

pull/1/head
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
962fdf6c6d
  1. 3
      README.md
  2. 124
      build.gradle
  3. 13
      encrypt.xml
  4. BIN
      lib/fine-tool-js-engine-1.0.jar
  5. 16
      plugin.xml
  6. 282
      src/main/java/com/tptj/tool/hg/fineui/swing/FineUIEngine.java
  7. 279
      src/main/java/com/tptj/tool/hg/fineui/swing/element/AbstractElement.java
  8. 61
      src/main/java/com/tptj/tool/hg/fineui/swing/element/Element.java
  9. 15
      src/main/java/com/tptj/tool/hg/fineui/swing/element/JPanelElement.java
  10. 43
      src/main/java/com/tptj/tool/hg/fineui/swing/element/LabelElement.java
  11. 12
      src/main/java/com/tptj/tool/hg/fineui/swing/element/Status.java
  12. 154
      src/main/java/com/tptj/tool/hg/fineui/swing/element/TextElement.java
  13. 464
      src/main/java/com/tptj/tool/hg/fineui/swing/element/VerticalFlowLayout.java
  14. 24
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/AbsoluteType.java
  15. 21
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/AbstractLayoutType.java
  16. 34
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/CenterAdaptType.java
  17. 28
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/HorizontalAdaptType.java
  18. 21
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/HorizontalType.java
  19. 52
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/LayoutBuilder.java
  20. 19
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/LayoutType.java
  21. 21
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/VerticalAdaptType.java
  22. 23
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/VerticalType.java
  23. 52
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/impl/AbsoluteLayout.java
  24. 95
      src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/impl/BaseFineUILayout.java
  25. 58
      src/main/java/com/tptj/tool/hg/fineui/swing/stable/ColorUtils.java
  26. 10
      src/main/resources/com/fr/fineui/base/0.base.js
  27. 152
      src/main/resources/com/fr/fineui/base/1.pane.js
  28. 38
      src/main/resources/com/fr/fineui/base/collection/__test__/collection.test.js
  29. 379
      src/main/resources/com/fr/fineui/base/collection/collection.js
  30. 585
      src/main/resources/com/fr/fineui/base/combination/combo.js
  31. 281
      src/main/resources/com/fr/fineui/base/combination/expander.js
  32. 329
      src/main/resources/com/fr/fineui/base/combination/group.button.js
  33. 96
      src/main/resources/com/fr/fineui/base/combination/group.combo.js
  34. 116
      src/main/resources/com/fr/fineui/base/combination/group.virtual.js
  35. 259
      src/main/resources/com/fr/fineui/base/combination/loader.js
  36. 162
      src/main/resources/com/fr/fineui/base/combination/navigation.js
  37. 319
      src/main/resources/com/fr/fineui/base/combination/searcher.js
  38. 291
      src/main/resources/com/fr/fineui/base/combination/switcher.js
  39. 157
      src/main/resources/com/fr/fineui/base/combination/tab.js
  40. 178
      src/main/resources/com/fr/fineui/base/combination/tree.button.js
  41. 38
      src/main/resources/com/fr/fineui/base/el.js
  42. 47
      src/main/resources/com/fr/fineui/base/foundation/__test__/message.test.js
  43. 203
      src/main/resources/com/fr/fineui/base/foundation/message.js
  44. 41
      src/main/resources/com/fr/fineui/base/grid/__test__/grid.test.js
  45. 381
      src/main/resources/com/fr/fineui/base/grid/grid.js
  46. 33
      src/main/resources/com/fr/fineui/base/layer/__test__/layer.popover.test.js
  47. 272
      src/main/resources/com/fr/fineui/base/layer/layer.popover.js
  48. 180
      src/main/resources/com/fr/fineui/base/layer/layer.popup.js
  49. 140
      src/main/resources/com/fr/fineui/base/layer/layer.searcher.js
  50. 48
      src/main/resources/com/fr/fineui/base/list/__test__/listview.test.js
  51. 119
      src/main/resources/com/fr/fineui/base/list/listview.js
  52. 158
      src/main/resources/com/fr/fineui/base/list/virtualgrouplist.js
  53. 195
      src/main/resources/com/fr/fineui/base/list/virtuallist.js
  54. 289
      src/main/resources/com/fr/fineui/base/pager/pager.js
  55. 207
      src/main/resources/com/fr/fineui/base/single/0.single.js
  56. 170
      src/main/resources/com/fr/fineui/base/single/1.text.js
  57. 195
      src/main/resources/com/fr/fineui/base/single/__test__/text.test.js
  58. 32
      src/main/resources/com/fr/fineui/base/single/a/__test__/a.test.js
  59. 33
      src/main/resources/com/fr/fineui/base/single/a/a.js
  60. 80
      src/main/resources/com/fr/fineui/base/single/bar/bar.loading.js
  61. 412
      src/main/resources/com/fr/fineui/base/single/button/button.basic.js
  62. 57
      src/main/resources/com/fr/fineui/base/single/button/button.node.js
  63. 117
      src/main/resources/com/fr/fineui/base/single/button/buttons/__test__/button.test.js
  64. 51
      src/main/resources/com/fr/fineui/base/single/button/buttons/button.icon.js
  65. 86
      src/main/resources/com/fr/fineui/base/single/button/buttons/button.image.js
  66. 157
      src/main/resources/com/fr/fineui/base/single/button/buttons/button.js
  67. 89
      src/main/resources/com/fr/fineui/base/single/button/buttons/button.text.js
  68. 119
      src/main/resources/com/fr/fineui/base/single/button/listitem/blankiconicontextitem.js
  69. 126
      src/main/resources/com/fr/fineui/base/single/button/listitem/blankicontexticonitem.js
  70. 105
      src/main/resources/com/fr/fineui/base/single/button/listitem/blankicontextitem.js
  71. 123
      src/main/resources/com/fr/fineui/base/single/button/listitem/icontexticonitem.js
  72. 102
      src/main/resources/com/fr/fineui/base/single/button/listitem/icontextitem.js
  73. 101
      src/main/resources/com/fr/fineui/base/single/button/listitem/texticonitem.js
  74. 86
      src/main/resources/com/fr/fineui/base/single/button/listitem/textitem.js
  75. 104
      src/main/resources/com/fr/fineui/base/single/button/node/__test__/icontexticonnode.test.js
  76. 104
      src/main/resources/com/fr/fineui/base/single/button/node/__test__/icontextnode.test.js
  77. 104
      src/main/resources/com/fr/fineui/base/single/button/node/__test__/texticonnode.test.js
  78. 106
      src/main/resources/com/fr/fineui/base/single/button/node/__test__/textnode.test.js
  79. 113
      src/main/resources/com/fr/fineui/base/single/button/node/icontexticonnode.js
  80. 90
      src/main/resources/com/fr/fineui/base/single/button/node/icontextnode.js
  81. 89
      src/main/resources/com/fr/fineui/base/single/button/node/texticonnode.js
  82. 77
      src/main/resources/com/fr/fineui/base/single/button/node/textnode.js
  83. 370
      src/main/resources/com/fr/fineui/base/single/editor/editor.js
  84. 99
      src/main/resources/com/fr/fineui/base/single/editor/editor.multifile.js
  85. 252
      src/main/resources/com/fr/fineui/base/single/editor/editor.textarea.js
  86. 42
      src/main/resources/com/fr/fineui/base/single/html/__test__/html.test.js
  87. 114
      src/main/resources/com/fr/fineui/base/single/html/html.js
  88. 21
      src/main/resources/com/fr/fineui/base/single/icon/icon.js
  89. 23
      src/main/resources/com/fr/fineui/base/single/iframe/__test__/iframe.test.js
  90. 57
      src/main/resources/com/fr/fineui/base/single/iframe/iframe.js
  91. 23
      src/main/resources/com/fr/fineui/base/single/img/__test__/img.test.js
  92. 40
      src/main/resources/com/fr/fineui/base/single/img/img.js
  93. 22
      src/main/resources/com/fr/fineui/base/single/input/checkbox/checkbox.image.js
  94. 61
      src/main/resources/com/fr/fineui/base/single/input/checkbox/checkbox.js
  95. 697
      src/main/resources/com/fr/fineui/base/single/input/file.js
  96. 315
      src/main/resources/com/fr/fineui/base/single/input/input.js
  97. 29
      src/main/resources/com/fr/fineui/base/single/input/radio/radio.image.js
  98. 62
      src/main/resources/com/fr/fineui/base/single/input/radio/radio.js
  99. 377
      src/main/resources/com/fr/fineui/base/single/label/abstract.label.js
  100. 25
      src/main/resources/com/fr/fineui/base/single/label/html.label.js
  101. Some files were not shown because too many files have changed in this diff Show More

3
README.md

@ -1,3 +1,4 @@
# open-fineui-swing
利用fineui标准,开发设计器的 swing UI
利用fineui标准,开发设计器的 swing UI\
这只是一个核心得框架代码,布局和核心组件的支持需要开发者一起迭代了

124
build.gradle

@ -0,0 +1,124 @@
apply plugin: 'java'
[compileJava,compileTestJava]*.options*.encoding = 'UTF-8'
ext {
/**
* jar的路径
* 1.jar需要打包到zip中,lib根目录下
* 2.jar仅仅是编译时需要lib下子目录下即可
*/
libPath = "$projectDir/../../webroot/WEB-INF/lib"
/**
* class进行加密保护
*/
guard = true
def pluginInfo = getPluginInfo()
pluginPre = "fine-plugin"
pluginName = pluginInfo.id
pluginVersion = pluginInfo.version
outputPath = "$projectDir/../../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes"
}
group = 'com.fr.plugin'
version = '10.0'
sourceCompatibility = '8'
sourceSets {
main {
java.outputDir = file(outputPath)
output.resourcesDir = file(outputPath)
}
}
ant.importBuild("encrypt.xml")
//ant变量
ant.projectDir = projectDir
ant.references["compile.classpath"] = ant.path {
fileset(dir: libPath, includes: '**/*.jar')
fileset(dir: ".",includes:"**/*.jar" )
}
classes.dependsOn('clean')
task copyFiles(type: Copy,dependsOn: 'classes'){
from outputPath
into "$projectDir/classes"
}
task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){
from "$projectDir/classes"
into "$projectDir/transform-classes"
include "**/*.*"
}
jar.dependsOn("preJar")
task makeJar(type: Jar,dependsOn: preJar){
from fileTree(dir: "$projectDir/transform-classes")
baseName pluginPre
appendix pluginName
version pluginVersion
destinationDir = file("$buildDir/libs")
doLast(){
delete file("$projectDir/classes")
delete file("$projectDir/transform-classes")
}
}
task copyFile(type: Copy,dependsOn: ["makeJar"]){
from "$buildDir/libs"
from("$projectDir/lib") {
include "*.jar"
}
from "$projectDir/plugin.xml"
into file("$buildDir/temp/plugin")
}
task zip(type:Zip,dependsOn:["copyFile"]){
from "$buildDir/temp/plugin"
destinationDir file("$buildDir/install")
baseName pluginPre
appendix pluginName
version pluginVersion
}
//build时包含哪些文件,
processResources {
// exclude everything
// *.css没效果
// exclude '**/*.css'
// except this file
// include 'xx.xml'
}
/*读取plugin.xml中的version*/
def getPluginInfo(){
def xmlFile = file("plugin.xml")
if (!xmlFile.exists()) {
return ["id":"none", "version":"1.0.0"]
}
def plugin = new XmlParser().parse(xmlFile)
def version = plugin.version[0].text()
def id = plugin.id[0].text()
return ["id":id,"version":version]
}
repositories {
mavenLocal()
maven {
url = uri('http://mvn.finedevelop.com/repository/maven-public/')
}
}
dependencies {
//使jar
implementation fileTree(dir: 'lib', include: ['**/*.jar'])
implementation fileTree(dir: libPath, include: ['**/*.jar'])
}

13
encrypt.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<target name="compile_encrypt_javas" depends="copyFiles">
<echo message="加密文件"/>
<echo message="${projectDir}"/>
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask">
<classpath refid="compile.classpath"/>
</taskdef>
<pretreatment baseDir="${projectDir}"/>
</target>
<target name="compile_plain_javas" depends="copyFiles">
</target>
</project>

BIN
lib/fine-tool-js-engine-1.0.jar

Binary file not shown.

16
plugin.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin>
<id>com.tptj.tool.hg.fineui.swing</id>
<name><![CDATA[ Swing Fine UI ]]></name>
<active>yes</active>
<version>1.0</version>
<env-version>10.0</env-version>
<vendor>tptj</vendor>
<jartime>2019-07-18</jartime>
<description><![CDATA[ ]]></description>
<change-notes><![CDATA[]]></change-notes>
<main-package>com.tptj.tool.hg.fineui.swing</main-package>
<function-recorder class="com.tptj.tool.hg.fineui.swing.DemoTableData"/>
<extra-designer>
<TableDataDefineProvider class="com.tptj.tool.hg.fineui.swing.DemoTableDataRegister"/>
</extra-designer>
</plugin>

282
src/main/java/com/tptj/tool/hg/fineui/swing/FineUIEngine.java

@ -0,0 +1,282 @@
package com.tptj.tool.hg.fineui.swing;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Object;
import com.fr.log.FineLoggerFactory;
import com.tptj.tool.hg.engine.js.Debugger;
import com.tptj.tool.hg.engine.js.JsEngineMaker;
import com.tptj.tool.hg.engine.js.JsProcess;
import com.tptj.tool.hg.fineui.swing.element.Element;
import com.tptj.tool.hg.fineui.swing.element.JPanelElement;
import javax.swing.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/10/28
**/
public class FineUIEngine {
public JsEngineMaker engine;
private static volatile FineUIEngine instance = null;
public static FineUIEngine getInstance() {
if (null == instance) {
synchronized (FineUIEngine.class) {
if (null == instance) {
instance = new FineUIEngine();
}
}
}
return instance;
}
private FineUIEngine() {
init();
}
private void init() {
try {
//之间一次引入全部fineui,会因为各种环境参数方法的缺失而大量报错,因为调试难度很大,
// 所以采用逐渐引入,逐渐调试的方式去逐渐覆盖,
// 待全面适配成功后应该可以直接引入fineui.min.js了
engine = JsEngineMaker.newInstance();
JsProcess.create(engine.getEngine(),()->{
engine.importJs(
//com/fr/fineui 目录下的都是fineui自身的源码
"com/fr/fineui/core/0.foundation.js",
"com/fr/fineui/core/1.lodash.js",
"com/fr/fineui/core/2.base.js",
"com/fr/fineui/core/3.ob.js",
"com/fr/fineui/core/4.widget.js",
"com/fr/fineui/core/5.shortcut.js",
"com/fr/fineui/core/6.inject.js",
"com/fr/fineui/core/7.plugin.js",
"com/fr/fineui/core/system.js",
"com/fr/fineui/core/version.js",
"com/fr/fineui/core/constant/date.i18n.js",
"com/fr/fineui/core/constant/events.js",
"com/fr/fineui/core/constant/var.js",
"com/fr/fineui/core/func/alias.js",
"com/fr/fineui/core/func/array.js",
"com/fr/fineui/core/func/date.js",
"com/fr/fineui/core/func/function.js",
"com/fr/fineui/core/func/number.js",
"com/fr/fineui/core/func/string.js",
"com/fr/fineui/core/structure/aes.js",
"com/fr/fineui/core/structure/aspect.js",
"com/fr/fineui/core/structure/base64.js",
"com/fr/fineui/core/structure/cache.js",
"com/fr/fineui/core/structure/cellSizeAndPositionManager.js",
"com/fr/fineui/core/structure/heap.js",
"com/fr/fineui/core/structure/linkedHashMap.js",
"com/fr/fineui/core/structure/lru.js",
"com/fr/fineui/core/structure/prefixIntervalTree.js",
"com/fr/fineui/core/structure/queue.js",
"com/fr/fineui/core/structure/sectionManager.js",
"com/fr/fineui/core/structure/tree.js",
"com/fr/fineui/core/structure/vector.js",
"com/fr/fineui/core/utils/chinesePY.js",
"com/fr/fineui/core/utils/i18n.js",
"com/fr/fineui/core/wrapper/layout.js",
"com/fr/fineui/core/wrapper/layout/layout.absolute.js",
"com/fr/fineui/core/wrapper/layout/layout.adaptive.js",
"com/fr/fineui/core/wrapper/layout/layout.border.js",
"com/fr/fineui/core/wrapper/layout/layout.default.js",
"com/fr/fineui/core/wrapper/layout/layout.flow.js",
"com/fr/fineui/core/wrapper/layout/layout.horizontal.js",
"com/fr/fineui/core/wrapper/layout/layout.tape.js",
"com/fr/fineui/core/wrapper/layout/layout.grid.js",
"com/fr/fineui/core/wrapper/layout/layout.window.js",
"com/fr/fineui/core/wrapper/layout/layout.vertical.js",
"com/fr/fineui/core/wrapper/layout/adapt/adapt.center.js",
"com/fr/fineui/core/wrapper/layout/adapt/adapt.vertical.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.vertical.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.horizontal.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.center.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.horizontal.center.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.vertical.center.js",
"com/fr/fineui/core/wrapper/layout/flex/flex.leftrightvertical.center.js",
//com/tptj/tool/hg/fineui/swing 下的都是适配swing的js代码
// 自定义布局
"com/tptj/tool/hg/fineui/swing/core/wrapper/layout.static.js",
"com/tptj/tool/hg/fineui/swing/core/wrapper/layout.horizontal.js",
"com/tptj/tool/hg/fineui/swing/core/wrapper/layout.vertical.js",
"com/tptj/tool/hg/fineui/swing/core/wrapper/layout.vertical_adapt.js",
"com/tptj/tool/hg/fineui/swing/core/wrapper/layout.center_adapt.js",
"com/tptj/tool/hg/fineui/swing/core/platform/swing/config.js",
"com/tptj/tool/hg/fineui/swing/core/platform/swing/dom.js",
"com/tptj/tool/hg/fineui/swing/core/platform/swing/function.js",
"com/tptj/tool/hg/fineui/swing/core/element.js",
"com/tptj/tool/hg/fineui/swing/core/extra.js",
//自定义的基础控件,最基本的控件需要由swing实现后,映射到fineui中,高级的组件就可以
//由开发者按照fineui的组件继承方式进行组合创建新的组件了
"com/tptj/tool/hg/fineui/swing/base/single/label.js",
"com/tptj/tool/hg/fineui/swing/widget/editor/editor.text.js"
);
return null;
}).run();
engine.setDebugger(new Debugger() {
@Override
public void debug(Object... obj) {
//用来打断点查看JS的属性和变量的,因为V8调试是很麻烦的,所以一般开发者可以简单的
//利用这个入口对调试的变量进行查看
//console.debug(变量1,变量2,变量3,....)
int a = 1;
}
});
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "FineUI swing引擎初始化失败!{}", e.getMessage());
}
}
/**
* 设置本次渲染的根节点
*
* @param element
*/
public FineUIEngine body(Element element) {
engine.set("body", element);
return this;
}
public FineUIEngine importJs(String... path) {
engine.importJs(path);
return this;
}
public void close(){
engine.close();
}
public static Object trans(V8 v8,Object result){
return JsEngineMaker.trans(v8,result);
}
public static void close( Object value ){
JsEngineMaker.close(value);
}
public static Object call(V8Object js, String method, Object ... args)throws Exception{
//为了保证跨线程调用成功,在java中调用JS对象的方法时,
// 需要使用JsProcess.create(V8Object,Action)的方式
return JsProcess.create(js,()->{
return executeFunction(js, method, args);
}).run();
}
public static Object executeFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeFunction(js, method, args);
}
public static V8Array executeArrayFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeArrayFunction(js, method, args);
}
public static V8Object executeObjectFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeObjectFunction(js, method, args);
}
public static String executeStringFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeStringFunction(js, method, args);
}
public static boolean executeBooleanFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeBooleanFunction(js, method, args);
}
public static double executeDoubleFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeDoubleFunction(js, method, args);
}
public static int executeIntegerFunction( V8Object js, String method, Object ... args ){
return JsEngineMaker.executeIntegerFunction(js, method, args);
}
public static void executeVoidFunction( V8Object js, String method, Object ... args ){
JsEngineMaker.executeVoidFunction(js, method, args);
}
public static void main(String[] args) throws Exception {
//最终UI整个结构就在el里面~再用java把el渲染出来即可
//目前利用这个框架简单的实现了 绝对布局 边界(圣杯)布局、水平带布局、垂直带布局、网格布局、窗口布局 几个经典的fineui静态布局
//设计器插件本身其实也基本都是静态布局即可满足需要
JPanelElement el = new JPanelElement();
FineUIEngine engine = FineUIEngine.getInstance();
JsProcess.create(engine.engine.getEngine(),()->{
engine.body(el)
//demo下面的就是实际使用时的代码了,该框架包开发完毕,使用者要写的就是按照demo目录下那些代码了
//.importJs("com/tptj/tool/hg/fineui/swing/demo/layout.border.js");
//.importJs("com/tptj/tool/hg/fineui/swing/demo/layout.tape.js");
//.importJs("com/tptj/tool/hg/fineui/swing/demo/layout.grid.js");
.importJs("com/tptj/tool/hg/fineui/swing/demo/layout.window.js");
return null;
}).run();
JFrame frame = new JFrame("Fine UI Demo");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(el.getComponent());
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
//hugh:使用的是V8的引擎,这个引擎要求必须是主动释放资源,否则会内存泄露
//所以在使用完毕后一定要记得关闭
engine.close();
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
// 显示窗口
frame.setVisible(true);
System.out.println(el);
}
}

279
src/main/java/com/tptj/tool/hg/fineui/swing/element/AbstractElement.java

@ -0,0 +1,279 @@
package com.tptj.tool.hg.fineui.swing.element;
import com.eclipsesource.v8.V8Object;
import com.fr.general.GeneralUtils;
import com.fr.log.FineLoggerFactory;
import com.tptj.tool.hg.fineui.swing.FineUIEngine;
import com.tptj.tool.hg.fineui.swing.element.layout.LayoutBuilder;
import com.tptj.tool.hg.fineui.swing.element.layout.LayoutType;
import com.tptj.tool.hg.fineui.swing.stable.ColorUtils;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/10/29
**/
public abstract class AbstractElement<T extends JComponent> implements Element<T> {
private T component;
private JComponent wrapper;
private V8Object ref;
private String type;
//记录当前的控件状态,用于驱动一些特殊事件
private Status status;
public AbstractElement(T component) {
this.wrapper = component;
this.component = component;
}
public void setComponent(T component) {
this.wrapper = component;
this.component = component;
}
private Map<String, Object> attributes = new HashMap<String, Object>();
private Map<String, Object> data = new HashMap<String, Object>();
private Set<String> clazz_set = new HashSet<String>();
private Map<String, Object> css = new HashMap<String, Object>();
private int width;
private int height;
private Object val;
private AbstractElement parent;
private List<AbstractElement> children = new ArrayList<AbstractElement>();
public AbstractElement() { }
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public JComponent getWrapper() {
return wrapper;
}
@Override
public T getComponent() {
return component;
}
@Override
public void setType(String type) {
this.type = type;
}
@Override
public void mounted() {
}
@Override
public AbstractElement parent() {
return parent;
}
@Override
public void setParent(AbstractElement parent) {
this.parent = parent;
}
@Override
public void ref(V8Object obj) {
this.ref = obj;
}
@Override
public void removeClass(String clazz) {
clazz_set.remove(clazz);
}
@Override
public void setData(String name, Object data) {
this.data.put(name, data);
}
@Override
public void css(String name, String val) {
switch (name) {
case "overflow":
case "overflowX":
case "overflowY":
case "overflow-x":
case "overflow-y":
if ("auto".equals(val)) {
wrapper = new JScrollPane(component);
}
break;
case "background":
component.setOpaque(true);
Color color = ColorUtils.str2Color(val);
component.setBackground( color );
break;
case "color":
color = ColorUtils.str2Color(val);
component.setForeground(color);
break;
default:
break;
}
css.put(name, val);
}
@Override
public Map<String, Object> getStyle() {
return css;
}
@Override
public void cssMap(V8Object map) {
String[] keys = map.getKeys();
for (String key : keys) {
css(key, GeneralUtils.objectToString( map.get(key) ) );
}
}
@Override
public void unbind() {
}
@Override
public void destroy() {
}
@Override
public Object getData(String name) {
return data.get(name);
}
@Override
public void addClass(String clazz) {
clazz_set.add(clazz);
}
@Override
public void setAttr(String name, Object val) {
attributes.put(name, val);
}
@Override
public Object getAttr(String name) {
return attributes.get(name);
}
@Override
public void empty() {
}
@Override
public void layout(String layoutType) {
LayoutType layout = LayoutBuilder.layout(layoutType, this);
component.setLayout(layout.init());
for (int i = 0, len = children.size(); i < len; i++) {
AbstractElement childElement = children.get(i);
layout.layout(childElement,i);
}
}
@Override
public void append(AbstractElement element) {
if (null == element.getComponent()) {
List<AbstractElement> children = element.children();
for (AbstractElement child : children) {
append(child);
}
} else {
children.add(element);
element.setParent(this);
}
}
@Override
public List<AbstractElement> children() {
return children;
}
@Override
public void appendTo(AbstractElement element) {
parent = element;
element.append(this);
}
@Override
public void appendChild(AbstractElement element) {
append(element);
}
@Override
public void setWidth(int width) {
this.width = width;
}
@Override
public void setHeight(int height) {
this.height = height;
}
@Override
public int getWidth() {
return component.getWidth();
}
@Override
public int getHeight() {
return component.getHeight();
}
@Override
public void setVal(Object val) {
this.val = val;
}
protected Object callJsMethod( String name, Object ... args ){
try{
return FineUIEngine.call(ref,name,args);
}catch(Exception e){
FineLoggerFactory.getLogger().error(e,e.getMessage());
}
return null;
}
@Override
public Object getVal() {
return val;
}
@Override
public int getRectStyleAttr( String name, int max, int min ){
Object val = css.get(name);
if("".equals(val)){
return min;
}
if( null == val ){
return min;
}
if( val instanceof String && ((String)val).endsWith("%") ){
String sv = (String)val;
sv = sv.substring( 0, sv.length()-1 );
double vald = GeneralUtils.objectToNumber(sv).doubleValue() * max ;
vald = vald/100;
return (int)vald;
}
return ( null == val || "initial".equals(val) || min > GeneralUtils.objectToNumber(val).intValue() )
? min : GeneralUtils.objectToNumber(val).intValue();
}
}

61
src/main/java/com/tptj/tool/hg/fineui/swing/element/Element.java

@ -0,0 +1,61 @@
package com.tptj.tool.hg.fineui.swing.element;
import com.eclipsesource.v8.V8Object;
import javax.swing.*;
import java.util.List;
import java.util.Map;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/10/29
* 模拟dom的基本操作
**/
public interface Element<T extends JComponent> {
T getComponent();
void setType(String type);
void mounted();
JComponent getWrapper();
Map<String,Object> getStyle();
int getRectStyleAttr( String name,int max, int min );
AbstractElement parent();
void setParent(AbstractElement parent);
void ref( V8Object obj );
void removeClass(String clazz);
/**
* swing组件的渲染都从这个地方接入
* @param name
* @param val
*/
void css(String name,String val);
void cssMap(V8Object map);
void unbind();
void destroy();
void setData(String name,Object data);
Object getData(String name);
void addClass(String clazz);
void setAttr(String name,Object val);
Object getAttr(String name);
void empty();
void layout(String layoutType);
void append( AbstractElement element );
List<AbstractElement> children();
void appendTo( AbstractElement element );
void appendChild( AbstractElement element );
void setWidth(int width);
void setHeight(int height);
int getWidth();
int getHeight();
void setVal(Object val);
Object getVal();
}

15
src/main/java/com/tptj/tool/hg/fineui/swing/element/JPanelElement.java

@ -0,0 +1,15 @@
package com.tptj.tool.hg.fineui.swing.element;
import javax.swing.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/10/29
**/
public class JPanelElement extends AbstractElement<JPanel> {
public JPanelElement() {
super(new JPanel());
}
}

43
src/main/java/com/tptj/tool/hg/fineui/swing/element/LabelElement.java

@ -0,0 +1,43 @@
package com.tptj.tool.hg.fineui.swing.element;
import com.fr.design.gui.ilable.UILabel;
import com.fr.general.GeneralUtils;
import javax.swing.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/10/29
**/
public class LabelElement extends AbstractElement<UILabel> {
public LabelElement() {
super(new UILabel());
}
@Override
public Object getVal(){
return getComponent().getText();
}
@Override
public void setVal( Object val ){
super.setVal(val);
getComponent().setText( GeneralUtils.objectToString(val) );
}
@Override
public void css(String name, String val) {
super.css(name, val);
val = val.toUpperCase();
if( "text-align".equals( name ) ){
if( "LEFT".equals(val) ){
getComponent().setHorizontalAlignment( SwingConstants.LEFT );
}else if( "CENTER".equals(val) ){
getComponent().setHorizontalAlignment( SwingConstants.CENTER );
}else if( "RIGHT".equals(val) ){
getComponent().setHorizontalAlignment( SwingConstants.RIGHT );
}
}
}
}

12
src/main/java/com/tptj/tool/hg/fineui/swing/element/Status.java

@ -0,0 +1,12 @@
package com.tptj.tool.hg.fineui.swing.element;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/2
* 简单的声明组件的几个状态用来驱动一些特殊的事件
* 本身其实并不强制要求实现所有的fineui的事件实现一些常用的即可
**/
public enum Status {
FREE,FOCUS,EDITING
}

154
src/main/java/com/tptj/tool/hg/fineui/swing/element/TextElement.java

@ -0,0 +1,154 @@
package com.tptj.tool.hg.fineui.swing.element;
import com.fr.design.gui.ipasswordfield.UIPassWordField;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.general.GeneralUtils;
import com.fr.stable.StringUtils;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/2
**/
public class TextElement extends AbstractElement<JTextField>{
public TextElement() {
super(new UITextField());
init();
}
private void validationChecker(){
callJsMethod("validationChecker");
}
private boolean quitChecker(){
return (boolean) callJsMethod("quitChecker");
}
private void init() {
JTextField wgt = getComponent();
wgt.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
validationChecker();
callJsMethod("fireEvent","EVENT_CHANGE", wgt.getText() );
}
@Override
public void removeUpdate(DocumentEvent e) {
validationChecker();
callJsMethod("fireEvent","EVENT_CHANGE", wgt.getText() );
if( StringUtils.isEmpty( wgt.getText() ) ){
callJsMethod("fireEvent","EVENT_EMPTY");
}
}
@Override
public void changedUpdate(DocumentEvent e) {
validationChecker();
callJsMethod("fireEvent","EVENT_CHANGE", wgt.getText() );
if( StringUtils.isEmpty( wgt.getText() ) ){
callJsMethod("fireEvent","EVENT_EMPTY");
}
}
});
wgt.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
setStatus(Status.FOCUS);
callJsMethod("fireEvent","EVENT_FOCUS" );
}
@Override
public void focusLost(FocusEvent e) {
setStatus(Status.FREE);
callJsMethod("fireEvent","EVENT_BLUR" );
if( quitChecker() ){
callJsMethod("fireEvent","EVENT_CONFIRM" );
}
}
});
/**
EVENT_CHANGE 输入值改变事件
EVENT_FOCUS focus事件
EVENT_BLUR blur事件
EVENT_KEY_DOWN keydown事件300毫秒debounce才会触发
EVENT_ENTER 回车按键事件当quitChecker为null或检查值不等于false时触发
EVENT_SPACE 空格按键事件
EVENT_BACKSPACE 删除按键事件backspace或del按键触发
EVENT_START 开始输入事件
EVENT_PAUSE 暂停输入事件
EVENT_STOP 停止输入事件
EVENT_CONFIRM 退出输入状态且当前值为有效值时表示的确定事件
EVENT_CHANGE_CONFIRM 当confirm事件触发时如果当前值与上一次有效值不同就会触发该事件
EVENT_REMOVE 清除事件当EVENT_BACKSPACE触发时删除到空的时候触发
EVENT_EMPTY 空事件输入框无值时触发
EVENT_VALID 有效事件输入框值有效触发
EVENT_ERROR 无效事件输入框值无效触发
EVENT_RESTRICT 被限制事件当回车键按下但是quitChecker检查为false表示不允许被退出
**/
wgt.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
char c = e.getKeyChar();
if( KeyEvent.VK_SPACE == (int)c ){
callJsMethod("fireEvent","EVENT_SPACE" );
}else if( KeyEvent.VK_BACK_SPACE == (int)c || KeyEvent.VK_DELETE == (int)c ){
callJsMethod("fireEvent","EVENT_BACKSPACE" );
}else if( KeyEvent.VK_ENTER == (int)c ){
callJsMethod("fireEvent","EVENT_BACKSPACE" );
if( StringUtils.isEmpty( wgt.getText() ) ){
callJsMethod("fireEvent","EVENT_REMOVE" );
}
}
if( Status.FOCUS == getStatus() ){
callJsMethod("fireEvent","EVENT_START" );
}
setStatus(Status.EDITING);
callJsMethod("fireEvent","EVENT_KEY_DOWN" );
}
@Override
public void keyReleased(KeyEvent e) {
}
});
}
@Override
public Object getVal(){
return getComponent().getText();
}
@Override
public void setVal( Object val ){
super.setVal(val);
getComponent().setText( GeneralUtils.objectToString(val) );
}
@Override
public void css(String name, String val){
super.css(name, val);
}
@Override
public void setAttr(String name, Object val){
super.setAttr(name, val);
name = name.toLowerCase();
if("type".equals(name) && "password".equals(val)){
//换JAVA控件只能在这里换,之后就不允许换了!否则会导致渲染的样式丢失
setComponent( new UIPassWordField() );
init();
}
}
}

464
src/main/java/com/tptj/tool/hg/fineui/swing/element/VerticalFlowLayout.java

@ -0,0 +1,464 @@
package com.tptj.tool.hg.fineui.swing.element;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
/**
* A vertical flow layout arranges components in a directional flow, much like
* lines of text in a paragraph. VerticalFlow layouts are typically used to
* arrange buttons in a panel. It arranges buttons vertically until no more
* buttons fit on the same line. The line alignment is determined by the
* <code>align</code> property. The possible values are:
* <ul>
* <li>{@link #TOP TOP}
* <li>{@link #BOTTOM BOTTOM}
* <li>{@link #CENTER CENTER}
* </ul>
* A vertical flow layout lets each component assume its natural (preferred)
* size.
*/
public class VerticalFlowLayout implements LayoutManager {
/**
* This value indicates that each row of components should be top-justified.
*/
public static final int TOP = 0;
/**
* This value indicates that each row of components should be centered.
*/
public static final int CENTER = 1;
/**
* This value indicates that each row of components should be
* bottom-justified.
*/
public static final int BOTTOM = 2;
/**
* <code>align</code> is the property that determines how each column
* distributes empty space. It can be one of the following values:
* <ul>
* <li><code>TOP</code>
* <li><code>RIGHT</code>
* <li><code>BOTTOM</code>
* </ul>
*
* @see #getAlignment()
* @see #setAlignment(int)
*/
private int align;
/**
* The vertical flow layout manager allows a separation of components with
* gaps. The horizontal gap will specify the space between columns and
* between the columns and the borders of the <code>Container</code>.
*
*
* @see #getHgap()
* @see #setHgap(int)
*/
private int hgap;
/**
* The vertical flow layout manager allows a separation of components with
* gaps. The vertical gap will specify the space between components and
* between the components and the borders of the <code>Container</code>.
*
* @see #getVgap()
* @see #setVgap(int)
*/
private int vgap;
/**
* If true, components will be filled with <code>Container</code>
* horizontally.
*
* @see #isHfill()
* @see #setHfill(boolean)
*/
private boolean hfill;
/**
* Constructs a new <code>VerticalFlowLayout</code> with a centered
* alignment and a default 5-unit horizontal and vertical gaps and not
* filled with <code>Container</code> horizontally.
*/
public VerticalFlowLayout() {
this(CENTER, 5, 5, false);
}
/**
* Constructs a new <code>FlowLayout</code> with the specified alignment and
* a default 5-unit horizontal and vertical gaps and not filled with
* <code>Container</code> horizontally. The value of the alignment argument
* must be one of <code>FlowLayout.TOP</code>,
* <code>FlowLayout.BOTTOM</code>, <code>FlowLayout.CENTER</code>.
*
* @param align
* the alignment value
*/
public VerticalFlowLayout(int align) {
this(align, 5, 5, false);
}
/**
* Constructs a new <code>VerticalFlowLayout</code> with the indicated
* alignment and the indicated horizontal and vertical gaps and not filled
* with <code>Container</code> horizontally.
* <p>
* The value of the alignment argument must be one of
* <code>FlowLayout.TOP</code>, <code>FlowLayout.BOTTOM</code>,
* <code>FlowLayout.CENTER</code>.
*
* @param align
* the alignment value
* @param hgap
* the horizontal gap between columns and between the columns and
* the borders of the <code>Container</code>
* @param vgap
* the vertical gap between components and between the components
* and the borders of the <code>Container</code>
*/
public VerticalFlowLayout(int align, int hgap, int vgap) {
this(align, hgap, vgap, false);
}
/**
* Constructs a new <code>VerticalFlowLayout</code> with the indicated
* alignment and the indicated horizontal and vertical gaps and the
* indicated filled with <code>Container</code> horizontally.
* <p>
* The value of the alignment argument must be one of
* <code>FlowLayout.TOP</code>, <code>FlowLayout.BOTTOM</code>,
* <code>FlowLayout.CENTER</code>.
*
* @param align
* the alignment value
* @param hgap
* the horizontal gap between columns and between the columns and
* the borders of the <code>Container</code>
* @param vgap
* the vertical gap between components and between the components
* and the borders of the <code>Container</code>
* @param hfill
* the horizontal filling of components in the
* <code>Container</code>
*/
public VerticalFlowLayout(int align, int hgap, int vgap, boolean hfill) {
this.align = align;
this.hgap = hgap;
this.vgap = vgap;
this.hfill = hfill;
}
/**
* Gets the alignment for this layout. Possible values are
* <code>FlowLayout.TOP</code>, <code>FlowLayout.BOTTOM</code>,
* <code>FlowLayout.CENTER</code>.
*
* @return the alignment value for this layout
* @see #setAlignment(int)
*/
public int getAlignment() {
return align;
}
/**
* Sets the alignment for this layout. Possible values are
* <ul>
* <li><code>FlowLayout.TOP</code>
* <li><code>FlowLayout.BOTTOM</code>
* <li><code>FlowLayout.CENTER</code>
* </ul>
*
* @param align
* one of the alignment values shown above
* @see #getAlignment()
*/
public void setAlignment(int align) {
this.align = align;
}
/**
* Gets the horizontal gap between columns and between the columns and the
* borders of the <code>Container</code>
*
* @return the horizontal gap between columns and between the columns and
* the borders of the <code>Container</code>
* @see #setHgap(int)
*/
public int getHgap() {
return hgap;
}
/**
* Sets the horizontal gap between columns and between the columns and the
* borders of the <code>Container</code>.
*
* @param hgap
* the horizontal gap between columns and between the columns and
* the borders of the <code>Container</code>
* @see #getHgap()
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
/**
* Gets the vertical gap between components and between the components and
* the borders of the <code>Container</code>.
*
* @return the vertical gap between components and between the components
* and the borders of the <code>Container</code>
* @see #setVgap(int)
*/
public int getVgap() {
return vgap;
}
/**
* Sets the vertical gap between components and between the components and
* the borders of the <code>Container</code>.
*
* @param vgap
* the vertical gap between components and between the components
* and the borders of the <code>Container</code>
* @see #getVgap()
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
/**
* Gets the horizontal filling of components in the
* <code>Container</code>.The default is false.
*
* @return the horizontal filling of components in the
* <code>Container</code>
* @see #setHfill(boolean)
*/
public boolean isHfill() {
return hfill;
}
/**
* Sets the horizontal filling of components in the
* <code>Container</code>.The default is false.
*
* @param hfill
* the horizontal filling of components in the
* <code>Container</code>
* @see #isHfill()
*/
public void setHfill(boolean hfill) {
this.hfill = hfill;
}
/**
* Adds the specified component to the layout. Not used by this class.
*
* @param name
* the name of the component
* @param comp
* the component to be added
*/
@Override
public void addLayoutComponent(String name, Component comp) {
}
/**
* Removes the specified component from the layout. Not used by this class.
*
* @param comp
* the component to remove
*/
@Override
public void removeLayoutComponent(Component comp) {
}
/**
* Returns the preferred dimensions for this layout given the <i>visible</i>
* components in the specified target container.
*
* @param target
* the container that needs to be layout
* @return the preferred dimensions to layout the subcomponents of the
* specified container
* @see #minimumLayoutSize(Container)
*/
@Override
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.width = Math.max(dim.width, d.width);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.height += vgap;
}
dim.height += d.height;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap * 2;
dim.height += insets.top + insets.bottom + vgap * 2;
return dim;
}
}
/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
*
* @param target
* the container that needs to be layout
* @return the minimum dimensions to layout the sub components of the
* specified container
* @see #preferredLayoutSize(Container)
*/
@Override
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getMinimumSize();
dim.width = Math.max(dim.width, d.width);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.height += vgap;
}
dim.height += d.height;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap * 2;
dim.height += insets.top + insets.bottom + vgap * 2;
return dim;
}
}
/**
* Layout the container. This method lets each <i>visible</i> component take
* its preferred size by reshaping the components in the target container in
* order to satisfy the alignment of this <code>VerticalFlowLayout</code>
* object.
*
* @param target
* the specified component being layout
*/
@Override
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int maxwidth = target.getWidth() - (insets.left + insets.right + hgap * 2);
int maxheight = target.getSize().height - (insets.top + insets.bottom + vgap * 2);
int nmembers = target.getComponentCount();
int x = insets.left + hgap, y = 0;
int colw = 0, start = 0;
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
if (hfill) {
d.width = maxwidth;
}
m.setSize(d.width, d.height);
if ((y == 0) || ((y + d.height) <= maxheight)) {
if (y > 0) {
y += vgap;
}
y += d.height;
colw = Math.max(colw, d.width);
} else {
colw = moveComponents(target, x, insets.top + vgap, colw, maxheight - y, start, i);
y = d.height;
x += hgap + colw;
colw = d.width;
start = i;
}
}
}
moveComponents(target, x, insets.top + vgap, colw, maxheight - y, start, nmembers);
}
}
/**
* Centers the elements in the specified column, if there is any slack.
*
* @param target
* the component which needs to be moved
* @param x
* the x coordinate
* @param y
* the y coordinate
* @param width
* the width dimensions
* @param height
* the height dimensions
* @param colStart
* the beginning of the row
* @param colEnd
* the the ending of the row
* @return actual column width
*/
private int moveComponents(Container target, int x, int y, int width, int height, int colStart, int colEnd) {
switch (align) {
case TOP:
y += 0;
break;
case CENTER:
y += height / 2;
break;
case BOTTOM:
y += height;
break;
}
for (int i = colStart; i < colEnd; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
int cx = x + (width - m.getWidth()) / 2;
m.setLocation(cx, y);
y += m.getHeight() + vgap;
}
}
return width;
}
/**
* Returns a string representation of this <code>VerticalFlowLayout</code>
* object and its values.
*
* @return a string representation of this layout
*/
public String toString() {
String str = "";
switch (align) {
case TOP:
str = ",align=top";
break;
case CENTER:
str = ",align=center";
break;
case BOTTOM:
str = ",align=bottom";
break;
}
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + ",hfill=" + hfill + str + "]";
}
}

24
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/AbsoluteType.java

@ -0,0 +1,24 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import com.tptj.tool.hg.fineui.swing.element.layout.impl.AbsoluteLayout;
import javax.swing.*;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class AbsoluteType extends AbstractLayoutType {
@Override
public LayoutManager init() {
return new AbsoluteLayout(element);
}
@Override
public void layout(Element child, int idx) {
JComponent childComponent = child.getWrapper();
element.getComponent().add(childComponent);
}
}

21
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/AbstractLayoutType.java

@ -0,0 +1,21 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public abstract class AbstractLayoutType implements LayoutType {
protected Element element;
@Override
public void setElement(Element element) {
this.element = element;
}
}

34
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/CenterAdaptType.java

@ -0,0 +1,34 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import javax.swing.*;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class CenterAdaptType extends AbstractLayoutType {
@Override
public LayoutManager init() {
return new BoxLayout( element.getComponent(), BoxLayout.X_AXIS);
}
@Override
public void layout(Element child,int idx ) {
JComponent component = element.getComponent();
Box box = new Box(BoxLayout.Y_AXIS);
box.add(Box.createVerticalGlue());
box.add( child.getWrapper() );
box.add(Box.createVerticalGlue());
if (idx == 0) {
component.add(Box.createHorizontalGlue());
}
component.add(box);
if ( idx == element.children().size() - 1) {
component.add(Box.createHorizontalGlue());
}
}
}

28
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/HorizontalAdaptType.java

@ -0,0 +1,28 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import com.tptj.tool.hg.fineui.swing.element.VerticalFlowLayout;
import javax.swing.*;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class HorizontalAdaptType extends AbstractLayoutType{
@Override
public LayoutManager init() {
return new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true);
}
@Override
public void layout(Element child, int idx) {
Box box = new Box(BoxLayout.X_AXIS);
box.add(Box.createHorizontalGlue());
box.add( child.getWrapper() );
box.add(Box.createHorizontalGlue());
element.getComponent().add(box);
}
}

21
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/HorizontalType.java

@ -0,0 +1,21 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import javax.swing.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class HorizontalType extends CenterAdaptType{
@Override
public void layout(Element child, int idx) {
Box box = new Box(BoxLayout.Y_AXIS);
box.add(child.getWrapper());
box.add(Box.createVerticalGlue());
element.getComponent().add(box);
}
}

52
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/LayoutBuilder.java

@ -0,0 +1,52 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.fr.log.FineLoggerFactory;
import com.tptj.tool.hg.fineui.swing.element.Element;
import java.util.HashMap;
import java.util.Map;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class LayoutBuilder {
public static final String ABSOLUTE = "absolute";
public static final String CENTER_ADAPT = "center_adapt";
public static final String VERTICAL = "vertical";
public static final String VERTICAL_ADAPT = "vertical_adapt";
public static final String HORIZONTAL = "horizontal";
public static final String HORIZONTAL_ADAPT = "horizontal_adapt";
private LayoutBuilder(){
}
private static final Map<String,Class<? extends LayoutType>> types = new HashMap<String,Class<? extends LayoutType>>();
static{
types.put(ABSOLUTE,AbsoluteType.class);
types.put(CENTER_ADAPT,CenterAdaptType.class);
types.put(VERTICAL,VerticalType.class);
types.put(VERTICAL_ADAPT,VerticalAdaptType.class);
types.put(HORIZONTAL,HorizontalType.class);
types.put(HORIZONTAL_ADAPT,HorizontalAdaptType.class);
}
public static LayoutType layout(String type,Element element){
Class<? extends LayoutType> layout_type = types.get(type);
if( null == layout_type ){
FineLoggerFactory.getLogger().error("不支持的布局:{}",type);
layout_type = AbsoluteType.class;
}
try{
LayoutType layout = layout_type.newInstance();
layout.setElement(element);
return layout;
}catch(Exception e){
FineLoggerFactory.getLogger().error(e,"布局失败{},{}",type,e.getMessage());
}
AbsoluteType dft = new AbsoluteType();
dft.setElement(element);
return dft;
}
}

19
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/LayoutType.java

@ -0,0 +1,19 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public interface LayoutType {
LayoutManager init();
void layout( Element child,int idx );
void setElement( Element element );
}

21
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/VerticalAdaptType.java

@ -0,0 +1,21 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import javax.swing.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class VerticalAdaptType extends CenterAdaptType {
@Override
public void layout(Element child, int idx ) {
Box box = new Box(BoxLayout.Y_AXIS);
box.add(Box.createVerticalGlue());
box.add( child.getWrapper() );
box.add(Box.createVerticalGlue());
element.getComponent().add(box);
}
}

23
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/VerticalType.java

@ -0,0 +1,23 @@
package com.tptj.tool.hg.fineui.swing.element.layout;
import com.tptj.tool.hg.fineui.swing.element.Element;
import com.tptj.tool.hg.fineui.swing.element.VerticalFlowLayout;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class VerticalType extends AbstractLayoutType{
@Override
public LayoutManager init() {
return new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true);
}
@Override
public void layout(Element child, int idx) {
element.getComponent().add( child.getWrapper() );
}
}

52
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/impl/AbsoluteLayout.java

@ -0,0 +1,52 @@
package com.tptj.tool.hg.fineui.swing.element.layout.impl;
import com.tptj.tool.hg.fineui.swing.element.Element;
import java.awt.*;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public class AbsoluteLayout extends BaseFineUILayout {
public AbsoluteLayout(Element element) {
super(element);
}
@Override
protected Rectangle getFineUIRect(Element child, int width, int height) {
Dimension size = child.getWrapper().getPreferredSize();
int w = child.getRectStyleAttr("width",width,NOT_EXIST);
int h = child.getRectStyleAttr("height",height, NOT_EXIST);
int l = child.getRectStyleAttr("left",width, NOT_EXIST);
int r = child.getRectStyleAttr("right",width, NOT_EXIST);
int t = child.getRectStyleAttr("top",height, NOT_EXIST);
int b = child.getRectStyleAttr("bottom",height, NOT_EXIST);
Rectangle rt = new Rectangle(l,t,w,h);
if( w == NOT_EXIST ){
if( l != NOT_EXIST && r != NOT_EXIST ){
rt.width = width - l - r;
}else{
rt.width = size.width;
}
}
if( h == NOT_EXIST ){
if( t != NOT_EXIST && b != NOT_EXIST){
rt.height = height - t - b;
}else{
rt.height = size.height;
}
}
if( l == NOT_EXIST && r != NOT_EXIST ){
rt.x = width - rt.width - r;
}
if( t == NOT_EXIST && b != NOT_EXIST){
rt.y = height - rt.height - b;
}
//内外边距的计算可以在这里继续
return rt;
}
}

95
src/main/java/com/tptj/tool/hg/fineui/swing/element/layout/impl/BaseFineUILayout.java

@ -0,0 +1,95 @@
package com.tptj.tool.hg.fineui.swing.element.layout.impl;
import com.tptj.tool.hg.fineui.swing.element.AbstractElement;
import com.tptj.tool.hg.fineui.swing.element.Element;
import java.awt.*;
import java.util.List;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
**/
public abstract class BaseFineUILayout implements LayoutManager2 {
public static final int NOT_EXIST = -99999;
protected Element element;
public BaseFineUILayout(Element element){
this.element = element;
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
//不需要了
}
@Override
public Dimension maximumLayoutSize(Container target) {
return null;
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0;
}
@Override
public void invalidateLayout(Container target) {
System.out.println("");
}
@Override
public void addLayoutComponent(String name, Component comp) {
//不需要了
}
@Override
public void removeLayoutComponent(Component comp) {
//暂时不需要了
}
@Override
public Dimension preferredLayoutSize(Container parent) {
List<AbstractElement> children = element.children();
int p_width = 0;
int p_height = 0;
int width = parent.getParent().getWidth();
int height = parent.getParent().getHeight();
for( Element child : children ){
Rectangle rect = getFineUIRect(child, width, height);
if( rect.x + rect.width > p_width ){
p_width = rect.x + rect.width;
}
if( rect.y + rect.height > p_height ){
p_height = rect.y + rect.height;
}
}
return new Dimension(p_width, p_height);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
List<AbstractElement> children = element.children();
for( Element child : children ){
Rectangle rect = getFineUIRect(child, width, height);
child.getComponent().setBounds(rect.x,rect.y,rect.width,rect.height);
}
}
protected abstract Rectangle getFineUIRect(Element child,int width,int height);
}

58
src/main/java/com/tptj/tool/hg/fineui/swing/stable/ColorUtils.java

@ -0,0 +1,58 @@
package com.tptj.tool.hg.fineui.swing.stable;
import com.fr.stable.StringUtils;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author 秃破天际
* @version 10.0
* Created by 秃破天际 on 2021/11/1
* 颜色转换工具
**/
public class ColorUtils {
private static final Map<String,Color> colors = new HashMap<String,Color>();
static{
colors.put("YELLOW",Color.YELLOW);
colors.put("BLACK",Color.BLACK);
colors.put("BLUE",Color.BLUE);
colors.put("CYAN",Color.CYAN);
colors.put("DARK_GRAY",Color.DARK_GRAY);
colors.put("GRAY",Color.GRAY);
colors.put("GREEN",Color.GREEN);
colors.put("LIGHT_GRAY",Color.LIGHT_GRAY);
colors.put("MAGENTA",Color.MAGENTA);
colors.put("ORANGE",Color.ORANGE);
colors.put("PINK",Color.PINK);
colors.put("RED",Color.RED);
colors.put("WHITE",Color.WHITE);
}
public static Color str2Color(String str) {
if(StringUtils.isEmpty(str) ){
return null;
}
str = str.toUpperCase().replaceAll(" ","");
if( str.startsWith("#") ){
str = str.substring(1);
if( str.length() < 5 ){
StringBuilder sb = new StringBuilder();
for( int i=0,len=str.length(); i<len; i++ ){
sb.append( str.charAt(i) ).append( str.charAt(i) );
}
str = sb.toString();
}
return new Color( Integer.parseInt(str,16),str.length() == 8 );
}else if( str.startsWith("RGB") ){
str = str.substring(4,str.length()-1);
String [] parts = str.split(",");
return new Color( Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]) );
}else if( str.startsWith("RGBA") ){
str = str.substring(5,str.length()-1);
String [] parts = str.split(",");
return new Color( Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]) , Integer.parseInt(parts[3]) );
}
return colors.get(str);
}
}

10
src/main/resources/com/fr/fineui/base/0.base.js

@ -0,0 +1,10 @@
BI.prepares.push(function () {
BI.Resizers = new BI.ResizeController();
BI.Layers = new BI.LayerController();
BI.Maskers = new BI.MaskersController();
BI.Bubbles = new BI.BubblesController();
BI.Tooltips = new BI.TooltipsController();
BI.Popovers = new BI.PopoverController();
BI.Broadcasts = new BI.BroadcastController();
BI.StyleLoaders = new BI.StyleLoaderManager();
});

152
src/main/resources/com/fr/fineui/base/1.pane.js

@ -0,0 +1,152 @@
/**
* 当没有元素时有提示信息的view
*
* Created by GUY on 2015/9/8.
* @class BI.Pane
* @extends BI.Widget
* @abstract
*/
BI.Pane = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Pane.superclass._defaultConfig.apply(this, arguments), {
_baseCls: "bi-pane",
tipText: BI.i18nText("BI-No_Selected_Item"),
loadingText: "",
loadingSize: "small",
overlap: true,
onLoaded: BI.emptyFn
});
},
_assertTip: function () {
var self = this, o = this.options;
if (!this._tipText) {
BI.createWidget({
type: "bi.absolute_center_adapt",
element: this,
items: [{
type: "bi.label",
ref: function (_ref) {
self._tipText = _ref;
},
cls: "bi-tips",
text: o.tipText,
height: 25
}]
});
}
},
loading: function () {
var self = this, o = this.options;
var isIE = BI.isIE();
var loadingAnimation = BI.createWidget({
type: "bi.horizontal",
cls: "bi-loading-widget" + (isIE ? " wave-loading hack" : ""),
height: this._getSize(60),
width: this._getSize(60),
hgap: this._getSize(10),
vgap: 2.5,
items: isIE ? [] : [{
type: "bi.layout",
cls: "animate-rect rect1",
height: this._getSize(50),
width: this._getSize(5)
}, {
type: "bi.layout",
cls: "animate-rect rect2",
height: this._getSize(50),
width: this._getSize(5)
}, {
type: "bi.layout",
cls: "animate-rect rect3",
height: this._getSize(50),
width: this._getSize(5)
}]
});
// pane在同步方式下由items决定tipText的显示与否
// loading的异步情况下由loaded后对面板的populate的时机决定
this.setTipVisible(false);
if (o.overlap === true) {
if (!BI.Layers.has(this.getName() + "-loading")) {
BI.createWidget({
type: "bi.center_adapt",
cls: "loading-container",
items: this._getLoadingTipItems(loadingAnimation),
element: BI.Layers.make(this.getName() + "-loading", this)
});
}
BI.Layers.show(self.getName() + "-loading");
} else if (BI.isNull(this._loading)) {
loadingAnimation.element.css("zIndex", 1);
BI.createWidget({
type: "bi.center_adapt",
element: this,
cls: "loading-container",
items: this._getLoadingTipItems(loadingAnimation)
});
}
self.fireEvent(BI.Pane.EVENT_LOADING);
this.element.addClass("loading-status");
},
_getSize: function (v) {
return Math.ceil(v / (this.options.loadingSize === "small" ? 2 : 1));
},
_getLoadingTipItems: function (loadingTip) {
var self = this, o = this.options;
var loadingTipItems = [{
type: "bi.horizontal_adapt",
items: [loadingTip]
}];
BI.isNotEmptyString(o.loadingText) && loadingTipItems.push({
type: "bi.text",
text: o.loadingText,
tgap: this._getSize(10)
});
return [{
type: "bi.vertical",
ref: function (_ref) {
self._loading = _ref;
},
items: loadingTipItems
}];
},
loaded: function () {
var self = this, o = this.options;
BI.Layers.remove(self.getName() + "-loading");
this._loading && this._loading.destroy();
o.onLoaded();
self.fireEvent(BI.Pane.EVENT_LOADED);
this.element.removeClass("loading-status");
},
check: function () {
this.setTipVisible(BI.isEmpty(this.options.items));
},
setTipVisible: function (b) {
if (b === true) {
this._assertTip();
this._tipText.setVisible(true);
} else {
this._tipText && this._tipText.setVisible(false);
}
},
setTipText: function (text) {
this._assertTip();
this._tipText.setText(text);
},
populate: function (items) {
this.options.items = items || [];
this.check();
}
});
BI.Pane.EVENT_LOADED = "EVENT_LOADED";
BI.Pane.EVENT_LOADING = "EVENT_LOADING";

38
src/main/resources/com/fr/fineui/base/collection/__test__/collection.test.js

@ -0,0 +1,38 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/17
*/
describe("CollectionTest", function () {
/**
* test_author_windy
*/
it("collection", function () {
var items = [];
var cellCount = 100;
for (var i = 0; i < cellCount; i++) {
items[i] = {
type: "bi.label",
text: i
};
}
var grid = BI.Test.createWidget({
type: "bi.collection_view",
width: 400,
height: 300,
items: items,
cellSizeAndPositionGetter: function (index) {
return {
x: index % 10 * 50,
y: Math.floor(index / 10) * 50,
width: 50,
height: 50
};
}
});
// TODO 列表展示类控件不知道该测什么,先标记一下
grid.destroy();
});
});

379
src/main/resources/com/fr/fineui/base/collection/collection.js

@ -0,0 +1,379 @@
/**
* CollectionView
*
* Created by GUY on 2016/1/15.
* @class BI.CollectionView
* @extends BI.Widget
*/
BI.CollectionView = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.CollectionView.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-collection",
// width: 400, //必设
// height: 300, //必设
overflowX: true,
overflowY: true,
cellSizeAndPositionGetter: BI.emptyFn,
horizontalOverscanSize: 0,
verticalOverscanSize: 0,
scrollLeft: 0,
scrollTop: 0,
items: []
});
},
render: function () {
var self = this, o = this.options;
this.renderedCells = [];
this.renderedKeys = [];
this.renderRange = {};
this._scrollLock = false;
this._debounceRelease = BI.debounce(function () {
self._scrollLock = false;
}, 1000 / 60);
this.container = BI._lazyCreateWidget({
type: "bi.absolute"
});
this.element.scroll(function () {
if (self._scrollLock === true) {
return;
}
o.scrollLeft = self.element.scrollLeft();
o.scrollTop = self.element.scrollTop();
self._calculateChildrenToRender();
self.fireEvent(BI.CollectionView.EVENT_SCROLL, {
scrollLeft: o.scrollLeft,
scrollTop: o.scrollTop
});
});
BI._lazyCreateWidget({
type: "bi.vertical",
element: this,
scrollable: o.overflowX === true && o.overflowY === true,
scrolly: o.overflowX === false && o.overflowY === true,
scrollx: o.overflowX === true && o.overflowY === false,
items: [this.container]
});
if (o.items.length > 0) {
this._calculateSizeAndPositionData();
this._populate();
}
},
// mounted之后绑定事件
mounted: function () {
var o = this.options;
if (o.scrollLeft !== 0 || o.scrollTop !== 0) {
this.element.scrollTop(o.scrollTop);
this.element.scrollLeft(o.scrollLeft);
}
},
_calculateSizeAndPositionData: function () {
var o = this.options;
var cellMetadata = [];
var sectionManager = new BI.SectionManager();
var height = 0;
var width = 0;
for (var index = 0, len = o.items.length; index < len; index++) {
var cellMetadatum = o.cellSizeAndPositionGetter(index);
if (cellMetadatum.height == null || isNaN(cellMetadatum.height) ||
cellMetadatum.width == null || isNaN(cellMetadatum.width) ||
cellMetadatum.x == null || isNaN(cellMetadatum.x) ||
cellMetadatum.y == null || isNaN(cellMetadatum.y)) {
throw Error();
}
height = Math.max(height, cellMetadatum.y + cellMetadatum.height);
width = Math.max(width, cellMetadatum.x + cellMetadatum.width);
cellMetadatum.index = index;
cellMetadata[index] = cellMetadatum;
sectionManager.registerCell(cellMetadatum, index);
}
this._cellMetadata = cellMetadata;
this._sectionManager = sectionManager;
this._height = height;
this._width = width;
},
_cellRenderers: function (height, width, x, y) {
this._lastRenderedCellIndices = this._sectionManager.getCellIndices(height, width, x, y);
return this._cellGroupRenderer();
},
_cellGroupRenderer: function () {
var self = this, o = this.options;
var rendered = [];
BI.each(this._lastRenderedCellIndices, function (i, index) {
var cellMetadata = self._sectionManager.getCellMetadata(index);
rendered.push(cellMetadata);
});
return rendered;
},
_calculateChildrenToRender: function () {
var self = this, o = this.options;
var scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft());
var scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop());
var left = Math.max(0, scrollLeft - o.horizontalOverscanSize);
var top = Math.max(0, scrollTop - o.verticalOverscanSize);
var right = Math.min(this._width, scrollLeft + o.width + o.horizontalOverscanSize);
var bottom = Math.min(this._height, scrollTop + o.height + o.verticalOverscanSize);
if (right > 0 && bottom > 0) {
// 如果滚动的区间并没有超出渲染的范围
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) {
return;
}
var childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top);
var renderedCells = [], renderedKeys = {}, renderedWidgets = {};
// 存储所有的left和top
var lefts = {}, tops = {};
for (var i = 0, len = childrenToDisplay.length; i < len; i++) {
var datum = childrenToDisplay[i];
lefts[datum.x] = datum.x;
lefts[datum.x + datum.width] = datum.x + datum.width;
tops[datum.y] = datum.y;
tops[datum.y + datum.height] = datum.y + datum.height;
}
lefts = BI.toArray(lefts);
tops = BI.toArray(tops);
var leftMap = BI.invert(lefts);
var topMap = BI.invert(tops);
// 存储上下左右四个边界
var leftBorder = {}, rightBorder = {}, topBorder = {}, bottomBorder = {};
var assertMinBorder = function (border, offset) {
if (border[offset] == null) {
border[offset] = Number.MAX_VALUE;
}
};
var assertMaxBorder = function (border, offset) {
if (border[offset] == null) {
border[offset] = 0;
}
};
for (var i = 0, len = childrenToDisplay.length; i < len; i++) {
var datum = childrenToDisplay[i];
var index = this.renderedKeys[datum.index] && this.renderedKeys[datum.index][1];
var child;
if (index >= 0) {
// if (datum.width !== this.renderedCells[index]._width) {
// this.renderedCells[index]._width = datum.width;
this.renderedCells[index].el.setWidth(datum.width);
// }
// if (datum.height !== this.renderedCells[index]._height) {
// this.renderedCells[index]._height = datum.height;
this.renderedCells[index].el.setHeight(datum.height);
// }
// if (this.renderedCells[index]._left !== datum.x) {
this.renderedCells[index].el.element.css("left", datum.x / BI.pixRatio + BI.pixUnit);
// }
// if (this.renderedCells[index]._top !== datum.y) {
this.renderedCells[index].el.element.css("top", datum.y / BI.pixRatio + BI.pixUnit);
// }
renderedCells.push(child = this.renderedCells[index]);
} else {
child = BI._lazyCreateWidget(BI.extend({
type: "bi.label",
width: datum.width,
height: datum.height
}, o.items[datum.index], {
cls: (o.items[datum.index].cls || "") + " collection-cell" + (datum.y === 0 ? " first-row" : "") + (datum.x === 0 ? " first-col" : ""),
_left: datum.x,
_top: datum.y
}));
renderedCells.push({
el: child,
left: datum.x,
top: datum.y,
_left: datum.x,
_top: datum.y,
// _width: datum.width,
// _height: datum.height
});
}
var startTopIndex = topMap[datum.y] | 0;
var endTopIndex = topMap[datum.y + datum.height] | 0;
for (var k = startTopIndex; k <= endTopIndex; k++) {
var t = tops[k];
assertMinBorder(leftBorder, t);
assertMaxBorder(rightBorder, t);
leftBorder[t] = Math.min(leftBorder[t], datum.x);
rightBorder[t] = Math.max(rightBorder[t], datum.x + datum.width);
}
var startLeftIndex = leftMap[datum.x] | 0;
var endLeftIndex = leftMap[datum.x + datum.width] | 0;
for (var k = startLeftIndex; k <= endLeftIndex; k++) {
var l = lefts[k];
assertMinBorder(topBorder, l);
assertMaxBorder(bottomBorder, l);
topBorder[l] = Math.min(topBorder[l], datum.y);
bottomBorder[l] = Math.max(bottomBorder[l], datum.y + datum.height);
}
renderedKeys[datum.index] = [datum.index, i];
renderedWidgets[i] = child;
}
// 已存在的, 需要添加的和需要删除的
var existSet = {}, addSet = {}, deleteArray = [];
BI.each(renderedKeys, function (i, key) {
if (self.renderedKeys[i]) {
existSet[i] = key;
} else {
addSet[i] = key;
}
});
BI.each(this.renderedKeys, function (i, key) {
if (existSet[i]) {
return;
}
if (addSet[i]) {
return;
}
deleteArray.push(key[1]);
});
BI.each(deleteArray, function (i, index) {
// 性能优化,不调用destroy方法防止触发destroy事件
self.renderedCells[index].el._destroy();
});
var addedItems = [];
BI.each(addSet, function (index, key) {
addedItems.push(renderedCells[key[1]]);
});
this.container.addItems(addedItems);
// 拦截父子级关系
this.container._children = renderedWidgets;
this.container.attr("items", renderedCells);
this.renderedCells = renderedCells;
this.renderedKeys = renderedKeys;
// Todo 左右比较特殊
var minX = BI.min(leftBorder);
var maxX = BI.max(rightBorder);
var minY = BI.max(topBorder);
var maxY = BI.min(bottomBorder);
this.renderRange = {minX: minX, minY: minY, maxX: maxX, maxY: maxY};
}
},
_getMaxScrollLeft: function () {
return Math.max(0, this._width - this.options.width + (this.options.overflowX ? BI.DOM.getScrollWidth() : 0));
},
_getMaxScrollTop: function () {
return Math.max(0, this._height - this.options.height + (this.options.overflowY ? BI.DOM.getScrollWidth() : 0));
},
_populate: function (items) {
var o = this.options;
this._reRange();
if (items && items !== this.options.items) {
this.options.items = items;
this._calculateSizeAndPositionData();
}
this.container.setWidth(this._width);
this.container.setHeight(this._height);
this._debounceRelease();
// 元素未挂载时不能设置scrollTop
try {
this.element.scrollTop(o.scrollTop);
this.element.scrollLeft(o.scrollLeft);
} catch (e) {
}
this._calculateChildrenToRender();
},
setScrollLeft: function (scrollLeft) {
if (this.options.scrollLeft === scrollLeft) {
return;
}
this._scrollLock = true;
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getMaxScrollLeft());
this._debounceRelease();
this.element.scrollLeft(this.options.scrollLeft);
this._calculateChildrenToRender();
},
setScrollTop: function (scrollTop) {
if (this.options.scrollTop === scrollTop) {
return;
}
this._scrollLock = true;
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop());
this._debounceRelease();
this.element.scrollTop(this.options.scrollTop);
this._calculateChildrenToRender();
},
setOverflowX: function (b) {
var self = this;
if (this.options.overflowX !== !!b) {
this.options.overflowX = !!b;
BI.nextTick(function () {
self.element.css({overflowX: b ? "auto" : "hidden"});
});
}
},
setOverflowY: function (b) {
var self = this;
if (this.options.overflowY !== !!b) {
this.options.overflowY = !!b;
BI.nextTick(function () {
self.element.css({overflowY: b ? "auto" : "hidden"});
});
}
},
getScrollLeft: function () {
return this.options.scrollLeft;
},
getScrollTop: function () {
return this.options.scrollTop;
},
getMaxScrollLeft: function () {
return this._getMaxScrollLeft();
},
getMaxScrollTop: function () {
return this._getMaxScrollTop();
},
// 重新计算children
_reRange: function () {
this.renderRange = {};
},
_clearChildren: function () {
this.container._children = {};
this.container.attr("items", []);
},
restore: function () {
BI.each(this.renderedCells, function (i, cell) {
cell.el._destroy();
});
this._clearChildren();
this.renderedCells = [];
this.renderedKeys = [];
this.renderRange = {};
this._scrollLock = false;
},
populate: function (items) {
if (items && items !== this.options.items) {
this.restore();
}
this._populate(items);
}
});
BI.CollectionView.EVENT_SCROLL = "EVENT_SCROLL";
BI.shortcut("bi.collection_view", BI.CollectionView);

585
src/main/resources/com/fr/fineui/base/combination/combo.js

@ -0,0 +1,585 @@
!(function () {
var needHideWhenAnotherComboOpen = {};
/**
* @class BI.Combo
* @extends BI.Widget
*/
BI.Combo = BI.inherit(BI.Widget, {
_defaultConfig: function () {
var conf = BI.Combo.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-combo" + (BI.isIE() ? " hack" : ""),
attributes: {
tabIndex: -1
},
trigger: "click", // click || hover || click-hover || ""
toggle: true,
direction: "bottom", // top||bottom||left||right||top,left||top,right||bottom,left||bottom,right||right,innerRight||right,innerLeft||innerRight||innerLeft
logic: {
dynamic: true
},
container: null, // popupview放置的容器,默认为this.element
isDefaultInit: false,
destroyWhenHide: false,
hideWhenBlur: true,
hideWhenAnotherComboOpen: false,
isNeedAdjustHeight: true, // 是否需要高度调整
isNeedAdjustWidth: true,
stopEvent: false,
stopPropagation: false,
adjustLength: 0, // 调整的距离
adjustXOffset: 0,
adjustYOffset: 0,
hideChecker: BI.emptyFn,
offsetStyle: "left", // left,right,center
el: {},
popup: {},
comboClass: "bi-combo-popup",
hoverClass: "bi-combo-hover",
belowMouse: false
});
},
render: function () {
var self = this, o = this.options;
this._initCombo();
this._initPullDownAction();
this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
if (self.isEnabled() && self.isValid()) {
if (type === BI.Events.EXPAND) {
self._popupView();
}
if (type === BI.Events.COLLAPSE) {
self._hideView();
}
if (type === BI.Events.EXPAND) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.fireEvent(BI.Combo.EVENT_EXPAND);
}
if (type === BI.Events.COLLAPSE) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.isViewVisible() && self.fireEvent(BI.Combo.EVENT_COLLAPSE);
}
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Combo.EVENT_TRIGGER_CHANGE, obj);
}
}
});
self.element.on("mouseenter." + self.getName(), function (e) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) {
self.element.addClass(o.hoverClass);
}
});
self.element.on("mouseleave." + self.getName(), function (e) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) {
self.element.removeClass(o.hoverClass);
}
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("vertical", BI.extend(o.logic, {
items: [
{ el: this.combo }
]
}))));
o.isDefaultInit && (this._assertPopupView());
BI.Resizers.add(this.getName(), BI.bind(function (e) {
// 如果resize对象是combo的子元素,则不应该收起,或交由hideChecker去处理
if (this.isViewVisible()) {
BI.isNotNull(e) ? this._hideIf(e) : this._hideView();
}
}, this));
},
_toggle: function (e) {
this._assertPopupViewRender();
if (this.popupView.isVisible()) {
this._hideView(e);
} else {
if (this.isEnabled()) {
this._popupView(e);
}
}
},
_initPullDownAction: function () {
var self = this, o = this.options;
var evs = (this.options.trigger || "").split(",");
var st = function (e) {
if (o.stopEvent) {
e.stopEvent();
}
if (o.stopPropagation) {
e.stopPropagation();
}
};
var enterPopup = false;
function hide(e) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid() && o.toggle === true) {
self._hideView(e);
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.combo);
self.fireEvent(BI.Combo.EVENT_COLLAPSE);
}
self.popupView && self.popupView.element.off("mouseenter." + self.getName()).off("mouseleave." + self.getName());
enterPopup = false;
}
BI.each(evs, function (i, ev) {
switch (ev) {
case "hover":
self.element.on("mouseenter." + self.getName(), function (e) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) {
self._popupView(e);
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo);
self.fireEvent(BI.Combo.EVENT_EXPAND);
}
});
self.element.on("mouseleave." + self.getName(), function (e) {
if (self.popupView) {
self.popupView.element.on("mouseenter." + self.getName(), function (e) {
enterPopup = true;
self.popupView.element.on("mouseleave." + self.getName(), function (e) {
hide(e);
});
self.popupView.element.off("mouseenter." + self.getName());
});
BI.defer(function () {
if (!enterPopup) {
hide(e);
}
}, 50);
}
});
break;
case "click":
var debounce = BI.debounce(function (e) {
if (self.combo.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) {
// if (!o.toggle && self.isViewVisible()) {
// return;
// }
o.toggle ? self._toggle(e) : self._popupView(e);
if (self.isViewVisible()) {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo);
self.fireEvent(BI.Combo.EVENT_EXPAND);
} else {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.combo);
self.fireEvent(BI.Combo.EVENT_COLLAPSE);
}
}
}
}, BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
self.element.off(ev + "." + self.getName()).on(ev + "." + self.getName(), function (e) {
debounce(e);
st(e);
});
break;
case "click-hover":
var debounce = BI.debounce(function (e) {
if (self.combo.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && self.isValid() && self.combo.isEnabled() && self.combo.isValid()) {
// if (self.isViewVisible()) {
// return;
// }
self._popupView(e);
if (self.isViewVisible()) {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.combo);
self.fireEvent(BI.Combo.EVENT_EXPAND);
}
}
}
}, BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
self.element.off("click." + self.getName()).on("click." + self.getName(), function (e) {
debounce(e);
st(e);
});
self.element.on("mouseleave." + self.getName(), function (e) {
if (self.popupView) {
self.popupView.element.on("mouseenter." + self.getName(), function (e) {
enterPopup = true;
self.popupView.element.on("mouseleave." + self.getName(), function (e) {
hide(e);
});
self.popupView.element.off("mouseenter." + self.getName());
});
BI.delay(function () {
if (!enterPopup) {
hide(e);
}
}, 50);
}
});
break;
}
});
},
_initCombo: function () {
this.combo = BI.createWidget(this.options.el, {
value: this.options.value
});
},
_assertPopupView: function () {
var self = this, o = this.options;
if (this.popupView == null) {
this.popupView = BI.createWidget(this.options.popup, {
type: "bi.popup_view",
value: o.value
}, this);
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
if (type === BI.Events.CLICK) {
self.combo.setValue(self.getValue());
self.fireEvent(BI.Combo.EVENT_CHANGE, value, obj);
}
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
this.popupView.setVisible(false);
BI.nextTick(function () {
self.fireEvent(BI.Combo.EVENT_AFTER_INIT);
});
}
},
_assertPopupViewRender: function () {
this._assertPopupView();
if (!this._rendered) {
BI.createWidget({
type: "bi.vertical",
scrolly: false,
element: this.options.container || this,
items: [
{ el: this.popupView }
]
});
this._rendered = true;
}
},
_hideIf: function (e, skipTriggerChecker) {
// if (this.element.__isMouseInBounds__(e) || (this.popupView && this.popupView.element.__isMouseInBounds__(e))) {
// return;
// }
// BI-10290 公式combo双击公式内容会收起
if (e && ((skipTriggerChecker !== true && this.element.find(e.target).length > 0)
|| (this.popupView && this.popupView.element.find(e.target).length > 0)
|| e.target.className === "CodeMirror-cursor" || BI.Widget._renderEngine.createElement(e.target).closest(".CodeMirror-hints").length > 0)) {// BI-9887 CodeMirror的公式弹框需要特殊处理下
var directions = this.options.direction.split(",");
if (BI.contains(directions, "innerLeft") || BI.contains(directions, "innerRight")) {
// popup可以出现在trigger内部的combo,滚动时不需要消失,而是调整位置
this.adjustWidth();
this.adjustHeight();
}
return;
}
var isHide = this.options.hideChecker.apply(this, [e]);
if (isHide === false) {
return;
}
this._hideView(e);
return true;
},
_hideView: function (e) {
var o = this.options;
this.fireEvent(BI.Combo.EVENT_BEFORE_HIDEVIEW);
if (this.options.destroyWhenHide === true) {
this.popupView && this.popupView.destroy();
this.popupView = null;
this._rendered = false;
} else {
this.popupView && this.popupView.invisible();
}
if (!e || !this.combo.element.__isMouseInBounds__(e)) {
this.element.removeClass(this.options.hoverClass);
// 应对bi-focus-shadow在收起时不失焦
this.element.blur();
}
this.element.removeClass(this.options.comboClass);
delete needHideWhenAnotherComboOpen[this.getName()];
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName());
o.hideWhenBlur && BI.Widget._renderEngine.createElement(window).unbind("blur." + this.getName());
this.fireEvent(BI.Combo.EVENT_AFTER_HIDEVIEW);
},
_popupView: function (e) {
var self = this, o = this.options;
this._assertPopupViewRender();
this.fireEvent(BI.Combo.EVENT_BEFORE_POPUPVIEW);
// popupVisible是为了获取其宽高, 放到可视范围之外以防止在IE下闪一下
this.popupView.css({ left: -999999999, top: -99999999 });
this.popupView.visible();
BI.each(needHideWhenAnotherComboOpen, function (i, combo) {
if (i !== self.getName()) {
if (combo && combo._hideIf(e, true) === true) {
delete needHideWhenAnotherComboOpen[i];
}
}
});
this.options.hideWhenAnotherComboOpen && (needHideWhenAnotherComboOpen[this.getName()] = this);
this.adjustWidth(e);
this.adjustHeight(e);
this.element.addClass(this.options.comboClass);
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + this.getName()).unbind("mousewheel." + this.getName());
o.hideWhenBlur && BI.Widget._renderEngine.createElement(window).unbind("blur." + this.getName());
BI.Widget._renderEngine.createElement(document).bind("mousedown." + this.getName(), BI.bind(this._hideIf, this)).bind("mousewheel." + this.getName(), BI.bind(this._hideIf, this));
o.hideWhenBlur && BI.Widget._renderEngine.createElement(window).bind("blur." + this.getName(), BI.bind(this._hideIf, this));
this.fireEvent(BI.Combo.EVENT_AFTER_POPUPVIEW);
},
adjustWidth: function (e) {
var o = this.options;
if (!this.popupView) {
return;
}
if (o.isNeedAdjustWidth === true) {
this.resetListWidth("");
var width = this.popupView.element.outerWidth();
var maxW = this.element.outerWidth() || o.width;
// BI-93885 最大列宽算法调整
if (maxW < 500) {
if (width >= 500) {
maxW = 500;
} else if(width > maxW) {
// 防止小数导致差那么一点
maxW = width + 1;
}
}
// if (width > maxW + 80) {
// maxW = maxW + 80;
// } else if (width > maxW) {
// maxW = width;
// }
this.resetListWidth(maxW < 100 ? 100 : maxW);
}
},
adjustHeight: function (e) {
var o = this.options, p = {};
if (!this.popupView) {
return;
}
var isVisible = this.popupView.isVisible();
this.popupView.visible();
var combo = (o.belowMouse && BI.isNotNull(e)) ? {
element: {
offset: function () {
return {
left: e.pageX,
top: e.pageY
};
},
bounds: function () {
// offset为其相对于父定位元素的偏移
return {
x: e.offsetX,
y: e.offsetY,
width: 0,
height: 24
};
},
outerWidth: function () {
return 0;
},
outerHeight: function () {
return 24;
}
}
} : this.combo;
switch (o.direction) {
case "bottom":
case "bottom,right":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["bottom", "top", "right", "left"], o.offsetStyle);
break;
case "top":
case "top,right":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["top", "bottom", "right", "left"], o.offsetStyle);
break;
case "left":
case "left,bottom":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "bottom", "top"], o.offsetStyle);
break;
case "right":
case "right,bottom":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "bottom", "top"], o.offsetStyle);
break;
case "top,left":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["top", "bottom", "left", "right"], o.offsetStyle);
break;
case "bottom,left":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight, ["bottom", "top", "left", "right"], o.offsetStyle);
break;
case "left,top":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["left", "right", "top", "bottom"], o.offsetStyle);
break;
case "right,top":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "top", "bottom"], o.offsetStyle);
break;
case "right,innerRight":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerRight", "innerLeft", "bottom", "top"], o.offsetStyle);
break;
case "right,innerLeft":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["right", "left", "innerLeft", "innerRight", "bottom", "top"], o.offsetStyle);
break;
case "innerRight":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["innerRight", "innerLeft", "right", "left", "bottom", "top"], o.offsetStyle);
break;
case "innerLeft":
p = BI.DOM.getComboPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength, o.adjustYOffset, o.isNeedAdjustHeight, ["innerLeft", "innerRight", "left", "right", "bottom", "top"], o.offsetStyle);
break;
case "top,custom":
case "custom,top":
p = BI.DOM.getTopAdaptPosition(combo, this.popupView, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight);
break;
case "custom,bottom":
case "bottom,custom":
p = BI.DOM.getBottomAdaptPosition(combo, this.popupView, o.adjustYOffset || o.adjustLength, o.isNeedAdjustHeight);
break;
case "left,custom":
case "custom,left":
p = BI.DOM.getLeftAdaptPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength);
delete p.top;
delete p.adaptHeight;
break;
case "custom,right":
case "right,custom":
p = BI.DOM.getRightAdaptPosition(combo, this.popupView, o.adjustXOffset || o.adjustLength);
delete p.top;
delete p.adaptHeight;
break;
}
if ("adaptHeight" in p) {
this.resetListHeight(p["adaptHeight"]);
}
if ("left" in p) {
this.popupView.element.css({
left: p.left
});
}
if ("top" in p) {
this.popupView.element.css({
top: p.top
});
}
this.position = p;
this.popupView.setVisible(isVisible);
},
resetListHeight: function (h) {
this._assertPopupView();
this.popupView.resetHeight && this.popupView.resetHeight(h);
},
resetListWidth: function (w) {
this._assertPopupView();
this.popupView.resetWidth && this.popupView.resetWidth(w);
},
populate: function (items) {
this._assertPopupView();
this.popupView.populate.apply(this.popupView, arguments);
this.combo.populate && this.combo.populate.apply(this.combo, arguments);
},
_setEnable: function (arg) {
BI.Combo.superclass._setEnable.apply(this, arguments);
if (arg === true) {
this.element.removeClass("base-disabled disabled");
} else if (arg === false) {
this.element.addClass("base-disabled disabled");
}
!arg && this.element.removeClass(this.options.hoverClass);
!arg && this.isViewVisible() && this._hideView();
},
setValue: function (v) {
this.combo.setValue(v);
if (BI.isNull(this.popupView)) {
this.options.popup.value = v;
} else {
this.popupView.setValue(v);
}
},
getValue: function () {
if (BI.isNull(this.popupView)) {
return this.options.popup.value;
} else {
return this.popupView.getValue();
}
},
isViewVisible: function () {
return this.isEnabled() && this.combo.isEnabled() && !!this.popupView && this.popupView.isVisible();
},
showView: function (e) {
// 减少popup 调整宽高的次数
if (this.isEnabled() && this.combo.isEnabled() && !this.isViewVisible()) {
this._popupView(e);
}
},
hideView: function (e) {
this._hideView(e);
},
getView: function () {
return this.popupView;
},
getPopupPosition: function () {
return this.position;
},
toggle: function () {
this._toggle();
},
destroyed: function () {
BI.Widget._renderEngine.createElement(document)
.unbind("click." + this.getName())
.unbind("mousedown." + this.getName())
.unbind("mousewheel." + this.getName())
.unbind("mouseenter." + this.getName())
.unbind("mousemove." + this.getName())
.unbind("mouseleave." + this.getName());
BI.Widget._renderEngine.createElement(window)
.unbind("blur." + this.getName());
BI.Resizers.remove(this.getName());
this.popupView && this.popupView._destroy();
delete needHideWhenAnotherComboOpen[this.getName()];
}
});
BI.Combo.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE";
BI.Combo.EVENT_CHANGE = "EVENT_CHANGE";
BI.Combo.EVENT_EXPAND = "EVENT_EXPAND";
BI.Combo.EVENT_COLLAPSE = "EVENT_COLLAPSE";
BI.Combo.EVENT_AFTER_INIT = "EVENT_AFTER_INIT";
BI.Combo.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW";
BI.Combo.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW";
BI.Combo.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW";
BI.Combo.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW";
BI.shortcut("bi.combo", BI.Combo);
}());

281
src/main/resources/com/fr/fineui/base/combination/expander.js

@ -0,0 +1,281 @@
/**
*
* 某个可以展开的节点
*
* Created by GUY on 2015/9/10.
* @class BI.Expander
* @extends BI.Widget
*/
BI.Expander = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Expander.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-expander",
trigger: "click",
toggle: true,
// direction: "bottom", //top,bottom四个方向
isDefaultInit: false, // 是否默认初始化子节点
el: {},
popup: {},
expanderClass: "bi-expander-popup",
hoverClass: "bi-expander-hover"
});
},
render: function () {
var self = this, o = this.options;
this._expanded = !!o.el.open;
this._initExpander();
this._initPullDownAction();
this.expander.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
if (self.isEnabled() && self.isValid()) {
if (type === BI.Events.EXPAND) {
self._popupView();
}
if (type === BI.Events.COLLAPSE) {
self._hideView();
}
if (type === BI.Events.EXPAND) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.fireEvent(BI.Expander.EVENT_EXPAND);
}
if (type === BI.Events.COLLAPSE) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.isViewVisible() && self.fireEvent(BI.Expander.EVENT_COLLAPSE);
}
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Expander.EVENT_TRIGGER_CHANGE, value, obj);
}
}
});
this.element.hover(function () {
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) {
self.element.addClass(o.hoverClass);
}
}, function () {
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) {
self.element.removeClass(o.hoverClass);
}
});
BI.createWidget({
type: "bi.vertical",
scrolly: false,
element: this,
items: [
{el: this.expander}
]
});
o.isDefaultInit && this._assertPopupView();
if (this.expander.isOpened() === true) {
this._popupView();
}
},
_toggle: function () {
this._assertPopupViewRender();
if (this.popupView.isVisible()) {
this._hideView();
} else {
if (this.isEnabled()) {
this._popupView();
}
}
},
_initPullDownAction: function () {
var self = this, o = this.options;
var evs = this.options.trigger.split(",");
BI.each(evs, function (i, e) {
switch (e) {
case "hover":
self.element[e](function (e) {
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) {
self._popupView();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.expander);
self.fireEvent(BI.Expander.EVENT_EXPAND);
}
}, function () {
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid() && o.toggle) {
self._hideView();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.expander);
self.fireEvent(BI.Expander.EVENT_COLLAPSE);
}
});
break;
case "click":
if (e) {
self.element.off(e + "." + self.getName()).on(e + "." + self.getName(), BI.debounce(function (e) {
if (self.expander.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && self.isValid() && self.expander.isEnabled() && self.expander.isValid()) {
o.toggle ? self._toggle() : self._popupView();
if (self.isExpanded()) {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.expander);
self.fireEvent(BI.Expander.EVENT_EXPAND);
} else {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.expander);
self.fireEvent(BI.Expander.EVENT_COLLAPSE);
}
}
}
}, BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
}));
}
break;
}
});
},
_initExpander: function () {
this.expander = BI.createWidget(this.options.el);
},
_assertPopupView: function () {
var self = this, o = this.options;
if (this.popupView == null) {
this.popupView = BI.createWidget(this.options.popup, {
type: "bi.button_group",
cls: "expander-popup",
layouts: [{
type: "bi.vertical",
hgap: 0,
vgap: 0
}],
value: o.value
}, this);
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
// self.setValue(self.getValue());
self.fireEvent(BI.Expander.EVENT_CHANGE, value, obj);
}
});
this.popupView.setVisible(this.isExpanded());
BI.nextTick(function () {
self.fireEvent(BI.Expander.EVENT_AFTER_INIT);
});
}
},
_assertPopupViewRender: function () {
this._assertPopupView();
if (!this._rendered) {
BI.createWidget({
type: "bi.vertical",
scrolly: false,
element: this,
items: [
{el: this.popupView}
]
});
this._rendered = true;
}
},
_hideView: function () {
this.fireEvent(BI.Expander.EVENT_BEFORE_HIDEVIEW);
this._expanded = false;
this.expander.setOpened(false);
this.popupView && this.popupView.invisible();
this.element.removeClass(this.options.expanderClass);
this.fireEvent(BI.Expander.EVENT_AFTER_HIDEVIEW);
},
_popupView: function () {
this._assertPopupViewRender();
this.fireEvent(BI.Expander.EVENT_BEFORE_POPUPVIEW);
this._expanded = true;
this.expander.setOpened(true);
this.popupView.visible();
this.element.addClass(this.options.expanderClass);
this.fireEvent(BI.Expander.EVENT_AFTER_POPUPVIEW);
},
populate: function (items) {
// this._assertPopupView();
this.popupView && this.popupView.populate.apply(this.popupView, arguments);
this.expander.populate && this.expander.populate.apply(this.expander, arguments);
},
_setEnable: function (arg) {
BI.Expander.superclass._setEnable.apply(this, arguments);
!arg && this.element.removeClass(this.options.hoverClass);
!arg && this.isViewVisible() && this._hideView();
},
setValue: function (v) {
this.expander.setValue(v);
if (BI.isNull(this.popupView)) {
this.options.popup.value = v;
} else {
this.popupView.setValue(v);
}
},
getValue: function () {
if (BI.isNull(this.popupView)) {
return this.options.popup.value;
} else {
return this.popupView.getValue();
}
},
isViewVisible: function () {
return this.isEnabled() && this.expander.isEnabled() && !!this.popupView && this.popupView.isVisible();
},
isExpanded: function () {
return this._expanded;
},
showView: function () {
if (this.isEnabled() && this.expander.isEnabled()) {
this._popupView();
}
},
hideView: function () {
this._hideView();
},
getView: function () {
return this.popupView;
},
getAllLeaves: function () {
return this.popupView && this.popupView.getAllLeaves();
},
getNodeById: function (id) {
if (this.expander.options.id === id) {
return this.expander;
}
return this.popupView && this.popupView.getNodeById(id);
},
getNodeByValue: function (value) {
if (this.expander.getValue() === value) {
return this.expander;
}
return this.popupView && this.popupView.getNodeByValue(value);
},
destroy: function () {
BI.Expander.superclass.destroy.apply(this, arguments);
}
});
BI.Expander.EVENT_EXPAND = "EVENT_EXPAND";
BI.Expander.EVENT_COLLAPSE = "EVENT_COLLAPSE";
BI.Expander.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE";
BI.Expander.EVENT_CHANGE = "EVENT_CHANGE";
BI.Expander.EVENT_AFTER_INIT = "EVENT_AFTER_INIT";
BI.Expander.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW";
BI.Expander.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW";
BI.Expander.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW";
BI.Expander.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW";
BI.shortcut("bi.expander", BI.Expander);

329
src/main/resources/com/fr/fineui/base/combination/group.button.js

@ -0,0 +1,329 @@
/**
* Created by GUY on 2015/6/26.
* @class BI.ButtonGroup
* @extends BI.Widget
*/
BI.ButtonGroup = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.ButtonGroup.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-button-group",
behaviors: {},
items: [],
value: "",
chooseType: BI.Selection.Single,
layouts: [{
type: "bi.center",
hgap: 0,
vgap: 0
}]
});
},
render: function () {
var o = this.options;
var behaviors = {};
BI.each(o.behaviors, function (key, rule) {
behaviors[key] = BI.BehaviorFactory.createBehavior(key, {
rule: rule
});
});
this.behaviors = behaviors;
this.populate(o.items);
if(BI.isKey(o.value) || BI.isNotEmptyArray(o.value)){
this.setValue(o.value);
}
},
_createBtns: function (items) {
var o = this.options;
return BI.createWidgets(BI.createItems(items, {
type: "bi.text_button"
}), this);
},
_btnsCreator: function (items) {
var self = this, args = Array.prototype.slice.call(arguments), o = this.options;
var buttons = this._createBtns(items);
args[0] = buttons;
BI.each(this.behaviors, function (i, behavior) {
behavior.doBehavior.apply(behavior, args);
});
BI.each(buttons, function (i, btn) {
btn.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
if (type === BI.Events.CLICK) {
switch (o.chooseType) {
case BI.ButtonGroup.CHOOSE_TYPE_SINGLE:
self.setValue(btn.getValue());
break;
case BI.ButtonGroup.CHOOSE_TYPE_NONE:
self.setValue([]);
break;
}
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.fireEvent(BI.ButtonGroup.EVENT_CHANGE, value, obj);
} else {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
}
});
btn.on(BI.Events.DESTROY, function () {
BI.remove(self.buttons, btn);
});
});
return buttons;
},
_packageBtns: function (btns) {
var o = this.options;
for (var i = o.layouts.length - 1; i > 0; i--) {
btns = BI.map(btns, function (k, it) {
return BI.extend({}, o.layouts[i], {
items: [
BI.extend({}, o.layouts[i].el, {
el: it
})
]
});
});
}
return btns;
},
_packageSimpleItems: function (btns) {
var o = this.options;
return BI.map(o.items, function (i, item) {
if (BI.stripEL(item) === item) {
return btns[i];
}
return BI.extend({}, item, {
el: btns[i]
});
});
},
_packageItems: function (items, packBtns) {
return BI.createItems(BI.makeArrayByArray(items, {}), BI.clone(packBtns));
},
_packageLayout: function (items) {
var o = this.options, layout = BI.deepClone(o.layouts[0]);
var lay = BI.formatEL(layout).el;
while (lay && lay.items && !BI.isEmpty(lay.items)) {
lay = BI.formatEL(lay.items[0]).el;
}
lay.items = items;
return layout;
},
// 如果是一个简单的layout
_isSimpleLayout: function () {
var o = this.options;
return o.layouts.length === 1 && !BI.isArray(o.items[0]);
},
doBehavior: function () {
var args = Array.prototype.slice.call(arguments);
args.unshift(this.buttons);
BI.each(this.behaviors, function (i, behavior) {
behavior.doBehavior.apply(behavior, args);
});
},
prependItems: function (items) {
var o = this.options;
var btns = this._btnsCreator.apply(this, arguments);
this.buttons = BI.concat(btns, this.buttons);
if (this._isSimpleLayout() && this.layouts && this.layouts.prependItems) {
this.layouts.prependItems(btns);
return;
}
items = this._packageItems(items, this._packageBtns(btns));
this.layouts.prependItems(this._packageLayout(items).items);
},
addItems: function (items) {
var o = this.options;
var btns = this._btnsCreator.apply(this, arguments);
this.buttons = BI.concat(this.buttons, btns);
// 如果是一个简单的layout
if (this._isSimpleLayout() && this.layouts && this.layouts.addItems) {
this.layouts.addItems(btns);
return;
}
items = this._packageItems(items, this._packageBtns(btns));
this.layouts.addItems(this._packageLayout(items).items);
},
removeItemAt: function (indexes) {
BI.removeAt(this.buttons, indexes);
this.layouts.removeItemAt(indexes);
},
removeItems: function (values) {
values = BI.isArray(values) ? values : [values];
var deleted = [];
BI.each(this.buttons, function (i, button) {
if (BI.deepContains(values, button.getValue())) {
deleted.push(i);
}
});
BI.removeAt(this.buttons, deleted);
this.layouts.removeItemAt(deleted);
},
populate: function (items) {
items = items || [];
this.empty();
this.options.items = items;
this.buttons = this._btnsCreator.apply(this, arguments);
if (this._isSimpleLayout()) {
items = this._packageSimpleItems(this.buttons);
} else {
items = this._packageItems(items, this._packageBtns(this.buttons));
}
this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items)));
},
setNotSelectedValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (BI.deepContains(v, item.getValue())) {
item.setSelected && item.setSelected(false);
} else {
item.setSelected && item.setSelected(true);
}
});
},
setEnabledValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (BI.deepContains(v, item.getValue())) {
item.setEnable(true);
} else {
item.setEnable(false);
}
});
},
setValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (BI.deepContains(v, item.getValue())) {
item.setSelected && item.setSelected(true);
} else {
item.setSelected && item.setSelected(false);
}
});
},
getNotSelectedValue: function () {
var v = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !(item.isSelected && item.isSelected())) {
v.push(item.getValue());
}
});
return v;
},
getValue: function () {
var v = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && item.isSelected && item.isSelected()) {
v.push(item.getValue());
}
});
return v;
},
getAllButtons: function () {
return this.buttons;
},
getAllLeaves: function () {
return this.buttons;
},
getSelectedButtons: function () {
var btns = [];
BI.each(this.buttons, function (i, item) {
if (item.isSelected && item.isSelected()) {
btns.push(item);
}
});
return btns;
},
getNotSelectedButtons: function () {
var btns = [];
BI.each(this.buttons, function (i, item) {
if (item.isSelected && !item.isSelected()) {
btns.push(item);
}
});
return btns;
},
getIndexByValue: function (value) {
var index = -1;
BI.any(this.buttons, function (i, item) {
if (item.isEnabled() && item.getValue() === value) {
index = i;
return true;
}
});
return index;
},
getNodeById: function (id) {
var node;
BI.any(this.buttons, function (i, item) {
if (item.isEnabled() && item.options.id === id) {
node = item;
return true;
}
});
return node;
},
getNodeByValue: function (value) {
var node;
BI.any(this.buttons, function (i, item) {
if (item.isEnabled() && item.getValue() === value) {
node = item;
return true;
}
});
return node;
},
empty: function () {
BI.ButtonGroup.superclass.empty.apply(this, arguments);
this.options.items = [];
},
destroy: function () {
BI.ButtonGroup.superclass.destroy.apply(this, arguments);
this.options.items = [];
}
});
BI.extend(BI.ButtonGroup, {
CHOOSE_TYPE_SINGLE: BI.Selection.Single,
CHOOSE_TYPE_MULTI: BI.Selection.Multi,
CHOOSE_TYPE_ALL: BI.Selection.All,
CHOOSE_TYPE_NONE: BI.Selection.None,
CHOOSE_TYPE_DEFAULT: BI.Selection.Default
});
BI.ButtonGroup.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.button_group", BI.ButtonGroup);

96
src/main/resources/com/fr/fineui/base/combination/group.combo.js

@ -0,0 +1,96 @@
/**
* Created by GUY on 2015/8/10.
*/
BI.ComboGroup = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.ComboGroup.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-combo-group bi-list-item",
// 以下这些属性对每一个combo都是公用的
trigger: "click,hover",
direction: "right",
adjustLength: 0,
isDefaultInit: false,
isNeedAdjustHeight: false,
isNeedAdjustWidth: false,
el: {type: "bi.text_button", text: "", value: ""},
children: [],
popup: {
el: {
type: "bi.button_tree",
chooseType: 0,
layouts: [{
type: "bi.vertical"
}]
}
}
});
},
render: function () {
this._populate(this.options.el);
},
_populate: function (item) {
var self = this, o = this.options;
var children = o.children;
if (BI.isEmpty(children)) {
throw new Error("ComboGroup构造错误");
}
BI.each(children, function (i, ch) {
var son = BI.formatEL(ch).el.children;
ch = BI.formatEL(ch).el;
if (!BI.isEmpty(son)) {
ch.el = BI.clone(ch);
ch.children = son;
ch.type = "bi.combo_group";
ch.action = o.action;
ch.height = o.height;
ch.direction = o.direction;
ch.isDefaultInit = o.isDefaultInit;
ch.isNeedAdjustHeight = o.isNeedAdjustHeight;
ch.isNeedAdjustWidth = o.isNeedAdjustWidth;
ch.adjustLength = o.adjustLength;
ch.popup = o.popup;
}
});
this.combo = BI.createWidget({
type: "bi.combo",
element: this,
container: o.container,
height: o.height,
trigger: o.trigger,
direction: o.direction,
isDefaultInit: o.isDefaultInit,
isNeedAdjustWidth: o.isNeedAdjustWidth,
isNeedAdjustHeight: o.isNeedAdjustHeight,
adjustLength: o.adjustLength,
el: item,
popup: BI.extend({}, o.popup, {
el: BI.extend({
items: children
}, o.popup.el)
})
});
this.combo.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.ComboGroup.EVENT_CHANGE, obj);
}
});
},
getValue: function () {
return this.combo.getValue();
},
setValue: function (v) {
this.combo.setValue(v);
}
});
BI.ComboGroup.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.combo_group", BI.ComboGroup);

116
src/main/resources/com/fr/fineui/base/combination/group.virtual.js

@ -0,0 +1,116 @@
BI.VirtualGroup = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.VirtualGroup.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-virtual-group",
items: [],
layouts: [{
type: "bi.center",
hgap: 0,
vgap: 0
}]
});
},
render: function () {
var o = this.options;
this.populate(o.items);
if (BI.isKey(o.value)) {
this.setValue(o.value);
}
},
_packageBtns: function (items) {
var o = this.options;
var map = this.buttonMap = {};
for (var i = o.layouts.length - 1; i > 0; i--) {
items = BI.map(items, function (k, it) {
var el = BI.stripEL(it);
return BI.extend({}, o.layouts[i], {
items: [
BI.extend({}, o.layouts[i].el, {
el: BI.extend({
ref: function (_ref) {
if (BI.isKey(map[el.value])) {
map[el.value] = _ref;
}
}
}, el)
})
]
});
});
}
return items;
},
_packageLayout: function (items) {
var o = this.options, layout = BI.deepClone(o.layouts[0]);
var lay = BI.formatEL(layout).el;
while (lay && lay.items && !BI.isEmpty(lay.items)) {
lay = BI.formatEL(lay.items[0]).el;
}
lay.items = items;
return layout;
},
addItems: function (items) {
this.layouts.addItems(items);
},
prependItems: function (items) {
this.layouts.prependItems(items);
},
setValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttonMap, function (key, item) {
if (item) {
if (v.deepContains(key)) {
item.setSelected && item.setSelected(true);
} else {
item.setSelected && item.setSelected(false);
}
}
});
},
getNotSelectedValue: function () {
var v = [];
BI.each(this.buttonMap, function (i, item) {
if (item) {
if (item.isEnabled() && !(item.isSelected && item.isSelected())) {
v.push(item.getValue());
}
}
});
return v;
},
getValue: function () {
var v = [];
BI.each(this.buttonMap, function (i, item) {
if (item) {
if (item.isEnabled() && item.isSelected && item.isSelected()) {
v.push(item.getValue());
}
}
});
return v;
},
populate: function (items) {
var self = this;
items = items || [];
this.options.items = items;
items = this._packageBtns(items);
if (!this.layouts) {
this.layouts = BI.createWidget(BI.extend({element: this}, this._packageLayout(items)));
} else {
this.layouts.populate(items);
}
}
});
BI.VirtualGroup.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.virtual_group", BI.VirtualGroup);

259
src/main/resources/com/fr/fineui/base/combination/loader.js

@ -0,0 +1,259 @@
/**
* 加载控件
*
* Created by GUY on 2015/8/31.
* @class BI.Loader
* @extends BI.Widget
*/
BI.Loader = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Loader.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-loader",
direction: "top",
isDefaultInit: true, // 是否默认初始化数据
logic: {
dynamic: true,
scrolly: true
},
// 下面是button_group的属性
el: {
type: "bi.button_group"
},
items: [],
itemsCreator: BI.emptyFn,
onLoaded: BI.emptyFn,
// 下面是分页信息
count: false,
prev: false,
next: {},
hasPrev: BI.emptyFn,
hasNext: BI.emptyFn
});
},
_prevLoad: function () {
var self = this, o = this.options;
this.prev.setLoading();
o.itemsCreator.apply(this, [{times: --this.times}, function () {
self.prev.setLoaded();
self.prependItems.apply(self, arguments);
}]);
},
_nextLoad: function () {
var self = this, o = this.options;
this.next.setLoading();
o.itemsCreator.apply(this, [{times: ++this.times}, function () {
self.next.setLoaded();
self.addItems.apply(self, arguments);
}]);
},
render: function () {
var self = this, o = this.options;
if (o.itemsCreator === false) {
o.prev = false;
o.next = false;
}
if (o.prev !== false) {
this.prev = BI.createWidget(BI.extend({
type: "bi.loading_bar"
}, o.prev));
this.prev.on(BI.Controller.EVENT_CHANGE, function (type) {
if (type === BI.Events.CLICK) {
self._prevLoad();
}
});
}
this.button_group = BI.createWidget(o.el, {
type: "bi.button_group",
chooseType: 0,
items: o.items,
behaviors: {},
layouts: [{
type: "bi.vertical"
}],
value: o.value
});
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Loader.EVENT_CHANGE, obj);
}
});
if (o.next !== false) {
this.next = BI.createWidget(BI.extend({
type: "bi.loading_bar"
}, o.next));
this.next.on(BI.Controller.EVENT_CHANGE, function (type) {
if (type === BI.Events.CLICK) {
self._nextLoad();
}
});
}
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({
scrolly: true
}, o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.prev, this.button_group, this.next)
}))));
o.isDefaultInit && BI.isEmpty(o.items) && BI.nextTick(BI.bind(function () {
o.isDefaultInit && BI.isEmpty(o.items) && this._populate();
}, this));
if (BI.isNotEmptyArray(o.items)) {
this._populate(o.items);
}
},
hasPrev: function () {
var o = this.options;
if (BI.isNumber(o.count)) {
return this.count < o.count;
}
return !!o.hasPrev.apply(this, [{
times: this.times,
count: this.count
}]);
},
hasNext: function () {
var o = this.options;
if (BI.isNumber(o.count)) {
return this.count < o.count;
}
return !!o.hasNext.apply(this, [{
times: this.times,
count: this.count
}]);
},
prependItems: function (items) {
this.count += items.length;
if (this.next !== false) {
if (this.hasPrev()) {
this.options.items = this.options.items.concat(items);
this.prev.setLoaded();
} else {
this.prev.setEnd();
}
}
this.button_group.prependItems.apply(this.button_group, arguments);
},
addItems: function (items) {
this.count += items.length;
if (BI.isObject(this.next)) {
if (this.hasNext()) {
this.options.items = this.options.items.concat(items);
this.next.setLoaded();
} else {
this.next.setEnd();
}
}
this.button_group.addItems.apply(this.button_group, arguments);
},
_populate: function (items) {
var self = this, o = this.options;
if (arguments.length === 0 && (BI.isFunction(o.itemsCreator))) {
o.itemsCreator.apply(this, [{times: 1}, function () {
if (arguments.length === 0) {
throw new Error("参数不能为空");
}
self.populate.apply(self, arguments);
o.onLoaded();
}]);
return false;
}
this.options.items = items;
this.times = 1;
this.count = 0;
this.count += items.length;
if (BI.isObject(this.next)) {
if (this.hasNext()) {
this.next.setLoaded();
} else {
this.next.invisible();
}
}
if (BI.isObject(this.prev)) {
if (this.hasPrev()) {
this.prev.setLoaded();
} else {
this.prev.invisible();
}
}
return true;
},
populate: function () {
this._populate.apply(this, arguments) && this.button_group.populate.apply(this.button_group, arguments);
},
setNotSelectedValue: function () {
this.button_group.setNotSelectedValue.apply(this.button_group, arguments);
},
getNotSelectedValue: function () {
return this.button_group.getNotSelectedValue();
},
setValue: function () {
this.button_group.setValue.apply(this.button_group, arguments);
},
getValue: function () {
return this.button_group.getValue.apply(this.button_group, arguments);
},
getAllButtons: function () {
return this.button_group.getAllButtons();
},
getAllLeaves: function () {
return this.button_group.getAllLeaves();
},
getSelectedButtons: function () {
return this.button_group.getSelectedButtons();
},
getNotSelectedButtons: function () {
return this.button_group.getNotSelectedButtons();
},
getIndexByValue: function (value) {
return this.button_group.getIndexByValue(value);
},
getNodeById: function (id) {
return this.button_group.getNodeById(id);
},
getNodeByValue: function (value) {
return this.button_group.getNodeByValue(value);
},
empty: function () {
this.button_group.empty();
BI.each([this.prev, this.next], function (i, ob) {
ob && ob.setVisible(false);
});
},
destroy: function () {
BI.Loader.superclass.destroy.apply(this, arguments);
}
});
BI.Loader.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.loader", BI.Loader);

162
src/main/resources/com/fr/fineui/base/combination/navigation.js

@ -0,0 +1,162 @@
/**
* Created by GUY on 2015/6/26.
*/
BI.Navigation = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Navigation.superclass._defaultConfig.apply(this, arguments), {
direction: "bottom", // top, bottom, left, right, custom
logic: {
dynamic: false
},
single: false,
showIndex: false,
tab: false,
cardCreator: function (v) {
return BI.createWidget();
},
afterCardCreated: BI.emptyFn,
afterCardShow: BI.emptyFn
});
},
render: function () {
var self = this, o = this.options;
this.tab = BI.createWidget(this.options.tab, {type: "bi.button_group"});
this.cardMap = {};
this.showIndex = 0;
this.layout = BI.createWidget({
type: "bi.card"
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout)
}))));
new BI.ShowListener({
eventObj: this.tab,
cardLayout: this.layout,
cardNameCreator: function (v) {
return self.showIndex + v;
},
cardCreator: function (v) {
var card = o.cardCreator(v);
self.cardMap[v] = card;
return card;
},
afterCardCreated: BI.bind(this.afterCardCreated, this),
afterCardShow: BI.bind(this.afterCardShow, this)
});
},
created: function () {
var o = this.options;
if (o.showIndex !== false) {
this.setSelect(o.showIndex);
}
},
_deleteOtherCards: function (currCardName) {
var self = this, o = this.options;
if (o.single === true) {
BI.each(this.cardMap, function (name, card) {
if (name !== (currCardName + "")) {
self.layout.deleteCardByName(name);
delete self.cardMap[name];
}
});
}
},
afterCardCreated: function (v) {
var self = this;
this.cardMap[v].on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Navigation.EVENT_CHANGE, obj);
}
});
this.options.afterCardCreated.apply(this, arguments);
},
afterCardShow: function (v) {
this.showIndex = v;
this._deleteOtherCards(v);
this.options.afterCardShow.apply(this, arguments);
},
populate: function () {
var card = this.layout.getShowingCard();
if (card) {
return card.populate.apply(card, arguments);
}
},
_assertCard: function (v) {
if (!this.layout.isCardExisted(v)) {
var card = this.options.cardCreator(v);
this.cardMap[v] = card;
this.layout.addCardByName(v, card);
this.afterCardCreated(v);
}
},
setSelect: function (v) {
this._assertCard(v);
this.layout.showCardByName(v);
this._deleteOtherCards(v);
if (this.showIndex !== v) {
this.showIndex = v;
BI.nextTick(BI.bind(this.afterCardShow, this, v));
}
},
getSelect: function () {
return this.showIndex;
},
getSelectedCard: function () {
if (BI.isKey(this.showIndex)) {
return this.cardMap[this.showIndex];
}
},
getAllCard: function() {
return BI.values(this.cardMap);
},
/**
* @override
*/
setValue: function (v) {
var card = this.layout.getShowingCard();
if (card) {
card.setValue(v);
}
},
/**
* @override
*/
getValue: function () {
var card = this.layout.getShowingCard();
if (card) {
return card.getValue();
}
},
empty: function () {
this.layout.deleteAllCard();
this.cardMap = {};
},
destroy: function () {
BI.Navigation.superclass.destroy.apply(this, arguments);
}
});
BI.Navigation.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.navigation", BI.Navigation);

319
src/main/resources/com/fr/fineui/base/combination/searcher.js

@ -0,0 +1,319 @@
/**
* 搜索逻辑控件
*
* Created by GUY on 2015/9/28.
* @class BI.Searcher
* @extends BI.Widget
*/
BI.Searcher = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Searcher.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-searcher",
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
vgap: 0,
hgap: 0,
isDefaultInit: false,
isAutoSearch: true, // 是否自动搜索
isAutoSync: true, // 是否自动同步数据, 即是否保持搜索面板和adapter面板状态值的统一
chooseType: BI.ButtonGroup.CHOOSE_TYPE_SINGLE,
// isAutoSearch为false时启用
onSearch: function (op, callback) {
callback([]);
},
el: {
type: "bi.search_editor"
},
popup: {
type: "bi.searcher_view"
},
adapter: null,
masker: { // masker层
offset: {}
}
});
},
render: function () {
var self = this, o = this.options;
this.editor = BI.createWidget(o.el, {
type: "bi.search_editor"
});
BI.createWidget({
type: "bi.vertical",
element: this,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
vgap: o.vgap,
hgap: o.hgap,
items: [this.editor]
});
o.isDefaultInit && (this._assertPopupView());
var search = BI.debounce(BI.bind(this._search, this), BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
this.editor.on(BI.Controller.EVENT_CHANGE, function (type) {
switch (type) {
case BI.Events.STARTEDIT:
self._startSearch();
break;
case BI.Events.EMPTY:
self._stopSearch();
break;
case BI.Events.CHANGE:
search();
break;
case BI.Events.PAUSE:
if (BI.endWith(this.getValue(), BI.BlankSplitChar)) {
self._pauseSearch();
}
break;
}
});
},
_assertPopupView: function () {
var self = this, o = this.options;
if ((o.masker && !BI.Maskers.has(this.getName())) || (o.masker === false && !this.popupView)) {
this.popupView = BI.createWidget(o.popup, {
type: "bi.searcher_view",
chooseType: o.chooseType
});
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
if (o.isAutoSync) {
var values = o.adapter && o.adapter.getValue();
switch (o.chooseType) {
case BI.ButtonGroup.CHOOSE_TYPE_SINGLE:
o.adapter && o.adapter.setValue([obj.getValue()]);
break;
case BI.ButtonGroup.CHOOSE_TYPE_MULTI:
if (!obj.isSelected()) {
o.adapter && o.adapter.setValue(BI.deepWithout(values, obj.getValue()));
}
values.push(obj.getValue());
o.adapter && o.adapter.setValue(values);
break;
}
}
self.fireEvent(BI.Searcher.EVENT_CHANGE, value, obj);
}
});
BI.nextTick(function () {
self.fireEvent(BI.Searcher.EVENT_AFTER_INIT);
});
}
if (o.masker && !BI.Maskers.has(this.getName())) {
BI.Maskers.create(this.getName(), o.adapter, BI.extend({
container: this,
render: this.popupView
}, o.masker), this);
}
},
_startSearch: function () {
this._assertPopupView();
this._stop = false;
this._isSearching = true;
this.fireEvent(BI.Searcher.EVENT_START);
this.popupView.startSearch && this.popupView.startSearch();
// 搜索前先清空dom
// BI.Maskers.get(this.getName()).empty();
BI.nextTick(function (name) {
BI.Maskers.show(name);
}, this.getName());
},
_pauseSearch: function () {
var o = this.options, name = this.getName();
this._stop = true;
BI.nextTick(function (name) {
BI.Maskers.hide(name);
}, this.getName());
if (this._isSearching === true) {
this.popupView && this.popupView.pauseSearch && this.popupView.pauseSearch();
this.fireEvent(BI.Searcher.EVENT_PAUSE);
}
this._isSearching = false;
},
_stopSearch: function () {
var o = this.options, name = this.getName();
this._stop = true;
BI.Maskers.hide(name);
if (this._isSearching === true) {
this.popupView && this.popupView.stopSearch && this.popupView.stopSearch();
this.fireEvent(BI.Searcher.EVENT_STOP);
}
this._isSearching = false;
},
_search: function () {
var self = this, o = this.options, keyword = this.editor.getValue();
if (keyword === "" || this._stop) {
return;
}
if (o.isAutoSearch) {
var items = (o.adapter && ((o.adapter.getItems && o.adapter.getItems()) || o.adapter.attr("items"))) || [];
var finding = BI.Func.getSearchResult(items, keyword);
var match = finding.match, find = finding.find;
this.popupView.populate(find, match, keyword);
o.isAutoSync && o.adapter && o.adapter.getValue && this.popupView.setValue(o.adapter.getValue());
self.fireEvent(BI.Searcher.EVENT_SEARCHING);
return;
}
this.popupView.loading && this.popupView.loading();
o.onSearch({
times: 1,
keyword: keyword,
selectedValues: o.adapter && o.adapter.getValue()
}, function (searchResult, matchResult) {
if (!self._stop) {
var args = [].slice.call(arguments);
if (args.length > 0) {
args.push(keyword);
}
BI.Maskers.show(self.getName());
self.popupView.populate.apply(self.popupView, args);
o.isAutoSync && o.adapter && o.adapter.getValue && self.popupView.setValue(o.adapter.getValue());
self.popupView.loaded && self.popupView.loaded();
self.fireEvent(BI.Searcher.EVENT_SEARCHING);
}
});
},
_getLastSearchKeyword: function () {
if (this.isValid()) {
var res = this.editor.getValue().split(/\u200b\s\u200b/);
if (BI.isEmptyString(res[res.length - 1])) {
res = res.slice(0, res.length - 1);
}
return BI.isNull(res) ? "" : res[res.length - 1];
}
},
setAdapter: function (adapter) {
this.options.adapter = adapter;
BI.Maskers.remove(this.getName());
},
doSearch: function () {
if (this.isSearching()) {
this._search();
}
},
stopSearch: function () {
this._stopSearch();// 先停止搜索,然后再去设置editor为空
// important:停止搜索必须退出编辑状态,这里必须加上try(input框不显示时blur会抛异常)
try {
this.editor.blur();
} catch (e) {
if (!this.editor.blur) {
throw new Error("editor没有实现blur方法");
}
} finally {
this.editor.setValue("");
}
},
isSearching: function () {
return this._isSearching;
},
isViewVisible: function () {
return this.editor.isEnabled() && BI.Maskers.isVisible(this.getName());
},
getView: function () {
return this.popupView;
},
hasMatched: function () {
this._assertPopupView();
return this.popupView.hasMatched();
},
adjustHeight: function () {
if (BI.Maskers.has(this.getName()) && BI.Maskers.get(this.getName()).isVisible()) {
BI.Maskers.show(this.getName());
}
},
adjustView: function () {
this.isViewVisible() && BI.Maskers.show(this.getName());
},
setValue: function (v) {
if (BI.isNull(this.popupView)) {
this.options.popup.value = v;
} else {
this.popupView.setValue(v);
}
},
getKeyword: function () {
return this._getLastSearchKeyword();
},
getKeywords: function () {
return this.editor.getKeywords();
},
getValue: function () {
var o = this.options;
if (o.isAutoSync && o.adapter && o.adapter.getValue) {
return o.adapter.getValue();
}
if (this.isSearching()) {
return this.popupView.getValue();
} else if (o.adapter && o.adapter.getValue) {
return o.adapter.getValue();
}
if (BI.isNull(this.popupView)) {
return o.popup.value;
}
return this.popupView.getValue();
},
populate: function (result, searchResult, keyword) {
var o = this.options;
this._assertPopupView();
this.popupView.populate.apply(this.popupView, arguments);
if (o.isAutoSync && o.adapter && o.adapter.getValue) {
this.popupView.setValue(o.adapter.getValue());
}
},
empty: function () {
this.popupView && this.popupView.empty();
},
destroyed: function () {
BI.Maskers.remove(this.getName());
}
});
BI.Searcher.EVENT_CHANGE = "EVENT_CHANGE";
BI.Searcher.EVENT_START = "EVENT_START";
BI.Searcher.EVENT_STOP = "EVENT_STOP";
BI.Searcher.EVENT_PAUSE = "EVENT_PAUSE";
BI.Searcher.EVENT_SEARCHING = "EVENT_SEARCHING";
BI.Searcher.EVENT_AFTER_INIT = "EVENT_AFTER_INIT";
BI.shortcut("bi.searcher", BI.Searcher);

291
src/main/resources/com/fr/fineui/base/combination/switcher.js

@ -0,0 +1,291 @@
/**
*
* 切换显示或隐藏面板
*
* Created by GUY on 2015/11/2.
* @class BI.Switcher
* @extends BI.Widget
*/
BI.Switcher = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Switcher.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-switcher",
direction: BI.Direction.Top,
trigger: "click",
toggle: true,
el: {},
popup: {},
adapter: null,
masker: {},
switcherClass: "bi-switcher-popup",
hoverClass: "bi-switcher-hover"
});
},
render: function () {
var self = this, o = this.options;
this._initSwitcher();
this._initPullDownAction();
this.switcher.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
if (self.isEnabled() && self.isValid()) {
if (type === BI.Events.EXPAND) {
self._popupView();
}
if (type === BI.Events.COLLAPSE) {
self._hideView();
}
if (type === BI.Events.EXPAND) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.fireEvent(BI.Switcher.EVENT_EXPAND);
}
if (type === BI.Events.COLLAPSE) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
self.isViewVisible() && self.fireEvent(BI.Switcher.EVENT_COLLAPSE);
}
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Switcher.EVENT_TRIGGER_CHANGE, value, obj);
}
}
});
this.element.hover(function () {
if (self.isEnabled() && self.switcher.isEnabled()) {
self.element.addClass(o.hoverClass);
}
}, function () {
if (self.isEnabled() && self.switcher.isEnabled()) {
self.element.removeClass(o.hoverClass);
}
});
BI.createWidget({
type: "bi.vertical",
scrolly: false,
element: this,
items: [
{el: this.switcher}
]
});
o.isDefaultInit && (this._assertPopupView());
},
_toggle: function () {
this._assertPopupView();
if (this.isExpanded()) {
this._hideView();
} else {
if (this.isEnabled()) {
this._popupView();
}
}
},
_initPullDownAction: function () {
var self = this, o = this.options;
var evs = this.options.trigger.split(",");
BI.each(evs, function (i, e) {
switch (e) {
case "hover":
self.element[e](function (e) {
if (self.isEnabled() && self.switcher.isEnabled()) {
self._popupView();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.switcher);
self.fireEvent(BI.Switcher.EVENT_EXPAND);
}
}, function () {
if (self.isEnabled() && self.switcher.isEnabled() && o.toggle) {
self._hideView();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.switcher);
self.fireEvent(BI.Switcher.EVENT_COLLAPSE);
}
});
break;
default :
if (e) {
self.element.off(e + "." + self.getName()).on(e + "." + self.getName(), BI.debounce(function (e) {
if (self.switcher.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && self.switcher.isEnabled()) {
o.toggle ? self._toggle() : self._popupView();
if (self.isExpanded()) {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, "", self.switcher);
self.fireEvent(BI.Switcher.EVENT_EXPAND);
} else {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, "", self.switcher);
self.fireEvent(BI.Switcher.EVENT_COLLAPSE);
}
}
}
}, BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
}));
}
break;
}
});
},
_initSwitcher: function () {
this.switcher = BI.createWidget(this.options.el, {
value: this.options.value
});
},
_assertPopupView: function () {
var self = this, o = this.options;
if (!this._created) {
this.popupView = BI.createWidget(o.popup, {
type: "bi.button_group",
element: o.adapter && BI.Maskers.create(this.getName(), o.adapter, BI.extend({container: this}, o.masker)),
cls: "switcher-popup",
layouts: [{
type: "bi.vertical",
hgap: 0,
vgap: 0
}],
value: o.value
}, this);
this.popupView.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.Switcher.EVENT_CHANGE, value, obj);
}
});
if (o.direction !== BI.Direction.Custom && !o.adapter) {
BI.createWidget({
type: "bi.vertical",
scrolly: false,
element: this,
items: [
{el: this.popupView}
]
});
}
this._created = true;
BI.nextTick(function () {
self.fireEvent(BI.Switcher.EVENT_AFTER_INIT);
});
}
},
_hideView: function () {
this.fireEvent(BI.Switcher.EVENT_BEFORE_HIDEVIEW);
var self = this, o = this.options;
o.adapter ? BI.Maskers.hide(self.getName()) : (self.popupView && self.popupView.setVisible(false));
BI.nextTick(function () {
o.adapter ? BI.Maskers.hide(self.getName()) : (self.popupView && self.popupView.setVisible(false));
self.element.removeClass(o.switcherClass);
self.fireEvent(BI.Switcher.EVENT_AFTER_HIDEVIEW);
});
},
_popupView: function () {
var self = this, o = this.options;
this._assertPopupView();
this.fireEvent(BI.Switcher.EVENT_BEFORE_POPUPVIEW);
o.adapter ? BI.Maskers.show(this.getName()) : self.popupView.setVisible(true);
BI.nextTick(function (name) {
o.adapter ? BI.Maskers.show(name) : self.popupView.setVisible(true);
self.element.addClass(o.switcherClass);
self.fireEvent(BI.Switcher.EVENT_AFTER_POPUPVIEW);
}, this.getName());
},
_populate: function () {
this._assertPopupView();
this.popupView.populate.apply(this.popupView, arguments);
},
populate: function (items) {
this._populate.apply(this, arguments);
this.switcher.populate && this.switcher.populate.apply(this.switcher, arguments);
},
_setEnable: function (arg) {
BI.Switcher.superclass._setEnable.apply(this, arguments);
!arg && this.isViewVisible() && this._hideView();
},
setValue: function (v) {
this.switcher.setValue(v);
if (BI.isNull(this.popupView)) {
this.options.popup.value = v;
} else {
this.popupView.setValue(v);
}
},
getValue: function () {
if (BI.isNull(this.popupView)) {
return this.options.popup.value;
} else {
return this.popupView.getValue();
}
},
setAdapter: function (adapter) {
this.options.adapter = adapter;
BI.Maskers.remove(this.getName());
},
isViewVisible: function () {
return this.isEnabled() && this.switcher.isEnabled() &&
(this.options.adapter ? BI.Maskers.isVisible(this.getName()) : (this.popupView && this.popupView.isVisible()));
},
isExpanded: function () {
return this.isViewVisible();
},
showView: function () {
if (this.isEnabled() && this.switcher.isEnabled()) {
this._popupView();
}
},
hideView: function () {
this._hideView();
},
getView: function () {
return this.popupView;
},
adjustView: function () {
this.isViewVisible() && BI.Maskers.show(this.getName());
},
getAllLeaves: function () {
return this.popupView && this.popupView.getAllLeaves();
},
getNodeById: function (id) {
if (this.switcher.attr("id") === id) {
return this.switcher;
}
return this.popupView && this.popupView.getNodeById(id);
},
getNodeByValue: function (value) {
if (this.switcher.getValue() === value) {
return this.switcher;
}
return this.popupView && this.popupView.getNodeByValue(value);
},
empty: function () {
this.popupView && this.popupView.empty();
}
});
BI.Switcher.EVENT_EXPAND = "EVENT_EXPAND";
BI.Switcher.EVENT_COLLAPSE = "EVENT_COLLAPSE";
BI.Switcher.EVENT_TRIGGER_CHANGE = "EVENT_TRIGGER_CHANGE";
BI.Switcher.EVENT_CHANGE = "EVENT_CHANGE";
BI.Switcher.EVENT_AFTER_INIT = "EVENT_AFTER_INIT";
BI.Switcher.EVENT_BEFORE_POPUPVIEW = "EVENT_BEFORE_POPUPVIEW";
BI.Switcher.EVENT_AFTER_POPUPVIEW = "EVENT_AFTER_POPUPVIEW";
BI.Switcher.EVENT_BEFORE_HIDEVIEW = "EVENT_BEFORE_HIDEVIEW";
BI.Switcher.EVENT_AFTER_HIDEVIEW = "EVENT_AFTER_HIDEVIEW";
BI.shortcut("bi.switcher", BI.Switcher);

157
src/main/resources/com/fr/fineui/base/combination/tab.js

@ -0,0 +1,157 @@
/**
* Created by GUY on 2015/6/26.
*/
BI.Tab = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Tab.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-tab",
direction: "top", // top, bottom, left, right, custom
single: false, // 是不是单页面
logic: {
dynamic: false
},
showIndex: false,
tab: false,
cardCreator: function (v) {
return BI.createWidget();
}
});
},
render: function () {
var self = this, o = this.options;
if (BI.isObject(o.tab)) {
this.tab = BI.createWidget(this.options.tab, {type: "bi.button_group"});
this.tab.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
}
this.cardMap = {};
this.layout = BI.createWidget({
type: "bi.card"
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tab, this.layout)
}))));
var listener = new BI.ShowListener({
eventObj: this.tab,
cardLayout: this.layout,
cardCreator: function (v) {
var card = o.cardCreator.apply(self, arguments);
self.cardMap[v] = card;
return card;
},
afterCardShow: function (v) {
self._deleteOtherCards(v);
self.curr = v;
}
});
listener.on(BI.ShowListener.EVENT_CHANGE, function (value) {
self.fireEvent(BI.Tab.EVENT_CHANGE, value, self);
});
},
_deleteOtherCards: function (currCardName) {
var self = this, o = this.options;
if (o.single === true) {
BI.each(this.cardMap, function (name, card) {
if (name !== (currCardName + "")) {
self.layout.deleteCardByName(name);
delete self.cardMap[name];
}
});
}
},
_assertCard: function (v) {
if (!this.layout.isCardExisted(v)) {
var card = this.options.cardCreator(v);
this.cardMap[v] = card;
this.layout.addCardByName(v, card);
}
},
created: function () {
var o = this.options;
if (o.showIndex !== false) {
this.setSelect(o.showIndex);
}
},
setSelect: function (v, action, callback) {
this.tab && this.tab.setValue(v);
this._assertCard(v);
this.layout.showCardByName(v, action, callback);
this._deleteOtherCards(v);
if (this.curr !== v) {
this.curr = v;
}
},
removeTab: function (cardname) {
var self = this, o = this.options;
BI.any(this.cardMap, function (name, card) {
if (BI.isEqual(name, (cardname + ""))) {
self.layout.deleteCardByName(name);
delete self.cardMap[name];
return true;
}
});
},
isCardExisted: function (cardName) {
return this.layout.isCardExisted(cardName);
},
getSelect: function () {
return this.curr;
},
getSelectedTab: function () {
return this.layout.getShowingCard();
},
getTab: function (v) {
this._assertCard(v);
return this.layout.getCardByName(v);
},
setValue: function (v) {
var card = this.layout.getShowingCard();
if (card) {
card.setValue(v);
}
},
getValue: function () {
var card = this.layout.getShowingCard();
if (card) {
return card.getValue();
}
},
populate: function () {
var card = this.layout.getShowingCard();
if (card) {
return card.populate && card.populate.apply(card, arguments);
}
},
empty: function () {
this.layout.deleteAllCard();
this.cardMap = {};
},
destroy: function () {
this.cardMap = {};
BI.Tab.superclass.destroy.apply(this, arguments);
}
});
BI.Tab.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.tab", BI.Tab);

178
src/main/resources/com/fr/fineui/base/combination/tree.button.js

@ -0,0 +1,178 @@
/**
* Created by GUY on 2015/8/10.
* @class BI.ButtonTree
* @extends BI.ButtonGroup
*/
BI.ButtonTree = BI.inherit(BI.ButtonGroup, {
_defaultConfig: function () {
return BI.extend(BI.ButtonTree.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-button-tree"
});
},
setNotSelectedValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (!BI.isFunction(item.setSelected)) {
item.setNotSelectedValue(v);
return;
}
if (BI.deepContains(v, item.getValue())) {
item.setSelected(false);
} else {
item.setSelected(true);
}
});
},
setEnabledValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (BI.isFunction(item.setEnabledValue)) {
item.setEnabledValue(v);
return;
}
if (BI.deepContains(v, item.getValue())) {
item.setEnable(true);
} else {
item.setEnable(false);
}
});
},
setValue: function (v) {
v = BI.isArray(v) ? v : [v];
BI.each(this.buttons, function (i, item) {
if (!BI.isFunction(item.setSelected)) {
item.setValue(v);
return;
}
if (BI.deepContains(v, item.getValue())) {
item.setSelected(true);
} else {
item.setSelected(false);
}
});
},
getNotSelectedValue: function () {
var v = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !BI.isFunction(item.setSelected)) {
v = BI.concat(v, item.getNotSelectedValue());
return;
}
if (item.isEnabled() && item.isSelected && !item.isSelected()) {
v.push(item.getValue());
}
});
return v;
},
getValue: function () {
var v = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !BI.isFunction(item.setSelected)) {
v = BI.concat(v, item.getValue());
return;
}
if (item.isEnabled() && item.isSelected && item.isSelected()) {
v.push(item.getValue());
}
});
return v;
},
getSelectedButtons: function () {
var btns = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !BI.isFunction(item.setSelected)) {
btns = btns.concat(item.getSelectedButtons());
return;
}
if (item.isSelected && item.isSelected()) {
btns.push(item);
}
});
return btns;
},
getNotSelectedButtons: function () {
var btns = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !BI.isFunction(item.setSelected)) {
btns = btns.concat(item.getNotSelectedButtons());
return;
}
if (item.isSelected && !item.isSelected()) {
btns.push(item);
}
});
return btns;
},
// 获取所有的叶子节点
getAllLeaves: function () {
var leaves = [];
BI.each(this.buttons, function (i, item) {
if (item.isEnabled() && !BI.isFunction(item.setSelected)) {
leaves = leaves.concat(item.getAllLeaves());
return;
}
if (item.isEnabled()) {
leaves.push(item);
}
});
return leaves;
},
getIndexByValue: function (value) {
var index = -1;
BI.any(this.buttons, function (i, item) {
var vs = item.getValue();
if (item.isEnabled() && (vs === value || BI.contains(vs, value))) {
index = i;
return true;
}
});
return index;
},
getNodeById: function (id) {
var node;
BI.any(this.buttons, function (i, item) {
if (item.isEnabled()) {
if (item.attr("id") === id) {
node = item;
return true;
} else if (BI.isFunction(item.getNodeById)) {
if (node = item.getNodeById(id)) {
return true;
}
}
}
});
return node;
},
getNodeByValue: function (value) {
var node;
BI.any(this.buttons, function (i, item) {
if (item.isEnabled()) {
if (BI.isFunction(item.getNodeByValue)) {
if (node = item.getNodeByValue(value)) {
return true;
}
} else if (item.attr("value") === value) {
node = item;
return true;
}
}
});
return node;
}
});
BI.ButtonTree.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.button_tree", BI.ButtonTree);

38
src/main/resources/com/fr/fineui/base/el.js

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

47
src/main/resources/com/fr/fineui/base/foundation/__test__/message.test.js

@ -0,0 +1,47 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/9
*/
describe("MessageTest", function () {
/**
* test_author_windy
*/
it("alert", function (done) {
BI.Msg.alert("message", "ASASASASA");
var body = BI.Widget._renderEngine.createElement("body");
expect(body.find(".bi-message-depend").length).to.equal(1);
BI.nextTick(function () {
body.find(".bi-message-depend .bi-button").click();
expect(body.find(".bi-message-depend").length).to.equal(0);
done();
});
});
/**
* test_author_windy
*/
it("toast_hand_close", function (done) {
BI.Msg.toast("message", {
autoClose: false
});
var body = BI.Widget._renderEngine.createElement("body");
expect(body.find(".bi-toast").length).to.equal(1);
BI.nextTick(function () {
body.find(".bi-toast .bi-icon-button").click();
expect(body.find(".bi-toast").length).to.equal(0);
done();
});
});
/**
* test_author_windy
*/
it("toast_auto_close", function () {
BI.Msg.toast("message");
var body = BI.Widget._renderEngine.createElement("body");
expect(body.find(".bi-toast").length).to.equal(1);
});
});

203
src/main/resources/com/fr/fineui/base/foundation/message.js

@ -0,0 +1,203 @@
/**
* z-index在1亿层级
* 弹出提示消息框用于模拟阻塞操作通过回调函数实现
* @class BI.Msg
*/
BI.Msg = function () {
var $mask, $pop;
var messageShows = [];
var toastStack = [];
return {
alert: function (title, message, callback) {
this._show(false, title, message, callback);
},
confirm: function (title, message, callback) {
this._show(true, title, message, callback);
},
prompt: function (title, message, value, callback, min_width) {
// BI.Msg.prompt(title, message, value, callback, min_width);
},
toast: function (message, options, context) {
options = options || {};
context = context || BI.Widget._renderEngine.createElement("body");
var level = options.level || "common";
var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose;
var callback = BI.isFunction(options.callback) ? options.callback : BI.emptyFn;
var toast = BI.createWidget({
type: "bi.toast",
cls: "bi-message-animate bi-message-leave",
level: level,
autoClose: autoClose,
text: message,
listeners: [{
eventName: BI.Toast.EVENT_DESTORY,
action: function () {
BI.remove(toastStack, toast.element);
var _height = BI.SIZE_CONSANTS.TOAST_TOP;
BI.each(toastStack, function (i, element) {
element.css({"top": _height});
_height += element.outerHeight() + 10;
});
callback();
}
}]
});
var height = BI.SIZE_CONSANTS.TOAST_TOP;
BI.each(toastStack, function (i, element) {
height += element.outerHeight() + 10;
});
BI.createWidget({
type: "bi.absolute",
element: context,
items: [{
el: toast,
left: "50%",
top: height
}]
});
toastStack.push(toast.element);
toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2});
toast.element.removeClass("bi-message-leave").addClass("bi-message-enter");
autoClose && BI.delay(function () {
toast.element.removeClass("bi-message-enter").addClass("bi-message-leave");
toast.destroy();
}, 5000);
},
_show: function (hasCancel, title, message, callback) {
BI.isNull($mask) && ($mask = BI.Widget._renderEngine.createElement("<div class=\"bi-z-index-mask\">").css({
position: "absolute",
zIndex: BI.zIndex_tip - 2,
top: 0,
left: 0,
right: 0,
bottom: 0,
opacity: 0.5
}).appendTo("body"));
$pop = BI.Widget._renderEngine.createElement("<div class=\"bi-message-depend\">").css({
position: "absolute",
zIndex: BI.zIndex_tip - 1,
top: 0,
left: 0,
right: 0,
bottom: 0
}).appendTo("body");
var close = function () {
messageShows[messageShows.length - 1].destroy();
messageShows.pop();
if (messageShows.length === 0) {
$mask.remove();
$mask = null;
}
};
var controlItems = [];
if (hasCancel === true) {
controlItems.push({
el: {
type: "bi.button",
text: BI.i18nText("BI-Basic_Cancel"),
level: "ignore",
handler: function () {
close();
if (BI.isFunction(callback)) {
callback.apply(null, [false]);
}
}
}
});
}
controlItems.push({
el: {
type: "bi.button",
text: BI.i18nText("BI-Basic_OK"),
handler: function () {
close();
if (BI.isFunction(callback)) {
callback.apply(null, [true]);
}
}
}
});
var conf = {
element: $pop,
type: "bi.center_adapt",
items: [
{
type: "bi.border",
cls: "bi-card",
items: {
north: {
el: {
type: "bi.border",
cls: "bi-message-title bi-background",
items: {
center: {
el: {
type: "bi.label",
cls: "bi-font-bold",
text: title || BI.i18nText("BI-Basic_Prompt"),
textAlign: "left",
hgap: 20,
height: 40
}
},
east: {
el: {
type: "bi.icon_button",
cls: "bi-message-close close-font",
// height: 50,
handler: function () {
close();
if (BI.isFunction(callback)) {
callback.apply(null, [false]);
}
}
},
width: 60
}
}
},
height: 40
},
center: {
el: {
type: "bi.label",
vgap: 10,
hgap: 20,
whiteSpace: "normal",
text: message
}
},
south: {
el: {
type: "bi.absolute",
items: [{
el: {
type: "bi.right_vertical_adapt",
lgap: 10,
items: controlItems
},
top: 0,
left: 20,
right: 20,
bottom: 0
}]
},
height: 44
}
},
width: 450,
height: 200
}
]
};
messageShows[messageShows.length] = BI.createWidget(conf);
}
};
}();

41
src/main/resources/com/fr/fineui/base/grid/__test__/grid.test.js

@ -0,0 +1,41 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/20
*/
describe("GridTest", function () {
/**
* test_author_windy
*/
it("grid", function () {
var items = [];
var rowCount = 1000, columnCount = 100;
for (var i = 0; i < rowCount; i++) {
items[i] = [];
for (var j = 0; j < columnCount; j++) {
items[i][j] = {
type: "bi.label",
text: i + "-" + j
};
}
}
var grid = BI.createWidget({
type: "bi.grid_view",
width: 400,
height: 300,
estimatedRowSize: 30,
estimatedColumnSize: 100,
items: items,
scrollTop: 100,
rowHeightGetter: function () {
return 30;
},
columnWidthGetter: function () {
return 100;
}
});
// TODO 性能展示类控件,不知道要测啥,标记一下
grid.destroy();
});
});

381
src/main/resources/com/fr/fineui/base/grid/grid.js

@ -0,0 +1,381 @@
/**
* GridView
*
* Created by GUY on 2016/1/11.
* @class BI.GridView
* @extends BI.Widget
*/
BI.GridView = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.GridView.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-grid-view",
// width: 400, //必设
// height: 300, //必设
overflowX: true,
overflowY: true,
overscanColumnCount: 0,
overscanRowCount: 0,
rowHeightGetter: BI.emptyFn, // number类型或function类型
columnWidthGetter: BI.emptyFn, // number类型或function类型
// estimatedColumnSize: 100, //columnWidthGetter为function时必设
// estimatedRowSize: 30, //rowHeightGetter为function时必设
scrollLeft: 0,
scrollTop: 0,
items: []
});
},
render: function () {
var self = this, o = this.options;
this.renderedCells = [];
this.renderedKeys = [];
this.renderRange = {};
this._scrollLock = false;
this._debounceRelease = BI.debounce(function () {
self._scrollLock = false;
}, 1000 / 60);
this.container = BI._lazyCreateWidget({
type: "bi.absolute"
});
this.element.scroll(function () {
if (self._scrollLock === true) {
return;
}
o.scrollLeft = self.element.scrollLeft();
o.scrollTop = self.element.scrollTop();
self._calculateChildrenToRender();
self.fireEvent(BI.GridView.EVENT_SCROLL, {
scrollLeft: o.scrollLeft,
scrollTop: o.scrollTop
});
});
BI._lazyCreateWidget({
type: "bi.vertical",
element: this,
scrollable: o.overflowX === true && o.overflowY === true,
scrolly: o.overflowX === false && o.overflowY === true,
scrollx: o.overflowX === true && o.overflowY === false,
items: [this.container]
});
if (o.items.length > 0) {
this._calculateSizeAndPositionData();
this._populate();
}
},
// mounted之后绑定事件
mounted: function () {
var o = this.options;
if (o.scrollLeft !== 0 || o.scrollTop !== 0) {
this.element.scrollTop(o.scrollTop);
this.element.scrollLeft(o.scrollLeft);
}
},
_calculateSizeAndPositionData: function () {
var o = this.options;
this.rowCount = 0;
this.columnCount = 0;
if (BI.isNumber(o.columnCount)) {
this.columnCount = o.columnCount;
} else if (o.items.length > 0) {
this.columnCount = o.items[0].length;
}
if (BI.isNumber(o.rowCount)) {
this.rowCount = o.rowCount;
} else {
this.rowCount = o.items.length;
}
this._columnSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.columnCount, o.columnWidthGetter, o.estimatedColumnSize);
this._rowSizeAndPositionManager = new BI.ScalingCellSizeAndPositionManager(this.rowCount, o.rowHeightGetter, o.estimatedRowSize);
},
_getOverscanIndices: function (cellCount, overscanCellsCount, startIndex, stopIndex) {
return {
overscanStartIndex: Math.max(0, startIndex - overscanCellsCount),
overscanStopIndex: Math.min(cellCount - 1, stopIndex + overscanCellsCount)
};
},
_calculateChildrenToRender: function () {
var self = this, o = this.options;
var width = o.width, height = o.height, scrollLeft = BI.clamp(o.scrollLeft, 0, this._getMaxScrollLeft()),
scrollTop = BI.clamp(o.scrollTop, 0, this._getMaxScrollTop()),
overscanColumnCount = o.overscanColumnCount, overscanRowCount = o.overscanRowCount;
if (height > 0 && width > 0) {
var visibleColumnIndices = this._columnSizeAndPositionManager.getVisibleCellRange(width, scrollLeft);
var visibleRowIndices = this._rowSizeAndPositionManager.getVisibleCellRange(height, scrollTop);
if (BI.isEmpty(visibleColumnIndices) || BI.isEmpty(visibleRowIndices)) {
return;
}
var horizontalOffsetAdjustment = this._columnSizeAndPositionManager.getOffsetAdjustment(width, scrollLeft);
var verticalOffsetAdjustment = this._rowSizeAndPositionManager.getOffsetAdjustment(height, scrollTop);
this._renderedColumnStartIndex = visibleColumnIndices.start;
this._renderedColumnStopIndex = visibleColumnIndices.stop;
this._renderedRowStartIndex = visibleRowIndices.start;
this._renderedRowStopIndex = visibleRowIndices.stop;
var overscanColumnIndices = this._getOverscanIndices(this.columnCount, overscanColumnCount, this._renderedColumnStartIndex, this._renderedColumnStopIndex);
var overscanRowIndices = this._getOverscanIndices(this.rowCount, overscanRowCount, this._renderedRowStartIndex, this._renderedRowStopIndex);
var columnStartIndex = overscanColumnIndices.overscanStartIndex;
var columnStopIndex = overscanColumnIndices.overscanStopIndex;
var rowStartIndex = overscanRowIndices.overscanStartIndex;
var rowStopIndex = overscanRowIndices.overscanStopIndex;
// 算区间size
var minRowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowStartIndex);
var minColumnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnStartIndex);
var maxRowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowStopIndex);
var maxColumnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnStopIndex);
var top = minRowDatum.offset + verticalOffsetAdjustment;
var left = minColumnDatum.offset + horizontalOffsetAdjustment;
var bottom = maxRowDatum.offset + verticalOffsetAdjustment + maxRowDatum.size;
var right = maxColumnDatum.offset + horizontalOffsetAdjustment + maxColumnDatum.size;
// 如果滚动的区间并没有超出渲染的范围
if (top >= this.renderRange.minY && bottom <= this.renderRange.maxY && left >= this.renderRange.minX && right <= this.renderRange.maxX) {
return;
}
var renderedCells = [], renderedKeys = {}, renderedWidgets = {};
var minX = this._getMaxScrollLeft(), minY = this._getMaxScrollTop(), maxX = 0, maxY = 0;
var count = 0;
for (var rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
var rowDatum = this._rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex);
for (var columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
var key = rowIndex + "-" + columnIndex;
var columnDatum = this._columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex);
var index = this.renderedKeys[key] && this.renderedKeys[key][2];
var child;
if (index >= 0) {
// if (columnDatum.size !== this.renderedCells[index]._width) {
// this.renderedCells[index]._width = columnDatum.size;
this.renderedCells[index].el.setWidth(columnDatum.size);
// }
// if (rowDatum.size !== this.renderedCells[index]._height) {
// this.renderedCells[index]._height = rowDatum.size;
this.renderedCells[index].el.setHeight(rowDatum.size);
// }
// if (this.renderedCells[index]._left !== columnDatum.offset + horizontalOffsetAdjustment) {
this.renderedCells[index].el.element.css("left", (columnDatum.offset + horizontalOffsetAdjustment) / BI.pixRatio + BI.pixUnit);
// }
// if (this.renderedCells[index]._top !== rowDatum.offset + verticalOffsetAdjustment) {
this.renderedCells[index].el.element.css("top", (rowDatum.offset + verticalOffsetAdjustment) / BI.pixRatio + BI.pixUnit);
// }
child = this.renderedCells[index].el;
renderedCells.push(this.renderedCells[index]);
} else {
child = BI._lazyCreateWidget(BI.extend({
type: "bi.label",
width: columnDatum.size,
height: rowDatum.size
}, o.items[rowIndex][columnIndex], {
cls: (o.items[rowIndex][columnIndex].cls || "") + " grid-cell" + (rowIndex === 0 ? " first-row" : "") + (columnIndex === 0 ? " first-col" : ""),
_rowIndex: rowIndex,
_columnIndex: columnIndex,
_left: columnDatum.offset + horizontalOffsetAdjustment,
_top: rowDatum.offset + verticalOffsetAdjustment
}), this);
renderedCells.push({
el: child,
left: columnDatum.offset + horizontalOffsetAdjustment,
top: rowDatum.offset + verticalOffsetAdjustment,
_left: columnDatum.offset + horizontalOffsetAdjustment,
_top: rowDatum.offset + verticalOffsetAdjustment
// _width: columnDatum.size,
// _height: rowDatum.size
});
}
minX = Math.min(minX, columnDatum.offset + horizontalOffsetAdjustment);
maxX = Math.max(maxX, columnDatum.offset + horizontalOffsetAdjustment + columnDatum.size);
minY = Math.min(minY, rowDatum.offset + verticalOffsetAdjustment);
maxY = Math.max(maxY, rowDatum.offset + verticalOffsetAdjustment + rowDatum.size);
renderedKeys[key] = [rowIndex, columnIndex, count];
renderedWidgets[count] = child;
count++;
}
}
// 已存在的, 需要添加的和需要删除的
var existSet = {}, addSet = {}, deleteArray = [];
BI.each(renderedKeys, function (i, key) {
if (self.renderedKeys[i]) {
existSet[i] = key;
} else {
addSet[i] = key;
}
});
BI.each(this.renderedKeys, function (i, key) {
if (existSet[i]) {
return;
}
if (addSet[i]) {
return;
}
deleteArray.push(key[2]);
});
BI.each(deleteArray, function (i, index) {
// 性能优化,不调用destroy方法防止触发destroy事件
self.renderedCells[index].el._destroy();
});
var addedItems = [];
BI.each(addSet, function (index, key) {
addedItems.push(renderedCells[key[2]]);
});
// 与listview一样, 给上下文
this.container.addItems(addedItems, this);
// 拦截父子级关系
this.container._children = renderedWidgets;
this.container.attr("items", renderedCells);
this.renderedCells = renderedCells;
this.renderedKeys = renderedKeys;
this.renderRange = {minX: minX, minY: minY, maxX: maxX, maxY: maxY};
}
},
_getMaxScrollLeft: function () {
return Math.max(0, this._getContainerWidth() - this.options.width + (this.options.overflowX ? BI.DOM.getScrollWidth() : 0));
},
_getMaxScrollTop: function () {
return Math.max(0, this._getContainerHeight() - this.options.height + (this.options.overflowY ? BI.DOM.getScrollWidth() : 0));
},
_getContainerWidth: function () {
return this.columnCount * this.options.estimatedColumnSize;
},
_getContainerHeight: function () {
return this.rowCount * this.options.estimatedRowSize;
},
_populate: function (items) {
var self = this, o = this.options;
this._reRange();
if (items && items !== this.options.items) {
this.options.items = items;
this._calculateSizeAndPositionData();
}
this.container.setWidth(this._getContainerWidth());
this.container.setHeight(this._getContainerHeight());
// 元素未挂载时不能设置scrollTop
this._debounceRelease();
try {
this.element.scrollTop(o.scrollTop);
this.element.scrollLeft(o.scrollLeft);
} catch (e) {
}
this._calculateChildrenToRender();
},
setScrollLeft: function (scrollLeft) {
if (this.options.scrollLeft === scrollLeft) {
return;
}
this._scrollLock = true;
this.options.scrollLeft = BI.clamp(scrollLeft || 0, 0, this._getMaxScrollLeft());
this._debounceRelease();
this.element.scrollLeft(this.options.scrollLeft);
this._calculateChildrenToRender();
},
setScrollTop: function (scrollTop) {
if (this.options.scrollTop === scrollTop) {
return;
}
this._scrollLock = true;
this.options.scrollTop = BI.clamp(scrollTop || 0, 0, this._getMaxScrollTop());
this._debounceRelease();
this.element.scrollTop(this.options.scrollTop);
this._calculateChildrenToRender();
},
setColumnCount: function (columnCount) {
this.options.columnCount = columnCount;
},
setRowCount: function (rowCount) {
this.options.rowCount = rowCount;
},
setOverflowX: function (b) {
var self = this;
if (this.options.overflowX !== !!b) {
this.options.overflowX = !!b;
BI.nextTick(function () {
self.element.css({overflowX: b ? "auto" : "hidden"});
});
}
},
setOverflowY: function (b) {
var self = this;
if (this.options.overflowY !== !!b) {
this.options.overflowY = !!b;
BI.nextTick(function () {
self.element.css({overflowY: b ? "auto" : "hidden"});
});
}
},
getScrollLeft: function () {
return this.options.scrollLeft;
},
getScrollTop: function () {
return this.options.scrollTop;
},
getMaxScrollLeft: function () {
return this._getMaxScrollLeft();
},
getMaxScrollTop: function () {
return this._getMaxScrollTop();
},
setEstimatedColumnSize: function (width) {
this.options.estimatedColumnSize = width;
},
setEstimatedRowSize: function (height) {
this.options.estimatedRowSize = height;
},
// 重新计算children
_reRange: function () {
this.renderRange = {};
},
_clearChildren: function () {
this.container._children = {};
this.container.attr("items", []);
},
restore: function () {
BI.each(this.renderedCells, function (i, cell) {
cell.el._destroy();
});
this._clearChildren();
this.renderedCells = [];
this.renderedKeys = [];
this.renderRange = {};
this._scrollLock = false;
},
populate: function (items) {
if (items && items !== this.options.items) {
this.restore();
}
this._populate(items);
}
});
BI.GridView.EVENT_SCROLL = "EVENT_SCROLL";
BI.shortcut("bi.grid_view", BI.GridView);

33
src/main/resources/com/fr/fineui/base/layer/__test__/layer.popover.test.js

@ -0,0 +1,33 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/17
*/
describe("PopoverTest", function () {
/**
* test_author_windy
*/
it("BarPopover", function (done) {
var id = BI.UUID();
BI.Popovers.remove(id);
BI.Popovers.create(id, {
type: "bi.bar_popover",
size: "normal",
header: {
type: "bi.label",
text: "这个是header"
},
body: {
type: "bi.label",
text: "这个是body"
}
}).open(id);
BI.delay(function () {
expect(BI.Widget._renderEngine.createElement("body").find(".bi-popup-view .bi-z-index-mask").length).to.equal(1);
BI.Popovers.remove(id);
done();
}, 100);
});
});

272
src/main/resources/com/fr/fineui/base/layer/layer.popover.js

@ -0,0 +1,272 @@
/**
* Popover弹出层
* @class BI.Popover
* @extends BI.Widget
*/
BI.Popover = BI.inherit(BI.Widget, {
_constant: {
SIZE: {
SMALL: "small",
NORMAL: "normal",
BIG: "big",
},
MAX_HEIGHT: 600
},
props: {
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: 20,
bodyTgap: 10
},
render: function () {
var self = this; var o = this.options;
var c = this._constant;
this.startX = 0;
this.startY = 0;
var size = this._calculateSize();
this.tracker = new BI.MouseMoveTracker(function (deltaX, deltaY) {
var W = BI.Widget._renderEngine.createElement("body").width();
var H = BI.Widget._renderEngine.createElement("body").height();
self.startX += deltaX;
self.startY += deltaY;
self.element.css({
left: BI.clamp(self.startX, 0, W - self.element.width()) + "px",
top: BI.clamp(self.startY, 0, H - self.element.height()) + "px",
});
// BI-12134 没有什么特别好的方法
BI.Resizers._resize({
target: self.element[0],
});
}, function () {
self.tracker.releaseMouseMoves();
}, _global);
var items = [{
el: {
type: "bi.htape",
cls: "bi-message-title bi-header-background",
ref: function (_ref) {
self.dragger = _ref;
},
items: [{
type: "bi.absolute",
items: [{
el: BI.isPlainObject(o.header) ? BI.extend({}, o.header, {
extraCls: "bi-font-bold",
}) : {
type: "bi.label",
cls: "bi-font-bold",
height: o.headerHeight,
text: o.header,
title: o.header,
textAlign: "left",
},
left: 20,
top: 0,
right: 0,
bottom: 0,
}],
}, {
el: o.closable ? {
type: "bi.icon_button",
cls: "bi-message-close close-font",
height: o.headerHeight,
handler: function () {
self.close();
},
} : {
type: "bi.layout",
},
width: 56,
}],
height: o.headerHeight,
},
height: o.headerHeight,
}, o.logic.dynamic ? {
el: {
type: "bi.vertical",
scrolly: true,
cls: "popover-body",
ref: function () {
self.body = this;
},
css: {
"max-height": this._getSuitableBodyHeight(c.MAX_HEIGHT - o.headerHeight - (o.footer ? o.footerHeight : 0) - o.bodyTgap),
"min-height": this._getSuitableBodyHeight(size.height - o.headerHeight - (o.footer ? o.footerHeight : 0) - o.bodyTgap),
},
items: [{
el: o.body,
}],
},
hgap: o.bodyHgap,
tgap: o.bodyTgap,
} : {
el: {
type: "bi.absolute",
items: [{
el: o.body,
left: o.bodyHgap,
top: o.bodyTgap,
right: o.bodyHgap,
bottom: 0,
}],
},
}];
if (o.footer) {
items.push({
el: {
type: "bi.absolute",
items: [{
el: o.footer,
left: 20,
top: 0,
right: 20,
bottom: 0,
}],
height: o.footerHeight,
},
height: o.footerHeight,
});
}
return BI.extend({
type: o.logic.dynamic ? "bi.vertical" : "bi.vtape",
items: items,
width: this._getSuitableWidth(size.width),
}, o.logic.dynamic ? {
type: "bi.vertical",
scrolly: false,
} : {
type: "bi.vtape",
height: this._getSuitableHeight(size.height),
});
},
// mounted之后绑定事件
mounted: function () {
var self = this; var o = this.options;
this.dragger.element.mousedown(function (e) {
var pos = self.element.offset();
self.startX = pos.left;
self.startY = pos.top;
self.tracker.captureMouseMoves(e);
});
},
_getSuitableBodyHeight: function (height) {
var o = this.options;
var c = this._constant;
return BI.clamp(height, 0, BI.Widget._renderEngine.createElement("body")[0].clientHeight - o.headerHeight - (o.footer ? o.footerHeight : 0) - o.bodyTgap);
},
_getSuitableHeight: function (height) {
return BI.clamp(height, 0, BI.Widget._renderEngine.createElement("body")[0].clientHeight);
},
_getSuitableWidth: function (width) {
return BI.clamp(width, 0, BI.Widget._renderEngine.createElement("body").width());
},
_calculateSize: function () {
var o = this.options;
var size = {};
if (BI.isNotNull(o.size)) {
switch (o.size) {
case this._constant.SIZE.SMALL:
size.width = 450;
size.height = 200;
size.type = "small";
break;
case this._constant.SIZE.BIG:
size.width = 900;
size.height = 500;
size.type = "big";
break;
default:
size.width = 550;
size.height = 500;
size.type = "default";
}
}
return {
width: o.width || size.width,
height: o.height || size.height,
type: size.type || "default",
};
},
hide: function () {
},
open: function () {
this.show();
this.fireEvent(BI.Popover.EVENT_OPEN, arguments);
},
close: function () {
this.hide();
this.fireEvent(BI.Popover.EVENT_CLOSE, arguments);
},
setZindex: function (zindex) {
this.element.css({ "z-index": zindex });
},
destroyed: function () {},
});
BI.shortcut("bi.popover", BI.Popover);
BI.BarPopover = BI.inherit(BI.Popover, {
_defaultConfig: function () {
return BI.extend(BI.BarPopover.superclass._defaultConfig.apply(this, arguments), {
btns: [BI.i18nText("BI-Basic_Sure"), BI.i18nText("BI-Basic_Cancel")],
});
},
beforeCreate: function () {
var self = this; var o = this.options;
o.footer || (o.footer = {
type: "bi.right_vertical_adapt",
lgap: 10,
items: [{
type: "bi.button",
text: this.options.btns[1],
value: 1,
level: "ignore",
handler: function (v) {
self.fireEvent(BI.Popover.EVENT_CANCEL, v);
self.close(v);
},
}, {
type: "bi.button",
text: this.options.btns[0],
warningTitle: o.warningTitle,
value: 0,
handler: function (v) {
self.fireEvent(BI.Popover.EVENT_CONFIRM, v);
self.close(v);
},
}],
});
},
});
BI.shortcut("bi.bar_popover", BI.BarPopover);
BI.Popover.EVENT_CLOSE = "EVENT_CLOSE";
BI.Popover.EVENT_OPEN = "EVENT_OPEN";
BI.Popover.EVENT_CANCEL = "EVENT_CANCEL";
BI.Popover.EVENT_CONFIRM = "EVENT_CONFIRM";

180
src/main/resources/com/fr/fineui/base/layer/layer.popup.js

@ -0,0 +1,180 @@
/**
* 下拉框弹出层, zIndex在1000w
* @class BI.PopupView
* @extends BI.Widget
*/
BI.PopupView = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.PopupView.superclass._defaultConfig.apply(this, arguments), {
_baseCls: "bi-popup-view",
maxWidth: "auto",
minWidth: 100,
// maxHeight: 200,
minHeight: 24,
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
vgap: 0,
hgap: 0,
innerVGap: 0,
innerHGap: 0,
direction: BI.Direction.Top, // 工具栏的方向
stopEvent: false, // 是否停止mousedown、mouseup事件
stopPropagation: false, // 是否停止mousedown、mouseup向上冒泡
logic: {
dynamic: true
},
tool: false, // 自定义工具栏
tabs: [], // 导航栏
buttons: [], // toolbar栏
el: {
type: "bi.button_group",
items: [],
chooseType: 0,
behaviors: {},
layouts: [{
type: "bi.vertical"
}]
}
});
},
render: function () {
var self = this, o = this.options;
var fn = function (e) {
e.stopPropagation();
}, stop = function (e) {
e.stopEvent();
return false;
};
this.element.css({
"z-index": BI.zIndex_popup,
"min-width": BI.isNumeric(o.minWidth) ? (o.minWidth / BI.pixRatio + BI.pixUnit) : o.minWidth,
"max-width": BI.isNumeric(o.maxWidth) ? (o.maxWidth / BI.pixRatio + BI.pixUnit) : o.maxWidth
}).bind({ click: fn });
this.element.bind("mousewheel", fn);
o.stopPropagation && this.element.bind({ mousedown: fn, mouseup: fn, mouseover: fn });
o.stopEvent && this.element.bind({ mousedown: stop, mouseup: stop, mouseover: stop });
this.tool = this._createTool();
this.tab = this._createTab();
this.view = this._createView();
this.toolbar = this._createToolBar();
this.view.on(BI.Controller.EVENT_CHANGE, function (type) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.PopupView.EVENT_CHANGE);
}
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
scrolly: false,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
vgap: o.vgap,
hgap: o.hgap,
items: BI.LogicFactory.createLogicItemsByDirection(o.direction,
BI.extend({
cls: "list-view-outer bi-card list-view-shadow"
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend({}, o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.tool, this.tab, this.view, this.toolbar)
})))
)
}))));
},
_createView: function () {
var o = this.options;
this.button_group = BI.createWidget(o.el, { type: "bi.button_group", value: o.value });
this.button_group.element.css({
"min-height": BI.isNumeric(o.minHeight) ? (o.minHeight / BI.pixRatio + BI.pixUnit) : o.minHeight,
"padding-top": o.innerVGap / BI.pixRatio + BI.pixUnit,
"padding-bottom": o.innerVGap / BI.pixRatio + BI.pixUnit,
"padding-left": o.innerHGap / BI.pixRatio + BI.pixUnit,
"padding-right": o.innerHGap / BI.pixRatio + BI.pixUnit,
});
return this.button_group;
},
_createTool: function () {
var o = this.options;
if (false === o.tool) {
return;
}
return BI.createWidget(o.tool);
},
_createTab: function () {
var o = this.options;
if (o.tabs.length === 0) {
return;
}
return BI.createWidget({
type: "bi.center",
cls: "list-view-tab",
height: 25,
items: o.tabs,
value: o.value
});
},
_createToolBar: function () {
var o = this.options;
if (o.buttons.length === 0) {
return;
}
return BI.createWidget({
type: "bi.center",
cls: "list-view-toolbar bi-high-light bi-split-top",
height: 24,
items: BI.createItems(o.buttons, {
once: false,
shadow: true,
isShadowShowingOnSelected: true
})
});
},
getView: function () {
return this.view;
},
populate: function (items) {
this.view.populate.apply(this.view, arguments);
},
resetWidth: function (w) {
this.options.width = w;
this.element.width(w);
},
resetHeight: function (h) {
var tbHeight = this.toolbar ? (this.toolbar.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);
var resetHeight = h - tbHeight - tabHeight - toolHeight - 2 * this.options.innerVGap;
this.view.resetHeight ? this.view.resetHeight(resetHeight) :
this.view.element.css({ "max-height": resetHeight / BI.pixRatio + BI.pixUnit });
},
setValue: function (selectedValues) {
this.tab && this.tab.setValue(selectedValues);
this.view.setValue(selectedValues);
},
getValue: function () {
return this.view.getValue();
}
});
BI.PopupView.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.popup_view", BI.PopupView);

140
src/main/resources/com/fr/fineui/base/layer/layer.searcher.js

@ -0,0 +1,140 @@
/**
* 搜索面板
*
* Created by GUY on 2015/9/28.
* @class BI.SearcherView
* @extends BI.Pane
*/
BI.SearcherView = BI.inherit(BI.Pane, {
_defaultConfig: function () {
var conf = BI.SearcherView.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-searcher-view bi-card",
tipText: BI.i18nText("BI-No_Select"),
chooseType: BI.Selection.Single,
matcher: {// 完全匹配的构造器
type: "bi.button_group",
behaviors: {
redmark: function () {
return true;
}
},
items: [],
layouts: [{
type: "bi.vertical"
}]
},
searcher: {
type: "bi.button_group",
behaviors: {
redmark: function () {
return true;
}
},
items: [],
layouts: [{
type: "bi.vertical"
}]
}
});
},
render: function () {
var self = this, o = this.options;
this.matcher = BI.createWidget(o.matcher, {
type: "bi.button_group",
chooseType: o.chooseType,
behaviors: {
redmark: function () {
return true;
}
},
layouts: [{
type: "bi.vertical"
}],
value: o.value
});
this.matcher.on(BI.Controller.EVENT_CHANGE, function (type, val, ob) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob);
}
});
this.spliter = BI.createWidget({
type: "bi.vertical",
height: 1,
hgap: 10,
items: [{
type: "bi.layout",
height: 1,
cls: "searcher-view-spliter bi-background"
}]
});
this.searcher = BI.createWidget(o.searcher, {
type: "bi.button_group",
chooseType: o.chooseType,
behaviors: {
redmark: function () {
return true;
}
},
layouts: [{
type: "bi.vertical"
}],
value: o.value
});
this.searcher.on(BI.Controller.EVENT_CHANGE, function (type, val, ob) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
if (type === BI.Events.CLICK) {
self.fireEvent(BI.SearcherView.EVENT_CHANGE, val, ob);
}
});
BI.createWidget({
type: "bi.vertical",
element: this,
items: [this.matcher, this.spliter, this.searcher]
});
},
startSearch: function () {
},
stopSearch: function () {
},
setValue: function (v) {
this.matcher.setValue(v);
this.searcher.setValue(v);
},
getValue: function () {
return this.matcher.getValue().concat(this.searcher.getValue());
},
populate: function (searchResult, matchResult, keyword) {
searchResult || (searchResult = []);
matchResult || (matchResult = []);
this.setTipVisible(searchResult.length + matchResult.length === 0);
this.spliter.setVisible(BI.isNotEmptyArray(matchResult) && BI.isNotEmptyArray(searchResult));
this.matcher.populate(matchResult, keyword);
this.searcher.populate(searchResult, keyword);
},
empty: function () {
this.searcher.empty();
this.matcher.empty();
},
hasMatched: function () {
return this.matcher.getAllButtons().length > 0;
}
});
BI.SearcherView.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.searcher_view", BI.SearcherView);

48
src/main/resources/com/fr/fineui/base/list/__test__/listview.test.js

@ -0,0 +1,48 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/24
*/
// TODO 展示类控件测什么没想好标记一下
describe("ListView && VirtualList", function () {
/**
* test_author_windy
*/
it("ListView初始化测试", function () {
var a = BI.Test.createWidget({
type: "bi.list_view",
el: {
type: "bi.left"
},
items: BI.map(BI.range(0, 100), function (i, item) {
return BI.extend({}, item, {
type: "bi.label",
width: 200,
height: 200,
text: (i + 1)
});
})
});
a.destroy();
});
/**
* test_author_windy
*/
it("VirtualList初始化测试", function () {
var a = BI.Test.createWidget({
type: "bi.virtual_list",
items: BI.map(BI.range(0, 100), function (i, item) {
return BI.extend({}, item, {
type: "bi.label",
height: 30,
text: (i + 1) + "." + item.text
});
})
});
a.destroy();
});
});

119
src/main/resources/com/fr/fineui/base/list/listview.js

@ -0,0 +1,119 @@
/**
* 表示当前对象
*
* Created by GUY on 2017/5/23.
* @class BI.ListView
* @extends BI.Widget
*/
BI.ListView = BI.inherit(BI.Widget, {
props: function () {
return {
baseCls: "bi-list-view",
overscanHeight: 100,
blockSize: 10,
scrollTop: 0,
el: {},
items: []
};
},
init: function () {
var self = this;
this.renderedIndex = -1;
this.cache = {};
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.vertical",
items: [BI.extend({
type: "bi.vertical",
scrolly: false,
ref: function () {
self.container = this;
}
}, o.el)],
element: this
};
},
// mounted之后绑定事件
mounted: function () {
var self = this, o = this.options;
this._populate();
this.element.scroll(function (e) {
o.scrollTop = self.element.scrollTop();
self._calculateBlocksToRender();
});
var lastWidth = this.element.width(),
lastHeight = this.element.height();
BI.ResizeDetector.addResizeListener(this, function () {
var width = self.element.width(),
height = self.element.height();
if (width !== lastWidth || height !== lastHeight) {
lastWidth = width;
lastHeight = height;
self._calculateBlocksToRender();
}
});
},
_renderMoreIf: function () {
var self = this, o = this.options;
var height = this.element.height();
var minContentHeight = o.scrollTop + height + o.overscanHeight;
var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0,
cnt = this.renderedIndex + 1;
var lastHeight;
var getElementHeight = function () {
return self.container.element.height();
};
while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) {
var items = o.items.slice(index, index + o.blockSize);
this.container.addItems(items, this);
var addedHeight = getElementHeight() - lastHeight;
this.cache[cnt] = {
index: index,
scrollTop: lastHeight,
height: addedHeight
};
this.renderedIndex = cnt;
cnt++;
index += o.blockSize;
}
},
_calculateBlocksToRender: function () {
var o = this.options;
this._renderMoreIf();
},
_populate: function (items) {
var o = this.options;
if (items && this.options.items !== items) {
this.options.items = items;
}
this._calculateBlocksToRender();
this.element.scrollTop(o.scrollTop);
},
restore: function () {
this.renderedIndex = -1;
this.container.empty();
this.cache = {};
},
populate: function (items) {
if (items && this.options.items !== items) {
this.restore();
}
this._populate(items);
},
destroyed: function () {
this.restore();
}
});
BI.shortcut("bi.list_view", BI.ListView);

158
src/main/resources/com/fr/fineui/base/list/virtualgrouplist.js

@ -0,0 +1,158 @@
/**
* 同时用于virtualGroup和virtualList特性的虚拟列表
*
* Created by GUY on 2017/5/22.
* @class BI.VirtualList
* @extends BI.Widget
*/
BI.VirtualGroupList = BI.inherit(BI.Widget, {
props: function () {
return {
baseCls: "bi-virtual-group-list",
overscanHeight: 100,
blockSize: 10,
scrollTop: 0,
rowHeight: "auto",
items: []
};
},
init: function () {
var self = this;
this.renderedIndex = -1;
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.vertical",
items: [{
type: "bi.layout",
ref: function () {
self.topBlank = this;
}
}, {
type: "bi.virtual_group",
height: o.rowHeight * o.items.length,
ref: function () {
self.container = this;
},
layouts: [{
type: "bi.vertical",
scrolly: false
}]
}, {
type: "bi.layout",
ref: function () {
self.bottomBlank = this;
}
}],
element: this
};
},
// mounted之后绑定事件
mounted: function () {
var self = this, o = this.options;
this._populate();
this._debounceRelease = BI.debounce(function () {
self._scrollLock = false;
}, 30);
this.element.scroll(function (e) {
if (self._scrollLock === true) {
return;
}
self._scrollLock = true;
o.scrollTop = self.element.scrollTop();
self._debounceRelease();
self._calculateBlocksToRender();
});
BI.ResizeDetector.addResizeListener(this, function () {
self._calculateBlocksToRender();
});
},
_isAutoHeight: function () {
return this.options.rowHeight === "auto";
},
_renderMoreIf: function () {
var self = this, o = this.options;
var height = this.element.height();
var minContentHeight = o.scrollTop + height + o.overscanHeight;
var index = (this.renderedIndex + 1) * o.blockSize, cnt = this.renderedIndex + 1;
var lastHeight;
var getElementHeight = function () {
return self.container.element.height() + self.topBlank.element.height() + self.bottomBlank.element.height();
};
while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) {
var items = o.items.slice(index, index + o.blockSize);
this.container.addItems(items, this);
var addedHeight = getElementHeight() - lastHeight;
this.tree.set(cnt, addedHeight);
this.renderedIndex = cnt;
cnt++;
index += o.blockSize;
}
},
_calculateBlocksToRender: function () {
var o = this.options;
this._isAutoHeight() && this._renderMoreIf();
var height = this.element.height();
var minContentHeightFrom = o.scrollTop - o.overscanHeight;
var minContentHeightTo = o.scrollTop + height + o.overscanHeight;
var start = this.tree.greatestLowerBound(minContentHeightFrom);
var end = this.tree.leastUpperBound(minContentHeightTo);
var items = [];
var topHeight = this.tree.sumTo(Math.max(-1, start - 1));
this.topBlank.setHeight(topHeight);
if (this._isAutoHeight()) {
for (var i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) {
var index = i * o.blockSize;
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) {
items.push(o.items[j]);
}
}
this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex)));
this.container.populate(items);
} else {
for (var i = (start < 0 ? 0 : start); i <= end; i++) {
var index = i * o.blockSize;
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) {
items.push(o.items[j]);
}
}
this.container.element.height(o.rowHeight * o.items.length - topHeight);
this.container.populate(items);
}
},
_populate: function (items) {
var o = this.options;
if (items && this.options.items !== items) {
this.options.items = items;
}
this.tree = BI.PrefixIntervalTree.uniform(Math.ceil(o.items.length / o.blockSize), this._isAutoHeight() ? 0 : o.rowHeight * o.blockSize);
this._calculateBlocksToRender();
try {
this.element.scrollTop(o.scrollTop);
} catch (e) {
}
},
restore: function () {
this.renderedIndex = -1;
this.options.scrollTop = 0;
// 依赖于cache的占位元素也要初始化
this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0);
},
populate: function (items) {
this._populate(items);
}
});
BI.shortcut("bi.virtual_group_list", BI.VirtualGroupList);

195
src/main/resources/com/fr/fineui/base/list/virtuallist.js

@ -0,0 +1,195 @@
/**
* 虚拟列表
*
* Created by GUY on 2017/5/22.
* @class BI.VirtualList
* @extends BI.Widget
*/
BI.VirtualList = BI.inherit(BI.Widget, {
props: function () {
return {
baseCls: "bi-virtual-list",
overscanHeight: 100,
blockSize: 10,
scrollTop: 0,
items: []
};
},
init: function () {
var self = this;
this.renderedIndex = -1;
this.cache = {};
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.vertical",
items: [{
type: "bi.layout",
ref: function () {
self.topBlank = this;
}
}, {
type: "bi.vertical",
scrolly: false,
ref: function () {
self.container = this;
}
}, {
type: "bi.layout",
ref: function () {
self.bottomBlank = this;
}
}],
element: this
};
},
// mounted之后绑定事件
mounted: function () {
var self = this, o = this.options;
this._populate();
this.element.scroll(function (e) {
o.scrollTop = self.element.scrollTop();
self._calculateBlocksToRender();
});
BI.ResizeDetector.addResizeListener(this, function () {
self._calculateBlocksToRender();
});
},
_renderMoreIf: function () {
var self = this, o = this.options;
var height = this.element.height();
var minContentHeight = o.scrollTop + height + o.overscanHeight;
var index = (this.renderedIndex + 1) * o.blockSize, cnt = this.renderedIndex + 1;
var lastHeight;
var getElementHeight = function () {
return self.container.element.height() + self.topBlank.element.height() + self.bottomBlank.element.height();
};
while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) {
var items = o.items.slice(index, index + o.blockSize);
this.container.addItems(items, this);
var addedHeight = getElementHeight() - lastHeight;
this.tree.set(cnt, addedHeight);
this.renderedIndex = cnt;
cnt++;
index += o.blockSize;
}
},
_calculateBlocksToRender: function () {
var o = this.options;
this._renderMoreIf();
var height = this.element.height();
var minContentHeightFrom = o.scrollTop - o.overscanHeight;
var minContentHeightTo = o.scrollTop + height + o.overscanHeight;
var start = this.tree.greatestLowerBound(minContentHeightFrom);
var end = this.tree.leastUpperBound(minContentHeightTo);
var needDestroyed = [], needMount = [];
for (var i = 0; i < start; i++) {
var index = i * o.blockSize;
if (!this.cache[i]) {
this.cache[i] = {};
}
if (!this.cache[i].destroyed) {
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) {
needDestroyed.push(this.container._children[j]);
this.container._children[j] = null;
}
this.cache[i].destroyed = true;
}
}
for (var i = end + 1; i <= this.renderedIndex; i++) {
var index = i * o.blockSize;
if (!this.cache[i]) {
this.cache[i] = {};
}
if (!this.cache[i].destroyed) {
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) {
needDestroyed.push(this.container._children[j]);
this.container._children[j] = null;
}
this.cache[i].destroyed = true;
}
}
var firstFragment = BI.Widget._renderEngine.createFragment(),
lastFragment = BI.Widget._renderEngine.createFragment();
var currentFragment = firstFragment;
for (var i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) {
var index = i * o.blockSize;
if (!this.cache[i]) {
this.cache[i] = {};
}
if (!this.cache[i].destroyed) {
currentFragment = lastFragment;
}
if (this.cache[i].destroyed === true) {
for (var j = index; j < index + o.blockSize && j < o.items.length; j++) {
var w = this.container._addElement(j, o.items[j], this);
needMount.push(w);
currentFragment.appendChild(w.element[0]);
}
this.cache[i].destroyed = false;
}
}
this.container.element.prepend(firstFragment);
this.container.element.append(lastFragment);
this.topBlank.setHeight(this.tree.sumTo(Math.max(-1, start - 1)));
this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex)));
BI.each(needMount, function (i, child) {
child && child._mount();
});
BI.each(needDestroyed, function (i, child) {
child && child._destroy();
});
},
_populate: function (items) {
var o = this.options;
if (items && this.options.items !== items) {
this.options.items = items;
}
this.tree = BI.PrefixIntervalTree.empty(Math.ceil(o.items.length / o.blockSize));
this._calculateBlocksToRender();
try {
this.element.scrollTop(o.scrollTop);
} catch (e) {
}
},
_clearChildren: function () {
BI.each(this.container._children, function (i, cell) {
cell && cell._destroy();
});
this.container._children = {};
this.container.attr("items", []);
},
restore: function () {
this.renderedIndex = -1;
this._clearChildren();
this.cache = {};
this.options.scrollTop = 0;
// 依赖于cache的占位元素也要初始化
this.topBlank.setHeight(0);
this.bottomBlank.setHeight(0);
},
populate: function (items) {
if (items && this.options.items !== items) {
this.restore();
}
this._populate(items);
},
destroyed: function () {
this.cache = {};
this.renderedIndex = -1;
}
});
BI.shortcut("bi.virtual_list", BI.VirtualList);

289
src/main/resources/com/fr/fineui/base/pager/pager.js

@ -0,0 +1,289 @@
/**
* 分页控件
*
* Created by GUY on 2015/8/31.
* @class BI.Pager
* @extends BI.Widget
*/
BI.Pager = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.Pager.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-pager",
behaviors: {},
layouts: [{
type: "bi.horizontal",
hgap: 10,
vgap: 0
}],
dynamicShow: true, // 是否动态显示上一页、下一页、首页、尾页, 若为false,则指对其设置使能状态
// dynamicShow为false时以下两个有用
dynamicShowFirstLast: false, // 是否动态显示首页、尾页
dynamicShowPrevNext: false, // 是否动态显示上一页、下一页
pages: false, // 总页数
curr: function () {
return 1;
}, // 初始化当前页
groups: 0, // 连续显示分页数
jump: BI.emptyFn, // 分页的回调函数
first: false, // 是否显示首页
last: false, // 是否显示尾页
prev: "上一页",
next: "下一页",
firstPage: 1,
lastPage: function () { // 在万不得已时才会调用这个函数获取最后一页的页码, 主要作用于setValue方法
return 1;
},
hasPrev: BI.emptyFn, // pages不可用时有效
hasNext: BI.emptyFn // pages不可用时有效
});
},
render: function () {
var self = this;
this.currPage = BI.result(this.options, "curr");
// 翻页太灵敏
// this._lock = false;
// this._debouce = BI.debounce(function () {
// self._lock = false;
// }, 300);
this._populate();
},
_populate: function () {
var self = this, o = this.options, view = [], dict = {};
this.empty();
var pages = BI.result(o, "pages");
var curr = BI.result(this, "currPage");
var groups = BI.result(o, "groups");
var first = BI.result(o, "first");
var last = BI.result(o, "last");
var prev = BI.result(o, "prev");
var next = BI.result(o, "next");
if (pages === false) {
groups = 0;
first = false;
last = false;
} else {
groups > pages && (groups = pages);
}
// 计算当前组
dict.index = Math.ceil((curr + ((groups > 1 && groups !== pages) ? 1 : 0)) / (groups === 0 ? 1 : groups));
// 当前页非首页,则输出上一页
if (((!o.dynamicShow && !o.dynamicShowPrevNext) || curr > 1) && prev !== false) {
if (BI.isKey(prev)) {
view.push({
text: prev,
value: "prev",
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false)
});
} else {
view.push(BI.extend({
disabled: pages === false ? o.hasPrev(curr) === false : !(curr > 1 && prev !== false)
}, prev));
}
}
// 当前组非首组,则输出首页
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (dict.index > 1 && groups !== 0)) && first) {
view.push({
text: first,
value: "first",
disabled: !(dict.index > 1 && groups !== 0)
});
if (dict.index > 1 && groups !== 0) {
view.push({
type: "bi.label",
cls: "page-ellipsis",
text: "\u2026"
});
}
}
// 输出当前页组
dict.poor = Math.floor((groups - 1) / 2);
dict.start = dict.index > 1 ? curr - dict.poor : 1;
dict.end = dict.index > 1 ? (function () {
var max = curr + (groups - dict.poor - 1);
return max > pages ? pages : max;
}()) : groups;
if (dict.end - dict.start < groups - 1) { // 最后一组状态
dict.start = dict.end - groups + 1;
}
var s = dict.start, e = dict.end;
if (first && last && (dict.index > 1 && groups !== 0) && (pages > groups && dict.end < pages && groups !== 0)) {
s++;
e--;
}
for (; s <= e; s++) {
if (s === curr) {
view.push({
text: s,
value: s,
selected: true
});
} else {
view.push({
text: s,
value: s
});
}
}
// 总页数大于连续分页数,且当前组最大页小于总页,输出尾页
if (((!o.dynamicShow && !o.dynamicShowFirstLast) || (pages > groups && dict.end < pages && groups !== 0)) && last) {
if (pages > groups && dict.end < pages && groups !== 0) {
view.push({
type: "bi.label",
cls: "page-ellipsis",
text: "\u2026"
});
}
view.push({
text: last,
value: "last",
disabled: !(pages > groups && dict.end < pages && groups !== 0)
});
}
// 当前页不为尾页时,输出下一页
dict.flow = !prev && groups === 0;
if (((!o.dynamicShow && !o.dynamicShowPrevNext) && next) || (curr !== pages && next || dict.flow)) {
view.push((function () {
if (BI.isKey(next)) {
if (pages === false) {
return {text: next, value: "next", disabled: o.hasNext(curr) === false};
}
return (dict.flow && curr === pages)
?
{text: next, value: "next", disabled: true}
:
{text: next, value: "next", disabled: !(curr !== pages && next || dict.flow)};
}
return BI.extend({
disabled: pages === false ? o.hasNext(curr) === false : !(curr !== pages && next || dict.flow)
}, next);
}()));
}
this.button_group = BI.createWidget({
type: "bi.button_group",
element: this,
items: BI.createItems(view, {
cls: "bi-list-item-select bi-border-radius",
height: 23,
hgap: 10,
stopPropagation: true
}),
behaviors: o.behaviors,
layouts: o.layouts
});
this.button_group.on(BI.Controller.EVENT_CHANGE, function (type, value, obj) {
// if (self._lock === true) {
// return;
// }
// self._lock = true;
// self._debouce();
if (type === BI.Events.CLICK) {
var v = self.button_group.getValue()[0];
switch (v) {
case "first":
self.currPage = 1;
break;
case "last":
self.currPage = pages;
break;
case "prev":
self.currPage--;
break;
case "next":
self.currPage++;
break;
default:
self.currPage = v;
break;
}
o.jump.apply(self, [{
pages: pages,
curr: self.currPage
}]);
self._populate();
self.fireEvent(BI.Pager.EVENT_CHANGE, obj);
}
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
this.fireEvent(BI.Pager.EVENT_AFTER_POPULATE);
},
getCurrentPage: function () {
return this.currPage;
},
setAllPages: function (pages) {
this.options.pages = pages;
},
hasPrev: function (v) {
v || (v = 1);
var o = this.options;
var pages = this.options.pages;
return pages === false ? o.hasPrev(v) : v > 1;
},
hasNext: function (v) {
v || (v = 1);
var o = this.options;
var pages = this.options.pages;
return pages === false ? o.hasNext(v) : v < pages;
},
setValue: function (v) {
var o = this.options;
v = v || 0;
v = v < 1 ? 1 : v;
if (o.pages === false) {
var lastPage = BI.result(o, "lastPage"), firstPage = 1;
this.currPage = v > lastPage ? lastPage : ((firstPage = BI.result(o, "firstPage")), (v < firstPage ? firstPage : v));
} else {
v = v > o.pages ? o.pages : v;
this.currPage = v;
}
this._populate();
},
getValue: function () {
var val = this.button_group.getValue()[0];
switch (val) {
case "prev":
return -1;
case "next":
return 1;
case "first":
return BI.MIN;
case "last":
return BI.MAX;
default :
return val;
}
},
attr: function (key, value) {
BI.Pager.superclass.attr.apply(this, arguments);
if (key === "curr") {
this.currPage = BI.result(this.options, "curr");
}
},
populate: function () {
this._populate();
}
});
BI.Pager.EVENT_CHANGE = "EVENT_CHANGE";
BI.Pager.EVENT_AFTER_POPULATE = "EVENT_AFTER_POPULATE";
BI.shortcut("bi.pager", BI.Pager);

207
src/main/resources/com/fr/fineui/base/single/0.single.js

@ -0,0 +1,207 @@
/**
* guy
* 这仅仅只是一个超类, 所有简单控件的基类
* 1类的控制
* 2title的控制
* 3文字超过边界显示3个点
* 4cursor默认pointor
* @class BI.Single
* @extends BI.Widget
* @abstract
*/
BI.Single = BI.inherit(BI.Widget, {
_defaultConfig: function () {
var conf = BI.Single.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
readonly: false,
title: null,
warningTitle: null,
tipType: null, // success或warning
belowMouse: false // title是否跟随鼠标
});
},
_showToolTip: function (e, opt) {
opt || (opt = {});
var self = this, o = this.options;
var type = this.getTipType() || (this.isEnabled() ? "success" : "warning");
var title = type === "success" ? this.getTitle() : (this.getWarningTitle() || this.getTitle());
if (BI.isKey(title)) {
BI.Tooltips.show(e, this.getName(), title, type, this, opt);
if (o.action) {
BI.Actions.runAction(o.action, "hover", o, this);
}
BI.Actions.runGlobalAction("hover", o, this);
}
},
_hideTooltip: function () {
var self = this;
var tooltip = BI.Tooltips.get(this.getName());
if (BI.isNotNull(tooltip)) {
tooltip.element.fadeOut(200, function () {
BI.Tooltips.remove(self.getName());
});
}
},
_init: function () {
BI.Single.superclass._init.apply(this, arguments);
var self = this, o = this.options;
if (BI.isKey(o.title) || BI.isKey(o.warningTitle)
|| BI.isFunction(o.title) || BI.isFunction(o.warningTitle)) {
this.enableHover({
belowMouse: o.belowMouse,
container: o.container
});
}
},
_clearTimeOut: function () {
if (BI.isNotNull(this.showTimeout)) {
clearTimeout(this.showTimeout);
this.showTimeout = null;
}
if (BI.isNotNull(this.hideTimeout)) {
clearTimeout(this.hideTimeout);
this.hideTimeout = null;
}
},
enableHover: function (opt) {
opt || (opt = {});
var self = this;
if (!this._hoverBinded) {
this.element.on("mouseenter.title" + this.getName(), function (e) {
self._e = e;
if (self.getTipType() === "warning" || (BI.isKey(self.getWarningTitle()) && !self.isEnabled())) {
self.showTimeout = BI.delay(function () {
if (BI.isNotNull(self.showTimeout)) {
self._showToolTip(self._e || e, opt);
}
}, 200);
} else if (self.getTipType() === "success" || self.isEnabled()) {
self.showTimeout = BI.delay(function () {
if (BI.isNotNull(self.showTimeout)) {
self._showToolTip(self._e || e, opt);
}
}, 500);
}
});
this.element.on("mousemove.title" + this.getName(), function (e) {
self._e = e;
if (BI.isNotNull(self.showTimeout)) {
clearTimeout(self.showTimeout);
self.showTimeout = null;
}
if (BI.isNull(self.hideTimeout)) {
self.hideTimeout = BI.delay(function () {
if (BI.isNotNull(self.hideTimeout)) {
self._hideTooltip();
}
}, 500);
}
self.showTimeout = BI.delay(function () {
// DEC-5321 IE下如果回调已经进入事件队列,clearTimeout将不会起作用
if (BI.isNotNull(self.showTimeout)) {
if (BI.isNotNull(self.hideTimeout)) {
clearTimeout(self.hideTimeout);
self.hideTimeout = null;
}
// CHART-10611 在拖拽的情况下, 鼠标拖拽着元素离开了拖拽元素的容器,但是子元素在dom结构上仍然属于容器
// 这样会认为鼠标仍然在容器中, 500ms内放开的话,会在容器之外显示鼠标停留处显示容器的title
if (self.element.__isMouseInBounds__(self._e || e)) {
self._showToolTip(self._e || e, opt);
}
}
}, 500);
});
this.element.on("mouseleave.title" + this.getName(), function (e) {
self._e = null;
self._clearTimeOut();
self._hideTooltip();
});
this._hoverBinded = true;
}
},
disabledHover: function () {
// 取消hover事件
this._clearTimeOut();
this._hideTooltip();
this.element.unbind("mouseenter.title" + this.getName())
.unbind("mousemove.title" + this.getName())
.unbind("mouseleave.title" + this.getName());
this._hoverBinded = false;
},
// opt: {container: '', belowMouse: false}
setTitle: function (title, opt) {
this.options.title = title;
if (BI.isKey(title) || BI.isFunction(title)) {
this.enableHover(opt);
} else {
this.disabledHover();
}
},
setWarningTitle: function (title, opt) {
this.options.warningTitle = title;
if (BI.isKey(title) || BI.isFunction(title)) {
this.enableHover(opt);
} else {
this.disabledHover();
}
},
setTipType: function (type) {
this.options.tipType = type;
},
getTipType: function () {
return this.options.tipType;
},
isReadOnly: function () {
return !!this.options.readonly;
},
getTitle: function () {
var title = this.options.title;
if (BI.isFunction(title)) {
return title();
}
return title;
},
getWarningTitle: function () {
var title = this.options.warningTitle;
if (BI.isFunction(title)) {
return title();
}
return title;
},
setValue: function (val) {
if (!this.options.readonly) {
this.options.value = val;
this.options.setValue && this.options.setValue(val);
}
},
getValue: function () {
return this.options.value;
},
__d: function () {
BI.Single.superclass.__d.call(this);
if (BI.isNotNull(this.showTimeout)) {
clearTimeout(this.showTimeout);
this.showTimeout = null;
}
BI.Tooltips.remove(this.getName());
}
});
BI.shortcut("bi.single", BI.Single);

170
src/main/resources/com/fr/fineui/base/single/1.text.js

@ -0,0 +1,170 @@
/**
* guy 表示一行数据通过position来定位位置的数据
* @class BI.Text
* @extends BI.Single
*/
!(function () {
BI.Text = BI.inherit(BI.Single, {
props: {
baseCls: "bi-text",
textAlign: "left",
whiteSpace: "normal",
lineHeight: null,
handler: null, // 如果传入handler,表示处理文字的点击事件,不是区域的
hgap: 0,
vgap: 0,
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
py: "",
highLight: false
},
render: function () {
var self = this, o = this.options;
if (o.hgap + o.lgap > 0) {
this.element.css({
"padding-left": (o.hgap + o.lgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.hgap + o.rgap > 0) {
this.element.css({
"padding-right": (o.hgap + o.rgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.vgap + o.tgap > 0) {
this.element.css({
"padding-top": (o.vgap + o.tgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.vgap + o.bgap > 0) {
this.element.css({
"padding-bottom": (o.vgap + o.bgap) / BI.pixRatio + BI.pixUnit
});
}
if (BI.isWidthOrHeight(o.height)) {
this.element.css({lineHeight: BI.isNumber(o.height) ? (o.height / BI.pixRatio + BI.pixUnit) : o.height});
}
if (BI.isWidthOrHeight(o.lineHeight)) {
this.element.css({lineHeight: BI.isNumber(o.lineHeight) ? (o.lineHeight / BI.pixRatio + BI.pixUnit) : o.lineHeight});
}
if (BI.isWidthOrHeight(o.maxWidth)) {
this.element.css({maxWidth: BI.isNumber(o.maxWidth) ? (o.maxWidth / BI.pixRatio + BI.pixUnit) : o.maxWidth});
}
this.element.css({
textAlign: o.textAlign,
whiteSpace: this._getTextWrap(),
textOverflow: o.whiteSpace === "nowrap" ? "ellipsis" : "",
overflow: o.whiteSpace === "nowrap" ? "" : (BI.isWidthOrHeight(o.height) ? "auto" : "")
});
if (o.handler && o.handler !== BI.emptyFn) {
this.text = BI.createWidget({
type: "bi.layout",
tagName: "span"
});
this.text.element.click(function (e) {
o.handler.call(self, self.getValue(), self, e);
});
BI.createWidget({
type: "bi.default",
element: this,
items: [this.text]
});
} else {
this.text = this;
}
var text = this._getShowText();
// 只要不是undefined就可以显示text值,否则显示value
if (!BI.isUndefined(text)) {
this.setText(text);
} else if (BI.isKey(o.value)) {
this.setText(o.value);
}
if (BI.isKey(o.keyword)) {
this.doRedMark(o.keyword);
}
if (o.highLight) {
this.doHighLight();
}
},
_getTextWrap: function () {
var o = this.options;
switch (o.whiteSpace) {
case "nowrap":
return "pre";
case "normal":
return "pre-wrap";
default:
return o.whiteSpace;
}
},
_getShowText: function () {
var o = this.options;
var text = BI.isFunction(o.text) ? o.text() : o.text;
return BI.isKey(text) ? BI.Text.formatText(text + "") : text;
},
_doRedMark: function (keyword) {
var o = this.options;
// render之后做的doRedMark,这个时候虽然标红了,但是之后text mounted执行的时候并没有keyword
o.keyword = keyword;
this.text.element.__textKeywordMarked__(this._getShowText(), keyword, o.py);
},
doRedMark: function (keyword) {
if (BI.isKey(keyword)) {
this._doRedMark(keyword);
}
},
unRedMark: function () {
var o = this.options;
o.keyword = "";
this.text.element.__textKeywordMarked__(this._getShowText(), "", o.py);
},
doHighLight: function () {
this.text.element.addClass("bi-high-light");
},
unHighLight: function () {
this.text.element.removeClass("bi-high-light");
},
setValue: function (text) {
BI.Text.superclass.setValue.apply(this, arguments);
if (!this.isReadOnly()) {
this.setText(text);
}
},
setStyle: function (css) {
this.text.element.css(css);
},
setText: function (text) {
BI.Text.superclass.setText.apply(this, arguments);
this.options.text = text;
this._doRedMark(this.options.keyword);
}
});
var formatters = [];
BI.Text.addTextFormatter = function (formatter) {
formatters.push(formatter);
};
BI.Text.formatText = function (text) {
if (formatters.length > 0) {
for (var i = 0, len = formatters.length; i < len; i++) {
text = formatters[i](text);
}
}
return text;
};
BI.shortcut("bi.text", BI.Text);
}());

195
src/main/resources/com/fr/fineui/base/single/__test__/text.test.js

@ -0,0 +1,195 @@
/**
* Created by windy on 2018/01/23.
*/
describe("TextTest", function () {
/**
* test_author_windy
*/
it("setText", function () {
var text = BI.Test.createWidget({
type: "bi.text"
});
text.setText("AAA");
expect(text.element.text()).to.equal("AAA");
text.destroy();
});
/**
* test_author_windy
*/
it("setStyle", function () {
var text = BI.Test.createWidget({
type: "bi.text"
});
text.setStyle({"color": "red"});
expect(text.element.getStyle("color")).to.equal("rgb(255, 0, 0)");
text.destroy();
});
/**
* test_author_windy
*/
it("高亮doHighlight", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "AAA",
highLight: true
});
expect(text.element.getStyle("color")).to.equal("rgb(54, 133, 242)");
text.destroy();
});
/**
* test_author_windy
*/
it("标红doRedMark", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是要标红的A",
keyword: "A"
});
expect(text.element.children(".bi-keyword-red-mark").length).to.not.equal(0);
text.destroy();
});
/**
* test_author_windy
*/
it("取消高亮undoHighlight", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "AAA",
highLight: true
});
text.unHighLight();
expect(text.element.getStyle("color")).to.not.equal("rgb(54, 133, 242)");
text.destroy();
});
/**
* test_author_windy
*/
it("取消标红undoRedMark", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是要标红的A",
keyword: "A"
});
text.unRedMark();
expect(text.element.children(".bi-keyword-red-mark").length).to.equal(0);
text.destroy();
});
/**
* test_author_windy
*/
it("setValue", function () {
var text = BI.Test.createWidget({
type: "bi.text",
value: "AAA",
});
text.setValue("value");
expect(text.element.text()).to.equal("value");
text.destroy();
});
/**
* test_author_windy
*/
it("gap测试", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是要标红的A",
vgap: 10,
hgap: 10
});
expect(text.element.css("padding")).to.equal("10px");
text.destroy();
});
/**
* test_author_windy
*/
it("空格测试", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是要标红的 A",
});
expect(text.element.text()).to.equal("我是要标红的 A");
text.destroy();
});
/**
* test_author_windy
*/
it("lineHeight和height", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是A",
lineHeight: 12,
height: 24
});
expect(text.element.css("height")).to.equal("24px");
expect(text.element.css("line-height")).to.equal("12px");
text.destroy();
});
/**
* test_author_windy
*/
it("handler", function (done) {
var text = BI.Test.createWidget({
type: "bi.text",
text: "我是A",
handler: function () {
text.setText("handler");
}
});
BI.nextTick(function () {
text.text.element.click();
expect(text.text.element.text()).to.equal("handler");
text.destroy();
done();
});
});
/**
* test_author_windy
*/
it("text的value属性", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: "",
value: "aaaa"
});
expect(text.element.text()).to.equal("");
text.destroy();
});
/**
* test_author_windy
*/
it("text的value属性1", function () {
var text = BI.Test.createWidget({
type: "bi.text",
value: "aaaa"
});
expect(text.element.text()).to.equal("aaaa");
text.destroy();
});
/**
* test_author_windy
*/
it("text的value属性2", function () {
var text = BI.Test.createWidget({
type: "bi.text",
text: null,
value: "aaaa"
});
expect(text.element.text()).to.equal("");
text.destroy();
});
});

32
src/main/resources/com/fr/fineui/base/single/a/__test__/a.test.js

@ -0,0 +1,32 @@
/**
* Created by windy on 2018/01/23.
*/
describe("ALinkTest", function () {
/**
* test_author_windy
*/
it("A初始化测试", function () {
var a = BI.Test.createWidget({
type: "bi.a",
text: "CCC"
});
expect(a.element.is('a')).to.equal(true);
a.destroy();
});
/**
* test_author_windy
*/
it("A的el测试", function () {
var a = BI.Test.createWidget({
type: "bi.a",
text: "DDD",
el: {
type: "bi.label"
}
});
expect(a.element.is('a') && a.element.hasClass("bi-label")).to.equal(true);
a.destroy();
});
});

33
src/main/resources/com/fr/fineui/base/single/a/a.js

@ -0,0 +1,33 @@
/**
* 超链接
*
* Created by GUY on 2015/9/9.
* @class BI.A
* @extends BI.Text
* @abstract
*/
BI.A = BI.inherit(BI.Text, {
_defaultConfig: function () {
var conf = BI.A.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-a display-block",
href: "",
target: "_blank",
el: null,
tagName: "a"
});
},
render: function () {
var o = this.options;
BI.A.superclass.render.apply(this, arguments);
this.element.attr({href: o.href, target: o.target});
if (o.el) {
BI.createWidget(o.el, {
element: this
});
}
}
});
BI.shortcut("bi.a", BI.A);

80
src/main/resources/com/fr/fineui/base/single/bar/bar.loading.js

@ -0,0 +1,80 @@
/**
* guy
* 加载条
* @type {*|void|Object}
*/
BI.LoadingBar = BI.inherit(BI.Single, {
_defaultConfig: function () {
var conf = BI.LoadingBar.superclass._defaultConfig.apply(this, arguments);
return BI.extend( conf, {
baseCls: (conf.baseCls || "") + " bi-loading-bar bi-tips",
height: 30,
handler: BI.emptyFn
});
},
render: function () {
var self = this;
this.loaded = BI.createWidget({
type: "bi.text_button",
cls: "loading-text bi-list-item-simple",
text: BI.i18nText("BI-Load_More"),
width: 120,
handler: this.options.handler
});
this.loaded.on(BI.Controller.EVENT_CHANGE, function (type) {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
this.loading = BI.createWidget({
type: "bi.layout",
width: this.options.height,
height: this.options.height,
cls: "loading-background cursor-default"
});
var loaded = BI.createWidget({
type: "bi.center_adapt",
items: [this.loaded]
});
var loading = BI.createWidget({
type: "bi.center_adapt",
items: [this.loading]
});
this.cardLayout = BI.createWidget({
type: "bi.card",
element: this,
items: [{
el: loaded,
cardName: "loaded"
}, {
el: loading,
cardName: "loading"
}]
});
this.invisible();
},
_reset: function () {
this.visible();
this.loaded.setText(BI.i18nText("BI-Load_More"));
this.loaded.enable();
},
setLoaded: function () {
this._reset();
this.cardLayout.showCardByName("loaded");
},
setEnd: function () {
this.setLoaded();
this.loaded.setText(BI.i18nText("BI-No_More_Data"));
this.loaded.disable();
},
setLoading: function () {
this._reset();
this.cardLayout.showCardByName("loading");
}
});
BI.shortcut("bi.loading_bar", BI.LoadingBar);

412
src/main/resources/com/fr/fineui/base/single/button/button.basic.js

@ -0,0 +1,412 @@
/**
* guy
* @class BI.BasicButton
* @extends BI.Single
*
* 一般的button父级
*/
BI.BasicButton = BI.inherit(BI.Single, {
_defaultConfig: function () {
var conf = BI.BasicButton.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
_baseCls: (conf._baseCls || "") + " bi-basic-button" + (conf.invalid ? "" : " cursor-pointer") + ((BI.isIE() && BI.getIEVersion() < 10) ? " hack" : ""),
value: "",
stopEvent: false,
stopPropagation: false,
selected: false,
once: false, // 点击一次选中有效,再点无效
forceSelected: false, // 点击即选中, 选中了就不会被取消,与once的区别是forceSelected不影响事件的触发
forceNotSelected: false, // 无论怎么点击都不会被选中
disableSelected: false, // 使能选中
shadow: false,
isShadowShowingOnSelected: false, // 选中状态下是否显示阴影
trigger: null,
handler: BI.emptyFn,
bubble: null
});
},
_init: function () {
BI.BasicButton.superclass._init.apply(this, arguments);
var opts = this.options;
if (opts.selected === true) {
BI.nextTick(BI.bind(function () {
this.setSelected(opts.selected);
}, this));
}
BI.nextTick(BI.bind(this.bindEvent, this));
if (opts.shadow) {
this._createShadow();
}
if (opts.level) {
this.element.addClass("button-" + opts.level);
}
},
_createShadow: function () {
var self = this, o = this.options;
var assertMask = function () {
if (!self.$mask) {
self.$mask = BI.createWidget(BI.isObject(o.shadow) ? o.shadow : {}, {
type: "bi.layout",
cls: "bi-button-mask"
});
self.$mask.invisible();
BI.createWidget({
type: "bi.absolute",
element: self,
items: [{
el: self.$mask,
left: 0,
right: 0,
top: 0,
bottom: 0
}]
});
}
};
this.element.mouseup(function () {
if (!self._hover && !o.isShadowShowingOnSelected) {
assertMask();
self.$mask.invisible();
}
});
this.element.on("mouseenter." + this.getName(), function (e) {
if (self.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && !self._hover && (o.isShadowShowingOnSelected || !self.isSelected())) {
assertMask();
self.$mask.visible();
}
}
});
this.element.on("mousemove." + this.getName(), function (e) {
if (!self.element.__isMouseInBounds__(e)) {
if (self.isEnabled() && !self._hover) {
assertMask();
self.$mask.invisible();
}
}
});
this.element.on("mouseleave." + this.getName(), function () {
if (self.isEnabled() && !self._hover) {
assertMask();
self.$mask.invisible();
}
});
},
bindEvent: function () {
var self = this;
var o = this.options, hand = this.handle();
if (!hand) {
return;
}
hand = hand.element;
var triggerArr = (o.trigger || "").split(",");
BI.each(triggerArr, function (idx, trigger) {
switch (trigger) {
case "mouseup":
var mouseDown = false;
hand.mousedown(function () {
mouseDown = true;
});
hand.mouseup(function (e) {
if (mouseDown === true) {
clk(e);
}
mouseDown = false;
ev(e);
});
break;
case "mousedown":
var mouseDown = false;
var selected = false;
hand.mousedown(function (e) {
// if (e.button === 0) {
BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
// if (e.button === 0) {
if (BI.DOM.isExist(self) && !hand.__isMouseInBounds__(e) && mouseDown === true && !selected) {
// self.setSelected(!self.isSelected());
self._trigger();
}
mouseDown = false;
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
// }
});
if (mouseDown === true) {
return;
}
if (self.isSelected()) {
selected = true;
} else {
clk(e);
}
mouseDown = true;
ev(e);
// }
});
hand.mouseup(function (e) {
// if (e.button === 0) {
if (BI.DOM.isExist(self) && mouseDown === true && selected === true) {
clk(e);
}
mouseDown = false;
selected = false;
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
// }
});
break;
case "dblclick":
hand.dblclick(clk);
break;
case "lclick":
var mouseDown = false;
var interval;
hand.mousedown(function (e) {
BI.Widget._renderEngine.createElement(document).bind("mouseup." + self.getName(), function (e) {
interval && clearInterval(interval);
interval = null;
mouseDown = false;
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + self.getName());
});
if (mouseDown === true) {
return;
}
if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
return;
}
interval = setInterval(function () {
if (self.isEnabled()) {
self.doClick();
}
}, 180);
mouseDown = true;
ev(e);
});
break;
default:
if (o.stopEvent || o.stopPropagation) {
hand.mousedown(function (e) {
ev(e);
});
}
hand.click(clk);
break;
}
});
// 之后的300ms点击无效
var onClick = BI.debounce(this._doClick, BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
function ev (e) {
if (o.stopEvent) {
e.stopEvent();
}
if (o.stopPropagation) {
e.stopPropagation();
}
}
function clk (e) {
ev(e);
if (!self.isEnabled() || (self.isOnce() && self.isSelected())) {
return;
}
if (BI.isKey(o.bubble) || BI.isFunction(o.bubble)) {
if (BI.isNull(self.combo)) {
var popup;
BI.createWidget({
type: "bi.absolute",
element: self,
items: [{
el: {
type: "bi.bubble_combo",
trigger: "",
// bubble的提示不需要一直存在在界面上
destroyWhenHide: true,
ref: function () {
self.combo = this;
},
el: {
type: "bi.layout",
height: "100%"
},
popup: {
type: "bi.text_bubble_bar_popup_view",
text: getBubble(),
ref: function () {
popup = this;
},
listeners: [{
eventName: BI.BubblePopupBarView.EVENT_CLICK_TOOLBAR_BUTTON,
action: function (v) {
self.combo.hideView();
if (v) {
onClick.apply(self, arguments);
}
}
}]
},
listeners: [{
eventName: BI.BubbleCombo.EVENT_BEFORE_POPUPVIEW,
action: function () {
popup.populate(getBubble());
}
}]
},
left: 0,
right: 0,
bottom: 0,
top: 0
}]
});
}
if (self.combo.isViewVisible()) {
self.combo.hideView();
} else {
self.combo.showView();
}
return;
}
onClick.apply(self, arguments);
}
function getBubble () {
var bubble = self.options.bubble;
if (BI.isFunction(bubble)) {
return bubble();
}
return bubble;
}
},
_trigger: function (e) {
var o = this.options;
if (!this.isEnabled()) {
return;
}
if (!this.isDisableSelected()) {
this.isForceSelected() ? this.setSelected(true) :
(this.isForceNotSelected() ? this.setSelected(false) :
this.setSelected(!this.isSelected()));
}
if (this.isValid()) {
var v = this.getValue();
o.handler.call(this, v, this, e);
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CLICK, v, this, e);
this.fireEvent(BI.BasicButton.EVENT_CHANGE, v, this);
if (o.action) {
BI.Actions.runAction(o.action, "click", o, this);
}
BI.Actions.runGlobalAction("click", o, this);
}
},
_doClick: function (e) {
if (this.isValid()) {
this.beforeClick(e);
}
this._trigger(e);
if (this.isValid()) {
this.doClick(e);
}
},
beforeClick: function () {
},
doClick: function () {
},
handle: function () {
return this;
},
hover: function () {
this._hover = true;
this.handle().element.addClass("hover");
if (this.options.shadow) {
this.$mask && this.$mask.setVisible(true);
}
},
dishover: function () {
this._hover = false;
this.handle().element.removeClass("hover");
if (this.options.shadow) {
this.$mask && this.$mask.setVisible(false);
}
},
setSelected: function (b) {
var o = this.options;
o.selected = b;
if (b) {
this.handle().element.addClass("active");
} else {
this.handle().element.removeClass("active");
}
if (o.shadow && !o.isShadowShowingOnSelected) {
this.$mask && this.$mask.setVisible(false);
}
this.options.setSelected && this.options.setSelected.call(this, b);
},
isSelected: function () {
return this.options.selected;
},
isOnce: function () {
return this.options.once;
},
isForceSelected: function () {
return this.options.forceSelected;
},
isForceNotSelected: function () {
return this.options.forceNotSelected;
},
isDisableSelected: function () {
return this.options.disableSelected;
},
setText: function (text) {
this.options.text = text;
this.options.setText && this.options.setText.call(this, text);
},
getText: function () {
return this.options.text;
},
_setEnable: function (enable) {
BI.BasicButton.superclass._setEnable.apply(this, arguments);
if (enable === true) {
this.element.removeClass("base-disabled disabled");
} else if (enable === false) {
this.element.addClass("base-disabled disabled");
}
if (!enable) {
if (this.options.shadow) {
this.$mask && this.$mask.setVisible(false);
}
}
},
empty: function () {
BI.Widget._renderEngine.createElement(document).unbind("mouseup." + this.getName());
BI.BasicButton.superclass.empty.apply(this, arguments);
}
});
BI.BasicButton.EVENT_CHANGE = "BasicButton.EVENT_CHANGE";
BI.shortcut("bi.basic_button", BI.BasicButton);

57
src/main/resources/com/fr/fineui/base/single/button/button.node.js

@ -0,0 +1,57 @@
/**
* 表示一个可以展开的节点, 不仅有选中状态而且有展开状态
*
* Created by GUY on 2015/9/9.
* @class BI.NodeButton
* @extends BI.BasicButton
* @abstract
*/
BI.NodeButton = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.NodeButton.superclass._defaultConfig.apply(this, arguments);
return BI.extend( conf, {
_baseCls: (conf._baseCls || "") + " bi-node",
open: false
});
},
_init: function () {
BI.NodeButton.superclass._init.apply(this, arguments);
var self = this;
BI.nextTick(function () {
self.setOpened(self.isOpened());
});
},
doClick: function () {
BI.NodeButton.superclass.doClick.apply(this, arguments);
this.setOpened(!this.isOpened());
},
isOnce: function () {
return false;
},
isOpened: function () {
return !!this.options.open;
},
setOpened: function (b) {
this.options.open = !!b;
},
triggerCollapse: function () {
if(this.isOpened()) {
this.setOpened(false);
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.COLLAPSE, this.getValue(), this);
}
},
triggerExpand: function () {
if(!this.isOpened()) {
this.setOpened(true);
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EXPAND, this.getValue(), this);
}
}
});
BI.shortcut("bi.node_button", BI.NodeButton);

117
src/main/resources/com/fr/fineui/base/single/button/buttons/__test__/button.test.js

@ -0,0 +1,117 @@
/**
* Created by windy on 2018/01/23.
*/
describe("ButtonTest", function () {
/**
* test_author_windy
*/
it("Click点击触发事件", function (done) {
var button = BI.Test.createWidget({
type: "bi.button",
text: "CCC",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
button.element.click();
expect(button.element.children(".bi-text").text()).to.equal("click");
button.destroy();
done();
});
});
/**
* test_author_windy
*/
it("MouseDown触发事件", function (done) {
var button = BI.Test.createWidget({
type: "bi.button",
text: "CCC",
trigger: "mousedown",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
button.element.mousedown();
expect(button.element.children(".bi-text").text()).to.equal("click");
button.destroy();
done();
});
});
/**
* test_author_windy
*/
it("MouseUp触发事件", function (done) {
var button = BI.Test.createWidget({
type: "bi.button",
text: "CCC",
trigger: "mouseup",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
button.element.mousedown();
button.element.mouseup();
expect(button.element.children(".bi-text").text()).to.equal("click");
button.destroy();
done();
});
});
/**
* test_author_windy
*/
it("doubleClick触发事件", function (done) {
var button = BI.Test.createWidget({
type: "bi.button",
text: "CCC",
trigger: "dblclick",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
button.element.dblclick();
expect(button.element.children(".bi-text").text()).to.equal("click");
button.destroy();
done();
});
});
/**
* test_author_windy
*/
it("LongClick触发事件", function (done) {
var clickNum = 0;
var button = BI.Test.createWidget({
type: "bi.button",
text: "CCC",
trigger: "lclick",
listeners: [{
eventName: BI.Button.EVENT_CHANGE,
action: function () {
clickNum++;
}
}]
});
BI.nextTick(function () {
button.element.mousedown();
BI.delay(function () {
expect(clickNum).to.equal(2);
button.destroy();
done();
}, 360);
});
});
});

51
src/main/resources/com/fr/fineui/base/single/button/buttons/button.icon.js

@ -0,0 +1,51 @@
/**
* @class BI.IconButton
* @extends BI.BasicButton
* 图标的button
*/
BI.IconButton = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.IconButton.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
_baseCls: (conf._baseCls || "") + " bi-icon-button horizon-center",
iconWidth: null,
iconHeight: null
});
},
render: function () {
var o = this.options;
this.element.css({
textAlign: "center"
});
this.icon = BI.createWidget({
type: "bi.icon",
width: o.iconWidth,
height: o.iconHeight
});
if (BI.isNumber(o.height) && o.height > 0 && BI.isNull(o.iconWidth) && BI.isNull(o.iconHeight)) {
this.element.css("lineHeight", o.height / BI.pixRatio + BI.pixUnit);
BI.createWidget({
type: "bi.default",
element: this,
items: [this.icon]
});
} else {
this.element.css("lineHeight", "1");
BI.createWidget({
element: this,
type: "bi.center_adapt",
items: [this.icon]
});
}
},
doClick: function () {
BI.IconButton.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.IconButton.EVENT_CHANGE, this);
}
}
});
BI.IconButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.icon_button", BI.IconButton);

86
src/main/resources/com/fr/fineui/base/single/button/buttons/button.image.js

@ -0,0 +1,86 @@
/**
* 图片的button
*
* Created by GUY on 2016/1/27.
* @class BI.ImageButton
* @extends BI.BasicButton
*/
BI.ImageButton = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.ImageButton.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-image-button",
src: "",
iconWidth: "100%",
iconHeight: "100%"
});
},
render: function () {
var o = this.options;
this.image = BI.createWidget({
type: "bi.img",
width: o.iconWidth,
height: o.iconHeight,
src: o.src
});
if (BI.isNumber(o.iconWidth) || BI.isNumber(o.iconHeight)) {
BI.createWidget({
type: "bi.center_adapt",
element: this,
items: [this.image]
});
} else {
BI.createWidget({
type: "bi.adaptive",
element: this,
items: [this.image],
scrollable: false
});
}
},
setWidth: function (w) {
BI.ImageButton.superclass.setWidth.apply(this, arguments);
this.options.width = w;
},
setHeight: function (h) {
BI.ImageButton.superclass.setHeight.apply(this, arguments);
this.options.height = h;
},
setImageWidth: function (w) {
this.image.setWidth(w);
},
setImageHeight: function (h) {
this.image.setHeight(h);
},
getImageWidth: function () {
return this.image.element.width();
},
getImageHeight: function () {
return this.image.element.height();
},
setSrc: function (src) {
this.options.src = src;
this.image.setSrc(src);
},
getSrc: function () {
return this.image.getSrc();
},
doClick: function () {
BI.ImageButton.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.ImageButton.EVENT_CHANGE, this);
}
}
});
BI.ImageButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.image_button", BI.ImageButton);

157
src/main/resources/com/fr/fineui/base/single/button/buttons/button.js

@ -0,0 +1,157 @@
/**
* 文字类型的按钮
* @class BI.Button
* @extends BI.BasicButton
*
* @cfg {JSON} options 配置属性
* @cfg {'common'/'success'/'warning'/'ignore'} [options.level='common'] 按钮类型用不同颜色强调不同的场景
*/
BI.Button = BI.inherit(BI.BasicButton, {
_const: {
iconWidth: 18
},
_defaultConfig: function (props) {
var conf = BI.Button.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-button" + ((BI.isIE() && BI.isIE9Below()) ? " hack" : ""),
minWidth: (props.block === true || props.clear === true) ? 0 : 80,
height: 24,
shadow: props.clear !== true,
isShadowShowingOnSelected: true,
readonly: true,
iconCls: "",
level: "common",
block: false, // 是否块状显示,即不显示边框,没有最小宽度的限制
clear: false, // 是否去掉边框和背景
ghost: false, // 是否幽灵显示, 即正常状态无背景
textAlign: "center",
whiteSpace: "nowrap",
textWidth: null,
textHeight: null,
hgap: props.clear ? 0 : 10,
vgap: 0,
tgap: 0,
bgap: 0,
lgap: 0,
rgap: 0
});
},
render: function () {
var o = this.options, self = this;
// 由于button默认情况下有个边框,所以要主动算行高
var lineHeight, textHeight = o.textHeight;
if (BI.isNumber(o.height)) {
if (o.clear || o.block) {
lineHeight = o.height;
} else {
lineHeight = o.height - 2;
}
}
if (!textHeight) {
if (o.whiteSpace === "nowrap") {
textHeight = lineHeight;
}
}
if (BI.isKey(o.iconCls)) {
this.icon = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls,
width: this._const.iconWidth,
height: o.height,
lineHeight: lineHeight,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
this.text = BI.createWidget({
type: "bi.label",
text: o.text,
textWidth: BI.isNotNull(o.textWidth) ? o.textWidth - this._const.iconWidth : null,
textHeight: textHeight,
height: o.height,
value: o.value
});
BI.createWidget({
type: "bi.center_adapt",
element: this,
hgap: o.hgap,
vgap: o.vgap,
items: [{
type: "bi.horizontal",
columnSize: ["", "fill"],
items: [this.icon, this.text]
}]
});
} else {
this.text = BI.createWidget({
type: "bi.label",
height: o.height,
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
textWidth: o.textWidth,
textHeight: textHeight,
hgap: o.hgap,
vgap: o.vgap,
tgap: o.tgap,
bgap: o.bgap,
lgap: o.lgap,
rgap: o.rgap,
element: this,
text: o.text,
value: o.value
});
}
if (o.block === true) {
this.element.addClass("block");
}
if (o.clear === true) {
this.element.addClass("clear");
}
if (o.ghost === true) {
this.element.addClass("ghost");
}
if (o.minWidth > 0) {
this.element.css({"min-width": o.minWidth / BI.pixRatio + BI.pixUnit});
}
},
doClick: function () {
BI.Button.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.Button.EVENT_CHANGE, this);
}
},
setText: function (text) {
BI.Button.superclass.setText.apply(this, arguments);
this.text.setText(text);
},
setValue: function (text) {
BI.Button.superclass.setValue.apply(this, arguments);
if (!this.isReadOnly()) {
this.text.setValue(text);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
}
});
BI.shortcut("bi.button", BI.Button);
BI.Button.EVENT_CHANGE = "EVENT_CHANGE";

89
src/main/resources/com/fr/fineui/base/single/button/buttons/button.text.js

@ -0,0 +1,89 @@
/**
* guy
* 可以点击的一行文字
* @class BI.TextButton
* @extends BI.BasicButton
* 文字button
*/
BI.TextButton = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.TextButton.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-text-button",
textAlign: "center",
whiteSpace: "nowrap",
textWidth: null,
textHeight: null,
hgap: 0,
lgap: 0,
rgap: 0,
vgap: 0,
py: ""
});
},
render: function () {
var o = this.options;
this.text = BI.createWidget({
type: "bi.label",
element: this,
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
textWidth: o.textWidth,
textHeight: o.textHeight,
width: o.width,
height: o.height,
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
text: o.text,
value: o.value,
py: o.py,
keyword: o.keyword
});
},
doClick: function () {
BI.TextButton.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.TextButton.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
},
setText: function (text) {
BI.TextButton.superclass.setText.apply(this, arguments);
text = BI.isArray(text) ? text.join(",") : text;
this.text.setText(text);
},
setStyle: function (style) {
this.text.setStyle(style);
},
setValue: function (text) {
BI.TextButton.superclass.setValue.apply(this, arguments);
if (!this.isReadOnly()) {
text = BI.isArray(text) ? text.join(",") : text;
this.text.setValue(text);
}
}
});
BI.TextButton.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.text_button", BI.TextButton);

119
src/main/resources/com/fr/fineui/base/single/button/listitem/blankiconicontextitem.js

@ -0,0 +1,119 @@
/**
* 带有一个占位
*
* Created by GUY on 2015/9/11.
* @class BI.BlankIconIconTextItem
* @extends BI.BasicButton
*/
BI.BlankIconIconTextItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.BlankIconIconTextItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item",
logic: {
dynamic: false
},
iconCls1: "",
iconCls2: "",
blankWidth: 0,
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
var blank = BI.createWidget({
type: "bi.layout",
width: o.blankWidth,
height: o.height
});
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon1 = BI.createWidget({
type: "bi.icon_button",
cls: o.iconCls1,
forceNotSelected: true,
width: o.height,
height: o.height
});
this.icon2 = BI.createWidget({
type: "bi.icon_button",
cls: o.iconCls2,
forceNotSelected: true,
width: o.height,
height: o.height
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", blank, this.icon1, this.icon2, this.text)
}))));
},
doClick: function () {
BI.BlankIconIconTextItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.BlankIconIconTextItem.EVENT_CHANGE, this.getValue(), this);
}
},
setSelected: function (b) {
BI.BlankIconIconTextItem.superclass.setSelected.apply(this, arguments);
this.icon1.setSelected(b);
this.icon2.setSelected(b);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
}
});
BI.BlankIconIconTextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.blank_icon_icon_text_item", BI.BlankIconIconTextItem);

126
src/main/resources/com/fr/fineui/base/single/button/listitem/blankicontexticonitem.js

@ -0,0 +1,126 @@
/**
* guy
* 一个占位符和两个icon和一行数 组成的一行listitem
*
* Created by GUY on 2015/9/15.
* @class BI.BlankIconTextIconItem
* @extends BI.BasicButton
*/
BI.BlankIconTextIconItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.BlankIconTextIconItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-icon-item",
logic: {
dynamic: false
},
iconCls1: "",
iconCls2: "",
blankWidth: 0,
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
var icon1 = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls1,
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: {
type: "bi.icon_label",
cls: o.iconCls2,
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
},
top: 0,
bottom: 0,
right: 0
}]
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", {
type: "bi.layout",
width: o.blankWidth
}, icon1, this.text, {
type: "bi.layout",
width: o.height
})
}))));
},
doClick: function () {
BI.BlankIconTextIconItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.BlankIconTextIconItem.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
}
});
BI.BlankIconTextIconItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.blank_icon_text_icon_item", BI.BlankIconTextIconItem);

105
src/main/resources/com/fr/fineui/base/single/button/listitem/blankicontextitem.js

@ -0,0 +1,105 @@
/**
* 带有一个占位
*
* Created by GUY on 2015/9/11.
* @class BI.BlankIconTextItem
* @extends BI.BasicButton
*/
BI.BlankIconTextItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.BlankIconTextItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item",
logic: {
dynamic: false
},
blankWidth: 0,
iconHeight: null,
iconWidth: null,
iconCls: "",
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
var blank = BI.createWidget({
type: "bi.layout",
width: o.blankWidth
});
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls,
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", blank, this.icon, this.text)
}))));
},
doClick: function () {
BI.BlankIconTextItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.BlankIconTextItem.EVENT_CHANGE, this.getValue(), this);
}
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
}
});
BI.BlankIconTextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.blank_icon_text_item", BI.BlankIconTextItem);

123
src/main/resources/com/fr/fineui/base/single/button/listitem/icontexticonitem.js

@ -0,0 +1,123 @@
/**
* guy
* 两个icon和一行数 组成的一行listitem
*
* Created by GUY on 2015/9/9.
* @class BI.IconTextIconItem
* @extends BI.BasicButton
*/
BI.IconTextIconItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.IconTextIconItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-icon-text-icon-item",
logic: {
dynamic: false
},
iconCls1: "",
iconCls2: "",
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
var icon1 = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls1,
width: o.leftIconWrapperWidth,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
var blank = BI.createWidget({
type: "bi.layout",
width: o.height
});
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: {
type: "bi.icon_label",
cls: o.iconCls2,
width: o.rightIconWrapperWidth,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
},
top: 0,
bottom: 0,
right: 0
}]
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", icon1, this.text, blank)
}))));
},
doClick: function () {
BI.IconTextIconItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.IconTextIconItem.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
}
});
BI.IconTextIconItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.icon_text_icon_item", BI.IconTextIconItem);

102
src/main/resources/com/fr/fineui/base/single/button/listitem/icontextitem.js

@ -0,0 +1,102 @@
/**
* guy
*
* Created by GUY on 2015/9/9.
* @class BI.IconTextItem
* @extends BI.BasicButton
*/
BI.IconTextItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.IconTextItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-icon-text-item",
direction: BI.Direction.Left,
logic: {
dynamic: false
},
iconWrapperWidth: null,
iconHeight: null,
iconWidth: null,
iconCls: "",
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls,
width: o.iconWrapperWidth || o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic(BI.LogicFactory.createLogicTypeByDirection(o.direction), BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection(o.direction, this.icon, this.text)
}))));
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doClick: function () {
BI.IconTextItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.IconTextItem.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
}
});
BI.IconTextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.icon_text_item", BI.IconTextItem);

101
src/main/resources/com/fr/fineui/base/single/button/listitem/texticonitem.js

@ -0,0 +1,101 @@
/**
*
* 图标的button
*
* Created by GUY on 2015/9/9.
* @class BI.TextIconItem
* @extends BI.BasicButton
*/
BI.TextIconItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.TextIconItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-text-icon-item",
logic: {
dynamic: false
},
iconHeight: null,
iconWidth: null,
iconCls: "",
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls,
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", this.text, this.icon)
}))));
},
doClick: function () {
BI.TextIconItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.TextIconItem.EVENT_CHANGE, this.getValue(), this);
}
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
}
});
BI.TextIconItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.text_icon_item", BI.TextIconItem);

86
src/main/resources/com/fr/fineui/base/single/button/listitem/textitem.js

@ -0,0 +1,86 @@
/**
* guy
* 一个button和一行数 组成的一行listitem
*
* Created by GUY on 2015/9/9.
* @class BI.TextItem
* @extends BI.BasicButton
*/
BI.TextItem = BI.inherit(BI.BasicButton, {
_defaultConfig: function () {
var conf = BI.TextItem.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-text-item",
textAlign: "left",
whiteSpace: "nowrap",
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options;
this.text = BI.createWidget({
type: "bi.label",
element: this,
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
textHeight: o.whiteSpace == "nowrap" ? o.height : o.textHeight,
height: o.height,
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
py: o.py
});
},
doClick: function () {
BI.TextItem.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.TextItem.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
}
});
BI.TextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.text_item", BI.TextItem);

104
src/main/resources/com/fr/fineui/base/single/button/node/__test__/icontexticonnode.test.js

@ -0,0 +1,104 @@
/**
* @author Kobi
* @date 2020/4/21
*/
describe("IconTextIconNodeTest", function () {
/**
* test_author_kobi
*/
it("setText", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node"
});
iconTextIconNode.setText("AAA");
expect(iconTextIconNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("getText", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node",
text: "AAA",
});
expect(iconTextIconNode.getText()).to.equal("AAA");
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("setValue", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node"
});
iconTextIconNode.setValue("AAA");
expect(iconTextIconNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("readonly下的setValue", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node",
value: "AAA",
readonly: true
});
iconTextIconNode.setValue("BBB");
expect(iconTextIconNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("getValue", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node",
value: "AAA"
});
expect(iconTextIconNode.getValue()).to.equal("AAA");
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("doRedMark和unRedMark", function () {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node",
text: "要标红的AAA",
});
iconTextIconNode.doRedMark("AAA");
expect(iconTextIconNode.element.find(".bi-keyword-red-mark").length).to.not.equal(0);
iconTextIconNode.unRedMark();
expect(iconTextIconNode.element.find(".bi-keyword-red-mark").length).to.equal(0);
iconTextIconNode.destroy();
});
/**
* test_author_kobi
*/
it("Click点击触发事件", function (done) {
var iconTextIconNode = BI.Test.createWidget({
type: "bi.icon_text_icon_node",
text: "AAA",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
iconTextIconNode.element.click();
expect(iconTextIconNode.element.find(".bi-text").text()).to.equal("click");
iconTextIconNode.destroy();
done();
});
});
});

104
src/main/resources/com/fr/fineui/base/single/button/node/__test__/icontextnode.test.js

@ -0,0 +1,104 @@
/**
* @author Kobi
* @date 2020/4/21
*/
describe("IconTextNodeTest", function () {
/**
* test_author_kobi
*/
it("setText", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node"
});
iconTextNode.setText("AAA");
expect(iconTextNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("getText", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node",
text: "AAA",
});
expect(iconTextNode.getText()).to.equal("AAA");
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("setValue", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node"
});
iconTextNode.setValue("AAA");
expect(iconTextNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("readonly下的setValue", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node",
value: "AAA",
readonly: true
});
iconTextNode.setValue("BBB");
expect(iconTextNode.element.find(".bi-text").text()).to.equal("AAA");
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("getValue", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node",
value: "AAA"
});
expect(iconTextNode.getValue()).to.equal("AAA");
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("doRedMark和unRedMark", function () {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node",
text: "要标红的AAA",
});
iconTextNode.doRedMark("AAA");
expect(iconTextNode.element.find(".bi-keyword-red-mark").length).to.not.equal(0);
iconTextNode.unRedMark();
expect(iconTextNode.element.find(".bi-keyword-red-mark").length).to.equal(0);
iconTextNode.destroy();
});
/**
* test_author_kobi
*/
it("Click点击触发事件", function (done) {
var iconTextNode = BI.Test.createWidget({
type: "bi.icon_text_node",
text: "AAA",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
iconTextNode.element.click();
expect(iconTextNode.element.find(".bi-text").text()).to.equal("click");
iconTextNode.destroy();
done();
});
});
});

104
src/main/resources/com/fr/fineui/base/single/button/node/__test__/texticonnode.test.js

@ -0,0 +1,104 @@
/**
* @author Kobi
* @date 2020/4/21
*/
describe("TextIconNodeTest", function () {
/**
* test_author_kobi
*/
it("setText", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node"
});
textIconNode.setText("AAA");
expect(textIconNode.element.find(".bi-text").text()).to.equal("AAA");
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("getText", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node",
text: "AAA",
});
expect(textIconNode.getText()).to.equal("AAA");
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("setValue", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node"
});
textIconNode.setValue("AAA");
expect(textIconNode.element.find(".bi-text").text()).to.equal("AAA");
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("readonly下的setValue", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node",
value: "AAA",
readonly: true
});
textIconNode.setValue("BBB");
expect(textIconNode.element.find(".bi-text").text()).to.equal("AAA");
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("getValue", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node",
value: "AAA"
});
expect(textIconNode.getValue()).to.equal("AAA");
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("doRedMark和unRedMark", function () {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node",
text: "要标红的AAA",
});
textIconNode.doRedMark("AAA");
expect(textIconNode.element.find(".bi-keyword-red-mark").length).to.not.equal(0);
textIconNode.unRedMark();
expect(textIconNode.element.find(".bi-keyword-red-mark").length).to.equal(0);
textIconNode.destroy();
});
/**
* test_author_kobi
*/
it("Click点击触发事件", function (done) {
var textIconNode = BI.Test.createWidget({
type: "bi.text_icon_node",
text: "AAA",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
textIconNode.element.click();
expect(textIconNode.element.find(".bi-text").text()).to.equal("click");
textIconNode.destroy();
done();
});
});
});

106
src/main/resources/com/fr/fineui/base/single/button/node/__test__/textnode.test.js

@ -0,0 +1,106 @@
/**
* @author Kobi
* @date 2020/4/21
*/
describe("TextNodeTest", function () {
/**
* test_author_kobi
*/
it("setText", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node"
});
textNode.setText("AAA");
expect(textNode.element.children(".bi-text").text()).to.equal("AAA");
textNode.destroy();
});
/**
* test_author_kobi
*/
it("getText", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node",
text: "AAA",
whiteSpace: "normal"
});
expect(textNode.getText()).to.equal("AAA");
textNode.destroy();
});
/**
* test_author_kobi
*/
it("setValue", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node"
});
textNode.setValue("AAA");
expect(textNode.element.children(".bi-text").text()).to.equal("AAA");
textNode.destroy();
});
/**
* test_author_kobi
*/
it("readonly下的setValue", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node",
value: "AAA",
readonly: true
});
textNode.setValue("BBB");
expect(textNode.element.children(".bi-text").text()).to.equal("AAA");
textNode.destroy();
});
/**
* test_author_kobi
*/
it("getValue", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node",
value: "AAA"
});
expect(textNode.getValue()).to.equal("AAA");
textNode.destroy();
});
/**
* test_author_kobi
*/
it("doRedMark和unRedMark", function () {
var textNode = BI.Test.createWidget({
type: "bi.text_node",
text: "要标红的AAA",
});
textNode.doRedMark("AAA");
expect(textNode.element.find(".bi-keyword-red-mark").length).to.not.equal(0);
textNode.unRedMark();
expect(textNode.element.find(".bi-keyword-red-mark").length).to.equal(0);
textNode.destroy();
});
/**
* test_author_kobi
*/
it("Click点击触发事件", function (done) {
var textNode = BI.Test.createWidget({
type: "bi.text_node",
text: "AAA",
handler: function () {
this.setText("click");
}
});
BI.nextTick(function () {
textNode.element.click();
expect(textNode.element.children(".bi-text").text()).to.equal("click");
textNode.destroy();
done();
});
});
});

113
src/main/resources/com/fr/fineui/base/single/button/node/icontexticonnode.js

@ -0,0 +1,113 @@
/**
* guy
* Created by GUY on 2015/9/9.
* @class BI.IconTextIconNode
* @extends BI.NodeButton
*/
BI.IconTextIconNode = BI.inherit(BI.NodeButton, {
_defaultConfig: function () {
var conf = BI.IconTextIconNode.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-icon-text-icon-node",
logic: {
dynamic: false
},
iconCls1: "close-ha-font",
iconCls2: "close-ha-font",
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
var icon1 = BI.createWidget({
type: "bi.icon_label",
cls: o.iconCls1,
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
var blank = BI.createWidget({
type: "bi.layout",
width: o.height,
height: o.height
});
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: {
type: "bi.icon_label",
cls: o.iconCls2,
width: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
},
top: 0,
bottom: 0,
right: 0
}]
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", icon1, this.text, blank)
}))));
},
doClick: function () {
BI.IconTextIconNode.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.IconTextIconNode.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
}
});
BI.IconTextIconNode.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.icon_text_icon_node", BI.IconTextIconNode);

90
src/main/resources/com/fr/fineui/base/single/button/node/icontextnode.js

@ -0,0 +1,90 @@
/**
* guy
* Created by GUY on 2015/9/9.
* @class BI.IconTextNode
* @extends BI.NodeButton
*/
BI.IconTextNode = BI.inherit(BI.NodeButton, {
_defaultConfig: function () {
var conf = BI.IconTextNode.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-icon-text-node",
logic: {
dynamic: false
},
cls: "close-ha-font",
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon = BI.createWidget({
type: "bi.icon_label",
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", this.icon, this.text)
}))));
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doClick: function () {
BI.IconTextNode.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.IconTextNode.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
}
});
BI.IconTextNode.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.icon_text_node", BI.IconTextNode);

89
src/main/resources/com/fr/fineui/base/single/button/node/texticonnode.js

@ -0,0 +1,89 @@
/**
* Created by GUY on 2015/9/9.
* @class BI.TextIconNode
* @extends BI.NodeButton
*/
BI.TextIconNode = BI.inherit(BI.NodeButton, {
_defaultConfig: function () {
var conf = BI.TextIconNode.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-text-icon-node",
logic: {
dynamic: false
},
cls: "close-ha-font",
iconHeight: null,
iconWidth: null,
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options, c = this._const;
this.text = BI.createWidget({
type: "bi.label",
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
});
this.icon = BI.createWidget({
type: "bi.icon_label",
width: o.height,
height: o.height,
iconWidth: o.iconWidth,
iconHeight: o.iconHeight
});
BI.createWidget(BI.extend({
element: this
}, BI.LogicFactory.createLogic("horizontal", BI.extend(o.logic, {
items: BI.LogicFactory.createLogicItemsByDirection("left", this.text, this.icon)
}))));
},
doClick: function () {
BI.TextIconNode.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.TextIconNode.EVENT_CHANGE, this.getValue(), this);
}
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
}
});
BI.TextIconNode.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.text_icon_node", BI.TextIconNode);

77
src/main/resources/com/fr/fineui/base/single/button/node/textnode.js

@ -0,0 +1,77 @@
/**
* guy
*
* Created by GUY on 2015/9/9.
* @class BI.TextNode
* @extends BI.NodeButton
*/
BI.TextNode = BI.inherit(BI.NodeButton, {
_defaultConfig: function () {
var conf = BI.TextNode.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-text-node",
textAlign: "left",
whiteSpace: "nowrap",
textHgap: 0,
textVgap: 0,
textLgap: 0,
textRgap: 0
});
},
render: function () {
var o = this.options;
this.text = BI.createWidget({
type: "bi.label",
element: this,
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
textHeight: o.whiteSpace == "nowrap" ? o.height : o.textHeight,
height: o.height,
hgap: o.textHgap,
vgap: o.textVgap,
lgap: o.textLgap,
rgap: o.textRgap,
text: o.text,
value: o.value,
keyword: o.keyword,
py: o.py
});
},
doClick: function () {
BI.TextNode.superclass.doClick.apply(this, arguments);
if (this.isValid()) {
this.fireEvent(BI.TextNode.EVENT_CHANGE, this.getValue(), this);
}
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
setValue: function () {
if (!this.isReadOnly()) {
this.text.setValue.apply(this.text, arguments);
}
},
getValue: function () {
return this.text.getValue();
},
setText: function () {
this.text.setText.apply(this.text, arguments);
},
getText: function () {
return this.text.getText();
}
});
BI.TextNode.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.text_node", BI.TextNode);

370
src/main/resources/com/fr/fineui/base/single/editor/editor.js

@ -0,0 +1,370 @@
/**
* Created by GUY on 2015/4/15.
* @class BI.Editor
* @extends BI.Single
*/
BI.Editor = BI.inherit(BI.Single, {
_defaultConfig: function () {
var conf = BI.Editor.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: "bi-editor bi-focus-shadow",
hgap: 4,
vgap: 2,
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
// title,warningTitle这两个属性没用
tipType: "warning",
inputType: "text",
validationChecker: BI.emptyFn,
quitChecker: BI.emptyFn,
allowBlank: false,
watermark: "",
errorText: "",
});
},
render: function () {
var self = this, o = this.options;
// 密码输入框设置autocomplete="new-password"的情况下Firefox和chrome不会自动填充密码
var autocomplete = o.autocomplete ? " autocomplete=" + o.autocomplete : "";
this.editor = this.addWidget(BI.createWidget({
type: "bi.input",
element: "<input type='" + o.inputType + "'" + autocomplete + " />",
root: true,
value: o.value,
watermark: o.watermark,
validationChecker: o.validationChecker,
quitChecker: o.quitChecker,
allowBlank: o.allowBlank
}));
this.editor.element.css({
width: "100%",
height: "100%",
border: "none",
outline: "none",
padding: "0",
margin: "0"
});
var items = [{
el: {
type: "bi.absolute",
ref: function (_ref) {
self.contentWrapper = _ref;
},
items: [{
el: this.editor,
left: 0,
right: 0,
top: 0,
bottom: 0
}]
},
left: o.hgap + o.lgap,
right: o.hgap + o.rgap,
top: o.vgap + o.tgap,
bottom: o.vgap + o.bgap
}];
BI.createWidget({
type: "bi.absolute",
element: this,
items: items
});
this.setWaterMark(this.options.watermark);
this.editor.on(BI.Controller.EVENT_CHANGE, function () {
self.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
});
this.editor.on(BI.Input.EVENT_FOCUS, function () {
self._checkError();
self.element.addClass("bi-editor-focus");
self.fireEvent(BI.Editor.EVENT_FOCUS, arguments);
});
this.editor.on(BI.Input.EVENT_BLUR, function () {
self._setErrorVisible(false);
self.element.removeClass("bi-editor-focus");
self.fireEvent(BI.Editor.EVENT_BLUR, arguments);
});
this.editor.on(BI.Input.EVENT_CLICK, function () {
self.fireEvent(BI.Editor.EVENT_CLICK, arguments);
});
this.editor.on(BI.Input.EVENT_CHANGE, function () {
self.fireEvent(BI.Editor.EVENT_CHANGE, arguments);
});
this.editor.on(BI.Input.EVENT_KEY_DOWN, function (v) {
self.fireEvent(BI.Editor.EVENT_KEY_DOWN, arguments);
});
this.editor.on(BI.Input.EVENT_QUICK_DOWN, function (e) {
// tab键就不要隐藏了
if (e.keyCode !== BI.KeyCode.TAB && self.watermark) {
self.watermark.invisible();
}
});
this.editor.on(BI.Input.EVENT_VALID, function () {
self._checkWaterMark();
self._setErrorVisible(false);
self.fireEvent(BI.Editor.EVENT_VALID, arguments);
});
this.editor.on(BI.Input.EVENT_ERROR, function () {
self._checkWaterMark();
self.fireEvent(BI.Editor.EVENT_ERROR, arguments);
self._setErrorVisible(self.isEditing());
});
this.editor.on(BI.Input.EVENT_RESTRICT, function () {
self._checkWaterMark();
var tip = self._setErrorVisible(true);
tip && tip.element.fadeOut(100, function () {
tip.element.fadeIn(100);
});
self.fireEvent(BI.Editor.EVENT_RESTRICT, arguments);
});
this.editor.on(BI.Input.EVENT_EMPTY, function () {
self._checkWaterMark();
self.fireEvent(BI.Editor.EVENT_EMPTY, arguments);
});
this.editor.on(BI.Input.EVENT_ENTER, function () {
self.fireEvent(BI.Editor.EVENT_ENTER, arguments);
});
this.editor.on(BI.Input.EVENT_SPACE, function () {
self.fireEvent(BI.Editor.EVENT_SPACE, arguments);
});
this.editor.on(BI.Input.EVENT_BACKSPACE, function () {
self.fireEvent(BI.Editor.EVENT_BACKSPACE, arguments);
});
this.editor.on(BI.Input.EVENT_REMOVE, function () {
self.fireEvent(BI.Editor.EVENT_REMOVE, arguments);
});
this.editor.on(BI.Input.EVENT_START, function () {
self.fireEvent(BI.Editor.EVENT_START, arguments);
});
this.editor.on(BI.Input.EVENT_PAUSE, function () {
self.fireEvent(BI.Editor.EVENT_PAUSE, arguments);
});
this.editor.on(BI.Input.EVENT_STOP, function () {
self.fireEvent(BI.Editor.EVENT_STOP, arguments);
});
this.editor.on(BI.Input.EVENT_CONFIRM, function () {
self.fireEvent(BI.Editor.EVENT_CONFIRM, arguments);
});
this.editor.on(BI.Input.EVENT_CHANGE_CONFIRM, function () {
self.fireEvent(BI.Editor.EVENT_CHANGE_CONFIRM, arguments);
});
this.element.click(function (e) {
e.stopPropagation();
return false;
});
if (BI.isKey(this.options.value) || BI.isEmptyString(this.options.value)) {
this._checkError();
this._checkWaterMark();
} else {
this._checkWaterMark();
}
},
_checkToolTip: function () {
var o = this.options;
var errorText = o.errorText;
if (BI.isFunction(errorText)) {
errorText = errorText(this.editor.getValue());
}
if (BI.isKey(errorText)) {
if (!this.isEnabled() || this.isValid() || BI.Bubbles.has(this.getName())) {
this.setTitle("");
} else {
this.setTitle(errorText);
}
}
},
_assertWaterMark: function () {
var self = this, o = this.options;
if (BI.isNull(this.watermark)) {
this.watermark = BI.createWidget({
type: "bi.label",
cls: "bi-water-mark",
text: this.options.watermark,
height: o.height - 2 * o.vgap - o.tgap,
hgap: 2,
whiteSpace: "nowrap",
textAlign: "left"
});
this.watermark.element.bind({
mousedown: function (e) {
if (self.isEnabled()) {
self.editor.isEditing() || self.editor.focus();
} else {
self.editor.isEditing() && self.editor.blur();
}
e.stopEvent();
}
});
this.watermark.element.bind("click", function (e) {
if (self.isEnabled()) {
self.editor.isEditing() || self.editor.focus();
} else {
self.editor.isEditing() && self.editor.blur();
}
e.stopEvent();
});
}
},
_checkError: function () {
this._setErrorVisible(this.isEnabled() && !this.isValid());
this._checkToolTip();
},
_checkWaterMark: function () {
var o = this.options;
if (!this.disabledWaterMark && this.editor.getValue() === "" && BI.isKey(o.watermark)) {
this.watermark && this.watermark.visible();
} else {
this.watermark && this.watermark.invisible();
}
},
setErrorText: function (text) {
this.options.errorText = text;
},
getErrorText: function () {
return this.options.errorText;
},
setWaterMark: function (v) {
if (!BI.isKey(v)) {
return;
}
this.options.watermark = v;
if (BI.isNull(this.watermark)) {
this._assertWaterMark();
BI.createWidget({
type: "bi.absolute",
element: this.contentWrapper,
items: [{
el: this.watermark,
left: 0,
right: 0,
top: 0,
bottom: 0,
}],
});
}
this.watermark.setText(v);
},
_setErrorVisible: function (b) {
var o = this.options;
var errorText = o.errorText;
if (BI.isFunction(errorText)) {
errorText = errorText(BI.trim(this.editor.getValue()));
}
if (!this.disabledError && BI.isKey(errorText)) {
BI.Bubbles[b ? "show" : "hide"](this.getName(), errorText, this, {
adjustYOffset: 2
});
this._checkToolTip();
}
},
disableError: function () {
this.disabledError = true;
this._checkError();
},
enableError: function () {
this.disabledError = false;
this._checkError();
},
disableWaterMark: function () {
this.disabledWaterMark = true;
this._checkWaterMark();
},
enableWaterMark: function () {
this.disabledWaterMark = false;
this._checkWaterMark();
},
focus: function () {
this.element.addClass("text-editor-focus");
this.editor.focus();
},
blur: function () {
this.element.removeClass("text-editor-focus");
this.editor.blur();
},
selectAll: function () {
this.editor.selectAll();
},
onKeyDown: function (k) {
this.editor.onKeyDown(k);
},
setValue: function (v) {
BI.Editor.superclass.setValue.apply(this, arguments);
this.editor.setValue(v);
this._checkError();
this._checkWaterMark();
},
getLastValidValue: function () {
return this.editor.getLastValidValue();
},
getLastChangedValue: function () {
return this.editor.getLastChangedValue();
},
getValue: function () {
if (!this.isValid()) {
return BI.trim(this.editor.getLastValidValue());
}
return BI.trim(this.editor.getValue());
},
isEditing: function () {
return this.editor.isEditing();
},
isValid: function () {
return this.editor.isValid();
},
destroyed: function () {
BI.Bubbles.remove(this.getName());
}
});
BI.Editor.EVENT_CHANGE = "EVENT_CHANGE";
BI.Editor.EVENT_FOCUS = "EVENT_FOCUS";
BI.Editor.EVENT_BLUR = "EVENT_BLUR";
BI.Editor.EVENT_CLICK = "EVENT_CLICK";
BI.Editor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN";
BI.Editor.EVENT_SPACE = "EVENT_SPACE";
BI.Editor.EVENT_BACKSPACE = "EVENT_BACKSPACE";
BI.Editor.EVENT_START = "EVENT_START";
BI.Editor.EVENT_PAUSE = "EVENT_PAUSE";
BI.Editor.EVENT_STOP = "EVENT_STOP";
BI.Editor.EVENT_CONFIRM = "EVENT_CONFIRM";
BI.Editor.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM";
BI.Editor.EVENT_VALID = "EVENT_VALID";
BI.Editor.EVENT_ERROR = "EVENT_ERROR";
BI.Editor.EVENT_ENTER = "EVENT_ENTER";
BI.Editor.EVENT_RESTRICT = "EVENT_RESTRICT";
BI.Editor.EVENT_REMOVE = "EVENT_REMOVE";
BI.Editor.EVENT_EMPTY = "EVENT_EMPTY";
BI.shortcut("bi.editor", BI.Editor);

99
src/main/resources/com/fr/fineui/base/single/editor/editor.multifile.js

@ -0,0 +1,99 @@
/**
* 多文件
*
* Created by GUY on 2016/4/13.
* @class BI.MultifileEditor
* @extends BI.Single
* @abstract
*/
BI.MultifileEditor = BI.inherit(BI.Widget, {
_defaultConfig: function () {
var conf = BI.MultifileEditor.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-multifile-editor",
multiple: false,
maxSize: -1, // 1024 * 1024
accept: "",
url: ""
});
},
render: function () {
var self = this, o = this.options;
this.file = BI.createWidget({
type: "bi.file",
cls: "multifile-editor",
width: "100%",
height: "100%",
name: o.name,
url: o.url,
multiple: o.multiple,
accept: o.accept,
maxSize: o.maxSize,
maxLength: o.maxLength,
title: o.title
});
this.file.on(BI.File.EVENT_CHANGE, function () {
self.fireEvent(BI.MultifileEditor.EVENT_CHANGE, arguments);
});
this.file.on(BI.File.EVENT_UPLOADSTART, function () {
self.fireEvent(BI.MultifileEditor.EVENT_UPLOADSTART, arguments);
});
this.file.on(BI.File.EVENT_ERROR, function () {
self.fireEvent(BI.MultifileEditor.EVENT_ERROR, arguments);
});
this.file.on(BI.File.EVENT_PROGRESS, function () {
self.fireEvent(BI.MultifileEditor.EVENT_PROGRESS, arguments);
});
this.file.on(BI.File.EVENT_UPLOADED, function () {
self.fireEvent(BI.MultifileEditor.EVENT_UPLOADED, arguments);
});
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: {
type: "bi.adaptive",
scrollable: false,
items: [this.file]
},
top: 0,
right: 0,
left: 0,
bottom: 0
}]
});
},
_reset: function () {
this.file.reset();
},
setMaxFileLength: function (v) {
this.file.setMaxFileLength(v);
},
select: function () {
this.file.select();
},
getValue: function () {
return this.file.getValue();
},
upload: function () {
this._reset();
this.file.upload();
},
reset: function () {
this._reset();
}
});
BI.MultifileEditor.EVENT_CHANGE = "EVENT_CHANGE";
BI.MultifileEditor.EVENT_UPLOADSTART = "EVENT_UPLOADSTART";
BI.MultifileEditor.EVENT_ERROR = "EVENT_ERROR";
BI.MultifileEditor.EVENT_PROGRESS = "EVENT_PROGRESS";
BI.MultifileEditor.EVENT_UPLOADED = "EVENT_UPLOADED";
BI.shortcut("bi.multifile_editor", BI.MultifileEditor);

252
src/main/resources/com/fr/fineui/base/single/editor/editor.textarea.js

@ -0,0 +1,252 @@
/**
*
* Created by GUY on 2016/1/18.
* @class BI.TextAreaEditor
* @extends BI.Single
*/
BI.TextAreaEditor = BI.inherit(BI.Single, {
_defaultConfig: function () {
return BI.extend(BI.TextAreaEditor.superclass._defaultConfig.apply(), {
baseCls: "bi-textarea-editor",
value: "",
errorText: "",
adjustYOffset: 2,
adjustXOffset: 0,
offsetStyle: "left",
validationChecker: function () {
return true;
},
scrolly: true,
});
},
render: function () {
var o = this.options, self = this;
this.content = BI.createWidget({
type: "bi.layout",
tagName: "textarea",
width: "100%",
height: "100%",
cls: "bi-textarea textarea-editor-content display-block",
css: o.scrolly ? null : {
overflowY: "hidden",
},
});
this.content.element.css({ resize: "none" });
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: {
type: "bi.adaptive",
items: [this.content]
},
left: 4,
right: 4,
top: 2,
bottom: 2
}]
});
this.content.element.on("input propertychange", function (e) {
self._checkError();
self._checkWaterMark();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CHANGE, self.getValue(), self);
self.fireEvent(BI.TextAreaEditor.EVENT_CHANGE);
if (BI.isEmptyString(self.getValue())) {
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, self.getValue(), self);
}
});
this.content.element.focus(function () {
self._checkError();
self._focus();
self.fireEvent(BI.TextAreaEditor.EVENT_FOCUS);
BI.Widget._renderEngine.createElement(document).bind("mousedown." + self.getName(), function (e) {
if (BI.DOM.isExist(self) && !self.element.__isMouseInBounds__(e)) {
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + self.getName());
self.content.element.blur();
}
});
});
this.content.element.blur(function () {
self._setErrorVisible(false);
self._blur();
if (!self._isError()) {
self.fireEvent(BI.TextAreaEditor.EVENT_CONFIRM);
}
self.fireEvent(BI.TextAreaEditor.EVENT_BLUR);
BI.Widget._renderEngine.createElement(document).unbind("mousedown." + self.getName());
});
this.content.element.keydown(function () {
// 水印快速消失
self._checkWaterMark();
});
this.content.element.keyup(function (e) {
self.fireEvent(BI.TextAreaEditor.EVENT_KEY_DOWN, e.keyCode);
});
this.content.element.click(function (e) {
e.stopPropagation();
});
if (BI.isKey(o.value)) {
this.setValue(o.value);
}
if (BI.isNotNull(o.style)) {
this.setStyle(o.style);
}
this._checkWaterMark();
},
_checkWaterMark: function () {
var self = this, o = this.options;
var val = this.getValue();
if (BI.isNotEmptyString(val)) {
this.watermark && this.watermark.destroy();
this.watermark = null;
} else {
if (BI.isNotEmptyString(o.watermark)) {
if (!this.watermark) {
this.watermark = BI.createWidget({
type: "bi.label",
cls: "bi-water-mark textarea-watermark",
textAlign: "left",
whiteSpace: o.scrolly ? "normal" : "nowrap",
title: o.watermark,
text: o.watermark,
invalid: o.invalid,
disabled: o.disabled,
hgap: 6,
vgap: o.height > 24 ? 4 : 2,
height: o.height > 24 ? "" : o.height,
});
this.watermark.element.bind({
mousedown: function (e) {
if (self.isEnabled()) {
self.focus();
} else {
self.blur();
}
e.stopEvent();
},
click: function (e) {
e.stopPropagation();
},
});
BI.createWidget({
type: "bi.absolute",
element: this,
items: [{
el: this.watermark,
left: 0,
top: 0,
right: 0
}]
});
} else {
this.watermark.setText(o.watermark);
this.watermark.setValid(!o.invalid);
this.watermark.setEnable(!o.disabled);
}
}
}
},
_isError: function () {
return this.isEnabled() && !this.options.validationChecker(this.getValue());
},
_checkError: function () {
this._setErrorVisible(this._isError());
},
_focus: function () {
this.content.element.addClass("textarea-editor-focus");
this._checkWaterMark();
if (BI.isEmptyString(this.getValue())) {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this);
}
},
_blur: function () {
this.content.element.removeClass("textarea-editor-focus");
this._checkWaterMark();
},
_setErrorVisible: function (b) {
var o = this.options;
var errorText = o.errorText;
if (BI.isFunction(errorText)) {
errorText = errorText(BI.trim(this.getValue()));
}
if (!this.disabledError && BI.isKey(errorText)) {
BI.Bubbles[b ? "show" : "hide"](this.getName(), errorText, this, {
adjustYOffset: o.adjustYOffset,
adjustXOffset: o.adjustXOffset,
offsetStyle: o.offsetStyle,
});
}
},
_defaultState: function () {
if (BI.isEmptyString(this.getValue())) {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this);
this.fireEvent(BI.TextAreaEditor.EVENT_EMPTY);
}
},
focus: function () {
this._focus();
this.content.element.focus();
},
blur: function () {
this._blur();
this.content.element.blur();
},
getValue: function () {
return this.content.element.val();
},
setValue: function (value) {
this.content.element.val(value);
this._checkError();
this._checkWaterMark();
this._defaultState();
},
setStyle: function (style) {
this.style = style;
this.element.css(style);
this.content.element.css(BI.extend({}, style, {
color: style.color || BI.DOM.getContrastColor(BI.DOM.isRGBColor(style.backgroundColor) ? BI.DOM.rgb2hex(style.backgroundColor) : style.backgroundColor)
}));
},
getStyle: function () {
return this.style;
},
setWatermark: function (v) {
this.options.watermark = v;
this._checkWaterMark();
},
_setValid: function (b) {
BI.TextAreaEditor.superclass._setValid.apply(this, arguments);
// this.content.setValid(b);
// this.watermark && this.watermark.setValid(b);
},
_setEnable: function (b) {
BI.TextAreaEditor.superclass._setEnable.apply(this, [b]);
this.content && (this.content.element[0].disabled = !b);
}
});
BI.TextAreaEditor.EVENT_CHANGE = "EVENT_CHANGE";
BI.TextAreaEditor.EVENT_BLUR = "EVENT_BLUR";
BI.TextAreaEditor.EVENT_FOCUS = "EVENT_FOCUS";
BI.TextAreaEditor.EVENT_CONFIRM = "EVENT_CONFIRM";
BI.TextAreaEditor.EVENT_EMPTY = "EVENT_EMPTY";
BI.TextAreaEditor.EVENT_KEY_DOWN = "EVENT_KEY_DOWN";
BI.shortcut("bi.textarea_editor", BI.TextAreaEditor);

42
src/main/resources/com/fr/fineui/base/single/html/__test__/html.test.js

@ -0,0 +1,42 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/10
*/
describe("HtmlTest", function () {
/**
* test_author_windy
*/
it("html_h1", function () {
var a = BI.Test.createWidget({
type: "bi.html",
text: "<h1>在bi.html标签中使用html原生标签</h1>"
});
expect(a.element.find("h1").length).to.equal(1);
a.destroy();
});
/**
* test_author_windy
*/
it("html测试属性方法", function () {
var a = BI.Test.createWidget({
type: "bi.html",
text: "<h1>在bi.html标签中使用html原生标签</h1>",
height: 200,
width: 200,
value: "1",
highLight: true,
hgap: 10,
vgap: 10,
handler: BI.emptyFn
});
a.setValue("DDDDD");
a.setStyle({"background-color": "red"});
expect(a.text.element.css("background-color")).to.equal("rgb(255, 0, 0)");
a.destroy();
});
});

114
src/main/resources/com/fr/fineui/base/single/html/html.js

@ -0,0 +1,114 @@
/**
* guy 表示一行数据通过position来定位位置的数据
* @class BI.Html
* @extends BI.Single
*/
BI.Html = BI.inherit(BI.Single, {
props: {
baseCls: "bi-html",
textAlign: "left",
whiteSpace: "normal",
lineHeight: null,
handler: null, // 如果传入handler,表示处理文字的点击事件,不是区域的
hgap: 0,
vgap: 0,
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
text: "",
highLight: false,
},
render: function () {
var self = this, o = this.options;
if (o.hgap + o.lgap > 0) {
this.element.css({
"padding-left": (o.hgap + o.lgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.hgap + o.rgap > 0) {
this.element.css({
"padding-right": (o.hgap + o.rgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.vgap + o.tgap > 0) {
this.element.css({
"padding-top": (o.vgap + o.tgap) / BI.pixRatio + BI.pixUnit
});
}
if (o.vgap + o.bgap > 0) {
this.element.css({
"padding-bottom": (o.vgap + o.bgap) / BI.pixRatio + BI.pixUnit
});
}
if (BI.isNumber(o.height)) {
this.element.css({lineHeight: o.height / BI.pixRatio + BI.pixUnit});
}
if (BI.isNumber(o.lineHeight)) {
this.element.css({lineHeight: o.lineHeight / BI.pixRatio + BI.pixUnit});
}
if (BI.isWidthOrHeight(o.maxWidth)) {
this.element.css({maxWidth: o.maxWidth});
}
this.element.css({
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
textOverflow: o.whiteSpace === 'nowrap' ? "ellipsis" : "",
overflow: o.whiteSpace === "nowrap" ? "" : "auto"
});
if (o.handler) {
this.text = BI.createWidget({
type: "bi.layout",
tagName: "span"
});
this.text.element.click(function () {
o.handler(self.getValue());
});
BI.createWidget({
type: "bi.default",
element: this,
items: [this.text]
});
} else {
this.text = this;
}
if (BI.isKey(o.text)) {
this.setText(o.text);
} else if (BI.isKey(o.value)) {
this.setText(o.value);
}
if (o.highLight) {
this.doHighLight();
}
},
doHighLight: function () {
this.text.element.addClass("bi-high-light");
},
unHighLight: function () {
this.text.element.removeClass("bi-high-light");
},
setValue: function (text) {
BI.Html.superclass.setValue.apply(this, arguments);
if (!this.isReadOnly()) {
this.setText(text);
}
},
setStyle: function (css) {
this.text.element.css(css);
},
setText: function (text) {
BI.Html.superclass.setText.apply(this, arguments);
this.options.text = text;
this.text.element.html(text);
}
});
BI.shortcut("bi.html", BI.Html);

21
src/main/resources/com/fr/fineui/base/single/icon/icon.js

@ -0,0 +1,21 @@
/**
* guy 图标
* @class BI.Icon
* @extends BI.Single
*/
BI.Icon = BI.inherit(BI.Single, {
_defaultConfig: function () {
var conf = BI.Icon.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
tagName: "i",
baseCls: (conf.baseCls || "") + " x-icon b-font horizon-center display-block"
});
},
render: function () {
if (BI.isIE9Below && BI.isIE9Below()) {
this.element.addClass("hack");
}
}
});
BI.shortcut("bi.icon", BI.Icon);

23
src/main/resources/com/fr/fineui/base/single/iframe/__test__/iframe.test.js

@ -0,0 +1,23 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/17
*/
describe("IframeTest", function () {
/**
* test_author_windy
*/
it("directionPager", function () {
var a = BI.Test.createWidget({
type: "bi.iframe"
});
a.setSrc("http://www.baidu.com");
a.setName("testIFrame");
expect(a.element.attr("src"), "http://www.baidu.com");
expect(a.getSrc(), "http://www.baidu.com");
expect(a.getName(), "testIFrame");
a.destroy();
});
});

57
src/main/resources/com/fr/fineui/base/single/iframe/iframe.js

@ -0,0 +1,57 @@
/**
* @class BI.Iframe
* @extends BI.Single
* @abstract
* Created by GameJian on 2016/3/2.
*/
BI.Iframe = BI.inherit(BI.Single, {
_defaultConfig: function (config) {
var conf = BI.Iframe.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
tagName: "iframe",
baseCls: (conf.baseCls || "") + " bi-iframe",
src: "",
name: "",
attributes: {},
width: "100%",
height: "100%"
});
},
render: function () {
var self = this;
this.element.on("load", function () {
self.fireEvent("EVENT_LOADED");
});
},
_initProps: function () {
BI.Iframe.superclass._initProps.apply(this, arguments);
var o = this.options;
this.options.attributes = BI.extend({
frameborder: 0,
src: o.src,
name: o.name
}, this.options.attributes);
},
setSrc: function (src) {
this.options.src = src;
this.element.attr("src", src);
},
getSrc: function () {
return this.options.src;
},
setName: function (name) {
this.options.name = name;
this.element.attr("name", name);
},
getName: function () {
return this.options.name;
}
});
BI.shortcut("bi.iframe", BI.Iframe);

23
src/main/resources/com/fr/fineui/base/single/img/__test__/img.test.js

@ -0,0 +1,23 @@
/**
* @author windy
* @version 2.0
* Created by windy on 2020/3/17
*/
describe("ImgTest", function () {
/**
* test_author_windy
*/
it("img", function () {
var a = BI.Test.createWidget({
type: "bi.img",
iconWidth: 36,
iconHeight: 36
});
a.setSrc("test.png");
expect(a.element.attr("src")).to.equal("test.png");
expect(a.getSrc()).to.equal("test.png");
a.destroy();
});
});

40
src/main/resources/com/fr/fineui/base/single/img/img.js

@ -0,0 +1,40 @@
/**
* ͼƬ
*
* Created by GUY on 2016/1/26.
* @class BI.Img
* @extends BI.Single
* @abstract
*/
BI.Img = BI.inherit(BI.Single, {
_defaultConfig: function (config) {
var conf = BI.Img.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
tagName: "img",
baseCls: (conf.baseCls || "") + " bi-img display-block",
src: "",
attributes: config.src ? { src: config.src } : {},
width: "100%",
height: "100%"
});
},
_initProps: function () {
BI.Img.superclass._initProps.apply(this, arguments);
var o = this.options;
this.options.attributes = BI.extend({
src: o.src
}, this.options.attributes);
},
setSrc: function (src) {
this.options.src = src;
this.element.attr("src", src);
},
getSrc: function () {
return this.options.src;
}
});
BI.shortcut("bi.img", BI.Img);

22
src/main/resources/com/fr/fineui/base/single/input/checkbox/checkbox.image.js

@ -0,0 +1,22 @@
/**
* guy
* @extends BI.Single
* @type {*|void|Object}
*/
BI.ImageCheckbox = BI.inherit(BI.IconButton, {
_defaultConfig: function () {
var conf = BI.ImageCheckbox.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-image-checkbox check-box-icon",
selected: false,
handler: BI.emptyFn,
width: 16,
height: 16,
iconWidth: 16,
iconHeight: 16
});
}
});
BI.ImageCheckbox.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE;
BI.shortcut("bi.image_checkbox", BI.ImageCheckbox);

61
src/main/resources/com/fr/fineui/base/single/input/checkbox/checkbox.js

@ -0,0 +1,61 @@
/**
* guy
* @extends BI.Single
* @type {*|void|Object}
*/
BI.Checkbox = BI.inherit(BI.BasicButton, {
props: {
baseCls: "bi-checkbox",
selected: false,
handler: BI.emptyFn,
width: 14,
height: 14,
iconWidth: 14,
iconHeight: 14
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.center_adapt",
items: [{
type: "bi.default",
ref: function (_ref) {
self.checkbox = _ref;
},
cls: "checkbox-content",
width: o.iconWidth,
height: o.iconHeight
}]
};
},
_setEnable: function (enable) {
BI.Checkbox.superclass._setEnable.apply(this, arguments);
if (enable === true) {
this.checkbox.element.removeClass("base-disabled disabled");
} else {
this.checkbox.element.addClass("base-disabled disabled");
}
},
doClick: function () {
BI.Checkbox.superclass.doClick.apply(this, arguments);
if(this.isValid()) {
this.fireEvent(BI.Checkbox.EVENT_CHANGE);
}
},
setSelected: function (b) {
BI.Checkbox.superclass.setSelected.apply(this, arguments);
if (b) {
this.checkbox.element.addClass("bi-high-light-background");
} else {
this.checkbox.element.removeClass("bi-high-light-background");
}
}
});
BI.Checkbox.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.checkbox", BI.Checkbox);

697
src/main/resources/com/fr/fineui/base/single/input/file.js

@ -0,0 +1,697 @@
/**
* 文件
*
* Created by GUY on 2016/1/27.
* @class BI.File
* @extends BI.Single
* @abstract
*/
(function (document) {
/**
* @description normalize input.files. create if not present, add item method if not present
* @param Object generated wrap object
* @return Object the wrap object itself
*/
var F = (function (item) {
return function (input) {
var files = input.files || [input];
if (!files.item) {
files.item = item;
}
return files;
};
})(function (i) {
return this[i];
});
var event = {
/**
* @description add an event via addEventListener or attachEvent
* @param DOMElement the element to add event
* @param String event name without "on" (e.g. "mouseover")
* @param Function the callback to associate as event
* @return Object noswfupload.event
*/
add: document.addEventListener ?
function (node, name, callback) {
node.addEventListener(name, callback, false);
return this;
} :
function (node, name, callback) {
node.attachEvent("on" + name, callback);
return this;
},
/**
* @description remove an event via removeEventListener or detachEvent
* @param DOMElement the element to remove event
* @param String event name without "on" (e.g. "mouseover")
* @param Function the callback associated as event
* @return Object noswfupload.event
*/
del: document.removeEventListener ?
function (node, name, callback) {
node.removeEventListener(name, callback, false);
return this;
} :
function (node, name, callback) {
node.detachEvent("on" + name, callback);
return this;
},
/**
* @description to block event propagation and prevent event default
* @param void generated event or undefined
* @return Boolean false
*/
stop: function (e) {
if (!e) {
if (self.event) {
event.returnValue = !(event.cancelBubble = true);
}
} else {
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
}
return false;
}
};
var sendFile = (function (toString) {
var multipart = function (boundary, name, file) {
return "--".concat(
boundary, CRLF,
"Content-Disposition: form-data; name=\"", name, "\"; filename=\"", _global.encodeURIComponent(file.fileName), "\"", CRLF,
"Content-Type: application/octet-stream", CRLF,
CRLF,
file.getAsBinary(), CRLF,
"--", boundary, "--", CRLF
);
},
isFunction = function (Function) {
return toString.call(Function) === "[object Function]";
},
split = "onabort.onerror.onloadstart.onprogress".split("."),
length = split.length,
CRLF = "\r\n",
xhr = this.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP"),
sendFile;
// FireFox 3+, Safari 4 beta (Chrome 2 beta file is buggy and will not work)
if (xhr.upload || xhr.sendAsBinary) {
sendFile = function (handler, maxSize, width, height) {
var current = handler.current;
if (-1 < maxSize && maxSize < handler.file.fileSize) {
if (isFunction(handler.onerror)) {
handler.onerror();
}
return;
}
for (var
xhr = new XMLHttpRequest,
upload = xhr.upload || {
addEventListener: function (event, callback) {
this["on" + event] = callback;
}
},
i = 0;
i < length;
i++
) {
upload.addEventListener(
split[i].substring(2),
(function (event) {
return function (rpe) {
if (isFunction(handler[event])) {
handler[event](rpe, xhr);
}
};
})(split[i]),
false
);
}
upload.addEventListener(
"load",
function (rpe) {
if (handler.onreadystatechange === false) {
if (isFunction(handler.onload)) {
handler.onload(rpe, xhr);
}
} else {
setTimeout(function () {
if (xhr.readyState === 4) {
if (isFunction(handler.onload)) {
handler.onload(rpe, xhr);
}
} else {
setTimeout(arguments.callee, 15);
}
}, 15);
}
},
false
);
xhr.open("post", BI.appendQuery(handler.url, {
filename: _global.encodeURIComponent(handler.file.fileName),
}), true);
if (!xhr.upload) {
var rpe = { loaded: 0, total: handler.file.fileSize || handler.file.size, simulation: true };
rpe.interval = setInterval(function () {
rpe.loaded += 1024 / 4;
if (rpe.total <= rpe.loaded) {
rpe.loaded = rpe.total;
}
upload.onprogress(rpe);
}, 100);
xhr.onabort = function () {
upload.onabort({});
};
xhr.onerror = function () {
upload.onerror({});
};
xhr.onreadystatechange = function () {
switch (xhr.readyState) {
case 2:
case 3:
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;
upload.onprogress(rpe);
if (199 < xhr.status && xhr.status < 400) {
upload["onload"]({});
var attachO = BI.jsonDecode(xhr.responseText);
attachO.filename = handler.file.fileName;
if (handler.file.type.indexOf("image") != -1) {
attachO.attach_type = "image";
}
handler.attach_array[current] = attachO;
} else {
upload["onerror"]({});
}
break;
}
};
upload.onloadstart(rpe);
} else {
xhr.onreadystatechange = function () {
switch (xhr.readyState) {
case 4:
var attachO = BI.jsonDecode(xhr.responseText);
if (handler.file.type.indexOf("image") != -1) {
attachO.attach_type = "image";
}
attachO.filename = handler.file.fileName;
if (handler.maxLength == 1) {
handler.attach_array[0] = attachO;
// handler.attach_array.push(attachO);
} else {
handler.attach_array[current] = attachO;
}
break;
}
};
if (isFunction(upload.onloadstart)) {
upload.onloadstart();
}
}
var boundary = "AjaxUploadBoundary" + (new Date).getTime();
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
if (handler.file.getAsBinary) {
xhr[xhr.sendAsBinary ? "sendAsBinary" : "send"](multipart(boundary, handler.name, handler.file));
} else {
xhr.setRequestHeader("Content-Type", "multipart/form-data");
// xhr.setRequestHeader("X-Name", handler.name);
// xhr.setRequestHeader("X-File-Name", handler.file.fileName);
var form = new FormData();
form.append("FileData", handler.file);
xhr.send(form);
}
return handler;
};
}
// Internet Explorer, Opera, others
else {
sendFile = function (handler, maxSize, width, height) {
var current = handler.current;
var url = handler.url.concat(-1 === handler.url.indexOf("?") ? "?" : "&", "AjaxUploadFrame=true"),
rpe = {
loaded: 1, total: 100, simulation: true, interval: setInterval(function () {
if (rpe.loaded < rpe.total) {
++rpe.loaded;
}
if (isFunction(handler.onprogress)) {
handler.onprogress(rpe, {});
}
}, 100)
},
onload = function () {
iframe.onreadystatechange = iframe.onload = iframe.onerror = null;
form.parentNode.removeChild(form);
form = null;
clearInterval(rpe.interval);
// rpe.loaded = rpe.total;
try {
var responseText = (iframe.contentWindow.document || iframe.contentWindow.contentDocument).body.innerHTML;
var attachO = BI.jsonDecode(responseText);
if (handler.file.type.indexOf("image") != -1) {
attachO.attach_type = "image";
}
// attachO.fileSize = responseText.length;
try {
// decodeURIComponent特殊字符可能有问题, catch一下,保证能正常上传
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) {
if (isFunction(handler.onerror)) {
handler.onerror(rpe, event || _global.event);
}
}
if (isFunction(handler.onload)) {
handler.onload(rpe, { responseText: responseText });
}
},
target = ["AjaxUpload", (new Date).getTime(), String(Math.random()).substring(2)].join("_");
try { // IE < 8 does not accept enctype attribute ...
var form = document.createElement("<form enctype=\"multipart/form-data\"></form>"),
iframe = handler.iframe || (handler.iframe = document.createElement("<iframe id=\"" + target + "\" name=\"" + target + "\" src=\"" + url + "\"></iframe>"));
} catch (e) {
var form = document.createElement("form"),
iframe = handler.iframe || (handler.iframe = document.createElement("iframe"));
form.setAttribute("enctype", "multipart/form-data");
iframe.setAttribute("name", iframe.id = target);
iframe.setAttribute("src", url);
}
iframe.style.position = "absolute";
iframe.style.left = iframe.style.top = "-10000px";
iframe.onload = onload;
iframe.onerror = function (event) {
if (isFunction(handler.onerror)) {
handler.onerror(rpe, event || _global.event);
}
};
iframe.onreadystatechange = function () {
if (/loaded|complete/i.test(iframe.readyState)) {
onload();
// wei : todo,将附件信息放到handler.attach
} else if (isFunction(handler.onloadprogress)) {
if (rpe.loaded < rpe.total) {
++rpe.loaded;
}
handler.onloadprogress(rpe, {
readyState: {
loading: 2,
interactive: 3,
loaded: 4,
complete: 4
}[iframe.readyState] || 1
});
}
};
form.setAttribute("action", handler.url + "&filename=" + _global.encodeURIComponent(handler.file.fileName));
form.setAttribute("target", iframe.id);
form.setAttribute("method", "post");
form.appendChild(handler.file);
form.style.display = "none";
if (isFunction(handler.onloadstart)) {
handler.onloadstart(rpe, {});
}
with (document.body || document.documentElement) {
appendChild(iframe);
appendChild(form);
form.submit();
}
return handler;
};
}
xhr = null;
return sendFile;
})(Object.prototype.toString);
var sendFiles = function (handler, maxSize, width, height) {
var length = handler.files.length,
i = 0,
onload = handler.onload,
onloadstart = handler.onloadstart;
handler.current = 0;
handler.total = 0;
handler.sent = 0;
while (handler.current < length) {
handler.total += (handler.files[handler.current].fileSize || handler.files[handler.current].size);
handler.current++;
}
handler.current = 0;
if (length && handler.files[0].fileSize !== -1) {
handler.file = handler.files[handler.current];
sendFile(handler, maxSize, width, height).onload = function (rpe, xhr) {
handler.onloadstart = null;
handler.sent += (handler.files[handler.current].fileSize || handler.files[handler.current].size);
if (++handler.current < length) {
handler.file = handler.files[handler.current];
sendFile(handler, maxSize, width, height).onload = arguments.callee;
} else if (onload) {
handler.onloadstart = onloadstart;
handler.onload = onload;
handler.onload(rpe, xhr);
}
};
} else if (length) {
handler.total = length * 100;
handler.file = handler.files[handler.current];
sendFile(handler, maxSize, width, height).onload = function (rpe, xhr) {
var callee = arguments.callee;
handler.onloadstart = null;
handler.sent += 100;
if (++handler.current < length) {
if (/\b(chrome|safari)\b/i.test(navigator.userAgent)) {
handler.iframe.parentNode.removeChild(handler.iframe);
handler.iframe = null;
}
setTimeout(function () {
handler.file = handler.files[handler.current];
sendFile(handler, maxSize, width, height).onload = callee;
}, 15);
} else if (onload) {
setTimeout(function () {
handler.iframe.parentNode.removeChild(handler.iframe);
handler.iframe = null;
handler.onloadstart = onloadstart;
handler.onload = onload;
handler.onload(rpe, xhr);
}, 15);
}
};
}
return handler;
};
var r1 = /\.([^.]+)$/; // .png
var r2 = /\/([^/]+)$/; // image/png
/**
* 校验文件类型是否合法,同时兼容旧版形式
* @param fileName
* @param fileType
* @returns {boolean}
*/
var fileTypeValidate = function (fileName, fileType) {
if (!fileType) {
return true;
}
var mimes = fileType.split(",");
if (mimes[0] === fileType) {
mimes = (fileType + "").split(";");
}
return BI.some(mimes, function (index, mime) {
var matches;
if (matches = mime.match(r1)) {
return fileName.toLowerCase().indexOf(matches[1]) > -1;
}
if (matches = mime.match(r2)) {
return matches[1] === "*" ? true : fileName.toLowerCase().indexOf(matches[1]) > -1;
}
});
};
BI.File = BI.inherit(BI.Widget, {
_defaultConfig: function () {
var conf = BI.File.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-file display-block",
tagName: "input",
attributes: {
type: "file"
},
name: "",
url: "",
multiple: true,
accept: "", // .png,.pdf,image/jpg,image/* 等
maxSize: -1, // 1024 * 1024
maxLength: -1 // 无限制, 与multiple配合使用
});
},
render: function () {
var self = this, o = this.options;
if (o.multiple === true) {
this.element.attr("multiple", "multiple");
}
this.element.attr("name", o.name || this.getName());
this.element.attr("title", o.title || "");
this.element.attr("accept", o.accept);
},
created: function () {
var self = this, o = this.options;
// create the noswfupload.wrap Object
// wrap.maxSize 文件大小限制
// wrap.maxLength 文件个数限制
var _wrap = this.wrap = this._wrap(this.element[0], o.maxSize);
// fileType could contain whatever text but filter checks *.{extension}
// if present
// handlers
_wrap.onloadstart = function (rpe, xhr) {
// BI.Msg.toast("loadstart");
self.fireEvent(BI.File.EVENT_UPLOADSTART, arguments);
};
_wrap.onprogress = function (rpe, xhr) {
// BI.Msg.toast("onprogress");
// percent for each bar
// fileSize is -1 only if browser does not support file info access
// this if splits recent browsers from others
if (this.file.fileSize !== -1) {
// simulation property indicates when the progress event is fake
if (rpe.simulation) {
} else {
}
} else {
// if fileSIze is -1 browser is using an iframe because it does
// not support
// files sent via Ajax (XMLHttpRequest)
// We can still show some information
}
self.fireEvent(BI.File.EVENT_PROGRESS, {
file: this.file,
total: rpe.total,
loaded: rpe.loaded,
simulation: rpe.simulation
});
};
// generated if there is something wrong during upload
_wrap.onerror = function () {
// just inform the user something was wrong
self.fireEvent(BI.File.EVENT_ERROR);
};
// generated when every file has been sent (one or more, it does not
// matter)
_wrap.onload = function (rpe, xhr) {
var self_ = this;
// just show everything is fine ...
// ... and after a second reset the component
setTimeout(function () {
self_.clean(); // remove files from list
self_.hide(); // hide progress bars and enable input file
// enable again the submit button/element
}, 100);
if (200 > xhr.status || xhr.status > 399) {
BI.Msg.toast(BI.i18nText("BI-Upload_File_Error"), { level: "error" });
self.fireEvent(BI.File.EVENT_ERROR);
return;
}
var error = BI.some(_wrap.attach_array, function (index, attach) {
if (attach.errorCode) {
BI.Msg.toast(BI.i18nText(attach.errorMsg), { level: "error" });
self.fireEvent(BI.File.EVENT_ERROR, attach);
return true;
}
});
!error && self.fireEvent(BI.File.EVENT_UPLOADED);
};
_wrap.url = o.url;
_wrap.fileType = o.accept; // 文件类型限制
_wrap.attach_array = [];
_wrap.attach_names = [];
_wrap.attachNum = 0;
},
_events: function (wrap) {
var self = this, o = this.options;
event.add(wrap.dom.input, "change", function () {
event.del(wrap.dom.input, "change", arguments.callee);
var input = wrap.dom.input.cloneNode(true);
var files = F(wrap.dom.input);
if (o.maxLength !== -1 && o.maxLength < files.length) {
self.fireEvent(BI.File.EVENT_ERROR, {
errorType: 2
});
} else {
for (var i = 0; i < files.length; i++) {
var item = files.item(i);
var tempFile = item.value || item.name;
var value = item.fileName || (item.fileName = tempFile.split("\\").pop()),
ext = -1 !== value.indexOf(".") ? value.split(".").pop().toLowerCase() : "unknown",
size = item.fileSize || item.size;
var validateFileType = fileTypeValidate(value, wrap.fileType);
if (!validateFileType) {
// 文件类型不支持
BI.Msg.toast(BI.i18nText("BI-Upload_File_Type_Error"), { level: "error" });
self.fireEvent(BI.File.EVENT_ERROR, {
errorType: 0,
file: item
});
} else if (wrap.maxSize !== -1 && size && wrap.maxSize < size) {
// 文件大小不支持
BI.Msg.toast(BI.i18nText("BI-Upload_File_Size_Error"), { level: "error" });
self.fireEvent(BI.File.EVENT_ERROR, {
errorType: 1,
file: item
});
} else {
wrap.files.unshift(item);
// BI.Msg.toast(value);
}
}
}
wrap.files.length > 0 && self.fireEvent(BI.File.EVENT_CHANGE, {
files: wrap.files
});
input.value = "";
wrap.dom.input.parentNode.replaceChild(input, wrap.dom.input);
wrap.dom.input = input;
event.add(wrap.dom.input, "change", arguments.callee);
});
return wrap;
},
_wrap: function () {
var self = this, o = this.options;
// be sure input accept multiple files
var input = this.element[0];
if (o.multiple === true) {
this.element.attr("multiple", "multiple");
}
input.value = "";
// wrap Object
return this._events({
// DOM namespace
dom: {
input: input, // input file
disabled: false // internal use, checks input file state
},
name: input.name, // name to send for each file ($_FILES[{name}] in the server)
// maxSize is the maximum amount of bytes for each file
maxSize: o.maxSize ? o.maxSize >> 0 : -1,
maxLength: o.maxLength,
files: [], // file list
// remove every file from the noswfupload component
clean: function () {
this.files = [];
},
// upload one file a time (which make progress possible rather than all files in one shot)
// the handler is an object injected into the wrap one, could be the wrap itself or
// something like {onload:function(){alert("OK")},onerror:function(){alert("Error")}, etc ...}
upload: function (handler) {
if (handler) {
for (var key in handler) {
this[key] = handler[key];
}
}
sendFiles(this, this.maxSize);
return this;
},
// hide progress bar (total + current) and enable files selection
hide: function () {
if (this.dom.disabled) {
this.dom.disabled = false;
this.dom.input.removeAttribute("disabled");
}
},
// show progress bar and disable file selection (used during upload)
// total and current are pixels used to style bars
// totalProp and currentProp are properties to change, "height" by default
show: function (total, current, totalProp, currentProp) {
if (!this.dom.disabled) {
this.dom.disabled = true;
this.dom.input.setAttribute("disabled", "disabled");
}
}
});
},
setMaxFileLength: function(v) {
this.options.maxLength = v;
if (this.wrap) {
this.wrap.maxLength = v;
}
},
select: function () {
this.wrap && BI.Widget._renderEngine.createElement(this.wrap.dom.input).click();
},
upload: function (handler) {
this.wrap && this.wrap.upload(handler);
},
getValue: function () {
return this.wrap ? this.wrap.attach_array : [];
},
reset: function () {
if (this.wrap) {
this.wrap.attach_array = [];
this.wrap.attach_names = [];
this.wrap.attachNum = 0;
}
},
_setEnable: function (enable) {
BI.File.superclass._setEnable.apply(this, arguments);
if (enable === true) {
this.element.attr("disabled", "disabled");
} else {
this.element.removeAttr("disabled");
}
}
});
BI.File.EVENT_CHANGE = "EVENT_CHANGE";
BI.File.EVENT_UPLOADSTART = "EVENT_UPLOADSTART";
BI.File.EVENT_ERROR = "EVENT_ERROR";
BI.File.EVENT_PROGRESS = "EVENT_PROGRESS";
BI.File.EVENT_UPLOADED = "EVENT_UPLOADED";
BI.shortcut("bi.file", BI.File);
})(_global.document || {});

315
src/main/resources/com/fr/fineui/base/single/input/input.js

@ -0,0 +1,315 @@
/**
* guy
* @class BI.Input 一个button和一行数 组成的一行listitem
* @extends BI.Single
* @type {*|void|Object}
*/
BI.Input = BI.inherit(BI.Single, {
_defaultConfig: function () {
var conf = BI.Input.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-input display-block overflow-dot",
tagName: "input",
validationChecker: BI.emptyFn,
quitChecker: BI.emptyFn, // 按确定键能否退出编辑
allowBlank: false
});
},
render: function () {
var self = this;
var ctrlKey = false;
var keyCode = null;
var inputEventValid = false;
var _keydown = BI.debounce(function (keyCode) {
self.onKeyDown(keyCode, ctrlKey);
self._keydown_ = false;
}, 300);
var _clk = BI.debounce(BI.bind(this._click, this), BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
this._focusDebounce = BI.debounce(BI.bind(this._focus, this), BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
this._blurDebounce = BI.debounce(BI.bind(this._blur, this), BI.EVENT_RESPONSE_TIME, {
"leading": true,
"trailing": false
});
this.element
.keydown(function (e) {
inputEventValid = false;
ctrlKey = e.ctrlKey || e.metaKey; // mac的cmd支持一下
keyCode = e.keyCode;
self.fireEvent(BI.Input.EVENT_QUICK_DOWN, arguments);
})
.keyup(function (e) {
keyCode = null;
if (!(inputEventValid && e.keyCode === BI.KeyCode.ENTER)) {
self._keydown_ = true;
_keydown(e.keyCode);
}
})
.on("input propertychange", function (e) {
// 输入内容全选并直接删光,如果按键没放开就失去焦点不会触发keyup,被focusout覆盖了
// 其中propertychange在元素属性发生改变的时候就会触发 是为了兼容IE8
// 通过keyCode判断会漏掉输入法点击输入(右键粘贴暂缓)
var originalEvent = e.originalEvent;
if (BI.isNull(originalEvent.propertyName) || originalEvent.propertyName === "value") {
inputEventValid = true;
self._keydown_ = true;
_keydown(keyCode);
keyCode = null;
}
})
.click(function (e) {
e.stopPropagation();
_clk();
})
.mousedown(function (e) {
self.element.val(self.element.val());
})
.focus(function (e) { // 可以不用冒泡
self._focusDebounce();
})
.blur(function (e) {
// DEC-14919 IE11在浏览器重新获得焦点之后会先触发focusout再触发focus,要保持先获得焦点再失去焦点的顺序不变,因此采用blur
self._blurDebounce();
});
if (BI.isKey(this.options.value) || BI.isEmptyString(this.options.value)) {
this.setValue(this.options.value);
}
},
_focus: function () {
this.element.addClass("bi-input-focus");
this._checkValidationOnValueChange();
this._isEditing = true;
if (this.getValue() == "") {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_EMPTY);
}
this.fireEvent(BI.Input.EVENT_FOCUS);
},
_blur: function () {
var self = this;
if (self._keydown_ === true) {
BI.delay(blur, 300);
} else {
blur();
}
function blur () {
if (!self.isValid() && self.options.quitChecker.apply(self, [BI.trim(self.getValue())]) !== false) {
self.element.val(self._lastValidValue ? self._lastValidValue : "");
self._checkValidationOnValueChange();
self._defaultState();
}
self.element.removeClass("bi-input-focus");
self._isEditing = false;
self._start = false;
if (self.isValid()) {
var lastValidValue = self._lastValidValue;
self._lastValidValue = self.getValue();
self.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CONFIRM, self.getValue(), self);
self.fireEvent(BI.Input.EVENT_CONFIRM);
if (self._lastValidValue !== lastValidValue) {
self.fireEvent(BI.Input.EVENT_CHANGE_CONFIRM);
}
}
self.fireEvent(BI.Input.EVENT_BLUR);
}
},
_click: function () {
if (this._isEditing !== true) {
this.selectAll();
this.fireEvent(BI.Input.EVENT_CLICK);
}
},
onClick: function () {
this._click();
},
onKeyDown: function (keyCode, ctrlKey) {
if (!this.isValid() || BI.trim(this._lastChangedValue) !== BI.trim(this.getValue())) {
this._checkValidationOnValueChange();
}
if (this.isValid() && BI.trim(this.getValue()) !== "") {
if (BI.trim(this.getValue()) !== this._lastValue && (!this._start || this._lastValue == null || this._lastValue === "")
|| (this._pause === true && !/(\s|\u00A0)$/.test(this.getValue()))) {
this._start = true;
this._pause = false;
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_START);
}
}
if (keyCode == BI.KeyCode.ENTER) {
if (this.isValid() || this.options.quitChecker.apply(this, [BI.trim(this.getValue())]) !== false) {
this.blur();
this.fireEvent(BI.Input.EVENT_ENTER);
} else {
this.fireEvent(BI.Input.EVENT_RESTRICT);
}
}
if (keyCode == BI.KeyCode.SPACE) {
this.fireEvent(BI.Input.EVENT_SPACE);
}
if (keyCode == BI.KeyCode.BACKSPACE && this._lastValue == "") {
this.fireEvent(BI.Input.EVENT_REMOVE);
}
if (keyCode == BI.KeyCode.BACKSPACE || keyCode == BI.KeyCode.DELETE) {
this.fireEvent(BI.Input.EVENT_BACKSPACE);
}
this.fireEvent(BI.Input.EVENT_KEY_DOWN, arguments);
// _valueChange中会更新_lastValue, 这边缓存用以后续STOP事件服务
var lastValue = this._lastValue;
if(BI.trim(this.getValue()) !== BI.trim(this._lastValue || "")){
this._valueChange();
}
if (BI.isEndWithBlank(this.getValue())) {
this._pause = true;
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this);
this.fireEvent(BI.Input.EVENT_PAUSE);
this._defaultState();
} else if ((keyCode === BI.KeyCode.BACKSPACE || keyCode === BI.KeyCode.DELETE) &&
BI.trim(this.getValue()) === "" && (lastValue !== null && BI.trim(lastValue) !== "")) {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STOPEDIT, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_STOP);
}
},
// 初始状态
_defaultState: function () {
if (this.getValue() == "") {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_EMPTY);
}
this._lastValue = this.getValue();
this._lastSubmitValue = null;
},
_valueChange: function () {
if (this.isValid() && BI.trim(this.getValue()) !== this._lastSubmitValue) {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.CHANGE, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_CHANGE);
this._lastSubmitValue = BI.trim(this.getValue());
}
if (this.getValue() == "") {
this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY, this.getValue(), this);
this.fireEvent(BI.Input.EVENT_EMPTY);
}
this._lastValue = this.getValue();
},
_checkValidationOnValueChange: function () {
var o = this.options;
var v = this.getValue();
this.setValid(
(o.allowBlank === true && BI.trim(v) == "") || (
BI.isNotEmptyString(BI.trim(v)) && o.validationChecker.apply(this, [BI.trim(v)]) !== false
)
);
},
focus: function () {
if (!this.element.is(":visible")) {
throw new Error("input输入框在不可见下不能focus");
}
if (!this._isEditing === true) {
this.element.focus();
this.selectAll();
}
},
blur: function () {
if (!this.element.is(":visible")) {
throw new Error("input输入框在不可见下不能blur");
}
if (this._isEditing === true) {
this.element.blur();
this._blurDebounce();
}
},
selectAll: function () {
if (!this.element.is(":visible")) {
throw new Error("input输入框在不可见下不能select");
}
this.element.select();
this._isEditing = true;
},
setValue: function (textValue) {
this.element.val(textValue);
BI.nextTick(BI.bind(function () {
this._checkValidationOnValueChange();
this._defaultState();
if (this.isValid()) {
this._lastValidValue = this._lastSubmitValue = this.getValue();
}
}, this));
},
getValue: function () {
return this.element.val() || "";
},
isEditing: function () {
return this._isEditing;
},
getLastValidValue: function () {
return this._lastValidValue;
},
getLastChangedValue: function () {
return this._lastChangedValue;
},
_setValid: function () {
BI.Input.superclass._setValid.apply(this, arguments);
if (this.isValid()) {
this._lastChangedValue = this.getValue();
this.element.removeClass("bi-input-error");
this.fireEvent(BI.Input.EVENT_VALID, BI.trim(this.getValue()), this);
} else {
if (this._lastChangedValue === this.getValue()) {
this._lastChangedValue = null;
}
this.element.addClass("bi-input-error");
this.fireEvent(BI.Input.EVENT_ERROR, BI.trim(this.getValue()), this);
}
},
_setEnable: function (b) {
BI.Input.superclass._setEnable.apply(this, [b]);
this.element[0].disabled = !b;
}
});
BI.Input.EVENT_CHANGE = "EVENT_CHANGE";
BI.Input.EVENT_FOCUS = "EVENT_FOCUS";
BI.Input.EVENT_CLICK = "EVENT_CLICK";
BI.Input.EVENT_BLUR = "EVENT_BLUR";
BI.Input.EVENT_KEY_DOWN = "EVENT_KEY_DOWN";
BI.Input.EVENT_QUICK_DOWN = "EVENT_QUICK_DOWN";
BI.Input.EVENT_SPACE = "EVENT_SPACE";
BI.Input.EVENT_BACKSPACE = "EVENT_BACKSPACE";
BI.Input.EVENT_START = "EVENT_START";
BI.Input.EVENT_PAUSE = "EVENT_PAUSE";
BI.Input.EVENT_STOP = "EVENT_STOP";
BI.Input.EVENT_CHANGE_CONFIRM = "EVENT_CHANGE_CONFIRM";
BI.Input.EVENT_CONFIRM = "EVENT_CONFIRM";
BI.Input.EVENT_REMOVE = "EVENT_REMOVE";
BI.Input.EVENT_EMPTY = "EVENT_EMPTY";
BI.Input.EVENT_VALID = "EVENT_VALID";
BI.Input.EVENT_ERROR = "EVENT_ERROR";
BI.Input.EVENT_ENTER = "EVENT_ENTER";
BI.Input.EVENT_RESTRICT = "EVENT_RESTRICT";
BI.shortcut("bi.input", BI.Input);

29
src/main/resources/com/fr/fineui/base/single/input/radio/radio.image.js

@ -0,0 +1,29 @@
/**
* guy
* @extends BI.Single
* @type {*|void|Object}
*/
BI.ImageRadio = BI.inherit(BI.IconButton, {
_defaultConfig: function () {
var conf = BI.ImageRadio.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
baseCls: (conf.baseCls || "") + " bi-radio radio-icon",
selected: false,
handler: BI.emptyFn,
width: 16,
height: 16,
iconWidth: 16,
iconHeight: 16
});
},
doClick: function () {
BI.ImageRadio.superclass.doClick.apply(this, arguments);
if(this.isValid()) {
this.fireEvent(BI.ImageRadio.EVENT_CHANGE);
}
}
});
BI.ImageRadio.EVENT_CHANGE = BI.IconButton.EVENT_CHANGE;
BI.shortcut("bi.image_radio", BI.ImageRadio);

62
src/main/resources/com/fr/fineui/base/single/input/radio/radio.js

@ -0,0 +1,62 @@
/**
* guy
* @extends BI.Single
* @type {*|void|Object}
*/
BI.Radio = BI.inherit(BI.BasicButton, {
props: {
baseCls: "bi-radio",
selected: false,
handler: BI.emptyFn,
width: 14,
height: 14,
iconWidth: 14,
iconHeight: 14
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.center_adapt",
element: this.element,
items: [{
type: "bi.layout",
cls: "radio-content",
ref: function (_ref) {
self.radio = _ref;
},
width: o.iconWidth,
height: o.iconHeight
}]
};
},
_setEnable: function (enable) {
BI.Radio.superclass._setEnable.apply(this, arguments);
if (enable === true) {
this.radio.element.removeClass("base-disabled disabled");
} else {
this.radio.element.addClass("base-disabled disabled");
}
},
doClick: function () {
BI.Radio.superclass.doClick.apply(this, arguments);
if(this.isValid()) {
this.fireEvent(BI.Radio.EVENT_CHANGE);
}
},
setSelected: function (b) {
BI.Radio.superclass.setSelected.apply(this, arguments);
if (b) {
this.radio.element.addClass("bi-high-light-background");
} else {
this.radio.element.removeClass("bi-high-light-background");
}
}
});
BI.Radio.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.radio", BI.Radio);

377
src/main/resources/com/fr/fineui/base/single/label/abstract.label.js

@ -0,0 +1,377 @@
/**
* Created by dailer on 2019/6/19.
*/
!(function () {
BI.AbstractLabel = BI.inherit(BI.Single, {
_defaultConfig: function (props) {
var conf = BI.AbstractLabel.superclass._defaultConfig.apply(this, arguments);
return BI.extend(conf, {
textAlign: "center",
whiteSpace: "nowrap", // normal or nowrap
textWidth: null,
textHeight: null,
hgap: 0,
vgap: 0,
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
highLight: false,
handler: null
});
},
_createJson: function () {
var o = this.options;
return {
type: "bi.text",
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
lineHeight: o.textHeight,
maxWidth: "100%",
text: o.text,
value: o.value,
py: o.py,
keyword: o.keyword,
highLight: o.highLight,
handler: o.handler
};
},
render: function () {
if (this.options.textAlign === "center") {
this._createCenterEl();
} else {
this._createNotCenterEl();
}
},
_createCenterEl: function () {
var o = this.options;
var json = this._createJson();
json.textAlign = "left";
if (BI.isNumber(o.width) && o.width > 0) {
if (BI.isNumber(o.textWidth) && o.textWidth > 0) {
json.maxWidth = o.textWidth;
if (BI.isNumber(o.height) && o.height > 0) { // 1.1
BI.createWidget({
type: "bi.center_adapt",
height: o.height,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
BI.createWidget({ // 1.2
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
if (o.whiteSpace === "normal") { // 1.3
BI.extend(json, {
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
});
this.text = BI.createWidget(json);
BI.createWidget({
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
element: this,
items: [this.text]
});
return;
}
if (BI.isNumber(o.height) && o.height > 0) { // 1.4
this.element.css({
"line-height": o.height / BI.pixRatio + BI.pixUnit
});
json.textAlign = o.textAlign;
this.text = BI.createWidget(BI.extend(json, {
element: this,
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
return;
}
BI.extend(json, { // 1.5
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
maxWidth: "100%"
});
this.text = BI.createWidget(json);
BI.createWidget({
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
element: this,
items: [this.text]
});
return;
}
if (BI.isNumber(o.textWidth) && o.textWidth > 0) { // 1.6
json.maxWidth = o.textWidth;
BI.createWidget({
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
if (o.whiteSpace === "normal") { // 1.7
BI.extend(json, {
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
});
this.text = BI.createWidget(json);
BI.createWidget({
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: true,
element: this,
items: [this.text]
});
return;
}
if (BI.isNumber(o.height) && o.height > 0) { // 1.8
this.element.css({
"line-height": o.height / BI.pixRatio + BI.pixUnit
});
json.textAlign = o.textAlign;
this.text = BI.createWidget(BI.extend(json, {
element: this,
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
return;
}
this.text = BI.createWidget(BI.extend(json, {
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
BI.createWidget({
type: "bi.center_adapt",
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
element: this,
items: [this.text]
});
},
_createNotCenterEl: function () {
var o = this.options;
var adaptLayout = "bi.vertical_adapt";
var json = this._createJson();
if (BI.isNumber(o.width) && o.width > 0) {
if (BI.isNumber(o.textWidth) && o.textWidth > 0) {
json.maxWidth = o.textWidth;
if (BI.isNumber(o.height) && o.height > 0) { // 2.1
BI.createWidget({
type: adaptLayout,
horizontalAlign: o.textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
height: o.height,
scrollable: o.whiteSpace === "normal",
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
BI.createWidget({ // 2.2
type: adaptLayout,
horizontalAlign: o.textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
if (BI.isNumber(o.height) && o.height > 0) { // 2.3
if (o.whiteSpace !== "normal") {
this.element.css({
"line-height": (o.height - (o.vgap * 2)) / BI.pixRatio + BI.pixUnit
});
}
this.text = BI.createWidget(BI.extend(json, {
element: this,
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
return;
}
json.maxWidth = o.width - 2 * o.hgap - o.lgap - o.rgap;
BI.createWidget({ // 2.4
type: adaptLayout,
horizontalAlign: o.textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
element: this,
items: [{
el: (this.text = BI.createWidget(json))
}]
});
return;
}
if (BI.isNumber(o.textWidth) && o.textWidth > 0) {
json.maxWidth = o.textWidth;
BI.createWidget({ // 2.5
type: adaptLayout,
horizontalAlign: o.textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
scrollable: o.whiteSpace === "normal",
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap,
element: this,
items: [
{
el: (this.text = BI.createWidget(json))
}
]
});
return;
}
if (BI.isNumber(o.height) && o.height > 0) {
if (o.whiteSpace !== "normal") {
this.element.css({
"line-height": (o.height - (o.vgap * 2)) / BI.pixRatio + BI.pixUnit
});
}
this.text = BI.createWidget(BI.extend(json, { // 2.6
element: this,
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
return;
}
this.text = BI.createWidget(BI.extend(json, {
hgap: o.hgap,
vgap: o.vgap,
lgap: o.lgap,
rgap: o.rgap,
tgap: o.tgap,
bgap: o.bgap
}));
BI.createWidget({
type: adaptLayout,
horizontalAlign: o.textAlign,
columnSize: ["auto"], // important! 让文字在flex布局下shrink为1
element: this,
scrollable: o.whiteSpace === "normal",
items: [this.text]
});
},
doRedMark: function () {
this.text.doRedMark.apply(this.text, arguments);
},
unRedMark: function () {
this.text.unRedMark.apply(this.text, arguments);
},
doHighLight: function () {
this.text.doHighLight.apply(this.text, arguments);
},
unHighLight: function () {
this.text.unHighLight.apply(this.text, arguments);
},
setText: function (v) {
this.options.text = v;
this.text.setText(v);
},
getText: function () {
return this.options.text;
},
setStyle: function (css) {
this.text.setStyle(css);
},
setValue: function (v) {
BI.AbstractLabel.superclass.setValue.apply(this, arguments);
if (!this.isReadOnly()) {
this.text.setValue(v);
}
}
});
}());

25
src/main/resources/com/fr/fineui/base/single/label/html.label.js

@ -0,0 +1,25 @@
/**
* Created by GUY on 2015/6/26.
*/
BI.HtmlLabel = BI.inherit(BI.AbstractLabel, {
props: {
baseCls: "bi-html-label"
},
_createJson: function () {
var o = this.options;
return {
type: "bi.html",
textAlign: o.textAlign,
whiteSpace: o.whiteSpace,
lineHeight: o.textHeight,
text: o.text,
value: o.value,
handler: o.handler
};
}
});
BI.shortcut("bi.html_label", BI.HtmlLabel);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save