Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47f4fce2ab | ||
|
|
1c3541cc05 | ||
|
|
5f05734e46 | ||
|
|
e5ab665c57 | ||
|
|
c3417792d9 | ||
|
|
174ed02058 | ||
|
|
e944409f5e | ||
|
|
713ccf26e2 | ||
|
|
3ee87354c8 | ||
|
|
e942bcf033 | ||
|
|
dea394a93d | ||
|
|
54ce56564b | ||
|
|
ae1d354d4c | ||
|
|
20c17d6077 | ||
|
|
abb951a889 | ||
|
|
72a1585e26 | ||
|
|
38c84fbdc6 | ||
|
|
d67ff9bf2c | ||
|
|
986e5bb9bd | ||
|
|
ba05c28bcf | ||
|
|
71ff337ee0 | ||
|
|
9e2c685870 | ||
|
|
75d1872b02 | ||
|
|
9cf4b8935f | ||
|
|
aa5d2b9fe8 | ||
|
|
76b3c381c3 | ||
|
|
c923dae619 | ||
|
|
7b0902477d | ||
|
|
126c4bc8c3 | ||
|
|
a9e300d063 | ||
|
|
05331eb99d | ||
|
|
adbf5b05ec | ||
|
|
bf6c66a77b | ||
|
|
3fc965e0e7 | ||
|
|
7e10d16f6c | ||
|
|
d9d63cc09d | ||
|
|
dcd6f2252f | ||
|
|
7922cabb5b | ||
|
|
900de5db80 | ||
|
|
bf49b35978 | ||
|
|
0df49fcfe8 | ||
|
|
fcde715553 | ||
|
|
08ca506cfb | ||
|
|
b757c5b7b3 | ||
|
|
9c927e621d | ||
|
|
8ebf1504de | ||
|
|
e315357dd2 | ||
|
|
7b96954b2f | ||
|
|
0c3cac9537 | ||
|
|
2a5065420c | ||
|
|
3bc161366a | ||
|
|
3be95bc577 | ||
|
|
8c5d7fd336 | ||
|
|
d21284f325 | ||
|
|
e7a0f97315 | ||
|
|
2b20edeff8 | ||
|
|
304da21e6d | ||
|
|
8dfa1834e3 | ||
|
|
d01f35deeb | ||
|
|
a4da433a6d | ||
|
|
fbddde13c3 | ||
|
|
eb7ef55aab | ||
|
|
6c47f48e06 | ||
|
|
9e67d8272e | ||
|
|
fbe8e6997e | ||
|
|
8c912f3906 | ||
|
|
8caf674f94 | ||
|
|
7d94c9fcb4 | ||
|
|
ff878564e4 | ||
|
|
da5cca0b90 | ||
|
|
e27297311c | ||
|
|
5593a7e7e6 | ||
|
|
a2a75a7fce | ||
|
|
4ca9cb9bab | ||
|
|
b743caeb6c | ||
|
|
2565627e7e | ||
|
|
d4096da4f5 | ||
|
|
afb19d8ba6 | ||
|
|
e7805c988b | ||
|
|
911fb59e56 | ||
|
|
080c66d12b | ||
|
|
9dc5db7557 | ||
|
|
370c047ff8 | ||
|
|
7d6cdabc09 | ||
|
|
1c235dc7f6 | ||
|
|
ff67062c7f | ||
|
|
91dd624048 | ||
|
|
ce18a9e86d | ||
|
|
d2e5bd1e43 | ||
|
|
c7c7d40e4d | ||
|
|
e0af01d16c | ||
|
|
58673fa502 | ||
|
|
a1523e3bfd | ||
|
|
53fbd6c974 | ||
|
|
f8165653b5 | ||
|
|
2c31fc9e48 | ||
|
|
1e665986a0 | ||
|
|
2eec1a116c | ||
|
|
fed4f1077d | ||
|
|
d76c57a691 | ||
|
|
90de1067d8 | ||
|
|
51b8bf85aa | ||
|
|
d74166f719 | ||
|
|
0eeb5b8930 | ||
|
|
f2b69c99e6 | ||
|
|
f96aeca790 | ||
|
|
27283e75c3 | ||
|
|
6bc852918e | ||
|
|
fd3ffcbd89 | ||
|
|
ea23976fde | ||
|
|
b46735fd78 | ||
|
|
d4b353d8f2 | ||
|
|
580ba66114 | ||
|
|
77d41b279d | ||
|
|
9ce273c359 | ||
|
|
36738bca90 | ||
|
|
dfd65fbeb8 | ||
|
|
49001edac8 | ||
|
|
7b4c8f89e1 | ||
|
|
b1f4952cde | ||
|
|
999cd996fd | ||
|
|
55a4bfe70c | ||
|
|
bfba5ebbfa | ||
|
|
bff44efcb0 | ||
|
|
7b36d1f60c | ||
|
|
54e05bae60 | ||
|
|
50515e1aff | ||
|
|
d1b440fc0d | ||
|
|
cd3dbd775b | ||
|
|
36e59c99f9 | ||
|
|
94aafdcf7e | ||
|
|
17dd48e51d | ||
|
|
1f9b26ae23 | ||
|
|
79138d5d2f | ||
|
|
65d01c2cee | ||
|
|
202bf1ce65 | ||
|
|
8a18c46b84 | ||
|
|
590fe13004 | ||
|
|
74834fd24e | ||
|
|
ba55256630 | ||
|
|
661db11765 | ||
|
|
89c4659911 | ||
|
|
c78802481e | ||
|
|
30a7806328 | ||
|
|
14c278554f | ||
|
|
428d718f75 | ||
|
|
8076277497 | ||
|
|
7d7c052771 | ||
|
|
b743bddb46 | ||
|
|
8968c9730d | ||
|
|
cb2232353a | ||
|
|
c480d769a5 | ||
|
|
a1df41ddde | ||
|
|
b95aadf198 | ||
|
|
4d45edbf52 | ||
|
|
854b9426b9 | ||
|
|
30cb122bdf | ||
|
|
e16f3a9af9 | ||
|
|
96d8e621e2 | ||
|
|
1818af2a08 | ||
|
|
efa3dbbd43 | ||
|
|
f85b5202dc | ||
|
|
f96113d55d | ||
|
|
bddb502427 | ||
|
|
c17de82c6b | ||
|
|
d2930ae84f | ||
|
|
9be8716776 | ||
|
|
a2d95a8083 | ||
|
|
7555e5aef1 | ||
|
|
0bad889607 | ||
|
|
7662c1eeab | ||
|
|
7d6537cc8d | ||
|
|
06f2fa25c0 | ||
|
|
962ab735b5 | ||
|
|
b8d1b54e22 | ||
|
|
b90b1704cf | ||
|
|
07dc3ee287 | ||
|
|
27c0a440d7 | ||
|
|
342eda526d | ||
|
|
0145494497 | ||
|
|
7329cbdceb | ||
|
|
8af0afc80d | ||
|
|
1f9b001648 | ||
|
|
125934592c | ||
|
|
d9aa73a7ad | ||
|
|
ce9463569f | ||
|
|
29127c07d3 | ||
|
|
b180a59497 | ||
|
|
8483e25250 | ||
|
|
a0a12636ef | ||
|
|
a2ca643a3a | ||
|
|
ff10fe098e | ||
|
|
72359f3b01 | ||
|
|
2d58091792 | ||
|
|
2ad741c4e8 | ||
|
|
5d84c7fcb0 | ||
|
|
d8883da034 | ||
|
|
cdaa3da76a | ||
|
|
bbcbf1ce9d | ||
|
|
867cd57ae8 | ||
|
|
0bf1717b65 | ||
|
|
83a96a2327 | ||
|
|
ab866e8a34 | ||
|
|
5b29b2098b | ||
|
|
4675691035 | ||
|
|
d92be7b3a3 | ||
|
|
99e85093e1 | ||
|
|
49a9b3e015 | ||
|
|
f48b9ff9b9 | ||
|
|
9312fe6dfb | ||
|
|
1790fceda9 | ||
|
|
25232575e3 |
@@ -4,12 +4,14 @@
|
||||
|
||||
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
|
||||
|
||||
若依基于hplus和inspinia两套后台系统模板开发。有需要可自行到群内下载。
|
||||
若依参考后台模板。有需要可自行到群内下载。
|
||||
|
||||
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需Oracle版本,请移步 [RuoYi-oracle](http://doc.ruoyi.vip/#/standard/xmkz) `(不定时更新)`
|
||||
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需其他版本,请移步 [项目扩展](http://doc.ruoyi.vip/#/standard/xmkz) `(不定时更新)`
|
||||
|
||||
> 阿里云通用云产品1888优惠券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof) 腾讯云通用云产品2860优惠券 :[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) `(仅限新用户)`
|
||||
|
||||
> 阿里云Hi拼购 限量爆款 低至199元/年 [点我进入](https://www.aliyun.com/acts/hi-group-buying?userCode=brki8iof) `(仅限新用户)`
|
||||
|
||||
## 内置功能
|
||||
|
||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||
@@ -42,34 +44,42 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/25b5e333768d013d45a990c152dbe4d9d6e.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5ac52ccc07a59f12205948c9408791f5c5b.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/e29fd81b2d43b517f99535564af41f9d1d5.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/66f8b5b24720dabe0e11ae84bd1ad4b038e.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/a46f34786bc9fc400697b6f3677be5bb3f0.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/629f1510fb6205f773c8c284863406b694f.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/9124eda87df0e72427cd63f458b813e3363.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/6010201b078dbc9e1d8c09c6a3e53f4344c.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/058928ad3a6e6de67b43d62d42dbf071355.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/438c59467afd0097cfbe9c89db932661687.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/72a015041db6843aca7f7b273688cb346f8.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/21acdcade5e306f2c5d7ae26993b4e6bd06.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/ad5ea3c4c2ea2e91d1f05f6cc384cbad2a1.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/ecb5f1c9929f1933f733f796749b2df73d9.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/e4283d500eb10e8dd8701e7742f7facb065.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/6ca845cca1701fbf71881efe4f341c82f99.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/e3aeb8fff585594f6e947218e14f2806ea1.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/2531dbf419a1b114e1177f8d2a120b8a9c3.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/8b740a42dddc1e5a8a150d97c5060df258b.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/197ddc2fdffc27020f8624bd7ca1a971f61.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/a2dabea752d7d70aede20908dee0b419829.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/00e642dc3515919b3760968cc496a12a849.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/f72d28a3e60413a4e1b5c7c2f45f962fd65.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/c5699c5726b5aebde71a37bb5163d840bc2.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/24740d59377e826d0d8664ebad66dc84abd.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/19222e495869a2a99fc31c5d2bd4539e1e7.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/264d25176f4e22b4b38e95fe6ce73775299.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/bbe7fe1048d29217ba73bd3ed88d6743b55.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/d85fbb59be27fb33f68bdbb6e8bc967c97b.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/bb902d2c54bad02a052e9a05e5f22a93df1.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/30cda883bb9a7f74f1454314e64f949942d.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/deebaaa8d6b14a419ed5911f49e3f222a6f.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/bed2b98a44e7ae820c2885329e711965c28.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5f3d39a141f21f81b90536f391b8408f1fa.jpg"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -77,4 +87,4 @@
|
||||
|
||||
## 若依交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) 点击按钮入群。
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) 点击按钮入群。
|
||||
+2
-4
@@ -2,13 +2,11 @@
|
||||
echo.
|
||||
echo [信息] 清理生成路径。
|
||||
echo.
|
||||
pause
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
cd..
|
||||
|
||||
cd ..
|
||||
call mvn clean
|
||||
|
||||
cd bin
|
||||
pause
|
||||
+3
-4
@@ -1,13 +1,12 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 打包工程,生成jar包文件。
|
||||
echo.
|
||||
pause
|
||||
echo [信息] 打包Web工程,生成war/jar包文件。
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
cd..
|
||||
|
||||
cd ..
|
||||
call mvn clean package -Dmaven.test.skip=true
|
||||
|
||||
pause
|
||||
Binary file not shown.
@@ -6,14 +6,14 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>4.0.0</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>3.3</ruoyi.version>
|
||||
<ruoyi.version>4.0.0</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
@@ -23,12 +23,12 @@
|
||||
<druid.version>1.1.14</druid.version>
|
||||
<bitwalker.version>1.19</bitwalker.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<swagger.version>2.7.0</swagger.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.47</fastjson.version>
|
||||
<oshi.version>3.9.1</oshi.version>
|
||||
<commons.io.version>2.5</commons.io.version>
|
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||
<commons.beanutils.version>1.9.3</commons.beanutils.version>
|
||||
<jsoup.version>1.11.3</jsoup.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
@@ -115,6 +115,16 @@
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
@@ -138,13 +148,6 @@
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 简化反射封工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>${commons.beanutils.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- HTML解析器 -->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
@@ -165,6 +168,13 @@
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 定时任务-->
|
||||
<dependency>
|
||||
|
||||
+14
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.3</version>
|
||||
<version>4.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
@@ -36,6 +36,19 @@
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.ruoyi;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
@@ -11,7 +10,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
@MapperScan("com.ruoyi.*.mapper")
|
||||
public class RuoYiApplication
|
||||
{
|
||||
public static void main(String[] args)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.ruoyi.web.controller.common;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
@@ -29,11 +27,6 @@ public class CommonController
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
||||
|
||||
/**
|
||||
* 文件上传路径
|
||||
*/
|
||||
public static final String UPLOAD_PATH = "/profile/upload/";
|
||||
|
||||
@Autowired
|
||||
private ServerConfig serverConfig;
|
||||
|
||||
@@ -50,7 +43,7 @@ public class CommonController
|
||||
{
|
||||
if (!FileUtils.isValidFilename(fileName))
|
||||
{
|
||||
throw new Exception(StringUtils.format(" 文件名称({})非法,不允许下载。 ", fileName));
|
||||
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
||||
}
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
String filePath = Global.getDownloadPath() + fileName;
|
||||
@@ -58,7 +51,7 @@ public class CommonController
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + setFileDownloadHeader(request, realFileName));
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
|
||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||
if (delete)
|
||||
{
|
||||
@@ -84,7 +77,7 @@ public class CommonController
|
||||
String filePath = Global.getUploadPath();
|
||||
// 上传并返回新文件名称
|
||||
String fileName = FileUploadUtils.upload(filePath, file);
|
||||
String url = serverConfig.getUrl() + UPLOAD_PATH + fileName;
|
||||
String url = serverConfig.getUrl() + fileName;
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("fileName", fileName);
|
||||
ajax.put("url", url);
|
||||
@@ -95,32 +88,4 @@ public class CommonController
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
|
||||
{
|
||||
final String agent = request.getHeader("USER-AGENT");
|
||||
String filename = fileName;
|
||||
if (agent.contains("MSIE"))
|
||||
{
|
||||
// IE浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
filename = filename.replace("+", " ");
|
||||
}
|
||||
else if (agent.contains("Firefox"))
|
||||
{
|
||||
// 火狐浏览器
|
||||
filename = new String(fileName.getBytes(), "ISO8859-1");
|
||||
}
|
||||
else if (agent.contains("Chrome"))
|
||||
{
|
||||
// google浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其它浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8");
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 模态窗口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/modal")
|
||||
public class DemoDialogController
|
||||
{
|
||||
private String prefix = "demo/modal";
|
||||
|
||||
/**
|
||||
* 模态窗口
|
||||
*/
|
||||
@GetMapping("/dialog")
|
||||
public String dialog()
|
||||
{
|
||||
return prefix + "/dialog";
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹层组件
|
||||
*/
|
||||
@GetMapping("/layer")
|
||||
public String layer()
|
||||
{
|
||||
return prefix + "/layer";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单
|
||||
*/
|
||||
@GetMapping("/form")
|
||||
public String form()
|
||||
{
|
||||
return prefix + "/form";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格
|
||||
*/
|
||||
@GetMapping("/table")
|
||||
public String table()
|
||||
{
|
||||
return prefix + "/table";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格check
|
||||
*/
|
||||
@GetMapping("/check")
|
||||
public String check()
|
||||
{
|
||||
return prefix + "/table/check";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格radio
|
||||
*/
|
||||
@GetMapping("/radio")
|
||||
public String radio()
|
||||
{
|
||||
return prefix + "/table/radio";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格回传父窗体
|
||||
*/
|
||||
@GetMapping("/parent")
|
||||
public String parent()
|
||||
{
|
||||
return prefix + "/table/parent";
|
||||
}
|
||||
}
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
|
||||
/**
|
||||
* 表单相关
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/form")
|
||||
public class DemoFormController
|
||||
{
|
||||
private String prefix = "demo/form";
|
||||
|
||||
private final static List<UserFormModel> users = new ArrayList<UserFormModel>();
|
||||
{
|
||||
users.add(new UserFormModel(1, "1000001", "测试1", "15888888888"));
|
||||
users.add(new UserFormModel(2, "1000002", "测试2", "15666666666"));
|
||||
users.add(new UserFormModel(3, "1000003", "测试3", "15666666666"));
|
||||
users.add(new UserFormModel(4, "1000004", "测试4", "15666666666"));
|
||||
users.add(new UserFormModel(5, "1000005", "测试5", "15666666666"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按钮页
|
||||
*/
|
||||
@GetMapping("/button")
|
||||
public String button()
|
||||
{
|
||||
return prefix + "/button";
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉框
|
||||
*/
|
||||
@GetMapping("/select")
|
||||
public String select()
|
||||
{
|
||||
return prefix + "/select";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单校验
|
||||
*/
|
||||
@GetMapping("/validate")
|
||||
public String validate()
|
||||
{
|
||||
return prefix + "/validate";
|
||||
}
|
||||
|
||||
/**
|
||||
* 功能扩展(包含文件上传)
|
||||
*/
|
||||
@GetMapping("/jasny")
|
||||
public String jasny()
|
||||
{
|
||||
return prefix + "/jasny";
|
||||
}
|
||||
|
||||
/**
|
||||
* 拖动排序
|
||||
*/
|
||||
@GetMapping("/sortable")
|
||||
public String sortable()
|
||||
{
|
||||
return prefix + "/sortable";
|
||||
}
|
||||
|
||||
/**
|
||||
* 选项卡 & 面板
|
||||
*/
|
||||
@GetMapping("/tabs_panels")
|
||||
public String tabs_panels()
|
||||
{
|
||||
return prefix + "/tabs_panels";
|
||||
}
|
||||
|
||||
/**
|
||||
* 栅格
|
||||
*/
|
||||
@GetMapping("/grid")
|
||||
public String grid()
|
||||
{
|
||||
return prefix + "/grid";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单向导
|
||||
*/
|
||||
@GetMapping("/wizard")
|
||||
public String wizard()
|
||||
{
|
||||
return prefix + "/wizard";
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*/
|
||||
@GetMapping("/upload")
|
||||
public String upload()
|
||||
{
|
||||
return prefix + "/upload";
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期和时间页
|
||||
*/
|
||||
@GetMapping("/datetime")
|
||||
public String datetime()
|
||||
{
|
||||
return prefix + "/datetime";
|
||||
}
|
||||
|
||||
/**
|
||||
* 左右互选组件
|
||||
*/
|
||||
@GetMapping("/duallistbox")
|
||||
public String duallistbox()
|
||||
{
|
||||
return prefix + "/duallistbox";
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本表单
|
||||
*/
|
||||
@GetMapping("/basic")
|
||||
public String basic()
|
||||
{
|
||||
return prefix + "/basic";
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡片列表
|
||||
*/
|
||||
@GetMapping("/cards")
|
||||
public String cards()
|
||||
{
|
||||
return prefix + "/cards";
|
||||
}
|
||||
|
||||
/**
|
||||
* summernote 富文本编辑器
|
||||
*/
|
||||
@GetMapping("/summernote")
|
||||
public String summernote()
|
||||
{
|
||||
return prefix + "/summernote";
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索自动补全
|
||||
*/
|
||||
@GetMapping("/autocomplete")
|
||||
public String autocomplete()
|
||||
{
|
||||
return prefix + "/autocomplete";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户数据
|
||||
*/
|
||||
@GetMapping("/userModel")
|
||||
@ResponseBody
|
||||
public AjaxResult userModel()
|
||||
{
|
||||
AjaxResult ajax = new AjaxResult();
|
||||
|
||||
ajax.put("code", 200);
|
||||
ajax.put("value", users);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据集合
|
||||
*/
|
||||
@GetMapping("/collection")
|
||||
@ResponseBody
|
||||
public AjaxResult collection()
|
||||
{
|
||||
String[] array = { "ruoyi 1", "ruoyi 2", "ruoyi 3", "ruoyi 4", "ruoyi 5" };
|
||||
AjaxResult ajax = new AjaxResult();
|
||||
ajax.put("value", array);
|
||||
return ajax;
|
||||
}
|
||||
}
|
||||
|
||||
class UserFormModel
|
||||
{
|
||||
/** 用户ID */
|
||||
private int userId;
|
||||
|
||||
/** 用户编号 */
|
||||
private String userCode;
|
||||
|
||||
/** 用户姓名 */
|
||||
private String userName;
|
||||
|
||||
/** 用户手机 */
|
||||
private String userPhone;
|
||||
|
||||
public UserFormModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UserFormModel(int userId, String userCode, String userName, String userPhone)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.userCode = userCode;
|
||||
this.userName = userName;
|
||||
this.userPhone = userPhone;
|
||||
}
|
||||
|
||||
public int getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserCode()
|
||||
{
|
||||
return userCode;
|
||||
}
|
||||
|
||||
public void setUserCode(String userCode)
|
||||
{
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserPhone()
|
||||
{
|
||||
return userPhone;
|
||||
}
|
||||
|
||||
public void setUserPhone(String userPhone)
|
||||
{
|
||||
this.userPhone = userPhone;
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 图标相关
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/icon")
|
||||
public class DemoIconController
|
||||
{
|
||||
private String prefix = "demo/icon";
|
||||
|
||||
/**
|
||||
* FontAwesome图标
|
||||
*/
|
||||
@GetMapping("/fontawesome")
|
||||
public String fontAwesome()
|
||||
{
|
||||
return prefix + "/fontawesome";
|
||||
}
|
||||
|
||||
/**
|
||||
* Glyphicons图标
|
||||
*/
|
||||
@GetMapping("/glyphicons")
|
||||
public String glyphicons()
|
||||
{
|
||||
return prefix + "/glyphicons";
|
||||
}
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.exception.BusinessException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.web.controller.demo.domain.UserOperateModel;
|
||||
|
||||
/**
|
||||
* 操作控制
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/operate")
|
||||
public class DemoOperateController extends BaseController
|
||||
{
|
||||
private String prefix = "demo/operate";
|
||||
|
||||
private final static Map<Integer, UserOperateModel> users = new LinkedHashMap<Integer, UserOperateModel>();
|
||||
{
|
||||
users.put(1, new UserOperateModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0"));
|
||||
users.put(2, new UserOperateModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||
users.put(3, new UserOperateModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||
users.put(4, new UserOperateModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||
users.put(5, new UserOperateModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1"));
|
||||
users.put(6, new UserOperateModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1"));
|
||||
users.put(7, new UserOperateModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||
users.put(8, new UserOperateModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1"));
|
||||
users.put(9, new UserOperateModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||
users.put(10, new UserOperateModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||
users.put(11, new UserOperateModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||
users.put(12, new UserOperateModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||
users.put(13, new UserOperateModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1"));
|
||||
users.put(14, new UserOperateModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1"));
|
||||
users.put(15, new UserOperateModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||
users.put(16, new UserOperateModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1"));
|
||||
users.put(17, new UserOperateModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||
users.put(18, new UserOperateModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1"));
|
||||
users.put(19, new UserOperateModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||
users.put(20, new UserOperateModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||
users.put(21, new UserOperateModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||
users.put(22, new UserOperateModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1"));
|
||||
users.put(23, new UserOperateModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1"));
|
||||
users.put(24, new UserOperateModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||
users.put(25, new UserOperateModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||
users.put(26, new UserOperateModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格
|
||||
*/
|
||||
@GetMapping("/table")
|
||||
public String table()
|
||||
{
|
||||
return prefix + "/table";
|
||||
}
|
||||
|
||||
/**
|
||||
* 其他
|
||||
*/
|
||||
@GetMapping("/other")
|
||||
public String other()
|
||||
{
|
||||
return prefix + "/other";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(UserOperateModel userModel)
|
||||
{
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
List<UserOperateModel> userList = new ArrayList<UserOperateModel>(users.values());
|
||||
// 查询条件过滤
|
||||
if (StringUtils.isNotEmpty(userModel.getSearchValue()))
|
||||
{
|
||||
userList.clear();
|
||||
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
|
||||
{
|
||||
if (entry.getValue().getUserName().equals(userModel.getSearchValue()))
|
||||
{
|
||||
userList.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
|
||||
{
|
||||
rspData.setRows(userList);
|
||||
rspData.setTotal(userList.size());
|
||||
return rspData;
|
||||
}
|
||||
Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
|
||||
Integer pageSize = pageDomain.getPageNum() * 10;
|
||||
if (pageSize > userList.size())
|
||||
{
|
||||
pageSize = userList.size();
|
||||
}
|
||||
rspData.setRows(userList.subList(pageNum, pageSize));
|
||||
rspData.setTotal(userList.size());
|
||||
return rspData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户
|
||||
*/
|
||||
@GetMapping("/add")
|
||||
public String add(ModelMap mmap)
|
||||
{
|
||||
return prefix + "/add";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增保存用户
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(UserOperateModel user)
|
||||
{
|
||||
Integer userId = users.size() + 1;
|
||||
user.setUserId(userId);
|
||||
return AjaxResult.success(users.put(userId, user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
*/
|
||||
@GetMapping("/edit/{userId}")
|
||||
public String edit(@PathVariable("userId") Integer userId, ModelMap mmap)
|
||||
{
|
||||
mmap.put("user", users.get(userId));
|
||||
return prefix + "/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改保存用户
|
||||
*/
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(UserOperateModel user)
|
||||
{
|
||||
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*/
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
public AjaxResult export(UserOperateModel user)
|
||||
{
|
||||
List<UserOperateModel> list = new ArrayList<UserOperateModel>(users.values());
|
||||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||
return util.exportExcel(list, "用户数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@GetMapping("/importTemplate")
|
||||
@ResponseBody
|
||||
public AjaxResult importTemplate()
|
||||
{
|
||||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||
return util.importTemplateExcel("用户数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@PostMapping("/importData")
|
||||
@ResponseBody
|
||||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
|
||||
{
|
||||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||
List<UserOperateModel> userList = util.importExcel(file.getInputStream());
|
||||
String message = importUser(userList, updateSupport);
|
||||
return AjaxResult.success(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
@PostMapping("/remove")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(String ids)
|
||||
{
|
||||
Integer[] userIds = Convert.toIntArray(ids);
|
||||
for (Integer userId : userIds)
|
||||
{
|
||||
users.remove(userId);
|
||||
}
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看详细
|
||||
*/
|
||||
@GetMapping("/detail/{userId}")
|
||||
public String detail(@PathVariable("userId") Integer userId, ModelMap mmap)
|
||||
{
|
||||
mmap.put("user", users.get(userId));
|
||||
return prefix + "/detail";
|
||||
}
|
||||
|
||||
@PostMapping("/clean")
|
||||
@ResponseBody
|
||||
public AjaxResult clean()
|
||||
{
|
||||
users.clear();
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入用户数据
|
||||
*
|
||||
* @param userList 用户数据列表
|
||||
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
|
||||
* @return 结果
|
||||
*/
|
||||
public String importUser(List<UserOperateModel> userList, Boolean isUpdateSupport)
|
||||
{
|
||||
if (StringUtils.isNull(userList) || userList.size() == 0)
|
||||
{
|
||||
throw new BusinessException("导入用户数据不能为空!");
|
||||
}
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
for (UserOperateModel user : userList)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 验证是否存在这个用户
|
||||
boolean userFlag = false;
|
||||
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
|
||||
{
|
||||
if (entry.getValue().getUserName().equals(user.getUserName()))
|
||||
{
|
||||
userFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!userFlag)
|
||||
{
|
||||
Integer userId = users.size() + 1;
|
||||
user.setUserId(userId);
|
||||
users.put(userId, user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 导入成功");
|
||||
}
|
||||
else if (isUpdateSupport)
|
||||
{
|
||||
users.put(user.getUserId(), user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 更新成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>" + failureNum + "、用户 " + user.getUserName() + " 已存在");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
|
||||
failureMsg.append(msg + e.getMessage());
|
||||
}
|
||||
}
|
||||
if (failureNum > 0)
|
||||
{
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new BusinessException(failureMsg.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 报表
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/report")
|
||||
public class DemoReportController
|
||||
{
|
||||
private String prefix = "demo/report";
|
||||
|
||||
/**
|
||||
* 百度ECharts
|
||||
*/
|
||||
@GetMapping("/echarts")
|
||||
public String echarts()
|
||||
{
|
||||
return prefix + "/echarts";
|
||||
}
|
||||
|
||||
/**
|
||||
* 图表插件
|
||||
*/
|
||||
@GetMapping("/peity")
|
||||
public String peity()
|
||||
{
|
||||
return prefix + "/peity";
|
||||
}
|
||||
|
||||
/**
|
||||
* 线状图插件
|
||||
*/
|
||||
@GetMapping("/sparkline")
|
||||
public String sparkline()
|
||||
{
|
||||
return prefix + "/sparkline";
|
||||
}
|
||||
|
||||
/**
|
||||
* 图表组合
|
||||
*/
|
||||
@GetMapping("/metrics")
|
||||
public String metrics()
|
||||
{
|
||||
return prefix + "/metrics";
|
||||
}
|
||||
}
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
package com.ruoyi.web.controller.demo.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 表格相关
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/demo/table")
|
||||
public class DemoTableController extends BaseController
|
||||
{
|
||||
private String prefix = "demo/table";
|
||||
|
||||
private final static List<UserTableModel> users = new ArrayList<UserTableModel>();
|
||||
{
|
||||
users.add(new UserTableModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0"));
|
||||
users.add(new UserTableModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||
users.add(new UserTableModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||
users.add(new UserTableModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||
users.add(new UserTableModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1"));
|
||||
users.add(new UserTableModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1"));
|
||||
users.add(new UserTableModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||
users.add(new UserTableModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1"));
|
||||
users.add(new UserTableModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||
users.add(new UserTableModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||
users.add(new UserTableModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||
users.add(new UserTableModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||
users.add(new UserTableModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1"));
|
||||
users.add(new UserTableModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1"));
|
||||
users.add(new UserTableModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||
users.add(new UserTableModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1"));
|
||||
users.add(new UserTableModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||
users.add(new UserTableModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1"));
|
||||
users.add(new UserTableModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||
users.add(new UserTableModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||
users.add(new UserTableModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||
users.add(new UserTableModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1"));
|
||||
users.add(new UserTableModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1"));
|
||||
users.add(new UserTableModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||
users.add(new UserTableModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||
users.add(new UserTableModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索相关
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public String search()
|
||||
{
|
||||
return prefix + "/search";
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据汇总
|
||||
*/
|
||||
@GetMapping("/footer")
|
||||
public String footer()
|
||||
{
|
||||
return prefix + "/footer";
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合表头
|
||||
*/
|
||||
@GetMapping("/groupHeader")
|
||||
public String groupHeader()
|
||||
{
|
||||
return prefix + "/groupHeader";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格导出
|
||||
*/
|
||||
@GetMapping("/export")
|
||||
public String export()
|
||||
{
|
||||
return prefix + "/export";
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻页记住选择
|
||||
*/
|
||||
@GetMapping("/remember")
|
||||
public String remember()
|
||||
{
|
||||
return prefix + "/remember";
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至指定页
|
||||
*/
|
||||
@GetMapping("/pageGo")
|
||||
public String pageGo()
|
||||
{
|
||||
return prefix + "/pageGo";
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义查询参数
|
||||
*/
|
||||
@GetMapping("/params")
|
||||
public String params()
|
||||
{
|
||||
return prefix + "/params";
|
||||
}
|
||||
|
||||
/**
|
||||
* 多表格
|
||||
*/
|
||||
@GetMapping("/multi")
|
||||
public String multi()
|
||||
{
|
||||
return prefix + "/multi";
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击按钮加载表格
|
||||
*/
|
||||
@GetMapping("/button")
|
||||
public String button()
|
||||
{
|
||||
return prefix + "/button";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格冻结列
|
||||
*/
|
||||
@GetMapping("/fixedColumns")
|
||||
public String fixedColumns()
|
||||
{
|
||||
return prefix + "/fixedColumns";
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义触发事件
|
||||
*/
|
||||
@GetMapping("/event")
|
||||
public String event()
|
||||
{
|
||||
return prefix + "/event";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格细节视图
|
||||
*/
|
||||
@GetMapping("/detail")
|
||||
public String detail()
|
||||
{
|
||||
return prefix + "/detail";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格图片预览
|
||||
*/
|
||||
@GetMapping("/image")
|
||||
public String image()
|
||||
{
|
||||
return prefix + "/image";
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态增删改查
|
||||
*/
|
||||
@GetMapping("/curd")
|
||||
public String curd()
|
||||
{
|
||||
return prefix + "/curd";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格拖拽操作
|
||||
*/
|
||||
@GetMapping("/reorder")
|
||||
public String reorder()
|
||||
{
|
||||
return prefix + "/reorder";
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格其他操作
|
||||
*/
|
||||
@GetMapping("/other")
|
||||
public String other()
|
||||
{
|
||||
return prefix + "/other";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(UserTableModel userModel)
|
||||
{
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
List<UserTableModel> userList = new ArrayList<UserTableModel>(Arrays.asList(new UserTableModel[users.size()]));
|
||||
Collections.copy(userList, users);
|
||||
// 查询条件过滤
|
||||
if (StringUtils.isNotEmpty(userModel.getUserName()))
|
||||
{
|
||||
userList.clear();
|
||||
for (UserTableModel user : users)
|
||||
{
|
||||
if (user.getUserName().equals(userModel.getUserName()))
|
||||
{
|
||||
userList.add(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
|
||||
{
|
||||
rspData.setRows(userList);
|
||||
rspData.setTotal(userList.size());
|
||||
return rspData;
|
||||
}
|
||||
Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
|
||||
Integer pageSize = pageDomain.getPageNum() * 10;
|
||||
if (pageSize > userList.size())
|
||||
{
|
||||
pageSize = userList.size();
|
||||
}
|
||||
rspData.setRows(userList.subList(pageNum, pageSize));
|
||||
rspData.setTotal(userList.size());
|
||||
return rspData;
|
||||
}
|
||||
}
|
||||
|
||||
class UserTableModel
|
||||
{
|
||||
/** 用户ID */
|
||||
private int userId;
|
||||
|
||||
/** 用户编号 */
|
||||
private String userCode;
|
||||
|
||||
/** 用户姓名 */
|
||||
private String userName;
|
||||
|
||||
/** 用户性别 */
|
||||
private String userSex;
|
||||
|
||||
/** 用户手机 */
|
||||
private String userPhone;
|
||||
|
||||
/** 用户邮箱 */
|
||||
private String userEmail;
|
||||
|
||||
/** 用户余额 */
|
||||
private double userBalance;
|
||||
|
||||
/** 用户状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
public UserTableModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UserTableModel(int userId, String userCode, String userName, String userSex, String userPhone,
|
||||
String userEmail, double userBalance, String status)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.userCode = userCode;
|
||||
this.userName = userName;
|
||||
this.userSex = userSex;
|
||||
this.userPhone = userPhone;
|
||||
this.userEmail = userEmail;
|
||||
this.userBalance = userBalance;
|
||||
this.status = status;
|
||||
this.createTime = DateUtils.getNowDate();
|
||||
}
|
||||
|
||||
public int getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserCode()
|
||||
{
|
||||
return userCode;
|
||||
}
|
||||
|
||||
public void setUserCode(String userCode)
|
||||
{
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserSex()
|
||||
{
|
||||
return userSex;
|
||||
}
|
||||
|
||||
public void setUserSex(String userSex)
|
||||
{
|
||||
this.userSex = userSex;
|
||||
}
|
||||
|
||||
public String getUserPhone()
|
||||
{
|
||||
return userPhone;
|
||||
}
|
||||
|
||||
public void setUserPhone(String userPhone)
|
||||
{
|
||||
this.userPhone = userPhone;
|
||||
}
|
||||
|
||||
public String getUserEmail()
|
||||
{
|
||||
return userEmail;
|
||||
}
|
||||
|
||||
public void setUserEmail(String userEmail)
|
||||
{
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
|
||||
public double getUserBalance()
|
||||
{
|
||||
return userBalance;
|
||||
}
|
||||
|
||||
public void setUserBalance(double userBalance)
|
||||
{
|
||||
this.userBalance = userBalance;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getCreateTime()
|
||||
{
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime)
|
||||
{
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.ruoyi.web.controller.demo.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.annotation.Excel.Type;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
|
||||
public class UserOperateModel extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int userId;
|
||||
|
||||
@Excel(name = "用户编号")
|
||||
private String userCode;
|
||||
|
||||
@Excel(name = "用户姓名")
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
|
||||
private String userSex;
|
||||
|
||||
@Excel(name = "用户手机")
|
||||
private String userPhone;
|
||||
|
||||
@Excel(name = "用户邮箱")
|
||||
private String userEmail;
|
||||
|
||||
@Excel(name = "用户余额")
|
||||
private double userBalance;
|
||||
|
||||
@Excel(name = "用户状态", readConverterExp = "0=正常,1=停用")
|
||||
private String status;
|
||||
|
||||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
||||
private Date createTime;
|
||||
|
||||
public UserOperateModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UserOperateModel(int userId, String userCode, String userName, String userSex, String userPhone,
|
||||
String userEmail, double userBalance, String status)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.userCode = userCode;
|
||||
this.userName = userName;
|
||||
this.userSex = userSex;
|
||||
this.userPhone = userPhone;
|
||||
this.userEmail = userEmail;
|
||||
this.userBalance = userBalance;
|
||||
this.status = status;
|
||||
this.createTime = DateUtils.getNowDate();
|
||||
}
|
||||
|
||||
public int getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserCode()
|
||||
{
|
||||
return userCode;
|
||||
}
|
||||
|
||||
public void setUserCode(String userCode)
|
||||
{
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserSex()
|
||||
{
|
||||
return userSex;
|
||||
}
|
||||
|
||||
public void setUserSex(String userSex)
|
||||
{
|
||||
this.userSex = userSex;
|
||||
}
|
||||
|
||||
public String getUserPhone()
|
||||
{
|
||||
return userPhone;
|
||||
}
|
||||
|
||||
public void setUserPhone(String userPhone)
|
||||
{
|
||||
this.userPhone = userPhone;
|
||||
}
|
||||
|
||||
public String getUserEmail()
|
||||
{
|
||||
return userEmail;
|
||||
}
|
||||
|
||||
public void setUserEmail(String userEmail)
|
||||
{
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
|
||||
public double getUserBalance()
|
||||
{
|
||||
return userBalance;
|
||||
}
|
||||
|
||||
public void setUserBalance(double userBalance)
|
||||
{
|
||||
this.userBalance = userBalance;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getCreateTime()
|
||||
{
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime)
|
||||
{
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import com.ruoyi.common.core.controller.BaseController;
|
||||
@RequestMapping("/monitor/data")
|
||||
public class DruidController extends BaseController
|
||||
{
|
||||
private String prefix = "/monitor/druid";
|
||||
private String prefix = "/druid";
|
||||
|
||||
@RequiresPermissions("monitor:data:view")
|
||||
@GetMapping()
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
@@ -81,8 +83,12 @@ public class SysConfigController extends BaseController
|
||||
@Log(title = "参数管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysConfig config)
|
||||
public AjaxResult addSave(@Validated SysConfig config)
|
||||
{
|
||||
if (UserConstants.CONFIG_KEY_NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
||||
{
|
||||
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||
}
|
||||
config.setCreateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(configService.insertConfig(config));
|
||||
}
|
||||
@@ -104,8 +110,12 @@ public class SysConfigController extends BaseController
|
||||
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysConfig config)
|
||||
public AjaxResult editSave(@Validated SysConfig config)
|
||||
{
|
||||
if (UserConstants.CONFIG_KEY_NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
||||
{
|
||||
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||
}
|
||||
config.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(configService.updateConfig(config));
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.Ztree;
|
||||
@@ -43,7 +45,7 @@ public class SysDeptController extends BaseController
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:dept:list")
|
||||
@GetMapping("/list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public List<SysDept> list(SysDept dept)
|
||||
{
|
||||
@@ -68,8 +70,12 @@ public class SysDeptController extends BaseController
|
||||
@RequiresPermissions("system:dept:add")
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysDept dept)
|
||||
public AjaxResult addSave(@Validated SysDept dept)
|
||||
{
|
||||
if (UserConstants.DEPT_NAME_NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
||||
{
|
||||
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||
}
|
||||
dept.setCreateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(deptService.insertDept(dept));
|
||||
}
|
||||
@@ -96,8 +102,16 @@ public class SysDeptController extends BaseController
|
||||
@RequiresPermissions("system:dept:edit")
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysDept dept)
|
||||
public AjaxResult editSave(@Validated SysDept dept)
|
||||
{
|
||||
if (UserConstants.DEPT_NAME_NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
||||
{
|
||||
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||
}
|
||||
else if (dept.getParentId().equals(dept.getDeptId()))
|
||||
{
|
||||
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
|
||||
}
|
||||
dept.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(deptService.updateDept(dept));
|
||||
}
|
||||
|
||||
+3
-2
@@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -79,7 +80,7 @@ public class SysDictDataController extends BaseController
|
||||
@RequiresPermissions("system:dict:add")
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysDictData dict)
|
||||
public AjaxResult addSave(@Validated SysDictData dict)
|
||||
{
|
||||
dict.setCreateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(dictDataService.insertDictData(dict));
|
||||
@@ -102,7 +103,7 @@ public class SysDictDataController extends BaseController
|
||||
@RequiresPermissions("system:dict:edit")
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysDictData dict)
|
||||
public AjaxResult editSave(@Validated SysDictData dict)
|
||||
{
|
||||
dict.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(dictDataService.updateDictData(dict));
|
||||
|
||||
+36
-2
@@ -5,14 +5,17 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.Ztree;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
@@ -79,8 +82,12 @@ public class SysDictTypeController extends BaseController
|
||||
@RequiresPermissions("system:dict:add")
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysDictType dict)
|
||||
public AjaxResult addSave(@Validated SysDictType dict)
|
||||
{
|
||||
if (UserConstants.DICT_TYPE_NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
||||
{
|
||||
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||
}
|
||||
dict.setCreateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(dictTypeService.insertDictType(dict));
|
||||
}
|
||||
@@ -102,8 +109,12 @@ public class SysDictTypeController extends BaseController
|
||||
@RequiresPermissions("system:dict:edit")
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysDictType dict)
|
||||
public AjaxResult editSave(@Validated SysDictType dict)
|
||||
{
|
||||
if (UserConstants.DICT_TYPE_NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
||||
{
|
||||
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||
}
|
||||
dict.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(dictTypeService.updateDictType(dict));
|
||||
}
|
||||
@@ -145,4 +156,27 @@ public class SysDictTypeController extends BaseController
|
||||
{
|
||||
return dictTypeService.checkDictTypeUnique(dictType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择字典树
|
||||
*/
|
||||
@GetMapping("/selectDictTree/{columnId}/{dictType}")
|
||||
public String selectDeptTree(@PathVariable("columnId") Long columnId, @PathVariable("dictType") String dictType,
|
||||
ModelMap mmap)
|
||||
{
|
||||
mmap.put("columnId", columnId);
|
||||
mmap.put("dict", dictTypeService.selectDictTypeByType(dictType));
|
||||
return prefix + "/tree";
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载字典列表树
|
||||
*/
|
||||
@GetMapping("/treeData")
|
||||
@ResponseBody
|
||||
public List<Ztree> treeData()
|
||||
{
|
||||
List<Ztree> ztrees = dictTypeService.selectDictTree(new SysDictType());
|
||||
return ztrees;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class SysIndexController extends BaseController
|
||||
mmap.put("menus", menus);
|
||||
mmap.put("user", user);
|
||||
mmap.put("copyrightYear", Global.getCopyrightYear());
|
||||
mmap.put("demoEnabled", Global.isDemoEnabled());
|
||||
return "index";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
public class SysLoginController extends BaseController
|
||||
{
|
||||
@GetMapping("/login")
|
||||
public String login(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
// 如果是Ajax请求,返回Json字符串。
|
||||
if (ServletUtils.isAjaxRequest(request))
|
||||
{
|
||||
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
|
||||
}
|
||||
|
||||
return "login";
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
@ResponseBody
|
||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
||||
{
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try
|
||||
{
|
||||
subject.login(token);
|
||||
return success();
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||
{
|
||||
msg = e.getMessage();
|
||||
}
|
||||
return error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/unauth")
|
||||
public String unauth()
|
||||
{
|
||||
return "/error/unauth";
|
||||
}
|
||||
}
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Controller
|
||||
public class SysLoginController extends BaseController
|
||||
{
|
||||
@GetMapping("/login")
|
||||
public String login(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
// 如果是Ajax请求,返回Json字符串。
|
||||
if (ServletUtils.isAjaxRequest(request))
|
||||
{
|
||||
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
|
||||
}
|
||||
|
||||
return "login";
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
@ResponseBody
|
||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
||||
{
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try
|
||||
{
|
||||
subject.login(token);
|
||||
return success();
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||
{
|
||||
msg = e.getMessage();
|
||||
}
|
||||
return error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/unauth")
|
||||
public String unauth()
|
||||
{
|
||||
return "error/unauth";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.Ztree;
|
||||
@@ -42,11 +44,12 @@ public class SysMenuController extends BaseController
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:menu:list")
|
||||
@GetMapping("/list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public List<SysMenu> list(SysMenu menu)
|
||||
{
|
||||
List<SysMenu> menuList = menuService.selectMenuList(menu);
|
||||
Long userId = ShiroUtils.getUserId();
|
||||
List<SysMenu> menuList = menuService.selectMenuList(menu, userId);
|
||||
return menuList;
|
||||
}
|
||||
|
||||
@@ -99,8 +102,12 @@ public class SysMenuController extends BaseController
|
||||
@RequiresPermissions("system:menu:add")
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysMenu menu)
|
||||
public AjaxResult addSave(@Validated SysMenu menu)
|
||||
{
|
||||
if (UserConstants.MENU_NAME_NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
||||
{
|
||||
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
menu.setCreateBy(ShiroUtils.getLoginName());
|
||||
ShiroUtils.clearCachedAuthorizationInfo();
|
||||
return toAjax(menuService.insertMenu(menu));
|
||||
@@ -123,8 +130,12 @@ public class SysMenuController extends BaseController
|
||||
@RequiresPermissions("system:menu:edit")
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysMenu menu)
|
||||
public AjaxResult editSave(@Validated SysMenu menu)
|
||||
{
|
||||
if (UserConstants.MENU_NAME_NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
||||
{
|
||||
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
menu.setUpdateBy(ShiroUtils.getLoginName());
|
||||
ShiroUtils.clearCachedAuthorizationInfo();
|
||||
return toAjax(menuService.updateMenu(menu));
|
||||
@@ -156,7 +167,8 @@ public class SysMenuController extends BaseController
|
||||
@ResponseBody
|
||||
public List<Ztree> roleMenuTreeData(SysRole role)
|
||||
{
|
||||
List<Ztree> ztrees = menuService.roleMenuTreeData(role);
|
||||
Long userId = ShiroUtils.getUserId();
|
||||
List<Ztree> ztrees = menuService.roleMenuTreeData(role, userId);
|
||||
return ztrees;
|
||||
}
|
||||
|
||||
@@ -165,9 +177,10 @@ public class SysMenuController extends BaseController
|
||||
*/
|
||||
@GetMapping("/menuTreeData")
|
||||
@ResponseBody
|
||||
public List<Ztree> menuTreeData(SysRole role)
|
||||
public List<Ztree> menuTreeData()
|
||||
{
|
||||
List<Ztree> ztrees = menuService.menuTreeData();
|
||||
Long userId = ShiroUtils.getUserId();
|
||||
List<Ztree> ztrees = menuService.menuTreeData(userId);
|
||||
return ztrees;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
@@ -94,8 +96,16 @@ public class SysPostController extends BaseController
|
||||
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysPost post)
|
||||
public AjaxResult addSave(@Validated SysPost post)
|
||||
{
|
||||
if (UserConstants.POST_NAME_NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
||||
{
|
||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||
}
|
||||
else if (UserConstants.POST_CODE_NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
||||
{
|
||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||
}
|
||||
post.setCreateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(postService.insertPost(post));
|
||||
}
|
||||
@@ -117,8 +127,16 @@ public class SysPostController extends BaseController
|
||||
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysPost post)
|
||||
public AjaxResult editSave(@Validated SysPost post)
|
||||
{
|
||||
if (UserConstants.POST_NAME_NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
||||
{
|
||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||
}
|
||||
else if (UserConstants.POST_CODE_NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
||||
{
|
||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||
}
|
||||
post.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(postService.updatePost(post));
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
@@ -84,8 +86,16 @@ public class SysRoleController extends BaseController
|
||||
@Log(title = "角色管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysRole role)
|
||||
public AjaxResult addSave(@Validated SysRole role)
|
||||
{
|
||||
if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
||||
{
|
||||
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||
}
|
||||
else if (UserConstants.ROLE_KEY_NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
||||
{
|
||||
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||
}
|
||||
role.setCreateBy(ShiroUtils.getLoginName());
|
||||
ShiroUtils.clearCachedAuthorizationInfo();
|
||||
return toAjax(roleService.insertRole(role));
|
||||
@@ -109,8 +119,16 @@ public class SysRoleController extends BaseController
|
||||
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysRole role)
|
||||
public AjaxResult editSave(@Validated SysRole role)
|
||||
{
|
||||
if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
||||
{
|
||||
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||
}
|
||||
else if (UserConstants.ROLE_KEY_NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
||||
{
|
||||
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||
}
|
||||
role.setUpdateBy(ShiroUtils.getLoginName());
|
||||
ShiroUtils.clearCachedAuthorizationInfo();
|
||||
return toAjax(roleService.updateRole(role));
|
||||
@@ -135,7 +153,13 @@ public class SysRoleController extends BaseController
|
||||
@ResponseBody
|
||||
public AjaxResult authDataScopeSave(SysRole role)
|
||||
{
|
||||
return toAjax(roleService.authDataScope(role));
|
||||
role.setUpdateBy(ShiroUtils.getLoginName());
|
||||
if (roleService.authDataScope(role) > 0)
|
||||
{
|
||||
ShiroUtils.setSysUser(userService.selectUserById(ShiroUtils.getSysUser().getUserId()));
|
||||
return success();
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:role:remove")
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
@@ -116,11 +118,19 @@ public class SysUserController extends BaseController
|
||||
@Log(title = "用户管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SysUser user)
|
||||
public AjaxResult addSave(@Validated SysUser user)
|
||||
{
|
||||
if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId()))
|
||||
if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user.getLoginName())))
|
||||
{
|
||||
return error("不允许修改超级管理员用户");
|
||||
return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
|
||||
}
|
||||
else if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return error("新增用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return error("新增用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||
@@ -147,12 +157,20 @@ public class SysUserController extends BaseController
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SysUser user)
|
||||
public AjaxResult editSave(@Validated SysUser user)
|
||||
{
|
||||
if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId()))
|
||||
{
|
||||
return error("不允许修改超级管理员用户");
|
||||
}
|
||||
else if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return error("修改用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
user.setUpdateBy(ShiroUtils.getLoginName());
|
||||
return toAjax(userService.updateUser(user));
|
||||
}
|
||||
@@ -174,7 +192,15 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||
return toAjax(userService.resetUserPwd(user));
|
||||
if (userService.resetUserPwd(user) > 0)
|
||||
{
|
||||
if (ShiroUtils.getUserId() == user.getUserId())
|
||||
{
|
||||
ShiroUtils.setSysUser(userService.selectUserById(user.getUserId()));
|
||||
}
|
||||
return success();
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:remove")
|
||||
|
||||
@@ -1,116 +1,144 @@
|
||||
package com.ruoyi.web.controller.tool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* swagger 测试方法
|
||||
* swagger 用户测试方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api("用户信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/test/*")
|
||||
@RequestMapping("/test/user")
|
||||
public class TestController extends BaseController
|
||||
{
|
||||
private final static List<Test> testList = new ArrayList<>();
|
||||
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
|
||||
{
|
||||
testList.add(new Test("1", "admin", "admin123"));
|
||||
testList.add(new Test("2", "ry", "admin123"));
|
||||
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
|
||||
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
|
||||
}
|
||||
|
||||
@ApiOperation("获取列表")
|
||||
@GetMapping("list")
|
||||
public List<Test> testList()
|
||||
@ApiOperation("获取用户列表")
|
||||
@GetMapping("/list")
|
||||
public AjaxResult userList()
|
||||
{
|
||||
return testList;
|
||||
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
|
||||
return AjaxResult.success(userList);
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户详细")
|
||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
|
||||
@GetMapping("/{userId}")
|
||||
public AjaxResult getUser(@PathVariable Integer userId)
|
||||
{
|
||||
if (!users.isEmpty() && users.containsKey(userId))
|
||||
{
|
||||
return AjaxResult.success(users.get(userId));
|
||||
}
|
||||
else
|
||||
{
|
||||
return error("用户不存在");
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("新增用户")
|
||||
@PostMapping("save")
|
||||
public AjaxResult save(Test test)
|
||||
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
|
||||
@PostMapping("/save")
|
||||
public AjaxResult save(UserEntity user)
|
||||
{
|
||||
return testList.add(test) ? success() : error();
|
||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||
{
|
||||
return error("用户ID不能为空");
|
||||
}
|
||||
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||
}
|
||||
|
||||
@ApiOperation("更新用户")
|
||||
@ApiImplicitParam(name = "Test", value = "单个用户信息", dataType = "Test")
|
||||
@PutMapping("update")
|
||||
public AjaxResult update(Test test)
|
||||
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
|
||||
@PutMapping("/update")
|
||||
public AjaxResult update(UserEntity user)
|
||||
{
|
||||
return testList.remove(test) && testList.add(test) ? success() : error();
|
||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||
{
|
||||
return error("用户ID不能为空");
|
||||
}
|
||||
if (users.isEmpty() || !users.containsKey(user.getUserId()))
|
||||
{
|
||||
return error("用户不存在");
|
||||
}
|
||||
users.remove(user.getUserId());
|
||||
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||
}
|
||||
|
||||
@ApiOperation("删除用户")
|
||||
@ApiImplicitParam(name = "Tests", value = "单个用户信息", dataType = "Test")
|
||||
@DeleteMapping("delete")
|
||||
public AjaxResult delete(Test test)
|
||||
@ApiOperation("删除用户信息")
|
||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
|
||||
@DeleteMapping("/{userId}")
|
||||
public AjaxResult delete(@PathVariable Integer userId)
|
||||
{
|
||||
return testList.remove(test) ? success() : error();
|
||||
if (!users.isEmpty() && users.containsKey(userId))
|
||||
{
|
||||
users.remove(userId);
|
||||
return success();
|
||||
}
|
||||
else
|
||||
{
|
||||
return error("用户不存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Test
|
||||
@ApiModel("用户实体")
|
||||
class UserEntity
|
||||
{
|
||||
private String userId;
|
||||
@ApiModelProperty("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("用户名称")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("用户密码")
|
||||
private String password;
|
||||
|
||||
public Test()
|
||||
@ApiModelProperty("用户手机")
|
||||
private String mobile;
|
||||
|
||||
public UserEntity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Test(String userId, String username, String password)
|
||||
public UserEntity(Integer userId, String username, String password, String mobile)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Test test = (Test) o;
|
||||
|
||||
return userId != null ? userId.equals(test.userId) : test.userId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (username != null ? username.hashCode() : 0);
|
||||
result = 31 * result + (password != null ? password.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getUserId()
|
||||
public Integer getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId)
|
||||
public void setUserId(Integer userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
@@ -134,4 +162,14 @@ class Test
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getMobile()
|
||||
{
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public void setMobile(String mobile)
|
||||
{
|
||||
this.mobile = mobile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.ruoyi.web.core.config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.ruoyi.common.config.Global;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
@@ -28,11 +29,14 @@ public class SwaggerConfig
|
||||
public Docket createRestApi()
|
||||
{
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
// 详细定制
|
||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||
.apiInfo(apiInfo())
|
||||
// 设置哪些接口暴露给Swagger展示
|
||||
.select()
|
||||
// 指定当前包路径
|
||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.web.controller.tool"))
|
||||
// 扫描所有有注解的api,用这种方式更灵活
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
// 扫描指定包中的swagger注解
|
||||
//.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
@@ -45,9 +49,13 @@ public class SwaggerConfig
|
||||
{
|
||||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder()
|
||||
// 设置标题
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
// 描述
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
// 作者信息
|
||||
.contact(new Contact(Global.getName(), null, null))
|
||||
// 版本
|
||||
.version("版本号:" + Global.getVersion())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,10 @@ spring:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /monitor/druid/*
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username:
|
||||
login-password:
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
|
||||
@@ -3,20 +3,22 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 3.3.0
|
||||
version: 4.0.0
|
||||
# 版权年份
|
||||
copyrightYear: 2019
|
||||
# 文件上传
|
||||
profile: D:/profile/
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||
profile: D:/ruoyi/uploadPath
|
||||
# 获取ip地址开关
|
||||
addressEnabled: true
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
# 服务端口
|
||||
# 服务器的HTTP端口,默认为80
|
||||
port: 80
|
||||
servlet:
|
||||
# 项目contextPath
|
||||
# 应用的访问路径
|
||||
context-path: /
|
||||
tomcat:
|
||||
# tomcat的URI编码
|
||||
@@ -30,8 +32,7 @@ server:
|
||||
logging:
|
||||
level:
|
||||
com.ruoyi: debug
|
||||
org.springframework: WARN
|
||||
org.spring.springboot.dao: debug
|
||||
org.springframework: warn
|
||||
|
||||
# 用户配置
|
||||
user:
|
||||
@@ -50,7 +51,7 @@ spring:
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
basename: i18n/messages
|
||||
basename: static/i18n/messages
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
@@ -59,8 +60,10 @@ spring:
|
||||
# 文件上传
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 30MB
|
||||
max-request-size: 30MB
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
@@ -74,7 +77,7 @@ mybatis:
|
||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 加载全局的配置文件
|
||||
configLocation: classpath:mapper/mybatis-config.xml
|
||||
configLocation: classpath:mybatis/mybatis-config.xml
|
||||
|
||||
# PageHelper分页插件
|
||||
pagehelper:
|
||||
@@ -112,6 +115,10 @@ shiro:
|
||||
dbSyncPeriod: 1
|
||||
# 相隔多久检查一次session的有效性,默认就是10分钟
|
||||
validationInterval: 10
|
||||
# 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
|
||||
maxSession: -1
|
||||
# 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
||||
kickoutAfter: false
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
|
||||
@@ -22,6 +22,17 @@
|
||||
overflowToDisk="false"
|
||||
statistics="true">
|
||||
</cache>
|
||||
|
||||
<!-- 系统活跃用户缓存 -->
|
||||
<cache name="sys-userCache"
|
||||
maxEntriesLocalHeap="10000"
|
||||
overflowToDisk="false"
|
||||
eternal="false"
|
||||
diskPersistent="false"
|
||||
timeToLiveSeconds="0"
|
||||
timeToIdleSeconds="0"
|
||||
statistics="true">
|
||||
</cache>
|
||||
|
||||
</ehcache>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="/home/ruoyi/logs" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
@@ -14,8 +15,9 @@
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 按天回滚 daily -->
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
@@ -24,15 +26,20 @@
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
@@ -41,8 +48,11 @@
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
@@ -61,13 +71,10 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 显示形成的sql、使用的参数、结果集 -->
|
||||
<!--
|
||||
<logger name="java.sql" level="debug" />
|
||||
<logger name="org.springframework.jdbc" level="debug" />
|
||||
-->
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.ruoyi" level="info" />
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn" />
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
|
||||
+15
-15
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE configuration
|
||||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
<configuration>
|
||||
|
||||
<settings>
|
||||
<setting name="cacheEnabled" value="true" /> <!-- 全局映射器启用缓存 -->
|
||||
<setting name="useGeneratedKeys" value="true" /> <!-- 允许 JDBC 支持自动生成主键 -->
|
||||
<setting name="defaultExecutorType" value="REUSE" /> <!-- 配置默认的执行器 -->
|
||||
<setting name="logImpl" value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 -->
|
||||
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> 驼峰式命名 -->
|
||||
</settings>
|
||||
|
||||
</configuration>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE configuration
|
||||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
<configuration>
|
||||
|
||||
<settings>
|
||||
<setting name="cacheEnabled" value="true" /> <!-- 全局映射器启用缓存 -->
|
||||
<setting name="useGeneratedKeys" value="true" /> <!-- 允许 JDBC 支持自动生成主键 -->
|
||||
<setting name="defaultExecutorType" value="REUSE" /> <!-- 配置默认的执行器 -->
|
||||
<setting name="logImpl" value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 -->
|
||||
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> 驼峰式命名 -->
|
||||
</settings>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,550 @@
|
||||
/*!
|
||||
* bootstrap-fileinput v5.0.4
|
||||
* http://plugins.krajee.com/file-input
|
||||
*
|
||||
* Krajee default styling for bootstrap-fileinput.
|
||||
*
|
||||
* Author: Kartik Visweswaran
|
||||
* Copyright: 2014 - 2019, Kartik Visweswaran, Krajee.com
|
||||
*
|
||||
* Licensed under the BSD-3-Clause
|
||||
* https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
|
||||
*/
|
||||
.file-loading input[type=file], input[type=file].file-loading {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.file-no-browse {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 20%;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
font-size: 0;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.kv-hidden, .file-caption-icon, .file-zoom-dialog .modal-header:before, .file-zoom-dialog .modal-header:after, .file-input-new .file-preview, .file-input-new .close, .file-input-new .glyphicon-file, .file-input-new .fileinput-remove-button, .file-input-new .fileinput-upload-button, .file-input-new .no-browse .input-group-btn, .file-input-ajax-new .fileinput-remove-button, .file-input-ajax-new .fileinput-upload-button, .file-input-ajax-new .no-browse .input-group-btn, .hide-content .kv-file-content, .is-locked .fileinput-upload-button, .is-locked .fileinput-remove-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn-file input[type=file], .file-caption-icon, .file-preview .fileinput-remove, .krajee-default .file-thumb-progress, .file-zoom-dialog .btn-navigate, .file-zoom-dialog .floating-buttons {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.file-caption-icon .kv-caption-icon {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.file-input, .file-loading:before, .btn-file, .file-caption, .file-preview, .krajee-default.file-preview-frame, .krajee-default .file-thumbnail-footer, .file-zoom-dialog .modal-dialog {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-error-message pre, .file-error-message ul, .krajee-default .file-actions, .krajee-default .file-other-error {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.file-error-message pre, .file-error-message ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.krajee-default .file-drag-handle, .krajee-default .file-upload-indicator {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.krajee-default .file-thumb-progress .progress, .krajee-default .file-thumb-progress .progress-bar {
|
||||
height: 11px;
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.krajee-default .file-thumb-progress .progress, .kv-upload-progress .progress {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.krajee-default .file-caption-info, .krajee-default .file-size-info {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 160px;
|
||||
height: 15px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.file-zoom-content > .file-object.type-video, .file-zoom-content > .file-object.type-flash, .file-zoom-content > .file-object.type-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.file-zoom-content > .file-object.type-video, .file-zoom-content > .file-object.type-flash {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-zoom-content > .file-object.type-pdf, .file-zoom-content > .file-object.type-html, .file-zoom-content > .file-object.type-text, .file-zoom-content > .file-object.type-default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-loading:before {
|
||||
content: " Loading...";
|
||||
display: inline-block;
|
||||
padding-left: 20px;
|
||||
line-height: 16px;
|
||||
font-size: 13px;
|
||||
font-variant: small-caps;
|
||||
color: #999;
|
||||
background: transparent url(loading.gif) top left no-repeat;
|
||||
}
|
||||
|
||||
.file-object {
|
||||
margin: 0 0 -5px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-file {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-file input[type=file] {
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
text-align: right;
|
||||
opacity: 0;
|
||||
background: none repeat scroll 0 0 transparent;
|
||||
cursor: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.btn-file ::-ms-browse {
|
||||
font-size: 10000px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-caption .file-caption-name {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.file-caption.icon-visible .file-caption-icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.file-caption.icon-visible .file-caption-name {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.file-caption-icon {
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.file-error-message {
|
||||
color: #a94442;
|
||||
background-color: #f2dede;
|
||||
margin: 5px;
|
||||
border: 1px solid #ebccd1;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.file-error-message pre {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.file-caption-disabled {
|
||||
background-color: #eee;
|
||||
cursor: not-allowed;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.file-preview {
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.file-preview .btn-xs {
|
||||
padding: 1px 5px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.file-preview .fileinput-remove {
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
.file-preview .clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-preview-image {
|
||||
font: 40px Impact, Charcoal, sans-serif;
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame {
|
||||
margin: 8px;
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
box-shadow: 0 0 10px 0 rgba(0,0,0,0.2);
|
||||
padding: 6px;
|
||||
float: left;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame .kv-file-content {
|
||||
width: 213px;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-other-frame {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame[data-template="audio"] .kv-file-content {
|
||||
width: 240px;
|
||||
height: 55px;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame .file-thumbnail-footer {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.krajee-default.file-preview-frame:not(.file-preview-error):hover {
|
||||
border: 1px solid rgba(0,0,0,0.3);
|
||||
box-shadow: 0 0 10px 0 rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-text {
|
||||
display: block;
|
||||
color: #428bca;
|
||||
border: 1px solid #ddd;
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
outline: none;
|
||||
padding: 8px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-html {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.krajee-default .file-other-icon {
|
||||
font-size: 6em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.krajee-default .file-footer-buttons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.krajee-default .file-footer-caption {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding-top: 4px;
|
||||
font-size: 11px;
|
||||
color: #777;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.file-upload-stats {
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.kv-upload-progress .file-upload-stats {
|
||||
font-size: 12px;
|
||||
margin: -10px 0 5px;
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-error {
|
||||
opacity: 0.65;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.krajee-default .file-thumb-progress {
|
||||
height: 11px;
|
||||
top: 37px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.krajee-default.kvsortable-ghost {
|
||||
background: #e1edf7;
|
||||
border: 2px solid #a1abff;
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-other:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.kv-upload-progress .progress {
|
||||
height: 20px;
|
||||
margin: 10px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.kv-upload-progress .progress-bar {
|
||||
height: 20px;
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
/*noinspection CssOverwrittenProperties*/
|
||||
.file-zoom-dialog .file-other-icon {
|
||||
font-size: 22em;
|
||||
font-size: 50vmin;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .modal-dialog {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .btn-navigate {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
opacity: 0.7;
|
||||
top: 45%;
|
||||
font-size: 4em;
|
||||
color: #1c94c4;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .btn-navigate:not([disabled]):hover {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .floating-buttons {
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .btn-navigate[disabled] {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .btn-prev {
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .btn-next {
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .kv-zoom-title {
|
||||
font-weight: 300;
|
||||
color: #999;
|
||||
max-width: 50%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.file-input-new .no-browse .form-control {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.file-input-ajax-new .no-browse .form-control {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.file-caption-main {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-thumb-loading {
|
||||
background: transparent url(loading.gif) no-repeat scroll center center content-box !important;
|
||||
}
|
||||
|
||||
.file-drop-zone {
|
||||
border: 1px dashed #aaa;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin: 12px 15px 12px 12px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.file-drop-zone.clickable:hover {
|
||||
border: 2px dashed #999;
|
||||
}
|
||||
|
||||
.file-drop-zone.clickable:focus {
|
||||
border: 2px solid #5acde2;
|
||||
}
|
||||
|
||||
.file-drop-zone .file-preview-thumbnails {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.file-drop-zone-title {
|
||||
color: #aaa;
|
||||
font-size: 1.6em;
|
||||
padding: 85px 10px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.file-highlighted {
|
||||
border: 2px dashed #999 !important;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.file-uploading {
|
||||
background: url(loading-sm.gif) no-repeat center bottom 10px;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.file-zoom-fullscreen .modal-dialog {
|
||||
min-width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.file-zoom-fullscreen .modal-content {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.file-zoom-fullscreen .modal-body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.floating-buttons {
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.floating-buttons .btn-kv {
|
||||
margin-left: 3px;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.kv-zoom-actions .btn-kv {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.file-zoom-content {
|
||||
height: 480px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.file-zoom-content .file-preview-image {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.file-zoom-content .file-preview-video {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.file-zoom-content > .file-object.type-image {
|
||||
height: auto;
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
.file-zoom-content > .file-object.type-audio {
|
||||
width: auto;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.file-zoom-dialog .modal-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.file-zoom-dialog .modal-lg {
|
||||
max-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.file-preview-thumbnails {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.file-zoom-dialog .modal-header {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.krajee-default.file-preview-frame:not([data-template="audio"]) .kv-file-content {
|
||||
width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.file-loading[dir=rtl]:before {
|
||||
background: transparent url(loading.gif) top right no-repeat;
|
||||
padding-left: 0;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.file-sortable .file-drag-handle {
|
||||
cursor: move;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.file-sortable .file-drag-handle:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.clickable .file-drop-zone-title {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-preview-initial.sortable-chosen {
|
||||
background-color: #d9edf7;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+12
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 847 B |
+429
@@ -0,0 +1,429 @@
|
||||
/*!
|
||||
* Bootstrap-select v1.13.10 (https://developer.snapappointments.com/bootstrap-select)
|
||||
*
|
||||
* Copyright 2012-2019 SnapAppointments, LLC
|
||||
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
select.bs-select-hidden,
|
||||
.bootstrap-select > select.bs-select-hidden,
|
||||
select.selectpicker {
|
||||
display: none !important;
|
||||
}
|
||||
.bootstrap-select {
|
||||
width: 220px \0;
|
||||
/*IE9 and below*/
|
||||
vertical-align: middle;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: justify;
|
||||
-webkit-justify-content: space-between;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle:after {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
|
||||
color: #999;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.bootstrap-select > select {
|
||||
position: absolute !important;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
display: block !important;
|
||||
width: 0.5px !important;
|
||||
height: 100% !important;
|
||||
padding: 0 !important;
|
||||
opacity: 0 !important;
|
||||
border: none;
|
||||
z-index: 0 !important;
|
||||
}
|
||||
.bootstrap-select > select.mobile-device {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
z-index: 2 !important;
|
||||
}
|
||||
.has-error .bootstrap-select .dropdown-toggle,
|
||||
.error .bootstrap-select .dropdown-toggle,
|
||||
.bootstrap-select.is-invalid .dropdown-toggle,
|
||||
.was-validated .bootstrap-select .selectpicker:invalid + .dropdown-toggle {
|
||||
border-color: #b94a48;
|
||||
}
|
||||
.bootstrap-select.is-valid .dropdown-toggle,
|
||||
.was-validated .bootstrap-select .selectpicker:valid + .dropdown-toggle {
|
||||
border-color: #28a745;
|
||||
}
|
||||
.bootstrap-select.fit-width {
|
||||
width: auto !important;
|
||||
}
|
||||
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||
width: 220px;
|
||||
}
|
||||
.bootstrap-select > select.mobile-device:focus + .dropdown-toggle,
|
||||
.bootstrap-select .dropdown-toggle:focus {
|
||||
outline: thin dotted #333333 !important;
|
||||
outline: 5px auto -webkit-focus-ring-color !important;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.bootstrap-select.form-control {
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
height: auto;
|
||||
}
|
||||
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select.form-control.input-group-btn {
|
||||
float: none;
|
||||
z-index: auto;
|
||||
}
|
||||
.form-inline .bootstrap-select,
|
||||
.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
|
||||
width: auto;
|
||||
}
|
||||
.bootstrap-select:not(.input-group-btn),
|
||||
.bootstrap-select[class*="col-"] {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
}
|
||||
.bootstrap-select.dropdown-menu-right,
|
||||
.bootstrap-select[class*="col-"].dropdown-menu-right,
|
||||
.row .bootstrap-select[class*="col-"].dropdown-menu-right {
|
||||
float: right;
|
||||
}
|
||||
.form-inline .bootstrap-select,
|
||||
.form-horizontal .bootstrap-select,
|
||||
.form-group .bootstrap-select {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.form-group-lg .bootstrap-select.form-control,
|
||||
.form-group-sm .bootstrap-select.form-control {
|
||||
padding: 0;
|
||||
}
|
||||
.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
|
||||
.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
|
||||
height: 100%;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select.form-control-sm .dropdown-toggle,
|
||||
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select.form-control-sm .dropdown-toggle {
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
.form-inline .bootstrap-select .form-control {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select.disabled,
|
||||
.bootstrap-select > .disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bootstrap-select.disabled:focus,
|
||||
.bootstrap-select > .disabled:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
.bootstrap-select.bs-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.bootstrap-select.bs-container .dropdown-menu {
|
||||
z-index: 1060;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-option {
|
||||
position: static;
|
||||
top: 0;
|
||||
left: 0;
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 1 auto;
|
||||
-ms-flex: 0 1 auto;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.bs3.bootstrap-select .dropdown-toggle .filter-option {
|
||||
padding-right: inherit;
|
||||
}
|
||||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
|
||||
position: absolute;
|
||||
padding-top: inherit;
|
||||
padding-bottom: inherit;
|
||||
padding-left: inherit;
|
||||
float: none;
|
||||
}
|
||||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
|
||||
padding-right: inherit;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-expand {
|
||||
width: 0 !important;
|
||||
float: left;
|
||||
opacity: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .caret {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 12px;
|
||||
margin-top: -2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.input-group .bootstrap-select.form-control .dropdown-toggle {
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select[class*="col-"] .dropdown-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu {
|
||||
min-width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu > .inner:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu.inner {
|
||||
position: static;
|
||||
float: none;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li {
|
||||
position: relative;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li.active small {
|
||||
color: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li.disabled a {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a.opt {
|
||||
position: relative;
|
||||
padding-left: 2.25em;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a span.check-mark {
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a span.text {
|
||||
display: inline-block;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li small {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu .notify {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
width: 96%;
|
||||
margin: 0 2%;
|
||||
min-height: 26px;
|
||||
padding: 3px 5px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #e3e3e3;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
pointer-events: none;
|
||||
opacity: 0.9;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bootstrap-select .no-results {
|
||||
padding: 3px;
|
||||
background: #f5f5f5;
|
||||
margin: 0 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option {
|
||||
position: static;
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
|
||||
display: inline;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
|
||||
content: '\00a0';
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .caret {
|
||||
position: static;
|
||||
top: auto;
|
||||
margin-top: -1px;
|
||||
}
|
||||
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
right: 15px;
|
||||
top: 5px;
|
||||
}
|
||||
.bootstrap-select.show-tick .dropdown-menu li a span.text {
|
||||
margin-right: 34px;
|
||||
}
|
||||
.bootstrap-select .bs-ok-default:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0.5em;
|
||||
height: 1em;
|
||||
border-style: solid;
|
||||
border-width: 0 0.26em 0.26em 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
|
||||
z-index: 1061;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
|
||||
content: '';
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 9px;
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
|
||||
content: '';
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid white;
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 10px;
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
|
||||
bottom: auto;
|
||||
top: -4px;
|
||||
border-top: 7px solid rgba(204, 204, 204, 0.2);
|
||||
border-bottom: 0;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
|
||||
bottom: auto;
|
||||
top: -4px;
|
||||
border-top: 6px solid white;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
|
||||
right: 12px;
|
||||
left: auto;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
|
||||
right: 13px;
|
||||
left: auto;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
|
||||
display: block;
|
||||
}
|
||||
.bs-searchbox,
|
||||
.bs-actionsbox,
|
||||
.bs-donebutton {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
.bs-actionsbox {
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bs-actionsbox .btn-group button {
|
||||
width: 50%;
|
||||
}
|
||||
.bs-donebutton {
|
||||
float: left;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bs-donebutton .btn-group button {
|
||||
width: 100%;
|
||||
}
|
||||
.bs-searchbox + .bs-actionsbox {
|
||||
padding: 0 8px 4px;
|
||||
}
|
||||
.bs-searchbox .form-control {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
float: none;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-select.css.map */
|
||||
+3139
File diff suppressed because it is too large
Load Diff
+6
File diff suppressed because one or more lines are too long
+9
File diff suppressed because one or more lines are too long
+7
-8
File diff suppressed because one or more lines are too long
-27
@@ -1,27 +0,0 @@
|
||||
.fixed-table-header-columns,
|
||||
.fixed-table-body-columns {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fixed-table-header-columns .table,
|
||||
.fixed-table-body-columns .table {
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.fixed-table-header-columns .table.table-no-bordered,
|
||||
.fixed-table-body-columns .table.table-no-bordered {
|
||||
border-right: 1px solid transparent;
|
||||
}
|
||||
|
||||
.fixed-table-body-columns table {
|
||||
position: absolute;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.bootstrap-table .table-hover > tbody > tr.hover > td {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
+62
-21
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 基于bootstrap-table-fixed-columns修改
|
||||
* 支持左右列冻结
|
||||
* 支持左右列冻结、支持固定高度
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
(function ($) {
|
||||
@@ -22,33 +22,43 @@
|
||||
this.timeoutHeaderColumns_ = 0;
|
||||
this.timeoutBodyColumns_ = 0;
|
||||
if (this.options.fixedColumns) {
|
||||
this.$fixedBody = $([
|
||||
'<div class="fixed-table-column" style="position: absolute; background-color: #fff; border-right:1px solid #ddd;">',
|
||||
this.$fixedHeader = $([
|
||||
'<div class="left-fixed-table-columns">',
|
||||
'<table>',
|
||||
'<thead></thead>',
|
||||
'</table>',
|
||||
'</div>'].join(''));
|
||||
|
||||
this.$fixedHeader.find('table').attr('class', this.$el.attr('class'));
|
||||
this.$fixedHeaderColumns = this.$fixedHeader.find('thead');
|
||||
this.$tableHeader.before(this.$fixedHeader);
|
||||
|
||||
this.$fixedBody = $([
|
||||
'<div class="left-fixed-body-columns">',
|
||||
'<table>',
|
||||
'<tbody></tbody>',
|
||||
'</table>',
|
||||
'</div>'].join(''));
|
||||
|
||||
|
||||
this.$fixedBody.find('table').attr('class', this.$el.attr('class'));
|
||||
this.$fixedHeaderColumns = this.$fixedBody.find('thead');
|
||||
this.$fixedBodyColumns = this.$fixedBody.find('tbody');
|
||||
this.$tableBody.before(this.$fixedBody);
|
||||
}
|
||||
if (this.options.rightFixedColumns) {
|
||||
this.$rightfixedBody = $([
|
||||
'<div class="fixed-table-column" style="position: absolute;right:0px; background-color: #fff; border-right:1px solid #ddd;">',
|
||||
'<div class="right-fixed-table-columns">',
|
||||
'<table>',
|
||||
'<thead></thead>',
|
||||
'<tbody></tbody>',
|
||||
'<tbody style="background-color: #fff;"></tbody>',
|
||||
'</table>',
|
||||
'</div>'].join(''));
|
||||
|
||||
this.$rightfixedBody.find('table').attr('class', this.$el.attr('class'));
|
||||
this.$rightfixedHeaderColumns = this.$rightfixedBody.find('thead');
|
||||
this.$rightfixedBodyColumns = this.$rightfixedBody.find('tbody');
|
||||
this.$tableBody.before(this.$rightfixedBody);
|
||||
if (this.options.fixedColumns) {
|
||||
$('.right-fixed-table-columns').attr('style','right:0px');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,9 +70,9 @@
|
||||
}
|
||||
this.initFixedColumns();
|
||||
|
||||
var $ltr = this.$header.find('tr:eq(0)').clone(),
|
||||
var $ltr = this.$header.find('tr:eq(0)').clone(true),
|
||||
$rtr = this.$header.find('tr:eq(0)').clone(),
|
||||
$lths = $ltr.clone().find('th'),
|
||||
$lths = $ltr.clone(true).find('th'),
|
||||
$rths = $rtr.clone().find('th');
|
||||
|
||||
$ltr.html('');
|
||||
@@ -78,9 +88,15 @@
|
||||
//左边列冻结
|
||||
if (this.options.fixedColumns) {
|
||||
for (var i = 0; i < this.options.fixedNumber; i++) {
|
||||
$ltr.append($lths.eq(i).clone());
|
||||
$ltr.append($lths.eq(i).clone(true));
|
||||
}
|
||||
this.$fixedHeaderColumns.html('').append($ltr);
|
||||
this.$selectAll = $ltr.find('[name="btSelectAll"]');
|
||||
this.$selectAll.on('click', function () {
|
||||
var checked = $(this).prop('checked');
|
||||
$(".left-fixed-body-columns input[name=btSelectItem]").filter(':enabled').prop('checked', checked);
|
||||
$('.fixed-table-body input[name=btSelectItem]').closest('tr').removeClass('selected');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -95,12 +111,12 @@
|
||||
if (this.options.fixedColumns) {
|
||||
this.$fixedBodyColumns.html('');
|
||||
this.$body.find('> tr[data-index]').each(function () {
|
||||
var $tr = $(this).clone(),
|
||||
$tds = $tr.clone().find('td');
|
||||
var $tr = $(this).clone(true),
|
||||
$tds = $tr.clone(true).find('td');
|
||||
|
||||
$tr.html('');
|
||||
for (var i = 0; i < that.options.fixedNumber; i++) {
|
||||
$tr.append($tds.eq(i).clone());
|
||||
$tr.append($tds.eq(i).clone(true));
|
||||
}
|
||||
that.$fixedBodyColumns.append($tr);
|
||||
});
|
||||
@@ -160,12 +176,11 @@
|
||||
if (that.options.detailView && !that.options.cardView) {
|
||||
index = i - 1;
|
||||
}
|
||||
|
||||
that.$fixedBody.find('thead th[data-field="' + visibleFields[index] + '"]')
|
||||
.find('.fht-cell').width($this.innerWidth() - 1);
|
||||
that.$fixedHeader.find('thead th[data-field="' + visibleFields[index] + '"]')
|
||||
.find('.fht-cell').width($this.innerWidth());
|
||||
headerWidth += $this.outerWidth();
|
||||
});
|
||||
this.$fixedBody.width(headerWidth - 1).show();
|
||||
this.$fixedHeader.width(headerWidth + 2).show();
|
||||
}
|
||||
if (that.options.rightFixedColumns) {
|
||||
this.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) {
|
||||
@@ -190,18 +205,44 @@
|
||||
|
||||
BootstrapTable.prototype.fitBodyColumns = function () {
|
||||
var that = this,
|
||||
top = -(parseInt(this.$el.css('margin-top')) - 2),
|
||||
height = this.$tableBody.height() - 2;
|
||||
top = -(parseInt(this.$el.css('margin-top'))),
|
||||
height = this.$tableBody.height();
|
||||
|
||||
if (that.options.fixedColumns) {
|
||||
if (!this.$body.find('> tr[data-index]').length) {
|
||||
this.$fixedBody.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.height) {
|
||||
top = this.$fixedHeader.height()- 1;
|
||||
height = height - top;
|
||||
}
|
||||
|
||||
this.$fixedBody.css({
|
||||
width: this.$fixedHeader.width(),
|
||||
height: height,
|
||||
top: top + 1
|
||||
}).show();
|
||||
|
||||
this.$body.find('> tr').each(function (i) {
|
||||
that.$fixedBody.find('tbody tr:eq(' + i + ')').height($(this).height());
|
||||
that.$fixedBody.find('tr:eq(' + i + ')').height($(this).height() - 0.5);
|
||||
var thattds = this;
|
||||
that.$fixedBody.find('tr:eq(' + i + ')').find('td').each(function (j) {
|
||||
$(this).width($($(thattds).find('td')[j]).width() + 1);
|
||||
});
|
||||
});
|
||||
|
||||
$.btTable.on("check.bs.table uncheck.bs.table", function (e, rows, $element) {
|
||||
var index= $element.data('index');
|
||||
$(this).find('.bs-checkbox').find('input[data-index="' + index + '"]').prop("checked", true);
|
||||
var selectFixedItem = $('.left-fixed-body-columns input[name=btSelectItem]');
|
||||
var checkAll = selectFixedItem.filter(':enabled').length &&
|
||||
selectFixedItem.filter(':enabled').length ===
|
||||
selectFixedItem.filter(':enabled').filter(':checked').length;
|
||||
$(".left-fixed-table-columns input[name=btSelectAll]").prop('checked', checkAll);
|
||||
$('.fixed-table-body input[name=btSelectItem]').closest('tr').removeClass('selected');
|
||||
});
|
||||
|
||||
//// events
|
||||
this.$tableBody.on('scroll', function () {
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* 实现表格拖拽功能
|
||||
* @version: v1.0.1
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var isSearch = false;
|
||||
|
||||
var rowAttr = function (row, index) {
|
||||
return {
|
||||
id: 'customId_' + index
|
||||
};
|
||||
};
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
reorderableRows: false,
|
||||
onDragStyle: null,
|
||||
onDropStyle: null,
|
||||
onDragClass: "reorder_rows_onDragClass",
|
||||
dragHandle: null,
|
||||
useRowAttrFunc: false,
|
||||
onReorderRowsDrag: function (table, row) {
|
||||
return false;
|
||||
},
|
||||
onReorderRowsDrop: function (table, row) {
|
||||
return false;
|
||||
},
|
||||
onReorderRow: function (newData) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
'reorder-row.bs.table': 'onReorderRow'
|
||||
});
|
||||
|
||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||
_init = BootstrapTable.prototype.init,
|
||||
_initSearch = BootstrapTable.prototype.initSearch;
|
||||
|
||||
BootstrapTable.prototype.init = function () {
|
||||
|
||||
if (!this.options.reorderableRows) {
|
||||
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
if (this.options.useRowAttrFunc) {
|
||||
this.options.rowAttributes = rowAttr;
|
||||
}
|
||||
|
||||
var onPostBody = this.options.onPostBody;
|
||||
this.options.onPostBody = function () {
|
||||
setTimeout(function () {
|
||||
that.makeRowsReorderable();
|
||||
onPostBody.apply();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
_init.apply(this, Array.prototype.slice.apply(arguments));
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.initSearch = function () {
|
||||
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!this.options.reorderableRows) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Known issue after search if you reorder the rows the data is not display properly
|
||||
//isSearch = true;
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.makeRowsReorderable = function () {
|
||||
if (this.options.cardView) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
this.$el.tableDnD({
|
||||
onDragStyle: that.options.onDragStyle,
|
||||
onDropStyle: that.options.onDropStyle,
|
||||
onDragClass: that.options.onDragClass,
|
||||
onDrop: that.onDrop,
|
||||
onDragStart: that.options.onReorderRowsDrag,
|
||||
dragHandle: that.options.dragHandle
|
||||
});
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.onDrop = function (table, droppedRow) {
|
||||
var tableBs = $(table),
|
||||
tableBsData = tableBs.data('bootstrap.table'),
|
||||
tableBsOptions = tableBs.data('bootstrap.table').options,
|
||||
row = null,
|
||||
newData = [];
|
||||
|
||||
for (var i = 0; i < table.tBodies[0].rows.length; i++) {
|
||||
row = $(table.tBodies[0].rows[i]);
|
||||
newData.push(tableBsOptions.data[row.data('index')]);
|
||||
row.data('index', i).attr('data-index', i);
|
||||
}
|
||||
|
||||
tableBsOptions.data = tableBsOptions.data.slice(0, tableBsData.pageFrom - 1)
|
||||
.concat(newData)
|
||||
.concat(tableBsOptions.data.slice(tableBsData.pageTo));
|
||||
|
||||
//Call the user defined function
|
||||
tableBsOptions.onReorderRowsDrop.apply(table, [table, droppedRow]);
|
||||
|
||||
//Call the event reorder-row
|
||||
tableBsData.trigger('reorder-row', newData);
|
||||
};
|
||||
})(jQuery);
|
||||
+598
@@ -0,0 +1,598 @@
|
||||
/**
|
||||
* TableDnD plug-in for JQuery, allows you to drag and drop table rows
|
||||
* You can set up various options to control how the system will work
|
||||
* Copyright (c) Denis Howlett <denish@isocra.com>
|
||||
* License: MIT.
|
||||
* See https://github.com/isocra/TableDnD
|
||||
*/
|
||||
!function ($, window, document, undefined) {
|
||||
|
||||
var startEvent = 'touchstart mousedown',
|
||||
moveEvent = 'touchmove mousemove',
|
||||
endEvent = 'touchend mouseup';
|
||||
|
||||
$(document).ready(function () {
|
||||
function parseStyle(css) {
|
||||
var objMap = {},
|
||||
parts = css.match(/([^;:]+)/g) || [];
|
||||
while (parts.length)
|
||||
objMap[parts.shift()] = parts.shift().trim();
|
||||
|
||||
return objMap;
|
||||
}
|
||||
$('table').each(function () {
|
||||
if ($(this).data('table') === 'dnd') {
|
||||
|
||||
$(this).tableDnD({
|
||||
onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null,
|
||||
onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null,
|
||||
onDragClass: $(this).data('ondragclass') === undefined && "tDnD_whileDrag" || $(this).data('ondragclass'),
|
||||
onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null,
|
||||
onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null,
|
||||
onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')),
|
||||
scrollAmount: $(this).data('scrollamount') || 5,
|
||||
sensitivity: $(this).data('sensitivity') || 10,
|
||||
hierarchyLevel: $(this).data('hierarchylevel') || 0,
|
||||
indentArtifact: $(this).data('indentartifact') || '<div class="indent"> </div>',
|
||||
autoWidthAdjust: $(this).data('autowidthadjust') || true,
|
||||
autoCleanRelations: $(this).data('autocleanrelations') || true,
|
||||
jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t',
|
||||
serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/,
|
||||
serializeParamName: $(this).data('serializeparamname') || false,
|
||||
dragHandle: $(this).data('draghandle') || null
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
jQuery.tableDnD = {
|
||||
/** Keep hold of the current table being dragged */
|
||||
currentTable: null,
|
||||
/** Keep hold of the current drag object if any */
|
||||
dragObject: null,
|
||||
/** The current mouse offset */
|
||||
mouseOffset: null,
|
||||
/** Remember the old value of X and Y so that we don't do too much processing */
|
||||
oldX: 0,
|
||||
oldY: 0,
|
||||
|
||||
/** Actually build the structure */
|
||||
build: function(options) {
|
||||
// Set up the defaults if any
|
||||
|
||||
this.each(function() {
|
||||
// This is bound to each matching table, set up the defaults and override with user options
|
||||
this.tableDnDConfig = $.extend({
|
||||
onDragStyle: null,
|
||||
onDropStyle: null,
|
||||
// Add in the default class for whileDragging
|
||||
onDragClass: "tDnD_whileDrag",
|
||||
onDrop: null,
|
||||
onDragStart: null,
|
||||
onDragStop: null,
|
||||
scrollAmount: 5,
|
||||
/** Sensitivity setting will throttle the trigger rate for movement detection */
|
||||
sensitivity: 10,
|
||||
/** Hierarchy level to support parent child. 0 switches this functionality off */
|
||||
hierarchyLevel: 0,
|
||||
/** The html artifact to prepend the first cell with as indentation */
|
||||
indentArtifact: '<div class="indent"> </div>',
|
||||
/** Automatically adjust width of first cell */
|
||||
autoWidthAdjust: true,
|
||||
/** Automatic clean-up to ensure relationship integrity */
|
||||
autoCleanRelations: true,
|
||||
/** Specify a number (4) as number of spaces or any indent string for JSON.stringify */
|
||||
jsonPretifySeparator: '\t',
|
||||
/** The regular expression to use to trim row IDs */
|
||||
serializeRegexp: /[^\-]*$/,
|
||||
/** If you want to specify another parameter name instead of the table ID */
|
||||
serializeParamName: false,
|
||||
/** If you give the name of a class here, then only Cells with this class will be draggable */
|
||||
dragHandle: null
|
||||
}, options || {});
|
||||
|
||||
// Now make the rows draggable
|
||||
$.tableDnD.makeDraggable(this);
|
||||
// Prepare hierarchy support
|
||||
this.tableDnDConfig.hierarchyLevel
|
||||
&& $.tableDnD.makeIndented(this);
|
||||
});
|
||||
|
||||
// Don't break the chain
|
||||
return this;
|
||||
},
|
||||
makeIndented: function (table) {
|
||||
var config = table.tableDnDConfig,
|
||||
rows = table.rows,
|
||||
firstCell = $(rows).first().find('td:first')[0],
|
||||
indentLevel = 0,
|
||||
cellWidth = 0,
|
||||
longestCell,
|
||||
tableStyle;
|
||||
|
||||
if ($(table).hasClass('indtd'))
|
||||
return null;
|
||||
|
||||
tableStyle = $(table).addClass('indtd').attr('style');
|
||||
$(table).css({whiteSpace: "nowrap"});
|
||||
|
||||
for (var w = 0; w < rows.length; w++) {
|
||||
if (cellWidth < $(rows[w]).find('td:first').text().length) {
|
||||
cellWidth = $(rows[w]).find('td:first').text().length;
|
||||
longestCell = w;
|
||||
}
|
||||
}
|
||||
$(firstCell).css({width: 'auto'});
|
||||
for (w = 0; w < config.hierarchyLevel; w++)
|
||||
$(rows[longestCell]).find('td:first').prepend(config.indentArtifact);
|
||||
firstCell && $(firstCell).css({width: firstCell.offsetWidth});
|
||||
tableStyle && $(table).css(tableStyle);
|
||||
|
||||
for (w = 0; w < config.hierarchyLevel; w++)
|
||||
$(rows[longestCell]).find('td:first').children(':first').remove();
|
||||
|
||||
config.hierarchyLevel
|
||||
&& $(rows).each(function () {
|
||||
indentLevel = $(this).data('level') || 0;
|
||||
indentLevel <= config.hierarchyLevel
|
||||
&& $(this).data('level', indentLevel)
|
||||
|| $(this).data('level', 0);
|
||||
for (var i = 0; i < $(this).data('level'); i++)
|
||||
$(this).find('td:first').prepend(config.indentArtifact);
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
/** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
|
||||
makeDraggable: function(table) {
|
||||
var config = table.tableDnDConfig;
|
||||
|
||||
config.dragHandle
|
||||
// We only need to add the event to the specified cells
|
||||
&& $(config.dragHandle, table).each(function() {
|
||||
// The cell is bound to "this"
|
||||
$(this).bind(startEvent, function(e) {
|
||||
$.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config);
|
||||
return false;
|
||||
});
|
||||
})
|
||||
// For backwards compatibility, we add the event to the whole row
|
||||
// get all the rows as a wrapped set
|
||||
|| $(table.rows).each(function() {
|
||||
// Iterate through each row, the row is bound to "this"
|
||||
if (! $(this).hasClass("nodrag")) {
|
||||
$(this).bind(startEvent, function(e) {
|
||||
if (e.target.tagName === "TD" && event.target.className !== "nodrag") {
|
||||
$.tableDnD.initialiseDrag(this, table, this, e, config);
|
||||
return false;
|
||||
}
|
||||
}).css("cursor", "move"); // Store the tableDnD object
|
||||
} else {
|
||||
$(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class
|
||||
}
|
||||
});
|
||||
},
|
||||
currentOrder: function() {
|
||||
var rows = this.currentTable.rows;
|
||||
return $.map(rows, function (val) {
|
||||
return ($(val).data('level') + val.id).replace(/\s/g, '');
|
||||
}).join('');
|
||||
},
|
||||
initialiseDrag: function(dragObject, table, target, e, config) {
|
||||
this.dragObject = dragObject;
|
||||
this.currentTable = table;
|
||||
this.mouseOffset = this.getMouseOffset(target, e);
|
||||
this.originalOrder = this.currentOrder();
|
||||
|
||||
// Now we need to capture the mouse up and mouse move event
|
||||
// We can use bind so that we don't interfere with other event handlers
|
||||
$(document)
|
||||
.bind(moveEvent, this.mousemove)
|
||||
.bind(endEvent, this.mouseup);
|
||||
|
||||
// Call the onDragStart method if there is one
|
||||
config.onDragStart
|
||||
&& config.onDragStart(table, target);
|
||||
},
|
||||
updateTables: function() {
|
||||
this.each(function() {
|
||||
// this is now bound to each matching table
|
||||
if (this.tableDnDConfig)
|
||||
$.tableDnD.makeDraggable(this);
|
||||
});
|
||||
},
|
||||
/** Get the mouse coordinates from the event (allowing for browser differences) */
|
||||
mouseCoords: function(e) {
|
||||
if (e.originalEvent.changedTouches)
|
||||
return {
|
||||
x: e.originalEvent.changedTouches[0].clientX,
|
||||
y: e.originalEvent.changedTouches[0].clientY
|
||||
};
|
||||
|
||||
if(e.pageX || e.pageY)
|
||||
return {
|
||||
x: e.pageX,
|
||||
y: e.pageY
|
||||
};
|
||||
|
||||
return {
|
||||
x: e.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||
y: e.clientY + document.body.scrollTop - document.body.clientTop
|
||||
};
|
||||
},
|
||||
/** Given a target element and a mouse eent, get the mouse offset from that element.
|
||||
To do this we need the element's position and the mouse position */
|
||||
getMouseOffset: function(target, e) {
|
||||
var mousePos,
|
||||
docPos;
|
||||
|
||||
e = e || window.event;
|
||||
|
||||
docPos = this.getPosition(target);
|
||||
mousePos = this.mouseCoords(e);
|
||||
|
||||
return {
|
||||
x: mousePos.x - docPos.x,
|
||||
y: mousePos.y - docPos.y
|
||||
};
|
||||
},
|
||||
/** Get the position of an element by going up the DOM tree and adding up all the offsets */
|
||||
getPosition: function(element) {
|
||||
var left = 0,
|
||||
top = 0;
|
||||
|
||||
// Safari fix -- thanks to Luis Chato for this!
|
||||
// Safari 2 doesn't correctly grab the offsetTop of a table row
|
||||
// this is detailed here:
|
||||
// http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
|
||||
// the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
|
||||
// note that firefox will return a text node as a first child, so designing a more thorough
|
||||
// solution may need to take that into account, for now this seems to work in firefox, safari, ie
|
||||
if (element.offsetHeight === 0)
|
||||
element = element.firstChild; // a table cell
|
||||
|
||||
while (element.offsetParent) {
|
||||
left += element.offsetLeft;
|
||||
top += element.offsetTop;
|
||||
element = element.offsetParent;
|
||||
}
|
||||
|
||||
left += element.offsetLeft;
|
||||
top += element.offsetTop;
|
||||
|
||||
return {
|
||||
x: left,
|
||||
y: top
|
||||
};
|
||||
},
|
||||
autoScroll: function (mousePos) {
|
||||
var config = this.currentTable.tableDnDConfig,
|
||||
yOffset = window.pageYOffset,
|
||||
windowHeight = window.innerHeight
|
||||
? window.innerHeight
|
||||
: document.documentElement.clientHeight
|
||||
? document.documentElement.clientHeight
|
||||
: document.body.clientHeight;
|
||||
|
||||
// Windows version
|
||||
// yOffset=document.body.scrollTop;
|
||||
if (document.all)
|
||||
if (typeof document.compatMode !== 'undefined'
|
||||
&& document.compatMode !== 'BackCompat')
|
||||
yOffset = document.documentElement.scrollTop;
|
||||
else if (typeof document.body !== 'undefined')
|
||||
yOffset = document.body.scrollTop;
|
||||
|
||||
mousePos.y - yOffset < config.scrollAmount
|
||||
&& window.scrollBy(0, - config.scrollAmount)
|
||||
|| windowHeight - (mousePos.y - yOffset) < config.scrollAmount
|
||||
&& window.scrollBy(0, config.scrollAmount);
|
||||
|
||||
},
|
||||
moveVerticle: function (moving, currentRow) {
|
||||
|
||||
if (0 !== moving.vertical
|
||||
// If we're over a row then move the dragged row to there so that the user sees the
|
||||
// effect dynamically
|
||||
&& currentRow
|
||||
&& this.dragObject !== currentRow
|
||||
&& this.dragObject.parentNode === currentRow.parentNode)
|
||||
0 > moving.vertical
|
||||
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling)
|
||||
|| 0 < moving.vertical
|
||||
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow);
|
||||
|
||||
},
|
||||
moveHorizontal: function (moving, currentRow) {
|
||||
var config = this.currentTable.tableDnDConfig,
|
||||
currentLevel;
|
||||
|
||||
if (!config.hierarchyLevel
|
||||
|| 0 === moving.horizontal
|
||||
// We only care if moving left or right on the current row
|
||||
|| !currentRow
|
||||
|| this.dragObject !== currentRow)
|
||||
return null;
|
||||
|
||||
currentLevel = $(currentRow).data('level');
|
||||
|
||||
0 < moving.horizontal
|
||||
&& currentLevel > 0
|
||||
&& $(currentRow).find('td:first').children(':first').remove()
|
||||
&& $(currentRow).data('level', --currentLevel);
|
||||
|
||||
0 > moving.horizontal
|
||||
&& currentLevel < config.hierarchyLevel
|
||||
&& $(currentRow).prev().data('level') >= currentLevel
|
||||
&& $(currentRow).children(':first').prepend(config.indentArtifact)
|
||||
&& $(currentRow).data('level', ++currentLevel);
|
||||
|
||||
},
|
||||
mousemove: function(e) {
|
||||
var dragObj = $($.tableDnD.dragObject),
|
||||
config = $.tableDnD.currentTable.tableDnDConfig,
|
||||
currentRow,
|
||||
mousePos,
|
||||
moving,
|
||||
x,
|
||||
y;
|
||||
|
||||
e && e.preventDefault();
|
||||
|
||||
if (!$.tableDnD.dragObject)
|
||||
return false;
|
||||
|
||||
// prevent touch device screen scrolling
|
||||
e.type === 'touchmove'
|
||||
&& event.preventDefault(); // TODO verify this is event and not really e
|
||||
|
||||
// update the style to show we're dragging
|
||||
config.onDragClass
|
||||
&& dragObj.addClass(config.onDragClass)
|
||||
|| dragObj.css(config.onDragStyle);
|
||||
|
||||
mousePos = $.tableDnD.mouseCoords(e);
|
||||
x = mousePos.x - $.tableDnD.mouseOffset.x;
|
||||
y = mousePos.y - $.tableDnD.mouseOffset.y;
|
||||
|
||||
// auto scroll the window
|
||||
$.tableDnD.autoScroll(mousePos);
|
||||
|
||||
currentRow = $.tableDnD.findDropTargetRow(dragObj, y);
|
||||
moving = $.tableDnD.findDragDirection(x, y);
|
||||
|
||||
$.tableDnD.moveVerticle(moving, currentRow);
|
||||
$.tableDnD.moveHorizontal(moving, currentRow);
|
||||
|
||||
return false;
|
||||
},
|
||||
findDragDirection: function (x,y) {
|
||||
var sensitivity = this.currentTable.tableDnDConfig.sensitivity,
|
||||
oldX = this.oldX,
|
||||
oldY = this.oldY,
|
||||
xMin = oldX - sensitivity,
|
||||
xMax = oldX + sensitivity,
|
||||
yMin = oldY - sensitivity,
|
||||
yMax = oldY + sensitivity,
|
||||
moving = {
|
||||
horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1,
|
||||
vertical : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1
|
||||
};
|
||||
|
||||
// update the old value
|
||||
if (moving.horizontal !== 0)
|
||||
this.oldX = x;
|
||||
if (moving.vertical !== 0)
|
||||
this.oldY = y;
|
||||
|
||||
return moving;
|
||||
},
|
||||
/** We're only worried about the y position really, because we can only move rows up and down */
|
||||
findDropTargetRow: function(draggedRow, y) {
|
||||
var rowHeight = 0,
|
||||
rows = this.currentTable.rows,
|
||||
config = this.currentTable.tableDnDConfig,
|
||||
rowY = 0,
|
||||
row = null;
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
row = rows[i];
|
||||
rowY = this.getPosition(row).y;
|
||||
rowHeight = parseInt(row.offsetHeight) / 2;
|
||||
if (row.offsetHeight === 0) {
|
||||
rowY = this.getPosition(row.firstChild).y;
|
||||
rowHeight = parseInt(row.firstChild.offsetHeight) / 2;
|
||||
}
|
||||
// Because we always have to insert before, we need to offset the height a bit
|
||||
if (y > (rowY - rowHeight) && y < (rowY + rowHeight))
|
||||
// that's the row we're over
|
||||
// If it's the same as the current row, ignore it
|
||||
if (draggedRow.is(row)
|
||||
|| (config.onAllowDrop
|
||||
&& !config.onAllowDrop(draggedRow, row))
|
||||
// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
|
||||
|| $(row).hasClass("nodrop"))
|
||||
return null;
|
||||
else
|
||||
return row;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
processMouseup: function() {
|
||||
if (!this.currentTable || !this.dragObject)
|
||||
return null;
|
||||
|
||||
var config = this.currentTable.tableDnDConfig,
|
||||
droppedRow = this.dragObject,
|
||||
parentLevel = 0,
|
||||
myLevel = 0;
|
||||
|
||||
// Unbind the event handlers
|
||||
$(document)
|
||||
.unbind(moveEvent, this.mousemove)
|
||||
.unbind(endEvent, this.mouseup);
|
||||
|
||||
config.hierarchyLevel
|
||||
&& config.autoCleanRelations
|
||||
&& $(this.currentTable.rows).first().find('td:first').children().each(function () {
|
||||
myLevel = $(this).parents('tr:first').data('level');
|
||||
myLevel
|
||||
&& $(this).parents('tr:first').data('level', --myLevel)
|
||||
&& $(this).remove();
|
||||
})
|
||||
&& config.hierarchyLevel > 1
|
||||
&& $(this.currentTable.rows).each(function () {
|
||||
myLevel = $(this).data('level');
|
||||
if (myLevel > 1) {
|
||||
parentLevel = $(this).prev().data('level');
|
||||
while (myLevel > parentLevel + 1) {
|
||||
$(this).find('td:first').children(':first').remove();
|
||||
$(this).data('level', --myLevel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If we have a dragObject, then we need to release it,
|
||||
// The row will already have been moved to the right place so we just reset stuff
|
||||
config.onDragClass
|
||||
&& $(droppedRow).removeClass(config.onDragClass)
|
||||
|| $(droppedRow).css(config.onDropStyle);
|
||||
|
||||
this.dragObject = null;
|
||||
// Call the onDrop method if there is one
|
||||
config.onDrop
|
||||
&& this.originalOrder !== this.currentOrder()
|
||||
&& $(droppedRow).hide().fadeIn('fast')
|
||||
&& config.onDrop(this.currentTable, droppedRow);
|
||||
|
||||
// Call the onDragStop method if there is one
|
||||
config.onDragStop
|
||||
&& config.onDragStop(this.currentTable, droppedRow);
|
||||
|
||||
this.currentTable = null; // let go of the table too
|
||||
},
|
||||
mouseup: function(e) {
|
||||
e && e.preventDefault();
|
||||
$.tableDnD.processMouseup();
|
||||
return false;
|
||||
},
|
||||
jsonize: function(pretify) {
|
||||
var table = this.currentTable;
|
||||
if (pretify)
|
||||
return JSON.stringify(
|
||||
this.tableData(table),
|
||||
null,
|
||||
table.tableDnDConfig.jsonPretifySeparator
|
||||
);
|
||||
return JSON.stringify(this.tableData(table));
|
||||
},
|
||||
serialize: function() {
|
||||
return $.param(this.tableData(this.currentTable));
|
||||
},
|
||||
serializeTable: function(table) {
|
||||
var result = "";
|
||||
var paramName = table.tableDnDConfig.serializeParamName || table.id;
|
||||
var rows = table.rows;
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
if (result.length > 0) result += "&";
|
||||
var rowId = rows[i].id;
|
||||
if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
|
||||
rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
|
||||
result += paramName + '[]=' + rowId;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
serializeTables: function() {
|
||||
var result = [];
|
||||
$('table').each(function() {
|
||||
this.id && result.push($.param($.tableDnD.tableData(this)));
|
||||
});
|
||||
return result.join('&');
|
||||
},
|
||||
tableData: function (table) {
|
||||
var config = table.tableDnDConfig,
|
||||
previousIDs = [],
|
||||
currentLevel = 0,
|
||||
indentLevel = 0,
|
||||
rowID = null,
|
||||
data = {},
|
||||
getSerializeRegexp,
|
||||
paramName,
|
||||
currentID,
|
||||
rows;
|
||||
|
||||
if (!table)
|
||||
table = this.currentTable;
|
||||
if (!table || !table.rows || !table.rows.length)
|
||||
return {error: { code: 500, message: "Not a valid table."}};
|
||||
if (!table.id && !config.serializeParamName)
|
||||
return {error: { code: 500, message: "No serializable unique id provided."}};
|
||||
|
||||
rows = config.autoCleanRelations
|
||||
&& table.rows
|
||||
|| $.makeArray(table.rows);
|
||||
paramName = config.serializeParamName || table.id;
|
||||
currentID = paramName;
|
||||
|
||||
getSerializeRegexp = function (rowId) {
|
||||
if (rowId && config && config.serializeRegexp)
|
||||
return rowId.match(config.serializeRegexp)[0];
|
||||
return rowId;
|
||||
};
|
||||
|
||||
data[currentID] = [];
|
||||
!config.autoCleanRelations
|
||||
&& $(rows[0]).data('level')
|
||||
&& rows.unshift({id: 'undefined'});
|
||||
|
||||
|
||||
|
||||
for (var i=0; i < rows.length; i++) {
|
||||
if (config.hierarchyLevel) {
|
||||
indentLevel = $(rows[i]).data('level') || 0;
|
||||
if (indentLevel === 0) {
|
||||
currentID = paramName;
|
||||
previousIDs = [];
|
||||
}
|
||||
else if (indentLevel > currentLevel) {
|
||||
previousIDs.push([currentID, currentLevel]);
|
||||
currentID = getSerializeRegexp(rows[i-1].id);
|
||||
}
|
||||
else if (indentLevel < currentLevel) {
|
||||
for (var h = 0; h < previousIDs.length; h++) {
|
||||
if (previousIDs[h][1] === indentLevel)
|
||||
currentID = previousIDs[h][0];
|
||||
if (previousIDs[h][1] >= currentLevel)
|
||||
previousIDs[h][1] = 0;
|
||||
}
|
||||
}
|
||||
currentLevel = indentLevel;
|
||||
|
||||
if (!$.isArray(data[currentID]))
|
||||
data[currentID] = [];
|
||||
rowID = getSerializeRegexp(rows[i].id);
|
||||
rowID && data[currentID].push(rowID);
|
||||
}
|
||||
else {
|
||||
rowID = getSerializeRegexp(rows[i].id);
|
||||
rowID && data[currentID].push(rowID);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
jQuery.fn.extend(
|
||||
{
|
||||
tableDnD : $.tableDnD.build,
|
||||
tableDnDUpdate : $.tableDnD.updateTables,
|
||||
tableDnDSerialize : $.proxy($.tableDnD.serialize, $.tableDnD),
|
||||
tableDnDSerializeAll : $.tableDnD.serializeTables,
|
||||
tableDnDData : $.proxy($.tableDnD.tableData, $.tableDnD)
|
||||
}
|
||||
);
|
||||
|
||||
}(jQuery, window, window.document);
|
||||
Vendored
-14
@@ -1,14 +0,0 @@
|
||||
.bootstrap-tree-table .treetable-indent {width:16px; height: 16px; display: inline-block; position: relative;}
|
||||
.bootstrap-tree-table .treetable-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
|
||||
.bootstrap-tree-table .treetable-selected{background: #f5f5f5 !important;}
|
||||
.bootstrap-tree-table .treetable-table{border:0 !important;margin-bottom:0}
|
||||
.bootstrap-tree-table .treetable-table tbody {display:block;height:auto;}
|
||||
.bootstrap-tree-table .treetable-table thead, .treetable-table tbody tr {display:table;width:100%;table-layout:fixed;}
|
||||
.bootstrap-tree-table .treetable-thead th{line-height:24px;border: 0 !important;border-radius: 4px;border-left:0px solid #e7eaec !important;border-bottom:1px solid #ccc!important;text-align: left;}
|
||||
.bootstrap-tree-table .treetable-thead tr :first-child{border-left:0 !important}
|
||||
.bootstrap-tree-table .treetable-tbody td{border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
|
||||
.bootstrap-tree-table .treetable-tbody tr :first-child{border-left:0 !important}
|
||||
.bootstrap-tree-table .treetable-bars .tool-left, .bootstrap-tree-table .treetable-bars .tool-right{margin-top: 10px; margin-bottom: 10px;}
|
||||
.bootstrap-tree-table .treetable-bars .tool-left{float: left;}
|
||||
.bootstrap-tree-table .treetable-bars .tool-right{float: right;}
|
||||
.bootstrap-tree-table .treetable-bars .columns li label{display: block;padding: 3px 20px;clear: both;font-weight: 400;line-height: 1.428571429;max-width: 100%;margin-bottom: 5px;cursor:pointer;}
|
||||
+74
-8
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* bootstrapTreeTable
|
||||
*
|
||||
* @author swifly
|
||||
* 基于bootstrapTreeTable/bootstrap-table-treegrid修改
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
(function($) {
|
||||
"use strict";
|
||||
@@ -71,6 +70,12 @@
|
||||
var $rightToolbar = $('<div class="btn-group tool-right">');
|
||||
$toolbar.append($rightToolbar);
|
||||
target.parent().before($toolbar);
|
||||
// ruoyi 是否显示检索信息
|
||||
if (options.showSearch) {
|
||||
var $searchBtn = $('<button class="btn btn-default btn-outline" type="button" aria-label="search" title="搜索"><i class="glyphicon glyphicon-search"></i></button>');
|
||||
$rightToolbar.append($searchBtn);
|
||||
registerSearchBtnClickEvent($searchBtn);
|
||||
}
|
||||
// 是否显示刷新按钮
|
||||
if (options.showRefresh) {
|
||||
var $refreshBtn = $('<button class="btn btn-default btn-outline" type="button" aria-label="refresh" title="刷新"><i class="glyphicon glyphicon-repeat"></i></button>');
|
||||
@@ -160,6 +165,7 @@
|
||||
data: parms ? parms : options.ajaxParams,
|
||||
dataType: "JSON",
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
data = calculateObjectValue(options, options.responseHandler, [data], data);
|
||||
renderTable(data);
|
||||
},
|
||||
error: function(xhr, textStatus) {
|
||||
@@ -234,7 +240,8 @@
|
||||
}
|
||||
// 缓存并格式化数据
|
||||
var formatData = function(data) {
|
||||
var _root = options.rootIdValue ? options.rootIdValue : null
|
||||
var _root = options.rootIdValue ? options.rootIdValue : null;
|
||||
var firstCode = data[0][options.parentCode];
|
||||
$.each(data, function(index, item) {
|
||||
// 添加一个默认属性,用来判断当前节点有没有被显示
|
||||
item.isShow = false;
|
||||
@@ -243,6 +250,7 @@
|
||||
var _defaultRootFlag = item[options.parentCode] == '0' ||
|
||||
item[options.parentCode] == 0 ||
|
||||
item[options.parentCode] == null ||
|
||||
item[options.parentCode] == firstCode ||
|
||||
item[options.parentCode] == '';
|
||||
if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootIdValue) : _defaultRootFlag)) {
|
||||
if (!target.data_list["_root_"]) {
|
||||
@@ -334,13 +342,13 @@
|
||||
}
|
||||
// 增加formatter渲染
|
||||
if (column.formatter) {
|
||||
$td.html(column.formatter.call(this, item[column.field], item, index));
|
||||
$td.html(column.formatter.call(this, getItemField(item, column.field), item, index));
|
||||
} else {
|
||||
if(options.showTitle){
|
||||
// 只在字段没有formatter时才添加title属性
|
||||
$td.attr("title",item[column.field]);
|
||||
}
|
||||
$td.text(item[column.field]);
|
||||
$td.text(getItemField(item, column.field));
|
||||
}
|
||||
if (options.expandColumn == index) {
|
||||
if (!isP) {
|
||||
@@ -357,6 +365,12 @@
|
||||
});
|
||||
return $tr;
|
||||
}
|
||||
// 检索信息按钮点击事件
|
||||
var registerSearchBtnClickEvent = function(btn) {
|
||||
$(btn).off('click').on('click', function () {
|
||||
$(".search-collapse").slideToggle();
|
||||
});
|
||||
}
|
||||
// 注册刷新按钮点击事件
|
||||
var registerRefreshBtnClickEvent = function(btn) {
|
||||
$(btn).off('click').on('click', function () {
|
||||
@@ -384,6 +398,15 @@
|
||||
_ipt.prop('checked', true);
|
||||
target.find("tbody").find("tr").removeClass("treetable-selected");
|
||||
$(this).addClass("treetable-selected");
|
||||
} else if (_ipt.attr("type") == "checkbox") {
|
||||
if (_ipt.prop('checked')) {
|
||||
_ipt.prop('checked', true);
|
||||
target.find("tbody").find("tr").removeClass("treetable-selected");
|
||||
$(this).addClass("treetable-selected");
|
||||
} else {
|
||||
_ipt.prop('checked', false);
|
||||
target.find("tbody").find("tr").removeClass("treetable-selected");
|
||||
}
|
||||
} else {
|
||||
if (_ipt.prop('checked')) {
|
||||
_ipt.prop('checked', false);
|
||||
@@ -573,6 +596,46 @@
|
||||
$input.prop("checked", '');
|
||||
}
|
||||
}
|
||||
// ruoyi 解析数据,支持多层级访问
|
||||
var getItemField = function (item, field) {
|
||||
var value = item;
|
||||
|
||||
if (typeof field !== 'string' || item.hasOwnProperty(field)) {
|
||||
return item[field];
|
||||
}
|
||||
var props = field.split('.');
|
||||
for (var p in props) {
|
||||
value = value && value[props[p]];
|
||||
}
|
||||
return value;
|
||||
};
|
||||
// ruoyi 发起对目标(target)函数的调用
|
||||
var calculateObjectValue = function (self, name, args, defaultValue) {
|
||||
var func = name;
|
||||
|
||||
if (typeof name === 'string') {
|
||||
var names = name.split('.');
|
||||
|
||||
if (names.length > 1) {
|
||||
func = window;
|
||||
$.each(names, function (i, f) {
|
||||
func = func[f];
|
||||
});
|
||||
} else {
|
||||
func = window[name];
|
||||
}
|
||||
}
|
||||
if (typeof func === 'object') {
|
||||
return func;
|
||||
}
|
||||
if (typeof func === 'function') {
|
||||
return func.apply(self, args);
|
||||
}
|
||||
if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {
|
||||
return sprintf.apply(this, [name].concat(args));
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
// 初始化
|
||||
init();
|
||||
return target;
|
||||
@@ -661,10 +724,13 @@
|
||||
toolbar: null, // 顶部工具条
|
||||
height: 0, // 表格高度
|
||||
showTitle: true, // 是否采用title属性显示字段内容(被formatter格式化的字段不会显示)
|
||||
showSearch: true, // 是否显示检索信息
|
||||
showColumns: true, // 是否显示内容列下拉框
|
||||
showRefresh: true, // 是否显示刷新按钮
|
||||
expanderExpandedClass: 'glyphicon glyphicon-chevron-down', // 展开的按钮的图标
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-chevron-right' // 缩起的按钮的图标
|
||||
|
||||
expanderCollapsedClass: 'glyphicon glyphicon-chevron-right', // 缩起的按钮的图标
|
||||
responseHandler: function(res) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Bootstrap Duallistbox - v3.0.7
|
||||
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
|
||||
* https://www.virtuosoft.eu/code/bootstrap-duallistbox/
|
||||
*
|
||||
* Made by István Ujj-Mészáros
|
||||
* Under Apache License v2.0 License
|
||||
*/
|
||||
.bootstrap-duallistbox-container .buttons {
|
||||
width: 100%;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .info {
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .clear1,
|
||||
.bootstrap-duallistbox-container .clear2 {
|
||||
display: none;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .box1.filtered .clear1,
|
||||
.bootstrap-duallistbox-container .box2.filtered .clear2 {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .move,
|
||||
.bootstrap-duallistbox-container .remove {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .btn-group .btn {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.bootstrap-duallistbox-container select {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .moveall,
|
||||
.bootstrap-duallistbox-container .removeall {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container select {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .filter {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 31px;
|
||||
margin: 0 0 5px 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container .filter.placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container.moveonselect .move,
|
||||
.bootstrap-duallistbox-container.moveonselect .remove {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.bootstrap-duallistbox-container.moveonselect .moveall,
|
||||
.bootstrap-duallistbox-container.moveonselect .removeall {
|
||||
width: 100%;
|
||||
}
|
||||
+841
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
* Bootstrap Duallistbox - v3.0.7
|
||||
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
|
||||
* https://www.virtuosoft.eu/code/bootstrap-duallistbox/
|
||||
*
|
||||
* Made by István Ujj-Mészáros
|
||||
* Under Apache License v2.0 License
|
||||
*/
|
||||
;(function ($, window, document, undefined) {
|
||||
// Create the defaults once
|
||||
var pluginName = 'bootstrapDualListbox',
|
||||
defaults = {
|
||||
bootstrap2Compatible: false,
|
||||
filterTextClear: 'show all',
|
||||
filterPlaceHolder: 'Filter',
|
||||
moveSelectedLabel: 'Move selected',
|
||||
moveAllLabel: 'Move all',
|
||||
removeSelectedLabel: 'Remove selected',
|
||||
removeAllLabel: 'Remove all',
|
||||
moveOnSelect: true, // true/false (forced true on androids, see the comment later)
|
||||
moveOnDoubleClick: true, // true/false (forced false on androids, cause moveOnSelect is forced to true)
|
||||
preserveSelectionOnMove: false, // 'all' / 'moved' / false
|
||||
selectedListLabel: false, // 'string', false
|
||||
nonSelectedListLabel: false, // 'string', false
|
||||
helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false
|
||||
selectorMinimalHeight: 100,
|
||||
showFilterInputs: true, // whether to show filter inputs
|
||||
nonSelectedFilter: '', // string, filter the non selected options
|
||||
selectedFilter: '', // string, filter the selected options
|
||||
infoText: 'Showing all {0}', // text when all options are visible / false for no info text
|
||||
infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
|
||||
infoTextEmpty: 'Empty list', // when there are no options present in the list
|
||||
filterOnValues: false, // filter by selector's values, boolean
|
||||
sortByInputOrder: false,
|
||||
eventMoveOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||
eventMoveAllOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||
eventRemoveOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||
eventRemoveAllOverride: false // boolean, allows user to unbind default event behaviour and run their own instead
|
||||
},
|
||||
// Selections are invisible on android if the containing select is styled with CSS
|
||||
// http://code.google.com/p/android/issues/detail?id=16922
|
||||
isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
|
||||
|
||||
// The actual plugin constructor
|
||||
function BootstrapDualListbox(element, options) {
|
||||
this.element = $(element);
|
||||
// jQuery has an extend method which merges the contents of two or
|
||||
// more objects, storing the result in the first object. The first object
|
||||
// is generally empty as we don't want to alter the default options for
|
||||
// future instances of the plugin
|
||||
this.settings = $.extend({}, defaults, options);
|
||||
this._defaults = defaults;
|
||||
this._name = pluginName;
|
||||
this.init();
|
||||
}
|
||||
|
||||
function triggerChangeEvent(dualListbox) {
|
||||
dualListbox.element.trigger('change');
|
||||
}
|
||||
|
||||
function updateSelectionStates(dualListbox) {
|
||||
dualListbox.element.find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if (typeof($item.data('original-index')) === 'undefined') {
|
||||
$item.data('original-index', dualListbox.elementCount++);
|
||||
}
|
||||
if (typeof($item.data('_selected')) === 'undefined') {
|
||||
$item.data('_selected', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function changeSelectionState(dualListbox, original_index, selected) {
|
||||
dualListbox.element.find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if ($item.data('original-index') === original_index) {
|
||||
$item.prop('selected', selected);
|
||||
if(selected){
|
||||
$item.attr('data-sortindex', dualListbox.sortIndex);
|
||||
dualListbox.sortIndex++;
|
||||
} else {
|
||||
$item.removeAttr('data-sortindex');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function formatString(s, args) {
|
||||
return s.replace(/\{(\d+)\}/g, function(match, number) {
|
||||
return typeof args[number] !== 'undefined' ? args[number] : match;
|
||||
});
|
||||
}
|
||||
|
||||
function refreshInfo(dualListbox) {
|
||||
if (!dualListbox.settings.infoText) {
|
||||
return;
|
||||
}
|
||||
|
||||
var visible1 = dualListbox.elements.select1.find('option').length,
|
||||
visible2 = dualListbox.elements.select2.find('option').length,
|
||||
all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
|
||||
all2 = dualListbox.selectedElements,
|
||||
content = '';
|
||||
|
||||
if (all1 === 0) {
|
||||
content = dualListbox.settings.infoTextEmpty;
|
||||
} else if (visible1 === all1) {
|
||||
content = formatString(dualListbox.settings.infoText, [visible1, all1]);
|
||||
} else {
|
||||
content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
|
||||
}
|
||||
|
||||
dualListbox.elements.info1.html(content);
|
||||
dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
|
||||
|
||||
if (all2 === 0) {
|
||||
content = dualListbox.settings.infoTextEmpty;
|
||||
} else if (visible2 === all2) {
|
||||
content = formatString(dualListbox.settings.infoText, [visible2, all2]);
|
||||
} else {
|
||||
content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
|
||||
}
|
||||
|
||||
dualListbox.elements.info2.html(content);
|
||||
dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
|
||||
}
|
||||
|
||||
function refreshSelects(dualListbox) {
|
||||
dualListbox.selectedElements = 0;
|
||||
|
||||
dualListbox.elements.select1.empty();
|
||||
dualListbox.elements.select2.empty();
|
||||
|
||||
dualListbox.element.find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if ($item.prop('selected')) {
|
||||
dualListbox.selectedElements++;
|
||||
dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||
} else {
|
||||
dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||
}
|
||||
});
|
||||
|
||||
if (dualListbox.settings.showFilterInputs) {
|
||||
filter(dualListbox, 1);
|
||||
filter(dualListbox, 2);
|
||||
}
|
||||
refreshInfo(dualListbox);
|
||||
}
|
||||
|
||||
function filter(dualListbox, selectIndex) {
|
||||
if (!dualListbox.settings.showFilterInputs) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveSelections(dualListbox, selectIndex);
|
||||
|
||||
dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
|
||||
var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
|
||||
allOptions = dualListbox.element.find('option'),
|
||||
options = dualListbox.element;
|
||||
|
||||
if (selectIndex === 1) {
|
||||
options = allOptions.not(':selected');
|
||||
} else {
|
||||
options = options.find('option:selected');
|
||||
}
|
||||
|
||||
options.each(function(index, item) {
|
||||
var $item = $(item),
|
||||
isFiltered = true;
|
||||
if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
|
||||
isFiltered = false;
|
||||
dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||
}
|
||||
allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
|
||||
});
|
||||
|
||||
refreshInfo(dualListbox);
|
||||
}
|
||||
|
||||
function saveSelections(dualListbox, selectIndex) {
|
||||
var options = dualListbox.element.find('option');
|
||||
dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
|
||||
});
|
||||
}
|
||||
|
||||
function sortOptionsByInputOrder(select){
|
||||
var selectopt = select.children('option');
|
||||
|
||||
selectopt.sort(function(a,b){
|
||||
var an = parseInt(a.getAttribute('data-sortindex')),
|
||||
bn = parseInt(b.getAttribute('data-sortindex'));
|
||||
|
||||
if(an > bn) {
|
||||
return 1;
|
||||
}
|
||||
if(an < bn) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
selectopt.detach().appendTo(select);
|
||||
}
|
||||
|
||||
function sortOptions(select) {
|
||||
select.find('option').sort(function(a, b) {
|
||||
return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
|
||||
}).appendTo(select);
|
||||
}
|
||||
|
||||
function clearSelections(dualListbox) {
|
||||
dualListbox.elements.select1.find('option').each(function() {
|
||||
dualListbox.element.find('option').data('_selected', false);
|
||||
});
|
||||
}
|
||||
|
||||
function move(dualListbox) {
|
||||
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
saveSelections(dualListbox, 2);
|
||||
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
}
|
||||
|
||||
dualListbox.elements.select1.find('option:selected').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if (!$item.data('filtered1')) {
|
||||
changeSelectionState(dualListbox, $item.data('original-index'), true);
|
||||
}
|
||||
});
|
||||
|
||||
refreshSelects(dualListbox);
|
||||
triggerChangeEvent(dualListbox);
|
||||
if(dualListbox.settings.sortByInputOrder){
|
||||
sortOptionsByInputOrder(dualListbox.elements.select2);
|
||||
} else {
|
||||
sortOptions(dualListbox.elements.select2);
|
||||
}
|
||||
}
|
||||
|
||||
function remove(dualListbox) {
|
||||
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
saveSelections(dualListbox, 2);
|
||||
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 2);
|
||||
}
|
||||
|
||||
dualListbox.elements.select2.find('option:selected').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if (!$item.data('filtered2')) {
|
||||
changeSelectionState(dualListbox, $item.data('original-index'), false);
|
||||
}
|
||||
});
|
||||
|
||||
refreshSelects(dualListbox);
|
||||
triggerChangeEvent(dualListbox);
|
||||
sortOptions(dualListbox.elements.select1);
|
||||
if(dualListbox.settings.sortByInputOrder){
|
||||
sortOptionsByInputOrder(dualListbox.elements.select2);
|
||||
}
|
||||
}
|
||||
|
||||
function moveAll(dualListbox) {
|
||||
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
saveSelections(dualListbox, 2);
|
||||
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
}
|
||||
|
||||
dualListbox.element.find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if (!$item.data('filtered1')) {
|
||||
$item.prop('selected', true);
|
||||
$item.attr('data-sortindex', dualListbox.sortIndex);
|
||||
dualListbox.sortIndex++;
|
||||
}
|
||||
});
|
||||
|
||||
refreshSelects(dualListbox);
|
||||
triggerChangeEvent(dualListbox);
|
||||
}
|
||||
|
||||
function removeAll(dualListbox) {
|
||||
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 1);
|
||||
saveSelections(dualListbox, 2);
|
||||
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||
saveSelections(dualListbox, 2);
|
||||
}
|
||||
|
||||
dualListbox.element.find('option').each(function(index, item) {
|
||||
var $item = $(item);
|
||||
if (!$item.data('filtered2')) {
|
||||
$item.prop('selected', false);
|
||||
$item.removeAttr('data-sortindex');
|
||||
}
|
||||
});
|
||||
|
||||
refreshSelects(dualListbox);
|
||||
triggerChangeEvent(dualListbox);
|
||||
}
|
||||
|
||||
function bindEvents(dualListbox) {
|
||||
dualListbox.elements.form.submit(function(e) {
|
||||
if (dualListbox.elements.filterInput1.is(':focus')) {
|
||||
e.preventDefault();
|
||||
dualListbox.elements.filterInput1.focusout();
|
||||
} else if (dualListbox.elements.filterInput2.is(':focus')) {
|
||||
e.preventDefault();
|
||||
dualListbox.elements.filterInput2.focusout();
|
||||
}
|
||||
});
|
||||
|
||||
dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
|
||||
dualListbox.refresh(mustClearSelections);
|
||||
});
|
||||
|
||||
dualListbox.elements.filterClear1.on('click', function() {
|
||||
dualListbox.setNonSelectedFilter('', true);
|
||||
});
|
||||
|
||||
dualListbox.elements.filterClear2.on('click', function() {
|
||||
dualListbox.setSelectedFilter('', true);
|
||||
});
|
||||
|
||||
if (dualListbox.settings.eventMoveOverride === false) {
|
||||
dualListbox.elements.moveButton.on('click', function() {
|
||||
move(dualListbox);
|
||||
});
|
||||
}
|
||||
|
||||
if (dualListbox.settings.eventMoveAllOverride === false) {
|
||||
dualListbox.elements.moveAllButton.on('click', function() {
|
||||
moveAll(dualListbox);
|
||||
});
|
||||
}
|
||||
|
||||
if (dualListbox.settings.eventRemoveOverride === false) {
|
||||
dualListbox.elements.removeButton.on('click', function() {
|
||||
remove(dualListbox);
|
||||
});
|
||||
}
|
||||
|
||||
if (dualListbox.settings.eventRemoveAllOverride === false) {
|
||||
dualListbox.elements.removeAllButton.on('click', function() {
|
||||
removeAll(dualListbox);
|
||||
});
|
||||
}
|
||||
|
||||
dualListbox.elements.filterInput1.on('change keyup', function() {
|
||||
filter(dualListbox, 1);
|
||||
});
|
||||
|
||||
dualListbox.elements.filterInput2.on('change keyup', function() {
|
||||
filter(dualListbox, 2);
|
||||
});
|
||||
}
|
||||
|
||||
BootstrapDualListbox.prototype = {
|
||||
init: function () {
|
||||
// Add the custom HTML template
|
||||
this.container = $('' +
|
||||
'<div class="bootstrap-duallistbox-container">' +
|
||||
' <div class="box1">' +
|
||||
' <label></label>' +
|
||||
' <span class="info-container">' +
|
||||
' <span class="info"></span>' +
|
||||
' <button type="button" class="btn clear1 pull-right"></button>' +
|
||||
' </span>' +
|
||||
' <input class="filter" type="text">' +
|
||||
' <div class="btn-group buttons">' +
|
||||
' <button type="button" class="btn moveall">' +
|
||||
' <i></i>' +
|
||||
' <i></i>' +
|
||||
' </button>' +
|
||||
' <button type="button" class="btn move">' +
|
||||
' <i></i>' +
|
||||
' </button>' +
|
||||
' </div>' +
|
||||
' <select multiple="multiple"></select>' +
|
||||
' </div>' +
|
||||
' <div class="box2">' +
|
||||
' <label></label>' +
|
||||
' <span class="info-container">' +
|
||||
' <span class="info"></span>' +
|
||||
' <button type="button" class="btn clear2 pull-right"></button>' +
|
||||
' </span>' +
|
||||
' <input class="filter" type="text">' +
|
||||
' <div class="btn-group buttons">' +
|
||||
' <button type="button" class="btn remove">' +
|
||||
' <i></i>' +
|
||||
' </button>' +
|
||||
' <button type="button" class="btn removeall">' +
|
||||
' <i></i>' +
|
||||
' <i></i>' +
|
||||
' </button>' +
|
||||
' </div>' +
|
||||
' <select multiple="multiple"></select>' +
|
||||
' </div>' +
|
||||
'</div>')
|
||||
.insertBefore(this.element);
|
||||
|
||||
// Cache the inner elements
|
||||
this.elements = {
|
||||
originalSelect: this.element,
|
||||
box1: $('.box1', this.container),
|
||||
box2: $('.box2', this.container),
|
||||
filterInput1: $('.box1 .filter', this.container),
|
||||
filterInput2: $('.box2 .filter', this.container),
|
||||
filterClear1: $('.box1 .clear1', this.container),
|
||||
filterClear2: $('.box2 .clear2', this.container),
|
||||
label1: $('.box1 > label', this.container),
|
||||
label2: $('.box2 > label', this.container),
|
||||
info1: $('.box1 .info', this.container),
|
||||
info2: $('.box2 .info', this.container),
|
||||
select1: $('.box1 select', this.container),
|
||||
select2: $('.box2 select', this.container),
|
||||
moveButton: $('.box1 .move', this.container),
|
||||
removeButton: $('.box2 .remove', this.container),
|
||||
moveAllButton: $('.box1 .moveall', this.container),
|
||||
removeAllButton: $('.box2 .removeall', this.container),
|
||||
form: $($('.box1 .filter', this.container)[0].form)
|
||||
};
|
||||
|
||||
// Set select IDs
|
||||
this.originalSelectName = this.element.attr('name') || '';
|
||||
var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
|
||||
select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
|
||||
this.elements.select1.attr('id', select1Id);
|
||||
this.elements.select2.attr('id', select2Id);
|
||||
this.elements.label1.attr('for', select1Id);
|
||||
this.elements.label2.attr('for', select2Id);
|
||||
|
||||
// Apply all settings
|
||||
this.selectedElements = 0;
|
||||
this.sortIndex = 0;
|
||||
this.elementCount = 0;
|
||||
this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
|
||||
this.setFilterTextClear(this.settings.filterTextClear);
|
||||
this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
|
||||
this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
|
||||
this.setMoveAllLabel(this.settings.moveAllLabel);
|
||||
this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
|
||||
this.setRemoveAllLabel(this.settings.removeAllLabel);
|
||||
this.setMoveOnSelect(this.settings.moveOnSelect);
|
||||
this.setMoveOnDoubleClick(this.settings.moveOnDoubleClick);
|
||||
this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
|
||||
this.setSelectedListLabel(this.settings.selectedListLabel);
|
||||
this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
|
||||
this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
|
||||
this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
|
||||
|
||||
updateSelectionStates(this);
|
||||
|
||||
this.setShowFilterInputs(this.settings.showFilterInputs);
|
||||
this.setNonSelectedFilter(this.settings.nonSelectedFilter);
|
||||
this.setSelectedFilter(this.settings.selectedFilter);
|
||||
this.setInfoText(this.settings.infoText);
|
||||
this.setInfoTextFiltered(this.settings.infoTextFiltered);
|
||||
this.setInfoTextEmpty(this.settings.infoTextEmpty);
|
||||
this.setFilterOnValues(this.settings.filterOnValues);
|
||||
this.setSortByInputOrder(this.settings.sortByInputOrder);
|
||||
this.setEventMoveOverride(this.settings.eventMoveOverride);
|
||||
this.setEventMoveAllOverride(this.settings.eventMoveAllOverride);
|
||||
this.setEventRemoveOverride(this.settings.eventRemoveOverride);
|
||||
this.setEventRemoveAllOverride(this.settings.eventRemoveAllOverride);
|
||||
|
||||
// Hide the original select
|
||||
this.element.hide();
|
||||
|
||||
bindEvents(this);
|
||||
refreshSelects(this);
|
||||
|
||||
return this.element;
|
||||
},
|
||||
setBootstrap2Compatible: function(value, refresh) {
|
||||
this.settings.bootstrap2Compatible = value;
|
||||
if (value) {
|
||||
this.container.removeClass('row').addClass('row-fluid bs2compatible');
|
||||
this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
|
||||
this.container.find('.clear1, .clear2').removeClass('btn-white btn-xs').addClass('btn-mini');
|
||||
this.container.find('input, select').removeClass('form-control');
|
||||
this.container.find('.btn').removeClass('btn-white');
|
||||
this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');
|
||||
this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');
|
||||
} else {
|
||||
this.container.removeClass('row-fluid bs2compatible').addClass('row');
|
||||
this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
|
||||
this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-white btn-xs');
|
||||
this.container.find('input, select').addClass('form-control');
|
||||
this.container.find('.btn').addClass('btn-white');
|
||||
this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');
|
||||
this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setFilterTextClear: function(value, refresh) {
|
||||
this.settings.filterTextClear = value;
|
||||
this.elements.filterClear1.html(value);
|
||||
this.elements.filterClear2.html(value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setFilterPlaceHolder: function(value, refresh) {
|
||||
this.settings.filterPlaceHolder = value;
|
||||
this.elements.filterInput1.attr('placeholder', value);
|
||||
this.elements.filterInput2.attr('placeholder', value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setMoveSelectedLabel: function(value, refresh) {
|
||||
this.settings.moveSelectedLabel = value;
|
||||
this.elements.moveButton.attr('title', value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setMoveAllLabel: function(value, refresh) {
|
||||
this.settings.moveAllLabel = value;
|
||||
this.elements.moveAllButton.attr('title', value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setRemoveSelectedLabel: function(value, refresh) {
|
||||
this.settings.removeSelectedLabel = value;
|
||||
this.elements.removeButton.attr('title', value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setRemoveAllLabel: function(value, refresh) {
|
||||
this.settings.removeAllLabel = value;
|
||||
this.elements.removeAllButton.attr('title', value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setMoveOnSelect: function(value, refresh) {
|
||||
if (isBuggyAndroid) {
|
||||
value = true;
|
||||
}
|
||||
this.settings.moveOnSelect = value;
|
||||
if (this.settings.moveOnSelect) {
|
||||
this.container.addClass('moveonselect');
|
||||
var self = this;
|
||||
this.elements.select1.on('change', function() {
|
||||
move(self);
|
||||
});
|
||||
this.elements.select2.on('change', function() {
|
||||
remove(self);
|
||||
});
|
||||
} else {
|
||||
this.container.removeClass('moveonselect');
|
||||
this.elements.select1.off('change');
|
||||
this.elements.select2.off('change');
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setMoveOnDoubleClick: function(value, refresh) {
|
||||
if (isBuggyAndroid) {
|
||||
value = false;
|
||||
}
|
||||
this.settings.moveOnDoubleClick = value;
|
||||
if (this.settings.moveOnDoubleClick) {
|
||||
this.container.addClass('moveondoubleclick');
|
||||
var self = this;
|
||||
this.elements.select1.on('dblclick', function() {
|
||||
move(self);
|
||||
});
|
||||
this.elements.select2.on('dblclick', function() {
|
||||
remove(self);
|
||||
});
|
||||
} else {
|
||||
this.container.removeClass('moveondoubleclick');
|
||||
this.elements.select1.off('dblclick');
|
||||
this.elements.select2.off('dblclick');
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setPreserveSelectionOnMove: function(value, refresh) {
|
||||
// We are forcing to move on select and disabling preserveSelectionOnMove on Android
|
||||
if (isBuggyAndroid) {
|
||||
value = false;
|
||||
}
|
||||
this.settings.preserveSelectionOnMove = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setSelectedListLabel: function(value, refresh) {
|
||||
this.settings.selectedListLabel = value;
|
||||
if (value) {
|
||||
this.elements.label2.show().html(value);
|
||||
} else {
|
||||
this.elements.label2.hide().html(value);
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setNonSelectedListLabel: function(value, refresh) {
|
||||
this.settings.nonSelectedListLabel = value;
|
||||
if (value) {
|
||||
this.elements.label1.show().html(value);
|
||||
} else {
|
||||
this.elements.label1.hide().html(value);
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setHelperSelectNamePostfix: function(value, refresh) {
|
||||
this.settings.helperSelectNamePostfix = value;
|
||||
if (value) {
|
||||
this.elements.select1.attr('name', this.originalSelectName + value + '1');
|
||||
this.elements.select2.attr('name', this.originalSelectName + value + '2');
|
||||
} else {
|
||||
this.elements.select1.removeAttr('name');
|
||||
this.elements.select2.removeAttr('name');
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setSelectOrMinimalHeight: function(value, refresh) {
|
||||
this.settings.selectorMinimalHeight = value;
|
||||
var height = this.element.height();
|
||||
if (this.element.height() < value) {
|
||||
height = value;
|
||||
}
|
||||
this.elements.select1.height(height);
|
||||
this.elements.select2.height(height);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setShowFilterInputs: function(value, refresh) {
|
||||
if (!value) {
|
||||
this.setNonSelectedFilter('');
|
||||
this.setSelectedFilter('');
|
||||
refreshSelects(this);
|
||||
this.elements.filterInput1.hide();
|
||||
this.elements.filterInput2.hide();
|
||||
} else {
|
||||
this.elements.filterInput1.show();
|
||||
this.elements.filterInput2.show();
|
||||
}
|
||||
this.settings.showFilterInputs = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setNonSelectedFilter: function(value, refresh) {
|
||||
if (this.settings.showFilterInputs) {
|
||||
this.settings.nonSelectedFilter = value;
|
||||
this.elements.filterInput1.val(value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
}
|
||||
},
|
||||
setSelectedFilter: function(value, refresh) {
|
||||
if (this.settings.showFilterInputs) {
|
||||
this.settings.selectedFilter = value;
|
||||
this.elements.filterInput2.val(value);
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
}
|
||||
},
|
||||
setInfoText: function(value, refresh) {
|
||||
this.settings.infoText = value;
|
||||
if (value) {
|
||||
this.elements.info1.show();
|
||||
this.elements.info2.show();
|
||||
} else {
|
||||
this.elements.info1.hide();
|
||||
this.elements.info2.hide();
|
||||
}
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setInfoTextFiltered: function(value, refresh) {
|
||||
this.settings.infoTextFiltered = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setInfoTextEmpty: function(value, refresh) {
|
||||
this.settings.infoTextEmpty = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setFilterOnValues: function(value, refresh) {
|
||||
this.settings.filterOnValues = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setSortByInputOrder: function(value, refresh){
|
||||
this.settings.sortByInputOrder = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setEventMoveOverride: function(value, refresh) {
|
||||
this.settings.eventMoveOverride = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setEventMoveAllOverride: function(value, refresh) {
|
||||
this.settings.eventMoveAllOverride = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setEventRemoveOverride: function(value, refresh) {
|
||||
this.settings.eventRemoveOverride = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
setEventRemoveAllOverride: function(value, refresh) {
|
||||
this.settings.eventRemoveAllOverride = value;
|
||||
if (refresh) {
|
||||
refreshSelects(this);
|
||||
}
|
||||
return this.element;
|
||||
},
|
||||
getContainer: function() {
|
||||
return this.container;
|
||||
},
|
||||
refresh: function(mustClearSelections) {
|
||||
updateSelectionStates(this);
|
||||
|
||||
if (!mustClearSelections) {
|
||||
saveSelections(this, 1);
|
||||
saveSelections(this, 2);
|
||||
} else {
|
||||
clearSelections(this);
|
||||
}
|
||||
|
||||
refreshSelects(this);
|
||||
},
|
||||
destroy: function() {
|
||||
this.container.remove();
|
||||
this.element.show();
|
||||
$.data(this, 'plugin_' + pluginName, null);
|
||||
return this.element;
|
||||
}
|
||||
};
|
||||
|
||||
// A really lightweight plugin wrapper around the constructor,
|
||||
// preventing against multiple instantiations
|
||||
$.fn[ pluginName ] = function (options) {
|
||||
var args = arguments;
|
||||
|
||||
// Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
|
||||
if (options === undefined || typeof options === 'object') {
|
||||
return this.each(function () {
|
||||
// If this is not a select
|
||||
if (!$(this).is('select')) {
|
||||
$(this).find('select').each(function(index, item) {
|
||||
// For each nested select, instantiate the Dual List Box
|
||||
$(item).bootstrapDualListbox(options);
|
||||
});
|
||||
} else if (!$.data(this, 'plugin_' + pluginName)) {
|
||||
// Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
|
||||
|
||||
// if it has no instance, create a new one, pass options to our plugin constructor,
|
||||
// and store the plugin instance in the elements jQuery data object.
|
||||
$.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
|
||||
}
|
||||
});
|
||||
// If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
|
||||
// treat this as a call to a public method.
|
||||
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
|
||||
|
||||
// Cache the method call to make it possible to return a value
|
||||
var returns;
|
||||
|
||||
this.each(function () {
|
||||
var instance = $.data(this, 'plugin_' + pluginName);
|
||||
// Tests that there's already a plugin-instance and checks that the requested public method exists
|
||||
if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
|
||||
// Call the method of our plugin instance, and pass it the supplied arguments.
|
||||
returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
|
||||
}
|
||||
});
|
||||
|
||||
// If the earlier cached method gives a value back return the value,
|
||||
// otherwise return this to preserve chainability.
|
||||
return returns !== undefined ? returns : this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})(jQuery, window, document);
|
||||
+1
@@ -0,0 +1 @@
|
||||
.bootstrap-duallistbox-container .buttons{width:100%;margin-bottom:-1px}.bootstrap-duallistbox-container label{display:block}.bootstrap-duallistbox-container .info{display:inline-block;margin-bottom:5px;font-size:11px}.bootstrap-duallistbox-container .clear1,.bootstrap-duallistbox-container .clear2{display:none;font-size:10px}.bootstrap-duallistbox-container .box1.filtered .clear1,.bootstrap-duallistbox-container .box2.filtered .clear2{display:inline-block}.bootstrap-duallistbox-container .move,.bootstrap-duallistbox-container .remove{width:60%}.bootstrap-duallistbox-container .btn-group .btn{border-bottom-left-radius:0;border-bottom-right-radius:0}.bootstrap-duallistbox-container select{border-top-left-radius:0;border-top-right-radius:0}.bootstrap-duallistbox-container .moveall,.bootstrap-duallistbox-container .removeall{width:40%}.bootstrap-duallistbox-container.bs2compatible .btn-group>.btn+.btn{margin-left:0}.bootstrap-duallistbox-container select{width:100%;height:300px;padding:0}.bootstrap-duallistbox-container .filter{display:inline-block;width:100%;height:31px;margin:0 0 5px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-duallistbox-container .filter.placeholder{color:#aaa}.bootstrap-duallistbox-container.moveonselect .move,.bootstrap-duallistbox-container.moveonselect .remove{display:none}.bootstrap-duallistbox-container.moveonselect .moveall,.bootstrap-duallistbox-container.moveonselect .removeall{width:100%}
|
||||
+10
File diff suppressed because one or more lines are too long
@@ -0,0 +1,315 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2011 by Michael Zinsmaier and nergal.dev
|
||||
Copyright (c) 2012 by Thomas Ritou
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
____________________________________________________
|
||||
|
||||
what it is:
|
||||
____________________________________________________
|
||||
|
||||
curvedLines is a plugin for flot, that tries to display lines in a smoother way.
|
||||
The plugin is based on nergal.dev's work https://code.google.com/p/flot/issues/detail?id=226
|
||||
and further extended with a mode that forces the min/max points of the curves to be on the
|
||||
points. Both modes are achieved through adding of more data points
|
||||
=> 1) with large data sets you may get trouble
|
||||
=> 2) if you want to display the points too, you have to plot them as 2nd data series over the lines
|
||||
|
||||
&& 3) consecutive x data points are not allowed to have the same value
|
||||
|
||||
This is version 0.5 of curvedLines so it will probably not work in every case. However
|
||||
the basic form of use descirbed next works (:
|
||||
|
||||
Feel free to further improve the code
|
||||
|
||||
____________________________________________________
|
||||
|
||||
how to use it:
|
||||
____________________________________________________
|
||||
|
||||
var d1 = [[5,5],[7,3],[9,12]];
|
||||
|
||||
var options = { series: { curvedLines: { active: true }}};
|
||||
|
||||
$.plot($("#placeholder"), [{data = d1, lines: { show: true}, curvedLines: {apply: true}}], options);
|
||||
|
||||
_____________________________________________________
|
||||
|
||||
options:
|
||||
_____________________________________________________
|
||||
|
||||
active: bool true => plugin can be used
|
||||
apply: bool true => series will be drawn as curved line
|
||||
fit: bool true => forces the max,mins of the curve to be on the datapoints
|
||||
curvePointFactor int defines how many "virtual" points are used per "real" data point to
|
||||
emulate the curvedLines (points total = real points * curvePointFactor)
|
||||
fitPointDist: int defines the x axis distance of the additional two points that are used
|
||||
to enforce the min max condition.
|
||||
|
||||
+ line options (since v0.5 curved lines use flots line implementation for drawing
|
||||
=> line options like fill, show ... are supported out of the box)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* v0.1 initial commit
|
||||
* v0.15 negative values should work now (outcommented a negative -> 0 hook hope it does no harm)
|
||||
* v0.2 added fill option (thanks to monemihir) and multi axis support (thanks to soewono effendi)
|
||||
* v0.3 improved saddle handling and added basic handling of Dates
|
||||
* v0.4 rewritten fill option (thomas ritou) mostly from original flot code (now fill between points rather than to graph bottom), corrected fill Opacity bug
|
||||
* v0.5 rewritten instead of implementing a own draw function CurvedLines is now based on the processDatapoints flot hook (credits go to thomas ritou).
|
||||
* This change breakes existing code however CurvedLines are now just many tiny straight lines to flot and therefore all flot lines options (like gradient fill,
|
||||
* shadow) are now supported out of the box
|
||||
* v0.6 flot 0.8 compatibility and some bug fixes
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var options = {
|
||||
series : {
|
||||
curvedLines : {
|
||||
active : false,
|
||||
apply: false,
|
||||
fit : false,
|
||||
curvePointFactor : 20,
|
||||
fitPointDist : undefined
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
|
||||
plot.hooks.processOptions.push(processOptions);
|
||||
|
||||
//if the plugin is active register processDatapoints method
|
||||
function processOptions(plot, options) {
|
||||
if (options.series.curvedLines.active) {
|
||||
plot.hooks.processDatapoints.unshift(processDatapoints);
|
||||
}
|
||||
}
|
||||
|
||||
//only if the plugin is active
|
||||
function processDatapoints(plot, series, datapoints) {
|
||||
var nrPoints = datapoints.points.length / datapoints.pointsize;
|
||||
var EPSILON = 0.5; //pretty large epsilon but save
|
||||
|
||||
if (series.curvedLines.apply == true && series.originSeries === undefined && nrPoints > (1 + EPSILON)) {
|
||||
if (series.lines.fill) {
|
||||
|
||||
var pointsTop = calculateCurvePoints(datapoints, series.curvedLines, 1)
|
||||
,pointsBottom = calculateCurvePoints(datapoints, series.curvedLines, 2); //flot makes sure for us that we've got a second y point if fill is true !
|
||||
|
||||
//Merge top and bottom curve
|
||||
datapoints.pointsize = 3;
|
||||
datapoints.points = [];
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
var i = 0;
|
||||
var ps = 2;
|
||||
while (i < pointsTop.length || j < pointsBottom.length) {
|
||||
if (pointsTop[i] == pointsBottom[j]) {
|
||||
datapoints.points[k] = pointsTop[i];
|
||||
datapoints.points[k + 1] = pointsTop[i + 1];
|
||||
datapoints.points[k + 2] = pointsBottom[j + 1];
|
||||
j += ps;
|
||||
i += ps;
|
||||
|
||||
} else if (pointsTop[i] < pointsBottom[j]) {
|
||||
datapoints.points[k] = pointsTop[i];
|
||||
datapoints.points[k + 1] = pointsTop[i + 1];
|
||||
datapoints.points[k + 2] = k > 0 ? datapoints.points[k-1] : null;
|
||||
i += ps;
|
||||
} else {
|
||||
datapoints.points[k] = pointsBottom[j];
|
||||
datapoints.points[k + 1] = k > 1 ? datapoints.points[k-2] : null;
|
||||
datapoints.points[k + 2] = pointsBottom[j + 1];
|
||||
j += ps;
|
||||
}
|
||||
k += 3;
|
||||
}
|
||||
} else if (series.lines.lineWidth > 0) {
|
||||
datapoints.points = calculateCurvePoints(datapoints, series.curvedLines, 1);
|
||||
datapoints.pointsize = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226
|
||||
//if fit option is selected additional datapoints get inserted before the curve calculations in nergal.dev s code.
|
||||
function calculateCurvePoints(datapoints, curvedLinesOptions, yPos) {
|
||||
|
||||
var points = datapoints.points, ps = datapoints.pointsize;
|
||||
var num = curvedLinesOptions.curvePointFactor * (points.length / ps);
|
||||
|
||||
var xdata = new Array;
|
||||
var ydata = new Array;
|
||||
|
||||
var curX = -1;
|
||||
var curY = -1;
|
||||
var j = 0;
|
||||
|
||||
if (curvedLinesOptions.fit) {
|
||||
//insert a point before and after the "real" data point to force the line
|
||||
//to have a max,min at the data point.
|
||||
|
||||
var fpDist;
|
||||
if(typeof curvedLinesOptions.fitPointDist == 'undefined') {
|
||||
//estimate it
|
||||
var minX = points[0];
|
||||
var maxX = points[points.length-ps];
|
||||
fpDist = (maxX - minX) / (500 * 100); //x range / (estimated pixel length of placeholder * factor)
|
||||
} else {
|
||||
//use user defined value
|
||||
fpDist = curvedLinesOptions.fitPointDist;
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
|
||||
var frontX;
|
||||
var backX;
|
||||
curX = i;
|
||||
curY = i + yPos;
|
||||
|
||||
//add point X s
|
||||
frontX = points[curX] - fpDist;
|
||||
backX = points[curX] + fpDist;
|
||||
|
||||
var factor = 2;
|
||||
while (frontX == points[curX] || backX == points[curX]) {
|
||||
//inside the ulp
|
||||
frontX = points[curX] - (fpDist * factor);
|
||||
backX = points[curX] + (fpDist * factor);
|
||||
factor++;
|
||||
}
|
||||
|
||||
//add curve points
|
||||
xdata[j] = frontX;
|
||||
ydata[j] = points[curY];
|
||||
j++;
|
||||
|
||||
xdata[j] = points[curX];
|
||||
ydata[j] = points[curY];
|
||||
j++;
|
||||
|
||||
xdata[j] = backX;
|
||||
ydata[j] = points[curY];
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
//just use the datapoints
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
curX = i;
|
||||
curY = i + yPos;
|
||||
|
||||
xdata[j] = points[curX];
|
||||
ydata[j] = points[curY];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
var n = xdata.length;
|
||||
|
||||
var y2 = new Array();
|
||||
var delta = new Array();
|
||||
y2[0] = 0;
|
||||
y2[n - 1] = 0;
|
||||
delta[0] = 0;
|
||||
|
||||
for (var i = 1; i < n - 1; ++i) {
|
||||
var d = (xdata[i + 1] - xdata[i - 1]);
|
||||
if (d == 0) {
|
||||
//point before current point and after current point need some space in between
|
||||
return [];
|
||||
}
|
||||
|
||||
var s = (xdata[i] - xdata[i - 1]) / d;
|
||||
var p = s * y2[i - 1] + 2;
|
||||
y2[i] = (s - 1) / p;
|
||||
delta[i] = (ydata[i + 1] - ydata[i]) / (xdata[i + 1] - xdata[i]) - (ydata[i] - ydata[i - 1]) / (xdata[i] - xdata[i - 1]);
|
||||
delta[i] = (6 * delta[i] / (xdata[i + 1] - xdata[i - 1]) - s * delta[i - 1]) / p;
|
||||
}
|
||||
|
||||
for (var j = n - 2; j >= 0; --j) {
|
||||
y2[j] = y2[j] * y2[j + 1] + delta[j];
|
||||
}
|
||||
|
||||
// xmax - xmin / #points
|
||||
var step = (xdata[n - 1] - xdata[0]) / (num - 1);
|
||||
|
||||
var xnew = new Array;
|
||||
var ynew = new Array;
|
||||
var result = new Array;
|
||||
|
||||
xnew[0] = xdata[0];
|
||||
ynew[0] = ydata[0];
|
||||
|
||||
result.push(xnew[0]);
|
||||
result.push(ynew[0]);
|
||||
|
||||
for ( j = 1; j < num; ++j) {
|
||||
//new x point (sampling point for the created curve)
|
||||
xnew[j] = xnew[0] + j * step;
|
||||
|
||||
var max = n - 1;
|
||||
var min = 0;
|
||||
|
||||
while (max - min > 1) {
|
||||
var k = Math.round((max + min) / 2);
|
||||
if (xdata[k] > xnew[j]) {
|
||||
max = k;
|
||||
} else {
|
||||
min = k;
|
||||
}
|
||||
}
|
||||
|
||||
//found point one to the left and one to the right of generated new point
|
||||
var h = (xdata[max] - xdata[min]);
|
||||
|
||||
if (h == 0) {
|
||||
//similar to above two points from original x data need some space between them
|
||||
return [];
|
||||
}
|
||||
|
||||
var a = (xdata[max] - xnew[j]) / h;
|
||||
var b = (xnew[j] - xdata[min]) / h;
|
||||
|
||||
ynew[j] = a * ydata[min] + b * ydata[max] + ((a * a * a - a) * y2[min] + (b * b * b - b) * y2[max]) * (h * h) / 6;
|
||||
|
||||
result.push(xnew[j]);
|
||||
result.push(ynew[j]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}//end init
|
||||
|
||||
$.plot.plugins.push({
|
||||
init : init,
|
||||
options : options,
|
||||
name : 'curvedLines',
|
||||
version : '0.5'
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,750 @@
|
||||
/*
|
||||
Flot plugin for rendering pie charts. The plugin assumes the data is
|
||||
coming is as a single data value for each series, and each of those
|
||||
values is a positive value or zero (negative numbers don't make
|
||||
any sense and will cause strange effects). The data values do
|
||||
NOT need to be passed in as percentage values because it
|
||||
internally calculates the total and percentages.
|
||||
|
||||
* Created by Brian Medendorp, June 2009
|
||||
* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars
|
||||
|
||||
* Changes:
|
||||
2009-10-22: lineJoin set to round
|
||||
2009-10-23: IE full circle fix, donut
|
||||
2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera
|
||||
2009-11-17: Added IE hover capability submitted by Anthony Aragues
|
||||
2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
|
||||
|
||||
|
||||
Available options are:
|
||||
series: {
|
||||
pie: {
|
||||
show: true/false
|
||||
radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
|
||||
innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
|
||||
startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
|
||||
tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
|
||||
offset: {
|
||||
top: integer value to move the pie up or down
|
||||
left: integer value to move the pie left or right, or 'auto'
|
||||
},
|
||||
stroke: {
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
|
||||
width: integer pixel width of the stroke
|
||||
},
|
||||
label: {
|
||||
show: true/false, or 'auto'
|
||||
formatter: a user-defined function that modifies the text/style of the label text
|
||||
radius: 0-1 for percentage of fullsize, or a specified pixel length
|
||||
background: {
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
|
||||
opacity: 0-1
|
||||
},
|
||||
threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
|
||||
},
|
||||
combine: {
|
||||
threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
|
||||
label: any text value of what the combined slice should be labeled
|
||||
}
|
||||
highlight: {
|
||||
opacity: 0-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
More detail and specific examples can be found in the included HTML file.
|
||||
|
||||
*/
|
||||
|
||||
(function ($)
|
||||
{
|
||||
function init(plot) // this is the "body" of the plugin
|
||||
{
|
||||
var canvas = null;
|
||||
var target = null;
|
||||
var maxRadius = null;
|
||||
var centerLeft = null;
|
||||
var centerTop = null;
|
||||
var total = 0;
|
||||
var redraw = true;
|
||||
var redrawAttempts = 10;
|
||||
var shrink = 0.95;
|
||||
var legendWidth = 0;
|
||||
var processed = false;
|
||||
var raw = false;
|
||||
|
||||
// interactive variables
|
||||
var highlights = [];
|
||||
|
||||
// add hook to determine if pie plugin in enabled, and then perform necessary operations
|
||||
plot.hooks.processOptions.push(checkPieEnabled);
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
|
||||
// check to see if the pie plugin is enabled
|
||||
function checkPieEnabled(plot, options)
|
||||
{
|
||||
if (options.series.pie.show)
|
||||
{
|
||||
//disable grid
|
||||
options.grid.show = false;
|
||||
|
||||
// set labels.show
|
||||
if (options.series.pie.label.show=='auto')
|
||||
if (options.legend.show)
|
||||
options.series.pie.label.show = false;
|
||||
else
|
||||
options.series.pie.label.show = true;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius=='auto')
|
||||
if (options.series.pie.label.show)
|
||||
options.series.pie.radius = 3/4;
|
||||
else
|
||||
options.series.pie.radius = 1;
|
||||
|
||||
// ensure sane tilt
|
||||
if (options.series.pie.tilt>1)
|
||||
options.series.pie.tilt=1;
|
||||
if (options.series.pie.tilt<0)
|
||||
options.series.pie.tilt=0;
|
||||
|
||||
// add processData hook to do transformations on the data
|
||||
plot.hooks.processDatapoints.push(processDatapoints);
|
||||
plot.hooks.drawOverlay.push(drawOverlay);
|
||||
|
||||
// add draw hook
|
||||
plot.hooks.draw.push(draw);
|
||||
}
|
||||
}
|
||||
|
||||
// bind hoverable events
|
||||
function bindEvents(plot, eventHolder)
|
||||
{
|
||||
var options = plot.getOptions();
|
||||
|
||||
if (options.series.pie.show && options.grid.hoverable)
|
||||
eventHolder.unbind('mousemove').mousemove(onMouseMove);
|
||||
|
||||
if (options.series.pie.show && options.grid.clickable)
|
||||
eventHolder.unbind('click').click(onClick);
|
||||
}
|
||||
|
||||
|
||||
// debugging function that prints out an object
|
||||
function alertObject(obj)
|
||||
{
|
||||
var msg = '';
|
||||
function traverse(obj, depth)
|
||||
{
|
||||
if (!depth)
|
||||
depth = 0;
|
||||
for (var i = 0; i < obj.length; ++i)
|
||||
{
|
||||
for (var j=0; j<depth; j++)
|
||||
msg += '\t';
|
||||
|
||||
if( typeof obj[i] == "object")
|
||||
{ // its an object
|
||||
msg += ''+i+':\n';
|
||||
traverse(obj[i], depth+1);
|
||||
}
|
||||
else
|
||||
{ // its a value
|
||||
msg += ''+i+': '+obj[i]+'\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(obj);
|
||||
alert(msg);
|
||||
}
|
||||
|
||||
function calcTotal(data)
|
||||
{
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
var item = parseFloat(data[i].data[0][1]);
|
||||
if (item)
|
||||
total += item;
|
||||
}
|
||||
}
|
||||
|
||||
function processDatapoints(plot, series, data, datapoints)
|
||||
{
|
||||
if (!processed)
|
||||
{
|
||||
processed = true;
|
||||
|
||||
canvas = plot.getCanvas();
|
||||
target = $(canvas).parent();
|
||||
options = plot.getOptions();
|
||||
|
||||
plot.setData(combine(plot.getData()));
|
||||
}
|
||||
}
|
||||
|
||||
function setupPie()
|
||||
{
|
||||
legendWidth = target.children().filter('.legend').children().width();
|
||||
|
||||
// calculate maximum radius and center point
|
||||
maxRadius = Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;
|
||||
centerTop = (canvas.height/2)+options.series.pie.offset.top;
|
||||
centerLeft = (canvas.width/2);
|
||||
|
||||
if (options.series.pie.offset.left=='auto')
|
||||
if (options.legend.position.match('w'))
|
||||
centerLeft += legendWidth/2;
|
||||
else
|
||||
centerLeft -= legendWidth/2;
|
||||
else
|
||||
centerLeft += options.series.pie.offset.left;
|
||||
|
||||
if (centerLeft<maxRadius)
|
||||
centerLeft = maxRadius;
|
||||
else if (centerLeft>canvas.width-maxRadius)
|
||||
centerLeft = canvas.width-maxRadius;
|
||||
}
|
||||
|
||||
function fixData(data)
|
||||
{
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
if (typeof(data[i].data)=='number')
|
||||
data[i].data = [[1,data[i].data]];
|
||||
else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
|
||||
{
|
||||
if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
|
||||
data[i].label = data[i].data.label; // fix weirdness coming from flot
|
||||
data[i].data = [[1,0]];
|
||||
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function combine(data)
|
||||
{
|
||||
data = fixData(data);
|
||||
calcTotal(data);
|
||||
var combined = 0;
|
||||
var numCombined = 0;
|
||||
var color = options.series.pie.combine.color;
|
||||
|
||||
var newdata = [];
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
// make sure its a number
|
||||
data[i].data[0][1] = parseFloat(data[i].data[0][1]);
|
||||
if (!data[i].data[0][1])
|
||||
data[i].data[0][1] = 0;
|
||||
|
||||
if (data[i].data[0][1]/total<=options.series.pie.combine.threshold)
|
||||
{
|
||||
combined += data[i].data[0][1];
|
||||
numCombined++;
|
||||
if (!color)
|
||||
color = data[i].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
newdata.push({
|
||||
data: [[1,data[i].data[0][1]]],
|
||||
color: data[i].color,
|
||||
label: data[i].label,
|
||||
angle: (data[i].data[0][1]*(Math.PI*2))/total,
|
||||
percent: (data[i].data[0][1]/total*100)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (numCombined>0)
|
||||
newdata.push({
|
||||
data: [[1,combined]],
|
||||
color: color,
|
||||
label: options.series.pie.combine.label,
|
||||
angle: (combined*(Math.PI*2))/total,
|
||||
percent: (combined/total*100)
|
||||
});
|
||||
return newdata;
|
||||
}
|
||||
|
||||
function draw(plot, newCtx)
|
||||
{
|
||||
if (!target) return; // if no series were passed
|
||||
ctx = newCtx;
|
||||
|
||||
setupPie();
|
||||
var slices = plot.getData();
|
||||
|
||||
var attempts = 0;
|
||||
while (redraw && attempts<redrawAttempts)
|
||||
{
|
||||
redraw = false;
|
||||
if (attempts>0)
|
||||
maxRadius *= shrink;
|
||||
attempts += 1;
|
||||
clear();
|
||||
if (options.series.pie.tilt<=0.8)
|
||||
drawShadow();
|
||||
drawPie();
|
||||
}
|
||||
if (attempts >= redrawAttempts) {
|
||||
clear();
|
||||
target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>');
|
||||
}
|
||||
|
||||
if ( plot.setSeries && plot.insertLegend )
|
||||
{
|
||||
plot.setSeries(slices);
|
||||
plot.insertLegend();
|
||||
}
|
||||
|
||||
// we're actually done at this point, just defining internal functions at this point
|
||||
|
||||
function clear()
|
||||
{
|
||||
ctx.clearRect(0,0,canvas.width,canvas.height);
|
||||
target.children().filter('.pieLabel, .pieLabelBackground').remove();
|
||||
}
|
||||
|
||||
function drawShadow()
|
||||
{
|
||||
var shadowLeft = 5;
|
||||
var shadowTop = 15;
|
||||
var edge = 10;
|
||||
var alpha = 0.02;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius>1)
|
||||
var radius = options.series.pie.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.radius;
|
||||
|
||||
if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
|
||||
return; // shadow would be outside canvas, so don't draw it
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(shadowLeft,shadowTop);
|
||||
ctx.globalAlpha = alpha;
|
||||
ctx.fillStyle = '#000';
|
||||
|
||||
// center and rotate to starting position
|
||||
ctx.translate(centerLeft,centerTop);
|
||||
ctx.scale(1, options.series.pie.tilt);
|
||||
|
||||
//radius -= edge;
|
||||
for (var i=1; i<=edge; i++)
|
||||
{
|
||||
ctx.beginPath();
|
||||
ctx.arc(0,0,radius,0,Math.PI*2,false);
|
||||
ctx.fill();
|
||||
radius -= i;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function drawPie()
|
||||
{
|
||||
startAngle = Math.PI*options.series.pie.startAngle;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius>1)
|
||||
var radius = options.series.pie.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.radius;
|
||||
|
||||
// center and rotate to starting position
|
||||
ctx.save();
|
||||
ctx.translate(centerLeft,centerTop);
|
||||
ctx.scale(1, options.series.pie.tilt);
|
||||
//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
|
||||
|
||||
// draw slices
|
||||
ctx.save();
|
||||
var currentAngle = startAngle;
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
slices[i].startAngle = currentAngle;
|
||||
drawSlice(slices[i].angle, slices[i].color, true);
|
||||
}
|
||||
ctx.restore();
|
||||
|
||||
// draw slice outlines
|
||||
ctx.save();
|
||||
ctx.lineWidth = options.series.pie.stroke.width;
|
||||
currentAngle = startAngle;
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
|
||||
ctx.restore();
|
||||
|
||||
// draw donut hole
|
||||
drawDonutHole(ctx);
|
||||
|
||||
// draw labels
|
||||
if (options.series.pie.label.show)
|
||||
drawLabels();
|
||||
|
||||
// restore to original state
|
||||
ctx.restore();
|
||||
|
||||
function drawSlice(angle, color, fill)
|
||||
{
|
||||
if (angle<=0)
|
||||
return;
|
||||
|
||||
if (fill)
|
||||
ctx.fillStyle = color;
|
||||
else
|
||||
{
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineJoin = 'round';
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
if (Math.abs(angle - Math.PI*2) > 0.000000001)
|
||||
ctx.moveTo(0,0); // Center of the pie
|
||||
else if ($.browser.msie)
|
||||
angle -= 0.0001;
|
||||
//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
|
||||
ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
|
||||
ctx.closePath();
|
||||
//ctx.rotate(angle); // This doesn't work properly in Opera
|
||||
currentAngle += angle;
|
||||
|
||||
if (fill)
|
||||
ctx.fill();
|
||||
else
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawLabels()
|
||||
{
|
||||
var currentAngle = startAngle;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.label.radius>1)
|
||||
var radius = options.series.pie.label.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.label.radius;
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
if (slices[i].percent >= options.series.pie.label.threshold*100)
|
||||
drawLabel(slices[i], currentAngle, i);
|
||||
currentAngle += slices[i].angle;
|
||||
}
|
||||
|
||||
function drawLabel(slice, startAngle, index)
|
||||
{
|
||||
if (slice.data[0][1]==0)
|
||||
return;
|
||||
|
||||
// format label text
|
||||
var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
|
||||
if (lf)
|
||||
text = lf(slice.label, slice);
|
||||
else
|
||||
text = slice.label;
|
||||
if (plf)
|
||||
text = plf(text, slice);
|
||||
|
||||
var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
|
||||
var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
|
||||
var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
|
||||
|
||||
var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
|
||||
target.append(html);
|
||||
var label = target.children('#pieLabel'+index);
|
||||
var labelTop = (y - label.height()/2);
|
||||
var labelLeft = (x - label.width()/2);
|
||||
label.css('top', labelTop);
|
||||
label.css('left', labelLeft);
|
||||
|
||||
// check to make sure that the label is not outside the canvas
|
||||
if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
|
||||
redraw = true;
|
||||
|
||||
if (options.series.pie.label.background.opacity != 0) {
|
||||
// put in the transparent background separately to avoid blended labels and label boxes
|
||||
var c = options.series.pie.label.background.color;
|
||||
if (c == null) {
|
||||
c = slice.color;
|
||||
}
|
||||
var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
|
||||
$('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);
|
||||
}
|
||||
} // end individual label function
|
||||
} // end drawLabels function
|
||||
} // end drawPie function
|
||||
} // end draw function
|
||||
|
||||
// Placed here because it needs to be accessed from multiple locations
|
||||
function drawDonutHole(layer)
|
||||
{
|
||||
// draw donut hole
|
||||
if(options.series.pie.innerRadius > 0)
|
||||
{
|
||||
// subtract the center
|
||||
layer.save();
|
||||
innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
|
||||
layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
|
||||
layer.beginPath();
|
||||
layer.fillStyle = options.series.pie.stroke.color;
|
||||
layer.arc(0,0,innerRadius,0,Math.PI*2,false);
|
||||
layer.fill();
|
||||
layer.closePath();
|
||||
layer.restore();
|
||||
|
||||
// add inner stroke
|
||||
layer.save();
|
||||
layer.beginPath();
|
||||
layer.strokeStyle = options.series.pie.stroke.color;
|
||||
layer.arc(0,0,innerRadius,0,Math.PI*2,false);
|
||||
layer.stroke();
|
||||
layer.closePath();
|
||||
layer.restore();
|
||||
// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
|
||||
}
|
||||
}
|
||||
|
||||
//-- Additional Interactive related functions --
|
||||
|
||||
function isPointInPoly(poly, pt)
|
||||
{
|
||||
for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
|
||||
((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
|
||||
&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
|
||||
&& (c = !c);
|
||||
return c;
|
||||
}
|
||||
|
||||
function findNearbySlice(mouseX, mouseY)
|
||||
{
|
||||
var slices = plot.getData(),
|
||||
options = plot.getOptions(),
|
||||
radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
var s = slices[i];
|
||||
|
||||
if(s.pie.show)
|
||||
{
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,0); // Center of the pie
|
||||
//ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
|
||||
ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
|
||||
ctx.closePath();
|
||||
x = mouseX-centerLeft;
|
||||
y = mouseY-centerTop;
|
||||
if(ctx.isPointInPath)
|
||||
{
|
||||
if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
|
||||
{
|
||||
//alert('found slice!');
|
||||
ctx.restore();
|
||||
return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// excanvas for IE doesn;t support isPointInPath, this is a workaround.
|
||||
p1X = (radius * Math.cos(s.startAngle));
|
||||
p1Y = (radius * Math.sin(s.startAngle));
|
||||
p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
|
||||
p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
|
||||
p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
|
||||
p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
|
||||
p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
|
||||
p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
|
||||
p5X = (radius * Math.cos(s.startAngle+s.angle));
|
||||
p5Y = (radius * Math.sin(s.startAngle+s.angle));
|
||||
arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
|
||||
arrPoint = [x,y];
|
||||
// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
|
||||
if(isPointInPoly(arrPoly, arrPoint))
|
||||
{
|
||||
ctx.restore();
|
||||
return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function onMouseMove(e)
|
||||
{
|
||||
triggerClickHoverEvent('plothover', e);
|
||||
}
|
||||
|
||||
function onClick(e)
|
||||
{
|
||||
triggerClickHoverEvent('plotclick', e);
|
||||
}
|
||||
|
||||
// trigger click or hover event (they send the same parameters so we share their code)
|
||||
function triggerClickHoverEvent(eventname, e)
|
||||
{
|
||||
var offset = plot.offset(),
|
||||
canvasX = parseInt(e.pageX - offset.left),
|
||||
canvasY = parseInt(e.pageY - offset.top),
|
||||
item = findNearbySlice(canvasX, canvasY);
|
||||
|
||||
if (options.grid.autoHighlight)
|
||||
{
|
||||
// clear auto-highlights
|
||||
for (var i = 0; i < highlights.length; ++i)
|
||||
{
|
||||
var h = highlights[i];
|
||||
if (h.auto == eventname && !(item && h.series == item.series))
|
||||
unhighlight(h.series);
|
||||
}
|
||||
}
|
||||
|
||||
// highlight the slice
|
||||
if (item)
|
||||
highlight(item.series, eventname);
|
||||
|
||||
// trigger any hover bind events
|
||||
var pos = { pageX: e.pageX, pageY: e.pageY };
|
||||
target.trigger(eventname, [ pos, item ]);
|
||||
}
|
||||
|
||||
function highlight(s, auto)
|
||||
{
|
||||
if (typeof s == "number")
|
||||
s = series[s];
|
||||
|
||||
var i = indexOfHighlight(s);
|
||||
if (i == -1)
|
||||
{
|
||||
highlights.push({ series: s, auto: auto });
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else if (!auto)
|
||||
highlights[i].auto = false;
|
||||
}
|
||||
|
||||
function unhighlight(s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
highlights = [];
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
|
||||
if (typeof s == "number")
|
||||
s = series[s];
|
||||
|
||||
var i = indexOfHighlight(s);
|
||||
if (i != -1)
|
||||
{
|
||||
highlights.splice(i, 1);
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function indexOfHighlight(s)
|
||||
{
|
||||
for (var i = 0; i < highlights.length; ++i)
|
||||
{
|
||||
var h = highlights[i];
|
||||
if (h.series == s)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function drawOverlay(plot, octx)
|
||||
{
|
||||
//alert(options.series.pie.radius);
|
||||
var options = plot.getOptions();
|
||||
//alert(options.series.pie.radius);
|
||||
|
||||
var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
|
||||
|
||||
octx.save();
|
||||
octx.translate(centerLeft, centerTop);
|
||||
octx.scale(1, options.series.pie.tilt);
|
||||
|
||||
for (i = 0; i < highlights.length; ++i)
|
||||
drawHighlight(highlights[i].series);
|
||||
|
||||
drawDonutHole(octx);
|
||||
|
||||
octx.restore();
|
||||
|
||||
function drawHighlight(series)
|
||||
{
|
||||
if (series.angle < 0) return;
|
||||
|
||||
//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
|
||||
octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor
|
||||
|
||||
octx.beginPath();
|
||||
if (Math.abs(series.angle - Math.PI*2) > 0.000000001)
|
||||
octx.moveTo(0,0); // Center of the pie
|
||||
octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
|
||||
octx.closePath();
|
||||
octx.fill();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // end init (plugin body)
|
||||
|
||||
// define pie specific options and their default values
|
||||
var options = {
|
||||
series: {
|
||||
pie: {
|
||||
show: false,
|
||||
radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
|
||||
innerRadius:0, /* for donut */
|
||||
startAngle: 3/2,
|
||||
tilt: 1,
|
||||
offset: {
|
||||
top: 0,
|
||||
left: 'auto'
|
||||
},
|
||||
stroke: {
|
||||
color: '#FFF',
|
||||
width: 1
|
||||
},
|
||||
label: {
|
||||
show: 'auto',
|
||||
formatter: function(label, slice){
|
||||
return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
|
||||
}, // formatter function
|
||||
radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
|
||||
background: {
|
||||
color: null,
|
||||
opacity: 0
|
||||
},
|
||||
threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow)
|
||||
},
|
||||
combine: {
|
||||
threshold: -1, // percentage at which to combine little slices into one larger slice
|
||||
color: null, // color to give the new slice (auto-generated if null)
|
||||
label: 'Other' // label to give the new slice
|
||||
},
|
||||
highlight: {
|
||||
//color: '#FFF', // will add this functionality once parseColor is available
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: "pie",
|
||||
version: "1.0"
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Flot plugin for automatically redrawing plots as the placeholder resizes.
|
||||
|
||||
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
It works by listening for changes on the placeholder div (through the jQuery
|
||||
resize event plugin) - if the size changes, it will redraw the plot.
|
||||
|
||||
There are no options. If you need to disable the plugin for some plots, you
|
||||
can just fix the size of their placeholders.
|
||||
|
||||
*/
|
||||
|
||||
/* Inline dependency:
|
||||
* jQuery resize event - v1.1 - 3/14/2010
|
||||
* http://benalman.com/projects/jquery-resize-plugin/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
|
||||
(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
|
||||
|
||||
(function ($) {
|
||||
var options = { }; // no options
|
||||
|
||||
function init(plot) {
|
||||
function onResize() {
|
||||
var placeholder = plot.getPlaceholder();
|
||||
|
||||
// somebody might have hidden us and we can't plot
|
||||
// when we don't have the dimensions
|
||||
if (placeholder.width() == 0 || placeholder.height() == 0)
|
||||
return;
|
||||
|
||||
plot.resize();
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
}
|
||||
|
||||
function bindEvents(plot, eventHolder) {
|
||||
plot.getPlaceholder().resize(onResize);
|
||||
}
|
||||
|
||||
function shutdown(plot, eventHolder) {
|
||||
plot.getPlaceholder().unbind("resize", onResize);
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
plot.hooks.shutdown.push(shutdown);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'resize',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Flot plugin that provides spline interpolation for line graphs
|
||||
* author: Alex Bardas < alex.bardas@gmail.com >
|
||||
* modified by: Avi Kohn https://github.com/AMKohn
|
||||
* based on the spline interpolation described at:
|
||||
* http://scaledinnovation.com/analytics/splines/aboutSplines.html
|
||||
*
|
||||
* Example usage: (add in plot options series object)
|
||||
* for linespline:
|
||||
* series: {
|
||||
* ...
|
||||
* lines: {
|
||||
* show: false
|
||||
* },
|
||||
* splines: {
|
||||
* show: true,
|
||||
* tension: x, (float between 0 and 1, defaults to 0.5),
|
||||
* lineWidth: y (number, defaults to 2),
|
||||
* fill: z (float between 0 .. 1 or false, as in flot documentation)
|
||||
* },
|
||||
* ...
|
||||
* }
|
||||
* areaspline:
|
||||
* series: {
|
||||
* ...
|
||||
* lines: {
|
||||
* show: true,
|
||||
* lineWidth: 0, (line drawing will not execute)
|
||||
* fill: x, (float between 0 .. 1, as in flot documentation)
|
||||
* ...
|
||||
* },
|
||||
* splines: {
|
||||
* show: true,
|
||||
* tension: 0.5 (float between 0 and 1)
|
||||
* },
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* @param {Number} x0, y0, x1, y1: coordinates of the end (knot) points of the segment
|
||||
* @param {Number} x2, y2: the next knot (not connected, but needed to calculate p2)
|
||||
* @param {Number} tension: control how far the control points spread
|
||||
* @return {Array}: p1 -> control point, from x1 back toward x0
|
||||
* p2 -> the next control point, returned to become the next segment's p1
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function getControlPoints(x0, y0, x1, y1, x2, y2, tension) {
|
||||
|
||||
var pow = Math.pow,
|
||||
sqrt = Math.sqrt,
|
||||
d01, d12, fa, fb, p1x, p1y, p2x, p2y;
|
||||
|
||||
// Scaling factors: distances from this knot to the previous and following knots.
|
||||
d01 = sqrt(pow(x1 - x0, 2) + pow(y1 - y0, 2));
|
||||
d12 = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
|
||||
|
||||
fa = tension * d01 / (d01 + d12);
|
||||
fb = tension - fa;
|
||||
|
||||
p1x = x1 + fa * (x0 - x2);
|
||||
p1y = y1 + fa * (y0 - y2);
|
||||
|
||||
p2x = x1 - fb * (x0 - x2);
|
||||
p2y = y1 - fb * (y0 - y2);
|
||||
|
||||
return [p1x, p1y, p2x, p2y];
|
||||
}
|
||||
|
||||
var line = [];
|
||||
|
||||
function drawLine(points, ctx, height, fill, seriesColor) {
|
||||
var c = $.color.parse(seriesColor);
|
||||
|
||||
c.a = typeof fill == "number" ? fill : .3;
|
||||
c.normalize();
|
||||
c = c.toString();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(points[0][0], points[0][1]);
|
||||
|
||||
var plength = points.length;
|
||||
|
||||
for (var i = 0; i < plength; i++) {
|
||||
ctx[points[i][3]].apply(ctx, points[i][2]);
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
ctx.lineWidth = 0;
|
||||
ctx.lineTo(points[plength - 1][0], height);
|
||||
ctx.lineTo(points[0][0], height);
|
||||
|
||||
ctx.closePath();
|
||||
|
||||
if (fill !== false) {
|
||||
ctx.fillStyle = c;
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} ctx: canvas context
|
||||
* @param {String} type: accepted strings: 'bezier' or 'quadratic' (defaults to quadratic)
|
||||
* @param {Array} points: 2 points for which to draw the interpolation
|
||||
* @param {Array} cpoints: control points for those segment points
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function queue(ctx, type, points, cpoints) {
|
||||
if (type === void 0 || (type !== 'bezier' && type !== 'quadratic')) {
|
||||
type = 'quadratic';
|
||||
}
|
||||
type = type + 'CurveTo';
|
||||
|
||||
if (line.length == 0) line.push([points[0], points[1], cpoints.concat(points.slice(2)), type]);
|
||||
else if (type == "quadraticCurveTo" && points.length == 2) {
|
||||
cpoints = cpoints.slice(0, 2).concat(points);
|
||||
|
||||
line.push([points[0], points[1], cpoints, type]);
|
||||
}
|
||||
else line.push([points[2], points[3], cpoints.concat(points.slice(2)), type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} plot
|
||||
* @param {Object} ctx: canvas context
|
||||
* @param {Object} series
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function drawSpline(plot, ctx, series) {
|
||||
// Not interested if spline is not requested
|
||||
if (series.splines.show !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cp = [],
|
||||
// array of control points
|
||||
tension = series.splines.tension || 0.5,
|
||||
idx, x, y, points = series.datapoints.points,
|
||||
ps = series.datapoints.pointsize,
|
||||
plotOffset = plot.getPlotOffset(),
|
||||
len = points.length,
|
||||
pts = [];
|
||||
|
||||
line = [];
|
||||
|
||||
// Cannot display a linespline/areaspline if there are less than 3 points
|
||||
if (len / ps < 4) {
|
||||
$.extend(series.lines, series.splines);
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < len; idx += ps) {
|
||||
x = points[idx];
|
||||
y = points[idx + 1];
|
||||
if (x == null || x < series.xaxis.min || x > series.xaxis.max || y < series.yaxis.min || y > series.yaxis.max) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pts.push(series.xaxis.p2c(x) + plotOffset.left, series.yaxis.p2c(y) + plotOffset.top);
|
||||
}
|
||||
|
||||
len = pts.length;
|
||||
|
||||
// Draw an open curve, not connected at the ends
|
||||
for (idx = 0; idx < len - 2; idx += 2) {
|
||||
cp = cp.concat(getControlPoints.apply(this, pts.slice(idx, idx + 6).concat([tension])));
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.strokeStyle = series.color;
|
||||
ctx.lineWidth = series.splines.lineWidth;
|
||||
|
||||
queue(ctx, 'quadratic', pts.slice(0, 4), cp.slice(0, 2));
|
||||
|
||||
for (idx = 2; idx < len - 3; idx += 2) {
|
||||
queue(ctx, 'bezier', pts.slice(idx, idx + 4), cp.slice(2 * idx - 2, 2 * idx + 2));
|
||||
}
|
||||
|
||||
queue(ctx, 'quadratic', pts.slice(len - 2, len), [cp[2 * len - 10], cp[2 * len - 9], pts[len - 4], pts[len - 3]]);
|
||||
|
||||
drawLine(line, ctx, plot.height() + 10, series.splines.fill, series.color);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: function(plot) {
|
||||
plot.hooks.drawSeries.push(drawSpline);
|
||||
},
|
||||
options: {
|
||||
series: {
|
||||
splines: {
|
||||
show: false,
|
||||
lineWidth: 2,
|
||||
tension: 0.5,
|
||||
fill: false
|
||||
}
|
||||
}
|
||||
},
|
||||
name: 'spline',
|
||||
version: '0.8.2'
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Flot plugin that adds some extra symbols for plotting points.
|
||||
|
||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
The symbols are accessed as strings through the standard symbol options:
|
||||
|
||||
series: {
|
||||
points: {
|
||||
symbol: "square" // or "diamond", "triangle", "cross"
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function processRawData(plot, series, datapoints) {
|
||||
// we normalize the area of each symbol so it is approximately the
|
||||
// same as a circle of the given radius
|
||||
|
||||
var handlers = {
|
||||
square: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.rect(x - size, y - size, size + size, size + size);
|
||||
},
|
||||
diamond: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 2s^2 => s = r * sqrt(pi/2)
|
||||
var size = radius * Math.sqrt(Math.PI / 2);
|
||||
ctx.moveTo(x - size, y);
|
||||
ctx.lineTo(x, y - size);
|
||||
ctx.lineTo(x + size, y);
|
||||
ctx.lineTo(x, y + size);
|
||||
ctx.lineTo(x - size, y);
|
||||
},
|
||||
triangle: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3))
|
||||
var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
|
||||
var height = size * Math.sin(Math.PI / 3);
|
||||
ctx.moveTo(x - size/2, y + height/2);
|
||||
ctx.lineTo(x + size/2, y + height/2);
|
||||
if (!shadow) {
|
||||
ctx.lineTo(x, y - height/2);
|
||||
ctx.lineTo(x - size/2, y + height/2);
|
||||
}
|
||||
},
|
||||
cross: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.moveTo(x - size, y - size);
|
||||
ctx.lineTo(x + size, y + size);
|
||||
ctx.moveTo(x - size, y + size);
|
||||
ctx.lineTo(x + size, y - size);
|
||||
}
|
||||
};
|
||||
|
||||
var s = series.points.symbol;
|
||||
if (handlers[s])
|
||||
series.points.symbol = handlers[s];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processDatapoints.push(processRawData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
name: 'symbols',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* jquery.flot.tooltip
|
||||
*
|
||||
* description: easy-to-use tooltips for Flot charts
|
||||
* version: 0.6.2
|
||||
* author: Krzysztof Urbas @krzysu [myviews.pl]
|
||||
* website: https://github.com/krzysu/flot.tooltip
|
||||
*
|
||||
* build on 2013-09-30
|
||||
* released under MIT License, 2012
|
||||
*/
|
||||
(function(t){var o={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},i=function(t){this.tipPosition={x:0,y:0},this.init(t)};i.prototype.init=function(o){function i(t){var o={};o.x=t.pageX,o.y=t.pageY,s.updateTooltipPosition(o)}function e(t,o,i){var e=s.getDomElement();if(i){var n;n=s.stringFormat(s.tooltipOptions.content,i),e.html(n),s.updateTooltipPosition({x:o.pageX,y:o.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(i,e)}else e.hide().html("")}var s=this;o.hooks.bindEvents.push(function(o,n){s.plotOptions=o.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(o.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",i))}),o.hooks.shutdown.push(function(o,s){t(o.getPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",i)})},i.prototype.getDomElement=function(){var o;return t("#flotTip").length>0?o=t("#flotTip"):(o=t("<div />").attr("id","flotTip"),o.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&o.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),o},i.prototype.updateTooltipPosition=function(o){var i=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;o.x-t(window).scrollLeft()>t(window).innerWidth()-i&&(o.x-=i),o.y-t(window).scrollTop()>t(window).innerHeight()-e&&(o.y-=e),this.tipPosition.x=o.x,this.tipPosition.y=o.y},i.prototype.stringFormat=function(t,o){var i=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(o.series.label,o.series.data[o.dataIndex][0],o.series.data[o.dataIndex][1],o)),o.series.percent!==void 0&&(t=this.adjustValPrecision(i,t,o.series.percent)),o.series.label!==void 0&&(t=t.replace(e,o.series.label)),this.isTimeMode("xaxis",o)&&this.isXDateFormat(o)&&(t=t.replace(s,this.timestampToDate(o.series.data[o.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",o)&&this.isYDateFormat(o)&&(t=t.replace(n,this.timestampToDate(o.series.data[o.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof o.series.data[o.dataIndex][0]&&(t=this.adjustValPrecision(s,t,o.series.data[o.dataIndex][0])),"number"==typeof o.series.data[o.dataIndex][1]&&(t=this.adjustValPrecision(n,t,o.series.data[o.dataIndex][1])),o.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,o.series.xaxis.tickFormatter(o.series.data[o.dataIndex][0],o.series.xaxis))),o.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,o.series.yaxis.tickFormatter(o.series.data[o.dataIndex][1],o.series.yaxis))),t},i.prototype.isTimeMode=function(t,o){return o.series[t].options.mode!==void 0&&"time"===o.series[t].options.mode},i.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},i.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},i.prototype.timestampToDate=function(o,i){var e=new Date(o);return t.plot.formatDate(e,i)},i.prototype.adjustValPrecision=function(t,o,i){var e,s=o.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,i=i.toFixed(e),o=o.replace(t,i)),o};var e=function(t){new i(t)};t.plot.plugins.push({init:e,options:o,name:"tooltip",version:"0.6.1"})})(jQuery);
|
||||
@@ -3,149 +3,180 @@
|
||||
* 新增支持IE全屏显示
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
/*jshint browser: true, jquery: true */
|
||||
(function($){
|
||||
"use strict";
|
||||
|
||||
// These helper functions available only to our plugin scope.
|
||||
function supportFullScreen(){
|
||||
var doc = document.documentElement;
|
||||
|
||||
return ('requestFullscreen' in doc) ||
|
||||
('msRequestFullscreen' in doc) ||
|
||||
('mozRequestFullScreen' in doc && document.mozFullScreenEnabled) ||
|
||||
('webkitRequestFullScreen' in doc);
|
||||
}
|
||||
|
||||
function requestFullScreen(elem){
|
||||
if (elem.requestFullscreen) {
|
||||
elem.requestFullscreen();
|
||||
} else if (elem.mozRequestFullScreen) {
|
||||
elem.mozRequestFullScreen();
|
||||
} else if (elem.webkitRequestFullScreen) {
|
||||
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
} else if (elem.msRequestFullscreen) {
|
||||
elem.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
function fullScreenStatus(){
|
||||
return document.fullscreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen ||
|
||||
document.msFullscreenElement ||
|
||||
false;
|
||||
}
|
||||
|
||||
function cancelFullScreen(){
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
function onFullScreenEvent(callback){
|
||||
$(document).on("fullscreenchange mozfullscreenchange webkitfullscreenchange", function(){
|
||||
// The full screen status is automatically
|
||||
// passed to our callback as an argument.
|
||||
callback(fullScreenStatus());
|
||||
});
|
||||
}
|
||||
|
||||
// Adding a new test to the jQuery support object
|
||||
$.support.fullscreen = supportFullScreen();
|
||||
|
||||
// Creating the plugin
|
||||
$.fn.fullScreen = function(props){
|
||||
if(!$.support.fullscreen || this.length !== 1) {
|
||||
// The plugin can be called only
|
||||
// on one element at a time
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
if(fullScreenStatus()){
|
||||
// if we are already in fullscreen, exit
|
||||
cancelFullScreen();
|
||||
return this;
|
||||
}
|
||||
|
||||
// You can potentially pas two arguments a color
|
||||
// for the background and a callback function
|
||||
|
||||
var options = $.extend({
|
||||
'background' : '#111',
|
||||
'callback' : $.noop( ),
|
||||
'fullscreenClass' : 'fullScreen'
|
||||
}, props),
|
||||
|
||||
elem = this,
|
||||
|
||||
// This temporary div is the element that is
|
||||
// actually going to be enlarged in full screen
|
||||
|
||||
fs = $('<div>', {
|
||||
'css' : {
|
||||
'overflow-y' : 'auto',
|
||||
'background' : options.background,
|
||||
'width' : '100%',
|
||||
'height' : '100%'
|
||||
}
|
||||
})
|
||||
.insertBefore(elem)
|
||||
.append(elem);
|
||||
|
||||
// You can use the .fullScreen class to
|
||||
// apply styling to your element
|
||||
elem.addClass( options.fullscreenClass );
|
||||
|
||||
// Inserting our element in the temporary
|
||||
// div, after which we zoom it in fullscreen
|
||||
|
||||
requestFullScreen(fs.get(0));
|
||||
|
||||
fs.click(function(e){
|
||||
if(e.target == this){
|
||||
// If the black bar was clicked
|
||||
cancelFullScreen();
|
||||
}
|
||||
});
|
||||
|
||||
elem.cancel = function(){
|
||||
cancelFullScreen();
|
||||
return elem;
|
||||
};
|
||||
|
||||
onFullScreenEvent(function(fullScreen){
|
||||
if(!fullScreen){
|
||||
// We have exited full screen.
|
||||
// Detach event listener
|
||||
$(document).off( 'fullscreenchange mozfullscreenchange webkitfullscreenchange' );
|
||||
// Remove the class and destroy
|
||||
// the temporary div
|
||||
|
||||
elem.removeClass( options.fullscreenClass ).insertBefore(fs);
|
||||
fs.remove();
|
||||
}
|
||||
|
||||
// Calling the facultative user supplied callback
|
||||
if(options.callback) {
|
||||
options.callback(fullScreen);
|
||||
}
|
||||
});
|
||||
|
||||
return elem;
|
||||
};
|
||||
|
||||
$.fn.cancelFullScreen = function( ) {
|
||||
cancelFullScreen();
|
||||
|
||||
return this;
|
||||
};
|
||||
}(jQuery));
|
||||
(function(jQuery) {
|
||||
|
||||
/**
|
||||
* Sets or gets the fullscreen state.
|
||||
*
|
||||
* @param {boolean=} state
|
||||
* True to enable fullscreen mode, false to disable it. If not
|
||||
* specified then the current fullscreen state is returned.
|
||||
* @return {boolean|Element|jQuery|null}
|
||||
* When querying the fullscreen state then the current fullscreen
|
||||
* element (or true if browser doesn't support it) is returned
|
||||
* when browser is currently in full screen mode. False is returned
|
||||
* if browser is not in full screen mode. Null is returned if
|
||||
* browser doesn't support fullscreen mode at all. When setting
|
||||
* the fullscreen state then the current jQuery selection is
|
||||
* returned for chaining.
|
||||
* @this {jQuery}
|
||||
*/
|
||||
function fullScreen(state)
|
||||
{
|
||||
var e, func, doc;
|
||||
|
||||
// Do nothing when nothing was selected
|
||||
if (!this.length) return this;
|
||||
|
||||
// We only use the first selected element because it doesn't make sense
|
||||
// to fullscreen multiple elements.
|
||||
e = (/** @type {Element} */ this[0]);
|
||||
|
||||
// Find the real element and the document (Depends on whether the
|
||||
// document itself or a HTML element was selected)
|
||||
if (e.ownerDocument)
|
||||
{
|
||||
doc = e.ownerDocument;
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = e;
|
||||
e = doc.documentElement;
|
||||
}
|
||||
|
||||
// When no state was specified then return the current state.
|
||||
if (state == null)
|
||||
{
|
||||
// When fullscreen mode is not supported then return null
|
||||
if (!((/** @type {?Function} */ doc["exitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["webkitExitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["webkitCancelFullScreen"])
|
||||
|| (/** @type {?Function} */ doc["msExitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["mozCancelFullScreen"])))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check fullscreen state
|
||||
state = !!doc["fullscreenElement"]
|
||||
|| !!doc["msFullscreenElement"]
|
||||
|| !!doc["webkitIsFullScreen"]
|
||||
|| !!doc["mozFullScreen"];
|
||||
if (!state) return state;
|
||||
|
||||
// Return current fullscreen element or "true" if browser doesn't
|
||||
// support this
|
||||
return (/** @type {?Element} */ doc["fullscreenElement"])
|
||||
|| (/** @type {?Element} */ doc["webkitFullscreenElement"])
|
||||
|| (/** @type {?Element} */ doc["webkitCurrentFullScreenElement"])
|
||||
|| (/** @type {?Element} */ doc["msFullscreenElement"])
|
||||
|| (/** @type {?Element} */ doc["mozFullScreenElement"])
|
||||
|| state;
|
||||
}
|
||||
|
||||
// When state was specified then enter or exit fullscreen mode.
|
||||
if (state)
|
||||
{
|
||||
// Enter fullscreen
|
||||
func = (/** @type {?Function} */ e["requestFullscreen"])
|
||||
|| (/** @type {?Function} */ e["webkitRequestFullscreen"])
|
||||
|| (/** @type {?Function} */ e["webkitRequestFullScreen"])
|
||||
|| (/** @type {?Function} */ e["msRequestFullscreen"])
|
||||
|| (/** @type {?Function} */ e["mozRequestFullScreen"]);
|
||||
if (func)
|
||||
{
|
||||
func.call(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exit fullscreen
|
||||
func = (/** @type {?Function} */ doc["exitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["webkitExitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["webkitCancelFullScreen"])
|
||||
|| (/** @type {?Function} */ doc["msExitFullscreen"])
|
||||
|| (/** @type {?Function} */ doc["mozCancelFullScreen"]);
|
||||
if (func) func.call(doc);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the fullscreen mode.
|
||||
*
|
||||
* @return {!jQuery}
|
||||
* The jQuery selection for chaining.
|
||||
* @this {jQuery}
|
||||
*/
|
||||
function toggleFullScreen()
|
||||
{
|
||||
return (/** @type {!jQuery} */ fullScreen.call(this,
|
||||
!fullScreen.call(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the browser-specific fullscreenchange event and triggers
|
||||
* a jquery event for it.
|
||||
*
|
||||
* @param {?Event} event
|
||||
* The fullscreenchange event.
|
||||
*/
|
||||
function fullScreenChangeHandler(event)
|
||||
{
|
||||
jQuery(document).trigger(new jQuery.Event("fullscreenchange"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the browser-specific fullscreenerror event and triggers
|
||||
* a jquery event for it.
|
||||
*
|
||||
* @param {?Event} event
|
||||
* The fullscreenerror event.
|
||||
*/
|
||||
function fullScreenErrorHandler(event)
|
||||
{
|
||||
jQuery(document).trigger(new jQuery.Event("fullscreenerror"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the fullscreenchange event handler.
|
||||
*/
|
||||
function installFullScreenHandlers()
|
||||
{
|
||||
var e, change, error;
|
||||
|
||||
// Determine event name
|
||||
e = document;
|
||||
if (e["webkitCancelFullScreen"])
|
||||
{
|
||||
change = "webkitfullscreenchange";
|
||||
error = "webkitfullscreenerror";
|
||||
}
|
||||
else if (e["msExitFullscreen"])
|
||||
{
|
||||
change = "MSFullscreenChange";
|
||||
error = "MSFullscreenError";
|
||||
}
|
||||
else if (e["mozCancelFullScreen"])
|
||||
{
|
||||
change = "mozfullscreenchange";
|
||||
error = "mozfullscreenerror";
|
||||
}
|
||||
else
|
||||
{
|
||||
change = "fullscreenchange";
|
||||
error = "fullscreenerror";
|
||||
}
|
||||
|
||||
// Install the event handlers
|
||||
jQuery(document).bind(change, fullScreenChangeHandler);
|
||||
jQuery(document).bind(error, fullScreenErrorHandler);
|
||||
}
|
||||
|
||||
jQuery.fn["fullScreen"] = fullScreen;
|
||||
jQuery.fn["toggleFullScreen"] = toggleFullScreen;
|
||||
installFullScreenHandlers();
|
||||
|
||||
})(jQuery);
|
||||
|
||||
@@ -0,0 +1,621 @@
|
||||
/*!
|
||||
* Jasny Bootstrap v3.1.3 (http://jasny.github.io/bootstrap)
|
||||
* Copyright 2012-2014 Arnold Daniels
|
||||
* Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
.container-smooth {
|
||||
max-width: 1170px;
|
||||
}
|
||||
@media (min-width: 1px) {
|
||||
.container-smooth {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
.btn-labeled {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.btn-label {
|
||||
position: relative;
|
||||
left: -12px;
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
background: transparent;
|
||||
background: rgba(0, 0, 0, .15);
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
.btn-label.btn-label-right {
|
||||
right: -12px;
|
||||
left: auto;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.btn-lg .btn-label {
|
||||
left: -16px;
|
||||
padding: 10px 16px;
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.btn-lg .btn-label.btn-label-right {
|
||||
right: -16px;
|
||||
left: auto;
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
.btn-sm .btn-label {
|
||||
left: -10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
.btn-sm .btn-label.btn-label-right {
|
||||
right: -10px;
|
||||
left: auto;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
.btn-xs .btn-label {
|
||||
left: -5px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
}
|
||||
.btn-xs .btn-label.btn-label-right {
|
||||
right: -5px;
|
||||
left: auto;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
.nav-tabs-bottom {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.nav-tabs-bottom > li {
|
||||
margin-top: -1px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.nav-tabs-bottom > li > a {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
.nav-tabs-bottom > li > a:hover,
|
||||
.nav-tabs-bottom > li > a:focus,
|
||||
.nav-tabs-bottom > li.active > a,
|
||||
.nav-tabs-bottom > li.active > a:hover,
|
||||
.nav-tabs-bottom > li.active > a:focus {
|
||||
border: 1px solid #ddd;
|
||||
border-top-color: transparent;
|
||||
}
|
||||
.nav-tabs-left {
|
||||
border-right: 1px solid #ddd;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.nav-tabs-left > li {
|
||||
float: none;
|
||||
margin-right: -1px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.nav-tabs-left > li > a {
|
||||
margin-right: 0;
|
||||
margin-bottom: 2px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
.nav-tabs-left > li > a:hover,
|
||||
.nav-tabs-left > li > a:focus,
|
||||
.nav-tabs-left > li.active > a,
|
||||
.nav-tabs-left > li.active > a:hover,
|
||||
.nav-tabs-left > li.active > a:focus {
|
||||
border: 1px solid #ddd;
|
||||
border-right-color: transparent;
|
||||
}
|
||||
.row > .nav-tabs-left {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-right: 0;
|
||||
padding-left: 15px;
|
||||
margin-right: -1px;
|
||||
}
|
||||
.row > .nav-tabs-left + .tab-content {
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
.nav-tabs-right {
|
||||
border-bottom: 0;
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
.nav-tabs-right > li {
|
||||
float: none;
|
||||
margin-bottom: 0;
|
||||
margin-left: -1px;
|
||||
}
|
||||
.nav-tabs-right > li > a {
|
||||
margin-bottom: 2px;
|
||||
margin-left: 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
.nav-tabs-right > li > a:hover,
|
||||
.nav-tabs-right > li > a:focus,
|
||||
.nav-tabs-right > li.active > a,
|
||||
.nav-tabs-right > li.active > a:hover,
|
||||
.nav-tabs-right > li.active > a:focus {
|
||||
border: 1px solid #ddd;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.row > .nav-tabs-right {
|
||||
padding-right: 15px;
|
||||
padding-left: 0;
|
||||
}
|
||||
.navmenu,
|
||||
.navbar-offcanvas {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.navmenu-fixed-left,
|
||||
.navmenu-fixed-right,
|
||||
.navbar-offcanvas {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1030;
|
||||
overflow-y: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
.navmenu-fixed-left,
|
||||
.navbar-offcanvas.navmenu-fixed-left {
|
||||
right: auto;
|
||||
left: 0;
|
||||
border-width: 0 1px 0 0;
|
||||
}
|
||||
.navmenu-fixed-right,
|
||||
.navbar-offcanvas {
|
||||
right: 0;
|
||||
left: auto;
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
.navmenu-nav {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.navmenu-nav.dropdown-menu {
|
||||
position: static;
|
||||
float: none;
|
||||
padding-top: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.navbar-offcanvas .navbar-nav {
|
||||
margin: 0;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.navbar-offcanvas {
|
||||
width: auto;
|
||||
border-top: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.navbar-offcanvas.offcanvas {
|
||||
position: static;
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
padding-bottom: 0;
|
||||
overflow: visible !important;
|
||||
}
|
||||
.navbar-offcanvas .navbar-nav.navbar-left:first-child {
|
||||
margin-left: -15px;
|
||||
}
|
||||
.navbar-offcanvas .navbar-nav.navbar-right:last-child {
|
||||
margin-right: -15px;
|
||||
}
|
||||
.navbar-offcanvas .navmenu-brand {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.navmenu-brand {
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
margin: 10px 0;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.navmenu-brand:hover,
|
||||
.navmenu-brand:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
.navmenu-default,
|
||||
.navbar-default .navbar-offcanvas {
|
||||
background-color: #f8f8f8;
|
||||
border-color: #e7e7e7;
|
||||
}
|
||||
.navmenu-default .navmenu-brand,
|
||||
.navbar-default .navbar-offcanvas .navmenu-brand {
|
||||
color: #777;
|
||||
}
|
||||
.navmenu-default .navmenu-brand:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-brand:hover,
|
||||
.navmenu-default .navmenu-brand:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-brand:focus {
|
||||
color: #5e5e5e;
|
||||
background-color: transparent;
|
||||
}
|
||||
.navmenu-default .navmenu-text,
|
||||
.navbar-default .navbar-offcanvas .navmenu-text {
|
||||
color: #777;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .dropdown > a:hover .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a:hover .caret,
|
||||
.navmenu-default .navmenu-nav > .dropdown > a:focus .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a:focus .caret {
|
||||
border-top-color: #333;
|
||||
border-bottom-color: #333;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .open > a,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a,
|
||||
.navmenu-default .navmenu-nav > .open > a:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:hover,
|
||||
.navmenu-default .navmenu-nav > .open > a:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:focus {
|
||||
color: #555;
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .open > a .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a .caret,
|
||||
.navmenu-default .navmenu-nav > .open > a:hover .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:hover .caret,
|
||||
.navmenu-default .navmenu-nav > .open > a:focus .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .open > a:focus .caret {
|
||||
border-top-color: #555;
|
||||
border-bottom-color: #555;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .dropdown > a .caret,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .dropdown > a .caret {
|
||||
border-top-color: #777;
|
||||
border-bottom-color: #777;
|
||||
}
|
||||
.navmenu-default .navmenu-nav.dropdown-menu,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu {
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
.navmenu-default .navmenu-nav.dropdown-menu > .divider,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .divider {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
.navmenu-default .navmenu-nav.dropdown-menu > .active > a,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a,
|
||||
.navmenu-default .navmenu-nav.dropdown-menu > .active > a:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:hover,
|
||||
.navmenu-default .navmenu-nav.dropdown-menu > .active > a:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:focus {
|
||||
background-color: #d7d7d7;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > li > a,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > li > a {
|
||||
color: #777;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > li > a:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > li > a:hover,
|
||||
.navmenu-default .navmenu-nav > li > a:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > li > a:focus {
|
||||
color: #333;
|
||||
background-color: transparent;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .active > a,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .active > a,
|
||||
.navmenu-default .navmenu-nav > .active > a:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .active > a:hover,
|
||||
.navmenu-default .navmenu-nav > .active > a:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .active > a:focus {
|
||||
color: #555;
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
.navmenu-default .navmenu-nav > .disabled > a,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a,
|
||||
.navmenu-default .navmenu-nav > .disabled > a:hover,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a:hover,
|
||||
.navmenu-default .navmenu-nav > .disabled > a:focus,
|
||||
.navbar-default .navbar-offcanvas .navmenu-nav > .disabled > a:focus {
|
||||
color: #ccc;
|
||||
background-color: transparent;
|
||||
}
|
||||
.navmenu-inverse,
|
||||
.navbar-inverse .navbar-offcanvas {
|
||||
background-color: #222;
|
||||
border-color: #080808;
|
||||
}
|
||||
.navmenu-inverse .navmenu-brand,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-brand {
|
||||
color: #999;
|
||||
}
|
||||
.navmenu-inverse .navmenu-brand:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-brand:hover,
|
||||
.navmenu-inverse .navmenu-brand:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-brand:focus {
|
||||
color: #fff;
|
||||
background-color: transparent;
|
||||
}
|
||||
.navmenu-inverse .navmenu-text,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-text {
|
||||
color: #999;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .dropdown > a:hover .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a:hover .caret,
|
||||
.navmenu-inverse .navmenu-nav > .dropdown > a:focus .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a:focus .caret {
|
||||
border-top-color: #fff;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .open > a,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a,
|
||||
.navmenu-inverse .navmenu-nav > .open > a:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:hover,
|
||||
.navmenu-inverse .navmenu-nav > .open > a:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:focus {
|
||||
color: #fff;
|
||||
background-color: #080808;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .open > a .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a .caret,
|
||||
.navmenu-inverse .navmenu-nav > .open > a:hover .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:hover .caret,
|
||||
.navmenu-inverse .navmenu-nav > .open > a:focus .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .open > a:focus .caret {
|
||||
border-top-color: #fff;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .dropdown > a .caret,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .dropdown > a .caret {
|
||||
border-top-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav.dropdown-menu,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu {
|
||||
background-color: #080808;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav.dropdown-menu > .divider,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .divider {
|
||||
background-color: #222;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a,
|
||||
.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:hover,
|
||||
.navmenu-inverse .navmenu-nav.dropdown-menu > .active > a:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav.dropdown-menu > .active > a:focus {
|
||||
background-color: #000;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > li > a,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a {
|
||||
color: #999;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > li > a:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a:hover,
|
||||
.navmenu-inverse .navmenu-nav > li > a:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > li > a:focus {
|
||||
color: #fff;
|
||||
background-color: transparent;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .active > a,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a,
|
||||
.navmenu-inverse .navmenu-nav > .active > a:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a:hover,
|
||||
.navmenu-inverse .navmenu-nav > .active > a:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .active > a:focus {
|
||||
color: #fff;
|
||||
background-color: #080808;
|
||||
}
|
||||
.navmenu-inverse .navmenu-nav > .disabled > a,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a,
|
||||
.navmenu-inverse .navmenu-nav > .disabled > a:hover,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a:hover,
|
||||
.navmenu-inverse .navmenu-nav > .disabled > a:focus,
|
||||
.navbar-inverse .navbar-offcanvas .navmenu-nav > .disabled > a:focus {
|
||||
color: #444;
|
||||
background-color: transparent;
|
||||
}
|
||||
.alert-fixed-top,
|
||||
.alert-fixed-bottom {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 1035;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.alert-fixed-top,
|
||||
.alert-fixed-bottom {
|
||||
left: 50%;
|
||||
width: 992px;
|
||||
margin-left: -496px;
|
||||
}
|
||||
}
|
||||
.alert-fixed-top {
|
||||
top: 0;
|
||||
border-width: 0 0 1px 0;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.alert-fixed-top {
|
||||
border-width: 0 1px 1px 1px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
}
|
||||
.alert-fixed-bottom {
|
||||
bottom: 0;
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.alert-fixed-bottom {
|
||||
border-width: 1px 1px 0 1px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
.offcanvas {
|
||||
display: none;
|
||||
}
|
||||
.offcanvas.in {
|
||||
display: block;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.offcanvas-xs {
|
||||
display: none;
|
||||
}
|
||||
.offcanvas-xs.in {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
.offcanvas-sm {
|
||||
display: none;
|
||||
}
|
||||
.offcanvas-sm.in {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1199px) {
|
||||
.offcanvas-md {
|
||||
display: none;
|
||||
}
|
||||
.offcanvas-md.in {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.offcanvas-lg {
|
||||
display: none;
|
||||
}
|
||||
.offcanvas-lg.in {
|
||||
display: block;
|
||||
}
|
||||
.canvas-sliding {
|
||||
-webkit-transition: top .35s, left .35s, bottom .35s, right .35s;
|
||||
transition: top .35s, left .35s, bottom .35s, right .35s;
|
||||
}
|
||||
.offcanvas-clone {
|
||||
position: absolute !important;
|
||||
top: auto !important;
|
||||
right: 0 !important;
|
||||
bottom: 0 !important;
|
||||
left: auto !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden !important;
|
||||
border: none !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.table.rowlink td:not(.rowlink-skip),
|
||||
.table .rowlink td:not(.rowlink-skip) {
|
||||
cursor: pointer;
|
||||
}
|
||||
.table.rowlink td:not(.rowlink-skip) a,
|
||||
.table .rowlink td:not(.rowlink-skip) a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
.table-hover.rowlink tr:hover td,
|
||||
.table-hover .rowlink tr:hover td {
|
||||
background-color: #cfcfcf;
|
||||
}
|
||||
.btn-file {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.btn-file > input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
cursor: pointer;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
|
||||
direction: ltr;
|
||||
}
|
||||
.fileinput {
|
||||
display: inline-block;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
.fileinput .form-control {
|
||||
display: inline-block;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 5px;
|
||||
margin-bottom: 0;
|
||||
vertical-align: middle;
|
||||
cursor: text;
|
||||
}
|
||||
.fileinput .thumbnail {
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.fileinput .thumbnail > img {
|
||||
max-height: 100%;
|
||||
}
|
||||
.fileinput .btn {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.fileinput-exists .fileinput-new,
|
||||
.fileinput-new .fileinput-exists {
|
||||
display: none;
|
||||
}
|
||||
.fileinput-inline .fileinput-controls {
|
||||
display: inline;
|
||||
}
|
||||
.fileinput-filename {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.form-control .fileinput-filename {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.fileinput.input-group {
|
||||
display: table;
|
||||
}
|
||||
.fileinput.input-group > * {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.fileinput.input-group > .btn-file {
|
||||
z-index: 1;
|
||||
}
|
||||
.fileinput-new.input-group .btn-file,
|
||||
.fileinput-new .input-group .btn-file {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
.fileinput-new.input-group .btn-file.btn-xs,
|
||||
.fileinput-new .input-group .btn-file.btn-xs,
|
||||
.fileinput-new.input-group .btn-file.btn-sm,
|
||||
.fileinput-new .input-group .btn-file.btn-sm {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.fileinput-new.input-group .btn-file.btn-lg,
|
||||
.fileinput-new .input-group .btn-file.btn-lg {
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
.form-group.has-warning .fileinput .fileinput-preview {
|
||||
color: #8a6d3b;
|
||||
}
|
||||
.form-group.has-warning .fileinput .thumbnail {
|
||||
border-color: #faebcc;
|
||||
}
|
||||
.form-group.has-error .fileinput .fileinput-preview {
|
||||
color: #a94442;
|
||||
}
|
||||
.form-group.has-error .fileinput .thumbnail {
|
||||
border-color: #ebccd1;
|
||||
}
|
||||
.form-group.has-success .fileinput .fileinput-preview {
|
||||
color: #3c763d;
|
||||
}
|
||||
.form-group.has-success .fileinput .thumbnail {
|
||||
border-color: #d6e9c6;
|
||||
}
|
||||
.input-group-addon:not(:first-child) {
|
||||
border-left: 0;
|
||||
}
|
||||
/*# sourceMappingURL=jasny-bootstrap.css.map */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@ body .layer-ext-moon .layui-layer-title {
|
||||
font-size: 14px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-bottom: 1px solid #eee;
|
||||
border: none;
|
||||
}
|
||||
|
||||
body .layer-ext-moon .layui-layer-content .layui-layer-ico {
|
||||
|
||||
File diff suppressed because one or more lines are too long
+13
@@ -0,0 +1,13 @@
|
||||
// Peity jQuery plugin version 2.0.3
|
||||
// (c) 2014 Ben Pickles
|
||||
//
|
||||
// http://benpickles.github.io/peity
|
||||
//
|
||||
// Released under MIT license.
|
||||
(function(e,q,h){var o=function(a,b){var c=q.createElementNS("http://www.w3.org/2000/svg",a);e.each(b,function(a,b){c.setAttribute(a,b)});return c},t="createElementNS"in q&&o("svg",{}).createSVGRect,r=1/(window.devicePixelRatio||1),j=e.fn.peity=function(a,b){t&&this.each(function(){var c=e(this),d=c.data("peity");if(d)a&&(d.type=a),e.extend(d.opts,b);else{var f=j.defaults[a],g={};e.each(c.data(),function(a,b){a in f&&(g[a]=b)});var h=e.extend({},f,g,b),d=new s(c,a,h);c.change(function(){d.draw()}).data("peity",
|
||||
d)}d.draw()});return this},s=function(a,b,c){this.$el=a;this.type=b;this.opts=c},m=s.prototype;m.draw=function(){j.graphers[this.type].call(this,this.opts)};m.fill=function(){var a=this.opts.fill,b=a;e.isFunction(b)||(b=function(b,d){return a[d%a.length]});return b};m.prepare=function(a,b){var c;this.svg?c=e(this.svg).empty():(this.svg=o("svg",{"class":"peity"}),this.$el.hide().after(this.svg),c=e(this.svg).data("peity",this));this.svg.setAttribute("height",b);this.svg.setAttribute("width",a);return c};
|
||||
m.values=function(){return e.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};j.defaults={};j.graphers={};j.register=function(a,b,c){this.defaults[a]=b;this.graphers[a]=c};j.register("pie",{delimiter:null,diameter:16,fill:["#ff9900","#fff4dd","#ffc66e"]},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=this.values();if("/"==a.delimiter)var c=b[0],b=[c,h.max(0,b[1]-c)];for(var d=0,c=b.length,f=0;d<c;d++)f+=b[d];for(var a=
|
||||
this.prepare(a.width||a.diameter,a.height||a.diameter),d=a.width(),g=a.height(),a=d/2,g=g/2,p=h.min(a,g),e=h.PI,j=this.fill(),i=-e/2,d=0;d<c;d++){var n=b[d],l=n/f,k;if(0!=l){if(1==l)k=o("circle",{cx:a,cy:g,r:p});else{k=2*l*e;var l=i+k,m=p*h.cos(i)+a,i=p*h.sin(i)+g,q=p*h.cos(l)+a,r=p*h.sin(l)+g;k=o("path",{d:["M",a,g,"L",m,i,"A",p,p,0,k>e?1:0,1,q,r,"Z"].join(" ")});i=l}k.setAttribute("fill",j.call(this,n,d,b));this.svg.appendChild(k)}}});j.register("line",{delimiter:",",fill:"#c6d9fd",height:16,max:null,
|
||||
min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height()-a.strokeWidth,e=g/(b.length-1),c=c-d,j=0==c?f:f/c,m=f+d*j,c=[0,m],i=0;i<b.length;i++)c.push(i*e,f-j*(b[i]-d)+a.strokeWidth/2);c.push(g,m);b=o("polygon",{fill:a.fill,points:c.join(" ")});this.svg.appendChild(b);a.strokeWidth&&(a=o("polyline",{fill:"transparent",
|
||||
points:c.slice(2,c.length-2).join(" "),stroke:a.stroke,"stroke-width":a.strokeWidth,"stroke-linecap":"square"}),this.svg.appendChild(a))});j.register("bar",{delimiter:",",fill:["#4D89F9"],gap:1,height:16,max:null,min:0,width:32},function(a){for(var b=this.values(),c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height(),e=c-d,j=0==e?0:f/e,a=a.gap,g=(g+a)/b.length,m=this.fill(),i=0;i<b.length;i++){var n=b[i],l=f-j*(n-d),k=j*n;if(0==
|
||||
k){if(k=r,0>=d&&0<c||0==e)l-=r}else 0>k&&(l+=k,k=-k);n=o("rect",{fill:m.call(this,n,i,b),x:i*g,y:l,width:g-a,height:k});this.svg.appendChild(n)}})})(jQuery,document,Math);
|
||||
+5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,484 @@
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
vertical-align: middle; }
|
||||
.select2-container .select2-selection--single {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 28px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-selection--single .select2-selection__clear {
|
||||
position: relative; }
|
||||
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||
padding-right: 8px;
|
||||
padding-left: 20px; }
|
||||
.select2-container .select2-selection--multiple {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-search--inline {
|
||||
float: left; }
|
||||
.select2-container .select2-search--inline .select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
padding: 0; }
|
||||
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
.select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
width: 100%;
|
||||
z-index: 1051; }
|
||||
|
||||
.select2-results {
|
||||
display: block; }
|
||||
|
||||
.select2-results__options {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-results__option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
|
||||
.select2-container--open .select2-dropdown {
|
||||
left: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--above {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--below {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-search--dropdown {
|
||||
display: block;
|
||||
padding: 4px; }
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
.select2-search--dropdown.select2-search--hide {
|
||||
display: none; }
|
||||
|
||||
.select2-close-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
z-index: 99;
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0); }
|
||||
|
||||
.select2-hidden-accessible {
|
||||
border: 0 !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
-webkit-clip-path: inset(50%) !important;
|
||||
clip-path: inset(50%) !important;
|
||||
height: 1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
white-space: nowrap !important; }
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
|
||||
color: #999;
|
||||
margin-top: 5px;
|
||||
float: left; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #333; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
border: solid black 1px;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa; }
|
||||
|
||||
.select2-container--default .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield; }
|
||||
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--default .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||
color: #999; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
|
||||
.select2-container--default .select2-results__option .select2-results__option {
|
||||
padding-left: 1em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em; }
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
.select2-container--default .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic .select2-selection--single {
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
outline: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
border: none;
|
||||
border-left: 1px solid #aaa;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
border: none;
|
||||
border-right: 1px solid #aaa;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||
background: transparent;
|
||||
border: none; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||
|
||||
.select2-container--classic .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
outline: 0; }
|
||||
.select2-container--classic .select2-selection--multiple:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||
display: none; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #555; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||
border: 1px solid #5897fb; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||
outline: 0;
|
||||
box-shadow: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid transparent; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--above {
|
||||
border-bottom: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--below {
|
||||
border-top: none; }
|
||||
|
||||
.select2-container--classic .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--classic .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||
color: grey; }
|
||||
|
||||
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #3875d7;
|
||||
color: white; }
|
||||
|
||||
.select2-container--classic .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
Common
|
||||
*/
|
||||
|
||||
.wizard,
|
||||
.tabcontrol
|
||||
{
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wizard a,
|
||||
.tabcontrol a
|
||||
{
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.wizard ul,
|
||||
.tabcontrol ul
|
||||
{
|
||||
list-style: none !important;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wizard ul > li,
|
||||
.tabcontrol ul > li
|
||||
{
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Accessibility */
|
||||
.wizard > .steps .current-info,
|
||||
.tabcontrol > .steps .current-info
|
||||
{
|
||||
position: absolute;
|
||||
left: -999em;
|
||||
}
|
||||
|
||||
.wizard > .content > .title,
|
||||
.tabcontrol > .content > .title
|
||||
{
|
||||
position: absolute;
|
||||
left: -999em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Wizard
|
||||
*/
|
||||
|
||||
.wizard > .steps
|
||||
{
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wizard.vertical > .steps
|
||||
{
|
||||
display: inline;
|
||||
float: left;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.wizard > .steps > ul > li
|
||||
{
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.wizard > .steps > ul > li,
|
||||
.wizard > .actions > ul > li
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.wizard.vertical > .steps > ul > li
|
||||
{
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wizard > .steps a,
|
||||
.wizard > .steps a:hover,
|
||||
.wizard > .steps a:active
|
||||
{
|
||||
display: block;
|
||||
width: auto;
|
||||
margin: 0 0.5em 0.5em;
|
||||
padding: 8px;
|
||||
text-decoration: none;
|
||||
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.wizard > .steps .disabled a,
|
||||
.wizard > .steps .disabled a:hover,
|
||||
.wizard > .steps .disabled a:active
|
||||
{
|
||||
background: #eee;
|
||||
color: #aaa;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.wizard > .steps .current a,
|
||||
.wizard > .steps .current a:hover,
|
||||
.wizard > .steps .current a:active
|
||||
{
|
||||
background: #1AB394;
|
||||
color: #fff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.wizard > .steps .done a,
|
||||
.wizard > .steps .done a:hover,
|
||||
.wizard > .steps .done a:active
|
||||
{
|
||||
background: #6fd1bd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.wizard > .steps .error a,
|
||||
.wizard > .steps .error a:hover,
|
||||
.wizard > .steps .error a:active
|
||||
{
|
||||
background: #ED5565 ;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.wizard > .content
|
||||
{
|
||||
background: #eee;
|
||||
display: block;
|
||||
margin: 5px 5px 10px 5px;
|
||||
min-height: 120px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: auto;
|
||||
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.wizard-big.wizard > .content {
|
||||
min-height: 320px;
|
||||
}
|
||||
.wizard.vertical > .content
|
||||
{
|
||||
display: inline;
|
||||
float: left;
|
||||
margin: 0 2.5% 0.5em 2.5%;
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
.wizard > .content > .body
|
||||
{
|
||||
float: left;
|
||||
position: absolute;
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
padding: 2.5%;
|
||||
}
|
||||
|
||||
.wizard > .content > .body ul
|
||||
{
|
||||
list-style: disc !important;
|
||||
}
|
||||
|
||||
.wizard > .content > .body ul > li
|
||||
{
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
.wizard > .content > .body > iframe
|
||||
{
|
||||
border: 0 none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.wizard > .content > .body input
|
||||
{
|
||||
display: block;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.wizard > .content > .body input[type="checkbox"]
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.wizard > .content > .body input.error
|
||||
{
|
||||
background: rgb(251, 227, 228);
|
||||
border: 1px solid #fbc2c4;
|
||||
color: #8a1f11;
|
||||
}
|
||||
|
||||
.wizard > .content > .body label
|
||||
{
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.wizard > .content > .body label.error
|
||||
{
|
||||
color: #8a1f11;
|
||||
display: inline-block;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.wizard > .actions
|
||||
{
|
||||
position: relative;
|
||||
display: block;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wizard.vertical > .actions
|
||||
{
|
||||
display: inline;
|
||||
float: right;
|
||||
margin: 0 2.5%;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.wizard > .actions > ul
|
||||
{
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.wizard > .actions > ul > li
|
||||
{
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
.wizard.vertical > .actions > ul > li
|
||||
{
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.wizard > .actions a,
|
||||
.wizard > .actions a:hover,
|
||||
.wizard > .actions a:active
|
||||
{
|
||||
background: #1AB394;
|
||||
color: #fff;
|
||||
display: block;
|
||||
padding: 0.5em 1em;
|
||||
text-decoration: none;
|
||||
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.wizard > .actions .disabled a,
|
||||
.wizard > .actions .disabled a:hover,
|
||||
.wizard > .actions .disabled a:active
|
||||
{
|
||||
background: #eee;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.wizard > .loading
|
||||
{
|
||||
}
|
||||
|
||||
.wizard > .loading .spinner
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Tabcontrol
|
||||
*/
|
||||
|
||||
.tabcontrol > .steps
|
||||
{
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul
|
||||
{
|
||||
position: relative;
|
||||
margin: 6px 0 0 0;
|
||||
top: 1px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li
|
||||
{
|
||||
float: left;
|
||||
margin: 5px 2px 0 0;
|
||||
padding: 1px;
|
||||
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-moz-border-radius-topleft: 5px;
|
||||
-moz-border-radius-topright: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li:hover
|
||||
{
|
||||
background: #edecec;
|
||||
border: 1px solid #bbb;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li.current
|
||||
{
|
||||
background: #fff;
|
||||
border: 1px solid #bbb;
|
||||
border-bottom: 0 none;
|
||||
padding: 0 0 1px 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li > a
|
||||
{
|
||||
color: #5f5f5f;
|
||||
display: inline-block;
|
||||
border: 0 none;
|
||||
margin: 0;
|
||||
padding: 10px 30px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li > a:hover
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tabcontrol > .steps > ul > li.current > a
|
||||
{
|
||||
padding: 15px 30px 10px 30px;
|
||||
}
|
||||
|
||||
.tabcontrol > .content
|
||||
{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 35em;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #bbb;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.tabcontrol > .content > .body
|
||||
{
|
||||
float: left;
|
||||
position: absolute;
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
padding: 2.5%;
|
||||
}
|
||||
|
||||
.tabcontrol > .content > .body ul
|
||||
{
|
||||
list-style: disc !important;
|
||||
}
|
||||
|
||||
.tabcontrol > .content > .body ul > li
|
||||
{
|
||||
display: list-item;
|
||||
}
|
||||
label.error { position:inherit; }
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1042
File diff suppressed because it is too large
Load Diff
+10
File diff suppressed because one or more lines are too long
@@ -7547,6 +7547,7 @@
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'underline', 'clear']],
|
||||
['fontsize',['fontsize']],
|
||||
['fontname', ['fontname']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+774
@@ -0,0 +1,774 @@
|
||||
/* =============================================================
|
||||
* bootstrap3-typeahead.js v4.0.2
|
||||
* https://github.com/bassjobsen/Bootstrap-3-Typeahead
|
||||
* =============================================================
|
||||
* Original written by @mdo and @fat
|
||||
* =============================================================
|
||||
* Copyright 2014 Bass Jobsen @bassjobsen
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================ */
|
||||
|
||||
|
||||
(function (root, factory) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// CommonJS module is defined
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = factory(require('jquery'));
|
||||
}
|
||||
// AMD module is defined
|
||||
else if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], function ($) {
|
||||
return factory($);
|
||||
});
|
||||
} else {
|
||||
factory(root.jQuery);
|
||||
}
|
||||
|
||||
}(this, function ($) {
|
||||
|
||||
'use strict';
|
||||
// jshint laxcomma: true
|
||||
|
||||
|
||||
/* TYPEAHEAD PUBLIC CLASS DEFINITION
|
||||
* ================================= */
|
||||
|
||||
var Typeahead = function (element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, Typeahead.defaults, options);
|
||||
this.matcher = this.options.matcher || this.matcher;
|
||||
this.sorter = this.options.sorter || this.sorter;
|
||||
this.select = this.options.select || this.select;
|
||||
this.autoSelect = typeof this.options.autoSelect == 'boolean' ? this.options.autoSelect : true;
|
||||
this.highlighter = this.options.highlighter || this.highlighter;
|
||||
this.render = this.options.render || this.render;
|
||||
this.updater = this.options.updater || this.updater;
|
||||
this.displayText = this.options.displayText || this.displayText;
|
||||
this.itemLink = this.options.itemLink || this.itemLink;
|
||||
this.itemTitle = this.options.itemTitle || this.itemTitle;
|
||||
this.followLinkOnSelect = this.options.followLinkOnSelect || this.followLinkOnSelect;
|
||||
this.source = this.options.source;
|
||||
this.delay = this.options.delay;
|
||||
this.theme = this.options.theme && this.options.themes && this.options.themes[this.options.theme] || Typeahead.defaults.themes[Typeahead.defaults.theme];
|
||||
this.$menu = $(this.options.menu || this.theme.menu);
|
||||
this.$appendTo = this.options.appendTo ? $(this.options.appendTo) : null;
|
||||
this.fitToElement = typeof this.options.fitToElement == 'boolean' ? this.options.fitToElement : false;
|
||||
this.shown = false;
|
||||
this.listen();
|
||||
this.showHintOnFocus = typeof this.options.showHintOnFocus == 'boolean' || this.options.showHintOnFocus === 'all' ? this.options.showHintOnFocus : false;
|
||||
this.afterSelect = this.options.afterSelect;
|
||||
this.afterEmptySelect = this.options.afterEmptySelect;
|
||||
this.addItem = false;
|
||||
this.value = this.$element.val() || this.$element.text();
|
||||
this.keyPressed = false;
|
||||
this.focused = this.$element.is(':focus');
|
||||
this.changeInputOnSelect = this.options.changeInputOnSelect || this.changeInputOnSelect;
|
||||
this.changeInputOnMove = this.options.changeInputOnMove || this.changeInputOnMove;
|
||||
this.openLinkInNewTab = this.options.openLinkInNewTab || this.openLinkInNewTab;
|
||||
this.selectOnBlur = this.options.selectOnBlur || this.selectOnBlur;
|
||||
this.showCategoryHeader = this.options.showCategoryHeader || this.showCategoryHeader;
|
||||
};
|
||||
|
||||
Typeahead.prototype = {
|
||||
|
||||
constructor: Typeahead,
|
||||
|
||||
|
||||
setDefault: function (val) {
|
||||
// var val = this.$menu.find('.active').data('value');
|
||||
this.$element.data('active', val);
|
||||
if (this.autoSelect || val) {
|
||||
var newVal = this.updater(val);
|
||||
// Updater can be set to any random functions via "options" parameter in constructor above.
|
||||
// Add null check for cases when updater returns void or undefined.
|
||||
if (!newVal) {
|
||||
newVal = '';
|
||||
}
|
||||
this.$element
|
||||
.val(this.displayText(newVal) || newVal)
|
||||
.text(this.displayText(newVal) || newVal)
|
||||
.change();
|
||||
this.afterSelect(newVal);
|
||||
}
|
||||
return this.hide();
|
||||
},
|
||||
|
||||
select: function () {
|
||||
var val = this.$menu.find('.active').data('value');
|
||||
|
||||
this.$element.data('active', val);
|
||||
if (this.autoSelect || val) {
|
||||
var newVal = this.updater(val);
|
||||
// Updater can be set to any random functions via "options" parameter in constructor above.
|
||||
// Add null check for cases when updater returns void or undefined.
|
||||
if (!newVal) {
|
||||
newVal = '';
|
||||
}
|
||||
|
||||
if (this.changeInputOnSelect) {
|
||||
this.$element
|
||||
.val(this.displayText(newVal) || newVal)
|
||||
.text(this.displayText(newVal) || newVal)
|
||||
.change();
|
||||
}
|
||||
|
||||
if (this.followLinkOnSelect && this.itemLink(val)) {
|
||||
if (this.openLinkInNewTab) {
|
||||
window.open(this.itemLink(val), '_blank');
|
||||
} else {
|
||||
document.location = this.itemLink(val);
|
||||
}
|
||||
this.afterSelect(newVal);
|
||||
} else if (this.followLinkOnSelect && !this.itemLink(val)) {
|
||||
this.afterEmptySelect(newVal);
|
||||
} else {
|
||||
this.afterSelect(newVal);
|
||||
}
|
||||
} else {
|
||||
this.afterEmptySelect();
|
||||
}
|
||||
|
||||
return this.hide();
|
||||
},
|
||||
|
||||
updater: function (item) {
|
||||
return item;
|
||||
},
|
||||
|
||||
setSource: function (source) {
|
||||
this.source = source;
|
||||
},
|
||||
|
||||
show: function () {
|
||||
var pos = $.extend({}, this.$element.position(), {
|
||||
height: this.$element[0].offsetHeight
|
||||
});
|
||||
|
||||
var scrollHeight = typeof this.options.scrollHeight == 'function' ?
|
||||
this.options.scrollHeight.call() :
|
||||
this.options.scrollHeight;
|
||||
|
||||
var element;
|
||||
if (this.shown) {
|
||||
element = this.$menu;
|
||||
} else if (this.$appendTo) {
|
||||
element = this.$menu.appendTo(this.$appendTo);
|
||||
this.hasSameParent = this.$appendTo.is(this.$element.parent());
|
||||
} else {
|
||||
element = this.$menu.insertAfter(this.$element);
|
||||
this.hasSameParent = true;
|
||||
}
|
||||
|
||||
if (!this.hasSameParent) {
|
||||
// We cannot rely on the element position, need to position relative to the window
|
||||
element.css('position', 'fixed');
|
||||
var offset = this.$element.offset();
|
||||
pos.top = offset.top;
|
||||
pos.left = offset.left;
|
||||
}
|
||||
// The rules for bootstrap are: 'dropup' in the parent and 'dropdown-menu-right' in the element.
|
||||
// Note that to get right alignment, you'll need to specify `menu` in the options to be:
|
||||
// '<ul class="typeahead dropdown-menu" role="listbox"></ul>'
|
||||
var dropup = $(element).parent().hasClass('dropup');
|
||||
var newTop = dropup ? 'auto' : (pos.top + pos.height + scrollHeight);
|
||||
var right = $(element).hasClass('dropdown-menu-right');
|
||||
var newLeft = right ? 'auto' : pos.left;
|
||||
// it seems like setting the css is a bad idea (just let Bootstrap do it), but I'll keep the old
|
||||
// logic in place except for the dropup/right-align cases.
|
||||
element.css({ top: newTop, left: newLeft }).show();
|
||||
|
||||
if (this.options.fitToElement === true) {
|
||||
element.css('width', this.$element.outerWidth() + 'px');
|
||||
}
|
||||
|
||||
this.shown = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.$menu.hide();
|
||||
this.shown = false;
|
||||
return this;
|
||||
},
|
||||
|
||||
lookup: function (query) {
|
||||
if (typeof(query) != 'undefined' && query !== null) {
|
||||
this.query = query;
|
||||
} else {
|
||||
this.query = this.$element.val();
|
||||
}
|
||||
|
||||
if (this.query.length < this.options.minLength && !this.options.showHintOnFocus) {
|
||||
return this.shown ? this.hide() : this;
|
||||
}
|
||||
|
||||
var worker = $.proxy(function () {
|
||||
|
||||
// Bloodhound (since 0.11) needs three arguments.
|
||||
// Two of them are callback functions (sync and async) for local and remote data processing
|
||||
// see https://github.com/twitter/typeahead.js/blob/master/src/bloodhound/bloodhound.js#L132
|
||||
if ($.isFunction(this.source) && this.source.length === 3) {
|
||||
this.source(this.query, $.proxy(this.process, this), $.proxy(this.process, this));
|
||||
} else if ($.isFunction(this.source)) {
|
||||
this.source(this.query, $.proxy(this.process, this));
|
||||
} else if (this.source) {
|
||||
this.process(this.source);
|
||||
}
|
||||
}, this);
|
||||
|
||||
clearTimeout(this.lookupWorker);
|
||||
this.lookupWorker = setTimeout(worker, this.delay);
|
||||
},
|
||||
|
||||
process: function (items) {
|
||||
var that = this;
|
||||
|
||||
items = $.grep(items, function (item) {
|
||||
return that.matcher(item);
|
||||
});
|
||||
|
||||
items = this.sorter(items);
|
||||
|
||||
if (!items.length && !this.options.addItem) {
|
||||
return this.shown ? this.hide() : this;
|
||||
}
|
||||
|
||||
if (items.length > 0) {
|
||||
this.$element.data('active', items[0]);
|
||||
} else {
|
||||
this.$element.data('active', null);
|
||||
}
|
||||
|
||||
if (this.options.items != 'all') {
|
||||
items = items.slice(0, this.options.items);
|
||||
}
|
||||
|
||||
// Add item
|
||||
if (this.options.addItem) {
|
||||
items.push(this.options.addItem);
|
||||
}
|
||||
|
||||
return this.render(items).show();
|
||||
},
|
||||
|
||||
matcher: function (item) {
|
||||
var it = this.displayText(item);
|
||||
return ~it.toLowerCase().indexOf(this.query.toLowerCase());
|
||||
},
|
||||
|
||||
sorter: function (items) {
|
||||
var beginswith = [];
|
||||
var caseSensitive = [];
|
||||
var caseInsensitive = [];
|
||||
var item;
|
||||
|
||||
while ((item = items.shift())) {
|
||||
var it = this.displayText(item);
|
||||
if (!it.toLowerCase().indexOf(this.query.toLowerCase())) {
|
||||
beginswith.push(item);
|
||||
} else if (~it.indexOf(this.query)) {
|
||||
caseSensitive.push(item);
|
||||
} else {
|
||||
caseInsensitive.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return beginswith.concat(caseSensitive, caseInsensitive);
|
||||
},
|
||||
|
||||
highlighter: function (item) {
|
||||
var text = this.query;
|
||||
if (text === '') {
|
||||
return item;
|
||||
}
|
||||
var matches = item.match(/(>)([^<]*)(<)/g);
|
||||
var first = [];
|
||||
var second = [];
|
||||
var i;
|
||||
if (matches && matches.length) {
|
||||
// html
|
||||
for (i = 0; i < matches.length; ++i) {
|
||||
if (matches[i].length > 2) {// escape '><'
|
||||
first.push(matches[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// text
|
||||
first = [];
|
||||
first.push(item);
|
||||
}
|
||||
text = text.replace((/[\(\)\/\.\*\+\?\[\]]/g), function (mat) {
|
||||
return '\\' + mat;
|
||||
});
|
||||
var reg = new RegExp(text, 'g');
|
||||
var m;
|
||||
for (i = 0; i < first.length; ++i) {
|
||||
m = first[i].match(reg);
|
||||
if (m && m.length > 0) {// find all text nodes matches
|
||||
second.push(first[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < second.length; ++i) {
|
||||
item = item.replace(second[i], second[i].replace(reg, '<strong>$&</strong>'));
|
||||
}
|
||||
return item;
|
||||
},
|
||||
|
||||
render: function (items) {
|
||||
var that = this;
|
||||
var self = this;
|
||||
var activeFound = false;
|
||||
var data = [];
|
||||
var _category = that.options.separator;
|
||||
|
||||
$.each(items, function (key, value) {
|
||||
// inject separator
|
||||
if (key > 0 && value[_category] !== items[key - 1][_category]) {
|
||||
data.push({
|
||||
__type: 'divider'
|
||||
});
|
||||
}
|
||||
|
||||
if (this.showCategoryHeader) {
|
||||
// inject category header
|
||||
if (value[_category] && (key === 0 || value[_category] !== items[key - 1][_category])) {
|
||||
data.push({
|
||||
__type: 'category',
|
||||
name: value[_category]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
data.push(value);
|
||||
});
|
||||
|
||||
items = $(data).map(function (i, item) {
|
||||
if ((item.__type || false) == 'category'){
|
||||
return $(that.options.headerHtml || that.theme.headerHtml).text(item.name)[0];
|
||||
}
|
||||
|
||||
if ((item.__type || false) == 'divider'){
|
||||
return $(that.options.headerDivider || that.theme.headerDivider)[0];
|
||||
}
|
||||
|
||||
var text = self.displayText(item);
|
||||
i = $(that.options.item || that.theme.item).data('value', item);
|
||||
i.find(that.options.itemContentSelector || that.theme.itemContentSelector)
|
||||
.addBack(that.options.itemContentSelector || that.theme.itemContentSelector)
|
||||
.html(that.highlighter(text, item));
|
||||
if(that.options.followLinkOnSelect) {
|
||||
i.find('a').attr('href', self.itemLink(item));
|
||||
}
|
||||
i.find('a').attr('title', self.itemTitle(item));
|
||||
if (text == self.$element.val()) {
|
||||
i.addClass('active');
|
||||
self.$element.data('active', item);
|
||||
activeFound = true;
|
||||
}
|
||||
return i[0];
|
||||
});
|
||||
|
||||
if (this.autoSelect && !activeFound) {
|
||||
items.filter(':not(.dropdown-header)').first().addClass('active');
|
||||
this.$element.data('active', items.first().data('value'));
|
||||
}
|
||||
this.$menu.html(items);
|
||||
return this;
|
||||
},
|
||||
|
||||
displayText: function (item) {
|
||||
return typeof item !== 'undefined' && typeof item.name != 'undefined' ? item.name : item;
|
||||
},
|
||||
|
||||
itemLink: function (item) {
|
||||
return null;
|
||||
},
|
||||
|
||||
itemTitle: function (item) {
|
||||
return null;
|
||||
},
|
||||
|
||||
next: function (event) {
|
||||
var active = this.$menu.find('.active').removeClass('active');
|
||||
var next = active.next();
|
||||
|
||||
if (!next.length) {
|
||||
next = $(this.$menu.find($(this.options.item || this.theme.item).prop('tagName'))[0]);
|
||||
}
|
||||
|
||||
while (next.hasClass('divider') || next.hasClass('dropdown-header')) {
|
||||
next = next.next();
|
||||
}
|
||||
|
||||
next.addClass('active');
|
||||
// added for screen reader
|
||||
var newVal = this.updater(next.data('value'));
|
||||
if (this.changeInputOnMove) {
|
||||
this.$element.val(this.displayText(newVal) || newVal);
|
||||
}
|
||||
},
|
||||
|
||||
prev: function (event) {
|
||||
var active = this.$menu.find('.active').removeClass('active');
|
||||
var prev = active.prev();
|
||||
|
||||
if (!prev.length) {
|
||||
prev = this.$menu.find($(this.options.item || this.theme.item).prop('tagName')).last();
|
||||
}
|
||||
|
||||
while (prev.hasClass('divider') || prev.hasClass('dropdown-header')) {
|
||||
prev = prev.prev();
|
||||
}
|
||||
|
||||
prev.addClass('active');
|
||||
// added for screen reader
|
||||
var newVal = this.updater(prev.data('value'));
|
||||
if (this.changeInputOnMove) {
|
||||
this.$element.val(this.displayText(newVal) || newVal);
|
||||
}
|
||||
},
|
||||
|
||||
listen: function () {
|
||||
this.$element
|
||||
.on('focus.bootstrap3Typeahead', $.proxy(this.focus, this))
|
||||
.on('blur.bootstrap3Typeahead', $.proxy(this.blur, this))
|
||||
.on('keypress.bootstrap3Typeahead', $.proxy(this.keypress, this))
|
||||
.on('propertychange.bootstrap3Typeahead input.bootstrap3Typeahead', $.proxy(this.input, this))
|
||||
.on('keyup.bootstrap3Typeahead', $.proxy(this.keyup, this));
|
||||
|
||||
if (this.eventSupported('keydown')) {
|
||||
this.$element.on('keydown.bootstrap3Typeahead', $.proxy(this.keydown, this));
|
||||
}
|
||||
|
||||
var itemTagName = $(this.options.item || this.theme.item).prop('tagName');
|
||||
if ('ontouchstart' in document.documentElement && 'onmousemove' in document.documentElement) {
|
||||
this.$menu
|
||||
.on('touchstart', itemTagName, $.proxy(this.touchstart, this))
|
||||
.on('touchend', itemTagName, $.proxy(this.click, this))
|
||||
.on('click', $.proxy(this.click, this))
|
||||
.on('mouseenter', itemTagName, $.proxy(this.mouseenter, this))
|
||||
.on('mouseleave', itemTagName, $.proxy(this.mouseleave, this))
|
||||
.on('mousedown', $.proxy(this.mousedown,this));
|
||||
} else if ('ontouchstart' in document.documentElement) {
|
||||
this.$menu
|
||||
.on('touchstart', itemTagName, $.proxy(this.touchstart, this))
|
||||
.on('touchend', itemTagName, $.proxy(this.click, this));
|
||||
} else {
|
||||
this.$menu
|
||||
.on('click', $.proxy(this.click, this))
|
||||
.on('mouseenter', itemTagName, $.proxy(this.mouseenter, this))
|
||||
.on('mouseleave', itemTagName, $.proxy(this.mouseleave, this))
|
||||
.on('mousedown', $.proxy(this.mousedown, this));
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.$element.data('typeahead', null);
|
||||
this.$element.data('active', null);
|
||||
this.$element
|
||||
.unbind('focus.bootstrap3Typeahead')
|
||||
.unbind('blur.bootstrap3Typeahead')
|
||||
.unbind('keypress.bootstrap3Typeahead')
|
||||
.unbind('propertychange.bootstrap3Typeahead input.bootstrap3Typeahead')
|
||||
.unbind('keyup.bootstrap3Typeahead');
|
||||
|
||||
if (this.eventSupported('keydown')) {
|
||||
this.$element.unbind('keydown.bootstrap3-typeahead');
|
||||
}
|
||||
|
||||
this.$menu.remove();
|
||||
this.destroyed = true;
|
||||
},
|
||||
|
||||
eventSupported: function (eventName) {
|
||||
var isSupported = eventName in this.$element;
|
||||
if (!isSupported) {
|
||||
this.$element.setAttribute(eventName, 'return;');
|
||||
isSupported = typeof this.$element[eventName] === 'function';
|
||||
}
|
||||
return isSupported;
|
||||
},
|
||||
|
||||
move: function (e) {
|
||||
if (!this.shown) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 9: // tab
|
||||
case 13: // enter
|
||||
case 27: // escape
|
||||
e.preventDefault();
|
||||
break;
|
||||
|
||||
case 38: // up arrow
|
||||
// with the shiftKey (this is actually the left parenthesis)
|
||||
if (e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
this.prev();
|
||||
break;
|
||||
|
||||
case 40: // down arrow
|
||||
// with the shiftKey (this is actually the right parenthesis)
|
||||
if (e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
this.next();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
keydown: function (e) {
|
||||
/**
|
||||
* Prevent to make an ajax call while copying and pasting.
|
||||
*
|
||||
* @author Simone Sacchi
|
||||
* @version 2018/01/18
|
||||
*/
|
||||
if (e.keyCode === 17) { // ctrl
|
||||
return;
|
||||
}
|
||||
this.keyPressed = true;
|
||||
this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40, 38, 9, 13, 27]);
|
||||
if (!this.shown && e.keyCode == 40) {
|
||||
this.lookup();
|
||||
} else {
|
||||
this.move(e);
|
||||
}
|
||||
},
|
||||
|
||||
keypress: function (e) {
|
||||
if (this.suppressKeyPressRepeat) {
|
||||
return;
|
||||
}
|
||||
this.move(e);
|
||||
},
|
||||
|
||||
input: function (e) {
|
||||
// This is a fixed for IE10/11 that fires the input event when a placehoder is changed
|
||||
// (https://connect.microsoft.com/IE/feedback/details/810538/ie-11-fires-input-event-on-focus)
|
||||
var currentValue = this.$element.val() || this.$element.text();
|
||||
if (this.value !== currentValue) {
|
||||
this.value = currentValue;
|
||||
this.lookup();
|
||||
}
|
||||
},
|
||||
|
||||
keyup: function (e) {
|
||||
if (this.destroyed) {
|
||||
return;
|
||||
}
|
||||
switch (e.keyCode) {
|
||||
case 40: // down arrow
|
||||
case 38: // up arrow
|
||||
case 16: // shift
|
||||
case 17: // ctrl
|
||||
case 18: // alt
|
||||
break;
|
||||
|
||||
case 9: // tab
|
||||
if (!this.shown || (this.showHintOnFocus && !this.keyPressed)) {
|
||||
return;
|
||||
}
|
||||
this.select();
|
||||
break;
|
||||
case 13: // enter
|
||||
if (!this.shown) {
|
||||
return;
|
||||
}
|
||||
this.select();
|
||||
break;
|
||||
|
||||
case 27: // escape
|
||||
if (!this.shown) {
|
||||
return;
|
||||
}
|
||||
this.hide();
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
focus: function (e) {
|
||||
if (!this.focused) {
|
||||
this.focused = true;
|
||||
this.keyPressed = false;
|
||||
if (this.options.showHintOnFocus && this.skipShowHintOnFocus !== true) {
|
||||
if (this.options.showHintOnFocus === 'all') {
|
||||
this.lookup('');
|
||||
} else {
|
||||
this.lookup();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.skipShowHintOnFocus) {
|
||||
this.skipShowHintOnFocus = false;
|
||||
}
|
||||
},
|
||||
|
||||
blur: function (e) {
|
||||
if (!this.mousedover && !this.mouseddown && this.shown) {
|
||||
if (this.selectOnBlur) {
|
||||
this.select();
|
||||
}
|
||||
this.hide();
|
||||
this.focused = false;
|
||||
this.keyPressed = false;
|
||||
} else if (this.mouseddown) {
|
||||
// This is for IE that blurs the input when user clicks on scroll.
|
||||
// We set the focus back on the input and prevent the lookup to occur again
|
||||
this.skipShowHintOnFocus = true;
|
||||
this.$element.focus();
|
||||
this.mouseddown = false;
|
||||
}
|
||||
},
|
||||
|
||||
click: function (e) {
|
||||
e.preventDefault();
|
||||
this.skipShowHintOnFocus = true;
|
||||
this.select();
|
||||
this.$element.focus();
|
||||
this.hide();
|
||||
},
|
||||
|
||||
mouseenter: function (e) {
|
||||
this.mousedover = true;
|
||||
this.$menu.find('.active').removeClass('active');
|
||||
$(e.currentTarget).addClass('active');
|
||||
},
|
||||
|
||||
mouseleave: function (e) {
|
||||
this.mousedover = false;
|
||||
if (!this.focused && this.shown) {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* We track the mousedown for IE. When clicking on the menu scrollbar, IE makes the input blur thus hiding the menu.
|
||||
*/
|
||||
mousedown: function (e) {
|
||||
this.mouseddown = true;
|
||||
this.$menu.one('mouseup', function (e) {
|
||||
// IE won't fire this, but FF and Chrome will so we reset our flag for them here
|
||||
this.mouseddown = false;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
touchstart: function (e) {
|
||||
e.preventDefault();
|
||||
this.$menu.find('.active').removeClass('active');
|
||||
$(e.currentTarget).addClass('active');
|
||||
},
|
||||
|
||||
touchend: function (e) {
|
||||
e.preventDefault();
|
||||
this.select();
|
||||
this.$element.focus();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* TYPEAHEAD PLUGIN DEFINITION
|
||||
* =========================== */
|
||||
|
||||
var old = $.fn.typeahead;
|
||||
|
||||
$.fn.typeahead = function (option) {
|
||||
var arg = arguments;
|
||||
if (typeof option == 'string' && option == 'getActive') {
|
||||
return this.data('active');
|
||||
}
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('typeahead');
|
||||
var options = typeof option == 'object' && option;
|
||||
if (!data) {
|
||||
$this.data('typeahead', (data = new Typeahead(this, options)));
|
||||
}
|
||||
if (typeof option == 'string' && data[option]) {
|
||||
if (arg.length > 1) {
|
||||
data[option].apply(data, Array.prototype.slice.call(arg, 1));
|
||||
} else {
|
||||
data[option]();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Typeahead.defaults = {
|
||||
source: [],
|
||||
items: 8,
|
||||
minLength: 1,
|
||||
scrollHeight: 0,
|
||||
autoSelect: true,
|
||||
afterSelect: $.noop,
|
||||
afterEmptySelect: $.noop,
|
||||
addItem: false,
|
||||
followLinkOnSelect: false,
|
||||
delay: 0,
|
||||
separator: 'category',
|
||||
changeInputOnSelect: true,
|
||||
changeInputOnMove: true,
|
||||
openLinkInNewTab: false,
|
||||
selectOnBlur: true,
|
||||
showCategoryHeader: true,
|
||||
theme: "bootstrap3",
|
||||
themes: {
|
||||
bootstrap3: {
|
||||
menu: '<ul class="typeahead dropdown-menu" role="listbox"></ul>',
|
||||
item: '<li><a class="dropdown-item" href="#" role="option"></a></li>',
|
||||
itemContentSelector: "a",
|
||||
headerHtml: '<li class="dropdown-header"></li>',
|
||||
headerDivider: '<li class="divider" role="separator"></li>'
|
||||
},
|
||||
bootstrap4: {
|
||||
menu: '<div class="typeahead dropdown-menu" role="listbox"></div>',
|
||||
item: '<button class="dropdown-item" role="option"></button>',
|
||||
itemContentSelector: '.dropdown-item',
|
||||
headerHtml: '<h6 class="dropdown-header"></h6>',
|
||||
headerDivider: '<div class="dropdown-divider"></div>'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.typeahead.Constructor = Typeahead;
|
||||
|
||||
/* TYPEAHEAD NO CONFLICT
|
||||
* =================== */
|
||||
|
||||
$.fn.typeahead.noConflict = function () {
|
||||
$.fn.typeahead = old;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/* TYPEAHEAD DATA-API
|
||||
* ================== */
|
||||
|
||||
$(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
|
||||
var $this = $(this);
|
||||
if ($this.data('typeahead')) {
|
||||
return;
|
||||
}
|
||||
$this.typeahead($this.data());
|
||||
});
|
||||
|
||||
}));
|
||||
+1
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@ $(document).ready(function(){
|
||||
//手机号码验证身份证正则合并:(^\d{15}$)|(^\d{17}([0-9]|X)$)
|
||||
jQuery.validator.addMethod("isPhone",function(value,element){
|
||||
var length = value.length;
|
||||
var phone=/^1[3|4|5|6|7|8][0-9]\d{8}$/;
|
||||
var phone=/^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
|
||||
return this.optional(element)||(length == 11 && phone.test(value));
|
||||
},"请填写正确的11位手机号");
|
||||
//电话号码验证
|
||||
@@ -37,6 +37,17 @@ $(document).ready(function(){
|
||||
var birth = /^(19|20)\d{2}-(1[0-2]|0?[1-9])-(0?[1-9]|[1-2][0-9]|3[0-1])$/;
|
||||
return this.optional(element) || (birth).test(value);
|
||||
},"出生日期格式示例2000-01-01");
|
||||
//校验IP地址
|
||||
jQuery.validator.addMethod("isIp",function(value,element){
|
||||
var ip = /^(?:(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:1[0-9][0-9]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:2[0-4][0-9])|(?:25[0-5])|(?:1[0-9][0-9])|(?:[1-9][0-9])|(?:[0-9]))$/;
|
||||
return this.optional(element) || (ip).test(value);
|
||||
},"IP地址格式示例127.0.0.1");
|
||||
jQuery.validator.addMethod("notEqual", function(value, element, param) {
|
||||
return value != param;
|
||||
}, $.validator.format("输入值不允许为{0}"));
|
||||
jQuery.validator.addMethod("gt", function(value, element, param) {
|
||||
return value > param;
|
||||
}, $.validator.format("输入值必须大于{0}"));
|
||||
//校验新旧密码是否相同
|
||||
jQuery.validator.addMethod("isdiff",function(){
|
||||
var p1=$("#pwdOld").val();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -9,6 +9,12 @@
|
||||
background-color: #3c8dbc
|
||||
}
|
||||
|
||||
.skin-blue .navbar-default .nav>li.selected>a,
|
||||
.skin-blue .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #1890ff;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.skin-blue .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
@@ -93,7 +99,7 @@
|
||||
border-left: 3px solid #3c8dbc;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active:last-child {
|
||||
.skin-blue .nav>li.active>ul li.active {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
@@ -170,7 +176,7 @@
|
||||
}
|
||||
|
||||
.skin-blue .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skin-blue.layout-top-nav>.logo {
|
||||
@@ -188,8 +194,14 @@
|
||||
background-color: #00a65a;
|
||||
}
|
||||
|
||||
.skin-green .navbar-default .nav>li.selected>a,
|
||||
.skin-green .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #52c41a;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.skin-green .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skin-green .navbar .nav>li>a {
|
||||
@@ -276,7 +288,7 @@
|
||||
border-left: 3px solid #00a65a;
|
||||
}
|
||||
|
||||
.skin-green .nav>li.active:last-child {
|
||||
.skin-green .nav>li.active>ul li.active {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
@@ -347,6 +359,12 @@
|
||||
background-color: #dd4b39
|
||||
}
|
||||
|
||||
.skin-red .navbar-default .nav>li.selected>a,
|
||||
.skin-red .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #f5222d;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.skin-red .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
@@ -431,12 +449,12 @@
|
||||
background: #293846;
|
||||
}
|
||||
|
||||
.skin-red .nav>li.active:last-child {
|
||||
.skin-red .nav>li.active>ul li.active {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-red .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skin-red .nav>li>.treeview-menu {
|
||||
@@ -506,6 +524,12 @@
|
||||
background-color: #f39c12
|
||||
}
|
||||
|
||||
.skin-yellow .navbar-default .nav>li.selected>a,
|
||||
.skin-yellow .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #faad14;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
@@ -590,13 +614,12 @@
|
||||
border-left: 3px solid #f39c12;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active:last-child {
|
||||
.skin-yellow .nav>li.active>ul li.active {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-yellow .content-tabs {
|
||||
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li>.treeview-menu {
|
||||
@@ -666,6 +689,12 @@
|
||||
background-color: #605ca8
|
||||
}
|
||||
|
||||
.skin-purple .navbar-default .nav>li.selected>a,
|
||||
.skin-purple .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #722ed1;
|
||||
color: rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.skin-purple .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
@@ -750,13 +779,12 @@
|
||||
border-left: 3px solid #605ca8;
|
||||
}
|
||||
|
||||
.skin-purple .nav>li.active:last-child {
|
||||
.skin-purple .nav>li.active>ul li.active {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-purple .content-tabs {
|
||||
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.skin-purple .nav>li>.treeview-menu {
|
||||
@@ -820,3 +848,117 @@
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* 侧边栏主题 若依管理系统
|
||||
* NAME - .theme-dark/theme-light
|
||||
*
|
||||
*/
|
||||
/** 深色主题 .theme-dark **/
|
||||
.theme-dark .user-panel>.info>p, .theme-dark .user-panel>.info, .theme-dark .user-panel>.info>a{
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.theme-dark .nav>li.active {
|
||||
background: #293846;
|
||||
}
|
||||
|
||||
.theme-dark .navbar-static-side {
|
||||
background-color: #2f4050;
|
||||
}
|
||||
|
||||
.theme-dark .user-panel {
|
||||
background-color: #2f4050;
|
||||
}
|
||||
|
||||
.theme-dark .navbar-default .nav>li>a:hover,
|
||||
.theme-dark .navbar-default .nav>li>a:focus {
|
||||
background: #293846;
|
||||
}
|
||||
|
||||
/** 浅色主题 theme-light **/
|
||||
.theme-light .user-panel>.info>p, .theme-light .user-panel>.info, .theme-light .user-panel>.info>a{
|
||||
color: #555
|
||||
}
|
||||
|
||||
.theme-light .nav>li.active{
|
||||
background: #f9fafc;
|
||||
}
|
||||
|
||||
.theme-light .navbar-static-side {
|
||||
background-color: #f9fafc;
|
||||
box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
|
||||
}
|
||||
|
||||
.theme-light .user-panel {
|
||||
background-color: #f9fafc;
|
||||
}
|
||||
|
||||
.theme-light .navbar-default .nav>li>a {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.theme-light.skin-blue .navbar-default .nav>li.active>a {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.theme-light.skin-blue .navbar-default .nav>li.selected>a,
|
||||
.theme-light.skin-blue .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: rgb(240, 245, 255);
|
||||
color: rgb(47, 84, 235);
|
||||
}
|
||||
|
||||
.theme-light.skin-green .navbar-default .nav>li.active>a {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.theme-light.skin-green .navbar-default .nav>li.selected>a,
|
||||
.theme-light.skin-green .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: rgb(246, 255, 237);
|
||||
color: rgb(82, 196, 26);
|
||||
}
|
||||
|
||||
.theme-light.skin-purple .navbar-default .nav>li.active>a {
|
||||
color: rgb(114, 46, 209);
|
||||
}
|
||||
|
||||
.theme-light.skin-purple .navbar-default .nav>li.selected>a,
|
||||
.theme-light.skin-purple .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #f9f0ff;
|
||||
color: #722ed1;
|
||||
}
|
||||
|
||||
.theme-light.skin-red .navbar-default .nav>li.active>a {
|
||||
color: rgb(245, 34, 45);
|
||||
}
|
||||
|
||||
.theme-light.skin-red .navbar-default .nav>li.selected>a,
|
||||
.theme-light.skin-red .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: rgb(255, 241, 240);
|
||||
color: rgb(245, 34, 45);
|
||||
}
|
||||
|
||||
.theme-light.skin-yellow .navbar-default .nav>li.active>a {
|
||||
color: rgb(250, 173, 20);
|
||||
}
|
||||
|
||||
.theme-light.skin-yellow .navbar-default .nav>li.selected>a,
|
||||
.theme-light.skin-yellow .navbar-default .nav>li.selected>a:focus {
|
||||
background-color: #fffbe6;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.theme-light .navbar-default .nav>li>a:hover,
|
||||
.theme-light .navbar-default .nav>li>a:focus {
|
||||
background-color: rgb(240, 245, 255);
|
||||
}
|
||||
|
||||
.fixed-sidebar.theme-light.mini-navbar .nav li:hover>a> span.nav-label {
|
||||
background-color: #f9fafc;
|
||||
}
|
||||
|
||||
.fixed-sidebar.theme-light.mini-navbar .nav li:hover>.nav-second-level {
|
||||
background-color: #f9fafc;
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ body.canvas-menu.mini-navbar #page-wrapper, body.canvas-menu.mini-navbar .footer
|
||||
|
||||
body.fixed-sidebar .navbar-static-side, body.canvas-menu .navbar-static-side {
|
||||
position: fixed;
|
||||
width: 220px;
|
||||
width: 200px;
|
||||
z-index: 2001;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -3166,7 +3166,7 @@ video {
|
||||
#page-wrapper {
|
||||
padding: 0 15px;
|
||||
position: inherit;
|
||||
margin: 0 0 0 220px;
|
||||
margin: 0 0 0 200px;
|
||||
}
|
||||
|
||||
.title-action {
|
||||
@@ -3247,15 +3247,15 @@ body.body-small .footer.fixed {
|
||||
/*CONTENTTABS*/
|
||||
.content-tabs {
|
||||
position: relative;
|
||||
height: 42px;
|
||||
height: 39px;
|
||||
background: #fafafa;
|
||||
line-height: 40px;
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
.content-tabs .roll-nav, .page-tabs-list {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 30px;
|
||||
height: 38px;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
z-index: 2;
|
||||
@@ -3285,9 +3285,9 @@ body.body-small .footer.fixed {
|
||||
}
|
||||
|
||||
nav.page-tabs {
|
||||
margin-left: 40px;
|
||||
margin-left: 30px;
|
||||
width: 100000px;
|
||||
height: 40px;
|
||||
height: 38px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -3313,7 +3313,7 @@ nav.page-tabs .page-tabs-content {
|
||||
}
|
||||
|
||||
.roll-right.tabRight {
|
||||
right: 140px;
|
||||
right: 60px;
|
||||
}
|
||||
|
||||
.roll-right.btn-group {
|
||||
@@ -3328,7 +3328,7 @@ nav.page-tabs .page-tabs-content {
|
||||
|
||||
.roll-right.tabReload {
|
||||
background: #fff;
|
||||
height: 40px;
|
||||
height: 38px;
|
||||
width: 60px;
|
||||
outline: none;
|
||||
}
|
||||
@@ -3338,7 +3338,7 @@ nav.page-tabs .page-tabs-content {
|
||||
}
|
||||
|
||||
#content-main {
|
||||
height: calc(100% - 140px);
|
||||
height: calc(100% - 127px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -6858,42 +6858,6 @@ body.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed
|
||||
transition: all .3s ease-out 0s;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #999;
|
||||
}
|
||||
/*GO HOME*/
|
||||
.gohome {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.gohome a {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
display: block;
|
||||
background: #2f4050;
|
||||
padding: 9px 8px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.gohome a:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio : 2) {
|
||||
#content-main {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
@@ -6987,7 +6951,7 @@ body.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed
|
||||
font-size: 20px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
width: 220px;
|
||||
width: 200px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
padding: 0 15px;
|
||||
font-weight: 300;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 142 KiB |
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
(function(k){function t(a){a.debug&&(g("callbackIfComplete()"),g("totalFiles: "+a.totalFiles),g("filesLoaded: "+a.filesLoaded));a.async&&a.filesLoaded===a.totalFiles&&a.callback&&a.callback()}function n(a,d){d.debug&&g("loadAndParseFiles");null!==a&&0<a.length?u(a[0],d,function(){a.shift();n(a,d)}):t(d)}function u(a,d,b){d.debug&&(g("loadAndParseFile('"+a+"')"),g("totalFiles: "+d.totalFiles),g("filesLoaded: "+d.filesLoaded));null!==a&&"undefined"!==typeof a&&k.ajax({url:a,async:d.async,cache:d.cache,
|
||||
dataType:"text",success:function(h,c){d.debug&&(g("Succeeded in downloading "+a+"."),g(h));v(h,d);b()},error:function(h,c,e){d.debug&&g("Failed to download or parse "+a+". errorThrown: "+e);404===h.status&&--d.totalFiles;b()}})}function v(a,d){var b="",h=a.split(/\n/),c=/(\{\d+})/g,e=/\{(\d+)}/g,g=/(\\u.{4})/ig;h.forEach(function(a,w){a=a.trim();if(0<a.length&&"#"!=a.match("^#")){var l=a.split("=");if(0<l.length){for(var m=decodeURI(l[0]).trim(),f=1==l.length?"":l[1];"\\"===f.match(/\\$/);)f=f.substring(0,
|
||||
f.length-1),f+=h[++w].trimRight();for(var p=2;p<l.length;p++)f+="="+l[p];f=f.trim();if("map"==d.mode||"both"==d.mode)(l=f.match(g))&&l.forEach(function(a){f=f.replace(a,x(a))}),k.i18n.map[m]=f;if("vars"==d.mode||"both"==d.mode)if(f=f.replace(/"/g,'\\"'),y(m),c.test(f)){var n=!0,q="",r=[];f.split(c).forEach(function(a){!c.test(a)||0!==r.length&&-1!=r.indexOf(a)||(n||(q+=","),q+=a.replace(e,"v$1"),r.push(a),n=!1)});b+=m+"=function("+q+"){";m='"'+f.replace(e,'"+v$1+"')+'"';b+="return "+m+";};"}else b+=
|
||||
m+'="'+f+'";'}}});eval(b);d.filesLoaded+=1}function y(a){if(/\./.test(a)){var d="";a.split(/\./).forEach(function(a,h){0<h&&(d+=".");d+=a;eval("typeof "+d+' == "undefined"')&&eval(d+"={};")})}}function x(a){var d=[];a=parseInt(a.substr(2),16);0<=a&&a<Math.pow(2,16)&&d.push(a);return d.reduce(function(a,d){return a+String.fromCharCode(d)},"")}k.i18n={};k.i18n.map={};var g=function(a){window.console&&console.log("i18n::"+a)};k.i18n.properties=function(a){a=k.extend({name:"Messages",language:"",path:"",
|
||||
mode:"vars",cache:!1,debug:!1,encoding:"UTF-8",async:!1,callback:null},a);a.path.match(/\/$/)||(a.path+="/");a.language=this.normaliseLanguageCode(a.language);var d=a.name&&a.name.constructor===Array?a.name:[a.name];a.totalFiles=2*d.length+(5<=a.language.length?d.length:0);a.debug&&g("totalFiles: "+a.totalFiles);a.filesLoaded=0;d.forEach(function(b){var d=a.path+b+".properties";var c=a.language.substring(0,2);c=a.path+b+"_"+c+".properties";if(5<=a.language.length){var e=a.language.substring(0,5);
|
||||
b=a.path+b+"_"+e+".properties";d=[d,c,b]}else d=[d,c];n(d,a)});a.callback&&!a.async&&a.callback()};k.i18n.prop=function(a){var d,b=k.i18n.map[a];if(null===b)return"["+a+"]";var h;2==arguments.length&&k.isArray(arguments[1])&&(h=arguments[1]);var c;if("string"==typeof b){for(c=0;-1!=(c=b.indexOf("\\",c));)b="t"==b.charAt(c+1)?b.substring(0,c)+"\t"+b.substring(c++ +2):"r"==b.charAt(c+1)?b.substring(0,c)+"\r"+b.substring(c++ +2):"n"==b.charAt(c+1)?b.substring(0,c)+"\n"+b.substring(c++ +2):"f"==b.charAt(c+
|
||||
1)?b.substring(0,c)+"\f"+b.substring(c++ +2):"\\"==b.charAt(c+1)?b.substring(0,c)+"\\"+b.substring(c++ +2):b.substring(0,c)+b.substring(c+1);var e=[];for(c=0;c<b.length;)if("'"==b.charAt(c))if(c==b.length-1)b=b.substring(0,c);else if("'"==b.charAt(c+1))b=b.substring(0,c)+b.substring(++c);else{for(d=c+2;-1!=(d=b.indexOf("'",d));)if(d==b.length-1||"'"!=b.charAt(d+1)){b=b.substring(0,c)+b.substring(c+1,d)+b.substring(d+1);c=d-1;break}else b=b.substring(0,d)+b.substring(++d);-1==d&&(b=b.substring(0,c)+
|
||||
b.substring(c+1))}else if("{"==b.charAt(c))if(d=b.indexOf("}",c+1),-1==d)c++;else{var g=parseInt(b.substring(c+1,d));!isNaN(g)&&0<=g?(c=b.substring(0,c),""!==c&&e.push(c),e.push(g),c=0,b=b.substring(d+1)):c=d+1}else c++;""!==b&&e.push(b);b=e;k.i18n.map[a]=e}if(0===b.length)return"";if(1==b.length&&"string"==typeof b[0])return b[0];e="";c=0;for(d=b.length;c<d;c++)e="string"==typeof b[c]?e+b[c]:h&&b[c]<h.length?e+h[b[c]]:!h&&b[c]+1<arguments.length?e+arguments[b[c]+1]:e+("{"+b[c]+"}");return e};k.i18n.normaliseLanguageCode=
|
||||
function(a){if(!a||2>a.length)a=navigator.languages&&0<navigator.languages.length?navigator.languages[0]:navigator.language||navigator.userLanguage||"en";a=a.toLowerCase();a=a.replace(/-/,"_");3<a.length&&(a=a.substring(0,3)+a.substring(3).toUpperCase());return a}})(jQuery);
|
||||
@@ -0,0 +1,492 @@
|
||||
/*!
|
||||
* jQuery Templates Plugin 1.0.0pre
|
||||
* http://github.com/jquery/jquery-tmpl
|
||||
* Requires jQuery 1.4.2
|
||||
*
|
||||
* Copyright 2011, Software Freedom Conservancy, Inc.
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
(function( factory ) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Loading from AMD script loader. Register as an anonymous module.
|
||||
define( ['jquery'], factory );
|
||||
} else {
|
||||
// Browser using plain <script> tag
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( jQuery ){
|
||||
var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
|
||||
newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
|
||||
|
||||
function newTmplItem( options, parentItem, fn, data ) {
|
||||
// Returns a template item data structure for a new rendered instance of a template (a 'template item').
|
||||
// The content field is a hierarchical array of strings and nested items (to be
|
||||
// removed and replaced by nodes field of dom elements, once inserted in DOM).
|
||||
var newItem = {
|
||||
data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
|
||||
_wrap: parentItem ? parentItem._wrap : null,
|
||||
tmpl: null,
|
||||
parent: parentItem || null,
|
||||
nodes: [],
|
||||
calls: tiCalls,
|
||||
nest: tiNest,
|
||||
wrap: tiWrap,
|
||||
html: tiHtml,
|
||||
update: tiUpdate
|
||||
};
|
||||
if ( options ) {
|
||||
jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
|
||||
}
|
||||
if ( fn ) {
|
||||
// Build the hierarchical content to be used during insertion into DOM
|
||||
newItem.tmpl = fn;
|
||||
newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
|
||||
newItem.key = ++itemKey;
|
||||
// Keep track of new template item, until it is stored as jQuery Data on DOM element
|
||||
(stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
|
||||
}
|
||||
return newItem;
|
||||
}
|
||||
|
||||
// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
|
||||
jQuery.each({
|
||||
appendTo: "append",
|
||||
prependTo: "prepend",
|
||||
insertBefore: "before",
|
||||
insertAfter: "after",
|
||||
replaceAll: "replaceWith"
|
||||
}, function( name, original ) {
|
||||
jQuery.fn[ name ] = function( selector ) {
|
||||
var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
|
||||
parent = this.length === 1 && this[0].parentNode;
|
||||
|
||||
appendToTmplItems = newTmplItems || {};
|
||||
if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
|
||||
insert[ original ]( this[0] );
|
||||
ret = this;
|
||||
} else {
|
||||
for ( i = 0, l = insert.length; i < l; i++ ) {
|
||||
cloneIndex = i;
|
||||
elems = (i > 0 ? this.clone(true) : this).get();
|
||||
jQuery( insert[i] )[ original ]( elems );
|
||||
ret = ret.concat( elems );
|
||||
}
|
||||
cloneIndex = 0;
|
||||
ret = this.pushStack( ret, name, insert.selector );
|
||||
}
|
||||
tmplItems = appendToTmplItems;
|
||||
appendToTmplItems = null;
|
||||
jQuery.tmpl.complete( tmplItems );
|
||||
return ret;
|
||||
};
|
||||
});
|
||||
|
||||
jQuery.fn.extend({
|
||||
// Use first wrapped element as template markup.
|
||||
// Return wrapped set of template items, obtained by rendering template against data.
|
||||
tmpl: function( data, options, parentItem ) {
|
||||
return jQuery.tmpl( this[0], data, options, parentItem );
|
||||
},
|
||||
|
||||
// Find which rendered template item the first wrapped DOM element belongs to
|
||||
tmplItem: function() {
|
||||
return jQuery.tmplItem( this[0] );
|
||||
},
|
||||
|
||||
// Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
|
||||
template: function( name ) {
|
||||
return jQuery.template( name, this[0] );
|
||||
},
|
||||
|
||||
domManip: function( args, table, callback, options ) {
|
||||
if ( args[0] && jQuery.isArray( args[0] )) {
|
||||
var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
|
||||
while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
|
||||
if ( tmplItem && cloneIndex ) {
|
||||
dmArgs[2] = function( fragClone ) {
|
||||
// Handler called by oldManip when rendered template has been inserted into DOM.
|
||||
jQuery.tmpl.afterManip( this, fragClone, callback );
|
||||
};
|
||||
}
|
||||
oldManip.apply( this, dmArgs );
|
||||
} else {
|
||||
oldManip.apply( this, arguments );
|
||||
}
|
||||
cloneIndex = 0;
|
||||
if ( !appendToTmplItems ) {
|
||||
jQuery.tmpl.complete( newTmplItems );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
// Return wrapped set of template items, obtained by rendering template against data.
|
||||
tmpl: function( tmpl, data, options, parentItem ) {
|
||||
var ret, topLevel = !parentItem;
|
||||
if ( topLevel ) {
|
||||
// This is a top-level tmpl call (not from a nested template using {{tmpl}})
|
||||
parentItem = topTmplItem;
|
||||
tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
|
||||
wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
|
||||
} else if ( !tmpl ) {
|
||||
// The template item is already associated with DOM - this is a refresh.
|
||||
// Re-evaluate rendered template for the parentItem
|
||||
tmpl = parentItem.tmpl;
|
||||
newTmplItems[parentItem.key] = parentItem;
|
||||
parentItem.nodes = [];
|
||||
if ( parentItem.wrapped ) {
|
||||
updateWrapped( parentItem, parentItem.wrapped );
|
||||
}
|
||||
// Rebuild, without creating a new template item
|
||||
return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
|
||||
}
|
||||
if ( !tmpl ) {
|
||||
return []; // Could throw...
|
||||
}
|
||||
if ( typeof data === "function" ) {
|
||||
data = data.call( parentItem || {} );
|
||||
}
|
||||
if ( options && options.wrapped ) {
|
||||
updateWrapped( options, options.wrapped );
|
||||
}
|
||||
ret = jQuery.isArray( data ) ?
|
||||
jQuery.map( data, function( dataItem ) {
|
||||
return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
|
||||
}) :
|
||||
[ newTmplItem( options, parentItem, tmpl, data ) ];
|
||||
return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
|
||||
},
|
||||
|
||||
// Return rendered template item for an element.
|
||||
tmplItem: function( elem ) {
|
||||
var tmplItem;
|
||||
if ( elem instanceof jQuery ) {
|
||||
elem = elem[0];
|
||||
}
|
||||
while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
|
||||
return tmplItem || topTmplItem;
|
||||
},
|
||||
|
||||
// Set:
|
||||
// Use $.template( name, tmpl ) to cache a named template,
|
||||
// where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
|
||||
// Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
|
||||
|
||||
// Get:
|
||||
// Use $.template( name ) to access a cached template.
|
||||
// Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
|
||||
// will return the compiled template, without adding a name reference.
|
||||
// If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
|
||||
// to $.template( null, templateString )
|
||||
template: function( name, tmpl ) {
|
||||
if (tmpl) {
|
||||
// Compile template and associate with name
|
||||
if ( typeof tmpl === "string" ) {
|
||||
// This is an HTML string being passed directly in.
|
||||
tmpl = buildTmplFn( tmpl );
|
||||
} else if ( tmpl instanceof jQuery ) {
|
||||
tmpl = tmpl[0] || {};
|
||||
}
|
||||
if ( tmpl.nodeType ) {
|
||||
// If this is a template block, use cached copy, or generate tmpl function and cache.
|
||||
tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
|
||||
// Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
|
||||
// This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
|
||||
// To correct this, include space in tag: foo="${ x }" -> foo="value of x"
|
||||
}
|
||||
return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
|
||||
}
|
||||
// Return named compiled template
|
||||
return name ? (typeof name !== "string" ? jQuery.template( null, name ):
|
||||
(jQuery.template[name] ||
|
||||
// If not in map, and not containing at least on HTML tag, treat as a selector.
|
||||
// (If integrated with core, use quickExpr.exec)
|
||||
jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
|
||||
},
|
||||
|
||||
encode: function( text ) {
|
||||
// Do HTML encoding replacing < > & and ' and " by corresponding entities.
|
||||
return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'");
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend( jQuery.tmpl, {
|
||||
tag: {
|
||||
"tmpl": {
|
||||
_default: { $2: "null" },
|
||||
open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
|
||||
// tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
|
||||
// This means that {{tmpl foo}} treats foo as a template (which IS a function).
|
||||
// Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
|
||||
},
|
||||
"wrap": {
|
||||
_default: { $2: "null" },
|
||||
open: "$item.calls(__,$1,$2);__=[];",
|
||||
close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
|
||||
},
|
||||
"each": {
|
||||
_default: { $2: "$index, $value" },
|
||||
open: "if($notnull_1){$.each($1a,function($2){with(this){",
|
||||
close: "}});}"
|
||||
},
|
||||
"if": {
|
||||
open: "if(($notnull_1) && $1a){",
|
||||
close: "}"
|
||||
},
|
||||
"else": {
|
||||
_default: { $1: "true" },
|
||||
open: "}else if(($notnull_1) && $1a){"
|
||||
},
|
||||
"html": {
|
||||
// Unecoded expression evaluation.
|
||||
open: "if($notnull_1){__.push($1a);}"
|
||||
},
|
||||
"=": {
|
||||
// Encoded expression evaluation. Abbreviated form is ${}.
|
||||
_default: { $1: "$data" },
|
||||
open: "if($notnull_1){__.push($.encode($1a));}"
|
||||
},
|
||||
"!": {
|
||||
// Comment tag. Skipped by parser
|
||||
open: ""
|
||||
}
|
||||
},
|
||||
|
||||
// This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
|
||||
complete: function( items ) {
|
||||
newTmplItems = {};
|
||||
},
|
||||
|
||||
// Call this from code which overrides domManip, or equivalent
|
||||
// Manage cloning/storing template items etc.
|
||||
afterManip: function afterManip( elem, fragClone, callback ) {
|
||||
// Provides cloned fragment ready for fixup prior to and after insertion into DOM
|
||||
var content = fragClone.nodeType === 11 ?
|
||||
jQuery.makeArray(fragClone.childNodes) :
|
||||
fragClone.nodeType === 1 ? [fragClone] : [];
|
||||
|
||||
// Return fragment to original caller (e.g. append) for DOM insertion
|
||||
callback.call( elem, fragClone );
|
||||
|
||||
// Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
|
||||
storeTmplItems( content );
|
||||
cloneIndex++;
|
||||
}
|
||||
});
|
||||
|
||||
//========================== Private helper functions, used by code above ==========================
|
||||
|
||||
function build( tmplItem, nested, content ) {
|
||||
// Convert hierarchical content into flat string array
|
||||
// and finally return array of fragments ready for DOM insertion
|
||||
var frag, ret = content ? jQuery.map( content, function( item ) {
|
||||
return (typeof item === "string") ?
|
||||
// Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
|
||||
(tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
|
||||
// This is a child template item. Build nested template.
|
||||
build( item, tmplItem, item._ctnt );
|
||||
}) :
|
||||
// If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
|
||||
tmplItem;
|
||||
if ( nested ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// top-level template
|
||||
ret = ret.join("");
|
||||
|
||||
// Support templates which have initial or final text nodes, or consist only of text
|
||||
// Also support HTML entities within the HTML markup.
|
||||
ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
|
||||
frag = jQuery( middle ).get();
|
||||
|
||||
storeTmplItems( frag );
|
||||
if ( before ) {
|
||||
frag = unencode( before ).concat(frag);
|
||||
}
|
||||
if ( after ) {
|
||||
frag = frag.concat(unencode( after ));
|
||||
}
|
||||
});
|
||||
return frag ? frag : unencode( ret );
|
||||
}
|
||||
|
||||
function unencode( text ) {
|
||||
// Use createElement, since createTextNode will not render HTML entities correctly
|
||||
var el = document.createElement( "div" );
|
||||
el.innerHTML = text;
|
||||
return jQuery.makeArray(el.childNodes);
|
||||
}
|
||||
|
||||
// Generate a reusable function that will serve to render a template against data
|
||||
function buildTmplFn( markup ) {
|
||||
return new Function("jQuery","$item",
|
||||
// Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
|
||||
"var $=jQuery,call,__=[],$data=$item.data;" +
|
||||
|
||||
// Introduce the data as local variables using with(){}
|
||||
"with($data){__.push('" +
|
||||
|
||||
// Convert the template into pure JavaScript
|
||||
jQuery.trim(markup)
|
||||
.replace( /([\\'])/g, "\\$1" )
|
||||
.replace( /[\r\t\n]/g, " " )
|
||||
.replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
|
||||
.replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
|
||||
function( all, slash, type, fnargs, target, parens, args ) {
|
||||
var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
|
||||
if ( !tag ) {
|
||||
throw "Unknown template tag: " + type;
|
||||
}
|
||||
def = tag._default || [];
|
||||
if ( parens && !/\w$/.test(target)) {
|
||||
target += parens;
|
||||
parens = "";
|
||||
}
|
||||
if ( target ) {
|
||||
target = unescape( target );
|
||||
args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
|
||||
// Support for target being things like a.toLowerCase();
|
||||
// In that case don't call with template item as 'this' pointer. Just evaluate...
|
||||
expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
|
||||
exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
|
||||
} else {
|
||||
exprAutoFnDetect = expr = def.$1 || "null";
|
||||
}
|
||||
fnargs = unescape( fnargs );
|
||||
return "');" +
|
||||
tag[ slash ? "close" : "open" ]
|
||||
.split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
|
||||
.split( "$1a" ).join( exprAutoFnDetect )
|
||||
.split( "$1" ).join( expr )
|
||||
.split( "$2" ).join( fnargs || def.$2 || "" ) +
|
||||
"__.push('";
|
||||
}) +
|
||||
"');}return __;"
|
||||
);
|
||||
}
|
||||
function updateWrapped( options, wrapped ) {
|
||||
// Build the wrapped content.
|
||||
options._wrap = build( options, true,
|
||||
// Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
|
||||
jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
|
||||
).join("");
|
||||
}
|
||||
|
||||
function unescape( args ) {
|
||||
return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
|
||||
}
|
||||
function outerHtml( elem ) {
|
||||
var div = document.createElement("div");
|
||||
div.appendChild( elem.cloneNode(true) );
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
|
||||
function storeTmplItems( content ) {
|
||||
var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
|
||||
for ( i = 0, l = content.length; i < l; i++ ) {
|
||||
if ( (elem = content[i]).nodeType !== 1 ) {
|
||||
continue;
|
||||
}
|
||||
elems = elem.getElementsByTagName("*");
|
||||
for ( m = elems.length - 1; m >= 0; m-- ) {
|
||||
processItemKey( elems[m] );
|
||||
}
|
||||
processItemKey( elem );
|
||||
}
|
||||
function processItemKey( el ) {
|
||||
var pntKey, pntNode = el, pntItem, tmplItem, key;
|
||||
// Ensure that each rendered template inserted into the DOM has its own template item,
|
||||
if ( (key = el.getAttribute( tmplItmAtt ))) {
|
||||
while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
|
||||
if ( pntKey !== key ) {
|
||||
// The next ancestor with a _tmplitem expando is on a different key than this one.
|
||||
// So this is a top-level element within this template item
|
||||
// Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
|
||||
pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
|
||||
if ( !(tmplItem = newTmplItems[key]) ) {
|
||||
// The item is for wrapped content, and was copied from the temporary parent wrappedItem.
|
||||
tmplItem = wrappedItems[key];
|
||||
tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
|
||||
tmplItem.key = ++itemKey;
|
||||
newTmplItems[itemKey] = tmplItem;
|
||||
}
|
||||
if ( cloneIndex ) {
|
||||
cloneTmplItem( key );
|
||||
}
|
||||
}
|
||||
el.removeAttribute( tmplItmAtt );
|
||||
} else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
|
||||
// This was a rendered element, cloned during append or appendTo etc.
|
||||
// TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
|
||||
cloneTmplItem( tmplItem.key );
|
||||
newTmplItems[tmplItem.key] = tmplItem;
|
||||
pntNode = jQuery.data( el.parentNode, "tmplItem" );
|
||||
pntNode = pntNode ? pntNode.key : 0;
|
||||
}
|
||||
if ( tmplItem ) {
|
||||
pntItem = tmplItem;
|
||||
// Find the template item of the parent element.
|
||||
// (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
|
||||
while ( pntItem && pntItem.key != pntNode ) {
|
||||
// Add this element as a top-level node for this rendered template item, as well as for any
|
||||
// ancestor items between this item and the item of its parent element
|
||||
pntItem.nodes.push( el );
|
||||
pntItem = pntItem.parent;
|
||||
}
|
||||
// Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
|
||||
delete tmplItem._ctnt;
|
||||
delete tmplItem._wrap;
|
||||
// Store template item as jQuery data on the element
|
||||
jQuery.data( el, "tmplItem", tmplItem );
|
||||
}
|
||||
function cloneTmplItem( key ) {
|
||||
key = key + keySuffix;
|
||||
tmplItem = newClonedItems[key] =
|
||||
(newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- Helper functions for template item ----
|
||||
|
||||
function tiCalls( content, tmpl, data, options ) {
|
||||
if ( !content ) {
|
||||
return stack.pop();
|
||||
}
|
||||
stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
|
||||
}
|
||||
|
||||
function tiNest( tmpl, data, options ) {
|
||||
// nested template, using {{tmpl}} tag
|
||||
return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
|
||||
}
|
||||
|
||||
function tiWrap( call, wrapped ) {
|
||||
// nested template, using {{wrap}} tag
|
||||
var options = call.options || {};
|
||||
options.wrapped = wrapped;
|
||||
// Apply the template, which may incorporate wrapped content,
|
||||
return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
|
||||
}
|
||||
|
||||
function tiHtml( filter, textOnly ) {
|
||||
var wrapped = this._wrap;
|
||||
return jQuery.map(
|
||||
jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
|
||||
function(e) {
|
||||
return textOnly ?
|
||||
e.innerText || e.textContent :
|
||||
e.outerHTML || outerHtml(e);
|
||||
});
|
||||
}
|
||||
|
||||
function tiUpdate() {
|
||||
var coll = this.nodes;
|
||||
jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
|
||||
jQuery( coll ).remove();
|
||||
}
|
||||
}));
|
||||
+2
-9
@@ -2,14 +2,7 @@
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
*
|
||||
* Version: 1.3.0
|
||||
* Version: 1.3.8
|
||||
*
|
||||
*/
|
||||
(function(f){jQuery.fn.extend({slimScroll:function(h){var a=f.extend({width:"auto",height:"250px",size:"4px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:0.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},h);this.each(function(){function r(d){if(s){d=d||
|
||||
window.event;var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);f(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,f,h){k=!1;var e=d,g=b.outerHeight()-c.outerHeight();f&&(e=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),e=Math.min(Math.max(e,0),g),e=0<d?Math.ceil(e):Math.floor(e),c.css({top:e+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());
|
||||
e=l*(b[0].scrollHeight-b.outerHeight());h&&(e=d,d=e/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),g),c.css({top:d+"px"}));b.scrollTop(e);b.trigger("slimscrolling",~~e);v();p()}function C(){window.addEventListener?(this.addEventListener("DOMMouseScroll",r,!1),this.addEventListener("mousewheel",r,!1),this.addEventListener("MozMousePixelScroll",r,!1)):document.attachEvent("onmousewheel",r)}function w(){u=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),D);c.css({height:u+"px"});
|
||||
var a=u==b.outerHeight()?"none":"block";c.css({display:a})}function v(){w();clearTimeout(A);l==~~l?(k=a.allowPageScroll,B!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;B=l;u>=b.outerHeight()?k=!0:(c.stop(!0,!0).fadeIn("fast"),a.railVisible&&g.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(A=setTimeout(function(){a.disableFadeOut&&s||(x||y)||(c.fadeOut("slow"),g.fadeOut("slow"))},1E3))}var s,x,y,A,z,u,l,B,D=30,k=!1,b=f(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),
|
||||
c=b.parent().find("."+a.barClass),g=b.parent().find("."+a.railClass);w();if(f.isPlainObject(h)){if("height"in h&&"auto"==h.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",q);b.css("height",q)}if("scrollTo"in h)n=parseInt(a.scrollTo);else if("scrollBy"in h)n+=parseInt(a.scrollBy);else if("destroy"in h){c.remove();g.remove();b.unwrap();return}m(n,!1,!0)}}else{a.height="auto"==a.height?b.parent().height():a.height;n=f("<div></div>").addClass(a.wrapperClass).css({position:"relative",width:a.width,height:a.height});b.css({width:a.width,height:a.height});var g=f("<div></div>").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=f("<div></div>").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?
|
||||
"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?{right:a.distance}:{left:a.distance};g.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(g);a.railDraggable&&c.bind("mousedown",function(a){var b=f(document);y=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});
|
||||
b.bind("mouseup.slimscroll",function(a){y=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});g.hover(function(){v()},function(){p()});c.hover(function(){x=!0},function(){x=!1});b.hover(function(){s=!0;v();p()},function(){s=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(z=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&
|
||||
(m((z-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),z=b.originalEvent.touches[0].pageY)});w();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),m(0,!0)):"top"!==a.start&&(m(f(a.start).position().top,null,!0),a.alwaysVisible||c.hide());C()}});return this}});jQuery.fn.extend({slimscroll:jQuery.fn.slimScroll})})(jQuery);
|
||||
(function(a){a.fn.extend({slimScroll:function(b){var c={width:"auto",height:"250px",size:"2px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:false,disableFadeOut:false,railVisible:false,railColor:"#333",railOpacity:0.2,railDraggable:true,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:false,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"};var d=a.extend(c,b);this.each(function(){var z,s,l,q,C,u,p,k,m="<div></div>",w=30,r=false;var D=a(this);if(D.parent().hasClass(d.wrapperClass)){var i=D.scrollTop();x=D.siblings("."+d.barClass);e=D.siblings("."+d.railClass);E();if(a.isPlainObject(b)){if("height" in b&&b.height=="auto"){D.parent().css("height","auto");D.css("height","auto");var o=D.parent().parent().height();D.parent().css("height",o);D.css("height",o)}else{if("height" in b){var v=b.height;D.parent().css("height",v);D.css("height",v)}}if("scrollTo" in b){i=parseInt(d.scrollTo)}else{if("scrollBy" in b){i+=parseInt(d.scrollBy)}else{if("destroy" in b){x.remove();e.remove();D.unwrap();return}}}y(i,false,true)}return}else{if(a.isPlainObject(b)){if("destroy" in b){return}}}d.height=(d.height=="auto")?D.parent().height():d.height;var j=a(m).addClass(d.wrapperClass).css({position:"relative",width:d.width,height:d.height});D.css({width:d.width,height:d.height});var e=a(m).addClass(d.railClass).css({width:d.size,height:"100%",position:"absolute",top:0,display:(d.alwaysVisible&&d.railVisible)?"block":"none","border-radius":d.railBorderRadius,background:d.railColor,opacity:d.railOpacity,zIndex:90});var x=a(m).addClass(d.barClass).css({background:d.color,width:d.size,position:"absolute",top:0,opacity:d.opacity,display:d.alwaysVisible?"block":"none","border-radius":d.borderRadius,BorderRadius:d.borderRadius,MozBorderRadius:d.borderRadius,WebkitBorderRadius:d.borderRadius,zIndex:99});var f=(d.position=="right")?{right:d.distance}:{left:d.distance};e.css(f);x.css(f);D.wrap(j);D.parent().append(x);D.parent().append(e);if(d.railDraggable){x.bind("mousedown",function(h){var F=a(document);l=true;t=parseFloat(x.css("top"));pageY=h.pageY;F.bind("mousemove.slimscroll",function(G){currTop=t+G.pageY-pageY;x.css("top",currTop);y(0,x.position().top,false)});F.bind("mouseup.slimscroll",function(G){l=false;n();F.unbind(".slimscroll")});return false}).bind("selectstart.slimscroll",function(h){h.stopPropagation();h.preventDefault();return false})}e.hover(function(){g()},function(){n()});x.hover(function(){s=true},function(){s=false});D.hover(function(){z=true;g();n()},function(){z=false;n()});D.bind("touchstart",function(F,h){if(F.originalEvent.touches.length){C=F.originalEvent.touches[0].pageY}});D.bind("touchmove",function(F){if(!r){F.originalEvent.preventDefault()}if(F.originalEvent.touches.length){var h=(C-F.originalEvent.touches[0].pageY)/d.touchScrollStep;y(h,true);C=F.originalEvent.touches[0].pageY}});E();if(d.start==="bottom"){x.css({top:D.outerHeight()-x.outerHeight()});y(0,true)}else{if(d.start!=="top"){y(a(d.start).position().top,null,true);if(!d.alwaysVisible){x.hide()}}}A(this);function B(F){if(!z){return}var F=F||window.event;var G=0;if(F.wheelDelta){G=-F.wheelDelta/120}if(F.detail){G=F.detail/3}var h=F.target||F.srcTarget||F.srcElement;if(a(h).closest("."+d.wrapperClass).is(D.parent())){y(G,true)}if(F.preventDefault&&!r){F.preventDefault()}if(!r){F.returnValue=false}}function y(J,G,h){r=false;var I=J;var H=D.outerHeight()-x.outerHeight();if(G){I=parseInt(x.css("top"))+J*parseInt(d.wheelStep)/100*x.outerHeight();I=Math.min(Math.max(I,0),H);I=(J>0)?Math.ceil(I):Math.floor(I);x.css({top:I+"px"})}p=parseInt(x.css("top"))/(D.outerHeight()-x.outerHeight());I=p*(D[0].scrollHeight-D.outerHeight());if(h){I=J;var F=I/D[0].scrollHeight*D.outerHeight();F=Math.min(Math.max(F,0),H);x.css({top:F+"px"})}D.scrollTop(I);D.trigger("slimscrolling",~~I);g();n()}function A(h){if(window.addEventListener){h.addEventListener("DOMMouseScroll",B,false);h.addEventListener("mousewheel",B,false)}else{document.attachEvent("onmousewheel",B)}}function E(){u=Math.max((D.outerHeight()/D[0].scrollHeight)*D.outerHeight(),w);x.css({height:u+"px"});var h=u==D.outerHeight()?"none":"block";x.css({display:h})}function g(){E();clearTimeout(q);if(p==~~p){r=d.allowPageScroll;if(k!=p){var h=(~~p==0)?"top":"bottom";D.trigger("slimscroll",h)}}else{r=false}k=p;if(u>=D.outerHeight()){r=true;return}x.stop(true,true).fadeIn("fast");if(d.railVisible){e.stop(true,true).fadeIn("fast")}}function n(){if(!d.alwaysVisible){q=setTimeout(function(){if(!(d.disableFadeOut&&z)&&!s&&!l){x.fadeOut("slow");e.fadeOut("slow")}},1000)}}});return this}});a.fn.extend({slimscroll:a.fn.slimScroll})})(jQuery);
|
||||
|
||||
@@ -46,10 +46,28 @@
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
.m20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.m50 {
|
||||
margin-left: 50px;
|
||||
}
|
||||
.img-xs {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.img-sm {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.img-md {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.section-content {
|
||||
min-height: 250px;
|
||||
margin-right: auto;
|
||||
@@ -128,6 +146,12 @@
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.nav-tabs-custom>.nav-tabs>li.header {
|
||||
padding-left: 5px;
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.nav-tabs-custom>.nav-tabs>li.disabled>a {
|
||||
color: #777
|
||||
}
|
||||
@@ -270,6 +294,12 @@
|
||||
margin: 5px 0 5px -25px
|
||||
}
|
||||
|
||||
@media ( min-width : 768px) {
|
||||
.section-content .about {
|
||||
padding-left: 0px
|
||||
}
|
||||
}
|
||||
|
||||
/** select2 样式修改 **/
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #1AB394;
|
||||
@@ -305,6 +335,11 @@ label.error {
|
||||
right: 42px
|
||||
}
|
||||
|
||||
.input-group.date label.error {
|
||||
z-index:99;
|
||||
right: 3px
|
||||
}
|
||||
|
||||
.Validform_error,input.error,select.error {
|
||||
background-color: #fbe2e2;
|
||||
border-color: #c66161;
|
||||
@@ -398,6 +433,79 @@ label.error {
|
||||
background-position: -180px 0
|
||||
}
|
||||
|
||||
/* 切换开关 */
|
||||
.toggle-switch {
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
margin-bottom: 0;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.toggle-switch input {
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
.toggle-switch span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #ebebeb;
|
||||
border: 2px solid #ebebeb;
|
||||
cursor: pointer;
|
||||
-webkit-transition: all .1s ease;
|
||||
-o-transition: all .1s ease;
|
||||
transition: all .1s ease
|
||||
}
|
||||
.toggle-switch span:after {
|
||||
content: '';
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
top: -7px;
|
||||
color: #aaa;
|
||||
-webkit-transition: all .1s ease;
|
||||
-o-transition: all .1s ease;
|
||||
transition: all .1s ease;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
background-color: #fff;
|
||||
-webkit-box-shadow: rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px;
|
||||
box-shadow: rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px
|
||||
}
|
||||
.toggle-switch input:checked~span:after {
|
||||
left: -webkit-calc(100% - 20px);
|
||||
left: calc(100% - 20px);
|
||||
background-color: #33cabb
|
||||
}
|
||||
|
||||
.toggle-switch.switch-solid span {
|
||||
height: 20px;
|
||||
}
|
||||
.toggle-switch.switch-solid span:after {
|
||||
top: -2px;
|
||||
}
|
||||
.switch-solid input:checked~span {
|
||||
background-color: #33cabb;
|
||||
border-color: #33cabb
|
||||
}
|
||||
.switch-solid input:checked~span:after {
|
||||
background-color: #fff;
|
||||
color: #33cabb
|
||||
}
|
||||
|
||||
/** 遮罩层 **/
|
||||
.loaderbox {
|
||||
display: inline-block;
|
||||
@@ -487,7 +595,7 @@ label {
|
||||
}
|
||||
|
||||
.container-div {
|
||||
padding: 10px 35px;
|
||||
padding: 0px 28px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -530,6 +638,13 @@ label {
|
||||
margin: 5px 15px 5px 0px;
|
||||
}
|
||||
|
||||
.select-list li p{
|
||||
float: left;
|
||||
width: 80px;
|
||||
margin: 5px 15px 5px 0px;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.select-list li input {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
@@ -555,9 +670,73 @@ label {
|
||||
background: transparent;
|
||||
outline: none;
|
||||
height: 30px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.bootstrap-select.form-control .btn-default {
|
||||
color: inherit;
|
||||
padding: 6px 12px;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #e5e6e7;
|
||||
outline: none;
|
||||
height: 34px;
|
||||
background: #FFFFFF none
|
||||
}
|
||||
|
||||
.file-input .btn-default {
|
||||
color: inherit;
|
||||
background: white;
|
||||
border: 1px solid #e7eaec;
|
||||
}
|
||||
|
||||
.select-list .btn-default {
|
||||
color: #555;
|
||||
padding: 5px 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
height: 30px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.select-list .btn-default:hover,.select-list .btn-default:focus,.select-list .btn-default:active,.select-list .btn-default.active,.open .dropdown-toggle.btn-default {
|
||||
color: #555;
|
||||
background-color: #e4e4e4;
|
||||
border-color: #b2b2b2
|
||||
}
|
||||
|
||||
.select-list .bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||
height: 30px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder,
|
||||
.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
|
||||
.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
|
||||
.select-list .bootstrap-select > .dropdown-toggle.bs-placeholder:active {
|
||||
color: inherit;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.select-list .bootstrap-select .dropdown-toggle .caret {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
.select-list .select-selectpicker li {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.select-list .dropdown-menu>li>a,.bootstrap-select.form-control .dropdown-menu>li>a {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.select-list .dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a,.bootstrap-select.form-control .dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
background-color: #12889a
|
||||
}
|
||||
|
||||
.select-list .select-time input {
|
||||
width: 93px;
|
||||
}
|
||||
@@ -602,6 +781,13 @@ label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select-title{
|
||||
color:#3d5266;
|
||||
font-size:15px;
|
||||
padding:10px 0px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/** 表格查询数据 **/
|
||||
.table-striped {
|
||||
min-height: 75%;
|
||||
@@ -611,12 +797,20 @@ label {
|
||||
border: 0px!important;
|
||||
}
|
||||
|
||||
.table-striped .table, .fixed-table-container, table, .table-striped .table, .table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td, .table>tbody>tr>td, .table>tfoot>tr>td {
|
||||
.table-striped .table, .table-striped .table, .table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td, .table>tbody>tr>td, .table>tfoot>tr>td {
|
||||
border-bottom: 1px solid #e7eaec!important;
|
||||
background-color: transparent!important;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.fixed-table-footer {
|
||||
border-top: 0px solid #ddd;
|
||||
}
|
||||
|
||||
.fixed-table-container {
|
||||
border: 0px solid #ddd;
|
||||
}
|
||||
|
||||
.table-striped .table>thead>tr>th, .table-striped .table>tbody>tr>th {
|
||||
border-bottom: 1px solid #ccc!important;
|
||||
border-top: 0px!important;
|
||||
@@ -638,6 +832,57 @@ label {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
/** 表格冻结列样式 **/
|
||||
.left-fixed-table-columns, .left-fixed-body-columns {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.left-fixed-table-columns .table, .left-fixed-body-columns .table {
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.left-fixed-table-columns .table.table-no-bordered, .left-fixed-body-columns .table.table-no-bordered {
|
||||
border-right: 1px solid transparent;
|
||||
}
|
||||
|
||||
.left-fixed-body-columns table {
|
||||
position: absolute;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.bootstrap-table .table-hover > tbody > tr.hover > td {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.right-fixed-table-columns{
|
||||
position: absolute;
|
||||
right:63px;
|
||||
border-left:1px solid #ddd;
|
||||
display: none;
|
||||
z-index:100;
|
||||
}
|
||||
|
||||
/** 表格树样式 **/
|
||||
.bootstrap-tree-table .treetable-indent {width:16px; height: 16px; display: inline-block; position: relative;}
|
||||
.bootstrap-tree-table .treetable-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
|
||||
.bootstrap-tree-table .treetable-selected{background: #f5f5f5 !important;}
|
||||
.bootstrap-tree-table .treetable-table{border:0 !important;margin-bottom:0}
|
||||
.bootstrap-tree-table .treetable-table tbody {display:block;height:auto;overflow-y:auto;}
|
||||
.bootstrap-tree-table .treetable-table thead, .treetable-table tbody tr {display:table;width:100%;table-layout:fixed;}
|
||||
.bootstrap-tree-table .treetable-thead th{line-height:24px;border: 0 !important;border-radius: 4px;border-left:0px solid #e7eaec !important;border-bottom:1px solid #ccc!important;text-align: left;}
|
||||
.bootstrap-tree-table .treetable-thead tr :first-child{border-left:0 !important}
|
||||
.bootstrap-tree-table .treetable-tbody td{overflow:hidden;border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
|
||||
.bootstrap-tree-table .treetable-tbody tr :first-child{border-left:0 !important}
|
||||
.bootstrap-tree-table .treetable-bars .tool-left, .bootstrap-tree-table .treetable-bars .tool-right{margin-top: 10px; margin-bottom: 10px;}
|
||||
.bootstrap-tree-table .treetable-bars .tool-left{float: left;}
|
||||
.bootstrap-tree-table .treetable-bars .tool-right{float: right;}
|
||||
.bootstrap-tree-table .treetable-bars .columns li label{display: block;padding: 3px 20px;clear: both;font-weight: 400;line-height: 1.428571429;max-width: 100%;margin-bottom: 5px;cursor:pointer;}
|
||||
.bootstrap-tree-table .table{border-bottom: 0px solid #e7eaec!important;}
|
||||
|
||||
/** 首页样式 **/
|
||||
.ax_close_max {
|
||||
position: fixed;
|
||||
@@ -689,7 +934,7 @@ label {
|
||||
padding-bottom:5px
|
||||
}
|
||||
|
||||
.form-content {
|
||||
.main-content {
|
||||
background-color: #ffffff;
|
||||
color: inherit;
|
||||
padding: 10px 15px 15px 15px;
|
||||
@@ -715,3 +960,33 @@ label {
|
||||
display: block;
|
||||
float:left;
|
||||
}
|
||||
|
||||
/** 表格拖拽样式 **/
|
||||
.reorder_rows_onDragClass td {
|
||||
color:yellow!important;
|
||||
background-color:#999!important;
|
||||
text-shadow:0 0 10px black,0 0 10px black,0 0 8px black,0 0 6px black,0 0 6px black;
|
||||
box-shadow:0 12px 14px -12px #111 inset,0 -2px 2px -1px #333 inset
|
||||
}
|
||||
|
||||
/** 表格选中样式 **/
|
||||
.fixed-table-container .selected {
|
||||
background-color: #E8F7FD;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
/** 滚动条样式 **/
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background-color: #999;
|
||||
}
|
||||
@@ -52,6 +52,7 @@ function() {
|
||||
$('body').addClass('mini-navbar');
|
||||
$('.navbar-static-side').fadeIn();
|
||||
$(".sidebar-collapse .logo").addClass("hide");
|
||||
$(".slimScrollDiv").css({ "overflow":"hidden" })
|
||||
}
|
||||
});
|
||||
|
||||
@@ -91,6 +92,21 @@ $(function() {
|
||||
});
|
||||
return width;
|
||||
}
|
||||
|
||||
// 激活指定选项卡
|
||||
function setActiveTab(element) {
|
||||
if (!$(element).hasClass('active')) {
|
||||
var currentId = $(element).data('id');
|
||||
// 显示tab对应的内容区
|
||||
$('.RuoYi_iframe').each(function() {
|
||||
if ($(this).data('id') == currentId) {
|
||||
$(this).show().siblings('.RuoYi_iframe').hide();
|
||||
}
|
||||
});
|
||||
$(element).addClass('active').siblings('.menuTab').removeClass('active');
|
||||
scrollToTab(element);
|
||||
}
|
||||
}
|
||||
|
||||
//滚动到指定选项卡
|
||||
function scrollToTab(element) {
|
||||
@@ -124,14 +140,14 @@ $(function() {
|
||||
|
||||
//查看左侧隐藏的选项卡
|
||||
function scrollTabLeft() {
|
||||
var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')) + 50);
|
||||
var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
|
||||
// 可视区域非tab宽度
|
||||
var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs"));
|
||||
//可视区域tab宽度
|
||||
var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
|
||||
//实际滚动宽度
|
||||
var scrollVal = 0;
|
||||
if (($(".page-tabs-content").width() + 50) < visibleWidth) {
|
||||
if (($(".page-tabs-content").width()) < visibleWidth) {
|
||||
return false;
|
||||
} else {
|
||||
var tabElement = $(".menuTab:first");
|
||||
@@ -201,6 +217,8 @@ $(function() {
|
||||
dataIndex = $(this).data('index'),
|
||||
menuName = $.trim($(this).text()),
|
||||
flag = true;
|
||||
$(".nav ul li, .nav li").removeClass("selected");
|
||||
$(this).parent("li").addClass("selected");
|
||||
if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false;
|
||||
|
||||
// 选项卡菜单已存在
|
||||
@@ -242,8 +260,17 @@ $(function() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function menuBlank() {
|
||||
// 新窗口打开外网以http://开头,如http://ruoyi.vip
|
||||
var dataUrl = $(this).attr('href');
|
||||
window.open(dataUrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
$('.menuItem').on('click', menuItem);
|
||||
|
||||
$('.menuBlank').on('click', menuBlank);
|
||||
|
||||
// 关闭选项卡菜单
|
||||
function closeTab() {
|
||||
@@ -335,19 +362,9 @@ $(function() {
|
||||
scrollToTab($('.menuTab.active'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$('.menuTabs').on('click', '.menuTab i', closeTab);
|
||||
|
||||
//关闭其他选项卡
|
||||
function closeOtherTabs() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
}
|
||||
$('.tabCloseOther').on('click', closeOtherTabs);
|
||||
|
||||
//滚动到已激活的选项卡
|
||||
function showActiveTab() {
|
||||
scrollToTab($('.menuTab.active'));
|
||||
@@ -373,7 +390,7 @@ $(function() {
|
||||
// 点击选项卡菜单
|
||||
$('.menuTabs').on('click', '.menuTab', activeTab);
|
||||
|
||||
//刷新iframe
|
||||
// 刷新iframe
|
||||
function refreshTab() {
|
||||
var currentId = $('.page-tabs-content').find('.active').attr('data-id');
|
||||
var target = $('.RuoYi_iframe[data-id="' + currentId + '"]');
|
||||
@@ -381,9 +398,37 @@ $(function() {
|
||||
target.attr('src', url).ready();
|
||||
}
|
||||
|
||||
// 关闭当前选项卡
|
||||
function tabCloseCurrent() {
|
||||
$('.page-tabs-content').find('.active i').trigger("click");
|
||||
}
|
||||
|
||||
//关闭其他选项卡
|
||||
function tabCloseOther() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
}
|
||||
|
||||
// 关闭全部选项卡
|
||||
function tabCloseAll() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').children("[data-id]:first").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').show();
|
||||
$(this).addClass("active");
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
}
|
||||
|
||||
|
||||
// 全屏显示
|
||||
$('#fullScreen').on('click', function () {
|
||||
$('#wrapper').fullScreen();
|
||||
$(document).toggleFullScreen();
|
||||
});
|
||||
|
||||
// 刷新按钮
|
||||
@@ -399,22 +444,13 @@ $(function() {
|
||||
$('.tabRight').on('click', scrollTabRight);
|
||||
|
||||
// 关闭当前
|
||||
$('.tabCloseCurrent').on('click', function () {
|
||||
$('.page-tabs-content').find('.active i').trigger("click");
|
||||
});
|
||||
$('.tabCloseCurrent').on('click', tabCloseCurrent);
|
||||
|
||||
// 关闭其他
|
||||
$('.tabCloseOther').on('click', tabCloseOther);
|
||||
|
||||
// 关闭全部
|
||||
$('.tabCloseAll').on('click', function() {
|
||||
$('.page-tabs-content').children("[data-id]").not(":first").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').children("[data-id]:first").each(function() {
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').show();
|
||||
$(this).addClass("active");
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
});
|
||||
$('.tabCloseAll').on('click', tabCloseAll);
|
||||
|
||||
// tab全屏显示
|
||||
$('.tabMaxCurrent').on('click', function () {
|
||||
@@ -439,4 +475,93 @@ $(function() {
|
||||
$('#ax_close_max').hide();
|
||||
}
|
||||
});
|
||||
|
||||
// 右键菜单实现
|
||||
$.contextMenu({
|
||||
selector: ".menuTab",
|
||||
trigger: 'right',
|
||||
autoHide: true,
|
||||
items: {
|
||||
"close_current": {
|
||||
name: "关闭当前",
|
||||
icon: "fa-close",
|
||||
callback: function(key, opt) {
|
||||
opt.$trigger.find('i').trigger("click");
|
||||
}
|
||||
},
|
||||
"close_other": {
|
||||
name: "关闭其他",
|
||||
icon: "fa-window-close-o",
|
||||
callback: function(key, opt) {
|
||||
setActiveTab(this);
|
||||
tabCloseOther();
|
||||
}
|
||||
},
|
||||
"close_left": {
|
||||
name: "关闭左侧",
|
||||
icon: "fa-reply",
|
||||
callback: function(key, opt) {
|
||||
setActiveTab(this);
|
||||
this.prevAll('.menuTab').not(":last").each(function() {
|
||||
if ($(this).hasClass('active')) {
|
||||
setActiveTab(this);
|
||||
}
|
||||
$('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
$('.page-tabs-content').css("margin-left", "0");
|
||||
}
|
||||
},
|
||||
"close_right": {
|
||||
name: "关闭右侧",
|
||||
icon: "fa-share",
|
||||
callback: function(key, opt) {
|
||||
setActiveTab(this);
|
||||
this.nextAll('.menuTab').each(function() {
|
||||
$('.menuTab[data-id="' + $(this).data('id') + '"]').remove();
|
||||
$(this).remove();
|
||||
});
|
||||
}
|
||||
},
|
||||
"close_all": {
|
||||
name: "全部关闭",
|
||||
icon: "fa-window-close",
|
||||
callback: function(key, opt) {
|
||||
tabCloseAll();
|
||||
}
|
||||
},
|
||||
"step": "---------",
|
||||
"full": {
|
||||
name: "全屏显示",
|
||||
icon: "fa-arrows-alt",
|
||||
callback: function(key, opt) {
|
||||
setActiveTab(this);
|
||||
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
|
||||
target.fullScreen(true);
|
||||
}
|
||||
},
|
||||
"refresh": {
|
||||
name: "刷新页面",
|
||||
icon: "fa-refresh",
|
||||
callback: function(key, opt) {
|
||||
setActiveTab(this);
|
||||
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
|
||||
var url = target.attr('src');
|
||||
target.attr('src', url).ready();
|
||||
$.modal.loading("数据加载中,请稍后...");
|
||||
target.attr('src', url).load(function () {
|
||||
$.modal.closeLoading();
|
||||
});
|
||||
}
|
||||
},
|
||||
"open": {
|
||||
name: "新窗口打开",
|
||||
icon: "fa-link",
|
||||
callback: function(key, opt) {
|
||||
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
|
||||
window.open(target.attr('src'));
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -5,26 +5,24 @@
|
||||
$(function() {
|
||||
// select2复选框事件绑定
|
||||
if ($.fn.select2 !== undefined) {
|
||||
$.fn.select2.defaults.set( "theme", "bootstrap" );
|
||||
$("select.form-control:not(.noselect2)").each(function () {
|
||||
$(this).select2().on("change", function () {
|
||||
$(this).valid();
|
||||
})
|
||||
})
|
||||
}
|
||||
// checkbox 事件绑定
|
||||
if ($(".check-box").length > 0) {
|
||||
$(".check-box").iCheck({
|
||||
checkboxClass: 'icheckbox-blue',
|
||||
radioClass: 'iradio-blue',
|
||||
})
|
||||
}
|
||||
// radio 事件绑定
|
||||
if ($(".radio-box").length > 0) {
|
||||
$(".radio-box").iCheck({
|
||||
checkboxClass: 'icheckbox-blue',
|
||||
radioClass: 'iradio-blue',
|
||||
})
|
||||
|
||||
// iCheck单选框及复选框事件绑定
|
||||
if ($.fn.iCheck !== undefined) {
|
||||
$(".check-box:not(.noicheck),.radio-box:not(.noicheck)").each(function() {
|
||||
$(this).iCheck({
|
||||
checkboxClass: 'icheckbox-blue',
|
||||
radioClass: 'iradio-blue',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// laydate 时间控件绑定
|
||||
if ($(".select-time").length > 0) {
|
||||
layui.use('laydate', function() {
|
||||
@@ -69,25 +67,50 @@ $(function() {
|
||||
}
|
||||
// laydate time-input 时间控件绑定
|
||||
if ($(".time-input").length > 0) {
|
||||
layui.use('laydate', function() {
|
||||
var laydate = layui.laydate;
|
||||
var times = $(".time-input");
|
||||
// 控制控件外观
|
||||
var type = times.attr("data-type") || 'date';
|
||||
// 控制回显格式
|
||||
var format = times.attr("data-format") || 'yyyy-MM-dd';
|
||||
for (var i = 0; i < times.length; i++) {
|
||||
var time = times[i];
|
||||
laydate.render({
|
||||
elem: time,
|
||||
theme: 'molv',
|
||||
trigger: 'click',
|
||||
type: type,
|
||||
format: format,
|
||||
done: function(value, date) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
layui.use('laydate', function () {
|
||||
var com = layui.laydate;
|
||||
$(".time-input").each(function (index, item) {
|
||||
var time = $(item);
|
||||
// 控制控件外观
|
||||
var type = time.attr("data-type") || 'date';
|
||||
// 控制回显格式
|
||||
var format = time.attr("data-format") || 'yyyy-MM-dd';
|
||||
// 控制日期控件按钮
|
||||
var buttons = time.attr("data-btn") || 'clear|now|confirm', newBtnArr = [];
|
||||
// 日期控件选择完成后回调处理
|
||||
var callback = time.attr("data-callback") || {};
|
||||
if (buttons) {
|
||||
if (buttons.indexOf("|") > 0) {
|
||||
var btnArr = buttons.split("|"), btnLen = btnArr.length;
|
||||
for (var j = 0; j < btnLen; j++) {
|
||||
if ("clear" === btnArr[j] || "now" === btnArr[j] || "confirm" === btnArr[j]) {
|
||||
newBtnArr.push(btnArr[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ("clear" === buttons || "now" === buttons || "confirm" === buttons) {
|
||||
newBtnArr.push(buttons);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newBtnArr = ['clear', 'now', 'confirm'];
|
||||
}
|
||||
com.render({
|
||||
elem: item,
|
||||
theme: 'molv',
|
||||
trigger: 'click',
|
||||
type: type,
|
||||
format: format,
|
||||
btns: newBtnArr,
|
||||
done: function (value, data) {
|
||||
if (typeof window[callback] != 'undefined'
|
||||
&& window[callback] instanceof Function) {
|
||||
window[callback](value, data);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
// tree 关键字搜索绑定
|
||||
if ($("#keyword").length > 0) {
|
||||
@@ -108,12 +131,18 @@ $(function() {
|
||||
var dataExpand = $.common.isEmpty($.table._option.expandAll) ? true : $.table._option.expandAll;
|
||||
expandFlag = $.common.isEmpty(expandFlag) ? dataExpand : expandFlag;
|
||||
if (!expandFlag) {
|
||||
$('#' + $.table._option.id).bootstrapTreeTable('expandAll');
|
||||
$.bttTable.bootstrapTreeTable('expandAll');
|
||||
} else {
|
||||
$('#' + $.table._option.id).bootstrapTreeTable('collapseAll');
|
||||
$.bttTable.bootstrapTreeTable('collapseAll');
|
||||
}
|
||||
expandFlag = expandFlag ? false: true;
|
||||
})
|
||||
// 按下ESC按钮关闭弹层
|
||||
$('body', document).on('keyup', function(e) {
|
||||
if (e.which === 27) {
|
||||
$.modal.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/** 刷新选项卡 */
|
||||
@@ -126,8 +155,16 @@ var refreshItem = function(){
|
||||
}
|
||||
|
||||
/** 关闭选项卡 */
|
||||
var closeItem = function(){
|
||||
var closeItem = function(dataId){
|
||||
var topWindow = $(window.parent.document);
|
||||
if($.common.isNotEmpty(dataId)){
|
||||
window.parent.$.modal.closeLoading();
|
||||
// 根据dataId关闭指定选项卡
|
||||
$('.menuTab[data-id="' + dataId + '"]', topWindow).remove();
|
||||
// 移除相应tab对应的内容区
|
||||
$('.mainContent .RuoYi_iframe[data-id="' + dataId + '"]', topWindow).remove();
|
||||
return;
|
||||
}
|
||||
var panelUrl = window.frameElement.getAttribute('data-panel');
|
||||
$('.page-tabs-content .active i', topWindow).click();
|
||||
if($.common.isNotEmpty(panelUrl)){
|
||||
@@ -206,10 +243,12 @@ var log = {
|
||||
$.ajaxSetup({
|
||||
complete: function(XMLHttpRequest, textStatus) {
|
||||
if (textStatus == 'timeout') {
|
||||
$.modal.alertWarning("服务器超时,请稍后再试!");
|
||||
$.modal.alertWarning("服务器超时,请稍后再试!");
|
||||
$.modal.enable();
|
||||
$.modal.closeLoading();
|
||||
} else if (textStatus == "parsererror") {
|
||||
$.modal.alertWarning("服务器错误,请联系管理员!");
|
||||
} else if (textStatus == "parsererror" || textStatus == "error") {
|
||||
$.modal.alertWarning("服务器错误,请联系管理员!");
|
||||
$.modal.enable();
|
||||
$.modal.closeLoading();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user